From 8ee83741696d9909af25aa5fb3ede7bacc3c2a5e Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 11:28:01 +0100 Subject: [PATCH 01/35] Misc - EventHandler --- Code/Game/DanBiasGame/GameClientRecieverFunc.h | 4 ++-- Code/Misc/EventHandler/EventButton.cpp | 0 Code/Misc/EventHandler/EventButton.h | 0 Code/Misc/EventHandler/EventButtonCollection.cpp | 0 Code/Misc/EventHandler/EventButtonCollection.h | 0 Code/Misc/EventHandler/EventHandler.cpp | 0 Code/Misc/EventHandler/EventHandler.h | 0 Code/Misc/Misc.vcxproj | 2 ++ Code/Misc/Misc.vcxproj.filters | 6 ++++++ 9 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Code/Misc/EventHandler/EventButton.cpp create mode 100644 Code/Misc/EventHandler/EventButton.h create mode 100644 Code/Misc/EventHandler/EventButtonCollection.cpp create mode 100644 Code/Misc/EventHandler/EventButtonCollection.h create mode 100644 Code/Misc/EventHandler/EventHandler.cpp create mode 100644 Code/Misc/EventHandler/EventHandler.h diff --git a/Code/Game/DanBiasGame/GameClientRecieverFunc.h b/Code/Game/DanBiasGame/GameClientRecieverFunc.h index b355027a..de8f63a6 100644 --- a/Code/Game/DanBiasGame/GameClientRecieverFunc.h +++ b/Code/Game/DanBiasGame/GameClientRecieverFunc.h @@ -130,8 +130,8 @@ namespace DanBias break; case protocol_Lobby_GameData: //this->LobbyGameData (Protocol_LobbyGameData (p), c); { - GameLogic::Protocol_LobbyGameData temp(p); - printf("%s, %i.%i\n", temp.mapName.c_str(), temp.majorVersion, temp.minorVersion); + //GameLogic::Protocol_LobbyGameData temp(p); + //printf("%s, %i.%i\n", temp.mapName.c_str(), temp.majorVersion, temp.minorVersion); } break; case protocol_Lobby_ClientData: //this->LobbyMainData (Protocol_LobbyClientData (p), c); diff --git a/Code/Misc/EventHandler/EventButton.cpp b/Code/Misc/EventHandler/EventButton.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h new file mode 100644 index 00000000..e69de29b diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index 6c3db1ec..46b85f01 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -146,6 +146,7 @@ + @@ -164,6 +165,7 @@ + diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index 8413642a..92a559df 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -116,5 +119,8 @@ Header Files + + Header Files + \ No newline at end of file From d6769ac62f145283088d0d2d56b2a884ecf5baf2 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 13:06:11 +0100 Subject: [PATCH 02/35] Misc - EventHandler, EventCollection --- .../EventHandler/EventButtonCollection.cpp | 25 +++++++++++++ .../Misc/EventHandler/EventButtonCollection.h | 31 ++++++++++++++++ Code/Misc/EventHandler/EventHandler.cpp | 37 +++++++++++++++++++ Code/Misc/EventHandler/EventHandler.h | 35 ++++++++++++++++++ Code/Misc/Misc.vcxproj | 8 +++- Code/Misc/Misc.vcxproj.filters | 16 +++++++- 6 files changed, 148 insertions(+), 4 deletions(-) diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp index e69de29b..b3d37bfe 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -0,0 +1,25 @@ +#include "EventButtonCollection.h" + +using namespace Oyster::Event; + +EventButtonCollection::EventButtonCollection() +{ + +} + +EventButtonCollection::~EventButtonCollection() +{ +} + +void EventButtonCollection::Update(InputClass* inputObject) +{ + for(int i = 0; i < buttons.size(); i++) + { + buttons.at(i)->Update(inputObject); + } +} + +EventButton* EventButtonCollection::AddButton(EventButton* button) +{ + +} \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h index e69de29b..31201f9c 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -0,0 +1,31 @@ +#ifndef EVENT_BUTTON_COLLECTION_H +#define EVENT_BUTTON_COLLECTION_H + +#include "../../Input/L_inputClass.h" + +#include "EventButton.h" + +#include + +namespace Oyster +{ + namespace Event + { + class EventButtonCollection + { + public: + EventButtonCollection(); + ~EventButtonCollection(); + + void Update(InputClass* inputObject); + + EventButton* AddButton(EventButton* button); + + private: + std::vector buttons; + + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp index e69de29b..8f6705df 100644 --- a/Code/Misc/EventHandler/EventHandler.cpp +++ b/Code/Misc/EventHandler/EventHandler.cpp @@ -0,0 +1,37 @@ +#include "EventHandler.h" + +using namespace Oyster::Event; + +EventHandler EvtHandler; + +EventHandler& EventHandler::Instance() +{ + return EvtHandler; +} + +EventHandler::EventHandler() +{ + +} + +EventHandler::~EventHandler() +{ +} + +void EventHandler::Update(InputClass* inputObject) +{ + for(int i = 0; i < collections.size(); i++) + { + collections.at(i)->Update(inputObject); + } +} + +EventButtonCollection* EventHandler::CreateCollection() +{ + +} + +EventButtonCollection* EventHandler::GetCollection(/*ID*/); +{ + +} \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h index e69de29b..c3ecc0a2 100644 --- a/Code/Misc/EventHandler/EventHandler.h +++ b/Code/Misc/EventHandler/EventHandler.h @@ -0,0 +1,35 @@ +#ifndef EVENT_HANDLER_H +#define EVENT_HANDLER_H + +#include "../../Input/L_inputClass.h" + +#include "EventButtonCollection.h" +#include "EventButton.h" + +#include + +namespace Oyster +{ + namespace Event + { + class EventHandler + { + EventHandler(); + ~EventHandler(); + + EventHandler& Instance(); + + void Update(InputClass* inputObject); + + EventButtonCollection* CreateCollection(); + EventButtonCollection* GetCollection(/*ID*/); + + + private: + std::vector collections; + + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index 46b85f01..52b7c96c 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -146,7 +146,9 @@ - + + + @@ -163,9 +165,11 @@ + + - + diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index 92a559df..d4874b4c 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -51,7 +51,13 @@ Source Files - + + Source Files + + + Source Files + + Source Files @@ -119,7 +125,13 @@ Header Files - + + Header Files + + + Header Files + + Header Files From a864ad81e71e0f65379b4c67b66ba8bffaec67ba Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 14:16:58 +0100 Subject: [PATCH 03/35] Misc - EventHandler, EventCollection updated. --- .../EventHandler/EventButtonCollection.cpp | 36 ++++++++++++++++--- .../Misc/EventHandler/EventButtonCollection.h | 19 +++++++++- Code/Misc/EventHandler/EventHandler.cpp | 7 ++-- Code/Misc/EventHandler/EventHandler.h | 5 ++- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp index b3d37bfe..268712c5 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -2,9 +2,9 @@ using namespace Oyster::Event; -EventButtonCollection::EventButtonCollection() +EventButtonCollection::EventButtonCollection() + : collectionState(EventCollectionState_Enabled) { - } EventButtonCollection::~EventButtonCollection() @@ -13,13 +13,39 @@ EventButtonCollection::~EventButtonCollection() void EventButtonCollection::Update(InputClass* inputObject) { - for(int i = 0; i < buttons.size(); i++) + if(this->collectionState == EventCollectionState_Enabled) { - buttons.at(i)->Update(inputObject); + for(int i = 0; i < buttons.size(); i++) + { + buttons.at(i)->CheckCollision(inputObject); + } } } -EventButton* EventButtonCollection::AddButton(EventButton* button) +void EventButtonCollection::AddButton(EventButton& button) { + buttons.push_back(button); +} +EventButton& EventButtonCollection::CreateButton() +{ + EventButton temp; + buttons.push_back(&temp); + return temp; +} + +EventCollectionState EventButtonCollection::GetState() const +{ + return collectionState; +} + +void EventButtonCollection::SetState(const EventCollectionState state) +{ + collectionState = state; +} + +void EventButtonCollection::Clear() +{ + buttons.clear(); + collectionState = EventCollectionState_Enabled; } \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h index 31201f9c..4368e195 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -11,6 +11,15 @@ namespace Oyster { namespace Event { + enum EventCollectionState + { + EventCollectionState_Disabled, + EventCollectionState_Enabled, + + EventCollectionState_Count, + EventCollectionState_Unknown = -1, + }; + class EventButtonCollection { public: @@ -19,10 +28,18 @@ namespace Oyster void Update(InputClass* inputObject); - EventButton* AddButton(EventButton* button); + void AddButton(EventButton& button); + EventButton& CreateButton(); + + EventCollectionState GetState() const; + void SetState(const EventCollectionState state); + + //Clear all buttons and reset the state. + void Clear(); private: std::vector buttons; + EventCollectionState collectionState; }; } diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp index 8f6705df..e064ad41 100644 --- a/Code/Misc/EventHandler/EventHandler.cpp +++ b/Code/Misc/EventHandler/EventHandler.cpp @@ -11,7 +11,6 @@ EventHandler& EventHandler::Instance() EventHandler::EventHandler() { - } EventHandler::~EventHandler() @@ -26,12 +25,12 @@ void EventHandler::Update(InputClass* inputObject) } } -EventButtonCollection* EventHandler::CreateCollection() +void EventHandler::AddCollection(EventButtonCollection& collection) { - + collections.push_back(&collection); } -EventButtonCollection* EventHandler::GetCollection(/*ID*/); +EventButtonCollection& EventHandler::CreateCollection() { } \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h index c3ecc0a2..1a438e8c 100644 --- a/Code/Misc/EventHandler/EventHandler.h +++ b/Code/Misc/EventHandler/EventHandler.h @@ -21,9 +21,8 @@ namespace Oyster void Update(InputClass* inputObject); - EventButtonCollection* CreateCollection(); - EventButtonCollection* GetCollection(/*ID*/); - + void AddCollection(EventButtonCollection& collection); + EventButtonCollection& CreateCollection(); private: std::vector collections; From 8f83dcd41345d41082588077da157d1b31308d20 Mon Sep 17 00:00:00 2001 From: Sam Mario Svensson Date: Fri, 31 Jan 2014 14:29:29 +0100 Subject: [PATCH 04/35] GL- Eventbutton implemented --- Code/Misc/EventHandler/EventButton.cpp | 0 Code/Misc/EventHandler/EventButton.h | 126 +++++++++++++++++++++++++ 2 files changed, 126 insertions(+) delete mode 100644 Code/Misc/EventHandler/EventButton.cpp diff --git a/Code/Misc/EventHandler/EventButton.cpp b/Code/Misc/EventHandler/EventButton.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index e69de29b..189102cc 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -0,0 +1,126 @@ +/////////////////////// +// Sam Svensson 2013 // +/////////////////////// + +#include "../../Input/L_inputClass.h" +#include + +namespace Oyster +{ + namespace Event + { + + template + class EventButton + { + private: + enum ButtonState + { + Button_Clicked, + Button_Hover, + Button_Hold, + Button_Smashed, + }; + struct ButtonEvent + { + ButtonState state; + EventButton &sender; + T owner; + }; + + struct PrivData + { + static unsigned int currID; + unsigned int ID; + + T owner; + void (*EventFunc)( ButtonEvent e ); + }; + + PrivData privData; + + public: + EventButton(); + EventButton(T owner); + EventButton(void (*EventFunc)( ButtonEvent e)); + EventButton(void (*EventFunc)( ButtonEvent e), T owner); + + ~EventButton(); + + void checkCollision(InputClass *input); + + void SetEventFunc(void (*EventFunc)( ButtonEvent e )); //? + + unsigned int GetID(); + T& GetOwner(); + + }; + + + template + EventButton::EventButton() + { + this->privData.ID = privData.currID; + this->privData.currID += 1; + this->privData.owner = NULL; + this->privData.EventFunc = NULL; + } + + template + EventButton::EventButton(T owner) + { + this->privData.ID = privData.currID; + this->privData.currID += 1; + this->privData.owner = owner; + this->privData.EventFunc = NULL; + } + + template + EventButton::EventButton(void (*EventFunc)( ButtonEvent e)) + { + this->privData.ID = privData.currID; + this->privData.currID += 1; + this->privData.owner = NULL; + this->privData.EventFunc = EventFunc; + } + + template + EventButton::EventButton(void (*EventFunc)( ButtonEvent e), T owner) + { + this->privData.ID = privData.currID; + this->privData.currID += 1; + this->privData.owner = owner; + this->privData.EventFunc = EventFunc; + } + + template + EventButton~EventButton() + { + + } + + template + void EventButton::checkCollision(InputClass *input) + { + //??????????????? TODO: everything + } + + template + void EventButton::SetEventFunc(void (*EventFunc)( ButtonEvent e )) + { + this->privData.EventFunc = EventFunc; + } + + template + unsigned int EventButton::GetID() + { + return this->privData.ID; + } + + template + T& EventButton::GetOwner() + { + return this->privData.owner; + } + } +} \ No newline at end of file From d5f285c089e4768509c4cf09fd8a0fcbc915ed2a Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 14:31:27 +0100 Subject: [PATCH 05/35] Misc - Test --- Code/Game/DanBiasGame/DanBiasGame_Impl.cpp | 5 +++++ Code/Misc/EventHandler/EventHandler.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index 4a54297f..24c14a0c 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -17,6 +17,9 @@ #include "vld.h" #include "GameClientRecieverFunc.h" +#include "../Misc/EventHandler/EventHandler.h" +using namespace Oyster::Event; + namespace DanBias { @@ -130,6 +133,8 @@ namespace DanBias HRESULT DanBiasGame::Update(float deltaTime) { + EventHandler::Instance(); + if(m_data->recieverObj->IsConnected()) m_data->recieverObj->Update(); diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h index 1a438e8c..e19a8149 100644 --- a/Code/Misc/EventHandler/EventHandler.h +++ b/Code/Misc/EventHandler/EventHandler.h @@ -17,7 +17,7 @@ namespace Oyster EventHandler(); ~EventHandler(); - EventHandler& Instance(); + static EventHandler& Instance(); void Update(InputClass* inputObject); From e76dfc73f2a646354c4c8e167a9e9112c15178a8 Mon Sep 17 00:00:00 2001 From: Sam Mario Svensson Date: Fri, 31 Jan 2014 15:06:25 +0100 Subject: [PATCH 06/35] Misc - EventButton changed to inheritance --- Code/Misc/EventHandler/EventButton.h | 65 +++++++++++---------------- Code/Misc/EventHandler/IEventButton.h | 41 +++++++++++++++++ Code/Misc/Misc.vcxproj | 1 + Code/Misc/Misc.vcxproj.filters | 3 ++ 4 files changed, 71 insertions(+), 39 deletions(-) create mode 100644 Code/Misc/EventHandler/IEventButton.h diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index 189102cc..e4ba0a4d 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -4,36 +4,23 @@ #include "../../Input/L_inputClass.h" #include +#include "IEventButton.h" namespace Oyster { namespace Event { - - template - class EventButton + template + class EventButton : public IEventButton { private: - enum ButtonState - { - Button_Clicked, - Button_Hover, - Button_Hold, - Button_Smashed, - }; - struct ButtonEvent - { - ButtonState state; - EventButton &sender; - T owner; - }; - + struct PrivData { static unsigned int currID; unsigned int ID; - T owner; + owner owner; void (*EventFunc)( ButtonEvent e ); }; @@ -41,9 +28,9 @@ namespace Oyster public: EventButton(); - EventButton(T owner); + EventButton(owner owner); EventButton(void (*EventFunc)( ButtonEvent e)); - EventButton(void (*EventFunc)( ButtonEvent e), T owner); + EventButton(void (*EventFunc)( ButtonEvent e), owner owner); ~EventButton(); @@ -52,13 +39,13 @@ namespace Oyster void SetEventFunc(void (*EventFunc)( ButtonEvent e )); //? unsigned int GetID(); - T& GetOwner(); + owner& GetOwner(); }; - template - EventButton::EventButton() + template + EventButton::EventButton() { this->privData.ID = privData.currID; this->privData.currID += 1; @@ -66,8 +53,8 @@ namespace Oyster this->privData.EventFunc = NULL; } - template - EventButton::EventButton(T owner) + template + EventButton::EventButton(owner owner) { this->privData.ID = privData.currID; this->privData.currID += 1; @@ -75,8 +62,8 @@ namespace Oyster this->privData.EventFunc = NULL; } - template - EventButton::EventButton(void (*EventFunc)( ButtonEvent e)) + template + EventButton::EventButton(void (*EventFunc)( ButtonEvent e)) { this->privData.ID = privData.currID; this->privData.currID += 1; @@ -84,8 +71,8 @@ namespace Oyster this->privData.EventFunc = EventFunc; } - template - EventButton::EventButton(void (*EventFunc)( ButtonEvent e), T owner) + template + EventButton::EventButton(void (*EventFunc)( ButtonEvent e), owner owner) { this->privData.ID = privData.currID; this->privData.currID += 1; @@ -93,32 +80,32 @@ namespace Oyster this->privData.EventFunc = EventFunc; } - template - EventButton~EventButton() + template + EventButton~EventButton() { } - template - void EventButton::checkCollision(InputClass *input) + template + void EventButton::checkCollision(InputClass *input) { //??????????????? TODO: everything } - template - void EventButton::SetEventFunc(void (*EventFunc)( ButtonEvent e )) + template + void EventButton::SetEventFunc(void (*EventFunc)( ButtonEvent e )) { this->privData.EventFunc = EventFunc; } - template - unsigned int EventButton::GetID() + template + unsigned int EventButton::GetID() { return this->privData.ID; } - template - T& EventButton::GetOwner() + template + owner& EventButton::GetOwner() { return this->privData.owner; } diff --git a/Code/Misc/EventHandler/IEventButton.h b/Code/Misc/EventHandler/IEventButton.h new file mode 100644 index 00000000..35a8827c --- /dev/null +++ b/Code/Misc/EventHandler/IEventButton.h @@ -0,0 +1,41 @@ +#include "../../Input/L_inputClass.h" + +namespace Oyster +{ + namespace Event + { + class IEventButton + { + + private: + + enum ButtonState + { + Button_Clicked, + Button_Hover, + Button_Hold, + Button_Smashed, + }; + + struct ButtonEvent + { + ButtonState state; + IEventButton &sender; + + template + owner owner; + }; + + public: + virtual void checkCollision(InputClass *input) = 0; + + virtual void SetEventFunc(void (*EventFunc)( ButtonEvent e )) = 0; + + virtual unsigned int GetID() = 0; + + template + virtual owner& GetOwner() = 0; + + }; + } +} \ No newline at end of file diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index 52b7c96c..2d2d35f4 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -167,6 +167,7 @@ + diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index d4874b4c..7bc3ffc9 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -134,5 +134,8 @@ Header Files + + Header Files + \ No newline at end of file From dbe8b4706b2e856eb47c46611433e01feb6dc8b2 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 15:06:30 +0100 Subject: [PATCH 07/35] Misc - Changed to no template/template --- Code/Misc/EventHandler/EventButton.h | 11 +++++++---- Code/Misc/EventHandler/EventButtonCollection.cpp | 6 ++++-- Code/Misc/EventHandler/EventButtonCollection.h | 10 +++++++--- Code/Misc/Misc.vcxproj | 1 - Code/Misc/Misc.vcxproj.filters | 3 --- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index 189102cc..99eb9279 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -9,11 +9,8 @@ namespace Oyster { namespace Event { - - template - class EventButton + struct IButton { - private: enum ButtonState { Button_Clicked, @@ -21,6 +18,12 @@ namespace Oyster Button_Hold, Button_Smashed, }; + }; + template + class EventButton :public IButton + { + private: + struct ButtonEvent { ButtonState state; diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp index 268712c5..859abc4d 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -22,12 +22,14 @@ void EventButtonCollection::Update(InputClass* inputObject) } } -void EventButtonCollection::AddButton(EventButton& button) +template +void EventButtonCollection::AddButton(EventButton& button) { buttons.push_back(button); } -EventButton& EventButtonCollection::CreateButton() +template +EventButton& EventButtonCollection::CreateButton() { EventButton temp; buttons.push_back(&temp); diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h index 4368e195..9065ffc5 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -3,6 +3,7 @@ #include "../../Input/L_inputClass.h" +#include "IEventButton.h" #include "EventButton.h" #include @@ -28,8 +29,11 @@ namespace Oyster void Update(InputClass* inputObject); - void AddButton(EventButton& button); - EventButton& CreateButton(); + template + void AddButton(EventButton& button); + + template + EventButton& CreateButton(); EventCollectionState GetState() const; void SetState(const EventCollectionState state); @@ -38,7 +42,7 @@ namespace Oyster void Clear(); private: - std::vector buttons; + std::vector buttons; EventCollectionState collectionState; }; diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index 52b7c96c..76191ba0 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -146,7 +146,6 @@ - diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index d4874b4c..649b0e5b 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -54,9 +54,6 @@ Source Files - - Source Files - Source Files From 6f264f5e7b8909ce8bb531b83a43039ef442b932 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Fri, 31 Jan 2014 15:38:12 +0100 Subject: [PATCH 08/35] Misc - EventHandler fixed all errors. --- Code/Game/DanBiasGame/DanBiasGame_Impl.cpp | 1 - Code/Misc/EventHandler/EventButton.h | 44 +++++++++++++--------- Code/Misc/EventHandler/EventHandler.cpp | 6 ++- Code/Misc/EventHandler/EventHandler.h | 1 + Code/Misc/EventHandler/IEventButton.h | 26 +++++-------- 5 files changed, 40 insertions(+), 38 deletions(-) diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index 24c14a0c..ea3a3fc9 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -133,7 +133,6 @@ namespace DanBias HRESULT DanBiasGame::Update(float deltaTime) { - EventHandler::Instance(); if(m_data->recieverObj->IsConnected()) m_data->recieverObj->Update(); diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index 01da474c..547cdb47 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -2,19 +2,25 @@ // Sam Svensson 2013 // /////////////////////// +#ifndef MISC_EVENT_BUTTON_H +#define MISC_EVENT_BUTTON_H #include "../../Input/L_inputClass.h" -#include -#include "IEventButton.h" namespace Oyster { namespace Event { - - template - class EventButton : public IEventButton + template + class EventButton { private: + struct ButtonEvent + { + IEventButton::ButtonState state; + EventButton &sender; + owner owner; + }; + struct PrivData { static unsigned int currID; @@ -34,7 +40,7 @@ namespace Oyster ~EventButton(); - void checkCollision(InputClass *input); + void CheckCollision(InputClass *input); void SetEventFunc(void (*EventFunc)( ButtonEvent e )); //? @@ -44,7 +50,7 @@ namespace Oyster }; - template + template EventButton::EventButton() { this->privData.ID = privData.currID; @@ -53,7 +59,7 @@ namespace Oyster this->privData.EventFunc = NULL; } - template + template EventButton::EventButton(owner owner) { this->privData.ID = privData.currID; @@ -62,7 +68,7 @@ namespace Oyster this->privData.EventFunc = NULL; } - template + template EventButton::EventButton(void (*EventFunc)( ButtonEvent e)) { this->privData.ID = privData.currID; @@ -71,7 +77,7 @@ namespace Oyster this->privData.EventFunc = EventFunc; } - template + template EventButton::EventButton(void (*EventFunc)( ButtonEvent e), owner owner) { this->privData.ID = privData.currID; @@ -80,34 +86,36 @@ namespace Oyster this->privData.EventFunc = EventFunc; } - template - EventButton~EventButton() + template + EventButton::~EventButton() { } - template - void EventButton::checkCollision(InputClass *input) + template + void EventButton::CheckCollision(InputClass *input) { //??????????????? TODO: everything } - template + template void EventButton::SetEventFunc(void (*EventFunc)( ButtonEvent e )) { this->privData.EventFunc = EventFunc; } - template + template unsigned int EventButton::GetID() { return this->privData.ID; } - template + template owner& EventButton::GetOwner() { return this->privData.owner; } } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp index e064ad41..0d270997 100644 --- a/Code/Misc/EventHandler/EventHandler.cpp +++ b/Code/Misc/EventHandler/EventHandler.cpp @@ -2,7 +2,7 @@ using namespace Oyster::Event; -EventHandler EvtHandler; +Oyster::Event::EventHandler EvtHandler; EventHandler& EventHandler::Instance() { @@ -32,5 +32,7 @@ void EventHandler::AddCollection(EventButtonCollection& collection) EventButtonCollection& EventHandler::CreateCollection() { - + EventButtonCollection temp; + collections.push_back(&temp); + return temp; } \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h index e19a8149..7fb86b13 100644 --- a/Code/Misc/EventHandler/EventHandler.h +++ b/Code/Misc/EventHandler/EventHandler.h @@ -14,6 +14,7 @@ namespace Oyster { class EventHandler { + public: EventHandler(); ~EventHandler(); diff --git a/Code/Misc/EventHandler/IEventButton.h b/Code/Misc/EventHandler/IEventButton.h index 35a8827c..4b2467c6 100644 --- a/Code/Misc/EventHandler/IEventButton.h +++ b/Code/Misc/EventHandler/IEventButton.h @@ -1,3 +1,5 @@ +#ifndef MISC_IEVENT_BUTTON +#define MISC_IEVENT_BUTTON #include "../../Input/L_inputClass.h" namespace Oyster @@ -6,8 +8,8 @@ namespace Oyster { class IEventButton { - - private: + + public: enum ButtonState { @@ -17,25 +19,15 @@ namespace Oyster Button_Smashed, }; - struct ButtonEvent - { - ButtonState state; - IEventButton &sender; - - template - owner owner; - }; - - public: - virtual void checkCollision(InputClass *input) = 0; + virtual void CheckCollision(InputClass *input) = 0; + struct ButtonEvent; virtual void SetEventFunc(void (*EventFunc)( ButtonEvent e )) = 0; virtual unsigned int GetID() = 0; - - template - virtual owner& GetOwner() = 0; }; } -} \ No newline at end of file +} + +#endif \ No newline at end of file From 9671eb8ee9ce1945c508974874bdd44dded432bf Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Mon, 3 Feb 2014 10:41:54 +0100 Subject: [PATCH 09/35] Misc - Having problems with template with events. --- Code/Misc/EventHandler/EventButton.h | 29 ++++++++++++------- .../EventHandler/EventButtonCollection.cpp | 6 ++-- .../Misc/EventHandler/EventButtonCollection.h | 2 +- Code/Misc/EventHandler/IEventButton.h | 2 ++ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index 547cdb47..6a0a2cfb 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -13,7 +13,7 @@ namespace Oyster template class EventButton { - private: + public: struct ButtonEvent { IEventButton::ButtonState state; @@ -42,13 +42,16 @@ namespace Oyster void CheckCollision(InputClass *input); + void SendEvent(IEventButton::ButtonState state); + void SetEventFunc(void (*EventFunc)( ButtonEvent e )); //? unsigned int GetID(); - owner& GetOwner(); }; - + + template + unsigned int EventButton::PrivData::currID = 0; template EventButton::EventButton() @@ -73,7 +76,7 @@ namespace Oyster { this->privData.ID = privData.currID; this->privData.currID += 1; - this->privData.owner = NULL; + //this->privData.owner = NULL; this->privData.EventFunc = EventFunc; } @@ -96,6 +99,17 @@ namespace Oyster void EventButton::CheckCollision(InputClass *input) { //??????????????? TODO: everything + SendEvent(Button_Smashed); + } + + template + void EventButton::SendEvent(IEventButton::ButtonState state) + { + ButtonEvent event; + event.state = state; + event.sender = this; + event.owner = privData.owner; + privData.EventFunc(event); } template @@ -109,13 +123,8 @@ namespace Oyster { return this->privData.ID; } - - template - owner& EventButton::GetOwner() - { - return this->privData.owner; - } } } + #endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp index 859abc4d..a6e4ed40 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -23,16 +23,16 @@ void EventButtonCollection::Update(InputClass* inputObject) } template -void EventButtonCollection::AddButton(EventButton& button) +void EventButtonCollection::AddButton(Owner a) { - buttons.push_back(button); + //buttons.push_back(button); } template EventButton& EventButtonCollection::CreateButton() { EventButton temp; - buttons.push_back(&temp); + buttons.push_back((IEventButton)&temp); return temp; } diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h index 9065ffc5..2a3faf35 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -30,7 +30,7 @@ namespace Oyster void Update(InputClass* inputObject); template - void AddButton(EventButton& button); + void AddButton(Owner a); template EventButton& CreateButton(); diff --git a/Code/Misc/EventHandler/IEventButton.h b/Code/Misc/EventHandler/IEventButton.h index 4b2467c6..236ab73c 100644 --- a/Code/Misc/EventHandler/IEventButton.h +++ b/Code/Misc/EventHandler/IEventButton.h @@ -21,6 +21,8 @@ namespace Oyster virtual void CheckCollision(InputClass *input) = 0; + virtual void SendEvent(IEventButton::ButtonState state) = 0; + struct ButtonEvent; virtual void SetEventFunc(void (*EventFunc)( ButtonEvent e )) = 0; From 50d28a5784163fe6186bfc6147f9386700a67281 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Tue, 4 Feb 2014 08:46:20 +0100 Subject: [PATCH 10/35] Misc - Still having problems with template with eventhandler. --- Code/Misc/EventHandler/EventButton.h | 2 +- .../EventHandler/EventButtonCollection.cpp | 14 -------------- .../Misc/EventHandler/EventButtonCollection.h | 19 +++++++++++++++---- Code/Misc/EventHandler/IEventButton.h | 2 -- Code/Misc/Misc.vcxproj | 2 +- Code/Misc/Misc.vcxproj.filters | 10 +++++----- 6 files changed, 22 insertions(+), 27 deletions(-) diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index 6a0a2cfb..e8fbc690 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -58,7 +58,7 @@ namespace Oyster { this->privData.ID = privData.currID; this->privData.currID += 1; - this->privData.owner = NULL; + //this->privData.owner = NULL; this->privData.EventFunc = NULL; } diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp index a6e4ed40..7908816e 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -22,20 +22,6 @@ void EventButtonCollection::Update(InputClass* inputObject) } } -template -void EventButtonCollection::AddButton(Owner a) -{ - //buttons.push_back(button); -} - -template -EventButton& EventButtonCollection::CreateButton() -{ - EventButton temp; - buttons.push_back((IEventButton)&temp); - return temp; -} - EventCollectionState EventButtonCollection::GetState() const { return collectionState; diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h index 2a3faf35..130d59fa 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -29,11 +29,22 @@ namespace Oyster void Update(InputClass* inputObject); - template - void AddButton(Owner a); + template + void AddButton(EventButton& button) + { + EventButton* b = new EventButton(); + buttons.size(); + buttons.push_back((IEventButton*)b); + //buttons.push_back((IEventButton*)&button); + } - template - EventButton& CreateButton(); + template + EventButton& CreateButton() + { + EventButton temp; + buttons.push_back(&temp); + return temp; + } EventCollectionState GetState() const; void SetState(const EventCollectionState state); diff --git a/Code/Misc/EventHandler/IEventButton.h b/Code/Misc/EventHandler/IEventButton.h index 236ab73c..92c58c10 100644 --- a/Code/Misc/EventHandler/IEventButton.h +++ b/Code/Misc/EventHandler/IEventButton.h @@ -8,9 +8,7 @@ namespace Oyster { class IEventButton { - public: - enum ButtonState { Button_Clicked, diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index 51b905d2..f3e58e56 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -166,10 +166,10 @@ + - diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index f8309aed..edcf0e99 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -51,10 +51,10 @@ Source Files - + Source Files - + Source Files @@ -122,15 +122,15 @@ Header Files - - Header Files - Header Files Header Files + + Header Files + Header Files From f372d3e05b0ebd2b5b8c7dce647616bca65c9027 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Thu, 6 Feb 2014 21:15:28 +0100 Subject: [PATCH 11/35] Some cool stuff --- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 26 +- Code/Game/GameLogic/Object.cpp | 5 +- .../Implementation/PhysicsAPI_Impl.cpp | 262 +++++++++++++++--- Code/GamePhysics/PhysicsStructs-Impl.h | 6 + Code/GamePhysics/PhysicsStructs.h | 1 + Code/OysterPhysics3D/OysterCollision3D.cpp | 2 +- Code/OysterPhysics3D/OysterPhysics3D.h | 2 +- Code/OysterPhysics3D/RigidBody.cpp | 13 +- 9 files changed, 258 insertions(+), 61 deletions(-) diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 61c36dd1..ee535868 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -19,7 +19,7 @@ Game::PlayerData::PlayerData() Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); //create player with this rigid body - this->player = new Player(rigidBody,Player::PlayerCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); + this->player = new Player(rigidBody,Player::DefaultCollisionAfter, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); /*Oyster::Physics::ICustomBody::State state; this->player->GetRigidBody()->GetState(state); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 49646e53..81c71de6 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -55,7 +55,7 @@ void Level::InitiateLevel(float radius) sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); sbDesc.ignoreGravity = true; sbDesc.radius = 300; - sbDesc.mass = 10e12f; + sbDesc.mass = 100; sbDesc.frictionCoeff_Static = 0; sbDesc.frictionCoeff_Dynamic = 0; //sbDesc.rotation = @@ -75,7 +75,7 @@ void Level::InitiateLevel(float radius) sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,0); sbDesc_TestBox.ignoreGravity = false; - sbDesc_TestBox.mass = 50; + sbDesc_TestBox.mass = 20; sbDesc_TestBox.size = Oyster::Math::Float4(2,2,2,0); @@ -85,7 +85,7 @@ void Level::InitiateLevel(float radius) int offset = 0; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20 +( i*7) ,320,20,0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,305 + i*5,5,1); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -95,7 +95,7 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20,320, -20 +( i*7),0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20,320, -200 +( i*7),0); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -105,7 +105,7 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(20,320,-20 + ( i*7),0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(200,320 + ( i*7),0,0); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -115,12 +115,12 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20 +( i*7) ,320,-20,0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(5,305 + i*5,0,0); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); - rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]); + rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i]); } @@ -129,10 +129,10 @@ void Level::InitiateLevel(float radius) // add crystal API::SimpleBodyDescription sbDesc_Crystal; - sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 305, 0, 0); + sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 305, 0, 1); sbDesc_Crystal.ignoreGravity = false; - sbDesc_Crystal.mass = 70; - sbDesc_Crystal.size = Oyster::Math::Float4(2,3,2,0); + sbDesc_Crystal.mass = 80; + sbDesc_Crystal.size = Oyster::Math::Float3(2,3,2); ICustomBody* rigidBody_Crystal = API::Instance().CreateRigidBody(sbDesc_Crystal).Release(); rigidBody_Crystal->SetSubscription(Level::PhysicsOnMoveLevel); @@ -143,11 +143,11 @@ void Level::InitiateLevel(float radius) // add house API::SimpleBodyDescription sbDesc_House; //sbDesc_House.centerPosition = Oyster::Math::Float4(212, 212, 0, 0); - sbDesc_House.centerPosition = Oyster::Math::Float4(-50, 290, 0, 0); + sbDesc_House.centerPosition = Oyster::Math::Float4(-50, 290, 0, 1); sbDesc_House.ignoreGravity = false; sbDesc_House.rotation = Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); - sbDesc_House.mass = 70; - sbDesc_House.size = Oyster::Math::Float4(40,40,40,0); + sbDesc_House.mass = 90; + sbDesc_House.size = Oyster::Math::Float3(40,40,40); ICustomBody* rigidBody_House = API::Instance().CreateRigidBody(sbDesc_House).Release(); diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index 68297d46..ebd5c275 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -167,6 +167,7 @@ void Object::EndFrame() //error int i =0 ; } + axis.Normalize(); currPhysicsState.SetRotation(axis.xyz); currPhysicsState.SetAngularMomentum(Float3::null); Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); @@ -177,13 +178,13 @@ void Object::EndFrame() //300, 0,0, //1,0,0 - if( pos.GetLength() < 303.5f) + /*if( pos.GetLength() < 303.5f) { Oyster::Math::Float moveUp = 303.5 - pos.GetLength(); up *= moveUp; currPhysicsState.SetCenterPosition(pos + up); - } + }*/ if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum()) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 7981322f..85b474d2 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -14,7 +14,7 @@ API_Impl API_instance; namespace { - void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef ) + /*void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef ) { auto proto = worldScene.GetCustomBody( protoTempRef ); auto deuter = worldScene.GetCustomBody( deuterTempRef ); @@ -27,26 +27,26 @@ namespace ICustomBody::State deuterState; deuter->GetState( deuterState ); // calc from perspective of deuter. - Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )).GetNormalized(); // Init value is only borrowed - if( normal.Dot(normal) > 0.0f ) + Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )); // Init value is only borrowed + //if( normal.Dot(normal) > 0.0f ) { deuter->GetNormalAt( worldPointOfContact, normal ); } - else - { // special case: deuter is completly contained within proto or they have overlapping centers. + //else + //{ // special case: deuter is completly contained within proto or they have overlapping centers. - normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f ); - if( normal.Dot(normal) == 0.0f ) - { // they have overlapping centers. Rebound at least - // calculate and store time interpolation value, for later rebound. - proto->SetTimeOfContact( worldPointOfContact ); - return; - } - - // borrowing the negated normal of proto. - proto->GetNormalAt( worldPointOfContact, normal ); - normal = -normal; - } + // normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f ); + // if( normal.Dot(normal) == 0.0f ) + // { // they have overlapping centers. Rebound at least + // // calculate and store time interpolation value, for later rebound. + // proto->SetTimeOfContact( worldPointOfContact ); + // return; + // } + // + // // borrowing the negated normal of proto. + // proto->GetNormalAt( worldPointOfContact, normal ); + // normal = -normal; + //} normal.Normalize(); Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0), @@ -93,13 +93,13 @@ namespace // PLayerHAck if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_player_collision_response ) { - Float3 linearMomentum = protoState.GetLinearMomentum(); - Float3 up = -protoState.GetGravityNormal(); - Float3 upForce = (linearMomentum.Dot(up) * up); + //Float3 linearMomentum = protoState.GetLinearMomentum(); + //Float3 up = -protoState.GetGravityNormal(); + //Float3 upForce = (linearMomentum.Dot(up) * up); - Float3 noBounceForce = linearMomentum - upForce; - protoState.SetLinearMomentum(noBounceForce); - proto->SetState(protoState); + //Float3 noBounceForce = linearMomentum - upForce; + //protoState.SetLinearMomentum(noBounceForce); + //proto->SetState(protoState); return; } // calculate and store time interpolation value, for later rebound. @@ -114,24 +114,25 @@ namespace // calc from perspective of proto normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized(); - if( normal.Dot(normal) > 0.0f ) + //if( normal.Dot(normal) > 0.0f ) { proto->GetNormalAt( worldPointOfContact, normal ); protoG_Magnitude = protoG.Dot( normal ); deuterG_Magnitude = deuterG.Dot( normal ); + normal.Normalize(); } - else - { // special case: proto is completly contained within deuter. - // borrowing the negated normal of deuter. - deuter->GetNormalAt( worldPointOfContact, normal ); - normal = -normal; - protoG_Magnitude = -protoG_Magnitude; - deuterG_Magnitude = -deuterG_Magnitude; - } + //else + //{ // special case: proto is completly contained within deuter. + // // borrowing the negated normal of deuter. + // deuter->GetNormalAt( worldPointOfContact, normal ); + // normal = -normal; + // protoG_Magnitude = -protoG_Magnitude; + // deuterG_Magnitude = -deuterG_Magnitude; + //} if( normal != normal ) // debug: trap const char *breakpoint = "This should never happen"; - + // bounce Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), protoState.GetMass(), protoG_Magnitude, @@ -143,9 +144,183 @@ namespace Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); + if(protoState.GetMass() == 70) + { + const char* breakPoint = "here"; + } + Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); - protoState.ApplyImpulse( bounce.xyz - friction.xyz, worldPointOfContact.xyz, normal.xyz ); + protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); + proto->SetState( protoState ); + + Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); + + proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyPBefore - kineticEnergyPAFter ); + } + + + }*/ + void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef ) + { + auto proto = worldScene.GetCustomBody( protoTempRef ); + auto deuter = worldScene.GetCustomBody( deuterTempRef ); + + if(proto->GetState().GetMass() == 70) + { + const char *breakpoint = "STOP"; + } + + Float4 worldPointOfContact; + if( proto->Intersects(*deuter, worldPointOfContact) ) + { + // Apply CollisionResponse in pure gather pattern + ICustomBody::State protoState; proto->GetState( protoState ); + ICustomBody::State deuterState; deuter->GetState( deuterState ); + + // calc from perspective of deuter. + // calc from perspective of deuter. + Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )).GetNormalized(); // Init value is only borrowed + if( normal.Dot(normal) > 0.0f ) + { + deuter->GetNormalAt( worldPointOfContact, normal ); + } + else + { // special case: deuter is completly contained within proto or they have overlapping centers. + + normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f ); + if( normal.Dot(normal) == 0.0f ) + { // they have overlapping centers. Rebound at least + // calculate and store time interpolation value, for later rebound. + proto->SetTimeOfContact( worldPointOfContact ); + return; + } + + // borrowing the negated normal of proto. + proto->GetNormalAt( worldPointOfContact, normal ); + normal = -normal; + } + normal.Normalize(); + + Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0), + deuterG = Float4(deuterState.GetLinearMomentum( worldPointOfContact.xyz ), 0); + + Float protoG_Magnitude = protoG.Dot( normal ), + deuterG_Magnitude = deuterG.Dot( normal ); + + if(protoState.GetMass() == 70) + { + const char *breakpoint = "STOP"; + } + + // if they are not relatively moving towards eachother, there is no collision + Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) ); + if( deltaPos < 0.0f ) + { + if( protoG_Magnitude >= deuterG_Magnitude ) + { + return; + } + } + else if( deltaPos > 0.0f ) + { + if( protoG_Magnitude <= deuterG_Magnitude ) + { + return; + } + } + else + { + return; + } + + // calc from perspective of proto + normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized(); + if( normal.Dot(normal) > 0.0f ) + { + proto->GetNormalAt( worldPointOfContact, normal ); + protoG_Magnitude = protoG.Dot( normal ); + deuterG_Magnitude = deuterG.Dot( normal ); + normal.Normalize(); + } + else + { // special case: proto is completly contained within deuter. + // borrowing the negated normal of deuter. + deuter->GetNormalAt( worldPointOfContact, normal ); + normal = -normal; + protoG_Magnitude = -protoG_Magnitude; + deuterG_Magnitude = -deuterG_Magnitude; + } + normal.Normalize(); + + if( normal != normal ) // debug: trap + const char *breakpoint = "This should never happen"; + + Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal, + Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), + Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); + + if(protoState.GetMass() == 70) + { + const char *breakpoint = "STOP"; + } + + protoState.ApplyFriction( -friction.xyz ); + + if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response ) + { + return; + } + + // PLayerHAck + if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_player_collision_response ) + { + return; + } + + + if(protoState.GetMass() == 50) + { + const char* breakPoint = "Break"; + } + + // bounce + Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), + deuterState.GetMass(), deuterG_Magnitude, + protoState.GetMass(), protoG_Magnitude ); + + // calc from perspective of proto + proto->GetNormalAt( worldPointOfContact, normal ); + normal.Normalize(); + protoG_Magnitude = protoG.Dot( normal ); + deuterG_Magnitude = deuterG.Dot( normal ); + + // bounce + Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), + protoState.GetMass(), protoG_Magnitude, + deuterState.GetMass(), deuterG_Magnitude ); + + Float4 bounce = bounceP; + + //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); + + + if( abs(bounce.x) < 0.001 ) + { + bounce.x = 0; + } + if( abs(bounce.y) < 0.001 ) + { + bounce.y = 0; + } + if( abs(bounce.z) < 0.001 ) + { + bounce.z = 0; + } + + Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); + + protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); proto->SetState( protoState ); Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); @@ -232,8 +407,12 @@ void API_Impl::Update() Float rSquared = d.Dot( d ); if( rSquared != 0.0 ) { + if(state.GetMass() == 70) + { + const char *breakpoint = "STOP"; + } Float force = Physics3D::Formula::ForceField( this->gravityConstant, state.GetMass(), this->gravity[i].well.mass, rSquared ); - gravityImpulse += (this->updateFrameLength * force / ::std::sqrt(rSquared)) * d; + gravityImpulse += ((this->updateFrameLength * force)) * d.GetNormalized(); } break; } @@ -250,14 +429,17 @@ void API_Impl::Update() if( gravityImpulse != gravityImpulse ) // debug: trap const char *breakpoint = "This should never happen"; - - if( gravityImpulse != Float4::null ) + Float posLength = state.GetCenterPosition().GetLength(); + if( gravityImpulse != Float4::null && posLength - 300 > 3.5 ) { state.ApplyLinearImpulse( gravityImpulse.xyz ); state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); (*proto)->SetState( state ); } - + if(state.GetMass() == 70) + { + const char *breakpoint = "STOP"; + } // Step 2: Apply Collision Response this->worldScene.Visit( *proto, OnPossibleCollision ); } @@ -271,7 +453,7 @@ void API_Impl::Update() //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); - if( abs(lM.x) < this->epsilon ) + /*if( abs(lM.x) < this->epsilon ) { state.linearMomentum.x = 0; } @@ -282,7 +464,7 @@ void API_Impl::Update() if( abs(lM.z) < this->epsilon ) { state.linearMomentum.z = 0; - } + }*/ (*proto)->SetState( state ); diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h index 30e1a605..eae72623 100644 --- a/Code/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/GamePhysics/PhysicsStructs-Impl.h @@ -333,6 +333,12 @@ namespace Oyster this->isDisturbed = true; } + inline void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j ) + { + this->linearImpulse += j; + this->isDisturbed = true; + } + inline void CustomBodyState::ApplyForwarding( const ::Oyster::Math::Float3 &deltaPos, const ::Oyster::Math::Float3 &deltaAxis ) { this->deltaPos += deltaPos; diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index 61a0569f..6bf39a67 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -109,6 +109,7 @@ namespace Oyster { namespace Physics void ApplyLinearImpulse( const ::Oyster::Math::Float3 &j ); void ApplyAngularImpulse( const ::Oyster::Math::Float3 &j ); void ApplyImpulse( const ::Oyster::Math::Float3 &j, const ::Oyster::Math::Float3 &at, const ::Oyster::Math::Float3 &normal ); + void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j); void ApplyForwarding( const ::Oyster::Math::Float3 &deltaPos, const ::Oyster::Math::Float3 &deltaAxis ); bool IsSpatiallyAltered() const; diff --git a/Code/OysterPhysics3D/OysterCollision3D.cpp b/Code/OysterPhysics3D/OysterCollision3D.cpp index 41e11875..6cade619 100644 --- a/Code/OysterPhysics3D/OysterCollision3D.cpp +++ b/Code/OysterPhysics3D/OysterCollision3D.cpp @@ -516,7 +516,7 @@ namespace Oyster { namespace Collision3D { namespace Utility Float4 C = sphereA.center; C -= sphereB.center; Float r = (sphereA.radius + sphereB.radius); - + Float dotprod = C.Dot(C); if (r*r >= C.Dot(C)) { return true; // Intersect detected! diff --git a/Code/OysterPhysics3D/OysterPhysics3D.h b/Code/OysterPhysics3D/OysterPhysics3D.h index e1eb94e3..e8506bc7 100644 --- a/Code/OysterPhysics3D/OysterPhysics3D.h +++ b/Code/OysterPhysics3D/OysterPhysics3D.h @@ -279,7 +279,7 @@ namespace Oyster { namespace Physics3D ******************************************************************/ inline ::Oyster::Math::Float ForceField( ::Oyster::Math::Float g, ::Oyster::Math::Float massA, ::Oyster::Math::Float massB, ::Oyster::Math::Float radiusSquared ) { - return g * massA * massB / radiusSquared; + return g * massB / radiusSquared; } /****************************************************************** diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index 3563c77e..d9f2f69d 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -51,12 +51,19 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the linear //Decrease momentum with 1% as "fall-off" //! HACK: @todo Add real solution with fluid drag - this->momentum_Linear = this->momentum_Linear*0.9999f; - this->momentum_Angular = this->momentum_Angular*0.9999f; + //this->momentum_Linear = this->momentum_Linear*0.99f; + //this->momentum_Angular = this->momentum_Angular*0.99f; // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G - this->centerPos += ( updateFrameLength / this->mass ) * AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); + Float3 delta = AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); + Float3 newPos = ( updateFrameLength)*this->momentum_Linear; + this->centerPos += newPos; + if(this->mass == 70) + { + const char *breakpoint = "STOP"; + } + // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); From b225c536112526c2c379053aa1a73fd359961c60 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Fri, 7 Feb 2014 11:43:18 +0100 Subject: [PATCH 12/35] More cool stuff --- .../GameClientState/LobbyState.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 6 +-- Code/Game/GameLogic/Object.cpp | 16 ++++---- .../Implementation/PhysicsAPI_Impl.cpp | 41 ++++++------------- .../Implementation/SimpleRigidBody.cpp | 6 +-- .../Implementation/SphericalRigidBody.cpp | 6 +-- Code/OysterPhysics3D/RigidBody.cpp | 6 +-- 7 files changed, 34 insertions(+), 49 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp index 538408c5..cce1dfcd 100644 --- a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp @@ -55,7 +55,7 @@ bool LobbyState::LoadModels(std::wstring file) modelData.world = Oyster::Math3D::Float4x4::identity; modelData.visible = true; - modelData.modelPath = L"..\\Content\\Models\\box_2.dan"; + modelData.modelPath = L"crate_colonists.dan"; // load models privData->object[0] = new C_StaticObj(); privData->object[0]->Init(modelData); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 81c71de6..14a5d140 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -72,11 +72,11 @@ void Level::InitiateLevel(float radius) //this->dynamicObjects = new DynamicArray< DynamicObject>; // add box API::SimpleBodyDescription sbDesc_TestBox; - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,1); sbDesc_TestBox.ignoreGravity = false; sbDesc_TestBox.mass = 20; - sbDesc_TestBox.size = Oyster::Math::Float4(2,2,2,0); + sbDesc_TestBox.size = Oyster::Math::Float4(1,1,1,0); ICustomBody* rigidBody_TestBox; @@ -132,7 +132,7 @@ void Level::InitiateLevel(float radius) sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 305, 0, 1); sbDesc_Crystal.ignoreGravity = false; sbDesc_Crystal.mass = 80; - sbDesc_Crystal.size = Oyster::Math::Float3(2,3,2); + sbDesc_Crystal.size = Oyster::Math::Float3(1,2,1); ICustomBody* rigidBody_Crystal = API::Instance().CreateRigidBody(sbDesc_Crystal).Release(); rigidBody_Crystal->SetSubscription(Level::PhysicsOnMoveLevel); diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index ebd5c275..b7e392fe 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -158,10 +158,10 @@ void Object::EndFrame() } - if(currPhysicsState.GetGravityNormal()!= Float3::null) + //if(currPhysicsState.GetGravityNormal()!= Float3::null) { Oyster::Math::Float4 axis; - Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(currPhysicsState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, -Oyster::Math::Float4(currPhysicsState.GetGravityNormal()), axis); + Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(currPhysicsState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, Oyster::Math::Float4(currPhysicsState.GetCenterPosition().GetNormalized(), 0), axis); if(axis !=axis) { //error @@ -170,17 +170,17 @@ void Object::EndFrame() axis.Normalize(); currPhysicsState.SetRotation(axis.xyz); currPhysicsState.SetAngularMomentum(Float3::null); - Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); - debug += currPhysicsState.GetGravityNormal(); + //Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); + //debug += currPhysicsState.GetGravityNormal(); } - Oyster::Math::Float3 pos = currPhysicsState.GetCenterPosition(); - Oyster::Math::Float3 up = -currPhysicsState.GetGravityNormal(); + //Oyster::Math::Float3 pos = currPhysicsState.GetCenterPosition(); + //Oyster::Math::Float3 up = -currPhysicsState.GetGravityNormal(); //300, 0,0, //1,0,0 - /*if( pos.GetLength() < 303.5f) + /*if( pos.GetLength() < 301.5f) { - Oyster::Math::Float moveUp = 303.5 - pos.GetLength(); + Oyster::Math::Float moveUp = 301.5 - pos.GetLength(); up *= moveUp; currPhysicsState.SetCenterPosition(pos + up); diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 85b474d2..06319fba 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -178,9 +178,7 @@ namespace ICustomBody::State protoState; proto->GetState( protoState ); ICustomBody::State deuterState; deuter->GetState( deuterState ); - // calc from perspective of deuter. - // calc from perspective of deuter. - Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )).GetNormalized(); // Init value is only borrowed + Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )); // Init value is only borrowed if( normal.Dot(normal) > 0.0f ) { deuter->GetNormalAt( worldPointOfContact, normal ); @@ -208,7 +206,7 @@ namespace Float protoG_Magnitude = protoG.Dot( normal ), deuterG_Magnitude = deuterG.Dot( normal ); - if(protoState.GetMass() == 70) + if(protoState.GetMass() == 20) { const char *breakpoint = "STOP"; } @@ -234,7 +232,11 @@ namespace return; } - // calc from perspective of proto + // bounce + Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), + deuterState.GetMass(), deuterG_Magnitude, + protoState.GetMass(), protoG_Magnitude ); + normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized(); if( normal.Dot(normal) > 0.0f ) { @@ -260,10 +262,7 @@ namespace Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); - if(protoState.GetMass() == 70) - { - const char *breakpoint = "STOP"; - } + protoState.ApplyFriction( -friction.xyz ); @@ -279,21 +278,7 @@ namespace } - if(protoState.GetMass() == 50) - { - const char* breakPoint = "Break"; - } - - // bounce - Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), - deuterState.GetMass(), deuterG_Magnitude, - protoState.GetMass(), protoG_Magnitude ); - - // calc from perspective of proto - proto->GetNormalAt( worldPointOfContact, normal ); - normal.Normalize(); - protoG_Magnitude = protoG.Dot( normal ); - deuterG_Magnitude = deuterG.Dot( normal ); + // bounce Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), @@ -411,7 +396,7 @@ void API_Impl::Update() { const char *breakpoint = "STOP"; } - Float force = Physics3D::Formula::ForceField( this->gravityConstant, state.GetMass(), this->gravity[i].well.mass, rSquared ); + Float force = 9.82*10; gravityImpulse += ((this->updateFrameLength * force)) * d.GetNormalized(); } break; @@ -430,7 +415,7 @@ void API_Impl::Update() if( gravityImpulse != gravityImpulse ) // debug: trap const char *breakpoint = "This should never happen"; Float posLength = state.GetCenterPosition().GetLength(); - if( gravityImpulse != Float4::null && posLength - 300 > 3.5 ) + if( gravityImpulse != Float4::null && posLength - 300 > state.GetReach().y ) { state.ApplyLinearImpulse( gravityImpulse.xyz ); state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); @@ -453,7 +438,7 @@ void API_Impl::Update() //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); - /*if( abs(lM.x) < this->epsilon ) + if( abs(lM.x) < this->epsilon ) { state.linearMomentum.x = 0; } @@ -464,7 +449,7 @@ void API_Impl::Update() if( abs(lM.z) < this->epsilon ) { state.linearMomentum.z = 0; - }*/ + } (*proto)->SetState( state ); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index b57c2a97..f1c196f7 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -335,17 +335,17 @@ UpdateState SimpleRigidBody::Update( Float timeStepLength ) timeStepLength *= 2.0f - this->collisionRebound.timeOfContact; // compensate for rebounded time this->collisionRebound.timeOfContact = 1.0f; } - + // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) Float4 temp; ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz ); this->rigid.axis -= ((2.0f * pi) * temp).xyz; - + // Update rebound data this->collisionRebound.previousSpatial.center = this->rigid.centerPos; this->collisionRebound.previousSpatial.axis = this->rigid.axis; this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - + // Check if this is close enough to be set resting temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f ); if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) ) diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index ac566abd..0ecb8b6e 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -257,17 +257,17 @@ UpdateState SphericalRigidBody::Update( Float timeStepLength ) timeStepLength *= 2.0f - this->collisionRebound.timeOfContact; // compensate for rebounded time this->collisionRebound.timeOfContact = 1.0f; } - + // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) Float4 temp; ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz ); this->rigid.axis -= ((2.0f * pi) * temp).xyz; - + // Update rebound data this->collisionRebound.previousSpatial.center = this->rigid.centerPos; this->collisionRebound.previousSpatial.axis = this->rigid.axis; this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - + // Check if this is close enough to be set resting temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f ); if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) ) diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index d9f2f69d..957d28a0 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -66,14 +66,14 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H - this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); - this->rotation = Rotation( this->axis ); + //this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); + //this->rotation = Rotation( this->axis ); // update momentums and clear impulse_Linear and impulse_Angular this->momentum_Linear += this->impulse_Linear; this->impulse_Linear = Float4::null; - this->momentum_Angular += this->impulse_Angular; //! HACK: @todo Rotation temporary disabled + //this->momentum_Angular += this->impulse_Angular; //! HACK: @todo Rotation temporary disabled this->impulse_Angular = Float4::null; } From 1633129a2c28cb66ea035210f5c1ef0b7a77a73d Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Fri, 7 Feb 2014 13:09:44 +0100 Subject: [PATCH 13/35] Commit to Dennis --- .../DanBiasGame/GameClientState/GameState.cpp | 2 +- .../Implementation/PhysicsAPI_Impl.cpp | 34 ++++++++++--------- Code/OysterPhysics3D/RigidBody.cpp | 10 +++--- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index d8547943..8b47400a 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -353,7 +353,7 @@ void GameState::readKeyInput(InputClass* KeyInput) } //send delta mouse movement - if (KeyInput->IsMousePressed()) + //if (KeyInput->IsMousePressed()) { camera->Yaw(-KeyInput->GetYaw()); camera->Pitch(KeyInput->GetPitch()); diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 06319fba..0203f87a 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -375,20 +375,21 @@ float API_Impl::GetFrameTimeLength() const void API_Impl::Update() { /** @todo TODO: Update is a temporary solution .*/ ::std::vector updateList; - auto proto = this->worldScene.Sample( Universe(), updateList ).begin(); + this->worldScene.Sample( Universe(), updateList ); ICustomBody::State state; - for( ; proto != updateList.end(); ++proto ) + for( int i = 0; i < updateList.size(); i++ ) { + auto proto = updateList[i]; // Step 1: Apply Gravity Float4 gravityImpulse = Float4::null; - (*proto)->GetState( state ); - for( ::std::vector::size_type i = 0; i < this->gravity.size(); ++i ) + proto->GetState( state ); + for( int j = 0; j < this->gravity.size(); ++j ) { - switch( this->gravity[i].gravityType ) + switch( this->gravity[j].gravityType ) { case Gravity::GravityType_Well: { - Float4 d = Float4( this->gravity[i].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f ); + Float4 d = Float4( this->gravity[j].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f ); Float rSquared = d.Dot( d ); if( rSquared != 0.0 ) { @@ -402,7 +403,7 @@ void API_Impl::Update() break; } case Gravity::GravityType_Directed: - gravityImpulse += Float4( this->gravity[i].directed.impulse, 0.0f ); + gravityImpulse += Float4( this->gravity[j].directed.impulse, 0.0f ); break; // case Gravity::GravityType_DirectedField: // //this->gravity[i].directedField. @@ -419,20 +420,21 @@ void API_Impl::Update() { state.ApplyLinearImpulse( gravityImpulse.xyz ); state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); - (*proto)->SetState( state ); + proto->SetState( state ); } if(state.GetMass() == 70) { const char *breakpoint = "STOP"; } // Step 2: Apply Collision Response - this->worldScene.Visit( *proto, OnPossibleCollision ); + this->worldScene.Visit( proto, OnPossibleCollision ); } - proto = updateList.begin(); - for( ; proto != updateList.end(); ++proto ) + + for( int i = 0; i < updateList.size(); i++ ) { - (*proto)->GetState( state ); + auto proto = updateList[i]; + proto->GetState( state ); Float3 lM = state.GetLinearMomentum(); //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); @@ -451,13 +453,13 @@ void API_Impl::Update() state.linearMomentum.z = 0; } - (*proto)->SetState( state ); + proto->SetState( state ); - switch( (*proto)->Update(this->updateFrameLength) ) + switch( proto->Update(this->updateFrameLength) ) { case UpdateState_altered: - this->worldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(*proto) ); - (*proto)->CallSubscription_Move(); + this->worldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(proto) ); + proto->CallSubscription_Move(); case UpdateState_resting: default: break; diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index 957d28a0..f7a5646e 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -51,8 +51,8 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the linear //Decrease momentum with 1% as "fall-off" //! HACK: @todo Add real solution with fluid drag - //this->momentum_Linear = this->momentum_Linear*0.99f; - //this->momentum_Angular = this->momentum_Angular*0.99f; + this->momentum_Linear = this->momentum_Linear*0.99f; + this->momentum_Angular = this->momentum_Angular*0.99f; // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G Float3 delta = AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); @@ -66,14 +66,14 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H - //this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); - //this->rotation = Rotation( this->axis ); + this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); + this->rotation = Rotation( this->axis ); // update momentums and clear impulse_Linear and impulse_Angular this->momentum_Linear += this->impulse_Linear; this->impulse_Linear = Float4::null; - //this->momentum_Angular += this->impulse_Angular; //! HACK: @todo Rotation temporary disabled + this->momentum_Angular += this->impulse_Angular; //! HACK: @todo Rotation temporary disabled this->impulse_Angular = Float4::null; } From ab9f81ac60f8c8743b8589ebe617a53e081a4ec9 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Fri, 7 Feb 2014 15:38:53 +0100 Subject: [PATCH 14/35] Collisions work better Still needs polishing --- .../DanBiasGame/GameClientState/GameState.cpp | 5 +- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 16 +- Code/GamePhysics/Implementation/Octree.cpp | 3 + .../Implementation/PhysicsAPI_Impl.cpp | 186 ++++++------------ .../Implementation/SimpleRigidBody.cpp | 5 + .../Implementation/SphericalRigidBody.cpp | 17 +- Code/OysterPhysics3D/RigidBody.cpp | 4 +- 8 files changed, 88 insertions(+), 150 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 8b47400a..06def943 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -94,6 +94,9 @@ bool GameState::LoadModels(std::wstring mapFile) C_Object* obj; translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(0,0,0)); modelData.world = translate ;//modelData.world * translate + modelData.world.v[0].x = 2; + modelData.world.v[1].y = 2; + modelData.world.v[2].z = 2; modelData.modelPath = L"world_earth.dan"; modelData.id = id++; @@ -483,7 +486,7 @@ void GameState::Protocol( ObjPos* pos ) camera->setRight(right); camera->setUp(up); - camera->setLook(objForward); + //camera->setLook(objForward); up *= 1; objForward *= -2; diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index ee535868..e4b54f9a 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -7,7 +7,7 @@ Game::PlayerData::PlayerData() { //set some stats that are appropriate to a player Oyster::Physics::API::SimpleBodyDescription sbDesc; - sbDesc.centerPosition = Oyster::Math::Float3(0,308,0); + sbDesc.centerPosition = Oyster::Math::Float3(0,608,0); sbDesc.size = Oyster::Math::Float3(0.5f,2,1); sbDesc.mass = 70; sbDesc.restitutionCoeff = 0.5; diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 14a5d140..9dc4a6f8 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -54,7 +54,7 @@ void Level::InitiateLevel(float radius) API::SphericalBodyDescription sbDesc; sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); sbDesc.ignoreGravity = true; - sbDesc.radius = 300; + sbDesc.radius = 600; sbDesc.mass = 100; sbDesc.frictionCoeff_Static = 0; sbDesc.frictionCoeff_Dynamic = 0; @@ -76,7 +76,7 @@ void Level::InitiateLevel(float radius) sbDesc_TestBox.ignoreGravity = false; sbDesc_TestBox.mass = 20; - sbDesc_TestBox.size = Oyster::Math::Float4(1,1,1,0); + sbDesc_TestBox.size = Oyster::Math::Float4(0.5,0.5,0.5,0); ICustomBody* rigidBody_TestBox; @@ -85,7 +85,7 @@ void Level::InitiateLevel(float radius) int offset = 0; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,305 + i*5,5,1); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,605 + i*5,5,1); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -95,7 +95,7 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20,320, -200 +( i*7),0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20,620, -200 +( i*7),0); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -105,7 +105,7 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(200,320 + ( i*7),0,0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(200,620 + ( i*7),0,0); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -115,7 +115,7 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(5,305 + i*5,0,0); + sbDesc_TestBox.centerPosition = Oyster::Math::Float4(5,605 + i*5,0,0); rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); @@ -129,7 +129,7 @@ void Level::InitiateLevel(float radius) // add crystal API::SimpleBodyDescription sbDesc_Crystal; - sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 305, 0, 1); + sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 605, 0, 1); sbDesc_Crystal.ignoreGravity = false; sbDesc_Crystal.mass = 80; sbDesc_Crystal.size = Oyster::Math::Float3(1,2,1); @@ -143,7 +143,7 @@ void Level::InitiateLevel(float radius) // add house API::SimpleBodyDescription sbDesc_House; //sbDesc_House.centerPosition = Oyster::Math::Float4(212, 212, 0, 0); - sbDesc_House.centerPosition = Oyster::Math::Float4(-50, 290, 0, 1); + sbDesc_House.centerPosition = Oyster::Math::Float4(-50, 690, 0, 1); sbDesc_House.ignoreGravity = false; sbDesc_House.rotation = Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); sbDesc_House.mass = 90; diff --git a/Code/GamePhysics/Implementation/Octree.cpp b/Code/GamePhysics/Implementation/Octree.cpp index 47bf3e39..e615df63 100644 --- a/Code/GamePhysics/Implementation/Octree.cpp +++ b/Code/GamePhysics/Implementation/Octree.cpp @@ -140,6 +140,7 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction ) { auto object = this->mapReferences.find(customBodyRef); + // If rigid body is not found if(object == this->mapReferences.end()) { return; @@ -147,8 +148,10 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction ) unsigned int tempRef = object->second; + // Go through all object and test for intersection for(unsigned int i = 0; ileafData.size(); i++) { + // If objects intersect call collision response function if(tempRef != i && !this->leafData[i].limbo) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container)) { hitAction(*this, tempRef, i); diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 0203f87a..a59c03b1 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -166,11 +166,6 @@ namespace auto proto = worldScene.GetCustomBody( protoTempRef ); auto deuter = worldScene.GetCustomBody( deuterTempRef ); - if(proto->GetState().GetMass() == 70) - { - const char *breakpoint = "STOP"; - } - Float4 worldPointOfContact; if( proto->Intersects(*deuter, worldPointOfContact) ) { @@ -178,25 +173,12 @@ namespace ICustomBody::State protoState; proto->GetState( protoState ); ICustomBody::State deuterState; deuter->GetState( deuterState ); - Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )); // Init value is only borrowed - if( normal.Dot(normal) > 0.0f ) - { - deuter->GetNormalAt( worldPointOfContact, normal ); - } - else - { // special case: deuter is completly contained within proto or they have overlapping centers. + - normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f ); - if( normal.Dot(normal) == 0.0f ) - { // they have overlapping centers. Rebound at least - // calculate and store time interpolation value, for later rebound. - proto->SetTimeOfContact( worldPointOfContact ); - return; - } - - // borrowing the negated normal of proto. - proto->GetNormalAt( worldPointOfContact, normal ); - normal = -normal; + Float4 normal = deuter->GetNormalAt(worldPointOfContact); + if(normal == Float4::null) + { + normal = Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1); } normal.Normalize(); @@ -206,12 +188,16 @@ namespace Float protoG_Magnitude = protoG.Dot( normal ), deuterG_Magnitude = deuterG.Dot( normal ); - if(protoState.GetMass() == 20) + // If true the object is inside the world + if(worldPointOfContact.GetLength() < 600 && protoState.GetCenterPosition().GetLength() != 0) { - const char *breakpoint = "STOP"; + Float overlap = 600 - worldPointOfContact.GetLength(); + Float3 newPos = overlap*worldPointOfContact.GetNormalized(); + protoState.SetCenterPosition(protoState.GetCenterPosition() + newPos); + protoState.SetLinearMomentum(Float3(0, 0, 0)); } - // if they are not relatively moving towards eachother, there is no collision + // If they are not relatively moving towards eachother, there is no collision Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) ); if( deltaPos < 0.0f ) { @@ -232,64 +218,34 @@ namespace return; } - // bounce - Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), - deuterState.GetMass(), deuterG_Magnitude, - protoState.GetMass(), protoG_Magnitude ); - - normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized(); - if( normal.Dot(normal) > 0.0f ) + // Proto + normal = -proto->GetNormalAt(worldPointOfContact); + if(normal == Float4::null) { - proto->GetNormalAt( worldPointOfContact, normal ); - protoG_Magnitude = protoG.Dot( normal ); - deuterG_Magnitude = deuterG.Dot( normal ); - normal.Normalize(); - } - else - { // special case: proto is completly contained within deuter. - // borrowing the negated normal of deuter. - deuter->GetNormalAt( worldPointOfContact, normal ); - normal = -normal; - protoG_Magnitude = -protoG_Magnitude; - deuterG_Magnitude = -deuterG_Magnitude; + normal = Float4(protoState.GetCenterPosition(), 1) - Float4(deuterState.GetCenterPosition(), 1); } normal.Normalize(); - - if( normal != normal ) // debug: trap - const char *breakpoint = "This should never happen"; + // Calculate and apply friction to rigid body Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal, Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); + //protoState.ApplyFriction( -friction.xyz ); - - protoState.ApplyFriction( -friction.xyz ); - + // If no other collision response is wanted then this will stop the bounce if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response ) { return; } - // PLayerHAck - if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_player_collision_response ) - { - return; - } - - + - - // bounce - Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), + // Calaculate bounce + Float4 bounce = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), protoState.GetMass(), protoG_Magnitude, deuterState.GetMass(), deuterG_Magnitude ); - - Float4 bounce = bounceP; - - //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); - - + // If bounce is not big enough to matter, set to 0 if( abs(bounce.x) < 0.001 ) { bounce.x = 0; @@ -303,14 +259,23 @@ namespace bounce.z = 0; } - Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); + if( bounce != bounce) + { + const char* breakpoint = "STOP"; + } + // Calculate kinetic energy before impulse is applied + Float kineticEnergyBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); + + // Apply the bounce as impulse protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); proto->SetState( protoState ); - Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); + // Calculate kinetic energy after impulse is applied + Float kineticEnergyAfter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); - proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyPBefore - kineticEnergyPAFter ); + // Call a collision function with kinetic energy loss + proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyBefore - kineticEnergyAfter ); } } } @@ -373,91 +338,50 @@ float API_Impl::GetFrameTimeLength() const } void API_Impl::Update() -{ /** @todo TODO: Update is a temporary solution .*/ - ::std::vector updateList; - this->worldScene.Sample( Universe(), updateList ); +{ ICustomBody::State state; + ::std::vector updateList; + + // Fetch objects in universe + this->worldScene.Sample( Universe(), updateList ); + + // Change momentum for all rigid bodies for( int i = 0; i < updateList.size(); i++ ) { - auto proto = updateList[i]; - // Step 1: Apply Gravity + ICustomBody* proto = updateList[i]; + // Step 1: Apply gravity to rigid body Float4 gravityImpulse = Float4::null; proto->GetState( state ); - for( int j = 0; j < this->gravity.size(); ++j ) + + Float4 deltaPosGrav = Float4( this->gravity[0].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f ); + Float rSquared = deltaPosGrav.Dot( deltaPosGrav ); + if( rSquared != 0.0 ) { - switch( this->gravity[j].gravityType ) - { - case Gravity::GravityType_Well: - { - Float4 d = Float4( this->gravity[j].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f ); - Float rSquared = d.Dot( d ); - if( rSquared != 0.0 ) - { - if(state.GetMass() == 70) - { - const char *breakpoint = "STOP"; - } - Float force = 9.82*10; - gravityImpulse += ((this->updateFrameLength * force)) * d.GetNormalized(); - } - break; - } - case Gravity::GravityType_Directed: - gravityImpulse += Float4( this->gravity[j].directed.impulse, 0.0f ); - break; -// case Gravity::GravityType_DirectedField: -// //this->gravity[i].directedField. -// //! TODO: @todo rethink -// break; - default: break; - } + Float force = 9.82*10; + gravityImpulse += (this->updateFrameLength*force)*deltaPosGrav.GetNormalized(); } - if( gravityImpulse != gravityImpulse ) // debug: trap - const char *breakpoint = "This should never happen"; Float posLength = state.GetCenterPosition().GetLength(); - if( gravityImpulse != Float4::null && posLength - 300 > state.GetReach().y ) + if( gravityImpulse != Float4::null && posLength - 601 > state.GetReach().GetLength() ) { state.ApplyLinearImpulse( gravityImpulse.xyz ); state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); proto->SetState( state ); } - if(state.GetMass() == 70) - { - const char *breakpoint = "STOP"; - } - // Step 2: Apply Collision Response + + // Step 2: Step through octree and apply collision responses to rigid body this->worldScene.Visit( proto, OnPossibleCollision ); } - + // Go through all rigid bodies and move them according to their momentums for( int i = 0; i < updateList.size(); i++ ) { auto proto = updateList[i]; - proto->GetState( state ); - Float3 lM = state.GetLinearMomentum(); - - //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f); - - - if( abs(lM.x) < this->epsilon ) - { - state.linearMomentum.x = 0; - } - if( abs(lM.y) < this->epsilon ) - { - state.linearMomentum.y = 0; - } - if( abs(lM.z) < this->epsilon ) - { - state.linearMomentum.z = 0; - } - - proto->SetState( state ); switch( proto->Update(this->updateFrameLength) ) { case UpdateState_altered: + // Moves the container in the octree to the new rigid body position this->worldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(proto) ); proto->CallSubscription_Move(); case UpdateState_resting: diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index f1c196f7..68759398 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -111,6 +111,11 @@ SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) this->scene = nullptr; this->customTag = nullptr; this->ignoreGravity = desc.ignoreGravity; + + this->collisionRebound.previousSpatial.center = this->rigid.centerPos; + this->collisionRebound.previousSpatial.axis = this->rigid.axis; + this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; + this->collisionRebound.timeOfContact = 1.0f; } SimpleRigidBody::~SimpleRigidBody() {} diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index 0ecb8b6e..b27d3a78 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -98,7 +98,8 @@ SphericalRigidBody::State SphericalRigidBody::GetState() const this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic, this->rigid.GetMomentOfInertia(), this->rigid.boundingReach, this->rigid.centerPos, this->rigid.axis, - this->rigid.momentum_Linear, this->rigid.momentum_Angular ); + this->rigid.momentum_Linear, this->rigid.momentum_Angular, + this->gravityNormal ); } SphericalRigidBody::State & SphericalRigidBody::GetState( SphericalRigidBody::State &targetMem ) const @@ -107,7 +108,8 @@ SphericalRigidBody::State & SphericalRigidBody::GetState( SphericalRigidBody::St this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic, this->rigid.GetMomentOfInertia(), this->rigid.boundingReach, this->rigid.centerPos, this->rigid.axis, - this->rigid.momentum_Linear, this->rigid.momentum_Angular ); + this->rigid.momentum_Linear, this->rigid.momentum_Angular, + this->gravityNormal ); } void SphericalRigidBody::SetState( const SphericalRigidBody::State &state ) @@ -299,6 +301,11 @@ void SphericalRigidBody::Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster: this->rigid.Predict_LeapFrog( outDeltaPos.xyz, outDeltaAxis.xyz, actingLinearImpulse.xyz, actingAngularImpulse.xyz, deltaTime ); } +void SphericalRigidBody::SetScene( void *scene ) +{ + this->scene = (Octree*)scene; +} + void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_BeforeCollisionResponse functionPointer ) { if( functionPointer ) @@ -335,11 +342,6 @@ void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Move function } } -void SphericalRigidBody::SetScene( void *scene ) -{ - this->scene = (Octree*)scene; -} - void SphericalRigidBody::SetGravity( bool ignore ) { this->ignoreGravity = ignore; @@ -349,6 +351,7 @@ void SphericalRigidBody::SetGravity( bool ignore ) void SphericalRigidBody::SetGravityNormal( const Float3 &normalizedVector ) { this->gravityNormal = normalizedVector; + this->rigid.gravityNormal = Float4( this->gravityNormal, 0 ); } void SphericalRigidBody::SetCustomTag( void *ref ) diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index f7a5646e..ab0b1a18 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -56,7 +56,7 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G Float3 delta = AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); - Float3 newPos = ( updateFrameLength)*this->momentum_Linear; + Float3 newPos = updateFrameLength*this->momentum_Linear; this->centerPos += newPos; if(this->mass == 70) @@ -66,7 +66,7 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H - this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); + this->axis += updateFrameLength*this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular ); this->rotation = Rotation( this->axis ); // update momentums and clear impulse_Linear and impulse_Angular From 92447a6352362966dc09782a68399ef50e30e5ac Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Fri, 7 Feb 2014 16:01:43 +0100 Subject: [PATCH 15/35] Very cool stuff --- Code/Game/GameLogic/Level.cpp | 12 +++++++----- Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 9dc4a6f8..82ba5def 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -55,7 +55,7 @@ void Level::InitiateLevel(float radius) sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); sbDesc.ignoreGravity = true; sbDesc.radius = 600; - sbDesc.mass = 100; + sbDesc.mass = 70; sbDesc.frictionCoeff_Static = 0; sbDesc.frictionCoeff_Dynamic = 0; //sbDesc.rotation = @@ -75,8 +75,9 @@ void Level::InitiateLevel(float radius) sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,1); sbDesc_TestBox.ignoreGravity = false; - sbDesc_TestBox.mass = 20; - sbDesc_TestBox.size = Oyster::Math::Float4(0.5,0.5,0.5,0); + sbDesc_TestBox.mass = 15; + sbDesc_TestBox.size = Oyster::Math::Float4(1, 1, 1, 0); + sbDesc_TestBox.inertiaTensor.Cuboid(15, 1, 1, 1); ICustomBody* rigidBody_TestBox; @@ -131,8 +132,9 @@ void Level::InitiateLevel(float radius) API::SimpleBodyDescription sbDesc_Crystal; sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 605, 0, 1); sbDesc_Crystal.ignoreGravity = false; - sbDesc_Crystal.mass = 80; - sbDesc_Crystal.size = Oyster::Math::Float3(1,2,1); + sbDesc_Crystal.mass = 15; + sbDesc_Crystal.size = Oyster::Math::Float3(1, 2, 1); + sbDesc_Crystal.inertiaTensor.Cuboid(15, 1, 2, 1); ICustomBody* rigidBody_Crystal = API::Instance().CreateRigidBody(sbDesc_Crystal).Release(); rigidBody_Crystal->SetSubscription(Level::PhysicsOnMoveLevel); diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index a59c03b1..81a9ac06 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -362,7 +362,7 @@ void API_Impl::Update() } Float posLength = state.GetCenterPosition().GetLength(); - if( gravityImpulse != Float4::null && posLength - 601 > state.GetReach().GetLength() ) + if( gravityImpulse != Float4::null && posLength - 600 > state.GetReach().GetLength() ) { state.ApplyLinearImpulse( gravityImpulse.xyz ); state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); From fb9e33fc9b2a064830ec43458a65fcd270a9d0c8 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Sat, 8 Feb 2014 14:26:18 +0100 Subject: [PATCH 16/35] Fixed warnings --- Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 81a9ac06..7e14c01b 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -346,7 +346,7 @@ void API_Impl::Update() this->worldScene.Sample( Universe(), updateList ); // Change momentum for all rigid bodies - for( int i = 0; i < updateList.size(); i++ ) + for( unsigned int i = 0; i < updateList.size(); i++ ) { ICustomBody* proto = updateList[i]; // Step 1: Apply gravity to rigid body @@ -357,7 +357,7 @@ void API_Impl::Update() Float rSquared = deltaPosGrav.Dot( deltaPosGrav ); if( rSquared != 0.0 ) { - Float force = 9.82*10; + Float force = 9.82f*10.0f; gravityImpulse += (this->updateFrameLength*force)*deltaPosGrav.GetNormalized(); } @@ -374,7 +374,7 @@ void API_Impl::Update() } // Go through all rigid bodies and move them according to their momentums - for( int i = 0; i < updateList.size(); i++ ) + for( unsigned int i = 0; i < updateList.size(); i++ ) { auto proto = updateList[i]; From 99146430a4c8ab96672a788a8bb59e511c36d3eb Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Sun, 9 Feb 2014 21:24:09 +0100 Subject: [PATCH 17/35] Major overhaul --- Code/DanBias.sln | 298 + .../DanBiasGame/GameClientState/Camera.cpp | 2 +- .../DanBiasGame/GameClientState/GameState.cpp | 5 +- Code/Game/GameLogic/AttatchmentMassDriver.cpp | 10 +- Code/Game/GameLogic/CollisionManager.cpp | 4 +- Code/Game/GameLogic/Game.cpp | 12 +- Code/Game/GameLogic/Game_PlayerData.cpp | 24 +- Code/Game/GameLogic/Level.cpp | 78 +- Code/Game/GameLogic/Object.cpp | 98 +- Code/Game/GameLogic/Player.cpp | 20 +- Code/Game/GameLogic/StaticObject.cpp | 4 +- Code/GamePhysics/GamePhysics.vcxproj | 5 +- Code/GamePhysics/Implementation/Octree.cpp | 6 +- .../Implementation/PhysicsAPI_Impl.cpp | 642 +- .../Implementation/PhysicsAPI_Impl.h | 45 +- .../Implementation/SimpleRigidBody.cpp | 495 +- .../Implementation/SimpleRigidBody.h | 70 +- .../Implementation/SphericalRigidBody.cpp | 408 - .../Implementation/SphericalRigidBody.h | 87 - Code/GamePhysics/PhysicsAPI.h | 368 +- Code/GamePhysics/PhysicsStructs-Impl.h | 515 +- Code/GamePhysics/PhysicsStructs.h | 228 +- Code/OysterPhysics3D/RigidBody.cpp | 50 +- Code/OysterPhysics3D/RigidBody.h | 6 +- .../BulletCollision/BulletCollision.vcxproj | 487 + .../BulletCollision.vcxproj.user | 4 + .../BulletCollision/CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + Code/Physics/BulletCollision/INSTALL.vcxproj | 217 + .../BulletCollision/cmake_install.cmake | 29 + .../BulletDynamics/BulletDynamics.vcxproj | 343 + .../BulletDynamics.vcxproj.user | 4 + .../BulletDynamics/CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + Code/Physics/BulletDynamics/INSTALL.vcxproj | 217 + .../BulletDynamics/cmake_install.cmake | 29 + Code/Physics/Glut/EmptyGL/GL/egl_cpx.h | 13 + Code/Physics/Glut/EmptyGL/GL/egl_defs.h | 706 + Code/Physics/Glut/EmptyGL/GL/egl_logged.h | 20 + Code/Physics/Glut/EmptyGL/GL/egl_tokens.h | 459 + Code/Physics/Glut/EmptyGL/GL/egl_void.h | 422 + Code/Physics/Glut/EmptyGL/GL/gl.h | 47 + Code/Physics/Glut/EmptyGL/GL/glu.h | 23 + Code/Physics/Glut/EmptyGL/GL/glut.h | 60 + Code/Physics/Glut/GL/glew.h | 15507 ++++++++++++++++ Code/Physics/Glut/GL/glext.h | 3326 ++++ Code/Physics/Glut/GL/glut.h | 607 + Code/Physics/Glut/GL/glxew.h | 1587 ++ Code/Physics/Glut/GL/glxext.h | 546 + Code/Physics/Glut/GL/wglew.h | 1363 ++ Code/Physics/Glut/GL/wglext.h | 466 + Code/Physics/Glut/btGlutInclude.h | 43 + .../LinearMath/CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + Code/Physics/LinearMath/INSTALL.vcxproj | 217 + Code/Physics/LinearMath/LinearMath.vcxproj | 303 + .../LinearMath/LinearMath.vcxproj.user | 4 + Code/Physics/LinearMath/cmake_install.cmake | 29 + Code/Physics/src/Bullet-C-Api.h | 176 + .../BroadphaseCollision/btAxisSweep3.cpp | 37 + .../BroadphaseCollision/btAxisSweep3.h | 1051 ++ .../btBroadphaseInterface.h | 82 + .../BroadphaseCollision/btBroadphaseProxy.cpp | 17 + .../BroadphaseCollision/btBroadphaseProxy.h | 270 + .../btCollisionAlgorithm.cpp | 23 + .../btCollisionAlgorithm.h | 81 + .../BroadphaseCollision/btDbvt.cpp | 1295 ++ .../BroadphaseCollision/btDbvt.h | 1270 ++ .../BroadphaseCollision/btDbvtBroadphase.cpp | 796 + .../BroadphaseCollision/btDbvtBroadphase.h | 146 + .../BroadphaseCollision/btDispatcher.cpp | 22 + .../BroadphaseCollision/btDispatcher.h | 107 + .../btMultiSapBroadphase.cpp | 489 + .../btMultiSapBroadphase.h | 151 + .../btOverlappingPairCache.cpp | 633 + .../btOverlappingPairCache.h | 470 + .../btOverlappingPairCallback.h | 40 + .../BroadphaseCollision/btQuantizedBvh.cpp | 1393 ++ .../BroadphaseCollision/btQuantizedBvh.h | 581 + .../btSimpleBroadphase.cpp | 349 + .../BroadphaseCollision/btSimpleBroadphase.h | 171 + .../src/BulletCollision/CMakeLists.txt | 286 + .../SphereTriangleDetector.cpp | 200 + .../SphereTriangleDetector.h | 51 + .../btActivatingCollisionAlgorithm.cpp | 47 + .../btActivatingCollisionAlgorithm.h | 36 + .../btBox2dBox2dCollisionAlgorithm.cpp | 421 + .../btBox2dBox2dCollisionAlgorithm.h | 66 + .../btBoxBoxCollisionAlgorithm.cpp | 84 + .../btBoxBoxCollisionAlgorithm.h | 66 + .../CollisionDispatch/btBoxBoxDetector.cpp | 718 + .../CollisionDispatch/btBoxBoxDetector.h | 44 + .../btCollisionConfiguration.h | 46 + .../CollisionDispatch/btCollisionCreateFunc.h | 45 + .../btCollisionDispatcher.cpp | 314 + .../CollisionDispatch/btCollisionDispatcher.h | 171 + .../CollisionDispatch/btCollisionObject.cpp | 117 + .../CollisionDispatch/btCollisionObject.h | 565 + .../btCollisionObjectWrapper.h | 43 + .../CollisionDispatch/btCollisionWorld.cpp | 1552 ++ .../CollisionDispatch/btCollisionWorld.h | 526 + .../btCompoundCollisionAlgorithm.cpp | 375 + .../btCompoundCollisionAlgorithm.h | 99 + .../btCompoundCompoundCollisionAlgorithm.cpp | 421 + .../btCompoundCompoundCollisionAlgorithm.h | 90 + .../btConvex2dConvex2dAlgorithm.cpp | 246 + .../btConvex2dConvex2dAlgorithm.h | 95 + .../btConvexConcaveCollisionAlgorithm.cpp | 335 + .../btConvexConcaveCollisionAlgorithm.h | 121 + .../btConvexConvexAlgorithm.cpp | 783 + .../btConvexConvexAlgorithm.h | 108 + .../btConvexPlaneCollisionAlgorithm.cpp | 174 + .../btConvexPlaneCollisionAlgorithm.h | 84 + .../btDefaultCollisionConfiguration.cpp | 307 + .../btDefaultCollisionConfiguration.h | 127 + .../btEmptyCollisionAlgorithm.cpp | 34 + .../btEmptyCollisionAlgorithm.h | 54 + .../CollisionDispatch/btGhostObject.cpp | 171 + .../CollisionDispatch/btGhostObject.h | 175 + .../btHashedSimplePairCache.cpp | 278 + .../btHashedSimplePairCache.h | 174 + .../btInternalEdgeUtility.cpp | 842 + .../CollisionDispatch/btInternalEdgeUtility.h | 47 + .../CollisionDispatch/btManifoldResult.cpp | 154 + .../CollisionDispatch/btManifoldResult.h | 150 + .../btSimulationIslandManager.cpp | 450 + .../btSimulationIslandManager.h | 81 + .../btSphereBoxCollisionAlgorithm.cpp | 214 + .../btSphereBoxCollisionAlgorithm.h | 75 + .../btSphereSphereCollisionAlgorithm.cpp | 106 + .../btSphereSphereCollisionAlgorithm.h | 66 + .../btSphereTriangleCollisionAlgorithm.cpp | 84 + .../btSphereTriangleCollisionAlgorithm.h | 69 + .../CollisionDispatch/btUnionFind.cpp | 82 + .../CollisionDispatch/btUnionFind.h | 129 + .../CollisionShapes/btBox2dShape.cpp | 42 + .../CollisionShapes/btBox2dShape.h | 371 + .../CollisionShapes/btBoxShape.cpp | 51 + .../CollisionShapes/btBoxShape.h | 314 + .../btBvhTriangleMeshShape.cpp | 466 + .../CollisionShapes/btBvhTriangleMeshShape.h | 145 + .../CollisionShapes/btCapsuleShape.cpp | 171 + .../CollisionShapes/btCapsuleShape.h | 184 + .../CollisionShapes/btCollisionMargin.h | 27 + .../CollisionShapes/btCollisionShape.cpp | 119 + .../CollisionShapes/btCollisionShape.h | 159 + .../CollisionShapes/btCompoundShape.cpp | 356 + .../CollisionShapes/btCompoundShape.h | 212 + .../CollisionShapes/btConcaveShape.cpp | 27 + .../CollisionShapes/btConcaveShape.h | 62 + .../CollisionShapes/btConeShape.cpp | 147 + .../CollisionShapes/btConeShape.h | 171 + .../CollisionShapes/btConvex2dShape.cpp | 92 + .../CollisionShapes/btConvex2dShape.h | 82 + .../CollisionShapes/btConvexHullShape.cpp | 250 + .../CollisionShapes/btConvexHullShape.h | 122 + .../CollisionShapes/btConvexInternalShape.cpp | 151 + .../CollisionShapes/btConvexInternalShape.h | 224 + .../btConvexPointCloudShape.cpp | 139 + .../CollisionShapes/btConvexPointCloudShape.h | 105 + .../CollisionShapes/btConvexPolyhedron.cpp | 302 + .../CollisionShapes/btConvexPolyhedron.h | 65 + .../CollisionShapes/btConvexShape.cpp | 455 + .../CollisionShapes/btConvexShape.h | 84 + .../btConvexTriangleMeshShape.cpp | 315 + .../btConvexTriangleMeshShape.h | 77 + .../CollisionShapes/btCylinderShape.cpp | 281 + .../CollisionShapes/btCylinderShape.h | 213 + .../CollisionShapes/btEmptyShape.cpp | 50 + .../CollisionShapes/btEmptyShape.h | 72 + .../btHeightfieldTerrainShape.cpp | 410 + .../btHeightfieldTerrainShape.h | 167 + .../CollisionShapes/btMaterial.h | 35 + .../CollisionShapes/btMinkowskiSumShape.cpp | 60 + .../CollisionShapes/btMinkowskiSumShape.h | 62 + .../CollisionShapes/btMultiSphereShape.cpp | 182 + .../CollisionShapes/btMultiSphereShape.h | 101 + .../btMultimaterialTriangleMeshShape.cpp | 45 + .../btMultimaterialTriangleMeshShape.h | 120 + .../CollisionShapes/btOptimizedBvh.cpp | 391 + .../CollisionShapes/btOptimizedBvh.h | 65 + .../btPolyhedralConvexShape.cpp | 500 + .../CollisionShapes/btPolyhedralConvexShape.h | 116 + .../btScaledBvhTriangleMeshShape.cpp | 121 + .../btScaledBvhTriangleMeshShape.h | 95 + .../CollisionShapes/btShapeHull.cpp | 170 + .../CollisionShapes/btShapeHull.h | 61 + .../CollisionShapes/btSphereShape.cpp | 71 + .../CollisionShapes/btSphereShape.h | 73 + .../CollisionShapes/btStaticPlaneShape.cpp | 107 + .../CollisionShapes/btStaticPlaneShape.h | 105 + .../btStridingMeshInterface.cpp | 381 + .../CollisionShapes/btStridingMeshInterface.h | 164 + .../CollisionShapes/btTetrahedronShape.cpp | 218 + .../CollisionShapes/btTetrahedronShape.h | 76 + .../CollisionShapes/btTriangleBuffer.cpp | 35 + .../CollisionShapes/btTriangleBuffer.h | 69 + .../CollisionShapes/btTriangleCallback.cpp | 28 + .../CollisionShapes/btTriangleCallback.h | 42 + .../btTriangleIndexVertexArray.cpp | 95 + .../btTriangleIndexVertexArray.h | 133 + .../btTriangleIndexVertexMaterialArray.cpp | 86 + .../btTriangleIndexVertexMaterialArray.h | 84 + .../CollisionShapes/btTriangleInfoMap.h | 241 + .../CollisionShapes/btTriangleMesh.cpp | 162 + .../CollisionShapes/btTriangleMesh.h | 69 + .../CollisionShapes/btTriangleMeshShape.cpp | 207 + .../CollisionShapes/btTriangleMeshShape.h | 90 + .../CollisionShapes/btTriangleShape.h | 184 + .../CollisionShapes/btUniformScalingShape.cpp | 160 + .../CollisionShapes/btUniformScalingShape.h | 89 + Code/Physics/src/BulletCollision/Doxyfile | 746 + .../BulletCollision/Gimpact/btBoxCollision.h | 645 + .../BulletCollision/Gimpact/btClipPolygon.h | 182 + .../Gimpact/btCompoundFromGimpact.h | 93 + .../Gimpact/btContactProcessing.cpp | 181 + .../Gimpact/btContactProcessing.h | 145 + .../BulletCollision/Gimpact/btGImpactBvh.cpp | 498 + .../BulletCollision/Gimpact/btGImpactBvh.h | 396 + .../Gimpact/btGImpactCollisionAlgorithm.cpp | 932 + .../Gimpact/btGImpactCollisionAlgorithm.h | 310 + .../Gimpact/btGImpactMassUtil.h | 60 + .../Gimpact/btGImpactQuantizedBvh.cpp | 528 + .../Gimpact/btGImpactQuantizedBvh.h | 372 + .../Gimpact/btGImpactShape.cpp | 238 + .../BulletCollision/Gimpact/btGImpactShape.h | 1184 ++ .../Gimpact/btGenericPoolAllocator.cpp | 283 + .../Gimpact/btGenericPoolAllocator.h | 163 + .../Gimpact/btGeometryOperations.h | 212 + .../BulletCollision/Gimpact/btQuantization.h | 88 + .../Gimpact/btTriangleShapeEx.cpp | 218 + .../Gimpact/btTriangleShapeEx.h | 180 + .../src/BulletCollision/Gimpact/gim_array.h | 324 + .../Gimpact/gim_basic_geometry_operations.h | 543 + .../src/BulletCollision/Gimpact/gim_bitset.h | 123 + .../Gimpact/gim_box_collision.h | 588 + .../BulletCollision/Gimpact/gim_box_set.cpp | 182 + .../src/BulletCollision/Gimpact/gim_box_set.h | 674 + .../Gimpact/gim_clip_polygon.h | 210 + .../BulletCollision/Gimpact/gim_contact.cpp | 146 + .../src/BulletCollision/Gimpact/gim_contact.h | 164 + .../BulletCollision/Gimpact/gim_geom_types.h | 97 + .../BulletCollision/Gimpact/gim_geometry.h | 42 + .../BulletCollision/Gimpact/gim_hash_table.h | 902 + .../BulletCollision/Gimpact/gim_linear_math.h | 1573 ++ .../src/BulletCollision/Gimpact/gim_math.h | 157 + .../BulletCollision/Gimpact/gim_memory.cpp | 135 + .../src/BulletCollision/Gimpact/gim_memory.h | 190 + .../BulletCollision/Gimpact/gim_radixsort.h | 406 + .../Gimpact/gim_tri_collision.cpp | 640 + .../Gimpact/gim_tri_collision.h | 379 + .../btContinuousConvexCollision.cpp | 242 + .../btContinuousConvexCollision.h | 59 + .../NarrowPhaseCollision/btConvexCast.cpp | 20 + .../NarrowPhaseCollision/btConvexCast.h | 73 + .../btConvexPenetrationDepthSolver.h | 40 + .../btDiscreteCollisionDetectorInterface.h | 88 + .../NarrowPhaseCollision/btGjkConvexCast.cpp | 176 + .../NarrowPhaseCollision/btGjkConvexCast.h | 50 + .../NarrowPhaseCollision/btGjkEpa2.cpp | 1031 + .../NarrowPhaseCollision/btGjkEpa2.h | 75 + .../btGjkEpaPenetrationDepthSolver.cpp | 66 + .../btGjkEpaPenetrationDepthSolver.h | 43 + .../btGjkPairDetector.cpp | 480 + .../NarrowPhaseCollision/btGjkPairDetector.h | 103 + .../NarrowPhaseCollision/btManifoldPoint.h | 156 + .../btMinkowskiPenetrationDepthSolver.cpp | 361 + .../btMinkowskiPenetrationDepthSolver.h | 40 + .../btPersistentManifold.cpp | 305 + .../btPersistentManifold.h | 240 + .../NarrowPhaseCollision/btPointCollector.h | 64 + .../btPolyhedralContactClipping.cpp | 570 + .../btPolyhedralContactClipping.h | 46 + .../btRaycastCallback.cpp | 178 + .../NarrowPhaseCollision/btRaycastCallback.h | 72 + .../btSimplexSolverInterface.h | 63 + .../btSubSimplexConvexCast.cpp | 160 + .../btSubSimplexConvexCast.h | 50 + .../btVoronoiSimplexSolver.cpp | 609 + .../btVoronoiSimplexSolver.h | 181 + Code/Physics/src/BulletCollision/premake4.lua | 11 + .../Physics/src/BulletDynamics/CMakeLists.txt | 153 + .../btCharacterControllerInterface.h | 47 + .../btKinematicCharacterController.cpp | 770 + .../btKinematicCharacterController.h | 170 + .../btConeTwistConstraint.cpp | 1141 ++ .../ConstraintSolver/btConeTwistConstraint.h | 381 + .../ConstraintSolver/btConstraintSolver.h | 64 + .../ConstraintSolver/btContactConstraint.cpp | 178 + .../ConstraintSolver/btContactConstraint.h | 71 + .../ConstraintSolver/btContactSolverInfo.h | 159 + .../ConstraintSolver/btFixedConstraint.cpp | 129 + .../ConstraintSolver/btFixedConstraint.h | 49 + .../ConstraintSolver/btGearConstraint.cpp | 54 + .../ConstraintSolver/btGearConstraint.h | 152 + .../btGeneric6DofConstraint.cpp | 1063 ++ .../btGeneric6DofConstraint.h | 640 + .../btGeneric6DofSpringConstraint.cpp | 185 + .../btGeneric6DofSpringConstraint.h | 121 + .../ConstraintSolver/btHinge2Constraint.cpp | 66 + .../ConstraintSolver/btHinge2Constraint.h | 60 + .../ConstraintSolver/btHingeConstraint.cpp | 1046 ++ .../ConstraintSolver/btHingeConstraint.h | 412 + .../ConstraintSolver/btJacobianEntry.h | 155 + .../btPoint2PointConstraint.cpp | 229 + .../btPoint2PointConstraint.h | 175 + .../btSequentialImpulseConstraintSolver.cpp | 1739 ++ .../btSequentialImpulseConstraintSolver.h | 148 + .../ConstraintSolver/btSliderConstraint.cpp | 864 + .../ConstraintSolver/btSliderConstraint.h | 361 + .../btSolve2LinearConstraint.cpp | 255 + .../btSolve2LinearConstraint.h | 107 + .../ConstraintSolver/btSolverBody.h | 306 + .../ConstraintSolver/btSolverConstraint.h | 80 + .../ConstraintSolver/btTypedConstraint.cpp | 222 + .../ConstraintSolver/btTypedConstraint.h | 544 + .../btUniversalConstraint.cpp | 87 + .../ConstraintSolver/btUniversalConstraint.h | 65 + .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 405 + .../Dynamics/btActionInterface.h | 46 + .../Dynamics/btDiscreteDynamicsWorld.cpp | 1463 ++ .../Dynamics/btDiscreteDynamicsWorld.h | 234 + .../BulletDynamics/Dynamics/btDynamicsWorld.h | 167 + .../BulletDynamics/Dynamics/btRigidBody.cpp | 400 + .../src/BulletDynamics/Dynamics/btRigidBody.h | 604 + .../Dynamics/btSimpleDynamicsWorld.cpp | 280 + .../Dynamics/btSimpleDynamicsWorld.h | 89 + .../Featherstone/btMultiBody.cpp | 1009 + .../BulletDynamics/Featherstone/btMultiBody.h | 466 + .../Featherstone/btMultiBodyConstraint.cpp | 527 + .../Featherstone/btMultiBodyConstraint.h | 166 + .../btMultiBodyConstraintSolver.cpp | 795 + .../btMultiBodyConstraintSolver.h | 85 + .../Featherstone/btMultiBodyDynamicsWorld.cpp | 578 + .../Featherstone/btMultiBodyDynamicsWorld.h | 56 + .../btMultiBodyJointLimitConstraint.cpp | 133 + .../btMultiBodyJointLimitConstraint.h | 44 + .../Featherstone/btMultiBodyJointMotor.cpp | 89 + .../Featherstone/btMultiBodyJointMotor.h | 47 + .../Featherstone/btMultiBodyLink.h | 110 + .../Featherstone/btMultiBodyLinkCollider.h | 92 + .../Featherstone/btMultiBodyPoint2Point.cpp | 143 + .../Featherstone/btMultiBodyPoint2Point.h | 60 + .../btMultiBodySolverConstraint.h | 82 + .../MLCPSolvers/btDantzigLCP.cpp | 2079 +++ .../BulletDynamics/MLCPSolvers/btDantzigLCP.h | 77 + .../MLCPSolvers/btDantzigSolver.h | 112 + .../MLCPSolvers/btMLCPSolver.cpp | 626 + .../BulletDynamics/MLCPSolvers/btMLCPSolver.h | 81 + .../MLCPSolvers/btMLCPSolverInterface.h | 33 + .../BulletDynamics/MLCPSolvers/btPATHSolver.h | 151 + .../MLCPSolvers/btSolveProjectedGaussSeidel.h | 80 + .../Vehicle/btRaycastVehicle.cpp | 771 + .../BulletDynamics/Vehicle/btRaycastVehicle.h | 236 + .../Vehicle/btVehicleRaycaster.h | 35 + .../BulletDynamics/Vehicle/btWheelInfo.cpp | 56 + .../src/BulletDynamics/Vehicle/btWheelInfo.h | 119 + Code/Physics/src/BulletDynamics/premake4.lua | 11 + .../src/BulletMultiThreaded/CMakeLists.txt | 126 + .../GpuSoftBodySolvers/CMakeLists.txt | 13 + .../GpuSoftBodySolvers/DX11/CMakeLists.txt | 86 + .../DX11/HLSL/ApplyForces.hlsl | 95 + .../DX11/HLSL/ComputeBounds.hlsl | 83 + .../DX11/HLSL/Integrate.hlsl | 41 + .../DX11/HLSL/OutputToVertexArray.hlsl | 63 + .../DX11/HLSL/PrepareLinks.hlsl | 44 + .../DX11/HLSL/SolvePositions.hlsl | 55 + .../DX11/HLSL/SolvePositionsSIMDBatched.hlsl | 147 + .../DX11/HLSL/UpdateConstants.hlsl | 48 + .../DX11/HLSL/UpdateNodes.hlsl | 49 + .../DX11/HLSL/UpdateNormals.hlsl | 98 + .../DX11/HLSL/UpdatePositions.hlsl | 44 + .../HLSL/UpdatePositionsFromVelocities.hlsl | 35 + .../DX11/HLSL/VSolveLinks.hlsl | 55 + .../solveCollisionsAndUpdateVelocities.hlsl | 170 + ...lisionsAndUpdateVelocitiesSIMDBatched.hlsl | 191 + .../DX11/btSoftBodySolverBuffer_DX11.h | 323 + .../DX11/btSoftBodySolverLinkData_DX11.h | 103 + .../btSoftBodySolverLinkData_DX11SIMDAware.h | 173 + .../DX11/btSoftBodySolverTriangleData_DX11.h | 96 + .../DX11/btSoftBodySolverVertexBuffer_DX11.h | 107 + .../DX11/btSoftBodySolverVertexData_DX11.h | 63 + .../DX11/btSoftBodySolver_DX11.cpp | 2236 +++ .../DX11/btSoftBodySolver_DX11.h | 691 + .../DX11/btSoftBodySolver_DX11SIMDAware.cpp | 1051 ++ .../DX11/btSoftBodySolver_DX11SIMDAware.h | 81 + .../GpuSoftBodySolvers/DX11/premake4.lua | 23 + .../OpenCL/AMD/CMakeLists.txt | 65 + .../OpenCL/AMD/premake4.lua | 27 + .../OpenCL/Apple/CMakeLists.txt | 80 + .../GpuSoftBodySolvers/OpenCL/CMakeLists.txt | 17 + .../OpenCL/Intel/CMakeLists.txt | 85 + .../OpenCL/Intel/premake4.lua | 27 + .../OpenCL/MiniCL/CMakeLists.txt | 78 + .../OpenCL/MiniCL/MiniCLTaskWrap.cpp | 249 + .../OpenCL/NVidia/CMakeLists.txt | 84 + .../OpenCL/NVidia/premake4.lua | 27 + .../OpenCL/OpenCLC10/ApplyForces.cl | 102 + .../OpenCL/OpenCLC10/ComputeBounds.cl | 82 + .../OpenCL/OpenCLC10/Integrate.cl | 35 + .../OpenCL/OpenCLC10/OutputToVertexArray.cl | 46 + .../OpenCL/OpenCLC10/PrepareLinks.cl | 38 + .../SolveCollisionsAndUpdateVelocities.cl | 204 + ...ollisionsAndUpdateVelocitiesSIMDBatched.cl | 242 + .../OpenCL/OpenCLC10/SolvePositions.cl | 57 + .../OpenCLC10/SolvePositionsSIMDBatched.cl | 130 + .../OpenCL/OpenCLC10/UpdateConstants.cl | 44 + .../OpenCLC10/UpdateFixedVertexPositions.cl | 25 + .../OpenCL/OpenCLC10/UpdateNodes.cl | 39 + .../OpenCL/OpenCLC10/UpdateNormals.cl | 102 + .../OpenCL/OpenCLC10/UpdatePositions.cl | 34 + .../UpdatePositionsFromVelocities.cl | 28 + .../OpenCL/OpenCLC10/VSolveLinks.cl | 45 + .../OpenCL/btSoftBodySolverBuffer_OpenCL.h | 209 + .../OpenCL/btSoftBodySolverLinkData_OpenCL.h | 99 + ...btSoftBodySolverLinkData_OpenCLSIMDAware.h | 169 + .../OpenCL/btSoftBodySolverOutputCLtoGL.cpp | 126 + .../OpenCL/btSoftBodySolverOutputCLtoGL.h | 62 + .../btSoftBodySolverTriangleData_OpenCL.h | 84 + .../btSoftBodySolverVertexBuffer_OpenGL.h | 166 + .../btSoftBodySolverVertexData_OpenCL.h | 52 + .../OpenCL/btSoftBodySolver_OpenCL.cpp | 1820 ++ .../OpenCL/btSoftBodySolver_OpenCL.h | 527 + .../btSoftBodySolver_OpenCLSIMDAware.cpp | 1101 ++ .../OpenCL/btSoftBodySolver_OpenCLSIMDAware.h | 81 + .../Shared/btSoftBodySolverData.h | 748 + .../src/BulletMultiThreaded/HeapManager.h | 117 + .../BulletMultiThreaded/PlatformDefinitions.h | 103 + .../PosixThreadSupport.cpp | 409 + .../BulletMultiThreaded/PosixThreadSupport.h | 147 + .../src/BulletMultiThreaded/PpuAddressSpace.h | 37 + .../SequentialThreadSupport.cpp | 181 + .../SequentialThreadSupport.h | 100 + .../SpuCollisionObjectWrapper.cpp | 48 + .../SpuCollisionObjectWrapper.h | 40 + .../SpuCollisionTaskProcess.cpp | 317 + .../SpuCollisionTaskProcess.h | 163 + .../SpuContactManifoldCollisionAlgorithm.cpp | 69 + .../SpuContactManifoldCollisionAlgorithm.h | 121 + .../src/BulletMultiThreaded/SpuDoubleBuffer.h | 126 + .../src/BulletMultiThreaded/SpuFakeDma.cpp | 215 + .../src/BulletMultiThreaded/SpuFakeDma.h | 135 + .../SpuGatheringCollisionDispatcher.cpp | 283 + .../SpuGatheringCollisionDispatcher.h | 72 + .../BulletMultiThreaded/SpuLibspe2Support.cpp | 257 + .../BulletMultiThreaded/SpuLibspe2Support.h | 180 + .../SpuNarrowPhaseCollisionTask/Box.h | 167 + .../SpuCollisionShapes.cpp | 302 + .../SpuCollisionShapes.h | 128 + .../SpuContactResult.cpp | 248 + .../SpuContactResult.h | 106 + .../SpuConvexPenetrationDepthSolver.h | 50 + .../SpuGatheringCollisionTask.cpp | 1432 ++ .../SpuGatheringCollisionTask.h | 140 + .../SpuLocalSupport.h | 19 + .../SpuMinkowskiPenetrationDepthSolver.cpp | 347 + .../SpuMinkowskiPenetrationDepthSolver.h | 47 + .../SpuPreferredPenetrationDirections.h | 70 + .../boxBoxDistance.cpp | 1160 ++ .../boxBoxDistance.h | 65 + .../SpuNarrowPhaseCollisionTask/readme.txt | 1 + .../SpuSampleTask/SpuSampleTask.cpp | 214 + .../SpuSampleTask/SpuSampleTask.h | 54 + .../SpuSampleTask/readme.txt | 1 + .../SpuSampleTaskProcess.cpp | 222 + .../SpuSampleTaskProcess.h | 153 + .../Physics/src/BulletMultiThreaded/SpuSync.h | 149 + .../src/BulletMultiThreaded/TrbDynBody.h | 79 + .../src/BulletMultiThreaded/TrbStateVec.h | 339 + .../Win32ThreadSupport.cpp | 458 + .../BulletMultiThreaded/Win32ThreadSupport.h | 141 + .../btGpu3DGridBroadphase.cpp | 590 + .../btGpu3DGridBroadphase.h | 140 + .../btGpu3DGridBroadphaseSharedCode.h | 430 + .../btGpu3DGridBroadphaseSharedDefs.h | 61 + .../btGpu3DGridBroadphaseSharedTypes.h | 67 + .../src/BulletMultiThreaded/btGpuDefines.h | 211 + .../btGpuUtilsSharedCode.h | 55 + .../btGpuUtilsSharedDefs.h | 52 + .../btParallelConstraintSolver.cpp | 1552 ++ .../btParallelConstraintSolver.h | 288 + .../btThreadSupportInterface.cpp | 22 + .../btThreadSupportInterface.h | 89 + .../BulletMultiThreaded/vectormath2bullet.h | 73 + .../Physics/src/BulletSoftBody/CMakeLists.txt | 67 + .../btDefaultSoftBodySolver.cpp | 151 + .../BulletSoftBody/btDefaultSoftBodySolver.h | 63 + .../Physics/src/BulletSoftBody/btSoftBody.cpp | 3655 ++++ Code/Physics/src/BulletSoftBody/btSoftBody.h | 1000 + .../btSoftBodyConcaveCollisionAlgorithm.cpp | 357 + .../btSoftBodyConcaveCollisionAlgorithm.h | 155 + .../src/BulletSoftBody/btSoftBodyData.h | 217 + .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 1055 ++ .../src/BulletSoftBody/btSoftBodyHelpers.h | 143 + .../src/BulletSoftBody/btSoftBodyInternals.h | 908 + ...oftBodyRigidBodyCollisionConfiguration.cpp | 134 + ...tSoftBodyRigidBodyCollisionConfiguration.h | 48 + .../btSoftBodySolverVertexBuffer.h | 165 + .../src/BulletSoftBody/btSoftBodySolvers.h | 154 + .../btSoftRigidCollisionAlgorithm.cpp | 86 + .../btSoftRigidCollisionAlgorithm.h | 75 + .../btSoftRigidDynamicsWorld.cpp | 367 + .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 107 + .../btSoftSoftCollisionAlgorithm.cpp | 48 + .../btSoftSoftCollisionAlgorithm.h | 69 + Code/Physics/src/BulletSoftBody/btSparseSDF.h | 319 + Code/Physics/src/BulletSoftBody/premake4.lua | 11 + Code/Physics/src/CMakeLists.txt | 32 + Code/Physics/src/LinearMath/CMakeLists.txt | 72 + Code/Physics/src/LinearMath/btAabbUtil2.h | 232 + .../src/LinearMath/btAlignedAllocator.cpp | 181 + .../src/LinearMath/btAlignedAllocator.h | 107 + .../src/LinearMath/btAlignedObjectArray.h | 511 + Code/Physics/src/LinearMath/btConvexHull.cpp | 1167 ++ Code/Physics/src/LinearMath/btConvexHull.h | 241 + .../src/LinearMath/btConvexHullComputer.cpp | 2755 +++ .../src/LinearMath/btConvexHullComputer.h | 103 + .../src/LinearMath/btDefaultMotionState.h | 42 + .../Physics/src/LinearMath/btGeometryUtil.cpp | 185 + Code/Physics/src/LinearMath/btGeometryUtil.h | 42 + .../src/LinearMath/btGrahamScan2dConvexHull.h | 117 + Code/Physics/src/LinearMath/btHashMap.h | 450 + Code/Physics/src/LinearMath/btIDebugDraw.h | 445 + Code/Physics/src/LinearMath/btList.h | 73 + Code/Physics/src/LinearMath/btMatrix3x3.h | 1367 ++ Code/Physics/src/LinearMath/btMatrixX.h | 504 + Code/Physics/src/LinearMath/btMinMax.h | 71 + Code/Physics/src/LinearMath/btMotionState.h | 40 + .../src/LinearMath/btPolarDecomposition.cpp | 99 + .../src/LinearMath/btPolarDecomposition.h | 73 + Code/Physics/src/LinearMath/btPoolAllocator.h | 121 + Code/Physics/src/LinearMath/btQuadWord.h | 244 + Code/Physics/src/LinearMath/btQuaternion.h | 909 + Code/Physics/src/LinearMath/btQuickprof.cpp | 566 + Code/Physics/src/LinearMath/btQuickprof.h | 203 + Code/Physics/src/LinearMath/btRandom.h | 42 + Code/Physics/src/LinearMath/btScalar.h | 731 + Code/Physics/src/LinearMath/btSerializer.cpp | 991 + Code/Physics/src/LinearMath/btSerializer.h | 639 + Code/Physics/src/LinearMath/btStackAlloc.h | 116 + Code/Physics/src/LinearMath/btTransform.h | 305 + Code/Physics/src/LinearMath/btTransformUtil.h | 228 + Code/Physics/src/LinearMath/btVector3.cpp | 1664 ++ Code/Physics/src/LinearMath/btVector3.h | 1352 ++ Code/Physics/src/LinearMath/premake4.lua | 11 + Code/Physics/src/Makefile.am | 612 + Code/Physics/src/MiniCL/CMakeLists.txt | 69 + Code/Physics/src/MiniCL/MiniCL.cpp | 788 + .../src/MiniCL/MiniCLTask/MiniCLTask.cpp | 74 + .../src/MiniCL/MiniCLTask/MiniCLTask.h | 62 + .../src/MiniCL/MiniCLTaskScheduler.cpp | 519 + Code/Physics/src/MiniCL/MiniCLTaskScheduler.h | 194 + Code/Physics/src/MiniCL/cl.h | 867 + Code/Physics/src/MiniCL/cl_MiniCL_Defs.h | 439 + Code/Physics/src/MiniCL/cl_gl.h | 113 + Code/Physics/src/MiniCL/cl_platform.h | 254 + Code/Physics/src/btBulletCollisionCommon.h | 68 + Code/Physics/src/btBulletDynamicsCommon.h | 51 + Code/Physics/src/vectormath/neon/boolInVec.h | 226 + Code/Physics/src/vectormath/neon/floatInVec.h | 344 + Code/Physics/src/vectormath/neon/mat_aos.h | 1631 ++ Code/Physics/src/vectormath/neon/quat_aos.h | 413 + Code/Physics/src/vectormath/neon/vec_aos.h | 1427 ++ .../src/vectormath/neon/vectormath_aos.h | 1890 ++ .../Physics/src/vectormath/scalar/boolInVec.h | 225 + .../src/vectormath/scalar/floatInVec.h | 343 + Code/Physics/src/vectormath/scalar/mat_aos.h | 1630 ++ Code/Physics/src/vectormath/scalar/quat_aos.h | 433 + Code/Physics/src/vectormath/scalar/vec_aos.h | 1426 ++ .../src/vectormath/scalar/vectormath_aos.h | 1872 ++ Code/Physics/src/vectormath/sse/boolInVec.h | 247 + Code/Physics/src/vectormath/sse/floatInVec.h | 340 + Code/Physics/src/vectormath/sse/mat_aos.h | 2190 +++ Code/Physics/src/vectormath/sse/quat_aos.h | 579 + Code/Physics/src/vectormath/sse/vec_aos.h | 1455 ++ Code/Physics/src/vectormath/sse/vecidx_aos.h | 80 + .../src/vectormath/sse/vectormath_aos.h | 2547 +++ Code/Physics/src/vectormath/vmInclude.h | 31 + 578 files changed, 183534 insertions(+), 2812 deletions(-) create mode 100644 Code/Physics/BulletCollision/BulletCollision.vcxproj create mode 100644 Code/Physics/BulletCollision/BulletCollision.vcxproj.user create mode 100644 Code/Physics/BulletCollision/CMakeFiles/generate.stamp create mode 100644 Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/BulletCollision/INSTALL.vcxproj create mode 100644 Code/Physics/BulletCollision/cmake_install.cmake create mode 100644 Code/Physics/BulletDynamics/BulletDynamics.vcxproj create mode 100644 Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user create mode 100644 Code/Physics/BulletDynamics/CMakeFiles/generate.stamp create mode 100644 Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/BulletDynamics/INSTALL.vcxproj create mode 100644 Code/Physics/BulletDynamics/cmake_install.cmake create mode 100644 Code/Physics/Glut/EmptyGL/GL/egl_cpx.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/egl_defs.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/egl_logged.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/egl_tokens.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/egl_void.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/gl.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/glu.h create mode 100644 Code/Physics/Glut/EmptyGL/GL/glut.h create mode 100644 Code/Physics/Glut/GL/glew.h create mode 100644 Code/Physics/Glut/GL/glext.h create mode 100644 Code/Physics/Glut/GL/glut.h create mode 100644 Code/Physics/Glut/GL/glxew.h create mode 100644 Code/Physics/Glut/GL/glxext.h create mode 100644 Code/Physics/Glut/GL/wglew.h create mode 100644 Code/Physics/Glut/GL/wglext.h create mode 100644 Code/Physics/Glut/btGlutInclude.h create mode 100644 Code/Physics/LinearMath/CMakeFiles/generate.stamp create mode 100644 Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/LinearMath/INSTALL.vcxproj create mode 100644 Code/Physics/LinearMath/LinearMath.vcxproj create mode 100644 Code/Physics/LinearMath/LinearMath.vcxproj.user create mode 100644 Code/Physics/LinearMath/cmake_install.cmake create mode 100644 Code/Physics/src/Bullet-C-Api.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp create mode 100644 Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h create mode 100644 Code/Physics/src/BulletCollision/CMakeLists.txt create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCollisionMargin.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMaterial.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleBuffer.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMesh.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btTriangleShape.h create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp create mode 100644 Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.h create mode 100644 Code/Physics/src/BulletCollision/Doxyfile create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btBoxCollision.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btClipPolygon.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btCompoundFromGimpact.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactMassUtil.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btGeometryOperations.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btQuantization.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_array.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_bitset.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_box_collision.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_box_set.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_box_set.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_clip_polygon.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_contact.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_contact.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_geom_types.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_geometry.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_hash_table.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_linear_math.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_math.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_memory.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_memory.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_radixsort.h create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.cpp create mode 100644 Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp create mode 100644 Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h create mode 100644 Code/Physics/src/BulletCollision/premake4.lua create mode 100644 Code/Physics/src/BulletDynamics/CMakeLists.txt create mode 100644 Code/Physics/src/BulletDynamics/Character/btCharacterControllerInterface.h create mode 100644 Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.cpp create mode 100644 Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverBody.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/Bullet-C-API.cpp create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btActionInterface.h create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btDynamicsWorld.h create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.cpp create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.h create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp create mode 100644 Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyLink.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h create mode 100644 Code/Physics/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btPATHSolver.h create mode 100644 Code/Physics/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h create mode 100644 Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp create mode 100644 Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.h create mode 100644 Code/Physics/src/BulletDynamics/Vehicle/btVehicleRaycaster.h create mode 100644 Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.cpp create mode 100644 Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.h create mode 100644 Code/Physics/src/BulletDynamics/premake4.lua create mode 100644 Code/Physics/src/BulletMultiThreaded/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h create mode 100644 Code/Physics/src/BulletMultiThreaded/HeapManager.h create mode 100644 Code/Physics/src/BulletMultiThreaded/PlatformDefinitions.h create mode 100644 Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.h create mode 100644 Code/Physics/src/BulletMultiThreaded/PpuAddressSpace.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuDoubleBuffer.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuFakeDma.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuFakeDma.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuSampleTask/readme.txt create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.h create mode 100644 Code/Physics/src/BulletMultiThreaded/SpuSync.h create mode 100644 Code/Physics/src/BulletMultiThreaded/TrbDynBody.h create mode 100644 Code/Physics/src/BulletMultiThreaded/TrbStateVec.h create mode 100644 Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpuDefines.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpuUtilsSharedCode.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.h create mode 100644 Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.cpp create mode 100644 Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.h create mode 100644 Code/Physics/src/BulletMultiThreaded/vectormath2bullet.h create mode 100644 Code/Physics/src/BulletSoftBody/CMakeLists.txt create mode 100644 Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBody.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBody.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyData.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyInternals.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftBodySolvers.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.h create mode 100644 Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp create mode 100644 Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h create mode 100644 Code/Physics/src/BulletSoftBody/btSparseSDF.h create mode 100644 Code/Physics/src/BulletSoftBody/premake4.lua create mode 100644 Code/Physics/src/CMakeLists.txt create mode 100644 Code/Physics/src/LinearMath/CMakeLists.txt create mode 100644 Code/Physics/src/LinearMath/btAabbUtil2.h create mode 100644 Code/Physics/src/LinearMath/btAlignedAllocator.cpp create mode 100644 Code/Physics/src/LinearMath/btAlignedAllocator.h create mode 100644 Code/Physics/src/LinearMath/btAlignedObjectArray.h create mode 100644 Code/Physics/src/LinearMath/btConvexHull.cpp create mode 100644 Code/Physics/src/LinearMath/btConvexHull.h create mode 100644 Code/Physics/src/LinearMath/btConvexHullComputer.cpp create mode 100644 Code/Physics/src/LinearMath/btConvexHullComputer.h create mode 100644 Code/Physics/src/LinearMath/btDefaultMotionState.h create mode 100644 Code/Physics/src/LinearMath/btGeometryUtil.cpp create mode 100644 Code/Physics/src/LinearMath/btGeometryUtil.h create mode 100644 Code/Physics/src/LinearMath/btGrahamScan2dConvexHull.h create mode 100644 Code/Physics/src/LinearMath/btHashMap.h create mode 100644 Code/Physics/src/LinearMath/btIDebugDraw.h create mode 100644 Code/Physics/src/LinearMath/btList.h create mode 100644 Code/Physics/src/LinearMath/btMatrix3x3.h create mode 100644 Code/Physics/src/LinearMath/btMatrixX.h create mode 100644 Code/Physics/src/LinearMath/btMinMax.h create mode 100644 Code/Physics/src/LinearMath/btMotionState.h create mode 100644 Code/Physics/src/LinearMath/btPolarDecomposition.cpp create mode 100644 Code/Physics/src/LinearMath/btPolarDecomposition.h create mode 100644 Code/Physics/src/LinearMath/btPoolAllocator.h create mode 100644 Code/Physics/src/LinearMath/btQuadWord.h create mode 100644 Code/Physics/src/LinearMath/btQuaternion.h create mode 100644 Code/Physics/src/LinearMath/btQuickprof.cpp create mode 100644 Code/Physics/src/LinearMath/btQuickprof.h create mode 100644 Code/Physics/src/LinearMath/btRandom.h create mode 100644 Code/Physics/src/LinearMath/btScalar.h create mode 100644 Code/Physics/src/LinearMath/btSerializer.cpp create mode 100644 Code/Physics/src/LinearMath/btSerializer.h create mode 100644 Code/Physics/src/LinearMath/btStackAlloc.h create mode 100644 Code/Physics/src/LinearMath/btTransform.h create mode 100644 Code/Physics/src/LinearMath/btTransformUtil.h create mode 100644 Code/Physics/src/LinearMath/btVector3.cpp create mode 100644 Code/Physics/src/LinearMath/btVector3.h create mode 100644 Code/Physics/src/LinearMath/premake4.lua create mode 100644 Code/Physics/src/Makefile.am create mode 100644 Code/Physics/src/MiniCL/CMakeLists.txt create mode 100644 Code/Physics/src/MiniCL/MiniCL.cpp create mode 100644 Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.cpp create mode 100644 Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.h create mode 100644 Code/Physics/src/MiniCL/MiniCLTaskScheduler.cpp create mode 100644 Code/Physics/src/MiniCL/MiniCLTaskScheduler.h create mode 100644 Code/Physics/src/MiniCL/cl.h create mode 100644 Code/Physics/src/MiniCL/cl_MiniCL_Defs.h create mode 100644 Code/Physics/src/MiniCL/cl_gl.h create mode 100644 Code/Physics/src/MiniCL/cl_platform.h create mode 100644 Code/Physics/src/btBulletCollisionCommon.h create mode 100644 Code/Physics/src/btBulletDynamicsCommon.h create mode 100644 Code/Physics/src/vectormath/neon/boolInVec.h create mode 100644 Code/Physics/src/vectormath/neon/floatInVec.h create mode 100644 Code/Physics/src/vectormath/neon/mat_aos.h create mode 100644 Code/Physics/src/vectormath/neon/quat_aos.h create mode 100644 Code/Physics/src/vectormath/neon/vec_aos.h create mode 100644 Code/Physics/src/vectormath/neon/vectormath_aos.h create mode 100644 Code/Physics/src/vectormath/scalar/boolInVec.h create mode 100644 Code/Physics/src/vectormath/scalar/floatInVec.h create mode 100644 Code/Physics/src/vectormath/scalar/mat_aos.h create mode 100644 Code/Physics/src/vectormath/scalar/quat_aos.h create mode 100644 Code/Physics/src/vectormath/scalar/vec_aos.h create mode 100644 Code/Physics/src/vectormath/scalar/vectormath_aos.h create mode 100644 Code/Physics/src/vectormath/sse/boolInVec.h create mode 100644 Code/Physics/src/vectormath/sse/floatInVec.h create mode 100644 Code/Physics/src/vectormath/sse/mat_aos.h create mode 100644 Code/Physics/src/vectormath/sse/quat_aos.h create mode 100644 Code/Physics/src/vectormath/sse/vec_aos.h create mode 100644 Code/Physics/src/vectormath/sse/vecidx_aos.h create mode 100644 Code/Physics/src/vectormath/sse/vectormath_aos.h create mode 100644 Code/Physics/src/vectormath/vmInclude.h diff --git a/Code/DanBias.sln b/Code/DanBias.sln index 4dedaaa2..b02fd49b 100644 --- a/Code/DanBias.sln +++ b/Code/DanBias.sln @@ -24,6 +24,11 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetworkDependencies", "Network\NetworkDependencies\NetworkDependencies.vcxproj", "{C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamePhysics", "GamePhysics\GamePhysics.vcxproj", "{104FA3E9-94D9-4E1D-A941-28A03BC8A095}" + ProjectSection(ProjectDependencies) = postProject + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} = {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} = {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} + {22C0C4D8-6C43-406A-9CDB-76A4F800971A} = {22C0C4D8-6C43-406A-9CDB-76A4F800971A} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasGame", "Game\DanBiasGame\DanBiasGame.vcxproj", "{2A1BC987-AF42-4500-802D-89CD32FC1309}" EndProject @@ -45,14 +50,28 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameServer", "Game\GameServ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aDanBiasGameLauncher", "Game\aDanBiasGameLauncher\aDanBiasGameLauncher.vcxproj", "{666FEA52-975F-41CD-B224-B19AF3C0ABBA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Physics", "Physics", "{0D86E569-9C74-47F0-BDB2-390C0C9A084B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "Physics\BulletCollision\BulletCollision.vcxproj", "{B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletDynamics", "Physics\BulletDynamics\BulletDynamics.vcxproj", "{6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "Physics\LinearMath\LinearMath.vcxproj", "{22C0C4D8-6C43-406A-9CDB-76A4F800971A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + MinSizeRel|Mixed Platforms = MinSizeRel|Mixed Platforms + MinSizeRel|Win32 = MinSizeRel|Win32 + MinSizeRel|x64 = MinSizeRel|x64 Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 + RelWithDebInfo|Mixed Platforms = RelWithDebInfo|Mixed Platforms + RelWithDebInfo|Win32 = RelWithDebInfo|Win32 + RelWithDebInfo|x64 = RelWithDebInfo|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 @@ -61,240 +80,516 @@ Global {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Win32.Build.0 = Debug|Win32 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|x64.ActiveCfg = Debug|x64 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|x64.Build.0 = Debug|x64 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Win32.Build.0 = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|x64.ActiveCfg = Release|x64 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|x64.Build.0 = Release|x64 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Mixed Platforms.Build.0 = Release|Win32 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Win32.ActiveCfg = Release|Win32 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Win32.Build.0 = Release|Win32 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|x64.ActiveCfg = Release|x64 {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|x64.Build.0 = Release|x64 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|x64.Build.0 = Release|x64 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Win32.ActiveCfg = Debug|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Win32.Build.0 = Debug|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|x64.ActiveCfg = Debug|x64 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|x64.Build.0 = Debug|x64 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Win32.Build.0 = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|x64.ActiveCfg = Release|x64 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|x64.Build.0 = Release|x64 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Mixed Platforms.Build.0 = Release|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Win32.ActiveCfg = Release|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Win32.Build.0 = Release|Win32 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|x64.ActiveCfg = Release|x64 {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|x64.Build.0 = Release|x64 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|x64.Build.0 = Release|x64 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Win32.ActiveCfg = Debug|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Win32.Build.0 = Debug|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|x64.ActiveCfg = Debug|x64 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|x64.Build.0 = Debug|x64 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Win32.Build.0 = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|x64.ActiveCfg = Release|x64 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|x64.Build.0 = Release|x64 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Mixed Platforms.Build.0 = Release|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Win32.ActiveCfg = Release|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Win32.Build.0 = Release|Win32 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|x64.ActiveCfg = Release|x64 {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|x64.Build.0 = Release|x64 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|x64.Build.0 = Release|x64 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Win32.ActiveCfg = Debug|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Win32.Build.0 = Debug|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|x64.ActiveCfg = Debug|x64 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|x64.Build.0 = Debug|x64 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Win32.Build.0 = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|x64.ActiveCfg = Release|x64 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|x64.Build.0 = Release|x64 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Mixed Platforms.Build.0 = Release|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Win32.ActiveCfg = Release|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Win32.Build.0 = Release|Win32 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|x64.ActiveCfg = Release|x64 {34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|x64.Build.0 = Release|x64 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|x64.Build.0 = Release|x64 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Win32.ActiveCfg = Debug|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Win32.Build.0 = Debug|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|x64.ActiveCfg = Debug|x64 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|x64.Build.0 = Debug|x64 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Win32.Build.0 = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|x64.ActiveCfg = Release|x64 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|x64.Build.0 = Release|x64 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Mixed Platforms.Build.0 = Release|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Win32.ActiveCfg = Release|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Win32.Build.0 = Release|Win32 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|x64.ActiveCfg = Release|x64 {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|x64.Build.0 = Release|x64 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|x64.Build.0 = Release|x64 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Win32.ActiveCfg = Debug|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Win32.Build.0 = Debug|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|x64.ActiveCfg = Debug|x64 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|x64.Build.0 = Debug|x64 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Win32.Build.0 = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|x64.ActiveCfg = Release|x64 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|x64.Build.0 = Release|x64 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Mixed Platforms.Build.0 = Release|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Win32.ActiveCfg = Release|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Win32.Build.0 = Release|Win32 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|x64.ActiveCfg = Release|x64 {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|x64.Build.0 = Release|x64 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|x64.Build.0 = Release|x64 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.ActiveCfg = Debug|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.Build.0 = Debug|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|x64.ActiveCfg = Debug|x64 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|x64.Build.0 = Debug|x64 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Win32.Build.0 = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|x64.ActiveCfg = Release|x64 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|x64.Build.0 = Release|x64 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Mixed Platforms.Build.0 = Release|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Win32.ActiveCfg = Release|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Win32.Build.0 = Release|Win32 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|x64.ActiveCfg = Release|x64 {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|x64.Build.0 = Release|x64 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|x64.Build.0 = Release|x64 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Win32.ActiveCfg = Debug|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Win32.Build.0 = Debug|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|x64.ActiveCfg = Debug|x64 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|x64.Build.0 = Debug|x64 + {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.MinSizeRel|x64.ActiveCfg = Release|x64 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Mixed Platforms.Build.0 = Release|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Win32.ActiveCfg = Release|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Win32.Build.0 = Release|Win32 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|x64.ActiveCfg = Release|x64 {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|x64.Build.0 = Release|x64 + {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Win32.ActiveCfg = Debug|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Win32.Build.0 = Debug|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|x64.ActiveCfg = Debug|x64 {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|x64.Build.0 = Debug|x64 + {6A066806-F43F-4B31-A4E3-57179674F460}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {6A066806-F43F-4B31-A4E3-57179674F460}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {6A066806-F43F-4B31-A4E3-57179674F460}.MinSizeRel|x64.ActiveCfg = Release|x64 {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Mixed Platforms.Build.0 = Release|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Win32.ActiveCfg = Release|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Win32.Build.0 = Release|Win32 {6A066806-F43F-4B31-A4E3-57179674F460}.Release|x64.ActiveCfg = Release|x64 {6A066806-F43F-4B31-A4E3-57179674F460}.Release|x64.Build.0 = Release|x64 + {6A066806-F43F-4B31-A4E3-57179674F460}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {6A066806-F43F-4B31-A4E3-57179674F460}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {6A066806-F43F-4B31-A4E3-57179674F460}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Win32.ActiveCfg = Debug|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Win32.Build.0 = Debug|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|x64.ActiveCfg = Debug|x64 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|x64.Build.0 = Debug|x64 + {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.MinSizeRel|x64.ActiveCfg = Release|x64 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Mixed Platforms.Build.0 = Release|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Win32.ActiveCfg = Release|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Win32.Build.0 = Release|Win32 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|x64.ActiveCfg = Release|x64 {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|x64.Build.0 = Release|x64 + {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Win32.ActiveCfg = Debug|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Win32.Build.0 = Debug|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|x64.ActiveCfg = Debug|x64 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|x64.Build.0 = Debug|x64 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Win32.Build.0 = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|x64.ActiveCfg = Release|x64 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|x64.Build.0 = Release|x64 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Mixed Platforms.Build.0 = Release|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Win32.ActiveCfg = Release|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Win32.Build.0 = Release|Win32 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|x64.ActiveCfg = Release|x64 {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|x64.Build.0 = Release|x64 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|x64.Build.0 = Release|x64 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Win32.ActiveCfg = Debug|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Win32.Build.0 = Debug|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|x64.ActiveCfg = Debug|x64 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|x64.Build.0 = Debug|x64 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Win32.Build.0 = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|x64.ActiveCfg = Release|x64 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|x64.Build.0 = Release|x64 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Mixed Platforms.Build.0 = Release|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Win32.ActiveCfg = Release|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Win32.Build.0 = Release|Win32 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|x64.ActiveCfg = Release|x64 {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|x64.Build.0 = Release|x64 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|x64.Build.0 = Release|x64 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Win32.ActiveCfg = Debug|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Win32.Build.0 = Debug|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|x64.ActiveCfg = Debug|x64 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|x64.Build.0 = Debug|x64 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Win32.Build.0 = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|x64.ActiveCfg = Release|x64 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|x64.Build.0 = Release|x64 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Mixed Platforms.Build.0 = Release|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Win32.ActiveCfg = Release|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Win32.Build.0 = Release|Win32 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|x64.ActiveCfg = Release|x64 {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|x64.Build.0 = Release|x64 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|x64.Build.0 = Release|x64 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Win32.ActiveCfg = Debug|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Win32.Build.0 = Debug|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|x64.ActiveCfg = Debug|x64 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|x64.Build.0 = Debug|x64 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Win32.Build.0 = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|x64.ActiveCfg = Release|x64 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|x64.Build.0 = Release|x64 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Mixed Platforms.Build.0 = Release|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Win32.ActiveCfg = Release|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Win32.Build.0 = Release|Win32 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|x64.ActiveCfg = Release|x64 {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|x64.Build.0 = Release|x64 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|x64.Build.0 = Release|x64 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Win32.ActiveCfg = Debug|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Win32.Build.0 = Debug|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|x64.ActiveCfg = Debug|x64 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|x64.Build.0 = Debug|x64 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Win32.Build.0 = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|x64.ActiveCfg = Release|x64 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|x64.Build.0 = Release|x64 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Mixed Platforms.Build.0 = Release|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Win32.ActiveCfg = Release|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Win32.Build.0 = Release|Win32 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|x64.ActiveCfg = Release|x64 {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|x64.Build.0 = Release|x64 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|x64.Build.0 = Release|x64 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Win32.ActiveCfg = Debug|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Win32.Build.0 = Debug|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|x64.ActiveCfg = Debug|x64 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|x64.Build.0 = Debug|x64 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Win32.Build.0 = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|x64.ActiveCfg = Release|x64 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|x64.Build.0 = Release|x64 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Mixed Platforms.Build.0 = Release|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Win32.ActiveCfg = Release|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Win32.Build.0 = Release|Win32 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|x64.ActiveCfg = Release|x64 {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|x64.Build.0 = Release|x64 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|x64.Build.0 = Release|x64 {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Win32.ActiveCfg = Debug|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Win32.Build.0 = Debug|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|x64.ActiveCfg = Debug|x64 {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|x64.Build.0 = Debug|x64 + {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Win32.Build.0 = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|x64.ActiveCfg = Release|x64 + {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|x64.Build.0 = Release|x64 {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Mixed Platforms.Build.0 = Release|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Win32.ActiveCfg = Release|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Win32.Build.0 = Release|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.Release|x64.ActiveCfg = Release|x64 {060B1890-CBF3-4808-BA99-A4776222093B}.Release|x64.Build.0 = Release|x64 + {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|x64.Build.0 = Release|x64 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Win32.ActiveCfg = Debug|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Win32.Build.0 = Debug|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|x64.ActiveCfg = Debug|x64 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|x64.Build.0 = Debug|x64 + {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.MinSizeRel|x64.ActiveCfg = Release|x64 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Mixed Platforms.Build.0 = Release|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Win32.ActiveCfg = Release|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Win32.Build.0 = Release|Win32 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|x64.ActiveCfg = Release|x64 {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|x64.Build.0 = Release|x64 + {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.ActiveCfg = Debug|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.Build.0 = Debug|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|x64.ActiveCfg = Debug|x64 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|x64.Build.0 = Debug|x64 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Win32.Build.0 = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|x64.ActiveCfg = Release|x64 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|x64.Build.0 = Release|x64 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Mixed Platforms.Build.0 = Release|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Win32.ActiveCfg = Release|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Win32.Build.0 = Release|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|x64.ActiveCfg = Release|x64 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|x64.Build.0 = Release|x64 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|x64.Build.0 = Release|x64 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Win32.ActiveCfg = Debug|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Win32.Build.0 = Debug|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|x64.ActiveCfg = Debug|x64 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|x64.Build.0 = Debug|x64 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Win32.ActiveCfg = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Win32.Build.0 = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|x64.ActiveCfg = Release|x64 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|x64.Build.0 = Release|x64 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Mixed Platforms.Build.0 = Release|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Win32.ActiveCfg = Release|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Win32.Build.0 = Release|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|x64.ActiveCfg = Release|x64 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|x64.Build.0 = Release|x64 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Win32.Build.0 = Release|Win32 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.Build.0 = Release|x64 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Win32.ActiveCfg = Debug|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Win32.Build.0 = Debug|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|x64.ActiveCfg = Debug|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Mixed Platforms.Build.0 = Release|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Win32.ActiveCfg = Release|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Win32.Build.0 = Release|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|x64.ActiveCfg = Release|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Win32.ActiveCfg = Debug|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Win32.Build.0 = Debug|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|x64.ActiveCfg = Debug|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Win32.ActiveCfg = Release|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Win32.Build.0 = Release|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|x64.ActiveCfg = Release|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Win32.ActiveCfg = Debug|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Win32.Build.0 = Debug|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|x64.ActiveCfg = Debug|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Mixed Platforms.Build.0 = Release|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Win32.ActiveCfg = Release|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Win32.Build.0 = Release|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|x64.ActiveCfg = Release|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -311,5 +606,8 @@ Global {060B1890-CBF3-4808-BA99-A4776222093B} = {20720CA7-795C-45AD-A302-9383A6DD503A} {143BD516-20A1-4890-A3E4-F8BFD02220E7} = {20720CA7-795C-45AD-A302-9383A6DD503A} {666FEA52-975F-41CD-B224-B19AF3C0ABBA} = {20720CA7-795C-45AD-A302-9383A6DD503A} + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} + {22C0C4D8-6C43-406A-9CDB-76A4F800971A} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} EndGlobalSection EndGlobal diff --git a/Code/Game/DanBiasGame/GameClientState/Camera.cpp b/Code/Game/DanBiasGame/GameClientState/Camera.cpp index 13b5a70f..afdf2eab 100644 --- a/Code/Game/DanBiasGame/GameClientState/Camera.cpp +++ b/Code/Game/DanBiasGame/GameClientState/Camera.cpp @@ -2,7 +2,7 @@ Camera::Camera() { - this->m_position = Oyster::Math::Float3(0, 50, 0); + this->m_position = Oyster::Math::Float3(0, 600, 0); this->mRight = Oyster::Math::Float3(1, 0, 0); this->mUp = Oyster::Math::Float3(0, 1, 0); this->mLook = Oyster::Math::Float3(0, 0, 1); diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 06def943..a7d04f86 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -465,13 +465,14 @@ void GameState::Protocol( ObjPos* pos ) if(privData->object[i]->GetId() == pos->object_ID) { privData->object[i]->setPos(world); - + if(i == myId) // playerobj { Oyster::Math::Float3 right = Oyster::Math::Float3(world[0], world[1], world[2]); Oyster::Math::Float3 up = Oyster::Math::Float3(world[4], world[5], world[6]); Oyster::Math::Float3 objForward = (Oyster::Math::Float3(world[8], world[9], world[10])); Oyster::Math::Float3 pos = Oyster::Math::Float3(world[12], world[13], world[14]); + Oyster::Math::Float3 cameraLook = camera->GetLook(); Oyster::Math::Float3 cameraUp = camera->GetUp(); @@ -490,7 +491,7 @@ void GameState::Protocol( ObjPos* pos ) up *= 1; objForward *= -2; - Oyster::Math::Float3 cameraPos = up + pos + objForward; + Oyster::Math::Float3 cameraPos = pos + up + objForward; camera->SetPosition(cameraPos); camera->UpdateViewMatrix(); diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.cpp b/Code/Game/GameLogic/AttatchmentMassDriver.cpp index 59be4542..a2002566 100644 --- a/Code/Game/GameLogic/AttatchmentMassDriver.cpp +++ b/Code/Game/GameLogic/AttatchmentMassDriver.cpp @@ -64,11 +64,11 @@ void AttatchmentMassDriver::Update(float dt) state = heldObject->GetState(); Oyster::Math::Float3 ownerPos = owner->GetPosition(); Oyster::Physics::ICustomBody::State ownerState = owner->GetRigidBody()->GetState(); - Oyster::Math::Float3 up = -ownerState.GetGravityNormal(); + Oyster::Math::Float3 up = -ownerState.GetOrientation().v[2]; up *= -0.3; Oyster::Math::Float3 pos = ownerPos + up + (owner->GetLookDir().GetNormalized()*5); - state.SetCenterPosition(pos); + state.centerPos = pos; heldObject->SetState(state); } @@ -88,7 +88,7 @@ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float Oyster::Physics::API::Instance().ReleaseFromLimbo(heldObject); pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (700); Oyster::Physics::ICustomBody::State state = heldObject->GetState(); - state.ApplyLinearImpulse((Oyster::Math::Float3)pushForce); + //state.ApplyLinearImpulse((Oyster::Math::Float3)pushForce); heldObject->SetState(state); hasObject = false; @@ -118,7 +118,7 @@ void AttatchmentMassDriver::ForceZip(const WEAPON_FIRE &usage, float dt) Oyster::Physics::Struct::CustomBodyState state = this->owner->GetRigidBody()->GetState(); //do something with state - state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt)); + //state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt)); this->owner->GetRigidBody()->SetState(state); } @@ -135,7 +135,7 @@ void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt) //if no object has been picked up then suck objects towards you Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (100 * dt); - Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition()); + Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetState().GetOrientation().v[2].xyz, owner->GetPosition()); Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20); Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace)); diff --git a/Code/Game/GameLogic/CollisionManager.cpp b/Code/Game/GameLogic/CollisionManager.cpp index 21c073f8..922ab7fe 100644 --- a/Code/Game/GameLogic/CollisionManager.cpp +++ b/Code/Game/GameLogic/CollisionManager.cpp @@ -68,7 +68,7 @@ using namespace GameLogic; Oyster::Physics::ICustomBody::State state; state = obj.GetState(); - state.ApplyLinearImpulse(force); + //state.ApplyLinearImpulse(force); obj.SetState(state); } @@ -130,7 +130,7 @@ using namespace GameLogic; return; state = obj->GetState(); - state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce); + //state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce); obj->SetState(state); } diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index 6aecc900..fe7a41c7 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -71,7 +71,7 @@ Game::PlayerData* Game::CreatePlayer() int id = InsertObject(this->players, (PlayerData*)0); this->players[id] = new PlayerData(); - this->players[id]->player->GetRigidBody()->SetSubscription(Game::PhysicsOnMove); + //this->players[id]->player->GetRigidBody()->SetSubscription(Game::PhysicsOnMove); return this->players[id]; } @@ -99,7 +99,7 @@ bool Game::NewFrame() if(this->players[i]->player) this->players[i]->player->BeginFrame(); } - API::Instance().Update(); + API::Instance().UpdateWorld(); for (unsigned int i = 0; i < this->players.Size(); i++) { @@ -110,7 +110,7 @@ bool Game::NewFrame() if(this->players[i]->player) this->players[i]->player->BeginFrame(); } - API::Instance().Update(); + API::Instance().UpdateWorld(); for (unsigned int i = 0; i < this->players.Size(); i++) { @@ -121,7 +121,7 @@ bool Game::NewFrame() if(this->players[i]->player) this->players[i]->player->BeginFrame(); } - API::Instance().Update(); + API::Instance().UpdateWorld(); for (unsigned int i = 0; i < this->players.Size(); i++) { @@ -159,8 +159,8 @@ void Game::SetSubscription(GameEvent::ObjectEventFunctionType type, GameEvent::O bool Game::Initiate() { - API::Instance().Init((int)pow(2u, 9u), 1u, Oyster::Math::Float3()); - API::Instance().SetSubscription(Game::PhysicsOnDestroy); + API::Instance().Init(); + //API::Instance().SetSubscription(Game::PhysicsOnDestroy); this->initiated = true; return true; } diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index e4b54f9a..0cb4e4bd 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -6,26 +6,26 @@ using namespace GameLogic; Game::PlayerData::PlayerData() { //set some stats that are appropriate to a player - Oyster::Physics::API::SimpleBodyDescription sbDesc; - sbDesc.centerPosition = Oyster::Math::Float3(0,608,0); - sbDesc.size = Oyster::Math::Float3(0.5f,2,1); - sbDesc.mass = 70; - sbDesc.restitutionCoeff = 0.5; - sbDesc.frictionCoeff_Static = 0.4; - sbDesc.frictionCoeff_Dynamic = 0.3; - sbDesc.rotation = Oyster::Math::Float3(0, Oyster::Math::pi, 0); + Oyster::Math::Float3 centerPosition = Oyster::Math::Float3(0,608,-5); + Oyster::Math::Float3 size = Oyster::Math::Float3(0.25f,1.0f,0.5f); + Oyster::Math::Float mass = 15; + Oyster::Math::Float restitutionCoeff = 0.5; + Oyster::Math::Float frictionCoeff_Static = 0.4; + Oyster::Math::Float frictionCoeff_Dynamic = 0.3; + //sbDesc.quaternion = Oyster::Math::Float3(0, Oyster::Math::pi, 0); //create rigid body - Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); + Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass); //create player with this rigid body this->player = new Player(rigidBody,Player::DefaultCollisionAfter, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); - /*Oyster::Physics::ICustomBody::State state; + + Oyster::Physics::ICustomBody::State state; this->player->GetRigidBody()->GetState(state); - state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0)); + //state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0)); this->player->GetRigidBody()->SetState(state); - player->EndFrame();*/ + player->EndFrame(); } Game::PlayerData::PlayerData(int playerID,int teamID) { diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 82ba5def..9c735c48 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -51,33 +51,17 @@ void Level::InitiateLevel(float radius) } // add level sphere - API::SphericalBodyDescription sbDesc; - sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1); - sbDesc.ignoreGravity = true; - sbDesc.radius = 600; - sbDesc.mass = 70; - sbDesc.frictionCoeff_Static = 0; - sbDesc.frictionCoeff_Dynamic = 0; - //sbDesc.rotation = - ICustomBody* rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); + ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); ICustomBody::State state; rigidBody->GetState(state); - state.SetRestitutionCoeff(0.2); + state.restitutionCoeff = 0.2f; rigidBody->SetState(state); - levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); rigidBody->SetCustomTag(levelObj); - - //this->dynamicObjects = new DynamicArray< DynamicObject>; - // add box - API::SimpleBodyDescription sbDesc_TestBox; - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,1); - sbDesc_TestBox.ignoreGravity = false; - sbDesc_TestBox.mass = 15; - sbDesc_TestBox.size = Oyster::Math::Float4(1, 1, 1, 0); - sbDesc_TestBox.inertiaTensor.Cuboid(15, 1, 1, 1); + + ICustomBody* rigidBody_TestBox; @@ -86,9 +70,7 @@ void Level::InitiateLevel(float radius) int offset = 0; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(0,605 + i*5,5,1); - rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); - rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 5), 5); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i]); @@ -96,32 +78,28 @@ void Level::InitiateLevel(float radius) offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20,620, -200 +( i*7),0); - rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); - rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0,5, -605 -( i*5)), 5); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]); + } offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(200,620 + ( i*7),0,0); - rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); - rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(200, 620 + ( i*7), 0), 5); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); - rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]); + rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]); } offset += nrOfBoxex; for(int i =0; i< nrOfBoxex; i ++) { - sbDesc_TestBox.centerPosition = Oyster::Math::Float4(5,605 + i*5,0,0); - rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release(); - rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(5, 605 + i*5, 0), 5); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i]); + } @@ -129,43 +107,19 @@ void Level::InitiateLevel(float radius) // add crystal - API::SimpleBodyDescription sbDesc_Crystal; - sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 605, 0, 1); - sbDesc_Crystal.ignoreGravity = false; - sbDesc_Crystal.mass = 15; - sbDesc_Crystal.size = Oyster::Math::Float3(1, 2, 1); - sbDesc_Crystal.inertiaTensor.Cuboid(15, 1, 2, 1); - ICustomBody* rigidBody_Crystal = API::Instance().CreateRigidBody(sbDesc_Crystal).Release(); - rigidBody_Crystal->SetSubscription(Level::PhysicsOnMoveLevel); + ICustomBody* rigidBody_Crystal = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(10, 605, 0), 5); + this->dynamicObjects.Push(new DynamicObject(rigidBody_Crystal,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); rigidBody_Crystal->SetCustomTag(this->dynamicObjects[nrOfBoxex]); + + // add house - API::SimpleBodyDescription sbDesc_House; - //sbDesc_House.centerPosition = Oyster::Math::Float4(212, 212, 0, 0); - sbDesc_House.centerPosition = Oyster::Math::Float4(-50, 690, 0, 1); - sbDesc_House.ignoreGravity = false; - sbDesc_House.rotation = Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); - sbDesc_House.mass = 90; - sbDesc_House.size = Oyster::Math::Float3(40,40,40); - - - ICustomBody* rigidBody_House = API::Instance().CreateRigidBody(sbDesc_House).Release(); - rigidBody_House->SetSubscription(Level::PhysicsOnMoveLevel); + ICustomBody* rigidBody_House =API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(10, 905, 0), 0); this->staticObjects.Push(new StaticObject(rigidBody_House,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); rigidBody_House->SetCustomTag(this->staticObjects[0]); - rigidBody_House->GetState(state); - Oyster::Math::Float4x4 world = state.GetOrientation(); - - - // add gravitation - API::Gravity gravityWell; - gravityWell.gravityType = API::Gravity::GravityType_Well; - gravityWell.well.mass = 1e17f; - gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); - API::Instance().AddGravity(gravityWell); } void Level::AddPlayerToTeam(Player *player, int teamID) diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index b7e392fe..e6a554f8 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -15,10 +15,8 @@ const Game *Object::gameInstance = (Game*)(&Game::Instance()); Object::Object() { - API::SimpleBodyDescription sbDesc; - this->rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); - Oyster::Physics::API::Instance().AddObject(rigidBody); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN; this->objectID = GID(); @@ -28,10 +26,7 @@ Object::Object() Object::Object(OBJECT_TYPE type) { - API::SimpleBodyDescription sbDesc; - - this->rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); - Oyster::Physics::API::Instance().AddObject(rigidBody); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); this->type = type; this->objectID = GID(); this->currPhysicsState = this->rigidBody->GetState(); @@ -40,7 +35,6 @@ Object::Object(OBJECT_TYPE type) Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) { - Oyster::Physics::API::Instance().AddObject(rigidBody); this->rigidBody = rigidBody; this->type = type; this->objectID = GID(); @@ -50,10 +44,7 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) { - API::SimpleBodyDescription sbDesc; - - this->rigidBody = API::Instance().CreateRigidBody(sbDesc).Release(); - Oyster::Physics::API::Instance().AddObject(rigidBody); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); this->type = type; this->objectID = GID(); @@ -63,11 +54,7 @@ Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) { - Oyster::Physics::API::Instance().AddObject(rigidBody); - this->rigidBody = rigidBody; - this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore)); - this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse)(collisionFuncAfter)); this->type = type; this->objectID = GID(); @@ -77,11 +64,7 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefor Object::Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter), Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), OBJECT_TYPE type) { - Oyster::Physics::API::Instance().AddObject(rigidBody); - this->rigidBody = rigidBody; - this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore)); - this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse)(collisionFuncAfter)); this->type = type; @@ -92,7 +75,7 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustom void Object::ApplyLinearImpulse(Oyster::Math::Float3 force) { - newPhysicsState.ApplyLinearImpulse(force); + } @@ -119,86 +102,19 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { + - if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum()) - { - //error - int i =0 ; - } - if(currPhysicsState.GetCenterPosition() !=currPhysicsState.GetCenterPosition()) - { - //error - int i =0 ; - } - if(currPhysicsState.GetAngularAxis() !=currPhysicsState.GetAngularAxis()) - { - //error - int i =0 ; - } this->rigidBody->SetState(this->newPhysicsState); } // update physic void Object::EndFrame() { - if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum()) - { - //error - int i =0 ; - } - this->currPhysicsState = this->rigidBody->GetState(); - if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum()) - { - //error - int i =0 ; - } - if(currPhysicsState.GetGravityNormal() !=currPhysicsState.GetGravityNormal()) - { - //error - int i =0 ; - } - - - //if(currPhysicsState.GetGravityNormal()!= Float3::null) - { - Oyster::Math::Float4 axis; - Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(currPhysicsState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, Oyster::Math::Float4(currPhysicsState.GetCenterPosition().GetNormalized(), 0), axis); - if(axis !=axis) - { - //error - int i =0 ; - } - axis.Normalize(); - currPhysicsState.SetRotation(axis.xyz); - currPhysicsState.SetAngularMomentum(Float3::null); - //Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y); - //debug += currPhysicsState.GetGravityNormal(); - } - //Oyster::Math::Float3 pos = currPhysicsState.GetCenterPosition(); - //Oyster::Math::Float3 up = -currPhysicsState.GetGravityNormal(); - //300, 0,0, - //1,0,0 - - /*if( pos.GetLength() < 301.5f) - { - Oyster::Math::Float moveUp = 301.5 - pos.GetLength(); - up *= moveUp; - - currPhysicsState.SetCenterPosition(pos + up); - }*/ - - - if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum()) - { - //error - int i =0 ; - } - this->newPhysicsState = this->currPhysicsState; } void Object::setBeforeCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter)) { - this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore)); + //this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore)); } void Object::setAfterCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss)) { @@ -209,7 +125,7 @@ Oyster::Math::Float3 Object::GetPosition() { Oyster::Physics::ICustomBody::State state; state = this->rigidBody->GetState(); - return state.GetCenterPosition(); + return state.centerPos; } Oyster::Math::Float4x4 Object::GetOrientation() { diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index 9b0c29ee..40102d2d 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -73,7 +73,7 @@ void Player::EndFrame() Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; - currPhysicsState.AddRotation(deltaAxis); + //currPhysicsState.AddRotation(deltaAxis); dx = 0; this->newPhysicsState = this->currPhysicsState; } @@ -108,21 +108,21 @@ void Player::MoveForward() { Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - newPhysicsState.ApplyLinearImpulse(forward * (MOVE_FORCE * this->gameInstance->GetFrameTime())); + //newPhysicsState.ApplyLinearImpulse(forward * (MOVE_FORCE * this->gameInstance->GetFrameTime())); } void Player::MoveBackwards() { Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - newPhysicsState.ApplyLinearImpulse(-forward * MOVE_FORCE * this->gameInstance->GetFrameTime()); + //newPhysicsState.ApplyLinearImpulse(-forward * MOVE_FORCE * this->gameInstance->GetFrameTime()); } void Player::MoveRight() { //Do cross product with forward vector and negative gravity vector Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); - newPhysicsState.ApplyLinearImpulse(-r * MOVE_FORCE * this->gameInstance->GetFrameTime()); + //Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); + //newPhysicsState.ApplyLinearImpulse(-r * MOVE_FORCE * this->gameInstance->GetFrameTime()); } void Player::MoveLeft() @@ -130,8 +130,8 @@ void Player::MoveLeft() //Do cross product with forward vector and negative gravity vector Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); //Still get zero - newPhysicsState.ApplyLinearImpulse(r * MOVE_FORCE * this->gameInstance->GetFrameTime()); + //Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); //Still get zero + //newPhysicsState.ApplyLinearImpulse(r * MOVE_FORCE * this->gameInstance->GetFrameTime()); } void Player::UseWeapon(const WEAPON_FIRE &usage) @@ -144,7 +144,7 @@ void Player::Respawn(Oyster::Math::Float3 spawnPoint) this->life = 100; this->playerState = PLAYER_STATE::PLAYER_STATE_IDLE; this->lookDir = Oyster::Math::Float4(1,0,0); - this->newPhysicsState.SetCenterPosition(spawnPoint); + this->newPhysicsState.centerPos = spawnPoint; } void Player::Rotate(const Oyster::Math3D::Float4 lookDir) @@ -162,7 +162,7 @@ void Player::Rotate(const Oyster::Math3D::Float4 lookDir) void Player::Jump() { Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; - newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime()); + //newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime()); } bool Player::IsWalking() @@ -180,7 +180,7 @@ bool Player::IsIdle() Oyster::Math::Float3 Player::GetPosition() const { - return (Oyster::Math::Float3)currPhysicsState.GetCenterPosition(); + return (Oyster::Math::Float3)currPhysicsState.centerPos; } Oyster::Math::Float4x4 Player::GetOrientation() const { diff --git a/Code/Game/GameLogic/StaticObject.cpp b/Code/Game/GameLogic/StaticObject.cpp index c007b919..65cc0577 100644 --- a/Code/Game/GameLogic/StaticObject.cpp +++ b/Code/Game/GameLogic/StaticObject.cpp @@ -18,8 +18,8 @@ StaticObject::StaticObject(OBJECT_TYPE type) StaticObject::StaticObject(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) :Object(rigidBody,type) { - this->rigidBody->SetGravity(true); - this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(CollisionManager::IgnoreCollision)); + //this->rigidBody->SetGravity(true); + //this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(CollisionManager::IgnoreCollision)); } StaticObject::StaticObject(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) diff --git a/Code/GamePhysics/GamePhysics.vcxproj b/Code/GamePhysics/GamePhysics.vcxproj index 1abcc6f8..813d87c6 100644 --- a/Code/GamePhysics/GamePhysics.vcxproj +++ b/Code/GamePhysics/GamePhysics.vcxproj @@ -89,7 +89,7 @@ Level3 Disabled - $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;%(AdditionalIncludeDirectories) + $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) _WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions) false @@ -97,6 +97,7 @@ true + $(SolutionDir)Physics/Debug/BulletCollision_Debug.lib;$(SolutionDir)Physics/Debug/BulletDynamics_Debug.lib;$(SolutionDir)Physics/Debug/LinearMath_Debug.lib;%(AdditionalDependencies) @@ -119,7 +120,7 @@ MaxSpeed true true - $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;%(AdditionalIncludeDirectories) + $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) _WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions) false diff --git a/Code/GamePhysics/Implementation/Octree.cpp b/Code/GamePhysics/Implementation/Octree.cpp index e615df63..4778e5f1 100644 --- a/Code/GamePhysics/Implementation/Octree.cpp +++ b/Code/GamePhysics/Implementation/Octree.cpp @@ -31,11 +31,11 @@ Octree& Octree::operator=(const Octree& orig) void Octree::AddObject(UniquePointer< ICustomBody > customBodyRef) { - customBodyRef->SetScene( this ); + //customBodyRef->SetScene( this ); Data data; //Data* tempPtr = this->worldNode.dataPtr; - data.container = customBodyRef->GetBoundingSphere(); + //data.container = customBodyRef->GetBoundingSphere(); data.queueRef = -1; data.next = NULL; data.prev = NULL; @@ -216,7 +216,7 @@ unsigned int Octree::GetTemporaryReferenceOf( const ICustomBody* objRef ) const void Octree::SetAsAltered( unsigned int tempRef ) { - this->leafData[tempRef].container = this->leafData[tempRef].customBodyRef->GetBoundingSphere(); + //this->leafData[tempRef].container = this->leafData[tempRef].customBodyRef->GetBoundingSphere(); //! @todo TODO: implement stub } diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 7e14c01b..4c07cc24 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -12,274 +12,6 @@ using namespace ::Utility::Value; API_Impl API_instance; -namespace -{ - /*void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef ) - { - auto proto = worldScene.GetCustomBody( protoTempRef ); - auto deuter = worldScene.GetCustomBody( deuterTempRef ); - - Float4 worldPointOfContact; - if( proto->Intersects(*deuter, worldPointOfContact) ) - { - // Apply CollisionResponse in pure gather pattern - ICustomBody::State protoState; proto->GetState( protoState ); - ICustomBody::State deuterState; deuter->GetState( deuterState ); - - // calc from perspective of deuter. - Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )); // Init value is only borrowed - //if( normal.Dot(normal) > 0.0f ) - { - deuter->GetNormalAt( worldPointOfContact, normal ); - } - //else - //{ // special case: deuter is completly contained within proto or they have overlapping centers. - - // normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f ); - // if( normal.Dot(normal) == 0.0f ) - // { // they have overlapping centers. Rebound at least - // // calculate and store time interpolation value, for later rebound. - // proto->SetTimeOfContact( worldPointOfContact ); - // return; - // } - // - // // borrowing the negated normal of proto. - // proto->GetNormalAt( worldPointOfContact, normal ); - // normal = -normal; - //} - normal.Normalize(); - - Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0), - deuterG = Float4(deuterState.GetLinearMomentum( worldPointOfContact.xyz ), 0); - - if( normal != normal ) // debug: trap - const char *breakpoint = "This should never happen"; - - if( protoG != protoG ) // debug: trap - const char *breakpoint = "This should never happen"; - - if( deuterG != deuterG ) // debug: trap - const char *breakpoint = "This should never happen"; - - Float protoG_Magnitude = protoG.Dot( normal ), - deuterG_Magnitude = deuterG.Dot( normal ); - - // if they are not relatively moving towards eachother, there is no collision - Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) ); - if( deltaPos < 0.0f ) - { - if( protoG_Magnitude >= deuterG_Magnitude ) - { - return; - } - } - else if( deltaPos > 0.0f ) - { - if( protoG_Magnitude <= deuterG_Magnitude ) - { - return; - } - } - else - { - return; - } - - if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response ) - { - return; - } - - // PLayerHAck - if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_player_collision_response ) - { - //Float3 linearMomentum = protoState.GetLinearMomentum(); - //Float3 up = -protoState.GetGravityNormal(); - //Float3 upForce = (linearMomentum.Dot(up) * up); - - //Float3 noBounceForce = linearMomentum - upForce; - //protoState.SetLinearMomentum(noBounceForce); - //proto->SetState(protoState); - return; - } - // calculate and store time interpolation value, for later rebound. - proto->SetTimeOfContact( worldPointOfContact ); - - // bounce - Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(), - deuterState.GetMass(), deuterG_Magnitude, - protoState.GetMass(), protoG_Magnitude ); - - - // calc from perspective of proto - - normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized(); - //if( normal.Dot(normal) > 0.0f ) - { - proto->GetNormalAt( worldPointOfContact, normal ); - protoG_Magnitude = protoG.Dot( normal ); - deuterG_Magnitude = deuterG.Dot( normal ); - normal.Normalize(); - } - //else - //{ // special case: proto is completly contained within deuter. - // // borrowing the negated normal of deuter. - // deuter->GetNormalAt( worldPointOfContact, normal ); - // normal = -normal; - // protoG_Magnitude = -protoG_Magnitude; - // deuterG_Magnitude = -deuterG_Magnitude; - //} - - if( normal != normal ) // debug: trap - const char *breakpoint = "This should never happen"; - - // bounce - Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), - protoState.GetMass(), protoG_Magnitude, - deuterState.GetMass(), deuterG_Magnitude ); - - Float4 bounce = Average( bounceD, bounceP ); - - Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal, - Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), - Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); - - if(protoState.GetMass() == 70) - { - const char* breakPoint = "here"; - } - - Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); - - protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); - proto->SetState( protoState ); - - Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); - - proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyPBefore - kineticEnergyPAFter ); - } - - - }*/ - void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef ) - { - auto proto = worldScene.GetCustomBody( protoTempRef ); - auto deuter = worldScene.GetCustomBody( deuterTempRef ); - - Float4 worldPointOfContact; - if( proto->Intersects(*deuter, worldPointOfContact) ) - { - // Apply CollisionResponse in pure gather pattern - ICustomBody::State protoState; proto->GetState( protoState ); - ICustomBody::State deuterState; deuter->GetState( deuterState ); - - - - Float4 normal = deuter->GetNormalAt(worldPointOfContact); - if(normal == Float4::null) - { - normal = Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1); - } - normal.Normalize(); - - Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0), - deuterG = Float4(deuterState.GetLinearMomentum( worldPointOfContact.xyz ), 0); - - Float protoG_Magnitude = protoG.Dot( normal ), - deuterG_Magnitude = deuterG.Dot( normal ); - - // If true the object is inside the world - if(worldPointOfContact.GetLength() < 600 && protoState.GetCenterPosition().GetLength() != 0) - { - Float overlap = 600 - worldPointOfContact.GetLength(); - Float3 newPos = overlap*worldPointOfContact.GetNormalized(); - protoState.SetCenterPosition(protoState.GetCenterPosition() + newPos); - protoState.SetLinearMomentum(Float3(0, 0, 0)); - } - - // If they are not relatively moving towards eachother, there is no collision - Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) ); - if( deltaPos < 0.0f ) - { - if( protoG_Magnitude >= deuterG_Magnitude ) - { - return; - } - } - else if( deltaPos > 0.0f ) - { - if( protoG_Magnitude <= deuterG_Magnitude ) - { - return; - } - } - else - { - return; - } - - // Proto - normal = -proto->GetNormalAt(worldPointOfContact); - if(normal == Float4::null) - { - normal = Float4(protoState.GetCenterPosition(), 1) - Float4(deuterState.GetCenterPosition(), 1); - } - normal.Normalize(); - - // Calculate and apply friction to rigid body - Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal, - Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(), - Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass()); - - //protoState.ApplyFriction( -friction.xyz ); - - // If no other collision response is wanted then this will stop the bounce - if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response ) - { - return; - } - - - - // Calaculate bounce - Float4 bounce = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(), - protoState.GetMass(), protoG_Magnitude, - deuterState.GetMass(), deuterG_Magnitude ); - // If bounce is not big enough to matter, set to 0 - if( abs(bounce.x) < 0.001 ) - { - bounce.x = 0; - } - if( abs(bounce.y) < 0.001 ) - { - bounce.y = 0; - } - if( abs(bounce.z) < 0.001 ) - { - bounce.z = 0; - } - - if( bounce != bounce) - { - const char* breakpoint = "STOP"; - } - - // Calculate kinetic energy before impulse is applied - Float kineticEnergyBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() ); - - // Apply the bounce as impulse - protoState.ApplyImpulse( bounce.xyz, worldPointOfContact.xyz, normal.xyz ); - proto->SetState( protoState ); - - // Calculate kinetic energy after impulse is applied - Float kineticEnergyAfter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() ); - - // Call a collision function with kinetic energy loss - proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyBefore - kineticEnergyAfter ); - } - } -} - API & API::Instance() { return API_instance; @@ -287,280 +19,186 @@ API & API::Instance() API_Impl::API_Impl() { - this->gravityConstant = Constant::gravity_constant; - this->epsilon = Constant::epsilon; - this->updateFrameLength = 1.0f / 120.0f; - this->destructionAction = Default::EventAction_Destruction; - this->gravity = ::std::vector(); - this->worldScene = Octree(); + this->broadphase = NULL; + this->collisionConfiguration = NULL; + this->dispatcher = NULL; + this->solver = NULL; + this->dynamicsWorld = NULL; } -API_Impl::~API_Impl() {} - -void API_Impl::Init( unsigned int numObjects, unsigned int numGravityWells , const Float3 &worldSize ) +API_Impl::~API_Impl() { - unsigned char numLayers = 4; //!< @todo TODO: calc numLayers from worldSize - this->gravity.resize( 0 ); - this->gravity.reserve( numGravityWells ); - this->worldScene = Octree( numObjects, numLayers, worldSize ); -} + delete this->dynamicsWorld; + this->dynamicsWorld = NULL; + delete this->solver; + this->solver = NULL; + delete this->dispatcher; + this->dispatcher = NULL; + delete this->collisionConfiguration; + this->collisionConfiguration = NULL; + delete this->broadphase; + this->broadphase = NULL; -void API_Impl::SetFrameTimeLength( float deltaTime ) -{ - this->updateFrameLength = deltaTime; -} - -void API_Impl::SetGravityConstant( float g ) -{ - this->gravityConstant = g; -} - -void API_Impl::SetEpsilon( float e ) -{ - this->epsilon = e; -} - -void API_Impl::SetSubscription( API::EventAction_Destruction functionPointer ) -{ - if( functionPointer ) + for(int i = 0; i < this->customBodies.size(); i++) { - this->destructionAction = functionPointer; - } - else - { - this->destructionAction = Default::EventAction_Destruction; + delete this->customBodies[i]; + this->customBodies[i] = NULL; } } -float API_Impl::GetFrameTimeLength() const +// Bullet physics +ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) { - return this->updateFrameLength; + SimpleRigidBody* body = new SimpleRigidBody; + + // Add collision shape + btCollisionShape* collisionShape = new btSphereShape(radius); + body->SetCollisionShape(collisionShape); + + // Add motion state + btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w),btVector3(position.x, position.y, position.z))); + body->SetMotionState(motionState); + + // Add rigid body + btVector3 fallInertia(0, 0, 0); + collisionShape->calculateLocalInertia(mass, fallInertia); + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); + btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); + rigidBody->setUserPointer(body); + body->SetRigidBody(rigidBody); + + // Add rigid body to world + this->dynamicsWorld->addRigidBody(rigidBody); + this->customBodies.push_back(body); + + return body; +} +ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) +{ + SimpleRigidBody* body = new SimpleRigidBody; + + // Add collision shape + btCollisionShape* collisionShape = new btBoxShape(btVector3(halfSize.x, halfSize.y, halfSize.z)); + body->SetCollisionShape(collisionShape); + + // Add motion state + btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w),btVector3(position.x, position.y, position.z))); + body->SetMotionState(motionState); + + // Add rigid body + btVector3 fallInertia(0, 0, 0); + collisionShape->calculateLocalInertia(mass, fallInertia); + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); + btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); + rigidBody->setUserPointer(body); + body->SetRigidBody(rigidBody); + + // Add rigid body to world + this->dynamicsWorld->addRigidBody(rigidBody); + this->customBodies.push_back(body); + + return body; } -void API_Impl::Update() -{ +void API_Impl::UpdateWorld() +{ + this->dynamicsWorld->stepSimulation(1.0f/120.0f, 1.0f, 1.0f/120.0f); + ICustomBody::State state; - ::std::vector updateList; - // Fetch objects in universe - this->worldScene.Sample( Universe(), updateList ); - - // Change momentum for all rigid bodies - for( unsigned int i = 0; i < updateList.size(); i++ ) + for(unsigned int i = 0; i < this->customBodies.size(); i++ ) { - ICustomBody* proto = updateList[i]; - // Step 1: Apply gravity to rigid body - Float4 gravityImpulse = Float4::null; - proto->GetState( state ); + this->customBodies[i]->GetState(state); - Float4 deltaPosGrav = Float4( this->gravity[0].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f ); - Float rSquared = deltaPosGrav.Dot( deltaPosGrav ); - if( rSquared != 0.0 ) - { - Float force = 9.82f*10.0f; - gravityImpulse += (this->updateFrameLength*force)*deltaPosGrav.GetNormalized(); - } + btTransform trans; + dynamic_cast(this->customBodies[i])->GetMotionState()->getWorldTransform(trans); + state.centerPos = Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z()); + state.quaternion = Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w()); + - Float posLength = state.GetCenterPosition().GetLength(); - if( gravityImpulse != Float4::null && posLength - 600 > state.GetReach().GetLength() ) - { - state.ApplyLinearImpulse( gravityImpulse.xyz ); - state.SetGravityNormal( gravityImpulse.GetNormalized().xyz ); - proto->SetState( state ); - } - - // Step 2: Step through octree and apply collision responses to rigid body - this->worldScene.Visit( proto, OnPossibleCollision ); + this->customBodies[i]->SetState(state); } - // Go through all rigid bodies and move them according to their momentums - for( unsigned int i = 0; i < updateList.size(); i++ ) + int numManifolds = this->dynamicsWorld->getDispatcher()->getNumManifolds(); + for (int i=0;idynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i); + const btCollisionObject* obA = contactManifold->getBody0(); + const btCollisionObject* obB = contactManifold->getBody1(); - switch( proto->Update(this->updateFrameLength) ) + ICustomBody* bodyA = (ICustomBody*)obA->getUserPointer(); + ICustomBody* bodyB = (ICustomBody*)obB->getUserPointer(); + + dynamic_cast(bodyA)->CallSubsciptMessage(bodyA, bodyB, 0.0f); + dynamic_cast(bodyB)->CallSubsciptMessage(bodyB, bodyA, 0.0f); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jworldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(proto) ); - proto->CallSubscription_Move(); - case UpdateState_resting: - default: - break; + btManifoldPoint& pt = contactManifold->getContactPoint(j); + if (pt.getDistance()<0.f) + { + const btVector3& ptA = pt.getPositionWorldOnA(); + const btVector3& ptB = pt.getPositionWorldOnB(); + const btVector3& normalOnB = pt.m_normalWorldOnB; + } } } + } +void API_Impl::Init() +{ + this->broadphase = new btDbvtBroadphase(); + this->collisionConfiguration = new btDefaultCollisionConfiguration(); + this->dispatcher = new btCollisionDispatcher(this->collisionConfiguration); + this->solver = new btSequentialImpulseConstraintSolver; + this->dynamicsWorld = new btDiscreteDynamicsWorld(this->dispatcher,this->broadphase,this->solver,this->collisionConfiguration); + this->dynamicsWorld->setGravity(btVector3(0,-10,0)); +} + + bool API_Impl::IsInLimbo( const ICustomBody* objRef ) { - return this->worldScene.IsInLimbo( objRef ); + return true; } void API_Impl::MoveToLimbo( const ICustomBody* objRef ) { - this->worldScene.MoveToLimbo( objRef ); + } + void API_Impl::ReleaseFromLimbo( const ICustomBody* objRef ) { - this->worldScene.ReleaseFromLimbo( objRef ); -} - -void API_Impl::AddObject( ::Utility::DynamicMemory::UniquePointer handle ) -{ - this->worldScene.AddObject( handle ); -} - -UniquePointer API_Impl::ExtractObject( const ICustomBody* objRef ) -{ - return this->worldScene.Extract( objRef ); -} - -void API_Impl::DestroyObject( const ICustomBody* objRef ) -{ - UniquePointer object = this->worldScene.Extract( objRef ); - if( object ) - { - this->destructionAction( object ); - } -} - -void API_Impl::AddGravity( const API::Gravity &g ) -{ - this->gravity.push_back( g ); -} - -void API_Impl::RemoveGravity( const API::Gravity &g ) -{ - for( ::std::vector::size_type i = this->gravity.size() - 1; i >= 0; --i ) - { - if( g == this->gravity[i] ) - { - int end = this->gravity.size() - 1; - this->gravity[i] = this->gravity[end]; - this->gravity.resize( end ); - } - } + } void API_Impl::ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) ) { - this->worldScene.Visit(collideable, args, hitAction); + } -//void API_Impl::ApplyForceAt( const ICustomBody* objRef, const Float3 &worldPos, const Float3 &worldF ) -//{ -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// //this->worldScene.GetCustomBody( tempRef )->Apply //!< @todo TODO: need function -// this->worldScene.SetAsAltered( tempRef ); -// } -//} -// -//void API_Impl::SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const Float4x4 &localI ) -//{ // deprecated -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepVelocity( localI ); -// } -//} -// -//void API_Impl::SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const Float4x4 &localI ) -//{ // deprecated -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepMomentum( localI ); -// } -//} -// -//void API_Impl::SetMass_KeepVelocity( const ICustomBody* objRef, Float m ) -//{ // deprecated -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepVelocity( m ); -// } -//} -// -//void API_Impl::SetMass_KeepMomentum( const ICustomBody* objRef, Float m ) -//{ // deprecated -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepMomentum( m ); -// } -//} -// -//void API_Impl::SetCenter( const ICustomBody* objRef, const Float3 &worldPos ) -//{ -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// //this->worldScene.GetCustomBody( tempRef )->Set //!< @todo TODO: need function -// this->worldScene.EvaluatePosition( tempRef ); -// } -//} -// -//void API_Impl::SetRotation( const ICustomBody* objRef, const Float4x4 &rotation ) -//{ -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetRotation( rotation ); -// this->worldScene.EvaluatePosition( tempRef ); -// } -//} -// -//void API_Impl::SetOrientation( const ICustomBody* objRef, const Float4x4 &orientation ) -//{ -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetOrientation( orientation ); -// this->worldScene.EvaluatePosition( tempRef ); -// } -//} -// -//void API_Impl::SetSize( const ICustomBody* objRef, const Float3 &size ) -//{ -// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef ); -// if( tempRef != this->worldScene.invalid_ref ) -// { -// this->worldScene.GetCustomBody( tempRef )->SetSize( size ); -// this->worldScene.EvaluatePosition( tempRef ); -// } -//} - -UniquePointer API_Impl::CreateRigidBody( const API::SimpleBodyDescription &desc ) const -{ - return new SimpleRigidBody( desc ); -} - -UniquePointer API_Impl::CreateRigidBody( const API::SphericalBodyDescription &desc ) const -{ - return new SphericalRigidBody( desc ); -} - -namespace Oyster { namespace Physics -{ - namespace Default +namespace Oyster +{ + namespace Physics { - void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto ) - { /* Do nothing except allowing the proto uniquePointer destroy itself. */ } + namespace Default + { + void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto ) + { /* Do nothing except allowing the proto uniquePointer destroy itself. */ } - ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_BeforeCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter ) - { /* Do nothing except returning business as usual. */ - return ::Oyster::Physics::ICustomBody::SubscriptMessage_none; + ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_BeforeCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter ) + { /* Do nothing except returning business as usual. */ + return ::Oyster::Physics::ICustomBody::SubscriptMessage_none; + } + + void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ) + { /* Do nothing except returning business as usual. */ + + } + + void EventAction_Move( const ::Oyster::Physics::ICustomBody *object ) + { /* Do nothing. */ } } - - void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ) - { /* Do nothing except returning business as usual. */ - - } - - void EventAction_Move( const ::Oyster::Physics::ICustomBody *object ) - { /* Do nothing. */ } - } -} } \ No newline at end of file + } +} \ No newline at end of file diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 21460944..03d1d3c6 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -3,6 +3,7 @@ #include "../PhysicsAPI.h" #include "Octree.h" +#include namespace Oyster { @@ -14,49 +15,27 @@ namespace Oyster API_Impl(); virtual ~API_Impl(); - void Init( unsigned int numObjects, unsigned int numGravityWells , const ::Oyster::Math::Float3 &worldSize ); - - void SetFrameTimeLength( float deltaTime ); - void SetGravityConstant( float g ); - void SetEpsilon( float e ); - void SetSubscription( EventAction_Destruction functionPointer ); - - float GetFrameTimeLength() const; - - void Update(); + void Init(); bool IsInLimbo( const ICustomBody* objRef ); void MoveToLimbo( const ICustomBody* objRef ); void ReleaseFromLimbo( const ICustomBody* objRef ); - void AddObject( ::Utility::DynamicMemory::UniquePointer handle ); - ::Utility::DynamicMemory::UniquePointer ExtractObject( const ICustomBody* objRef ); - void DestroyObject( const ICustomBody* objRef ); + // Bullet physics + ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass); + ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass); - void AddGravity( const API::Gravity &g ); - void RemoveGravity( const API::Gravity &g ); + void UpdateWorld(); void ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) ); - //void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF ); - - //void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ); - //void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ); - //void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m ); - //void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m ); - //void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos ); - //void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation ); - //void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation ); - //void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size ); - - ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const; - ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const; - private: - ::Oyster::Math::Float gravityConstant, updateFrameLength, epsilon; - EventAction_Destruction destructionAction; - ::std::vector gravity; - Octree worldScene; + btBroadphaseInterface* broadphase; + btDefaultCollisionConfiguration* collisionConfiguration; + btCollisionDispatcher* dispatcher; + btSequentialImpulseConstraintSolver* solver; + btDiscreteDynamicsWorld* dynamicsWorld; + std::vector customBodies; }; namespace Default diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 68759398..ca18dc1c 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -8,296 +8,87 @@ using namespace ::Oyster::Collision3D; using namespace ::Utility::DynamicMemory; using namespace ::Utility::Value; -namespace Private -{ - const Float epsilon = (const Float)1e-20; - - // Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture - inline bool EqualsZero( const Float &value ) - { // by Dan Andersson - return Abs( value ) < epsilon; - } - - inline bool Contains( const Plane &container, const Float4 &pos ) - { // by Dan Andersson - return EqualsZero( container.normal.Dot( pos ) + container.phasing ); - } - - // revision of Ray Vs Plane intersect test, there ray is more of an axis - bool Intersects( const Ray &axis, const Plane &plane, Float &connectDistance ) - { // by Dan Andersson - Float c = plane.normal.Dot(axis.direction); - if( EqualsZero(c) ) - { // axis is parallell with the plane. (axis direction orthogonal with the planar normal) - connectDistance = 0.0f; - return Contains( plane, axis.origin ); - } - - connectDistance = -plane.phasing; - connectDistance -= plane.normal.Dot( axis.origin ); - connectDistance /= c; - - return true; - } -} - SimpleRigidBody::SimpleRigidBody() { - this->rigid = RigidBody(); - this->rigid.SetMass_KeepMomentum( 16.0f ); - this->gravityNormal = Float3::null; - this->onCollision = Default::EventAction_BeforeCollisionResponse; - this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; - this->onMovement = Default::EventAction_Move; - - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - this->collisionRebound.timeOfContact = 1.0f; + this->collisionShape = NULL; + this->motionState = NULL; + this->rigidBody = NULL; + + this->state.centerPos = Float3(0.0f, 0.0f, 0.0f); + this->state.quaternion = Quaternion(Float3(0.0f, 0.0f, 0.0f), 1.0f); + this->state.dynamicFrictionCoeff = 0.0f; + this->state.staticFrictionCoeff = 0.0f; + this->state.mass = 0.0f; + this->state.restitutionCoeff = 0.0f; + this->state.reach = Float3(0.0f, 0.0f, 0.0f); - this->scene = nullptr; this->customTag = nullptr; - this->ignoreGravity = this->isForwarded = false; } SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) { - this->rigid = RigidBody(); - this->rigid.SetRotation( desc.rotation ); - this->rigid.centerPos = desc.centerPosition; - this->rigid.SetSize( desc.size ); - this->rigid.restitutionCoeff = desc.restitutionCoeff; - this->rigid.frictionCoeff_Static = desc.frictionCoeff_Static; - this->rigid.frictionCoeff_Kinetic = desc.frictionCoeff_Dynamic; - this->rigid.SetMass_KeepMomentum( desc.mass ); - this->rigid.SetMomentOfInertia_KeepMomentum( desc.inertiaTensor ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; + this->collisionShape = NULL; + this->motionState = NULL; + this->rigidBody = NULL; - this->gravityNormal = Float3::null; - - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - this->collisionRebound.timeOfContact = 1.0f; - - if( desc.subscription_onCollision ) - { - this->onCollision = desc.subscription_onCollision; - } - else - { - this->onCollision = Default::EventAction_BeforeCollisionResponse; - } - - if( desc.subscription_onCollisionResponse ) - { - this->onCollisionResponse = desc.subscription_onCollisionResponse; - } - else - { - this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; - } - - if( desc.subscription_onMovement ) - { - this->onMovement= desc.subscription_onMovement; - } - else - { - this->onMovement = Default::EventAction_Move; - } - - this->scene = nullptr; this->customTag = nullptr; - this->ignoreGravity = desc.ignoreGravity; - - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - this->collisionRebound.timeOfContact = 1.0f; } -SimpleRigidBody::~SimpleRigidBody() {} - -UniquePointer SimpleRigidBody::Clone() const +SimpleRigidBody::~SimpleRigidBody() { - return new SimpleRigidBody( *this ); + delete this->motionState; + this->motionState = NULL; + delete this->collisionShape; + this->collisionShape = NULL; + delete this->rigidBody; + this->rigidBody = NULL; +} + +void SimpleRigidBody::SetCollisionShape(btCollisionShape* shape) +{ + this->collisionShape = shape; +} + +void SimpleRigidBody::SetMotionState(btDefaultMotionState* motionState) +{ + this->motionState = motionState; +} + +void SimpleRigidBody::SetRigidBody(btRigidBody* rigidBody) +{ + this->rigidBody = rigidBody; + +} + +void SimpleRigidBody::SetSubscription(EventAction_AfterCollisionResponse function) +{ + this->afterCollision = function; +} + +void SimpleRigidBody::CallSubsciptMessage(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) +{ + this->CallSubsciptMessage(bodyA, bodyB, kineticEnergyLoss); +} + +btDefaultMotionState* SimpleRigidBody::GetMotionState() const +{ + return this->motionState; } SimpleRigidBody::State SimpleRigidBody::GetState() const { - return State( this->rigid.GetMass(), this->rigid.restitutionCoeff, - this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic, - this->rigid.GetMomentOfInertia(), this->rigid.boundingReach, - this->rigid.centerPos, this->rigid.axis, - this->rigid.momentum_Linear, this->rigid.momentum_Angular, - this->rigid.gravityNormal ); + return this->state; } SimpleRigidBody::State & SimpleRigidBody::GetState( SimpleRigidBody::State &targetMem ) const { - return targetMem = State( this->rigid.GetMass(), this->rigid.restitutionCoeff, - this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic, - this->rigid.GetMomentOfInertia(), this->rigid.boundingReach, - this->rigid.centerPos, this->rigid.axis, - this->rigid.momentum_Linear, this->rigid.momentum_Angular, - this->rigid.gravityNormal ); + targetMem = this->state; + return targetMem; } void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) { - this->rigid.centerPos = state.GetCenterPosition(); - this->rigid.axis = state.GetAngularAxis(); - this->rigid.boundingReach = state.GetReach(); - this->rigid.momentum_Linear = state.GetLinearMomentum(); - this->rigid.momentum_Angular = state.GetAngularMomentum(); - this->rigid.impulse_Linear += state.GetLinearImpulse(); - this->rigid.impulse_Angular += state.GetAngularImpulse(); - this->rigid.restitutionCoeff = state.GetRestitutionCoeff(); - this->rigid.frictionCoeff_Static = state.GetFrictionCoeff_Static(); - this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic(); - this->rigid.SetMass_KeepMomentum( state.GetMass() ); - this->rigid.SetMomentOfInertia_KeepMomentum( state.GetMomentOfInertia() ); - this->rigid.gravityNormal = state.GetGravityNormal(); - - if( state.IsForwarded() ) - { - this->deltaPos += Float4(state.GetForward_DeltaPos(), 0); - this->deltaAxis += Float4(state.GetForward_DeltaAxis(), 0); - this->isForwarded; - } - - if( this->scene ) - { - if( state.IsSpatiallyAltered() ) - { - unsigned int tempRef = this->scene->GetTemporaryReferenceOf( this ); - this->scene->SetAsAltered( tempRef ); - this->scene->EvaluatePosition( tempRef ); - } - else if( state.IsDisturbed() ) - { - this->scene->SetAsAltered( this->scene->GetTemporaryReferenceOf(this) ); - } - } -} - -ICustomBody::SubscriptMessage SimpleRigidBody::CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter ) -{ - return this->onCollision( this, deuter ); -} - -void SimpleRigidBody::CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, Float kineticEnergyLoss ) -{ - return this->onCollisionResponse( this, deuter, kineticEnergyLoss ); -} - -void SimpleRigidBody::CallSubscription_Move() -{ - this->onMovement( this ); -} - -bool SimpleRigidBody::IsAffectedByGravity() const -{ - return !this->ignoreGravity; -} - -bool SimpleRigidBody::Intersects( const ICollideable &shape ) const -{ - return Box( this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize() ).Intersects( shape ); -} - -bool SimpleRigidBody::Intersects( const ICollideable &shape, Float4 &worldPointOfContact ) const -{ - return Box( this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize() ).Intersects( shape, worldPointOfContact ); -} - -bool SimpleRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointOfContact ) const -{ - return object.Intersects( Box(this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize()), worldPointOfContact ); -} - -void SimpleRigidBody::SetTimeOfContact( Float4 &worldPointOfContact ) -{ - Point pointOfContact = Point( worldPointOfContact ); - Box start = Box(); - { - start.rotation = RotationMatrix( this->collisionRebound.previousSpatial.axis ); - start.center = this->collisionRebound.previousSpatial.center; - start.boundingOffset = this->collisionRebound.previousSpatial.reach; - } - Box end = Box(); - { - end.rotation = RotationMatrix( this->rigid.axis ); - end.center = this->rigid.centerPos; - end.boundingOffset = this->rigid.boundingReach; - } - Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact ); - - this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact ); -} - -Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const -{ - return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() ); -} - -Float4 & SimpleRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem ) const -{ - Float4 offset = worldPos.xyz - this->rigid.centerPos; - Float distance = offset.Dot( offset ); - Float3 normal = Float3::null; - - if( distance != 0.0f ) - { // sanity check - Ray axis( Float4::standard_unit_w, offset / (Float)::std::sqrt(distance) ); - Float minDistance = numeric_limits::max(); - Float4x4 rotationMatrix = this->rigid.GetRotationMatrix(); - - if( Private::Intersects(axis, Plane(rotationMatrix.v[0], -this->rigid.boundingReach.x), axis.collisionDistance) ) - { // check along x-axis - if( axis.collisionDistance < 0.0f ) - normal = -rotationMatrix.v[0].xyz; - else - normal = rotationMatrix.v[0].xyz; - - minDistance = Abs( axis.collisionDistance ); - } - - if( Private::Intersects(axis, Plane(rotationMatrix.v[1], -this->rigid.boundingReach.y), axis.collisionDistance) ) - { // check along y-axis - distance = Abs( axis.collisionDistance ); // recycling memory - if( minDistance > distance ) - { - if( axis.collisionDistance < 0.0f ) - normal = -rotationMatrix.v[1].xyz; - else - normal = rotationMatrix.v[1].xyz; - - minDistance = distance; - } - } - - if( Private::Intersects(axis, Plane(rotationMatrix.v[2], -this->rigid.boundingReach.z), axis.collisionDistance) ) - { // check along z-axis - if( minDistance > Abs( axis.collisionDistance ) ) - { - if( axis.collisionDistance < 0.0f ) - normal = -rotationMatrix.v[2].xyz; - else - normal = rotationMatrix.v[2].xyz; - } - } - } - targetMem.xyz = normal; - targetMem.w = 0.0f; - return targetMem; -} - -Float3 & SimpleRigidBody::GetGravityNormal( Float3 &targetMem ) const -{ - return targetMem = this->gravityNormal; + this->state = state; } void * SimpleRigidBody::GetCustomTag() const @@ -305,182 +96,10 @@ void * SimpleRigidBody::GetCustomTag() const return this->customTag; } -//Float3 & SimpleRigidBody::GetCenter( Float3 &targetMem ) const -//{ -// return targetMem = this->rigid.centerPos; -//} -// -//Float4x4 & SimpleRigidBody::GetRotation( Float4x4 &targetMem ) const -//{ -// return targetMem = this->rigid.box.rotation; -//} -// -//Float4x4 & SimpleRigidBody::GetOrientation( Float4x4 &targetMem ) const -//{ -// return targetMem = this->rigid.GetOrientation(); -//} -// -//Float4x4 & SimpleRigidBody::GetView( Float4x4 &targetMem ) const -//{ -// return targetMem = this->rigid.GetView(); -//} - -//Float3 SimpleRigidBody::GetRigidLinearVelocity() const -//{ -// return this->rigid.GetLinearVelocity(); -//} - -UpdateState SimpleRigidBody::Update( Float timeStepLength ) -{ - if( this->collisionRebound.timeOfContact < 1.0f ) - { // Rebound if needed - this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact ); - this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) ); - this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact ); - timeStepLength *= 2.0f - this->collisionRebound.timeOfContact; // compensate for rebounded time - this->collisionRebound.timeOfContact = 1.0f; - } - - // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) - Float4 temp; - ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz ); - this->rigid.axis -= ((2.0f * pi) * temp).xyz; - - // Update rebound data - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - - // Check if this is close enough to be set resting - temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f ); - if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) ) - { - unsigned char resting = 0; - if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) ) - { - this->rigid.momentum_Linear = Float3::null; - resting = 1; - } - if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) ) - { - this->rigid.momentum_Angular = Float3::null; - ++resting; - } - if( resting == 2 ) - { - this->rigid.impulse_Linear = this->rigid.impulse_Angular = Float3::null; - return UpdateState_resting; - } - } - - this->rigid.Update_LeapFrog( timeStepLength ); - return UpdateState_altered; -} - -void SimpleRigidBody::Predict( Float4 &outDeltaPos, Float4 &outDeltaAxis, const Float4 &actingLinearImpulse, const Float4 &actingAngularImpulse, Float deltaTime ) -{ - this->rigid.Predict_LeapFrog( outDeltaPos.xyz, outDeltaAxis.xyz, actingLinearImpulse.xyz, actingAngularImpulse.xyz, deltaTime ); -} - -void SimpleRigidBody::SetScene( void *scene ) -{ - this->scene = (Octree*)scene; -} - -void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_BeforeCollisionResponse functionPointer ) -{ - if( functionPointer ) - { - this->onCollision = functionPointer; - } - else - { - this->onCollision = Default::EventAction_BeforeCollisionResponse; - } -} - -void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_AfterCollisionResponse functionPointer ) -{ - if( functionPointer ) - { - this->onCollisionResponse = functionPointer; - } - else - { - this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; - } -} - -void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Move functionPointer ) -{ - if( functionPointer ) - { - this->onMovement = functionPointer; - } - else - { - this->onMovement = Default::EventAction_Move; - } -} - -void SimpleRigidBody::SetGravity( bool ignore) -{ - this->ignoreGravity = ignore; - this->gravityNormal = Float3::null; -} - -void SimpleRigidBody::SetGravityNormal( const Float3 &normalizedVector ) -{ - this->gravityNormal = normalizedVector; - this->rigid.gravityNormal = Float4( this->gravityNormal, 0 ); -} void SimpleRigidBody::SetCustomTag( void *ref ) { this->customTag = ref; } -//void SimpleRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI ) -//{ -// this->rigid.SetMomentOfInertia_KeepVelocity( localI ); -//} -// -//void SimpleRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI ) -//{ -// this->rigid.SetMomentOfInertia_KeepMomentum( localI ); -//} -// -//void SimpleRigidBody::SetMass_KeepVelocity( Float m ) -//{ -// this->rigid.SetMass_KeepVelocity( m ); -//} -// -//void SimpleRigidBody::SetMass_KeepMomentum( Float m ) -//{ -// this->rigid.SetMass_KeepMomentum( m ); -//} -// -//void SimpleRigidBody::SetCenter( const Float3 &worldPos ) -//{ -// this->rigid.SetCenter( worldPos ); -//} -// -//void SimpleRigidBody::SetRotation( const Float4x4 &rotation ) -//{ -// this->rigid.SetRotation( rotation ); -//} -// -//void SimpleRigidBody::SetOrientation( const Float4x4 &orientation ) -//{ -// this->rigid.SetOrientation( orientation ); -//} -// -//void SimpleRigidBody::SetSize( const Float3 &size ) -//{ -// this->rigid.SetSize( size ); -//} -// -//void SimpleRigidBody::SetMomentum( const Float3 &worldG ) -//{ -// this->rigid.SetLinearMomentum( worldG ); -//} + diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 1811c911..1b699e9a 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -2,8 +2,7 @@ #define OYSTER_PHYSICS_SIMPLE_RIGIDBODY_H #include "..\PhysicsAPI.h" -#include "RigidBody.h" -#include "Octree.h" +#include namespace Oyster { namespace Physics { @@ -14,73 +13,32 @@ namespace Oyster { namespace Physics SimpleRigidBody( const API::SimpleBodyDescription &desc ); virtual ~SimpleRigidBody(); - ::Utility::DynamicMemory::UniquePointer Clone() const; + void SetCollisionShape(btCollisionShape* shape); + void SetMotionState(btDefaultMotionState* motionState); + void SetRigidBody(btRigidBody* rigidBody); + void SetSubscription(EventAction_AfterCollisionResponse function); + void CallSubsciptMessage(ICustomBody* bodyA, ICustomBody* bodyB, Math::Float kineticEnergyLoss); + State GetState() const; State & GetState( State &targetMem ) const; void SetState( const State &state ); - //::Oyster::Math::Float3 GetRigidLinearVelocity() const; - SubscriptMessage CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter ); - void CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ); - void CallSubscription_Move(); + btDefaultMotionState* GetMotionState() const; - bool IsAffectedByGravity() const; - bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const; - bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; - bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const; - - void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ); - - ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; - ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const; - ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; - void * GetCustomTag() const; - //::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; - //::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; - //::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; - //::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; - - UpdateState Update( ::Oyster::Math::Float timeStepLength ); - void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ); - - void SetScene( void *scene ); - - void SetSubscription( EventAction_BeforeCollisionResponse functionPointer ); - void SetSubscription( EventAction_AfterCollisionResponse functionPointer ); - void SetSubscription( EventAction_Move functionPointer ); - - void SetGravity( bool ignore); - void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ); void SetCustomTag( void *ref ); - //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ); - //void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ); - //void SetMass_KeepVelocity( ::Oyster::Math::Float m ); - //void SetMass_KeepMomentum( ::Oyster::Math::Float m ); - //void SetCenter( const ::Oyster::Math::Float3 &worldPos ); - //void SetRotation( const ::Oyster::Math::Float4x4 &rotation ); - //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ); - //void SetSize( const ::Oyster::Math::Float3 &size ); - //void SetMomentum( const ::Oyster::Math::Float3 &worldG ); + void* GetCustomTag() const; private: - ::Oyster::Physics3D::RigidBody rigid; - ::Oyster::Math::Float4 deltaPos, deltaAxis; - ::Oyster::Math::Float3 gravityNormal; + btCollisionShape* collisionShape; + btDefaultMotionState* motionState; + btRigidBody* rigidBody; - struct - { - struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial; - ::Oyster::Math::Float timeOfContact; - } collisionRebound; + Struct::CustomBodyState state; - EventAction_BeforeCollisionResponse onCollision; - EventAction_AfterCollisionResponse onCollisionResponse; - EventAction_Move onMovement; + EventAction_AfterCollisionResponse afterCollision; - Octree *scene; void *customTag; - bool ignoreGravity, isForwarded; }; } } diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp index b27d3a78..e69de29b 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp @@ -1,408 +0,0 @@ -#include "SphericalRigidBody.h" -#include "PhysicsAPI_Impl.h" - -using namespace ::Oyster::Physics; -using namespace ::Oyster::Physics3D; -using namespace ::Oyster::Math3D; -using namespace ::Oyster::Collision3D; -using namespace ::Utility::DynamicMemory; -using namespace ::Utility::Value; - -SphericalRigidBody::SphericalRigidBody() -{ - this->rigid = RigidBody(); - this->rigid.SetMass_KeepMomentum( 16.0f ); - this->gravityNormal = Float3::null; - this->onCollision = Default::EventAction_BeforeCollisionResponse; - this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; - this->onMovement = Default::EventAction_Move; - - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - this->collisionRebound.timeOfContact = 1.0f; - - this->scene = nullptr; - this->customTag = nullptr; - this->ignoreGravity = this->isForwarded = false; -} - -SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc ) -{ - this->rigid = RigidBody(); - this->rigid.SetRotation( desc.rotation ); - this->rigid.centerPos = desc.centerPosition; - this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f ); - this->rigid.restitutionCoeff = desc.restitutionCoeff; - this->rigid.frictionCoeff_Static = desc.frictionCoeff_Static; - this->rigid.frictionCoeff_Kinetic = desc.frictionCoeff_Dynamic; - this->rigid.SetMass_KeepMomentum( desc.mass ); - this->rigid.SetMomentOfInertia_KeepMomentum( MomentOfInertia::Sphere(desc.mass, desc.radius) ); - this->deltaPos = Float4::null; - this->deltaAxis = Float4::null; - - this->gravityNormal = Float3::null; - - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - this->collisionRebound.timeOfContact = 1.0f; - - if( desc.subscription_onCollision ) - { - this->onCollision = desc.subscription_onCollision; - } - else - { - this->onCollision = Default::EventAction_BeforeCollisionResponse; - } - - if( desc.subscription_onCollisionResponse ) - { - this->onCollisionResponse = desc.subscription_onCollisionResponse; - } - else - { - this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; - } - - if( desc.subscription_onMovement ) - { - this->onMovement= desc.subscription_onMovement; - } - else - { - this->onMovement = Default::EventAction_Move; - } - - this->scene = nullptr; - this->customTag = nullptr; - this->ignoreGravity = desc.ignoreGravity; - - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - this->collisionRebound.timeOfContact = 1.0f; -} - -SphericalRigidBody::~SphericalRigidBody() {} - -UniquePointer SphericalRigidBody::Clone() const -{ - return new SphericalRigidBody( *this ); -} - -SphericalRigidBody::State SphericalRigidBody::GetState() const -{ - return State( this->rigid.GetMass(), this->rigid.restitutionCoeff, - this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic, - this->rigid.GetMomentOfInertia(), this->rigid.boundingReach, - this->rigid.centerPos, this->rigid.axis, - this->rigid.momentum_Linear, this->rigid.momentum_Angular, - this->gravityNormal ); -} - -SphericalRigidBody::State & SphericalRigidBody::GetState( SphericalRigidBody::State &targetMem ) const -{ - return targetMem = State( this->rigid.GetMass(), this->rigid.restitutionCoeff, - this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic, - this->rigid.GetMomentOfInertia(), this->rigid.boundingReach, - this->rigid.centerPos, this->rigid.axis, - this->rigid.momentum_Linear, this->rigid.momentum_Angular, - this->gravityNormal ); -} - -void SphericalRigidBody::SetState( const SphericalRigidBody::State &state ) -{ - this->rigid.centerPos = state.GetCenterPosition(); - this->rigid.axis = state.GetAngularAxis(); - this->rigid.boundingReach = state.GetReach(); - this->rigid.momentum_Linear = state.GetLinearMomentum(); - this->rigid.momentum_Angular = state.GetAngularMomentum(); - this->rigid.impulse_Linear += state.GetLinearImpulse(); - this->rigid.impulse_Angular += state.GetAngularImpulse(); - this->rigid.restitutionCoeff = state.GetRestitutionCoeff(); - this->rigid.frictionCoeff_Static = state.GetFrictionCoeff_Static(); - this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic(); - this->rigid.SetMass_KeepMomentum( state.GetMass() ); - this->rigid.SetMomentOfInertia_KeepMomentum( state.GetMomentOfInertia() ); - this->rigid.gravityNormal = state.GetGravityNormal(); - - if( state.IsForwarded() ) - { - this->deltaPos += Float4(state.GetForward_DeltaPos(), 0); - this->deltaAxis += Float4(state.GetForward_DeltaAxis()); - this->isForwarded = false; - } - - if( this->scene ) - { - if( state.IsSpatiallyAltered() ) - { - unsigned int tempRef = this->scene->GetTemporaryReferenceOf( this ); - this->scene->SetAsAltered( tempRef ); - this->scene->EvaluatePosition( tempRef ); - } - else if( state.IsDisturbed() ) - { - this->scene->SetAsAltered( this->scene->GetTemporaryReferenceOf(this) ); - } - } -} - -ICustomBody::SubscriptMessage SphericalRigidBody::CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter ) -{ - return this->onCollision( this, deuter ); -} - -void SphericalRigidBody::CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, Float kineticEnergyLoss ) -{ - this->onCollisionResponse( this, deuter, kineticEnergyLoss); -} - - -void SphericalRigidBody::CallSubscription_Move() -{ - this->onMovement( this ); -} - -bool SphericalRigidBody::IsAffectedByGravity() const -{ - return !this->ignoreGravity; -} - -bool SphericalRigidBody::Intersects( const ICollideable &shape ) const -{ - return Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ).Intersects( shape ); -} - -bool SphericalRigidBody::Intersects( const ICollideable &shape, Float4 &worldPointOfContact ) const -{ - return Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ).Intersects( shape, worldPointOfContact ); -} - -bool SphericalRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointOfContact ) const -{ - return object.Intersects( Sphere(this->rigid.centerPos, this->rigid.boundingReach.x), worldPointOfContact ); -} - -void SphericalRigidBody::SetTimeOfContact( Float4 &worldPointOfContact ) -{ - Point pointOfContact = Point( worldPointOfContact ); - Sphere start = Sphere( this->collisionRebound.previousSpatial.center, this->collisionRebound.previousSpatial.reach.x ); - Sphere end = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); - - Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact ); - - this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact ); -} - -Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const -{ - return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ); -} - -Float4 & SphericalRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem ) const -{ - targetMem = Float4( worldPos.xyz - this->rigid.centerPos, 0); - Float magnitude = targetMem.GetMagnitude(); - if( magnitude != 0.0f ) - { // sanity check - targetMem.Normalize(); - } - - return targetMem; -} - -Float3 & SphericalRigidBody::GetGravityNormal( Float3 &targetMem ) const -{ - return targetMem = this->gravityNormal; -} - -void * SphericalRigidBody::GetCustomTag() const -{ - return this->customTag; -} - -//Float3 & SphericalRigidBody::GetCenter( Float3 &targetMem ) const -//{ -// return targetMem = this->rigid.centerPos; -//} -// -//Float4x4 & SphericalRigidBody::GetRotation( Float4x4 &targetMem ) const -//{ -// return targetMem = this->rigid.box.rotation; -//} -// -//Float4x4 & SphericalRigidBody::GetOrientation( Float4x4 &targetMem ) const -//{ -// return targetMem = this->rigid.GetOrientation(); -//} -// -//Float4x4 & SphericalRigidBody::GetView( Float4x4 &targetMem ) const -//{ -// return targetMem = this->rigid.GetView(); -//} - -//Float3 SphericalRigidBody::GetRigidLinearVelocity() const -//{ -// return this->rigid.GetLinearVelocity(); -//} - -UpdateState SphericalRigidBody::Update( Float timeStepLength ) -{ - if( this->collisionRebound.timeOfContact < 1.0f ) - { // Rebound if needed - this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact ); - this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) ); - this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact ); - timeStepLength *= 2.0f - this->collisionRebound.timeOfContact; // compensate for rebounded time - this->collisionRebound.timeOfContact = 1.0f; - } - - // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too) - Float4 temp; - ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz ); - this->rigid.axis -= ((2.0f * pi) * temp).xyz; - - // Update rebound data - this->collisionRebound.previousSpatial.center = this->rigid.centerPos; - this->collisionRebound.previousSpatial.axis = this->rigid.axis; - this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach; - - // Check if this is close enough to be set resting - temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f ); - if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) ) - { - unsigned char resting = 0; - if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) ) - { - this->rigid.momentum_Linear = Float3::null; - resting = 1; - } - if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) ) - { - this->rigid.momentum_Angular = Float3::null; - ++resting; - } - if( resting == 2 ) - { - this->rigid.impulse_Linear = this->rigid.impulse_Angular = Float3::null; - return UpdateState_resting; - } - } - - this->rigid.Update_LeapFrog( timeStepLength ); - return UpdateState_altered; -} - -void SphericalRigidBody::Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ) -{ - this->rigid.Predict_LeapFrog( outDeltaPos.xyz, outDeltaAxis.xyz, actingLinearImpulse.xyz, actingAngularImpulse.xyz, deltaTime ); -} - -void SphericalRigidBody::SetScene( void *scene ) -{ - this->scene = (Octree*)scene; -} - -void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_BeforeCollisionResponse functionPointer ) -{ - if( functionPointer ) - { - this->onCollision = functionPointer; - } - else - { - this->onCollision = Default::EventAction_BeforeCollisionResponse; - } -} - -void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_AfterCollisionResponse functionPointer ) -{ - if( functionPointer ) - { - this->onCollisionResponse = functionPointer; - } - else - { - this->onCollisionResponse = Default::EventAction_AfterCollisionResponse; - } -} - -void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Move functionPointer ) -{ - if( functionPointer ) - { - this->onMovement = functionPointer; - } - else - { - this->onMovement = Default::EventAction_Move; - } -} - -void SphericalRigidBody::SetGravity( bool ignore ) -{ - this->ignoreGravity = ignore; - this->gravityNormal = Float3::null; -} - -void SphericalRigidBody::SetGravityNormal( const Float3 &normalizedVector ) -{ - this->gravityNormal = normalizedVector; - this->rigid.gravityNormal = Float4( this->gravityNormal, 0 ); -} - -void SphericalRigidBody::SetCustomTag( void *ref ) -{ - this->customTag = ref; -} - -//void SphericalRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI ) -//{ -// this->rigid.SetMomentOfInertia_KeepVelocity( localI ); -//} -// -//void SphericalRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI ) -//{ -// this->rigid.SetMomentOfInertia_KeepMomentum( localI ); -//} -// -//void SphericalRigidBody::SetMass_KeepVelocity( Float m ) -//{ -// this->rigid.SetMass_KeepVelocity( m ); -//} -// -//void SphericalRigidBody::SetMass_KeepMomentum( Float m ) -//{ -// this->rigid.SetMass_KeepMomentum( m ); -//} -// -//void SphericalRigidBody::SetCenter( const Float3 &worldPos ) -//{ -// this->rigid.SetCenter( worldPos ); -// this->body.center = worldPos; -//} -// -//void SphericalRigidBody::SetRotation( const Float4x4 &rotation ) -//{ -// this->rigid.SetRotation( rotation ); -//} -// -//void SphericalRigidBody::SetOrientation( const Float4x4 &orientation ) -//{ -// this->rigid.SetOrientation( orientation ); -// this->body.center = orientation.v[3].xyz; -//} -// -//void SphericalRigidBody::SetSize( const Float3 &size ) -//{ -// this->rigid.SetSize( size ); -// this->body.radius = 0.5f * Min( Min( size.x, size.y ), size.z ); // inline Min( FloatN )? -//} -// -//void SphericalRigidBody::SetMomentum( const Float3 &worldG ) -//{ -// this->rigid.SetLinearMomentum( worldG ); -//} diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h index c2dc8131..e69de29b 100644 --- a/Code/GamePhysics/Implementation/SphericalRigidBody.h +++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h @@ -1,87 +0,0 @@ -#ifndef OYSTER_PHYSICS_SPHERICAL_RIGIDBODY_H -#define OYSTER_PHYSICS_SPHERICAL_RIGIDBODY_H - -#include "..\PhysicsAPI.h" -#include "RigidBody.h" -#include "Sphere.h" -#include "Octree.h" - -namespace Oyster { namespace Physics -{ - class SphericalRigidBody : public ICustomBody - { - public: - SphericalRigidBody(); - SphericalRigidBody( const API::SphericalBodyDescription &desc ); - virtual ~SphericalRigidBody(); - - ::Utility::DynamicMemory::UniquePointer Clone() const; - - State GetState() const; - State & GetState( State &targetMem = State() ) const; - void SetState( const State &state ); - //::Oyster::Math::Float3 GetRigidLinearVelocity() const; - - SubscriptMessage CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter ); - void CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ); - void CallSubscription_Move(); - - bool IsAffectedByGravity() const; - bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const; - bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const; - bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const; - - void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ); - - ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const; - ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const; - ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; - void * GetCustomTag() const; - //::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const; - //::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; - //::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; - //::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const; - - UpdateState Update( ::Oyster::Math::Float timeStepLength ); - void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ); - - void SetScene( void *scene ); - - void SetSubscription( EventAction_BeforeCollisionResponse functionPointer ); - void SetSubscription( EventAction_AfterCollisionResponse functionPointer ); - void SetSubscription( EventAction_Move functionPointer ); - - void SetGravity( bool ignore); - void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ); - void SetCustomTag( void *ref ); - //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ); - //void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ); - //void SetMass_KeepVelocity( ::Oyster::Math::Float m ); - //void SetMass_KeepMomentum( ::Oyster::Math::Float m ); - //void SetCenter( const ::Oyster::Math::Float3 &worldPos ); - //void SetRotation( const ::Oyster::Math::Float4x4 &rotation ); - //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ); - //void SetSize( const ::Oyster::Math::Float3 &size ); - //void SetMomentum( const ::Oyster::Math::Float3 &worldG ); - - private: - ::Oyster::Physics3D::RigidBody rigid; - ::Oyster::Math::Float4 deltaPos, deltaAxis; - ::Oyster::Math::Float3 gravityNormal; - - struct - { - struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial; - ::Oyster::Math::Float timeOfContact; - } collisionRebound; - - EventAction_BeforeCollisionResponse onCollision; - EventAction_AfterCollisionResponse onCollisionResponse; - EventAction_Move onMovement; - Octree *scene; - void *customTag; - bool ignoreGravity, isForwarded; - }; -} } - -#endif \ No newline at end of file diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index c3efef3e..9af0e256 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -55,35 +55,7 @@ namespace Oyster * @param numGravityWells: The predicted max number of active gravity wells. * @param worldSize: The size of acceptable physics space. ********************************************************/ - virtual void Init( unsigned int numObjects, unsigned int numGravityWells , const ::Oyster::Math::Float3 &worldSize ) = 0; - - /******************************************************** - * Sets the time length of each physics update frame. - ********************************************************/ - virtual void SetFrameTimeLength( float seconds ) = 0; - - /******************************************************** - * Sets the Gravityconstant in the physics that will be - * used in ForceField calculations. - * @param g: Default is the real world Constant::gravity_constant [N(m/kg)^2] - ********************************************************/ - virtual void SetGravityConstant( float g ) = 0; - - /******************************************************** - * Sets the function that will be called by the engine - * whenever an object is being destroyed for some reason. - * - Because DestroyObject(...) were called. - * - Out of memory forced engine to destroy an object. - * @param functionPointer: If NULL, an empty default function will be set. - ********************************************************/ - virtual void SetSubscription( EventAction_Destruction functionPointer ) = 0; - - /******************************************************** - * Triggers the engine to run next update frame. - * All accumulated forces and changes will be consumed. - * EventAction functions might be called. - ********************************************************/ - virtual void Update() = 0; + virtual void Init() = 0; /******************************************************** * An object in limbo state will be ignored during the physics frame Update. @@ -106,36 +78,15 @@ namespace Oyster ********************************************************/ virtual void ReleaseFromLimbo( const ICustomBody* objRef ) = 0; - /******************************************************** - * Introduces a new object into the engine. - * @param handle: A pointer along with the responsibility to delete. - ********************************************************/ - virtual void AddObject( ::Utility::DynamicMemory::UniquePointer handle ) = 0; - /******************************************************** - * Fetches and removes an object from the engine. - * Will not call the provided EventAction_Destruction method. - * @param objRef: A pointer to the ICustomBody representing a physical object. - * @return A pointer along with the responsibility to delete. NULL if faulty objRef. - ********************************************************/ - virtual ::Utility::DynamicMemory::UniquePointer ExtractObject( const ICustomBody* objRef ) = 0; + // Bullet physics + virtual ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) = 0; - /******************************************************** - * Removes an object from the engine. - * Will call the provided EventAction_Destruction method. Not if objRef is faulty. - * @param objRef: A pointer to the ICustomBody representing a physical object. - ********************************************************/ - virtual void DestroyObject( const ICustomBody* objRef ) = 0; + virtual ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) = 0; + + virtual void UpdateWorld() = 0; - /******************************************************** - * TODO: @todo doc - ********************************************************/ - virtual void AddGravity( const API::Gravity &g ) = 0; - /******************************************************** - * TODO: @todo doc - ********************************************************/ - virtual void RemoveGravity( const API::Gravity &g ) = 0; /******************************************************** * Applies an effect to objects that collide with the set volume. @@ -146,88 +97,6 @@ namespace Oyster ********************************************************/ virtual void ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) ) = 0; - ///******************************************************** - // * Apply force on an object. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param worldPos: Relative to the world origo. (Not relative to object) [m] - // * @param worldF: Vector with the direction and magnitude of the force. [N] - // ********************************************************/ - //virtual void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF ) = 0; - - ///******************************************************** - // * Sets the MomentOfInertia tensor matrix of an object without changing it's angular velocity. - // * Noticeable effect: The angular momentum will change. Changing the amount of kinetic energy. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace. - // ********************************************************/ - //virtual void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0; - // - ///******************************************************** - // * Sets the MomentOfInertia tensor matrix of an object without changing it's angular momentum. - // * Noticeable effect: The angular velocity will change. Can be used to create slow effects. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace. - // ********************************************************/ - //virtual void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0; - // - ///******************************************************** - // * Sets the mass of an object without changing it's linear velocity. - // * Noticeable effect: The linear momentum will change. Changing the amount of kinetic energy. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param m: [kg] - // ********************************************************/ - //virtual void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0; - // - ///******************************************************** - // * Sets the mass of an object without changing it's linear velocity. - // * Noticeable effect: The linear velocity will change. Can be used to create slow effects. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param m: [kg] - // ********************************************************/ - //virtual void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0; - // - ///******************************************************** - // * Instantly moves an object. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param worldPos: Relative to the world origo. (Not relative to object) [m] - // ********************************************************/ - //virtual void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos ) = 0; - // - ///******************************************************** - // * Instantly redirects object. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param rotation: New rotation. - // ********************************************************/ - //virtual void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation ) = 0; - // - ///******************************************************** - // * Instantly moves and redirects object. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param orientation: New orientation. - // ********************************************************/ - //virtual void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation ) = 0; - // - ///******************************************************** - // * Resizes the boundingBox. - // * @param objRef: A pointer to the ICustomBody representing a physical object. - // * @param size: New size of this [m] - // ********************************************************/ - //virtual void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size ) = 0; - - /******************************************************** - * Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies. - * @param desc: @see API::SimpleBodyDescription - * @return A pointer along with the responsibility to delete. - ********************************************************/ - virtual ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const = 0; - - /******************************************************** - * Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies. - * @param desc: @see API::SphericalBodyDescription - * @return A pointer along with the responsibility to delete. - ********************************************************/ - virtual ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const = 0; - protected: virtual ~API() {} }; @@ -246,190 +115,39 @@ namespace Oyster SubscriptMessage_player_collision_response }; + typedef SubscriptMessage (*EventAction_BeforeCollisionResponse)( const ICustomBody *proto, const ICustomBody *deuter ); typedef void (*EventAction_AfterCollisionResponse)( const ICustomBody *proto, const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ); typedef void (*EventAction_Move)( const ICustomBody *object ); - typedef Struct::SimpleBodyDescription SimpleBodyDescription; - typedef Struct::SphericalBodyDescription SphericalBodyDescription; typedef Struct::CustomBodyState State; virtual ~ICustomBody() {}; /******************************************************** - * Creates a complete copy of the current (type)object. - * @return An ICustomBody pointer along with the responsibility to delete. - ********************************************************/ - virtual ::Utility::DynamicMemory::UniquePointer Clone() const = 0; - - /******************************************************** - * @todo TODO: need doc - ********************************************************/ - virtual SubscriptMessage CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter ) = 0; - - /******************************************************** - * @todo TODO: need doc - ********************************************************/ - virtual void CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ) = 0; - - /******************************************************** - * @todo TODO: need doc - ********************************************************/ - virtual void CallSubscription_Move() = 0; - - /******************************************************** - * @todo TODO: need doc + * Gets the current state of the rigid body + * @return the current state of the rigid body ********************************************************/ virtual State GetState() const = 0; /******************************************************** - * @todo TODO: need doc + * Gets the current state of the rigid body + * @param targetMem: The state is copied into targetMem + * @return the current state of the rigid body ********************************************************/ virtual State & GetState( State &targetMem ) const = 0; /******************************************************** - * @return the linear velocity of the rigid body in a vector. + * Sets the current state of the rigid body ********************************************************/ - //virtual Math::Float3 GetRigidLinearVelocity() const = 0; + virtual void SetState( const State &state ) = 0; - /******************************************************** - * @todo TODO: need doc - ********************************************************/ - virtual void SetState( const State &state ) = 0; - - /******************************************************** - * @return true if Engine should apply gravity on this object. - ********************************************************/ - virtual bool IsAffectedByGravity() const = 0; - - /******************************************************** - * param shape: Any defined sample shape. - * @return true if this truly intersects with shape. - ********************************************************/ - virtual bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const = 0; - - /******************************************************** - * Performs a detailed Intersect test and returns if, when and where. - * @param shape: Any defined sample shape. - * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother. - * @return true if this truly intersects with object. - ********************************************************/ - virtual bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; - - /******************************************************** - * Performs a detailed Intersect test and returns if, when and where. - * @param object: What this is intersect testing against. - * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother. - * @return true if this truly intersects with object. - ********************************************************/ - virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0; - - /******************************************************** - * Sets how far back it needs to be interpolated to not be overlapping worldPointOfContact. - ********************************************************/ - virtual void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ) = 0; - - /******************************************************** - * Required by Engine's Collision Search. - * @param targetMem: Provided memory that written into and then returned. - * @return a sphere shape that contains the ICustomBody. - ********************************************************/ - virtual ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const = 0; - - /******************************************************** - * Required by Engine's Collision Responsing. - * @param worldPos: Should be worldPointOfContact from Intersects( ... ) - * @param targetMem: Provided memory that written into and then returned. - * @return a surface normal in worldSpace. - ********************************************************/ - virtual ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const = 0; - - /******************************************************** - * The gravity normal will have same direction as the total gravity force pulling on this and have the magnitude of 1.0f. - * @param targetMem: Provided memory that written into and then returned. - * @return a normalized vector in worldSpace. Exception: Null vector if no gravity been applied. - ********************************************************/ - virtual ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0; + virtual void SetSubscription(EventAction_AfterCollisionResponse function) = 0; /******************************************************** * @return the void pointer set by SetCustomTag. * nullptr if none is set. ********************************************************/ - virtual void * GetCustomTag() const = 0; - - ///******************************************************** - // * The world position of this center of gravity. - // * @param targetMem: Provided memory that written into and then returned. - // * @return a position in worldSpace. - // ********************************************************/ - //virtual ::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0; - // - ///******************************************************** - // * @param targetMem: Provided memory that written into and then returned. - // * @return a copy of this's rotation matrix. - // ********************************************************/ - //virtual ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0; - // - ///******************************************************** - // * @param targetMem: Provided memory that written into and then returned. - // * @return a copy of this's orientation matrix. - // ********************************************************/ - //virtual ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0; - // - ///******************************************************** - // * @param targetMem: Provided memory that written into and then returned. - // * @return a copy of this's view matrix. - // ********************************************************/ - //virtual ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0; - - /******************************************************** - * To not be called if is in Engine - * Is called during API::Update - ********************************************************/ - virtual UpdateState Update( ::Oyster::Math::Float timeStepLength ) = 0; - - /******************************************************** - * @todo TODO: add doc - ********************************************************/ - virtual void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ) = 0; - - /******************************************************** - * Sets which scene this ICustomBody is within. - * Reserved to only be used by the scene. - * @todo TODO: create an IScene interface - ********************************************************/ - virtual void SetScene( void *scene ) = 0; - - /******************************************************** - * Sets the function that will be called by the engine - * whenever a collision occurs. - * @param functionPointer: If NULL, an empty default function will be set. - ********************************************************/ - virtual void SetSubscription( EventAction_BeforeCollisionResponse functionPointer ) = 0; - - /******************************************************** - * Sets the function that will be called by the engine - * whenever a collision has finished. - * @param functionPointer: If NULL, an empty default function will be set. - ********************************************************/ - virtual void SetSubscription( EventAction_AfterCollisionResponse functionPointer ) = 0; - - /******************************************************** - * Sets the function that will be called by the engine - * whenever an object have moved. - * @param functionPointer: If NULL, an empty default function will be set. - ********************************************************/ - virtual void SetSubscription( EventAction_Move functionPointer ) = 0; - - /******************************************************** - * @param ignore: True if Engine should not apply Gravity. - ********************************************************/ - virtual void SetGravity( bool ignore) = 0; - - /******************************************************** - * Used by Engine - * @param normalizedVector: Should have same direction as the pullinggravity. - ********************************************************/ - virtual void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ) = 0; + virtual void* GetCustomTag() const = 0; /******************************************************** * Not used by the engine itself. Just a quality of life feature @@ -437,60 +155,6 @@ namespace Oyster * @param ref: Anything castable to a void pointer, the engine won't care. ********************************************************/ virtual void SetCustomTag( void *ref ) = 0; - - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetMomentOfInertiaTensor_KeepVelocity(...) instead - // ********************************************************/ - //virtual void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ) = 0; - // - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetMomentOfInertiaTensor_KeepMomentum(...) - // ********************************************************/ - //virtual void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ) = 0; - // - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetMass_KeepVelocity(...) - // ********************************************************/ - //virtual void SetMass_KeepVelocity( ::Oyster::Math::Float m ) = 0; - // - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetMass_KeepMomentum(...) - // ********************************************************/ - //virtual void SetMass_KeepMomentum( ::Oyster::Math::Float m ) = 0; - // - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetCenter(...) - // ********************************************************/ - //virtual void SetCenter( const ::Oyster::Math::Float3 &worldPos ) = 0; - // - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetRotation(...) - // ********************************************************/ - //virtual void SetRotation( const ::Oyster::Math::Float4x4 &rotation ) = 0; - // - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetOrientation(...) - // ********************************************************/ - //virtual void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ) = 0; - - ///******************************************************** - // * To not be called if is in Engine - // * Use API::SetSize(...) - // ********************************************************/ - //virtual void SetSize( const ::Oyster::Math::Float3 &size ) = 0; - - ///******************************************************** - // * To not be called if is in Engine - // * Use API::?? @todo TODO: - // ********************************************************/ - //virtual void SetMomentum( const ::Oyster::Math::Float3 &worldG ) = 0; }; } } diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h index eae72623..928c5099 100644 --- a/Code/GamePhysics/PhysicsStructs-Impl.h +++ b/Code/GamePhysics/PhysicsStructs-Impl.h @@ -10,53 +10,14 @@ namespace Oyster { namespace Struct { - inline SimpleBodyDescription::SimpleBodyDescription() - { - this->rotation = ::Oyster::Math::Float3::null; - this->centerPosition = ::Oyster::Math::Float3::null; - this->size = ::Oyster::Math::Float3( 1.0f ); - this->mass = 6.0f; - this->restitutionCoeff = 1.0f; - this->frictionCoeff_Dynamic = 0.5f; - this->frictionCoeff_Static = 0.5f; - this->inertiaTensor = ::Oyster::Physics3D::MomentOfInertia(); - this->subscription_onCollision = NULL; - this->subscription_onCollisionResponse = NULL; - this->subscription_onMovement = NULL; - this->ignoreGravity = false; - } - - inline SphericalBodyDescription::SphericalBodyDescription() - { - this->rotation = ::Oyster::Math::Float3::null; - this->centerPosition = ::Oyster::Math::Float3::null; - this->radius = 0.5f; - this->mass = 10.0f; - this->restitutionCoeff = 1.0f; - this->frictionCoeff_Dynamic = 0.5f; - this->frictionCoeff_Static = 0.5f; - this->subscription_onCollision = NULL; - this->subscription_onCollisionResponse = NULL; - this->subscription_onMovement = NULL; - this->ignoreGravity = false; - } - - inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float kineticFrictionCoeff, const ::Oyster::Physics3D::MomentOfInertia &inertiaTensor, const ::Oyster::Math::Float3 &reach, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Float3 &rotation, const ::Oyster::Math::Float3 &linearMomentum, const ::Oyster::Math::Float3 &angularMomentum, const ::Oyster::Math::Float3 &gravityNormal ) + inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float dynamicFrictionCoeff, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Quaternion& quaternion) { this->mass = mass; this->restitutionCoeff = restitutionCoeff; this->staticFrictionCoeff = staticFrictionCoeff; - this->kineticFrictionCoeff = kineticFrictionCoeff; - this->inertiaTensor = inertiaTensor; - this->reach = reach; + this->dynamicFrictionCoeff = dynamicFrictionCoeff; this->centerPos = centerPos; - this->angularAxis = rotation; - this->linearMomentum = linearMomentum; - this->angularMomentum = angularMomentum; - this->linearImpulse = this->angularImpulse = ::Oyster::Math::Float3::null; - this->deltaPos = this->deltaAxis = ::Oyster::Math::Float3::null; - this->isSpatiallyAltered = this->isDisturbed = this->isForwarded = false; - this->gravityNormal = gravityNormal; + this->quaternion = quaternion; } inline CustomBodyState & CustomBodyState::operator = ( const CustomBodyState &state ) @@ -64,488 +25,32 @@ namespace Oyster this->mass = state.mass; this->restitutionCoeff = state.restitutionCoeff; this->staticFrictionCoeff = state.staticFrictionCoeff; - this->kineticFrictionCoeff = state.kineticFrictionCoeff; - this->inertiaTensor = state.inertiaTensor; - this->reach = state.reach; + this->dynamicFrictionCoeff = state.dynamicFrictionCoeff; this->centerPos = state.centerPos; - this->angularAxis = state.angularAxis; - this->linearMomentum = state.linearMomentum; - this->angularMomentum = state.angularMomentum; - this->linearImpulse = state.linearImpulse; - this->angularImpulse = state.angularImpulse; - this->deltaPos = state.deltaPos; - this->deltaAxis = state.deltaAxis; - this->isSpatiallyAltered = state.isSpatiallyAltered; - this->isDisturbed = state.isDisturbed; - this->isForwarded = state.isForwarded; - this->gravityNormal = state.gravityNormal; + this->quaternion = state.quaternion; + return *this; } - inline const ::Oyster::Math::Float CustomBodyState::GetMass() const - { - return this->mass; - } - - inline const ::Oyster::Math::Float CustomBodyState::GetRestitutionCoeff() const - { - return this->restitutionCoeff; - } - - inline const ::Oyster::Math::Float CustomBodyState::GetFrictionCoeff_Static() const - { - return this->staticFrictionCoeff; - } - - inline const ::Oyster::Math::Float CustomBodyState::GetFrictionCoeff_Kinetic() const - { - return this->kineticFrictionCoeff; - } - - inline const ::Oyster::Physics3D::MomentOfInertia & CustomBodyState::GetMomentOfInertia() const - { - return this->inertiaTensor; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetReach() const - { - return this->reach; - } - - inline ::Oyster::Math::Float3 CustomBodyState::GetSize() const - { - return 2.0f * this->GetReach(); - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetCenterPosition() const - { - return this->centerPos; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularAxis() const - { - return this->angularAxis; - } inline ::Oyster::Math::Float4x4 CustomBodyState::GetRotation() const { - return ::Oyster::Math3D::RotationMatrix( this->GetAngularAxis() ); + return ::Oyster::Math3D::RotationMatrix( this->quaternion ); } inline ::Oyster::Math::Float4x4 CustomBodyState::GetOrientation() const { - return ::Oyster::Math3D::OrientationMatrix( this->angularAxis, this->centerPos ); - } - - inline ::Oyster::Math::Float4x4 CustomBodyState::GetOrientation( const ::Oyster::Math::Float3 &offset ) const - { - return ::Oyster::Math3D::OrientationMatrix( this->angularAxis, (this->centerPos + offset) ); + return ::Oyster::Math3D::OrientationMatrix( this->quaternion, this->centerPos ); } inline ::Oyster::Math::Float4x4 CustomBodyState::GetView() const { - return ::Oyster::Math3D::ViewMatrix( this->angularAxis, this->centerPos ); + return ::Oyster::Math3D::ViewMatrix( this->quaternion, this->centerPos ); } inline ::Oyster::Math::Float4x4 CustomBodyState::GetView( const ::Oyster::Math::Float3 &offset ) const { - return ::Oyster::Math3D::ViewMatrix( this->angularAxis, (this->centerPos + offset) ); - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetLinearMomentum() const - { - return this->linearMomentum; - } - - inline ::Oyster::Math::Float3 CustomBodyState::GetLinearMomentum( const ::Oyster::Math::Float3 &at ) const - { - ::Oyster::Math::Float3 offset = at - this->centerPos; - if( offset.Dot(offset) > 0.0f ) - { - return this->linearMomentum + ::Oyster::Physics3D::Formula::TangentialLinearMomentum( this->angularMomentum, offset ); - } - return this->linearMomentum; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularMomentum() const - { - return this->angularMomentum; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetLinearImpulse() const - { - return this->linearImpulse; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularImpulse() const - { - return this->angularImpulse; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetForward_DeltaPos() const - { - return this->deltaPos; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetForward_DeltaAxis() const - { - return this->deltaAxis; - } - - inline const ::Oyster::Math::Float3 & CustomBodyState::GetGravityNormal() const - { - return this->gravityNormal; - } - - inline void CustomBodyState::SetMass_KeepMomentum( ::Oyster::Math::Float m ) - { - this->mass = m; - } - - inline void CustomBodyState::SetMass_KeepVelocity( ::Oyster::Math::Float m ) - { - if( m != 0.0f ) - { // sanity block! - this->linearMomentum *= (m / this->mass); - this->mass = m; - } - } - - inline void CustomBodyState::SetRestitutionCoeff( ::Oyster::Math::Float e ) - { - this->restitutionCoeff = e; - } - - inline void CustomBodyState::SetFrictionCoeff( ::Oyster::Math::Float staticU, ::Oyster::Math::Float kineticU ) - { - this->staticFrictionCoeff = staticU; - this->kineticFrictionCoeff = kineticU; - } - - inline void CustomBodyState::SetMomentOfInertia_KeepMomentum( const ::Oyster::Physics3D::MomentOfInertia &tensor ) - { - this->inertiaTensor = tensor; - } - - inline void CustomBodyState::SetMomentOfInertia_KeepVelocity( const ::Oyster::Physics3D::MomentOfInertia &tensor ) - { - ::Oyster::Math::Quaternion rotation = ::Oyster::Math3D::Rotation(this->angularAxis); - ::Oyster::Math::Float3 w = this->inertiaTensor.CalculateAngularVelocity( rotation, this->angularMomentum ); - this->inertiaTensor = tensor; - this->angularMomentum = this->inertiaTensor.CalculateAngularMomentum( rotation, w ); - } - - inline void CustomBodyState::SetSize( const ::Oyster::Math::Float3 &size ) - { - this->SetReach( 0.5f * size ); - } - - inline void CustomBodyState::SetReach( const ::Oyster::Math::Float3 &halfSize ) - { - this->reach = halfSize; - this->reach = ::Utility::Value::Max( this->reach, ::Oyster::Math::Float3::null ); - this->isSpatiallyAltered = this->isDisturbed = true; - } - - inline void CustomBodyState::SetCenterPosition( const ::Oyster::Math::Float3 ¢erPos ) - { - this->centerPos = centerPos; - this->isSpatiallyAltered = this->isDisturbed = true; - } - - inline void CustomBodyState::SetRotation( const ::Oyster::Math::Float3 &angularAxis ) - { - this->angularAxis = angularAxis; - this->isSpatiallyAltered = this->isDisturbed = true; - } - - inline void CustomBodyState::SetOrientation( const ::Oyster::Math::Float3 &angularAxis, const ::Oyster::Math::Float3 &translation ) - { - this->angularAxis = angularAxis ; - this->centerPos = translation; - this->isSpatiallyAltered = this->isDisturbed = true; - } - - inline void CustomBodyState::SetLinearMomentum( const ::Oyster::Math::Float3 &g ) - { - this->linearMomentum = g; - this->isDisturbed = true; - } - - inline void CustomBodyState::SetAngularMomentum( const ::Oyster::Math::Float3 &h ) - { - this->angularMomentum = h; - this->isDisturbed = true; - } - - inline void CustomBodyState::SetLinearImpulse( const ::Oyster::Math::Float3 &j ) - { - this->linearImpulse = j; - this->isDisturbed = true; - } - - inline void CustomBodyState::SetAngularImpulse( const ::Oyster::Math::Float3 &j ) - { - this->angularImpulse = j; - this->isDisturbed = true; - } - - inline void CustomBodyState::SetGravityNormal( const ::Oyster::Math::Float3 &gravityNormal ) - { - this->gravityNormal = gravityNormal; - } - - inline void CustomBodyState::AddRotation( const ::Oyster::Math::Float3 &angularAxis ) - { - this->angularAxis += angularAxis; - this->isSpatiallyAltered = this->isDisturbed = true; - } - - inline void CustomBodyState::AddTranslation( const ::Oyster::Math::Float3 &deltaPos ) - { - this->centerPos += deltaPos; - this->isSpatiallyAltered = this->isDisturbed = true; - } - - inline void CustomBodyState::ApplyLinearImpulse( const ::Oyster::Math::Float3 &j ) - { - this->linearImpulse += j; - this->isDisturbed = true; - } - - inline void CustomBodyState::ApplyAngularImpulse( const ::Oyster::Math::Float3 &j ) - { - this->angularImpulse += j; - this->isDisturbed = true; - } - - inline void CustomBodyState::ApplyImpulse( const ::Oyster::Math::Float3 &j, const ::Oyster::Math::Float3 &at, const ::Oyster::Math::Float3 &normal ) - { - ::Oyster::Math::Float3 offset = at - this->centerPos; - if( offset.Dot(offset) > 0.0f ) - { - ::Oyster::Math::Float3 deltaAngularImpulse = ::Oyster::Physics3D::Formula::AngularMomentum( j, offset ); - - this->linearImpulse -= ::Oyster::Physics3D::Formula::TangentialLinearMomentum( deltaAngularImpulse, offset ); - this->angularImpulse += deltaAngularImpulse; - } - this->linearImpulse += j; - this->isDisturbed = true; - } - - inline void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j ) - { - this->linearImpulse += j; - this->isDisturbed = true; - } - - inline void CustomBodyState::ApplyForwarding( const ::Oyster::Math::Float3 &deltaPos, const ::Oyster::Math::Float3 &deltaAxis ) - { - this->deltaPos += deltaPos; - this->deltaAxis += deltaAxis; - this->isDisturbed = this->isForwarded = true; - } - - inline bool CustomBodyState::IsSpatiallyAltered() const - { - return this->isSpatiallyAltered; - } - - inline bool CustomBodyState::IsDisturbed() const - { - return this->isDisturbed; - } - - inline bool CustomBodyState::IsForwarded() const - { - return this->isForwarded; - } - - inline GravityWell::GravityWell( ) - { - this->position = ::Oyster::Math::Float3::null; - this->mass = 0.0f; - } - - inline GravityWell::GravityWell( const GravityWell &gravityWell ) - { - this->position = gravityWell.position; - this->mass = gravityWell.mass; - } - - inline GravityWell & GravityWell::operator = ( const GravityWell &gravityWell ) - { - this->position = gravityWell.position; - this->mass = gravityWell.mass; - - return *this; - } - - inline bool GravityWell::operator == ( const GravityWell &gravity ) const - { - if( this->position == gravity.position ) - if( this->mass == gravity.mass ) - { - return true; - } - return false; - } - - inline bool GravityWell::operator != ( const GravityWell &gravity ) const - { - if( this->position == gravity.position ) - if( this->mass == gravity.mass ) - { - return false; - } - return true; - } - - inline GravityDirected::GravityDirected( ) - { - this->impulse = ::Oyster::Math::Float3::null; - } - - inline GravityDirected::GravityDirected( const GravityDirected &gravityDirected ) - { - this->impulse = gravityDirected.impulse; - } - - inline GravityDirected & GravityDirected::operator = ( const GravityDirected &gravityDirected ) - { - this->impulse = gravityDirected.impulse; - - return *this; - } - - inline bool GravityDirected::operator == ( const GravityDirected &gravity ) const - { - return this->impulse == gravity.impulse; - } - - inline bool GravityDirected::operator != ( const GravityDirected &gravity ) const - { - return this->impulse != gravity.impulse; - } - - inline GravityDirectedField::GravityDirectedField( ) - { - this->normalizedDirection = ::Oyster::Math::Float3::null; - this->mass = 0.0f; - this->magnitude = 0.0f; - } - - inline GravityDirectedField::GravityDirectedField( const GravityDirectedField &gravityDirectedField ) - { - this->normalizedDirection = gravityDirectedField.normalizedDirection; - this->mass = gravityDirectedField.mass; - this->magnitude = gravityDirectedField.magnitude; - } - - inline GravityDirectedField & GravityDirectedField::operator = ( const GravityDirectedField &gravityDirectedField ) - { - this->normalizedDirection = gravityDirectedField.normalizedDirection; - this->mass = gravityDirectedField.mass; - this->magnitude = gravityDirectedField.magnitude; - - return *this; - } - - inline bool GravityDirectedField::operator == ( const GravityDirectedField &gravity ) const - { - if( this->normalizedDirection == gravity.normalizedDirection ) - if( this->mass == gravity.mass ) - if( this->magnitude == gravity.magnitude ) - { - return true; - } - return false; - } - - inline bool GravityDirectedField::operator != ( const GravityDirectedField &gravity ) const - { - if( this->normalizedDirection == gravity.normalizedDirection ) - if( this->mass == gravity.mass ) - if( this->magnitude == gravity.magnitude ) - { - return false; - } - return true; - } - - inline Gravity::Gravity() - { - this->gravityType = GravityType_Undefined; - } - - inline Gravity::Gravity( const Gravity &gravity ) - { - this->gravityType = gravity.gravityType; - - switch( gravity.gravityType ) - { - case GravityType_Well: - this->well = gravity.well; - break; - case GravityType_Directed: - this->directed = gravity.directed; - break; - case GravityType_DirectedField: - this->directedField = gravity.directedField; - break; - default: break; - } - } - - inline Gravity & Gravity::operator = ( const Gravity &gravity ) - { - this->gravityType = gravity.gravityType; - - switch( gravity.gravityType ) - { - case GravityType_Well: - this->well = gravity.well; - break; - case GravityType_Directed: - this->directed = gravity.directed; - break; - case GravityType_DirectedField: - this->directedField = gravity.directedField; - break; - default: break; - } - - return *this; - } - - inline bool Gravity::operator == ( const Gravity &gravity ) const - { - if( this->gravityType == gravity.gravityType ) - { - switch( this->gravityType ) - { - case GravityType_Well: return this->well == gravity.well; - case GravityType_Directed: return this->directed == gravity.directed; - case GravityType_DirectedField: return this->directedField == gravity.directedField; - default: return true; - } - } - return false; - } - - inline bool Gravity::operator != ( const Gravity &gravity ) const - { - if( this->gravityType == gravity.gravityType ) - { - switch( this->gravityType ) - { - case GravityType_Well: return this->well != gravity.well; - case GravityType_Directed: return this->directed != gravity.directed; - case GravityType_DirectedField: return this->directedField != gravity.directedField; - default: return false; - } - } - return true; + return ::Oyster::Math3D::ViewMatrix( this->quaternion, (this->centerPos + offset) ); } } } diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index 6bf39a67..d4ca7b99 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -5,212 +5,40 @@ #include "PhysicsAPI.h" #include "Inertia.h" -namespace Oyster { namespace Physics -{ - namespace Struct +namespace Oyster +{ + namespace Physics { - struct SimpleBodyDescription + namespace Struct { - ::Oyster::Math::Float3 rotation; - ::Oyster::Math::Float3 centerPosition; - ::Oyster::Math::Float3 size; - ::Oyster::Math::Float mass; - ::Oyster::Math::Float restitutionCoeff; - ::Oyster::Math::Float frictionCoeff_Static; - ::Oyster::Math::Float frictionCoeff_Dynamic; - ::Oyster::Physics3D::MomentOfInertia inertiaTensor; - ::Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse subscription_onCollision; - ::Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse subscription_onCollisionResponse; - ::Oyster::Physics::ICustomBody::EventAction_Move subscription_onMovement; - bool ignoreGravity; - - SimpleBodyDescription(); - }; - - struct SphericalBodyDescription - { - ::Oyster::Math::Float3 rotation; - ::Oyster::Math::Float3 centerPosition; - ::Oyster::Math::Float radius; - ::Oyster::Math::Float mass; - ::Oyster::Math::Float restitutionCoeff; - ::Oyster::Math::Float frictionCoeff_Static; - ::Oyster::Math::Float frictionCoeff_Dynamic; - ::Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse subscription_onCollision; - ::Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse subscription_onCollisionResponse; - ::Oyster::Physics::ICustomBody::EventAction_Move subscription_onMovement; - bool ignoreGravity; - - SphericalBodyDescription(); - }; - - struct CustomBodyState - { - public: - CustomBodyState( ::Oyster::Math::Float mass = 1.0f, - ::Oyster::Math::Float restitutionCoeff = 1.0f, - ::Oyster::Math::Float staticFrictionCoeff = 1.0f, - ::Oyster::Math::Float kineticFrictionCoeff = 1.0f, - const ::Oyster::Physics3D::MomentOfInertia &inertiaTensor = ::Oyster::Physics3D::MomentOfInertia(), - const ::Oyster::Math::Float3 &reach = ::Oyster::Math::Float3::null, - const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null, - const ::Oyster::Math::Float3 &rotation = ::Oyster::Math::Float3::null, - const ::Oyster::Math::Float3 &linearMomentum = ::Oyster::Math::Float3::null, - const ::Oyster::Math::Float3 &angularMomentum = ::Oyster::Math::Float3::null, - const ::Oyster::Math::Float3 &gravityNormal = ::Oyster::Math::Float3::null); - - CustomBodyState & operator = ( const CustomBodyState &state ); - - const ::Oyster::Math::Float GetMass() const; - const ::Oyster::Math::Float GetRestitutionCoeff() const; - const ::Oyster::Math::Float GetFrictionCoeff_Static() const; - const ::Oyster::Math::Float GetFrictionCoeff_Kinetic() const; - const ::Oyster::Physics3D::MomentOfInertia & GetMomentOfInertia() const; - const ::Oyster::Math::Float3 & GetReach() const; - ::Oyster::Math::Float3 GetSize() const; - const ::Oyster::Math::Float3 & GetCenterPosition() const; - const ::Oyster::Math::Float3 & GetAngularAxis() const; - ::Oyster::Math::Float4x4 GetRotation() const; - ::Oyster::Math::Float4x4 GetOrientation() const; - ::Oyster::Math::Float4x4 GetOrientation( const ::Oyster::Math::Float3 &offset ) const; - ::Oyster::Math::Float4x4 GetView() const; - ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const; - const ::Oyster::Math::Float3 & GetLinearMomentum() const; - ::Oyster::Math::Float3 GetLinearMomentum( const ::Oyster::Math::Float3 &at ) const; - const ::Oyster::Math::Float3 & GetAngularMomentum() const; - const ::Oyster::Math::Float3 & GetLinearImpulse() const; - const ::Oyster::Math::Float3 & GetAngularImpulse() const; - const ::Oyster::Math::Float3 & GetForward_DeltaPos() const; - const ::Oyster::Math::Float3 & GetForward_DeltaAxis() const; - const ::Oyster::Math::Float3 & GetGravityNormal() const; - - void SetMass_KeepMomentum( ::Oyster::Math::Float m ); - void SetMass_KeepVelocity( ::Oyster::Math::Float m ); - void SetRestitutionCoeff( ::Oyster::Math::Float e ); - void SetFrictionCoeff( ::Oyster::Math::Float staticU, ::Oyster::Math::Float kineticU ); - void SetMomentOfInertia_KeepMomentum( const ::Oyster::Physics3D::MomentOfInertia &tensor ); - void SetMomentOfInertia_KeepVelocity( const ::Oyster::Physics3D::MomentOfInertia &tensor ); - void SetSize( const ::Oyster::Math::Float3 &size ); - void SetReach( const ::Oyster::Math::Float3 &halfSize ); - void SetCenterPosition( const ::Oyster::Math::Float3 ¢erPos ); - void SetRotation( const ::Oyster::Math::Float3 &angularAxis ); - //void SetRotation( const ::Oyster::Math::Float4x4 &rotation ); - //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ); - void SetOrientation( const ::Oyster::Math::Float3 &angularAxis, const ::Oyster::Math::Float3 &translation ); - void SetLinearMomentum( const ::Oyster::Math::Float3 &g ); - void SetAngularMomentum( const ::Oyster::Math::Float3 &h ); - void SetLinearImpulse( const ::Oyster::Math::Float3 &j ); - void SetAngularImpulse( const ::Oyster::Math::Float3 &j ); - void SetGravityNormal( const ::Oyster::Math::Float3 &gravityNormal ); - - void AddRotation( const ::Oyster::Math::Float3 &angularAxis ); - void AddTranslation( const ::Oyster::Math::Float3 &deltaPos ); - - void ApplyLinearImpulse( const ::Oyster::Math::Float3 &j ); - void ApplyAngularImpulse( const ::Oyster::Math::Float3 &j ); - void ApplyImpulse( const ::Oyster::Math::Float3 &j, const ::Oyster::Math::Float3 &at, const ::Oyster::Math::Float3 &normal ); - void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j); - void ApplyForwarding( const ::Oyster::Math::Float3 &deltaPos, const ::Oyster::Math::Float3 &deltaAxis ); - - bool IsSpatiallyAltered() const; - bool IsDisturbed() const; - bool IsForwarded() const; - - ::Oyster::Math::Float3 linearMomentum; - - private: - ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, kineticFrictionCoeff; - ::Oyster::Physics3D::MomentOfInertia inertiaTensor; - ::Oyster::Math::Float3 reach, centerPos, angularAxis; - ::Oyster::Math::Float3 angularMomentum; - ::Oyster::Math::Float3 linearImpulse, angularImpulse; - ::Oyster::Math::Float3 deltaPos, deltaAxis; // Forwarding data sum - ::Oyster::Math::Float3 gravityNormal; - - bool isSpatiallyAltered, isDisturbed, isForwarded; - }; - - /** - ############################################################################### - Can't define structs inside structs in a union therefor they are declared here. - ############################################################################### - */ - struct GravityWell - { - ::Oyster::Math::Float3 position; - ::Oyster::Math::Float mass; - - GravityWell( ); - GravityWell( const GravityWell &gravityWell ); - GravityWell & operator = ( const GravityWell &gravityWell ); - - bool operator == ( const GravityWell &gravity ) const; - bool operator != ( const GravityWell &gravity ) const; - }; - - struct GravityDirected - { - ::Oyster::Math::Float3 impulse; - - GravityDirected( ); - GravityDirected( const GravityDirected &gravityDirected ); - GravityDirected & operator = ( const GravityDirected &gravityDirected ); - - bool operator == ( const GravityDirected &gravity ) const; - bool operator != ( const GravityDirected &gravity ) const; - }; - - struct GravityDirectedField - { - ::Oyster::Math::Float3 normalizedDirection; - ::Oyster::Math::Float mass; - ::Oyster::Math::Float magnitude; - - GravityDirectedField( ); - GravityDirectedField( const GravityDirectedField &gravityDirectedField ); - GravityDirectedField & operator = ( const GravityDirectedField &gravityDirectedField ); - - bool operator == ( const GravityDirectedField &gravity ) const; - bool operator != ( const GravityDirectedField &gravity ) const; - }; - - struct Gravity - { - enum GravityType + struct CustomBodyState { - GravityType_Undefined = -1, - GravityType_Well = 0, - GravityType_Directed = 1, - GravityType_DirectedField = 2, - } gravityType; + public: + // Default constructor + CustomBodyState( ::Oyster::Math::Float mass = 1.0f, + ::Oyster::Math::Float restitutionCoeff = 1.0f, + ::Oyster::Math::Float staticFrictionCoeff = 1.0f, + ::Oyster::Math::Float dynamicFrictionCoeff = 1.0f, + const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null, + const ::Oyster::Math::Quaternion &quaternion = ::Oyster::Math::Quaternion(::Oyster::Math::Float3(0, 0, 0), 1)); - union - { - struct - { - GravityWell well; - }; + // Assignment operator + CustomBodyState & operator = ( const CustomBodyState &state ); - struct - { - GravityDirected directed; - }; + // Get functions that calculate matrices that do not exist as variables + ::Oyster::Math::Float4x4 GetRotation() const; + ::Oyster::Math::Float4x4 GetOrientation() const; + ::Oyster::Math::Float4x4 GetView() const; + ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const; - struct - { - GravityDirectedField directedField; - }; - }; - - Gravity( ); - Gravity( const Gravity &gravity ); - Gravity & operator = ( const Gravity &gravity ); - - bool operator == ( const Gravity &gravity ) const; - bool operator != ( const Gravity &gravity ) const; - }; - } -} } + // Variables for state + ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, dynamicFrictionCoeff; + ::Oyster::Math::Float3 reach, centerPos; + ::Oyster::Math::Quaternion quaternion; + }; + } + } +} #include "PhysicsStructs-Impl.h" diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index ab0b1a18..43d6f9a4 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -13,7 +13,7 @@ using namespace ::Utility::Value; RigidBody::RigidBody( ) { // by Dan Andersson this->centerPos = Float4::standard_unit_w; - this->axis = Float4::null; + this->quaternion = Quaternion(Float3(0, 0, 0), 1); this->boundingReach = Float4( 0.5f, 0.5f, 0.5f, 0.0f ); this->momentum_Linear = Float4::null; this->momentum_Angular = Float4::null; @@ -24,13 +24,12 @@ RigidBody::RigidBody( ) this->frictionCoeff_Kinetic = 1.0f; this->mass = 10; this->momentOfInertiaTensor = MomentOfInertia(); - this->rotation = Quaternion::identity; } RigidBody & RigidBody::operator = ( const RigidBody &body ) { // by Dan Andersson this->centerPos = body.centerPos; - this->axis = body.axis; + this->quaternion = body.quaternion; this->boundingReach = body.boundingReach; this->momentum_Linear = body.momentum_Linear; this->momentum_Angular = body.momentum_Angular; @@ -41,7 +40,6 @@ RigidBody & RigidBody::operator = ( const RigidBody &body ) this->frictionCoeff_Kinetic = body.frictionCoeff_Kinetic; this->mass = body.mass; this->momentOfInertiaTensor = body.momentOfInertiaTensor; - this->rotation = body.rotation; return *this; } @@ -55,19 +53,14 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) this->momentum_Angular = this->momentum_Angular*0.99f; // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G - Float3 delta = AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); - Float3 newPos = updateFrameLength*this->momentum_Linear; + Float3 delta = this->momentum_Linear; + Float3 newPos = (updateFrameLength)*this->momentum_Linear; this->centerPos += newPos; - - if(this->mass == 70) - { - const char *breakpoint = "STOP"; - } // updating the angular // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H - this->axis += updateFrameLength*this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular ); - this->rotation = Rotation( this->axis ); + /*this->axis += updateFrameLength*this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular ); + this->rotation = Rotation( this->axis );*/ // update momentums and clear impulse_Linear and impulse_Angular this->momentum_Linear += this->impulse_Linear; @@ -89,14 +82,14 @@ void RigidBody::Predict_LeapFrog( Float3 &outDeltaPos, Float3 &outDeltaAxis, con // dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H //outDeltaAxis = Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, actingAngularImpulse) ); - outDeltaAxis = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); + //utDeltaAxis = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) ); } void RigidBody::Move( const Float3 &deltaPos, const Float3 &deltaAxis ) { - this->centerPos += deltaPos; - this->axis += deltaAxis; - this->rotation = Rotation( this->axis ); + //this->centerPos += deltaPos; + //this->axis += deltaAxis; + //this->rotation = Rotation( this->axis ); } void RigidBody::ApplyImpulse( const Float3 &worldJ, const Float3 &atWorldPos ) @@ -125,22 +118,22 @@ Float RigidBody::GetMass() const const Quaternion & RigidBody::GetRotationQuaternion() const { // by Dan Andersson - return this->rotation; + return this->quaternion; } Float4x4 RigidBody::GetRotationMatrix() const { // by Dan Andersson - return RotationMatrix( this->rotation ); + return RotationMatrix( quaternion ); } Float4x4 RigidBody::GetOrientation() const { // by Dan Andersson - return ::Oyster::Math3D::OrientationMatrix( this->rotation, this->centerPos ); + return ::Oyster::Math3D::OrientationMatrix( this->quaternion, this->centerPos ); } Float4x4 RigidBody::GetView() const { // by Dan Andersson - return ViewMatrix( this->rotation, this->centerPos ); + return ViewMatrix( this->quaternion, this->centerPos ); } Float3 RigidBody::GetVelocity_Linear() const @@ -150,7 +143,7 @@ Float3 RigidBody::GetVelocity_Linear() const Float3 RigidBody::GetVelocity_Angular() const { // by Dan Andersson - return this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular ); + return Float3(0, 0, 0); } Float3 RigidBody::GetLinearMomentum( const Float3 &atWorldPos ) const @@ -165,9 +158,7 @@ Float3 RigidBody::GetLinearMomentum( const Float3 &atWorldPos ) const void RigidBody::SetMomentOfInertia_KeepVelocity( const MomentOfInertia &localTensorI ) { // by Dan Andersson - Float3 w = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular ); - this->momentOfInertiaTensor = localTensorI; - this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, w ); + } void RigidBody::SetMomentOfInertia_KeepMomentum( const MomentOfInertia &localTensorI ) @@ -193,10 +184,9 @@ void RigidBody::SetMass_KeepMomentum( const Float &m ) } } -void RigidBody::SetRotation( const Float3 &axis ) +void RigidBody::SetRotation( const ::Oyster::Math::Quaternion &quaternion ) { // by Dan Andersson - this->axis = axis; - this->rotation = Rotation( this->axis ); + this->quaternion = quaternion; } void RigidBody::SetMomentum_Linear( const Float3 &worldG, const Float3 &atWorldPos ) @@ -215,12 +205,12 @@ void RigidBody::SetVelocity_Linear( const Float3 &worldV, const Float3 &atWorldP { // by Dan Andersson Float3 worldOffset = atWorldPos - this->centerPos; this->momentum_Linear = Formula::LinearMomentum( this->mass, VectorProjection(worldV, worldOffset) ); - this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->rotation, Formula::AngularVelocity(worldV, worldOffset) ); + this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->quaternion, Formula::AngularVelocity(worldV, worldOffset) ); } void RigidBody::SetVelocity_Angular( const Float3 &worldW ) { // by Dan Andersson - this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->rotation, worldW ); + this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->quaternion, worldW ); } void RigidBody::SetImpulse_Linear( const Float3 &worldJ, const Float3 &atWorldPos ) diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h index f7aebd22..2d2226cf 100644 --- a/Code/OysterPhysics3D/RigidBody.h +++ b/Code/OysterPhysics3D/RigidBody.h @@ -15,8 +15,8 @@ namespace Oyster { namespace Physics3D struct RigidBody { //! A struct of a simple rigid body. public: + ::Oyster::Math::Quaternion quaternion; ::Oyster::Math::Float3 centerPos, //!< Location of the body's center in the world. - axis, //!< Euler rotationAxis of the body. boundingReach, //!< momentum_Linear, //!< The linear momentum G (kg*m/s). momentum_Angular, //!< The angular momentum H (Nm*s) around an parallell axis. @@ -64,7 +64,7 @@ namespace Oyster { namespace Physics3D void SetMass_KeepMomentum( const ::Oyster::Math::Float &m ); //void SetOrientation( const ::Oyster::Math::Float4x4 &o ); - void SetRotation( const ::Oyster::Math::Float3 &axis ); + void SetRotation( const ::Oyster::Math::Quaternion &quaternion ); void SetSize( const ::Oyster::Math::Float3 &widthHeight ); void SetMomentum_Linear( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &atWorldPos ); @@ -81,7 +81,7 @@ namespace Oyster { namespace Physics3D ::Oyster::Math::Float mass; //!< m (kg) //::Oyster::Math::Float4x4 momentOfInertiaTensor; //!< I (Nm*s) Tensor matrix ( only need to be 3x3 matrix, but is 4x4 for future hardware acceleration ) (localValue) ::Oyster::Physics3D::MomentOfInertia momentOfInertiaTensor; - ::Oyster::Math::Quaternion rotation; //!< RotationAxis of the body. + //::Oyster::Math::Quaternion rotation; //!< RotationAxis of the body. }; } } diff --git a/Code/Physics/BulletCollision/BulletCollision.vcxproj b/Code/Physics/BulletCollision/BulletCollision.vcxproj new file mode 100644 index 00000000..28c24c6e --- /dev/null +++ b/Code/Physics/BulletCollision/BulletCollision.vcxproj @@ -0,0 +1,487 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} + Win32Proj + Win32 + BulletCollision + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)Physics\Debug\ + BulletCollision.dir\Debug\ + BulletCollision_Debug + .lib + $(SolutionDir)Physics\Release + BulletCollision.dir\Release\ + BulletCollision + .lib + C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\MinSizeRel\ + BulletCollision.dir\MinSizeRel\ + BulletCollision_MinsizeRel + .lib + C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\RelWithDebInfo\ + BulletCollision.dir\RelWithDebInfo\ + BulletCollision_RelWithDebugInfo + .lib + + + + $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreadedDLL + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Physics/BulletCollision/BulletCollision.vcxproj.user b/Code/Physics/BulletCollision/BulletCollision.vcxproj.user new file mode 100644 index 00000000..a375ae35 --- /dev/null +++ b/Code/Physics/BulletCollision/BulletCollision.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Code/Physics/BulletCollision/CMakeFiles/generate.stamp b/Code/Physics/BulletCollision/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/BulletCollision/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend b/Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..d667b1b5 --- /dev/null +++ b/Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt diff --git a/Code/Physics/BulletCollision/INSTALL.vcxproj b/Code/Physics/BulletCollision/INSTALL.vcxproj new file mode 100644 index 00000000..f8528ea7 --- /dev/null +++ b/Code/Physics/BulletCollision/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {0A758B62-DE3C-493C-985D-39E48A384A7C} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + false + + + + + F5149B3B-C2B1-4522-9FFD-121CED456BD3 + + + + + + \ No newline at end of file diff --git a/Code/Physics/BulletCollision/cmake_install.cmake b/Code/Physics/BulletCollision/cmake_install.cmake new file mode 100644 index 00000000..20924d01 --- /dev/null +++ b/Code/Physics/BulletCollision/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/BulletDynamics/BulletDynamics.vcxproj b/Code/Physics/BulletDynamics/BulletDynamics.vcxproj new file mode 100644 index 00000000..fed75f6d --- /dev/null +++ b/Code/Physics/BulletDynamics/BulletDynamics.vcxproj @@ -0,0 +1,343 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} + Win32Proj + Win32 + BulletDynamics + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)Physics\Debug\ + BulletDynamics.dir\Debug\ + BulletDynamics_Debug + .lib + $(SolutionDir)Physics\Release + BulletDynamics.dir\Release\ + BulletDynamics + .lib + C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\MinSizeRel\ + BulletDynamics.dir\MinSizeRel\ + BulletDynamics_MinsizeRel + .lib + C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\RelWithDebInfo\ + BulletDynamics.dir\RelWithDebInfo\ + BulletDynamics_RelWithDebugInfo + .lib + + + + $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreadedDLL + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user b/Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user new file mode 100644 index 00000000..a375ae35 --- /dev/null +++ b/Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp b/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend b/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..89a4cf45 --- /dev/null +++ b/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt diff --git a/Code/Physics/BulletDynamics/INSTALL.vcxproj b/Code/Physics/BulletDynamics/INSTALL.vcxproj new file mode 100644 index 00000000..8480d320 --- /dev/null +++ b/Code/Physics/BulletDynamics/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {0A758B62-DE3C-493C-985D-39E48A384A7C} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + + + + F5149B3B-C2B1-4522-9FFD-121CED456BD3 + + + + + + \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/cmake_install.cmake b/Code/Physics/BulletDynamics/cmake_install.cmake new file mode 100644 index 00000000..3cf003da --- /dev/null +++ b/Code/Physics/BulletDynamics/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_cpx.h b/Code/Physics/Glut/EmptyGL/GL/egl_cpx.h new file mode 100644 index 00000000..16a685aa --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/egl_cpx.h @@ -0,0 +1,13 @@ +// todo - implement these as you see fit. +inline GLint glRenderMode(GLenum a0) { return GL_RENDER; }; // ymmv. should return previous mode +inline GLenum glGetError() { return GL_NO_ERROR; }; +inline GLboolean glIsList(GLuint a0) { return GL_TRUE; }; +inline GLuint glGenLists(GLsizei a0) { return (GLuint)a0; }; +inline const GLubyte* glGetString(GLenum a0) { return (const GLubyte *)"egl-xyzzy"; }; +inline GLboolean glIsEnabled(GLenum a0) { return GL_TRUE; }; +inline GLboolean glAreTexturesResident(GLsizei a0,const GLuint * a1,GLboolean * a2) { return GL_TRUE; }; +inline GLboolean glIsTexture(GLuint a0) { return GL_TRUE; }; +inline void glGetBooleanv(GLenum a0,GLboolean * a1) { *a1 = GL_TRUE; }; +inline void glGetDoublev(GLenum a0,GLdouble * a1) { *a1 = 0.0; }; +inline void glGetFloatv(GLenum a0,GLfloat * a1) { *a1 = 0.0f; }; +inline void glGetIntegerv(GLenum a0,GLint * a1) { *a1 = 0; }; diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_defs.h b/Code/Physics/Glut/EmptyGL/GL/egl_defs.h new file mode 100644 index 00000000..cbd57114 --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/egl_defs.h @@ -0,0 +1,706 @@ +#ifndef EGL_DEFS_H +#define EGL_DEFS_H + +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef signed char GLbyte; +typedef short GLshort; +typedef int GLint; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef int GLsizei; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; + +#define __gl_h_ +#define GL_VERSION_1_1 1 +#define GL_VERSION_1_2 1 +#define GL_VERSION_1_3 1 +#define GL_ARB_imaging 1 +#define GL_FALSE 0x0 +#define GL_TRUE 0x1 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON 0x0009 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_MATRIX_MODE 0x0BA0 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_LIST_MODE 0x0B30 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_SHININESS 0x1601 +#define GL_EMISSION 0x1600 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_SHADE_MODEL 0x0B54 +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_NORMALIZE 0x0BA1 +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_ACCUM 0x0100 +#define GL_ADD 0x0104 +#define GL_LOAD 0x0101 +#define GL_MULT 0x0103 +#define GL_RETURN 0x0102 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_BLEND 0x0BE2 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND_DST 0x0BE0 +#define GL_ZERO 0x0 +#define GL_ONE 0x1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FEEDBACK 0x1C01 +#define GL_RENDER 0x1C00 +#define GL_SELECT 0x1C02 +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_FOG 0x0B60 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_COLOR 0x0B66 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_LINEAR 0x2601 +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 +#define GL_LOGIC_OP 0x0BF1 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_CLEAR 0x1500 +#define GL_SET 0x150F +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_NOOP 0x1505 +#define GL_INVERT 0x150A +#define GL_AND 0x1501 +#define GL_NAND 0x150E +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_XOR 0x1506 +#define GL_EQUIV 0x1509 +#define GL_AND_REVERSE 0x1502 +#define GL_AND_INVERTED 0x1504 +#define GL_OR_REVERSE 0x150B +#define GL_OR_INVERTED 0x150D +#define GL_STENCIL_BITS 0x0D57 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_INDEX 0x1901 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_NONE 0x0 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_COLOR_INDEX 0x1900 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_ALPHA_BITS 0x0D55 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_INDEX_BITS 0x0D51 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_READ_BUFFER 0x0C02 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_BITMAP 0x1A00 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_DITHER 0x0BD0 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_MODE 0x0C30 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_RENDER_MODE 0x0C40 +#define GL_RGBA_MODE 0x0C31 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_LINEAR 0x2400 +#define GL_EYE_PLANE 0x2502 +#define GL_SPHERE_MAP 0x2402 +#define GL_DECAL 0x2101 +#define GL_MODULATE 0x2100 +#define GL_NEAREST 0x2600 +#define GL_REPEAT 0x2901 +#define GL_CLAMP 0x2900 +#define GL_S 0x2000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NO_ERROR 0x0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CURRENT_BIT 0x00000001 +#define GL_POINT_BIT 0x00000002 +#define GL_LINE_BIT 0x00000004 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_HINT_BIT 0x00008000 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000FFFFF +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_ALL_CLIENT_ATTRIB_BITS 0xFFFFFFFF +#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF +#define GL_RESCALE_NORMAL 0x803A +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_BLEND_EQUATION 0x8009 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_COLOR 0x8005 +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 + +#endif diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_logged.h b/Code/Physics/Glut/EmptyGL/GL/egl_logged.h new file mode 100644 index 00000000..67efcafe --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/egl_logged.h @@ -0,0 +1,20 @@ +inline void glFinish() {xGLL(EGL_TOKEN_glFinish);}; +inline void glClear(GLbitfield a0) {xGLL(EGL_TOKEN_glClear);xGLL(a0);}; +inline void glFlush() {xGLL(EGL_TOKEN_glFlush);}; +inline void glMatrixMode(GLenum a0) {xGLL(EGL_TOKEN_glMatrixMode);xGLL(a0);}; +inline void glOrtho(GLdouble a0,GLdouble a1,GLdouble a2,GLdouble a3,GLdouble a4,GLdouble a5) {xGLL(EGL_TOKEN_glOrtho);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);xGLL(a4);xGLL(a5);}; +inline void glFrustum(GLdouble a0,GLdouble a1,GLdouble a2,GLdouble a3,GLdouble a4,GLdouble a5) {xGLL(EGL_TOKEN_glFrustum);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);xGLL(a4);xGLL(a5);}; +inline void glViewport(GLint a0,GLint a1,GLsizei a2,GLsizei a3) {xGLL(EGL_TOKEN_glViewport);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);}; +inline void glPushMatrix() {xGLL(EGL_TOKEN_glPushMatrix);}; +inline void glPopMatrix() {xGLL(EGL_TOKEN_glPopMatrix);}; +inline void glLoadIdentity() {xGLL(EGL_TOKEN_glLoadIdentity);}; +inline void glLoadMatrixd(const GLdouble * a0) {xGLL(EGL_TOKEN_glLoadMatrixd);xGLL(a0);}; +inline void glLoadMatrixf(const GLfloat * a0) {xGLL(EGL_TOKEN_glLoadMatrixf);xGLL(a0);}; +inline void glMultMatrixd(const GLdouble * a0) {xGLL(EGL_TOKEN_glMultMatrixd);xGLL(a0);}; +inline void glMultMatrixf(const GLfloat * a0) {xGLL(EGL_TOKEN_glMultMatrixf);xGLL(a0);}; +inline void glRotated(GLdouble a0,GLdouble a1,GLdouble a2,GLdouble a3) {xGLL(EGL_TOKEN_glRotated);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);}; +inline void glRotatef(GLfloat a0,GLfloat a1,GLfloat a2,GLfloat a3) {xGLL(EGL_TOKEN_glRotatef);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);}; +inline void glScaled(GLdouble a0,GLdouble a1,GLdouble a2) {xGLL(EGL_TOKEN_glScaled);xGLL(a0);xGLL(a1);xGLL(a2);}; +inline void glScalef(GLfloat a0,GLfloat a1,GLfloat a2) {xGLL(EGL_TOKEN_glScalef);xGLL(a0);xGLL(a1);xGLL(a2);}; +inline void glTranslated(GLdouble a0,GLdouble a1,GLdouble a2) {xGLL(EGL_TOKEN_glTranslated);xGLL(a0);xGLL(a1);xGLL(a2);}; +inline void glTranslatef(GLfloat a0,GLfloat a1,GLfloat a2) {xGLL(EGL_TOKEN_glTranslatef);xGLL(a0);xGLL(a1);xGLL(a2);}; diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_tokens.h b/Code/Physics/Glut/EmptyGL/GL/egl_tokens.h new file mode 100644 index 00000000..9678adcd --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/egl_tokens.h @@ -0,0 +1,459 @@ +#ifndef EGL_TOKENS_H +#define EGL_TOKENS_H + +#define EGL_TOKEN_glClearIndex 0x0 +#define EGL_TOKEN_glClearColor 0x1 +#define EGL_TOKEN_glClear 0x2 +#define EGL_TOKEN_glIndexMask 0x3 +#define EGL_TOKEN_glColorMask 0x4 +#define EGL_TOKEN_glAlphaFunc 0x5 +#define EGL_TOKEN_glBlendFunc 0x6 +#define EGL_TOKEN_glLogicOp 0x7 +#define EGL_TOKEN_glCullFace 0x8 +#define EGL_TOKEN_glFrontFace 0x9 +#define EGL_TOKEN_glPointSize 0xa +#define EGL_TOKEN_glLineWidth 0xb +#define EGL_TOKEN_glLineStipple 0xc +#define EGL_TOKEN_glPolygonMode 0xd +#define EGL_TOKEN_glPolygonOffset 0xe +#define EGL_TOKEN_glPolygonStipple 0xf +#define EGL_TOKEN_glGetPolygonStipple 0x10 +#define EGL_TOKEN_glEdgeFlag 0x11 +#define EGL_TOKEN_glEdgeFlagv 0x12 +#define EGL_TOKEN_glScissor 0x13 +#define EGL_TOKEN_glClipPlane 0x14 +#define EGL_TOKEN_glGetClipPlane 0x15 +#define EGL_TOKEN_glDrawBuffer 0x16 +#define EGL_TOKEN_glReadBuffer 0x17 +#define EGL_TOKEN_glEnable 0x18 +#define EGL_TOKEN_glDisable 0x19 +#define EGL_TOKEN_glIsEnabled 0x1a +#define EGL_TOKEN_glEnableClientState 0x1b +#define EGL_TOKEN_glDisableClientState 0x1c +#define EGL_TOKEN_glGetBooleanv 0x1d +#define EGL_TOKEN_glGetDoublev 0x1e +#define EGL_TOKEN_glGetFloatv 0x1f +#define EGL_TOKEN_glGetIntegerv 0x20 +#define EGL_TOKEN_glPushAttrib 0x21 +#define EGL_TOKEN_glPopAttrib 0x22 +#define EGL_TOKEN_glPushClientAttrib 0x23 +#define EGL_TOKEN_glPopClientAttrib 0x24 +#define EGL_TOKEN_glRenderMode 0x25 +#define EGL_TOKEN_glGetError 0x26 +#define EGL_TOKEN_glGetString 0x27 +#define EGL_TOKEN_glFinish 0x28 +#define EGL_TOKEN_glFlush 0x29 +#define EGL_TOKEN_glHint 0x2a +#define EGL_TOKEN_glClearDepth 0x2b +#define EGL_TOKEN_glDepthFunc 0x2c +#define EGL_TOKEN_glDepthMask 0x2d +#define EGL_TOKEN_glDepthRange 0x2e +#define EGL_TOKEN_glClearAccum 0x2f +#define EGL_TOKEN_glAccum 0x30 +#define EGL_TOKEN_glMatrixMode 0x31 +#define EGL_TOKEN_glOrtho 0x32 +#define EGL_TOKEN_glFrustum 0x33 +#define EGL_TOKEN_glViewport 0x34 +#define EGL_TOKEN_glPushMatrix 0x35 +#define EGL_TOKEN_glPopMatrix 0x36 +#define EGL_TOKEN_glLoadIdentity 0x37 +#define EGL_TOKEN_glLoadMatrixd 0x38 +#define EGL_TOKEN_glLoadMatrixf 0x39 +#define EGL_TOKEN_glMultMatrixd 0x3a +#define EGL_TOKEN_glMultMatrixf 0x3b +#define EGL_TOKEN_glRotated 0x3c +#define EGL_TOKEN_glRotatef 0x3d +#define EGL_TOKEN_glScaled 0x3e +#define EGL_TOKEN_glScalef 0x3f +#define EGL_TOKEN_glTranslated 0x40 +#define EGL_TOKEN_glTranslatef 0x41 +#define EGL_TOKEN_glIsList 0x42 +#define EGL_TOKEN_glDeleteLists 0x43 +#define EGL_TOKEN_glGenLists 0x44 +#define EGL_TOKEN_glNewList 0x45 +#define EGL_TOKEN_glEndList 0x46 +#define EGL_TOKEN_glCallList 0x47 +#define EGL_TOKEN_glCallLists 0x48 +#define EGL_TOKEN_glListBase 0x49 +#define EGL_TOKEN_glBegin 0x4a +#define EGL_TOKEN_glEnd 0x4b +#define EGL_TOKEN_glVertex2d 0x4c +#define EGL_TOKEN_glVertex2f 0x4d +#define EGL_TOKEN_glVertex2i 0x4e +#define EGL_TOKEN_glVertex2s 0x4f +#define EGL_TOKEN_glVertex3d 0x50 +#define EGL_TOKEN_glVertex3f 0x51 +#define EGL_TOKEN_glVertex3i 0x52 +#define EGL_TOKEN_glVertex3s 0x53 +#define EGL_TOKEN_glVertex4d 0x54 +#define EGL_TOKEN_glVertex4f 0x55 +#define EGL_TOKEN_glVertex4i 0x56 +#define EGL_TOKEN_glVertex4s 0x57 +#define EGL_TOKEN_glVertex2dv 0x58 +#define EGL_TOKEN_glVertex2fv 0x59 +#define EGL_TOKEN_glVertex2iv 0x5a +#define EGL_TOKEN_glVertex2sv 0x5b +#define EGL_TOKEN_glVertex3dv 0x5c +#define EGL_TOKEN_glVertex3fv 0x5d +#define EGL_TOKEN_glVertex3iv 0x5e +#define EGL_TOKEN_glVertex3sv 0x5f +#define EGL_TOKEN_glVertex4dv 0x60 +#define EGL_TOKEN_glVertex4fv 0x61 +#define EGL_TOKEN_glVertex4iv 0x62 +#define EGL_TOKEN_glVertex4sv 0x63 +#define EGL_TOKEN_glNormal3b 0x64 +#define EGL_TOKEN_glNormal3d 0x65 +#define EGL_TOKEN_glNormal3f 0x66 +#define EGL_TOKEN_glNormal3i 0x67 +#define EGL_TOKEN_glNormal3s 0x68 +#define EGL_TOKEN_glNormal3bv 0x69 +#define EGL_TOKEN_glNormal3dv 0x6a +#define EGL_TOKEN_glNormal3fv 0x6b +#define EGL_TOKEN_glNormal3iv 0x6c +#define EGL_TOKEN_glNormal3sv 0x6d +#define EGL_TOKEN_glIndexd 0x6e +#define EGL_TOKEN_glIndexf 0x6f +#define EGL_TOKEN_glIndexi 0x70 +#define EGL_TOKEN_glIndexs 0x71 +#define EGL_TOKEN_glIndexub 0x72 +#define EGL_TOKEN_glIndexdv 0x73 +#define EGL_TOKEN_glIndexfv 0x74 +#define EGL_TOKEN_glIndexiv 0x75 +#define EGL_TOKEN_glIndexsv 0x76 +#define EGL_TOKEN_glIndexubv 0x77 +#define EGL_TOKEN_glColor3b 0x78 +#define EGL_TOKEN_glColor3d 0x79 +#define EGL_TOKEN_glColor3f 0x7a +#define EGL_TOKEN_glColor3i 0x7b +#define EGL_TOKEN_glColor3s 0x7c +#define EGL_TOKEN_glColor3ub 0x7d +#define EGL_TOKEN_glColor3ui 0x7e +#define EGL_TOKEN_glColor3us 0x7f +#define EGL_TOKEN_glColor4b 0x80 +#define EGL_TOKEN_glColor4d 0x81 +#define EGL_TOKEN_glColor4f 0x82 +#define EGL_TOKEN_glColor4i 0x83 +#define EGL_TOKEN_glColor4s 0x84 +#define EGL_TOKEN_glColor4ub 0x85 +#define EGL_TOKEN_glColor4ui 0x86 +#define EGL_TOKEN_glColor4us 0x87 +#define EGL_TOKEN_glColor3bv 0x88 +#define EGL_TOKEN_glColor3dv 0x89 +#define EGL_TOKEN_glColor3fv 0x8a +#define EGL_TOKEN_glColor3iv 0x8b +#define EGL_TOKEN_glColor3sv 0x8c +#define EGL_TOKEN_glColor3ubv 0x8d +#define EGL_TOKEN_glColor3uiv 0x8e +#define EGL_TOKEN_glColor3usv 0x8f +#define EGL_TOKEN_glColor4bv 0x90 +#define EGL_TOKEN_glColor4dv 0x91 +#define EGL_TOKEN_glColor4fv 0x92 +#define EGL_TOKEN_glColor4iv 0x93 +#define EGL_TOKEN_glColor4sv 0x94 +#define EGL_TOKEN_glColor4ubv 0x95 +#define EGL_TOKEN_glColor4uiv 0x96 +#define EGL_TOKEN_glColor4usv 0x97 +#define EGL_TOKEN_glTexCoord1d 0x98 +#define EGL_TOKEN_glTexCoord1f 0x99 +#define EGL_TOKEN_glTexCoord1i 0x9a +#define EGL_TOKEN_glTexCoord1s 0x9b +#define EGL_TOKEN_glTexCoord2d 0x9c +#define EGL_TOKEN_glTexCoord2f 0x9d +#define EGL_TOKEN_glTexCoord2i 0x9e +#define EGL_TOKEN_glTexCoord2s 0x9f +#define EGL_TOKEN_glTexCoord3d 0xa0 +#define EGL_TOKEN_glTexCoord3f 0xa1 +#define EGL_TOKEN_glTexCoord3i 0xa2 +#define EGL_TOKEN_glTexCoord3s 0xa3 +#define EGL_TOKEN_glTexCoord4d 0xa4 +#define EGL_TOKEN_glTexCoord4f 0xa5 +#define EGL_TOKEN_glTexCoord4i 0xa6 +#define EGL_TOKEN_glTexCoord4s 0xa7 +#define EGL_TOKEN_glTexCoord1dv 0xa8 +#define EGL_TOKEN_glTexCoord1fv 0xa9 +#define EGL_TOKEN_glTexCoord1iv 0xaa +#define EGL_TOKEN_glTexCoord1sv 0xab +#define EGL_TOKEN_glTexCoord2dv 0xac +#define EGL_TOKEN_glTexCoord2fv 0xad +#define EGL_TOKEN_glTexCoord2iv 0xae +#define EGL_TOKEN_glTexCoord2sv 0xaf +#define EGL_TOKEN_glTexCoord3dv 0xb0 +#define EGL_TOKEN_glTexCoord3fv 0xb1 +#define EGL_TOKEN_glTexCoord3iv 0xb2 +#define EGL_TOKEN_glTexCoord3sv 0xb3 +#define EGL_TOKEN_glTexCoord4dv 0xb4 +#define EGL_TOKEN_glTexCoord4fv 0xb5 +#define EGL_TOKEN_glTexCoord4iv 0xb6 +#define EGL_TOKEN_glTexCoord4sv 0xb7 +#define EGL_TOKEN_glRasterPos2d 0xb8 +#define EGL_TOKEN_glRasterPos2f 0xb9 +#define EGL_TOKEN_glRasterPos2i 0xba +#define EGL_TOKEN_glRasterPos2s 0xbb +#define EGL_TOKEN_glRasterPos3d 0xbc +#define EGL_TOKEN_glRasterPos3f 0xbd +#define EGL_TOKEN_glRasterPos3i 0xbe +#define EGL_TOKEN_glRasterPos3s 0xbf +#define EGL_TOKEN_glRasterPos4d 0xc0 +#define EGL_TOKEN_glRasterPos4f 0xc1 +#define EGL_TOKEN_glRasterPos4i 0xc2 +#define EGL_TOKEN_glRasterPos4s 0xc3 +#define EGL_TOKEN_glRasterPos2dv 0xc4 +#define EGL_TOKEN_glRasterPos2fv 0xc5 +#define EGL_TOKEN_glRasterPos2iv 0xc6 +#define EGL_TOKEN_glRasterPos2sv 0xc7 +#define EGL_TOKEN_glRasterPos3dv 0xc8 +#define EGL_TOKEN_glRasterPos3fv 0xc9 +#define EGL_TOKEN_glRasterPos3iv 0xca +#define EGL_TOKEN_glRasterPos3sv 0xcb +#define EGL_TOKEN_glRasterPos4dv 0xcc +#define EGL_TOKEN_glRasterPos4fv 0xcd +#define EGL_TOKEN_glRasterPos4iv 0xce +#define EGL_TOKEN_glRasterPos4sv 0xcf +#define EGL_TOKEN_glRectd 0xd0 +#define EGL_TOKEN_glRectf 0xd1 +#define EGL_TOKEN_glRecti 0xd2 +#define EGL_TOKEN_glRects 0xd3 +#define EGL_TOKEN_glRectdv 0xd4 +#define EGL_TOKEN_glRectfv 0xd5 +#define EGL_TOKEN_glRectiv 0xd6 +#define EGL_TOKEN_glRectsv 0xd7 +#define EGL_TOKEN_glVertexPointer 0xd8 +#define EGL_TOKEN_glNormalPointer 0xd9 +#define EGL_TOKEN_glColorPointer 0xda +#define EGL_TOKEN_glIndexPointer 0xdb +#define EGL_TOKEN_glTexCoordPointer 0xdc +#define EGL_TOKEN_glEdgeFlagPointer 0xdd +#define EGL_TOKEN_glGetPointerv 0xde +#define EGL_TOKEN_glArrayElement 0xdf +#define EGL_TOKEN_glDrawArrays 0xe0 +#define EGL_TOKEN_glDrawElements 0xe1 +#define EGL_TOKEN_glInterleavedArrays 0xe2 +#define EGL_TOKEN_glShadeModel 0xe3 +#define EGL_TOKEN_glLightf 0xe4 +#define EGL_TOKEN_glLighti 0xe5 +#define EGL_TOKEN_glLightfv 0xe6 +#define EGL_TOKEN_glLightiv 0xe7 +#define EGL_TOKEN_glGetLightfv 0xe8 +#define EGL_TOKEN_glGetLightiv 0xe9 +#define EGL_TOKEN_glLightModelf 0xea +#define EGL_TOKEN_glLightModeli 0xeb +#define EGL_TOKEN_glLightModelfv 0xec +#define EGL_TOKEN_glLightModeliv 0xed +#define EGL_TOKEN_glMaterialf 0xee +#define EGL_TOKEN_glMateriali 0xef +#define EGL_TOKEN_glMaterialfv 0xf0 +#define EGL_TOKEN_glMaterialiv 0xf1 +#define EGL_TOKEN_glGetMaterialfv 0xf2 +#define EGL_TOKEN_glGetMaterialiv 0xf3 +#define EGL_TOKEN_glColorMaterial 0xf4 +#define EGL_TOKEN_glPixelZoom 0xf5 +#define EGL_TOKEN_glPixelStoref 0xf6 +#define EGL_TOKEN_glPixelStorei 0xf7 +#define EGL_TOKEN_glPixelTransferf 0xf8 +#define EGL_TOKEN_glPixelTransferi 0xf9 +#define EGL_TOKEN_glPixelMapfv 0xfa +#define EGL_TOKEN_glPixelMapuiv 0xfb +#define EGL_TOKEN_glPixelMapusv 0xfc +#define EGL_TOKEN_glGetPixelMapfv 0xfd +#define EGL_TOKEN_glGetPixelMapuiv 0xfe +#define EGL_TOKEN_glGetPixelMapusv 0xff +#define EGL_TOKEN_glBitmap 0x100 +#define EGL_TOKEN_glReadPixels 0x101 +#define EGL_TOKEN_glDrawPixels 0x102 +#define EGL_TOKEN_glCopyPixels 0x103 +#define EGL_TOKEN_glStencilFunc 0x104 +#define EGL_TOKEN_glStencilMask 0x105 +#define EGL_TOKEN_glStencilOp 0x106 +#define EGL_TOKEN_glClearStencil 0x107 +#define EGL_TOKEN_glTexGend 0x108 +#define EGL_TOKEN_glTexGenf 0x109 +#define EGL_TOKEN_glTexGeni 0x10a +#define EGL_TOKEN_glTexGendv 0x10b +#define EGL_TOKEN_glTexGenfv 0x10c +#define EGL_TOKEN_glTexGeniv 0x10d +#define EGL_TOKEN_glGetTexGendv 0x10e +#define EGL_TOKEN_glGetTexGenfv 0x10f +#define EGL_TOKEN_glGetTexGeniv 0x110 +#define EGL_TOKEN_glTexEnvf 0x111 +#define EGL_TOKEN_glTexEnvi 0x112 +#define EGL_TOKEN_glTexEnvfv 0x113 +#define EGL_TOKEN_glTexEnviv 0x114 +#define EGL_TOKEN_glGetTexEnvfv 0x115 +#define EGL_TOKEN_glGetTexEnviv 0x116 +#define EGL_TOKEN_glTexParameterf 0x117 +#define EGL_TOKEN_glTexParameteri 0x118 +#define EGL_TOKEN_glTexParameterfv 0x119 +#define EGL_TOKEN_glTexParameteriv 0x11a +#define EGL_TOKEN_glGetTexParameterfv 0x11b +#define EGL_TOKEN_glGetTexParameteriv 0x11c +#define EGL_TOKEN_glGetTexLevelParameterfv 0x11d +#define EGL_TOKEN_glGetTexLevelParameteriv 0x11e +#define EGL_TOKEN_glTexImage1D 0x11f +#define EGL_TOKEN_glTexImage2D 0x120 +#define EGL_TOKEN_glGetTexImage 0x121 +#define EGL_TOKEN_glGenTextures 0x122 +#define EGL_TOKEN_glDeleteTextures 0x123 +#define EGL_TOKEN_glBindTexture 0x124 +#define EGL_TOKEN_glPrioritizeTextures 0x125 +#define EGL_TOKEN_glAreTexturesResident 0x126 +#define EGL_TOKEN_glIsTexture 0x127 +#define EGL_TOKEN_glTexSubImage1D 0x128 +#define EGL_TOKEN_glTexSubImage2D 0x129 +#define EGL_TOKEN_glCopyTexImage1D 0x12a +#define EGL_TOKEN_glCopyTexImage2D 0x12b +#define EGL_TOKEN_glCopyTexSubImage1D 0x12c +#define EGL_TOKEN_glCopyTexSubImage2D 0x12d +#define EGL_TOKEN_glMap1d 0x12e +#define EGL_TOKEN_glMap1f 0x12f +#define EGL_TOKEN_glMap2d 0x130 +#define EGL_TOKEN_glMap2f 0x131 +#define EGL_TOKEN_glGetMapdv 0x132 +#define EGL_TOKEN_glGetMapfv 0x133 +#define EGL_TOKEN_glGetMapiv 0x134 +#define EGL_TOKEN_glEvalCoord1d 0x135 +#define EGL_TOKEN_glEvalCoord1f 0x136 +#define EGL_TOKEN_glEvalCoord1dv 0x137 +#define EGL_TOKEN_glEvalCoord1fv 0x138 +#define EGL_TOKEN_glEvalCoord2d 0x139 +#define EGL_TOKEN_glEvalCoord2f 0x13a +#define EGL_TOKEN_glEvalCoord2dv 0x13b +#define EGL_TOKEN_glEvalCoord2fv 0x13c +#define EGL_TOKEN_glMapGrid1d 0x13d +#define EGL_TOKEN_glMapGrid1f 0x13e +#define EGL_TOKEN_glMapGrid2d 0x13f +#define EGL_TOKEN_glMapGrid2f 0x140 +#define EGL_TOKEN_glEvalPoint1 0x141 +#define EGL_TOKEN_glEvalPoint2 0x142 +#define EGL_TOKEN_glEvalMesh1 0x143 +#define EGL_TOKEN_glEvalMesh2 0x144 +#define EGL_TOKEN_glFogf 0x145 +#define EGL_TOKEN_glFogi 0x146 +#define EGL_TOKEN_glFogfv 0x147 +#define EGL_TOKEN_glFogiv 0x148 +#define EGL_TOKEN_glFeedbackBuffer 0x149 +#define EGL_TOKEN_glPassThrough 0x14a +#define EGL_TOKEN_glSelectBuffer 0x14b +#define EGL_TOKEN_glInitNames 0x14c +#define EGL_TOKEN_glLoadName 0x14d +#define EGL_TOKEN_glPushName 0x14e +#define EGL_TOKEN_glPopName 0x14f +#define EGL_TOKEN_glDrawRangeElements 0x150 +#define EGL_TOKEN_glTexImage3D 0x151 +#define EGL_TOKEN_glTexSubImage3D 0x152 +#define EGL_TOKEN_glCopyTexSubImage3D 0x153 +#define EGL_TOKEN_glColorTable 0x154 +#define EGL_TOKEN_glColorSubTable 0x155 +#define EGL_TOKEN_glColorTableParameteriv 0x156 +#define EGL_TOKEN_glColorTableParameterfv 0x157 +#define EGL_TOKEN_glCopyColorSubTable 0x158 +#define EGL_TOKEN_glCopyColorTable 0x159 +#define EGL_TOKEN_glGetColorTable 0x15a +#define EGL_TOKEN_glGetColorTableParameterfv 0x15b +#define EGL_TOKEN_glGetColorTableParameteriv 0x15c +#define EGL_TOKEN_glBlendEquation 0x15d +#define EGL_TOKEN_glBlendColor 0x15e +#define EGL_TOKEN_glHistogram 0x15f +#define EGL_TOKEN_glResetHistogram 0x160 +#define EGL_TOKEN_glGetHistogram 0x161 +#define EGL_TOKEN_glGetHistogramParameterfv 0x162 +#define EGL_TOKEN_glGetHistogramParameteriv 0x163 +#define EGL_TOKEN_glMinmax 0x164 +#define EGL_TOKEN_glResetMinmax 0x165 +#define EGL_TOKEN_glGetMinmax 0x166 +#define EGL_TOKEN_glGetMinmaxParameterfv 0x167 +#define EGL_TOKEN_glGetMinmaxParameteriv 0x168 +#define EGL_TOKEN_glConvolutionFilter1D 0x169 +#define EGL_TOKEN_glConvolutionFilter2D 0x16a +#define EGL_TOKEN_glConvolutionParameterf 0x16b +#define EGL_TOKEN_glConvolutionParameterfv 0x16c +#define EGL_TOKEN_glConvolutionParameteri 0x16d +#define EGL_TOKEN_glConvolutionParameteriv 0x16e +#define EGL_TOKEN_glCopyConvolutionFilter1D 0x16f +#define EGL_TOKEN_glCopyConvolutionFilter2D 0x170 +#define EGL_TOKEN_glGetConvolutionFilter 0x171 +#define EGL_TOKEN_glGetConvolutionParameterfv 0x172 +#define EGL_TOKEN_glGetConvolutionParameteriv 0x173 +#define EGL_TOKEN_glSeparableFilter2D 0x174 +#define EGL_TOKEN_glGetSeparableFilter 0x175 +#define EGL_TOKEN_glActiveTexture 0x176 +#define EGL_TOKEN_glClientActiveTexture 0x177 +#define EGL_TOKEN_glCompressedTexImage1D 0x178 +#define EGL_TOKEN_glCompressedTexImage2D 0x179 +#define EGL_TOKEN_glCompressedTexImage3D 0x17a +#define EGL_TOKEN_glCompressedTexSubImage1D 0x17b +#define EGL_TOKEN_glCompressedTexSubImage2D 0x17c +#define EGL_TOKEN_glCompressedTexSubImage3D 0x17d +#define EGL_TOKEN_glGetCompressedTexImage 0x17e +#define EGL_TOKEN_glMultiTexCoord1d 0x17f +#define EGL_TOKEN_glMultiTexCoord1dv 0x180 +#define EGL_TOKEN_glMultiTexCoord1f 0x181 +#define EGL_TOKEN_glMultiTexCoord1fv 0x182 +#define EGL_TOKEN_glMultiTexCoord1i 0x183 +#define EGL_TOKEN_glMultiTexCoord1iv 0x184 +#define EGL_TOKEN_glMultiTexCoord1s 0x185 +#define EGL_TOKEN_glMultiTexCoord1sv 0x186 +#define EGL_TOKEN_glMultiTexCoord2d 0x187 +#define EGL_TOKEN_glMultiTexCoord2dv 0x188 +#define EGL_TOKEN_glMultiTexCoord2f 0x189 +#define EGL_TOKEN_glMultiTexCoord2fv 0x18a +#define EGL_TOKEN_glMultiTexCoord2i 0x18b +#define EGL_TOKEN_glMultiTexCoord2iv 0x18c +#define EGL_TOKEN_glMultiTexCoord2s 0x18d +#define EGL_TOKEN_glMultiTexCoord2sv 0x18e +#define EGL_TOKEN_glMultiTexCoord3d 0x18f +#define EGL_TOKEN_glMultiTexCoord3dv 0x190 +#define EGL_TOKEN_glMultiTexCoord3f 0x191 +#define EGL_TOKEN_glMultiTexCoord3fv 0x192 +#define EGL_TOKEN_glMultiTexCoord3i 0x193 +#define EGL_TOKEN_glMultiTexCoord3iv 0x194 +#define EGL_TOKEN_glMultiTexCoord3s 0x195 +#define EGL_TOKEN_glMultiTexCoord3sv 0x196 +#define EGL_TOKEN_glMultiTexCoord4d 0x197 +#define EGL_TOKEN_glMultiTexCoord4dv 0x198 +#define EGL_TOKEN_glMultiTexCoord4f 0x199 +#define EGL_TOKEN_glMultiTexCoord4fv 0x19a +#define EGL_TOKEN_glMultiTexCoord4i 0x19b +#define EGL_TOKEN_glMultiTexCoord4iv 0x19c +#define EGL_TOKEN_glMultiTexCoord4s 0x19d +#define EGL_TOKEN_glMultiTexCoord4sv 0x19e +#define EGL_TOKEN_glLoadTransposeMatrixd 0x19f +#define EGL_TOKEN_glLoadTransposeMatrixf 0x1a0 +#define EGL_TOKEN_glMultTransposeMatrixd 0x1a1 +#define EGL_TOKEN_glMultTransposeMatrixf 0x1a2 +#define EGL_TOKEN_glSampleCoverage 0x1a3 +#define EGL_TOKEN_glActiveTextureARB 0x1a4 +#define EGL_TOKEN_glClientActiveTextureARB 0x1a5 +#define EGL_TOKEN_glMultiTexCoord1dARB 0x1a6 +#define EGL_TOKEN_glMultiTexCoord1dvARB 0x1a7 +#define EGL_TOKEN_glMultiTexCoord1fARB 0x1a8 +#define EGL_TOKEN_glMultiTexCoord1fvARB 0x1a9 +#define EGL_TOKEN_glMultiTexCoord1iARB 0x1aa +#define EGL_TOKEN_glMultiTexCoord1ivARB 0x1ab +#define EGL_TOKEN_glMultiTexCoord1sARB 0x1ac +#define EGL_TOKEN_glMultiTexCoord1svARB 0x1ad +#define EGL_TOKEN_glMultiTexCoord2dARB 0x1ae +#define EGL_TOKEN_glMultiTexCoord2dvARB 0x1af +#define EGL_TOKEN_glMultiTexCoord2fARB 0x1b0 +#define EGL_TOKEN_glMultiTexCoord2fvARB 0x1b1 +#define EGL_TOKEN_glMultiTexCoord2iARB 0x1b2 +#define EGL_TOKEN_glMultiTexCoord2ivARB 0x1b3 +#define EGL_TOKEN_glMultiTexCoord2sARB 0x1b4 +#define EGL_TOKEN_glMultiTexCoord2svARB 0x1b5 +#define EGL_TOKEN_glMultiTexCoord3dARB 0x1b6 +#define EGL_TOKEN_glMultiTexCoord3dvARB 0x1b7 +#define EGL_TOKEN_glMultiTexCoord3fARB 0x1b8 +#define EGL_TOKEN_glMultiTexCoord3fvARB 0x1b9 +#define EGL_TOKEN_glMultiTexCoord3iARB 0x1ba +#define EGL_TOKEN_glMultiTexCoord3ivARB 0x1bb +#define EGL_TOKEN_glMultiTexCoord3sARB 0x1bc +#define EGL_TOKEN_glMultiTexCoord3svARB 0x1bd +#define EGL_TOKEN_glMultiTexCoord4dARB 0x1be +#define EGL_TOKEN_glMultiTexCoord4dvARB 0x1bf +#define EGL_TOKEN_glMultiTexCoord4fARB 0x1c0 +#define EGL_TOKEN_glMultiTexCoord4fvARB 0x1c1 +#define EGL_TOKEN_glMultiTexCoord4iARB 0x1c2 +#define EGL_TOKEN_glMultiTexCoord4ivARB 0x1c3 +#define EGL_TOKEN_glMultiTexCoord4sARB 0x1c4 +#define EGL_TOKEN_glMultiTexCoord4svARB 0x1c5 + +#endif diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_void.h b/Code/Physics/Glut/EmptyGL/GL/egl_void.h new file mode 100644 index 00000000..82cb7e36 --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/egl_void.h @@ -0,0 +1,422 @@ +#define glClearIndex(_a0) {(void)(_a0);} +#define glClearColor(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glIndexMask(_a0) {(void)(_a0);} +#define glColorMask(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glAlphaFunc(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glBlendFunc(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glLogicOp(_a0) {(void)(_a0);} +#define glCullFace(_a0) {(void)(_a0);} +#define glFrontFace(_a0) {(void)(_a0);} +#define glPointSize(_a0) {(void)(_a0);} +#define glLineWidth(_a0) {(void)(_a0);} +#define glLineStipple(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPolygonMode(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPolygonOffset(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPolygonStipple(_a0) {(void)(_a0);} +#define glGetPolygonStipple(_a0) {(void)(_a0);} +#define glEdgeFlag(_a0) {(void)(_a0);} +#define glEdgeFlagv(_a0) {(void)(_a0);} +#define glScissor(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glClipPlane(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glGetClipPlane(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glDrawBuffer(_a0) {(void)(_a0);} +#define glReadBuffer(_a0) {(void)(_a0);} +#define glEnable(_a0) {(void)(_a0);} +#define glDisable(_a0) {(void)(_a0);} +#define glEnableClientState(_a0) {(void)(_a0);} +#define glDisableClientState(_a0) {(void)(_a0);} +#define glPushAttrib(_a0) {(void)(_a0);} +#define glPopAttrib() {} +#define glPushClientAttrib(_a0) {(void)(_a0);} +#define glPopClientAttrib() {} +#define glHint(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glClearDepth(_a0) {(void)(_a0);} +#define glDepthFunc(_a0) {(void)(_a0);} +#define glDepthMask(_a0) {(void)(_a0);} +#define glDepthRange(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glClearAccum(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glAccum(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glDeleteLists(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glNewList(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glEndList() {} +#define glCallList(_a0) {(void)(_a0);} +#define glCallLists(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glListBase(_a0) {(void)(_a0);} +#define glBegin(_a0) {(void)(_a0);} +#define glEnd() {} +#define glVertex2d(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glVertex2f(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glVertex2i(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glVertex2s(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glVertex3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glVertex3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glVertex3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glVertex3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glVertex4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glVertex4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glVertex4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glVertex4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glVertex2dv(_a0) {(void)(_a0);} +#define glVertex2fv(_a0) {(void)(_a0);} +#define glVertex2iv(_a0) {(void)(_a0);} +#define glVertex2sv(_a0) {(void)(_a0);} +#define glVertex3dv(_a0) {(void)(_a0);} +#define glVertex3fv(_a0) {(void)(_a0);} +#define glVertex3iv(_a0) {(void)(_a0);} +#define glVertex3sv(_a0) {(void)(_a0);} +#define glVertex4dv(_a0) {(void)(_a0);} +#define glVertex4fv(_a0) {(void)(_a0);} +#define glVertex4iv(_a0) {(void)(_a0);} +#define glVertex4sv(_a0) {(void)(_a0);} +#define glNormal3b(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glNormal3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glNormal3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glNormal3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glNormal3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glNormal3bv(_a0) {(void)(_a0);} +#define glNormal3dv(_a0) {(void)(_a0);} +#define glNormal3fv(_a0) {(void)(_a0);} +#define glNormal3iv(_a0) {(void)(_a0);} +#define glNormal3sv(_a0) {(void)(_a0);} +#define glIndexd(_a0) {(void)(_a0);} +#define glIndexf(_a0) {(void)(_a0);} +#define glIndexi(_a0) {(void)(_a0);} +#define glIndexs(_a0) {(void)(_a0);} +#define glIndexub(_a0) {(void)(_a0);} +#define glIndexdv(_a0) {(void)(_a0);} +#define glIndexfv(_a0) {(void)(_a0);} +#define glIndexiv(_a0) {(void)(_a0);} +#define glIndexsv(_a0) {(void)(_a0);} +#define glIndexubv(_a0) {(void)(_a0);} +#define glColor3b(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3ub(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3ui(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor3us(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColor4b(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4ub(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4ui(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor4us(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glColor3bv(_a0) {(void)(_a0);} +#define glColor3dv(_a0) {(void)(_a0);} +#define glColor3fv(_a0) {(void)(_a0);} +#define glColor3iv(_a0) {(void)(_a0);} +#define glColor3sv(_a0) {(void)(_a0);} +#define glColor3ubv(_a0) {(void)(_a0);} +#define glColor3uiv(_a0) {(void)(_a0);} +#define glColor3usv(_a0) {(void)(_a0);} +#define glColor4bv(_a0) {(void)(_a0);} +#define glColor4dv(_a0) {(void)(_a0);} +#define glColor4fv(_a0) {(void)(_a0);} +#define glColor4iv(_a0) {(void)(_a0);} +#define glColor4sv(_a0) {(void)(_a0);} +#define glColor4ubv(_a0) {(void)(_a0);} +#define glColor4uiv(_a0) {(void)(_a0);} +#define glColor4usv(_a0) {(void)(_a0);} +#define glTexCoord1d(_a0) {(void)(_a0);} +#define glTexCoord1f(_a0) {(void)(_a0);} +#define glTexCoord1i(_a0) {(void)(_a0);} +#define glTexCoord1s(_a0) {(void)(_a0);} +#define glTexCoord2d(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glTexCoord2f(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glTexCoord2i(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glTexCoord2s(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glTexCoord3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexCoord3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexCoord3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexCoord3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexCoord4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glTexCoord4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glTexCoord4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glTexCoord4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glTexCoord1dv(_a0) {(void)(_a0);} +#define glTexCoord1fv(_a0) {(void)(_a0);} +#define glTexCoord1iv(_a0) {(void)(_a0);} +#define glTexCoord1sv(_a0) {(void)(_a0);} +#define glTexCoord2dv(_a0) {(void)(_a0);} +#define glTexCoord2fv(_a0) {(void)(_a0);} +#define glTexCoord2iv(_a0) {(void)(_a0);} +#define glTexCoord2sv(_a0) {(void)(_a0);} +#define glTexCoord3dv(_a0) {(void)(_a0);} +#define glTexCoord3fv(_a0) {(void)(_a0);} +#define glTexCoord3iv(_a0) {(void)(_a0);} +#define glTexCoord3sv(_a0) {(void)(_a0);} +#define glTexCoord4dv(_a0) {(void)(_a0);} +#define glTexCoord4fv(_a0) {(void)(_a0);} +#define glTexCoord4iv(_a0) {(void)(_a0);} +#define glTexCoord4sv(_a0) {(void)(_a0);} +#define glRasterPos2d(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRasterPos2f(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRasterPos2i(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRasterPos2s(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRasterPos3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glRasterPos3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glRasterPos3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glRasterPos3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glRasterPos4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRasterPos4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRasterPos4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRasterPos4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRasterPos2dv(_a0) {(void)(_a0);} +#define glRasterPos2fv(_a0) {(void)(_a0);} +#define glRasterPos2iv(_a0) {(void)(_a0);} +#define glRasterPos2sv(_a0) {(void)(_a0);} +#define glRasterPos3dv(_a0) {(void)(_a0);} +#define glRasterPos3fv(_a0) {(void)(_a0);} +#define glRasterPos3iv(_a0) {(void)(_a0);} +#define glRasterPos3sv(_a0) {(void)(_a0);} +#define glRasterPos4dv(_a0) {(void)(_a0);} +#define glRasterPos4fv(_a0) {(void)(_a0);} +#define glRasterPos4iv(_a0) {(void)(_a0);} +#define glRasterPos4sv(_a0) {(void)(_a0);} +#define glRectd(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRectf(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRecti(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRects(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glRectdv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRectfv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRectiv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glRectsv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glVertexPointer(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glNormalPointer(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColorPointer(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glIndexPointer(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexCoordPointer(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glEdgeFlagPointer(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glGetPointerv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glArrayElement(_a0) {(void)(_a0);} +#define glDrawArrays(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glDrawElements(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glInterleavedArrays(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glShadeModel(_a0) {(void)(_a0);} +#define glLightf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glLighti(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glLightfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glLightiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetLightfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetLightiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glLightModelf(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glLightModeli(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glLightModelfv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glLightModeliv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMaterialf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMateriali(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMaterialfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMaterialiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetMaterialfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetMaterialiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColorMaterial(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPixelZoom(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPixelStoref(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPixelStorei(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPixelTransferf(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPixelTransferi(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPixelMapfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glPixelMapuiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glPixelMapusv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetPixelMapfv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glGetPixelMapuiv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glGetPixelMapusv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glBitmap(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glReadPixels(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glDrawPixels(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glCopyPixels(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glStencilFunc(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glStencilMask(_a0) {(void)(_a0);} +#define glStencilOp(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glClearStencil(_a0) {(void)(_a0);} +#define glTexGend(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexGenf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexGeni(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexGendv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexGenfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexGeniv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexGendv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexGenfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexGeniv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexEnvf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexEnvi(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexEnvfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexEnviv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexEnvfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexEnviv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexParameterf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexParameteri(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetTexLevelParameterfv(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glGetTexLevelParameteriv(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glTexImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} +#define glTexImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} +#define glGetTexImage(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glGenTextures(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glDeleteTextures(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glBindTexture(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glPrioritizeTextures(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glTexSubImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glTexSubImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} +#define glCopyTexImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glCopyTexImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} +#define glCopyTexSubImage1D(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glCopyTexSubImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} +#define glMap1d(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glMap1f(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glMap2d(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);} +#define glMap2f(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);} +#define glGetMapdv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetMapfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetMapiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glEvalCoord1d(_a0) {(void)(_a0);} +#define glEvalCoord1f(_a0) {(void)(_a0);} +#define glEvalCoord1dv(_a0) {(void)(_a0);} +#define glEvalCoord1fv(_a0) {(void)(_a0);} +#define glEvalCoord2d(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glEvalCoord2f(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glEvalCoord2dv(_a0) {(void)(_a0);} +#define glEvalCoord2fv(_a0) {(void)(_a0);} +#define glMapGrid1d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMapGrid1f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMapGrid2d(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glMapGrid2f(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glEvalPoint1(_a0) {(void)(_a0);} +#define glEvalPoint2(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glEvalMesh1(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glEvalMesh2(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glFogf(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glFogi(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glFogfv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glFogiv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glFeedbackBuffer(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glPassThrough(_a0) {(void)(_a0);} +#define glSelectBuffer(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glInitNames() {} +#define glLoadName(_a0) {(void)(_a0);} +#define glPushName(_a0) {(void)(_a0);} +#define glPopName() {} +#define glDrawRangeElements(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glTexImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);} +#define glTexSubImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9,_a10) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);(void)(_a10);} +#define glCopyTexSubImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} +#define glColorTable(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glColorSubTable(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glColorTableParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glColorTableParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glCopyColorSubTable(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glCopyColorTable(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glGetColorTable(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glGetColorTableParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetColorTableParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glBlendEquation(_a0) {(void)(_a0);} +#define glBlendColor(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glHistogram(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glResetHistogram(_a0) {(void)(_a0);} +#define glGetHistogram(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glGetHistogramParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetHistogramParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMinmax(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glResetMinmax(_a0) {(void)(_a0);} +#define glGetMinmax(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glGetMinmaxParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetMinmaxParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glConvolutionFilter1D(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glConvolutionFilter2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glConvolutionParameterf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glConvolutionParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glConvolutionParameteri(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glConvolutionParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glCopyConvolutionFilter1D(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glCopyConvolutionFilter2D(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glGetConvolutionFilter(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glGetConvolutionParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glGetConvolutionParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glSeparableFilter2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} +#define glGetSeparableFilter(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} +#define glActiveTexture(_a0) {(void)(_a0);} +#define glClientActiveTexture(_a0) {(void)(_a0);} +#define glCompressedTexImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glCompressedTexImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} +#define glCompressedTexImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} +#define glCompressedTexSubImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} +#define glCompressedTexSubImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} +#define glCompressedTexSubImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9,_a10) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);(void)(_a10);} +#define glGetCompressedTexImage(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord1d(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1dv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1f(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1fv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1i(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1iv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1s(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1sv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2dv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2fv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2iv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2sv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3dv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3fv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3iv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3sv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4d(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4dv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4f(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4fv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4i(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4iv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4s(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4sv(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glLoadTransposeMatrixd(_a0) {(void)(_a0);} +#define glLoadTransposeMatrixf(_a0) {(void)(_a0);} +#define glMultTransposeMatrixd(_a0) {(void)(_a0);} +#define glMultTransposeMatrixf(_a0) {(void)(_a0);} +#define glSampleCoverage(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glActiveTextureARB(_a0) {(void)(_a0);} +#define glClientActiveTextureARB(_a0) {(void)(_a0);} +#define glMultiTexCoord1dARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1fARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1iARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1sARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord1svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2dARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2fARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2iARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord2sARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} +#define glMultiTexCoord2svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3dARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3fARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3iARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord3sARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} +#define glMultiTexCoord3svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4dARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4fARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4iARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} +#define glMultiTexCoord4sARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} +#define glMultiTexCoord4svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} diff --git a/Code/Physics/Glut/EmptyGL/GL/gl.h b/Code/Physics/Glut/EmptyGL/GL/gl.h new file mode 100644 index 00000000..ee588a60 --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/gl.h @@ -0,0 +1,47 @@ +#ifndef __EGL_H +#define __EGL_H + +// include types and defines + +#include + +// include log tokens + +#include + +// include simple void functions we ignore + +#include + +// include functions that need a bit of work, but we don't log + +#include + +// include functions we log + +#ifdef EGL_LOG_PTR + +extern unsigned int *EGL_LOG_PTR; + +inline void xGLL(int a) { *EGL_LOG_PTR=(unsigned int)a; EGL_LOG_PTR++; }; +inline void xGLL(unsigned int a) { *EGL_LOG_PTR=a; EGL_LOG_PTR++; }; +inline void xGLL(float a) { *(float *)EGL_LOG_PTR=a; EGL_LOG_PTR++; }; +inline void xGLL(double a) { *(float *)EGL_LOG_PTR=(float)a; EGL_LOG_PTR++; }; +inline void xGLL(const float *a) { for(int t=0;t!=16;t++) xGLL(a[t]); }; +inline void xGLL(const double *a) { for(int t=0;t!=16;t++) xGLL(a[t]); }; +#else + +inline void xGLL(int a) {}; +inline void xGLL(unsigned int a) {}; +inline void xGLL(float a) {}; +inline void xGLL(double a) {}; +inline void xGLL(const float *a) {}; +inline void xGLL(const double *a) {}; + +#endif + +// functions we might log + +#include + +#endif diff --git a/Code/Physics/Glut/EmptyGL/GL/glu.h b/Code/Physics/Glut/EmptyGL/GL/glu.h new file mode 100644 index 00000000..95a40b2c --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/glu.h @@ -0,0 +1,23 @@ +#ifndef EMPTY_GLU +#define EMPTY_GLU + +inline void gluOrtho2D( int a,int b, int c ,int d ) { } ; +inline void gluLookAt( + GLfloat a,GLfloat b, GLfloat c, + GLfloat d,GLfloat e, GLfloat f, + GLfloat g,GLfloat h, GLfloat i ) { }; + +#define GLU_FILL 1 +#define GLU_SMOOTH 2 + +typedef int GLUquadric; +typedef GLUquadric GLUquadricObj; + +inline GLUquadric *gluNewQuadric() { return (GLUquadric *)1; }; +inline void gluQuadricDrawStyle( GLUquadric *o, int mode) {}; +inline void gluQuadricNormals( GLUquadric *o, int mode) {}; +inline void gluDeleteQuadric( GLUquadric *q) {}; +inline void gluDisk (GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops) {}; +inline void gluCylinder (GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks) {}; +inline int gluBuild2DMipmaps (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, const void *data) { return 0;} +#endif diff --git a/Code/Physics/Glut/EmptyGL/GL/glut.h b/Code/Physics/Glut/EmptyGL/GL/glut.h new file mode 100644 index 00000000..9007ecda --- /dev/null +++ b/Code/Physics/Glut/EmptyGL/GL/glut.h @@ -0,0 +1,60 @@ +#ifndef EMPTY_GLUT_H +#define EMPTY_GLUT_H + +#include +#include + + +#define GLUT_KEY_F1 0 +#define GLUT_KEY_F2 1 +#define GLUT_KEY_END 2 +#define GLUT_KEY_LEFT 3 +#define GLUT_KEY_RIGHT 4 +#define GLUT_KEY_UP 5 +#define GLUT_KEY_DOWN 6 +#define GLUT_KEY_PAGE_UP 7 +#define GLUT_KEY_PAGE_DOWN 8 +#define GLUT_KEY_HOME 9 +#define GLUT_KEY_F3 10 +#define GLUT_KEY_F4 11 +#define GLUT_KEY_F5 12 +#define GLUT_ACTIVE_SHIFT 13 + + +#define GLUT_DOUBLE 1 +#define GLUT_RGBA 2 +#define GLUT_DEPTH 4 +#define GLUT_STENCIL 8 +#define GLUT_WINDOW_WIDTH 16 +#define GLUT_WINDOW_HEIGHT 32 +#define GLUT_RGB 64 + + + + +inline void glutSwapBuffers() {} +inline void glutShowWindow() {} +inline void glutPostRedisplay() {} +inline void glutInit(int *argc, char **argv) {} +inline void glutInitDisplayMode( unsigned int ) {} +inline void glutInitWindowPosition(int x, int y) {} +inline void glutInitWindowSize(int x, int y) {} +inline int glutCreateWindow( const char *str) {return 0;} +inline void glutKeyboardFunc( void (*func)(unsigned char, int ,int ) ) {} +inline void glutSpecialFunc( void (*func)(int key, int x,int y) ) {} +inline void glutSpecialUpFunc( void (*func)(int key, int x,int y) ) {} +inline void glutReshapeFunc( void (*func)(int w,int h) ) {} +inline void glutDisplayFunc( void (*func)() ) {} +inline void glutIdleFunc( void (*func)() ) {} +inline void glutMotionFunc( void (*func)(int x,int y) ) {} +inline void glutMouseFunc( void (*func)(int button,int state,int x,int y) ) {} +inline void glutMainLoop() {} +inline void glutSetWindow(int bla) {} + +inline void glutSolidCube(GLfloat ) {} +inline void glutSolidSphere(GLfloat , int a , int b) {} +inline void glutSolidCone(GLfloat ,GLfloat , int a , int b) {} +inline int glutGetModifiers() { return 0;} +inline void gluPerspective(float a,float b,float c,float d) {} +inline float glutGet(int code) { return 0.f;} +#endif diff --git a/Code/Physics/Glut/GL/glew.h b/Code/Physics/Glut/GL/glew.h new file mode 100644 index 00000000..f70103d1 --- /dev/null +++ b/Code/Physics/Glut/GL/glew.h @@ -0,0 +1,15507 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glew_h__ +#define __glew_h__ +#define __GLEW_H__ + +#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H) +#error gl.h included before glew.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error glext.h included before glew.h +#endif +#if defined(__gl_ATI_h_) +#error glATI.h included before glew.h +#endif + +#define __gl_h_ +#define __GL_H__ +#define __X_GL_H +#define __glext_h_ +#define __GLEXT_H_ +#define __gl_ATI_h_ + +#if defined(_WIN32) + +/* + * GLEW does not include to avoid name space pollution. + * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t + * defined properly. + */ +/* */ +#ifndef APIENTRY +#define GLEW_APIENTRY_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define APIENTRY __stdcall +# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +#endif +#ifndef GLAPI +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define GLAPI extern +# endif +#endif +/* */ +#ifndef CALLBACK +#define GLEW_CALLBACK_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define CALLBACK __attribute__ ((__stdcall__)) +# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +#endif +/* and */ +#ifndef WINGDIAPI +#define GLEW_WINGDIAPI_DEFINED +#define WINGDIAPI __declspec(dllimport) +#endif +/* */ +#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +#endif +/* */ +#if !defined(_W64) +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif +#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) && !defined(__MINGW64__) +# ifdef _WIN64 +typedef __int64 ptrdiff_t; +# else +typedef _W64 int ptrdiff_t; +# endif +# define _PTRDIFF_T_DEFINED +# define _PTRDIFF_T_ +#endif + +#ifndef GLAPI +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define GLAPI extern +# else +# define GLAPI WINGDIAPI +# endif +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY APIENTRY +#endif + +/* + * GLEW_STATIC is defined for static library. + * GLEW_BUILD is defined for building the DLL library. + */ + +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#else /* _UNIX */ + +/* + * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO + * C. On my system, this amounts to _3 lines_ of included code, all of + * them pretty much harmless. If you know of a way of detecting 32 vs + * 64 _targets_ at compile time you are free to replace this with + * something that's portable. For now, _this_ is the portable solution. + * (mem, 2004-01-04) + */ + +#include + +/* SGI MIPSPro doesn't like stdint.h in C++ mode */ + +#if defined(__sgi) && !defined(__GNUC__) +#include +#else +#include +#endif + +#define GLEW_APIENTRY_DEFINED +#define APIENTRY + +/* + * GLEW_STATIC is defined for static library. + */ + +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# if defined(__GNUC__) && __GNUC__>=4 +# define GLEWAPI extern __attribute__ ((visibility("default"))) +# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define GLEWAPI extern __global +# else +# define GLEWAPI extern +# endif +#endif + +/* */ +#ifndef GLAPI +#define GLAPI extern +#endif +#ifndef GLAPIENTRY +#define GLAPIENTRY +#endif + +#endif /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------- GL_VERSION_1_1 ---------------------------- */ + +#ifndef GL_VERSION_1_1 +#define GL_VERSION_1_1 1 + +typedef unsigned int GLenum; +typedef unsigned int GLbitfield; +typedef unsigned int GLuint; +typedef int GLint; +typedef int GLsizei; +typedef unsigned char GLboolean; +typedef signed char GLbyte; +typedef short GLshort; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned long GLulong; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void GLvoid; +#if defined(_MSC_VER) && _MSC_VER < 1400 +typedef __int64 GLint64EXT; +typedef unsigned __int64 GLuint64EXT; +#elif defined(_MSC_VER) || defined(__BORLANDC__) +typedef signed long long GLint64EXT; +typedef unsigned long long GLuint64EXT; +#else +# if defined(__MINGW32__) || defined(__CYGWIN__) +#include +# endif +typedef int64_t GLint64EXT; +typedef uint64_t GLuint64EXT; +#endif +typedef GLint64EXT GLint64; +typedef GLuint64EXT GLuint64; +typedef struct __GLsync *GLsync; + +typedef char GLchar; + +#define GL_ZERO 0 +#define GL_FALSE 0 +#define GL_LOGIC_OP 0x0BF1 +#define GL_NONE 0 +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_NO_ERROR 0 +#define GL_POINTS 0x0000 +#define GL_CURRENT_BIT 0x00000001 +#define GL_TRUE 1 +#define GL_ONE 1 +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_POINT_BIT 0x00000002 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_BIT 0x00000004 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON 0x0009 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM 0x0100 +#define GL_LOAD 0x0101 +#define GL_RETURN 0x0102 +#define GL_MULT 0x0103 +#define GL_ADD 0x0104 +#define GL_NEVER 0x0200 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_EXP 0x0800 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_EXP2 0x0801 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LIST_MODE 0x0B30 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_SHADE_MODEL 0x0B54 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_FOG 0x0B60 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_NORMALIZE 0x0BA1 +#define GL_VIEWPORT 0x0BA2 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_INDEX_MODE 0x0C30 +#define GL_RGBA_MODE 0x0C31 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_RENDER_MODE 0x0C40 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_INDEX_BITS 0x0D51 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_COLOR_INDEX 0x1900 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_BITMAP 0x1A00 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_RENDER 0x1C00 +#define GL_FEEDBACK 0x1C01 +#define GL_SELECT 0x1C02 +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_S 0x2000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_ENV 0x2300 +#define GL_EYE_LINEAR 0x2400 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_SPHERE_MAP 0x2402 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_PLANE 0x2502 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_CLAMP 0x2900 +#define GL_REPEAT 0x2901 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_R3_G3_B2 0x2A10 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_LIGHT0 0x4000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_HINT_BIT 0x00008000 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000fffff +#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff + +GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value); +GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref); +GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences); +GLAPI void GLAPIENTRY glArrayElement (GLint i); +GLAPI void GLAPIENTRY glBegin (GLenum mode); +GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void GLAPIENTRY glCallList (GLuint list); +GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists); +GLAPI void GLAPIENTRY glClear (GLbitfield mask); +GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GLAPI void GLAPIENTRY glClearDepth (GLclampd depth); +GLAPI void GLAPIENTRY glClearIndex (GLfloat c); +GLAPI void GLAPIENTRY glClearStencil (GLint s); +GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation); +GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue); +GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue); +GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue); +GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue); +GLAPI void GLAPIENTRY glColor3iv (const GLint *v); +GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue); +GLAPI void GLAPIENTRY glColor3sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue); +GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue); +GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue); +GLAPI void GLAPIENTRY glColor3usv (const GLushort *v); +GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha); +GLAPI void GLAPIENTRY glColor4iv (const GLint *v); +GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha); +GLAPI void GLAPIENTRY glColor4sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha); +GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha); +GLAPI void GLAPIENTRY glColor4usv (const GLushort *v); +GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glCullFace (GLenum mode); +GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range); +GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GLAPI void GLAPIENTRY glDepthFunc (GLenum func); +GLAPI void GLAPIENTRY glDepthMask (GLboolean flag); +GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar); +GLAPI void GLAPIENTRY glDisable (GLenum cap); +GLAPI void GLAPIENTRY glDisableClientState (GLenum array); +GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode); +GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag); +GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag); +GLAPI void GLAPIENTRY glEnable (GLenum cap); +GLAPI void GLAPIENTRY glEnableClientState (GLenum array); +GLAPI void GLAPIENTRY glEnd (void); +GLAPI void GLAPIENTRY glEndList (void); +GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u); +GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u); +GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v); +GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v); +GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2); +GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +GLAPI void GLAPIENTRY glEvalPoint1 (GLint i); +GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j); +GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer); +GLAPI void GLAPIENTRY glFinish (void); +GLAPI void GLAPIENTRY glFlush (void); +GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glFrontFace (GLenum mode); +GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range); +GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures); +GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params); +GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation); +GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params); +GLAPI GLenum GLAPIENTRY glGetError (void); +GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v); +GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v); +GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v); +GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values); +GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values); +GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values); +GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params); +GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask); +GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name); +GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); +GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode); +GLAPI void GLAPIENTRY glIndexMask (GLuint mask); +GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glIndexd (GLdouble c); +GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c); +GLAPI void GLAPIENTRY glIndexf (GLfloat c); +GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c); +GLAPI void GLAPIENTRY glIndexi (GLint c); +GLAPI void GLAPIENTRY glIndexiv (const GLint *c); +GLAPI void GLAPIENTRY glIndexs (GLshort c); +GLAPI void GLAPIENTRY glIndexsv (const GLshort *c); +GLAPI void GLAPIENTRY glIndexub (GLubyte c); +GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c); +GLAPI void GLAPIENTRY glInitNames (void); +GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); +GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap); +GLAPI GLboolean GLAPIENTRY glIsList (GLuint list); +GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture); +GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern); +GLAPI void GLAPIENTRY glLineWidth (GLfloat width); +GLAPI void GLAPIENTRY glListBase (GLuint base); +GLAPI void GLAPIENTRY glLoadIdentity (void); +GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glLoadName (GLuint name); +GLAPI void GLAPIENTRY glLogicOp (GLenum opcode); +GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2); +GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2); +GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glMatrixMode (GLenum mode); +GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode); +GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz); +GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz); +GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); +GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz); +GLAPI void GLAPIENTRY glNormal3iv (const GLint *v); +GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz); +GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v); +GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void GLAPIENTRY glPassThrough (GLfloat token); +GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values); +GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values); +GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values); +GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor); +GLAPI void GLAPIENTRY glPointSize (GLfloat size); +GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask); +GLAPI void GLAPIENTRY glPopAttrib (void); +GLAPI void GLAPIENTRY glPopClientAttrib (void); +GLAPI void GLAPIENTRY glPopMatrix (void); +GLAPI void GLAPIENTRY glPopName (void); +GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities); +GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushMatrix (void); +GLAPI void GLAPIENTRY glPushName (GLuint name); +GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v); +GLAPI void GLAPIENTRY glReadBuffer (GLenum mode); +GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2); +GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2); +GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2); +GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2); +GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2); +GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2); +GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode); +GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer); +GLAPI void GLAPIENTRY glShadeModel (GLenum mode); +GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void GLAPIENTRY glStencilMask (GLuint mask); +GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s); +GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s); +GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord1i (GLint s); +GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord1s (GLshort s); +GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t); +GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t); +GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t); +GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t); +GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r); +GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); +GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r); +GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r); +GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q); +GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param); +GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params); +GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glVertex2iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glVertex3iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glVertex4iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1) + +#endif /* GL_VERSION_1_1 */ + +/* ---------------------------------- GLU ---------------------------------- */ + +#ifndef GLEW_NO_GLU +/* this is where we can safely include GLU */ +# if defined(__APPLE__) && defined(__MACH__) +# include +# else +# include +# endif +#endif + +/* ----------------------------- GL_VERSION_1_2 ---------------------------- */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 + +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + +#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D) +#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements) +#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D) +#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D) + +#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2) + +#endif /* GL_VERSION_1_2 */ + +/* ---------------------------- GL_VERSION_1_2_1 --------------------------- */ + +#ifndef GL_VERSION_1_2_1 +#define GL_VERSION_1_2_1 1 + +#define GLEW_VERSION_1_2_1 GLEW_GET_VAR(__GLEW_VERSION_1_2_1) + +#endif /* GL_VERSION_1_2_1 */ + +/* ----------------------------- GL_VERSION_1_3 ---------------------------- */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 + +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_SUBTRACT 0x84E7 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_MULTISAMPLE_BIT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); + +#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture) +#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture) +#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D) +#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D) +#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D) +#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D) +#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D) +#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D) +#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage) +#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd) +#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf) +#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd) +#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf) +#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d) +#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv) +#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f) +#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv) +#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i) +#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv) +#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s) +#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv) +#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d) +#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv) +#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f) +#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv) +#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i) +#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv) +#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s) +#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv) +#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d) +#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv) +#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f) +#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv) +#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i) +#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv) +#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s) +#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv) +#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d) +#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv) +#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f) +#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv) +#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i) +#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv) +#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s) +#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv) +#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage) + +#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3) + +#endif /* GL_VERSION_1_3 */ + +/* ----------------------------- GL_VERSION_1_4 ---------------------------- */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E + +typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p); + +#define glBlendColor GLEW_GET_FUN(__glewBlendColor) +#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation) +#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate) +#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer) +#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd) +#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv) +#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf) +#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv) +#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays) +#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements) +#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf) +#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv) +#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri) +#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv) +#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b) +#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv) +#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d) +#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv) +#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f) +#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv) +#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i) +#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv) +#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s) +#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv) +#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub) +#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv) +#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui) +#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv) +#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us) +#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv) +#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer) +#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d) +#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv) +#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f) +#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv) +#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i) +#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv) +#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s) +#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv) +#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d) +#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv) +#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f) +#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv) +#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i) +#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv) +#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s) +#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv) + +#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4) + +#endif /* GL_VERSION_1_4 */ + +/* ----------------------------- GL_VERSION_1_5 ---------------------------- */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 + +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 + +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); +typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target); + +#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery) +#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer) +#define glBufferData GLEW_GET_FUN(__glewBufferData) +#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData) +#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers) +#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries) +#define glEndQuery GLEW_GET_FUN(__glewEndQuery) +#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) +#define glGenQueries GLEW_GET_FUN(__glewGenQueries) +#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv) +#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv) +#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData) +#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv) +#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv) +#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv) +#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer) +#define glIsQuery GLEW_GET_FUN(__glewIsQuery) +#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer) +#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer) + +#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5) + +#endif /* GL_VERSION_1_5 */ + +/* ----------------------------- GL_VERSION_2_0 ---------------------------- */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 + +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source); +typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths); +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); + +#define glAttachShader GLEW_GET_FUN(__glewAttachShader) +#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) +#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) +#define glCompileShader GLEW_GET_FUN(__glewCompileShader) +#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram) +#define glCreateShader GLEW_GET_FUN(__glewCreateShader) +#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram) +#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader) +#define glDetachShader GLEW_GET_FUN(__glewDetachShader) +#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray) +#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers) +#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray) +#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib) +#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform) +#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders) +#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation) +#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog) +#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv) +#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog) +#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource) +#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv) +#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation) +#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv) +#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv) +#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv) +#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv) +#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv) +#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv) +#define glIsProgram GLEW_GET_FUN(__glewIsProgram) +#define glIsShader GLEW_GET_FUN(__glewIsShader) +#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram) +#define glShaderSource GLEW_GET_FUN(__glewShaderSource) +#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate) +#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate) +#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate) +#define glUniform1f GLEW_GET_FUN(__glewUniform1f) +#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv) +#define glUniform1i GLEW_GET_FUN(__glewUniform1i) +#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv) +#define glUniform2f GLEW_GET_FUN(__glewUniform2f) +#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv) +#define glUniform2i GLEW_GET_FUN(__glewUniform2i) +#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv) +#define glUniform3f GLEW_GET_FUN(__glewUniform3f) +#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv) +#define glUniform3i GLEW_GET_FUN(__glewUniform3i) +#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv) +#define glUniform4f GLEW_GET_FUN(__glewUniform4f) +#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv) +#define glUniform4i GLEW_GET_FUN(__glewUniform4i) +#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv) +#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv) +#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv) +#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv) +#define glUseProgram GLEW_GET_FUN(__glewUseProgram) +#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram) +#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d) +#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv) +#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f) +#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv) +#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s) +#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv) +#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d) +#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv) +#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f) +#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv) +#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s) +#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv) +#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d) +#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv) +#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f) +#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv) +#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s) +#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv) +#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv) +#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv) +#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv) +#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub) +#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv) +#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv) +#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv) +#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv) +#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d) +#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv) +#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f) +#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv) +#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv) +#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s) +#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv) +#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv) +#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) +#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) +#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) + +#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) + +#endif /* GL_VERSION_2_0 */ + +/* ----------------------------- GL_VERSION_2_1 ---------------------------- */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 + +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B + +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + +#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv) +#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv) +#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv) +#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv) +#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv) +#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv) + +#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1) + +#endif /* GL_VERSION_2_1 */ + +/* ----------------------------- GL_VERSION_3_0 ---------------------------- */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 + +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_DEPTH_BUFFER 0x8223 +#define GL_STENCIL_BUFFER 0x8224 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum); +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*); +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*); +typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*); + +#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender) +#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback) +#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation) +#define glClampColor GLEW_GET_FUN(__glewClampColor) +#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi) +#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv) +#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv) +#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv) +#define glColorMaski GLEW_GET_FUN(__glewColorMaski) +#define glDisablei GLEW_GET_FUN(__glewDisablei) +#define glEnablei GLEW_GET_FUN(__glewEnablei) +#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender) +#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback) +#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v) +#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation) +#define glGetStringi GLEW_GET_FUN(__glewGetStringi) +#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv) +#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv) +#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying) +#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv) +#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv) +#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv) +#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi) +#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv) +#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv) +#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings) +#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui) +#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv) +#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui) +#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv) +#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui) +#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv) +#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui) +#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv) +#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i) +#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv) +#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui) +#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv) +#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i) +#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv) +#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui) +#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv) +#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i) +#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv) +#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui) +#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv) +#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv) +#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i) +#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv) +#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv) +#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv) +#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui) +#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv) +#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv) +#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer) + +#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0) + +#endif /* GL_VERSION_3_0 */ + +/* ----------------------------- GL_VERSION_3_1 ---------------------------- */ + +#ifndef GL_VERSION_3_1 +#define GL_VERSION_3_1 1 + +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint); + +#define glDrawArraysInstanced GLEW_GET_FUN(__glewDrawArraysInstanced) +#define glDrawElementsInstanced GLEW_GET_FUN(__glewDrawElementsInstanced) +#define glPrimitiveRestartIndex GLEW_GET_FUN(__glewPrimitiveRestartIndex) +#define glTexBuffer GLEW_GET_FUN(__glewTexBuffer) + +#define GLEW_VERSION_3_1 GLEW_GET_VAR(__GLEW_VERSION_3_1) + +#endif /* GL_VERSION_3_1 */ + +/* ----------------------------- GL_VERSION_3_2 ---------------------------- */ + +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 + +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum, GLenum, GLint64 *); +typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *); + +#define glFramebufferTexture GLEW_GET_FUN(__glewFramebufferTexture) +#define glGetBufferParameteri64v GLEW_GET_FUN(__glewGetBufferParameteri64v) +#define glGetInteger64i_v GLEW_GET_FUN(__glewGetInteger64i_v) + +#define GLEW_VERSION_3_2 GLEW_GET_VAR(__GLEW_VERSION_3_2) + +#endif /* GL_VERSION_3_2 */ + +/* ----------------------------- GL_VERSION_3_3 ---------------------------- */ + +#ifndef GL_VERSION_3_3 +#define GL_VERSION_3_3 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_RGB10_A2UI 0x906F + +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); + +#define glVertexAttribDivisor GLEW_GET_FUN(__glewVertexAttribDivisor) + +#define GLEW_VERSION_3_3 GLEW_GET_VAR(__GLEW_VERSION_3_3) + +#endif /* GL_VERSION_3_3 */ + +/* ----------------------------- GL_VERSION_4_0 ---------------------------- */ + +#ifndef GL_VERSION_4_0 +#define GL_VERSION_4_0 1 + +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value); + +#define glBlendEquationSeparatei GLEW_GET_FUN(__glewBlendEquationSeparatei) +#define glBlendEquationi GLEW_GET_FUN(__glewBlendEquationi) +#define glBlendFuncSeparatei GLEW_GET_FUN(__glewBlendFuncSeparatei) +#define glBlendFunci GLEW_GET_FUN(__glewBlendFunci) +#define glMinSampleShading GLEW_GET_FUN(__glewMinSampleShading) + +#define GLEW_VERSION_4_0 GLEW_GET_VAR(__GLEW_VERSION_4_0) + +#endif /* GL_VERSION_4_0 */ + +/* ----------------------------- GL_VERSION_4_1 ---------------------------- */ + +#ifndef GL_VERSION_4_1 +#define GL_VERSION_4_1 1 + +#define GLEW_VERSION_4_1 GLEW_GET_VAR(__GLEW_VERSION_4_1) + +#endif /* GL_VERSION_4_1 */ + +/* -------------------------- GL_3DFX_multisample -------------------------- */ + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 + +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 + +#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample) + +#endif /* GL_3DFX_multisample */ + +/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */ + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 + +typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); + +#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX) + +#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer) + +#endif /* GL_3DFX_tbuffer */ + +/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */ + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 + +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 + +#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1) + +#endif /* GL_3DFX_texture_compression_FXT1 */ + +/* ----------------------- GL_AMD_blend_minmax_factor ---------------------- */ + +#ifndef GL_AMD_blend_minmax_factor +#define GL_AMD_blend_minmax_factor 1 + +#define GL_FACTOR_MIN_AMD 0x901C +#define GL_FACTOR_MAX_AMD 0x901D + +#define GLEW_AMD_blend_minmax_factor GLEW_GET_VAR(__GLEW_AMD_blend_minmax_factor) + +#endif /* GL_AMD_blend_minmax_factor */ + +/* ----------------------- GL_AMD_conservative_depth ----------------------- */ + +#ifndef GL_AMD_conservative_depth +#define GL_AMD_conservative_depth 1 + +#define GLEW_AMD_conservative_depth GLEW_GET_VAR(__GLEW_AMD_conservative_depth) + +#endif /* GL_AMD_conservative_depth */ + +/* -------------------------- GL_AMD_debug_output -------------------------- */ + +#ifndef GL_AMD_debug_output +#define GL_AMD_debug_output 1 + +#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147 +#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148 +#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149 +#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A +#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B +#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C +#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D +#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E +#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F +#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 + +typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message); + +#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD) +#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD) +#define glDebugMessageInsertAMD GLEW_GET_FUN(__glewDebugMessageInsertAMD) +#define glGetDebugMessageLogAMD GLEW_GET_FUN(__glewGetDebugMessageLogAMD) + +#define GLEW_AMD_debug_output GLEW_GET_VAR(__GLEW_AMD_debug_output) + +#endif /* GL_AMD_debug_output */ + +/* ---------------------- GL_AMD_depth_clamp_separate ---------------------- */ + +#ifndef GL_AMD_depth_clamp_separate +#define GL_AMD_depth_clamp_separate 1 + +#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E +#define GL_DEPTH_CLAMP_FAR_AMD 0x901F + +#define GLEW_AMD_depth_clamp_separate GLEW_GET_VAR(__GLEW_AMD_depth_clamp_separate) + +#endif /* GL_AMD_depth_clamp_separate */ + +/* ----------------------- GL_AMD_draw_buffers_blend ----------------------- */ + +#ifndef GL_AMD_draw_buffers_blend +#define GL_AMD_draw_buffers_blend 1 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +#define glBlendEquationIndexedAMD GLEW_GET_FUN(__glewBlendEquationIndexedAMD) +#define glBlendEquationSeparateIndexedAMD GLEW_GET_FUN(__glewBlendEquationSeparateIndexedAMD) +#define glBlendFuncIndexedAMD GLEW_GET_FUN(__glewBlendFuncIndexedAMD) +#define glBlendFuncSeparateIndexedAMD GLEW_GET_FUN(__glewBlendFuncSeparateIndexedAMD) + +#define GLEW_AMD_draw_buffers_blend GLEW_GET_VAR(__GLEW_AMD_draw_buffers_blend) + +#endif /* GL_AMD_draw_buffers_blend */ + +/* ------------------------- GL_AMD_name_gen_delete ------------------------ */ + +#ifndef GL_AMD_name_gen_delete +#define GL_AMD_name_gen_delete 1 + +#define GL_DATA_BUFFER_AMD 0x9151 +#define GL_PERFORMANCE_MONITOR_AMD 0x9152 +#define GL_QUERY_OBJECT_AMD 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154 +#define GL_SAMPLER_OBJECT_AMD 0x9155 + +typedef void (GLAPIENTRY * PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint* names); +typedef void (GLAPIENTRY * PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint* names); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name); + +#define glDeleteNamesAMD GLEW_GET_FUN(__glewDeleteNamesAMD) +#define glGenNamesAMD GLEW_GET_FUN(__glewGenNamesAMD) +#define glIsNameAMD GLEW_GET_FUN(__glewIsNameAMD) + +#define GLEW_AMD_name_gen_delete GLEW_GET_VAR(__GLEW_AMD_name_gen_delete) + +#endif /* GL_AMD_name_gen_delete */ + +/* ----------------------- GL_AMD_performance_monitor ---------------------- */ + +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 + +typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); +typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList); + +#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD) +#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD) +#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD) +#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD) +#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD) +#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD) +#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD) +#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD) +#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD) +#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD) +#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD) + +#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor) + +#endif /* GL_AMD_performance_monitor */ + +/* ------------------------ GL_AMD_sample_positions ------------------------ */ + +#ifndef GL_AMD_sample_positions +#define GL_AMD_sample_positions 1 + +#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F + +typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat* val); + +#define glSetMultisamplefvAMD GLEW_GET_FUN(__glewSetMultisamplefvAMD) + +#define GLEW_AMD_sample_positions GLEW_GET_VAR(__GLEW_AMD_sample_positions) + +#endif /* GL_AMD_sample_positions */ + +/* ------------------ GL_AMD_seamless_cubemap_per_texture ------------------ */ + +#ifndef GL_AMD_seamless_cubemap_per_texture +#define GL_AMD_seamless_cubemap_per_texture 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB 0x884F + +#define GLEW_AMD_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_AMD_seamless_cubemap_per_texture) + +#endif /* GL_AMD_seamless_cubemap_per_texture */ + +/* ---------------------- GL_AMD_shader_stencil_export --------------------- */ + +#ifndef GL_AMD_shader_stencil_export +#define GL_AMD_shader_stencil_export 1 + +#define GLEW_AMD_shader_stencil_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_export) + +#endif /* GL_AMD_shader_stencil_export */ + +/* ------------------------ GL_AMD_texture_texture4 ------------------------ */ + +#ifndef GL_AMD_texture_texture4 +#define GL_AMD_texture_texture4 1 + +#define GLEW_AMD_texture_texture4 GLEW_GET_VAR(__GLEW_AMD_texture_texture4) + +#endif /* GL_AMD_texture_texture4 */ + +/* --------------- GL_AMD_transform_feedback3_lines_triangles -------------- */ + +#ifndef GL_AMD_transform_feedback3_lines_triangles +#define GL_AMD_transform_feedback3_lines_triangles 1 + +#define GLEW_AMD_transform_feedback3_lines_triangles GLEW_GET_VAR(__GLEW_AMD_transform_feedback3_lines_triangles) + +#endif /* GL_AMD_transform_feedback3_lines_triangles */ + +/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */ + +#ifndef GL_AMD_vertex_shader_tessellator +#define GL_AMD_vertex_shader_tessellator 1 + +#define GL_SAMPLER_BUFFER_AMD 0x9001 +#define GL_INT_SAMPLER_BUFFER_AMD 0x9002 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003 +#define GL_TESSELLATION_MODE_AMD 0x9004 +#define GL_TESSELLATION_FACTOR_AMD 0x9005 +#define GL_DISCRETE_AMD 0x9006 +#define GL_CONTINUOUS_AMD 0x9007 + +typedef void (GLAPIENTRY * PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); + +#define glTessellationFactorAMD GLEW_GET_FUN(__glewTessellationFactorAMD) +#define glTessellationModeAMD GLEW_GET_FUN(__glewTessellationModeAMD) + +#define GLEW_AMD_vertex_shader_tessellator GLEW_GET_VAR(__GLEW_AMD_vertex_shader_tessellator) + +#endif /* GL_AMD_vertex_shader_tessellator */ + +/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */ + +#ifndef GL_APPLE_aux_depth_stencil +#define GL_APPLE_aux_depth_stencil 1 + +#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 + +#define GLEW_APPLE_aux_depth_stencil GLEW_GET_VAR(__GLEW_APPLE_aux_depth_stencil) + +#endif /* GL_APPLE_aux_depth_stencil */ + +/* ------------------------ GL_APPLE_client_storage ------------------------ */ + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 + +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 + +#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage) + +#endif /* GL_APPLE_client_storage */ + +/* ------------------------- GL_APPLE_element_array ------------------------ */ + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 + +#define GL_ELEMENT_ARRAY_APPLE 0x8A0C +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); + +#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE) +#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE) +#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE) + +#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array) + +#endif /* GL_APPLE_element_array */ + +/* ----------------------------- GL_APPLE_fence ---------------------------- */ + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 + +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); + +#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE) +#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE) +#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE) +#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE) +#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE) +#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE) +#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE) +#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE) + +#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence) + +#endif /* GL_APPLE_fence */ + +/* ------------------------- GL_APPLE_float_pixels ------------------------- */ + +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels 1 + +#define GL_HALF_APPLE 0x140B +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#define GL_COLOR_FLOAT_APPLE 0x8A0F + +#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels) + +#endif /* GL_APPLE_float_pixels */ + +/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */ + +#ifndef GL_APPLE_flush_buffer_range +#define GL_APPLE_flush_buffer_range 1 + +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 + +typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); + +#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE) +#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE) + +#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range) + +#endif /* GL_APPLE_flush_buffer_range */ + +/* ----------------------- GL_APPLE_object_purgeable ----------------------- */ + +#ifndef GL_APPLE_object_purgeable +#define GL_APPLE_object_purgeable 1 + +#define GL_BUFFER_OBJECT_APPLE 0x85B3 +#define GL_RELEASED_APPLE 0x8A19 +#define GL_VOLATILE_APPLE 0x8A1A +#define GL_RETAINED_APPLE 0x8A1B +#define GL_UNDEFINED_APPLE 0x8A1C +#define GL_PURGEABLE_APPLE 0x8A1D + +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params); +typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); + +#define glGetObjectParameterivAPPLE GLEW_GET_FUN(__glewGetObjectParameterivAPPLE) +#define glObjectPurgeableAPPLE GLEW_GET_FUN(__glewObjectPurgeableAPPLE) +#define glObjectUnpurgeableAPPLE GLEW_GET_FUN(__glewObjectUnpurgeableAPPLE) + +#define GLEW_APPLE_object_purgeable GLEW_GET_VAR(__GLEW_APPLE_object_purgeable) + +#endif /* GL_APPLE_object_purgeable */ + +/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */ + +#ifndef GL_APPLE_pixel_buffer +#define GL_APPLE_pixel_buffer 1 + +#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10 + +#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer) + +#endif /* GL_APPLE_pixel_buffer */ + +/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */ + +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 + +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#define GL_RGB_422_APPLE 0x8A1F + +#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422) + +#endif /* GL_APPLE_rgb_422 */ + +/* --------------------------- GL_APPLE_row_bytes -------------------------- */ + +#ifndef GL_APPLE_row_bytes +#define GL_APPLE_row_bytes 1 + +#define GL_PACK_ROW_BYTES_APPLE 0x8A15 +#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 + +#define GLEW_APPLE_row_bytes GLEW_GET_VAR(__GLEW_APPLE_row_bytes) + +#endif /* GL_APPLE_row_bytes */ + +/* ------------------------ GL_APPLE_specular_vector ----------------------- */ + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 + +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 + +#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector) + +#endif /* GL_APPLE_specular_vector */ + +/* ------------------------- GL_APPLE_texture_range ------------------------ */ + +#ifndef GL_APPLE_texture_range +#define GL_APPLE_texture_range 1 + +#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 +#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 +#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC +#define GL_STORAGE_PRIVATE_APPLE 0x85BD +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params); +typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer); + +#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE) +#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE) + +#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range) + +#endif /* GL_APPLE_texture_range */ + +/* ------------------------ GL_APPLE_transform_hint ------------------------ */ + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 + +#define GL_TRANSFORM_HINT_APPLE 0x85B1 + +#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint) + +#endif /* GL_APPLE_transform_hint */ + +/* ---------------------- GL_APPLE_vertex_array_object --------------------- */ + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); + +#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE) + +#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object) + +#endif /* GL_APPLE_vertex_array_object */ + +/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */ + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CLIENT_APPLE 0x85B4 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) +#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE) + +#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range) + +#endif /* GL_APPLE_vertex_array_range */ + +/* ------------------- GL_APPLE_vertex_program_evaluators ------------------ */ + +#ifndef GL_APPLE_vertex_program_evaluators +#define GL_APPLE_vertex_program_evaluators 1 + +#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 +#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 +#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 +#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 +#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 +#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 +#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 +#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 +#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 +#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 + +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points); + +#define glDisableVertexAttribAPPLE GLEW_GET_FUN(__glewDisableVertexAttribAPPLE) +#define glEnableVertexAttribAPPLE GLEW_GET_FUN(__glewEnableVertexAttribAPPLE) +#define glIsVertexAttribEnabledAPPLE GLEW_GET_FUN(__glewIsVertexAttribEnabledAPPLE) +#define glMapVertexAttrib1dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1dAPPLE) +#define glMapVertexAttrib1fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1fAPPLE) +#define glMapVertexAttrib2dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2dAPPLE) +#define glMapVertexAttrib2fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2fAPPLE) + +#define GLEW_APPLE_vertex_program_evaluators GLEW_GET_VAR(__GLEW_APPLE_vertex_program_evaluators) + +#endif /* GL_APPLE_vertex_program_evaluators */ + +/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */ + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 + +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB + +#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422) + +#endif /* GL_APPLE_ycbcr_422 */ + +/* ------------------------ GL_ARB_ES2_compatibility ----------------------- */ + +#ifndef GL_ARB_ES2_compatibility +#define GL_ARB_ES2_compatibility 1 + +#define GL_FIXED 0x140C +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision); +typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length); + +#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf) +#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef) +#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat) +#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler) +#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary) + +#define GLEW_ARB_ES2_compatibility GLEW_GET_VAR(__GLEW_ARB_ES2_compatibility) + +#endif /* GL_ARB_ES2_compatibility */ + +/* ----------------------- GL_ARB_blend_func_extended ---------------------- */ + +#ifndef GL_ARB_blend_func_extended +#define GL_ARB_blend_func_extended 1 + +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name); + +#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed) +#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex) + +#define GLEW_ARB_blend_func_extended GLEW_GET_VAR(__GLEW_ARB_blend_func_extended) + +#endif /* GL_ARB_blend_func_extended */ + +/* ---------------------------- GL_ARB_cl_event ---------------------------- */ + +#ifndef GL_ARB_cl_event +#define GL_ARB_cl_event 1 + +#define GL_SYNC_CL_EVENT_ARB 0x8240 +#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 + +typedef struct _cl_context *cl_context; +typedef struct _cl_event *cl_event; + +typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context context, cl_event event, GLbitfield flags); + +#define glCreateSyncFromCLeventARB GLEW_GET_FUN(__glewCreateSyncFromCLeventARB) + +#define GLEW_ARB_cl_event GLEW_GET_VAR(__GLEW_ARB_cl_event) + +#endif /* GL_ARB_cl_event */ + +/* ----------------------- GL_ARB_color_buffer_float ----------------------- */ + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 + +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D + +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); + +#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB) + +#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float) + +#endif /* GL_ARB_color_buffer_float */ + +/* -------------------------- GL_ARB_compatibility ------------------------- */ + +#ifndef GL_ARB_compatibility +#define GL_ARB_compatibility 1 + +#define GLEW_ARB_compatibility GLEW_GET_VAR(__GLEW_ARB_compatibility) + +#endif /* GL_ARB_compatibility */ + +/* --------------------------- GL_ARB_copy_buffer -------------------------- */ + +#ifndef GL_ARB_copy_buffer +#define GL_ARB_copy_buffer 1 + +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 + +typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size); + +#define glCopyBufferSubData GLEW_GET_FUN(__glewCopyBufferSubData) + +#define GLEW_ARB_copy_buffer GLEW_GET_VAR(__GLEW_ARB_copy_buffer) + +#endif /* GL_ARB_copy_buffer */ + +/* -------------------------- GL_ARB_debug_output -------------------------- */ + +#ifndef GL_ARB_debug_output +#define GL_ARB_debug_output 1 + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 + +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog); + +#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB) +#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB) +#define glDebugMessageInsertARB GLEW_GET_FUN(__glewDebugMessageInsertARB) +#define glGetDebugMessageLogARB GLEW_GET_FUN(__glewGetDebugMessageLogARB) + +#define GLEW_ARB_debug_output GLEW_GET_VAR(__GLEW_ARB_debug_output) + +#endif /* GL_ARB_debug_output */ + +/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD + +#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float) + +#endif /* GL_ARB_depth_buffer_float */ + +/* --------------------------- GL_ARB_depth_clamp -------------------------- */ + +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 + +#define GL_DEPTH_CLAMP 0x864F + +#define GLEW_ARB_depth_clamp GLEW_GET_VAR(__GLEW_ARB_depth_clamp) + +#endif /* GL_ARB_depth_clamp */ + +/* -------------------------- GL_ARB_depth_texture ------------------------- */ + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B + +#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture) + +#endif /* GL_ARB_depth_texture */ + +/* -------------------------- GL_ARB_draw_buffers -------------------------- */ + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB) + +#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers) + +#endif /* GL_ARB_draw_buffers */ + +/* ----------------------- GL_ARB_draw_buffers_blend ----------------------- */ + +#ifndef GL_ARB_draw_buffers_blend +#define GL_ARB_draw_buffers_blend 1 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); + +#define glBlendEquationSeparateiARB GLEW_GET_FUN(__glewBlendEquationSeparateiARB) +#define glBlendEquationiARB GLEW_GET_FUN(__glewBlendEquationiARB) +#define glBlendFuncSeparateiARB GLEW_GET_FUN(__glewBlendFuncSeparateiARB) +#define glBlendFunciARB GLEW_GET_FUN(__glewBlendFunciARB) + +#define GLEW_ARB_draw_buffers_blend GLEW_GET_VAR(__GLEW_ARB_draw_buffers_blend) + +#endif /* GL_ARB_draw_buffers_blend */ + +/* -------------------- GL_ARB_draw_elements_base_vertex ------------------- */ + +#ifndef GL_ARB_draw_elements_base_vertex +#define GL_ARB_draw_elements_base_vertex 1 + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex); + +#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex) +#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex) +#define glDrawRangeElementsBaseVertex GLEW_GET_FUN(__glewDrawRangeElementsBaseVertex) +#define glMultiDrawElementsBaseVertex GLEW_GET_FUN(__glewMultiDrawElementsBaseVertex) + +#define GLEW_ARB_draw_elements_base_vertex GLEW_GET_VAR(__GLEW_ARB_draw_elements_base_vertex) + +#endif /* GL_ARB_draw_elements_base_vertex */ + +/* -------------------------- GL_ARB_draw_indirect ------------------------- */ + +#ifndef GL_ARB_draw_indirect +#define GL_ARB_draw_indirect 1 + +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect); + +#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect) +#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect) + +#define GLEW_ARB_draw_indirect GLEW_GET_VAR(__GLEW_ARB_draw_indirect) + +#endif /* GL_ARB_draw_indirect */ + +/* ------------------------- GL_ARB_draw_instanced ------------------------- */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 + +#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced) + +#endif /* GL_ARB_draw_instanced */ + +/* -------------------- GL_ARB_explicit_attrib_location -------------------- */ + +#ifndef GL_ARB_explicit_attrib_location +#define GL_ARB_explicit_attrib_location 1 + +#define GLEW_ARB_explicit_attrib_location GLEW_GET_VAR(__GLEW_ARB_explicit_attrib_location) + +#endif /* GL_ARB_explicit_attrib_location */ + +/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */ + +#ifndef GL_ARB_fragment_coord_conventions +#define GL_ARB_fragment_coord_conventions 1 + +#define GLEW_ARB_fragment_coord_conventions GLEW_GET_VAR(__GLEW_ARB_fragment_coord_conventions) + +#endif /* GL_ARB_fragment_coord_conventions */ + +/* ------------------------ GL_ARB_fragment_program ------------------------ */ + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 + +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 + +#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program) + +#endif /* GL_ARB_fragment_program */ + +/* --------------------- GL_ARB_fragment_program_shadow -------------------- */ + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 + +#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow) + +#endif /* GL_ARB_fragment_program_shadow */ + +/* ------------------------- GL_ARB_fragment_shader ------------------------ */ + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 + +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B + +#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader) + +#endif /* GL_ARB_fragment_shader */ + +/* ----------------------- GL_ARB_framebuffer_object ----------------------- */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_INDEX 0x8222 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_SRGB 0x8C40 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer) +#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer) +#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer) +#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus) +#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers) +#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers) +#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer) +#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D) +#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D) +#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D) +#define glFramebufferTextureLayer GLEW_GET_FUN(__glewFramebufferTextureLayer) +#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers) +#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers) +#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap) +#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv) +#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv) +#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer) +#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer) +#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage) +#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample) + +#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object) + +#endif /* GL_ARB_framebuffer_object */ + +/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB 0x8DB9 + +#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB) + +#endif /* GL_ARB_framebuffer_sRGB */ + +/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_ARB 0xA +#define GL_LINE_STRIP_ADJACENCY_ARB 0xB +#define GL_TRIANGLES_ADJACENCY_ARB 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB) +#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB) +#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB) +#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB) + +#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4) + +#endif /* GL_ARB_geometry_shader4 */ + +/* ----------------------- GL_ARB_get_program_binary ----------------------- */ + +#ifndef GL_ARB_get_program_binary +#define GL_ARB_get_program_binary 1 + +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); +typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); + +#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary) +#define glProgramBinary GLEW_GET_FUN(__glewProgramBinary) +#define glProgramParameteri GLEW_GET_FUN(__glewProgramParameteri) + +#define GLEW_ARB_get_program_binary GLEW_GET_VAR(__GLEW_ARB_get_program_binary) + +#endif /* GL_ARB_get_program_binary */ + +/* --------------------------- GL_ARB_gpu_shader5 -------------------------- */ + +#ifndef GL_ARB_gpu_shader5 +#define GL_ARB_gpu_shader5 1 + +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MAX_VERTEX_STREAMS 0x8E71 + +#define GLEW_ARB_gpu_shader5 GLEW_GET_VAR(__GLEW_ARB_gpu_shader5) + +#endif /* GL_ARB_gpu_shader5 */ + +/* ------------------------- GL_ARB_gpu_shader_fp64 ------------------------ */ + +#ifndef GL_ARB_gpu_shader_fp64 +#define GL_ARB_gpu_shader_fp64 1 + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + +#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv) +#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT) +#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT) +#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT) +#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT) +#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT) +#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT) +#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT) +#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT) +#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT) +#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT) +#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT) +#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT) +#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT) +#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT) +#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT) +#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT) +#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT) +#define glUniform1d GLEW_GET_FUN(__glewUniform1d) +#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv) +#define glUniform2d GLEW_GET_FUN(__glewUniform2d) +#define glUniform2dv GLEW_GET_FUN(__glewUniform2dv) +#define glUniform3d GLEW_GET_FUN(__glewUniform3d) +#define glUniform3dv GLEW_GET_FUN(__glewUniform3dv) +#define glUniform4d GLEW_GET_FUN(__glewUniform4d) +#define glUniform4dv GLEW_GET_FUN(__glewUniform4dv) +#define glUniformMatrix2dv GLEW_GET_FUN(__glewUniformMatrix2dv) +#define glUniformMatrix2x3dv GLEW_GET_FUN(__glewUniformMatrix2x3dv) +#define glUniformMatrix2x4dv GLEW_GET_FUN(__glewUniformMatrix2x4dv) +#define glUniformMatrix3dv GLEW_GET_FUN(__glewUniformMatrix3dv) +#define glUniformMatrix3x2dv GLEW_GET_FUN(__glewUniformMatrix3x2dv) +#define glUniformMatrix3x4dv GLEW_GET_FUN(__glewUniformMatrix3x4dv) +#define glUniformMatrix4dv GLEW_GET_FUN(__glewUniformMatrix4dv) +#define glUniformMatrix4x2dv GLEW_GET_FUN(__glewUniformMatrix4x2dv) +#define glUniformMatrix4x3dv GLEW_GET_FUN(__glewUniformMatrix4x3dv) + +#define GLEW_ARB_gpu_shader_fp64 GLEW_GET_VAR(__GLEW_ARB_gpu_shader_fp64) + +#endif /* GL_ARB_gpu_shader_fp64 */ + +/* ------------------------ GL_ARB_half_float_pixel ------------------------ */ + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 + +#define GL_HALF_FLOAT_ARB 0x140B + +#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel) + +#endif /* GL_ARB_half_float_pixel */ + +/* ------------------------ GL_ARB_half_float_vertex ----------------------- */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 + +#define GL_HALF_FLOAT 0x140B + +#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex) + +#endif /* GL_ARB_half_float_vertex */ + +/* ----------------------------- GL_ARB_imaging ---------------------------- */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 + +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_IGNORE_BORDER 0x8150 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_WRAP_BORDER 0x8152 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + +#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable) +#define glColorTable GLEW_GET_FUN(__glewColorTable) +#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv) +#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv) +#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D) +#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D) +#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf) +#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv) +#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri) +#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv) +#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable) +#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable) +#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D) +#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable) +#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv) +#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv) +#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter) +#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv) +#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv) +#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram) +#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv) +#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv) +#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax) +#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv) +#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv) +#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter) +#define glHistogram GLEW_GET_FUN(__glewHistogram) +#define glMinmax GLEW_GET_FUN(__glewMinmax) +#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram) +#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax) +#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D) + +#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging) + +#endif /* GL_ARB_imaging */ + +/* ------------------------ GL_ARB_instanced_arrays ------------------------ */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); + +#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB) +#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB) +#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB) + +#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays) + +#endif /* GL_ARB_instanced_arrays */ + +/* ------------------------ GL_ARB_map_buffer_range ------------------------ */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 + +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 + +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + +#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange) +#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange) + +#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range) + +#endif /* GL_ARB_map_buffer_range */ + +/* ------------------------- GL_ARB_matrix_palette ------------------------- */ + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 + +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 + +typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices); + +#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB) +#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB) +#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB) +#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB) +#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB) + +#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette) + +#endif /* GL_ARB_matrix_palette */ + +/* --------------------------- GL_ARB_multisample -------------------------- */ + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 + +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); + +#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB) + +#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample) + +#endif /* GL_ARB_multisample */ + +/* -------------------------- GL_ARB_multitexture -------------------------- */ + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 + +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); + +#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB) +#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB) +#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB) +#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB) +#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB) +#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB) +#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB) +#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB) +#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB) +#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB) +#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB) +#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB) +#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB) +#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB) +#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB) +#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB) +#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB) +#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB) +#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB) +#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB) +#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB) +#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB) +#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB) +#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB) +#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB) +#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB) +#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB) +#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB) +#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB) +#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB) +#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB) +#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB) +#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB) +#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB) + +#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture) + +#endif /* GL_ARB_multitexture */ + +/* ------------------------- GL_ARB_occlusion_query ------------------------ */ + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 + +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id); + +#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB) +#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB) +#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB) +#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB) +#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB) +#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB) +#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB) +#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB) + +#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query) + +#endif /* GL_ARB_occlusion_query */ + +/* ------------------------ GL_ARB_occlusion_query2 ------------------------ */ + +#ifndef GL_ARB_occlusion_query2 +#define GL_ARB_occlusion_query2 1 + +#define GL_ANY_SAMPLES_PASSED 0x8C2F + +#define GLEW_ARB_occlusion_query2 GLEW_GET_VAR(__GLEW_ARB_occlusion_query2) + +#endif /* GL_ARB_occlusion_query2 */ + +/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF + +#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object) + +#endif /* GL_ARB_pixel_buffer_object */ + +/* ------------------------ GL_ARB_point_parameters ------------------------ */ + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 + +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat* params); + +#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB) +#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB) + +#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters) + +#endif /* GL_ARB_point_parameters */ + +/* -------------------------- GL_ARB_point_sprite -------------------------- */ + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 + +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 + +#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite) + +#endif /* GL_ARB_point_sprite */ + +/* ------------------------ GL_ARB_provoking_vertex ------------------------ */ + +#ifndef GL_ARB_provoking_vertex +#define GL_ARB_provoking_vertex 1 + +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F + +typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode); + +#define glProvokingVertex GLEW_GET_FUN(__glewProvokingVertex) + +#define GLEW_ARB_provoking_vertex GLEW_GET_VAR(__GLEW_ARB_provoking_vertex) + +#endif /* GL_ARB_provoking_vertex */ + +/* --------------------------- GL_ARB_robustness --------------------------- */ + +#ifndef GL_ARB_robustness +#define GL_ARB_robustness 1 + +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 + +typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table); +typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img); +typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image); +typedef void (GLAPIENTRY * PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); +typedef void (GLAPIENTRY * PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble* v); +typedef void (GLAPIENTRY * PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat* v); +typedef void (GLAPIENTRY * PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint* v); +typedef void (GLAPIENTRY * PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values); +typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern); +typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span); +typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params); +typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data); + +#define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB) +#define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB) +#define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB) +#define glGetnHistogramARB GLEW_GET_FUN(__glewGetnHistogramARB) +#define glGetnMapdvARB GLEW_GET_FUN(__glewGetnMapdvARB) +#define glGetnMapfvARB GLEW_GET_FUN(__glewGetnMapfvARB) +#define glGetnMapivARB GLEW_GET_FUN(__glewGetnMapivARB) +#define glGetnMinmaxARB GLEW_GET_FUN(__glewGetnMinmaxARB) +#define glGetnPixelMapfvARB GLEW_GET_FUN(__glewGetnPixelMapfvARB) +#define glGetnPixelMapuivARB GLEW_GET_FUN(__glewGetnPixelMapuivARB) +#define glGetnPixelMapusvARB GLEW_GET_FUN(__glewGetnPixelMapusvARB) +#define glGetnPolygonStippleARB GLEW_GET_FUN(__glewGetnPolygonStippleARB) +#define glGetnSeparableFilterARB GLEW_GET_FUN(__glewGetnSeparableFilterARB) +#define glGetnTexImageARB GLEW_GET_FUN(__glewGetnTexImageARB) +#define glGetnUniformdvARB GLEW_GET_FUN(__glewGetnUniformdvARB) +#define glGetnUniformfvARB GLEW_GET_FUN(__glewGetnUniformfvARB) +#define glGetnUniformivARB GLEW_GET_FUN(__glewGetnUniformivARB) +#define glGetnUniformuivARB GLEW_GET_FUN(__glewGetnUniformuivARB) +#define glReadnPixelsARB GLEW_GET_FUN(__glewReadnPixelsARB) + +#define GLEW_ARB_robustness GLEW_GET_VAR(__GLEW_ARB_robustness) + +#endif /* GL_ARB_robustness */ + +/* ------------------------- GL_ARB_sample_shading ------------------------- */ + +#ifndef GL_ARB_sample_shading +#define GL_ARB_sample_shading 1 + +#define GL_SAMPLE_SHADING_ARB 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 + +typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value); + +#define glMinSampleShadingARB GLEW_GET_FUN(__glewMinSampleShadingARB) + +#define GLEW_ARB_sample_shading GLEW_GET_VAR(__GLEW_ARB_sample_shading) + +#endif /* GL_ARB_sample_shading */ + +/* ------------------------- GL_ARB_sampler_objects ------------------------ */ + +#ifndef GL_ARB_sampler_objects +#define GL_ARB_sampler_objects 1 + +#define GL_SAMPLER_BINDING 0x8919 + +typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers); +typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* params); + +#define glBindSampler GLEW_GET_FUN(__glewBindSampler) +#define glDeleteSamplers GLEW_GET_FUN(__glewDeleteSamplers) +#define glGenSamplers GLEW_GET_FUN(__glewGenSamplers) +#define glGetSamplerParameterIiv GLEW_GET_FUN(__glewGetSamplerParameterIiv) +#define glGetSamplerParameterIuiv GLEW_GET_FUN(__glewGetSamplerParameterIuiv) +#define glGetSamplerParameterfv GLEW_GET_FUN(__glewGetSamplerParameterfv) +#define glGetSamplerParameteriv GLEW_GET_FUN(__glewGetSamplerParameteriv) +#define glIsSampler GLEW_GET_FUN(__glewIsSampler) +#define glSamplerParameterIiv GLEW_GET_FUN(__glewSamplerParameterIiv) +#define glSamplerParameterIuiv GLEW_GET_FUN(__glewSamplerParameterIuiv) +#define glSamplerParameterf GLEW_GET_FUN(__glewSamplerParameterf) +#define glSamplerParameterfv GLEW_GET_FUN(__glewSamplerParameterfv) +#define glSamplerParameteri GLEW_GET_FUN(__glewSamplerParameteri) +#define glSamplerParameteriv GLEW_GET_FUN(__glewSamplerParameteriv) + +#define GLEW_ARB_sampler_objects GLEW_GET_VAR(__GLEW_ARB_sampler_objects) + +#endif /* GL_ARB_sampler_objects */ + +/* ------------------------ GL_ARB_seamless_cube_map ----------------------- */ + +#ifndef GL_ARB_seamless_cube_map +#define GL_ARB_seamless_cube_map 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define GLEW_ARB_seamless_cube_map GLEW_GET_VAR(__GLEW_ARB_seamless_cube_map) + +#endif /* GL_ARB_seamless_cube_map */ + +/* --------------------- GL_ARB_separate_shader_objects -------------------- */ + +#ifndef GL_ARB_separate_shader_objects +#define GL_ARB_separate_shader_objects 1 + +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_ALL_SHADER_BITS 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); + +#define glActiveShaderProgram GLEW_GET_FUN(__glewActiveShaderProgram) +#define glBindProgramPipeline GLEW_GET_FUN(__glewBindProgramPipeline) +#define glCreateShaderProgramv GLEW_GET_FUN(__glewCreateShaderProgramv) +#define glDeleteProgramPipelines GLEW_GET_FUN(__glewDeleteProgramPipelines) +#define glGenProgramPipelines GLEW_GET_FUN(__glewGenProgramPipelines) +#define glGetProgramPipelineInfoLog GLEW_GET_FUN(__glewGetProgramPipelineInfoLog) +#define glGetProgramPipelineiv GLEW_GET_FUN(__glewGetProgramPipelineiv) +#define glIsProgramPipeline GLEW_GET_FUN(__glewIsProgramPipeline) +#define glProgramUniform1d GLEW_GET_FUN(__glewProgramUniform1d) +#define glProgramUniform1dv GLEW_GET_FUN(__glewProgramUniform1dv) +#define glProgramUniform1f GLEW_GET_FUN(__glewProgramUniform1f) +#define glProgramUniform1fv GLEW_GET_FUN(__glewProgramUniform1fv) +#define glProgramUniform1i GLEW_GET_FUN(__glewProgramUniform1i) +#define glProgramUniform1iv GLEW_GET_FUN(__glewProgramUniform1iv) +#define glProgramUniform1ui GLEW_GET_FUN(__glewProgramUniform1ui) +#define glProgramUniform1uiv GLEW_GET_FUN(__glewProgramUniform1uiv) +#define glProgramUniform2d GLEW_GET_FUN(__glewProgramUniform2d) +#define glProgramUniform2dv GLEW_GET_FUN(__glewProgramUniform2dv) +#define glProgramUniform2f GLEW_GET_FUN(__glewProgramUniform2f) +#define glProgramUniform2fv GLEW_GET_FUN(__glewProgramUniform2fv) +#define glProgramUniform2i GLEW_GET_FUN(__glewProgramUniform2i) +#define glProgramUniform2iv GLEW_GET_FUN(__glewProgramUniform2iv) +#define glProgramUniform2ui GLEW_GET_FUN(__glewProgramUniform2ui) +#define glProgramUniform2uiv GLEW_GET_FUN(__glewProgramUniform2uiv) +#define glProgramUniform3d GLEW_GET_FUN(__glewProgramUniform3d) +#define glProgramUniform3dv GLEW_GET_FUN(__glewProgramUniform3dv) +#define glProgramUniform3f GLEW_GET_FUN(__glewProgramUniform3f) +#define glProgramUniform3fv GLEW_GET_FUN(__glewProgramUniform3fv) +#define glProgramUniform3i GLEW_GET_FUN(__glewProgramUniform3i) +#define glProgramUniform3iv GLEW_GET_FUN(__glewProgramUniform3iv) +#define glProgramUniform3ui GLEW_GET_FUN(__glewProgramUniform3ui) +#define glProgramUniform3uiv GLEW_GET_FUN(__glewProgramUniform3uiv) +#define glProgramUniform4d GLEW_GET_FUN(__glewProgramUniform4d) +#define glProgramUniform4dv GLEW_GET_FUN(__glewProgramUniform4dv) +#define glProgramUniform4f GLEW_GET_FUN(__glewProgramUniform4f) +#define glProgramUniform4fv GLEW_GET_FUN(__glewProgramUniform4fv) +#define glProgramUniform4i GLEW_GET_FUN(__glewProgramUniform4i) +#define glProgramUniform4iv GLEW_GET_FUN(__glewProgramUniform4iv) +#define glProgramUniform4ui GLEW_GET_FUN(__glewProgramUniform4ui) +#define glProgramUniform4uiv GLEW_GET_FUN(__glewProgramUniform4uiv) +#define glProgramUniformMatrix2dv GLEW_GET_FUN(__glewProgramUniformMatrix2dv) +#define glProgramUniformMatrix2fv GLEW_GET_FUN(__glewProgramUniformMatrix2fv) +#define glProgramUniformMatrix2x3dv GLEW_GET_FUN(__glewProgramUniformMatrix2x3dv) +#define glProgramUniformMatrix2x3fv GLEW_GET_FUN(__glewProgramUniformMatrix2x3fv) +#define glProgramUniformMatrix2x4dv GLEW_GET_FUN(__glewProgramUniformMatrix2x4dv) +#define glProgramUniformMatrix2x4fv GLEW_GET_FUN(__glewProgramUniformMatrix2x4fv) +#define glProgramUniformMatrix3dv GLEW_GET_FUN(__glewProgramUniformMatrix3dv) +#define glProgramUniformMatrix3fv GLEW_GET_FUN(__glewProgramUniformMatrix3fv) +#define glProgramUniformMatrix3x2dv GLEW_GET_FUN(__glewProgramUniformMatrix3x2dv) +#define glProgramUniformMatrix3x2fv GLEW_GET_FUN(__glewProgramUniformMatrix3x2fv) +#define glProgramUniformMatrix3x4dv GLEW_GET_FUN(__glewProgramUniformMatrix3x4dv) +#define glProgramUniformMatrix3x4fv GLEW_GET_FUN(__glewProgramUniformMatrix3x4fv) +#define glProgramUniformMatrix4dv GLEW_GET_FUN(__glewProgramUniformMatrix4dv) +#define glProgramUniformMatrix4fv GLEW_GET_FUN(__glewProgramUniformMatrix4fv) +#define glProgramUniformMatrix4x2dv GLEW_GET_FUN(__glewProgramUniformMatrix4x2dv) +#define glProgramUniformMatrix4x2fv GLEW_GET_FUN(__glewProgramUniformMatrix4x2fv) +#define glProgramUniformMatrix4x3dv GLEW_GET_FUN(__glewProgramUniformMatrix4x3dv) +#define glProgramUniformMatrix4x3fv GLEW_GET_FUN(__glewProgramUniformMatrix4x3fv) +#define glUseProgramStages GLEW_GET_FUN(__glewUseProgramStages) +#define glValidateProgramPipeline GLEW_GET_FUN(__glewValidateProgramPipeline) + +#define GLEW_ARB_separate_shader_objects GLEW_GET_VAR(__GLEW_ARB_separate_shader_objects) + +#endif /* GL_ARB_separate_shader_objects */ + +/* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */ + +#ifndef GL_ARB_shader_bit_encoding +#define GL_ARB_shader_bit_encoding 1 + +#define GLEW_ARB_shader_bit_encoding GLEW_GET_VAR(__GLEW_ARB_shader_bit_encoding) + +#endif /* GL_ARB_shader_bit_encoding */ + +/* ------------------------- GL_ARB_shader_objects ------------------------- */ + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 + +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 + +typedef char GLcharARB; +typedef unsigned int GLhandleARB; + +typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj); +typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); + +#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB) +#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB) +#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB) +#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB) +#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB) +#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB) +#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB) +#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB) +#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB) +#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB) +#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB) +#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB) +#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB) +#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB) +#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB) +#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB) +#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB) +#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB) +#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB) +#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB) +#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB) +#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB) +#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB) +#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB) +#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB) +#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB) +#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB) +#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB) +#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB) +#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB) +#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB) +#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB) +#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB) +#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB) +#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB) +#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB) +#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB) +#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB) +#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB) + +#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects) + +#endif /* GL_ARB_shader_objects */ + +/* ------------------------ GL_ARB_shader_precision ------------------------ */ + +#ifndef GL_ARB_shader_precision +#define GL_ARB_shader_precision 1 + +#define GLEW_ARB_shader_precision GLEW_GET_VAR(__GLEW_ARB_shader_precision) + +#endif /* GL_ARB_shader_precision */ + +/* ---------------------- GL_ARB_shader_stencil_export --------------------- */ + +#ifndef GL_ARB_shader_stencil_export +#define GL_ARB_shader_stencil_export 1 + +#define GLEW_ARB_shader_stencil_export GLEW_GET_VAR(__GLEW_ARB_shader_stencil_export) + +#endif /* GL_ARB_shader_stencil_export */ + +/* ------------------------ GL_ARB_shader_subroutine ----------------------- */ + +#ifndef GL_ARB_shader_subroutine +#define GL_ARB_shader_subroutine 1 + +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B + +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values); +typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name); +typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params); +typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices); + +#define glGetActiveSubroutineName GLEW_GET_FUN(__glewGetActiveSubroutineName) +#define glGetActiveSubroutineUniformName GLEW_GET_FUN(__glewGetActiveSubroutineUniformName) +#define glGetActiveSubroutineUniformiv GLEW_GET_FUN(__glewGetActiveSubroutineUniformiv) +#define glGetProgramStageiv GLEW_GET_FUN(__glewGetProgramStageiv) +#define glGetSubroutineIndex GLEW_GET_FUN(__glewGetSubroutineIndex) +#define glGetSubroutineUniformLocation GLEW_GET_FUN(__glewGetSubroutineUniformLocation) +#define glGetUniformSubroutineuiv GLEW_GET_FUN(__glewGetUniformSubroutineuiv) +#define glUniformSubroutinesuiv GLEW_GET_FUN(__glewUniformSubroutinesuiv) + +#define GLEW_ARB_shader_subroutine GLEW_GET_VAR(__GLEW_ARB_shader_subroutine) + +#endif /* GL_ARB_shader_subroutine */ + +/* ----------------------- GL_ARB_shader_texture_lod ----------------------- */ + +#ifndef GL_ARB_shader_texture_lod +#define GL_ARB_shader_texture_lod 1 + +#define GLEW_ARB_shader_texture_lod GLEW_GET_VAR(__GLEW_ARB_shader_texture_lod) + +#endif /* GL_ARB_shader_texture_lod */ + +/* ---------------------- GL_ARB_shading_language_100 ---------------------- */ + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 + +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C + +#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100) + +#endif /* GL_ARB_shading_language_100 */ + +/* -------------------- GL_ARB_shading_language_include -------------------- */ + +#ifndef GL_ARB_shading_language_include +#define GL_ARB_shading_language_include 1 + +#define GL_SHADER_INCLUDE_ARB 0x8DAE +#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 +#define GL_NAMED_STRING_TYPE_ARB 0x8DEA + +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length); +typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name); +typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string); + +#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB) +#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB) +#define glGetNamedStringARB GLEW_GET_FUN(__glewGetNamedStringARB) +#define glGetNamedStringivARB GLEW_GET_FUN(__glewGetNamedStringivARB) +#define glIsNamedStringARB GLEW_GET_FUN(__glewIsNamedStringARB) +#define glNamedStringARB GLEW_GET_FUN(__glewNamedStringARB) + +#define GLEW_ARB_shading_language_include GLEW_GET_VAR(__GLEW_ARB_shading_language_include) + +#endif /* GL_ARB_shading_language_include */ + +/* ----------------------------- GL_ARB_shadow ----------------------------- */ + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 + +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E + +#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow) + +#endif /* GL_ARB_shadow */ + +/* ------------------------- GL_ARB_shadow_ambient ------------------------- */ + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 + +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF + +#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient) + +#endif /* GL_ARB_shadow_ambient */ + +/* ------------------------------ GL_ARB_sync ------------------------------ */ + +#ifndef GL_ARB_sync +#define GL_ARB_sync 1 + +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF + +typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); +typedef void (GLAPIENTRY * PFNGLDELETESYNCPROC) (GLsync GLsync); +typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETSYNCIVPROC) (GLsync GLsync,GLenum pname,GLsizei bufSize,GLsizei* length, GLint *values); +typedef GLboolean (GLAPIENTRY * PFNGLISSYNCPROC) (GLsync GLsync); +typedef void (GLAPIENTRY * PFNGLWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); + +#define glClientWaitSync GLEW_GET_FUN(__glewClientWaitSync) +#define glDeleteSync GLEW_GET_FUN(__glewDeleteSync) +#define glFenceSync GLEW_GET_FUN(__glewFenceSync) +#define glGetInteger64v GLEW_GET_FUN(__glewGetInteger64v) +#define glGetSynciv GLEW_GET_FUN(__glewGetSynciv) +#define glIsSync GLEW_GET_FUN(__glewIsSync) +#define glWaitSync GLEW_GET_FUN(__glewWaitSync) + +#define GLEW_ARB_sync GLEW_GET_VAR(__GLEW_ARB_sync) + +#endif /* GL_ARB_sync */ + +/* ----------------------- GL_ARB_tessellation_shader ---------------------- */ + +#ifndef GL_ARB_tessellation_shader +#define GL_ARB_tessellation_shader 1 + +#define GL_PATCHES 0xE +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_ISOLINES 0x8E7A +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A + +typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat* values); +typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); + +#define glPatchParameterfv GLEW_GET_FUN(__glewPatchParameterfv) +#define glPatchParameteri GLEW_GET_FUN(__glewPatchParameteri) + +#define GLEW_ARB_tessellation_shader GLEW_GET_VAR(__GLEW_ARB_tessellation_shader) + +#endif /* GL_ARB_tessellation_shader */ + +/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_ARB 0x812D + +#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp) + +#endif /* GL_ARB_texture_border_clamp */ + +/* ---------------------- GL_ARB_texture_buffer_object --------------------- */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB) + +#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object) + +#endif /* GL_ARB_texture_buffer_object */ + +/* ------------------- GL_ARB_texture_buffer_object_rgb32 ------------------ */ + +#ifndef GL_ARB_texture_buffer_object_rgb32 +#define GL_ARB_texture_buffer_object_rgb32 1 + +#define GLEW_ARB_texture_buffer_object_rgb32 GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object_rgb32) + +#endif /* GL_ARB_texture_buffer_object_rgb32 */ + +/* ----------------------- GL_ARB_texture_compression ---------------------- */ + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 + +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 + +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img); + +#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) +#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) +#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB) +#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB) +#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB) +#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB) +#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB) + +#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression) + +#endif /* GL_ARB_texture_compression */ + +/* -------------------- GL_ARB_texture_compression_bptc -------------------- */ + +#ifndef GL_ARB_texture_compression_bptc +#define GL_ARB_texture_compression_bptc 1 + +#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F + +#define GLEW_ARB_texture_compression_bptc GLEW_GET_VAR(__GLEW_ARB_texture_compression_bptc) + +#endif /* GL_ARB_texture_compression_bptc */ + +/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE + +#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc) + +#endif /* GL_ARB_texture_compression_rgtc */ + +/* ------------------------ GL_ARB_texture_cube_map ------------------------ */ + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 + +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C + +#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map) + +#endif /* GL_ARB_texture_cube_map */ + +/* --------------------- GL_ARB_texture_cube_map_array --------------------- */ + +#ifndef GL_ARB_texture_cube_map_array +#define GL_ARB_texture_cube_map_array 1 + +#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F + +#define GLEW_ARB_texture_cube_map_array GLEW_GET_VAR(__GLEW_ARB_texture_cube_map_array) + +#endif /* GL_ARB_texture_cube_map_array */ + +/* ------------------------- GL_ARB_texture_env_add ------------------------ */ + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 + +#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add) + +#endif /* GL_ARB_texture_env_add */ + +/* ----------------------- GL_ARB_texture_env_combine ---------------------- */ + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 + +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A + +#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine) + +#endif /* GL_ARB_texture_env_combine */ + +/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */ + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 + +#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar) + +#endif /* GL_ARB_texture_env_crossbar */ + +/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */ + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 + +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF + +#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3) + +#endif /* GL_ARB_texture_env_dot3 */ + +/* -------------------------- GL_ARB_texture_float ------------------------- */ + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 + +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 + +#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float) + +#endif /* GL_ARB_texture_float */ + +/* ------------------------- GL_ARB_texture_gather ------------------------- */ + +#ifndef GL_ARB_texture_gather +#define GL_ARB_texture_gather 1 + +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F + +#define GLEW_ARB_texture_gather GLEW_GET_VAR(__GLEW_ARB_texture_gather) + +#endif /* GL_ARB_texture_gather */ + +/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_ARB 0x8370 + +#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat) + +#endif /* GL_ARB_texture_mirrored_repeat */ + +/* ----------------------- GL_ARB_texture_multisample ---------------------- */ + +#ifndef GL_ARB_texture_multisample +#define GL_ARB_texture_multisample 1 + +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); + +#define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv) +#define glSampleMaski GLEW_GET_FUN(__glewSampleMaski) +#define glTexImage2DMultisample GLEW_GET_FUN(__glewTexImage2DMultisample) +#define glTexImage3DMultisample GLEW_GET_FUN(__glewTexImage3DMultisample) + +#define GLEW_ARB_texture_multisample GLEW_GET_VAR(__GLEW_ARB_texture_multisample) + +#endif /* GL_ARB_texture_multisample */ + +/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 + +#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two) + +#endif /* GL_ARB_texture_non_power_of_two */ + +/* ------------------------ GL_ARB_texture_query_lod ----------------------- */ + +#ifndef GL_ARB_texture_query_lod +#define GL_ARB_texture_query_lod 1 + +#define GLEW_ARB_texture_query_lod GLEW_GET_VAR(__GLEW_ARB_texture_query_lod) + +#endif /* GL_ARB_texture_query_lod */ + +/* ------------------------ GL_ARB_texture_rectangle ----------------------- */ + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 + +#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle) + +#endif /* GL_ARB_texture_rectangle */ + +/* --------------------------- GL_ARB_texture_rg --------------------------- */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 + +#define GL_RED 0x1903 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C + +#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg) + +#endif /* GL_ARB_texture_rg */ + +/* ----------------------- GL_ARB_texture_rgb10_a2ui ----------------------- */ + +#ifndef GL_ARB_texture_rgb10_a2ui +#define GL_ARB_texture_rgb10_a2ui 1 + +#define GL_RGB10_A2UI 0x906F + +#define GLEW_ARB_texture_rgb10_a2ui GLEW_GET_VAR(__GLEW_ARB_texture_rgb10_a2ui) + +#endif /* GL_ARB_texture_rgb10_a2ui */ + +/* ------------------------- GL_ARB_texture_swizzle ------------------------ */ + +#ifndef GL_ARB_texture_swizzle +#define GL_ARB_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 + +#define GLEW_ARB_texture_swizzle GLEW_GET_VAR(__GLEW_ARB_texture_swizzle) + +#endif /* GL_ARB_texture_swizzle */ + +/* --------------------------- GL_ARB_timer_query -------------------------- */ + +#ifndef GL_ARB_timer_query +#define GL_ARB_timer_query 1 + +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params); +typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); + +#define glGetQueryObjecti64v GLEW_GET_FUN(__glewGetQueryObjecti64v) +#define glGetQueryObjectui64v GLEW_GET_FUN(__glewGetQueryObjectui64v) +#define glQueryCounter GLEW_GET_FUN(__glewQueryCounter) + +#define GLEW_ARB_timer_query GLEW_GET_VAR(__GLEW_ARB_timer_query) + +#endif /* GL_ARB_timer_query */ + +/* ----------------------- GL_ARB_transform_feedback2 ---------------------- */ + +#ifndef GL_ARB_transform_feedback2 +#define GL_ARB_transform_feedback2 1 + +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 + +typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); +typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); +typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); + +#define glBindTransformFeedback GLEW_GET_FUN(__glewBindTransformFeedback) +#define glDeleteTransformFeedbacks GLEW_GET_FUN(__glewDeleteTransformFeedbacks) +#define glDrawTransformFeedback GLEW_GET_FUN(__glewDrawTransformFeedback) +#define glGenTransformFeedbacks GLEW_GET_FUN(__glewGenTransformFeedbacks) +#define glIsTransformFeedback GLEW_GET_FUN(__glewIsTransformFeedback) +#define glPauseTransformFeedback GLEW_GET_FUN(__glewPauseTransformFeedback) +#define glResumeTransformFeedback GLEW_GET_FUN(__glewResumeTransformFeedback) + +#define GLEW_ARB_transform_feedback2 GLEW_GET_VAR(__GLEW_ARB_transform_feedback2) + +#endif /* GL_ARB_transform_feedback2 */ + +/* ----------------------- GL_ARB_transform_feedback3 ---------------------- */ + +#ifndef GL_ARB_transform_feedback3 +#define GL_ARB_transform_feedback3 1 + +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +#define GL_MAX_VERTEX_STREAMS 0x8E71 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); +typedef void (GLAPIENTRY * PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); + +#define glBeginQueryIndexed GLEW_GET_FUN(__glewBeginQueryIndexed) +#define glDrawTransformFeedbackStream GLEW_GET_FUN(__glewDrawTransformFeedbackStream) +#define glEndQueryIndexed GLEW_GET_FUN(__glewEndQueryIndexed) +#define glGetQueryIndexediv GLEW_GET_FUN(__glewGetQueryIndexediv) + +#define GLEW_ARB_transform_feedback3 GLEW_GET_VAR(__GLEW_ARB_transform_feedback3) + +#endif /* GL_ARB_transform_feedback3 */ + +/* ------------------------ GL_ARB_transpose_matrix ------------------------ */ + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 + +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 + +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); + +#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB) +#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB) +#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB) +#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB) + +#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix) + +#endif /* GL_ARB_transpose_matrix */ + +/* ---------------------- GL_ARB_uniform_buffer_object --------------------- */ + +#ifndef GL_ARB_uniform_buffer_object +#define GL_ARB_uniform_buffer_object 1 + +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data); +typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices); +typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + +#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) +#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange) +#define glGetActiveUniformBlockName GLEW_GET_FUN(__glewGetActiveUniformBlockName) +#define glGetActiveUniformBlockiv GLEW_GET_FUN(__glewGetActiveUniformBlockiv) +#define glGetActiveUniformName GLEW_GET_FUN(__glewGetActiveUniformName) +#define glGetActiveUniformsiv GLEW_GET_FUN(__glewGetActiveUniformsiv) +#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v) +#define glGetUniformBlockIndex GLEW_GET_FUN(__glewGetUniformBlockIndex) +#define glGetUniformIndices GLEW_GET_FUN(__glewGetUniformIndices) +#define glUniformBlockBinding GLEW_GET_FUN(__glewUniformBlockBinding) + +#define GLEW_ARB_uniform_buffer_object GLEW_GET_VAR(__GLEW_ARB_uniform_buffer_object) + +#endif /* GL_ARB_uniform_buffer_object */ + +/* ------------------------ GL_ARB_vertex_array_bgra ----------------------- */ + +#ifndef GL_ARB_vertex_array_bgra +#define GL_ARB_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_ARB_vertex_array_bgra GLEW_GET_VAR(__GLEW_ARB_vertex_array_bgra) + +#endif /* GL_ARB_vertex_array_bgra */ + +/* ----------------------- GL_ARB_vertex_array_object ---------------------- */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array); + +#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray) +#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays) +#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays) +#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray) + +#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object) + +#endif /* GL_ARB_vertex_array_object */ + +/* ----------------------- GL_ARB_vertex_attrib_64bit ---------------------- */ + +#ifndef GL_ARB_vertex_attrib_64bit +#define GL_ARB_vertex_attrib_64bit 1 + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); + +#define glGetVertexAttribLdv GLEW_GET_FUN(__glewGetVertexAttribLdv) +#define glVertexAttribL1d GLEW_GET_FUN(__glewVertexAttribL1d) +#define glVertexAttribL1dv GLEW_GET_FUN(__glewVertexAttribL1dv) +#define glVertexAttribL2d GLEW_GET_FUN(__glewVertexAttribL2d) +#define glVertexAttribL2dv GLEW_GET_FUN(__glewVertexAttribL2dv) +#define glVertexAttribL3d GLEW_GET_FUN(__glewVertexAttribL3d) +#define glVertexAttribL3dv GLEW_GET_FUN(__glewVertexAttribL3dv) +#define glVertexAttribL4d GLEW_GET_FUN(__glewVertexAttribL4d) +#define glVertexAttribL4dv GLEW_GET_FUN(__glewVertexAttribL4dv) +#define glVertexAttribLPointer GLEW_GET_FUN(__glewVertexAttribLPointer) + +#define GLEW_ARB_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_64bit) + +#endif /* GL_ARB_vertex_attrib_64bit */ + +/* -------------------------- GL_ARB_vertex_blend -------------------------- */ + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 + +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F + +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count); +typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights); + +#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB) +#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB) +#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB) +#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB) +#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB) +#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB) +#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB) +#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB) +#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB) +#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB) + +#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend) + +#endif /* GL_ARB_vertex_blend */ + +/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */ + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 + +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA + +typedef ptrdiff_t GLintptrARB; +typedef ptrdiff_t GLsizeiptrARB; + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); + +#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB) +#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB) +#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB) +#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB) +#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB) +#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB) +#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB) +#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB) +#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB) +#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB) +#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB) + +#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object) + +#endif /* GL_ARB_vertex_buffer_object */ + +/* ------------------------- GL_ARB_vertex_program ------------------------- */ + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 + +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF + +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + +#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) +#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) +#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB) +#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB) +#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB) +#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB) +#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB) +#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB) +#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB) +#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB) +#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB) +#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB) +#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB) +#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB) +#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB) +#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB) +#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB) +#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB) +#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB) +#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB) +#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB) +#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB) +#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB) +#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB) +#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB) +#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB) +#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB) +#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB) +#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB) +#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB) +#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB) +#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB) +#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB) +#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB) +#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB) +#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB) +#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB) +#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB) +#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB) +#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB) +#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB) +#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB) +#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB) +#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB) +#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB) +#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB) +#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB) +#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB) +#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB) +#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB) + +#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program) + +#endif /* GL_ARB_vertex_program */ + +/* -------------------------- GL_ARB_vertex_shader ------------------------- */ + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 + +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A + +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); + +#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB) +#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB) +#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB) + +#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader) + +#endif /* GL_ARB_vertex_shader */ + +/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */ + +#ifndef GL_ARB_vertex_type_2_10_10_10_rev +#define GL_ARB_vertex_type_2_10_10_10_rev 1 + +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_INT_2_10_10_10_REV 0x8D9F + +typedef void (GLAPIENTRY * PFNGLCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLCOLORP4UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint* value); + +#define glColorP3ui GLEW_GET_FUN(__glewColorP3ui) +#define glColorP3uiv GLEW_GET_FUN(__glewColorP3uiv) +#define glColorP4ui GLEW_GET_FUN(__glewColorP4ui) +#define glColorP4uiv GLEW_GET_FUN(__glewColorP4uiv) +#define glMultiTexCoordP1ui GLEW_GET_FUN(__glewMultiTexCoordP1ui) +#define glMultiTexCoordP1uiv GLEW_GET_FUN(__glewMultiTexCoordP1uiv) +#define glMultiTexCoordP2ui GLEW_GET_FUN(__glewMultiTexCoordP2ui) +#define glMultiTexCoordP2uiv GLEW_GET_FUN(__glewMultiTexCoordP2uiv) +#define glMultiTexCoordP3ui GLEW_GET_FUN(__glewMultiTexCoordP3ui) +#define glMultiTexCoordP3uiv GLEW_GET_FUN(__glewMultiTexCoordP3uiv) +#define glMultiTexCoordP4ui GLEW_GET_FUN(__glewMultiTexCoordP4ui) +#define glMultiTexCoordP4uiv GLEW_GET_FUN(__glewMultiTexCoordP4uiv) +#define glNormalP3ui GLEW_GET_FUN(__glewNormalP3ui) +#define glNormalP3uiv GLEW_GET_FUN(__glewNormalP3uiv) +#define glSecondaryColorP3ui GLEW_GET_FUN(__glewSecondaryColorP3ui) +#define glSecondaryColorP3uiv GLEW_GET_FUN(__glewSecondaryColorP3uiv) +#define glTexCoordP1ui GLEW_GET_FUN(__glewTexCoordP1ui) +#define glTexCoordP1uiv GLEW_GET_FUN(__glewTexCoordP1uiv) +#define glTexCoordP2ui GLEW_GET_FUN(__glewTexCoordP2ui) +#define glTexCoordP2uiv GLEW_GET_FUN(__glewTexCoordP2uiv) +#define glTexCoordP3ui GLEW_GET_FUN(__glewTexCoordP3ui) +#define glTexCoordP3uiv GLEW_GET_FUN(__glewTexCoordP3uiv) +#define glTexCoordP4ui GLEW_GET_FUN(__glewTexCoordP4ui) +#define glTexCoordP4uiv GLEW_GET_FUN(__glewTexCoordP4uiv) +#define glVertexAttribP1ui GLEW_GET_FUN(__glewVertexAttribP1ui) +#define glVertexAttribP1uiv GLEW_GET_FUN(__glewVertexAttribP1uiv) +#define glVertexAttribP2ui GLEW_GET_FUN(__glewVertexAttribP2ui) +#define glVertexAttribP2uiv GLEW_GET_FUN(__glewVertexAttribP2uiv) +#define glVertexAttribP3ui GLEW_GET_FUN(__glewVertexAttribP3ui) +#define glVertexAttribP3uiv GLEW_GET_FUN(__glewVertexAttribP3uiv) +#define glVertexAttribP4ui GLEW_GET_FUN(__glewVertexAttribP4ui) +#define glVertexAttribP4uiv GLEW_GET_FUN(__glewVertexAttribP4uiv) +#define glVertexP2ui GLEW_GET_FUN(__glewVertexP2ui) +#define glVertexP2uiv GLEW_GET_FUN(__glewVertexP2uiv) +#define glVertexP3ui GLEW_GET_FUN(__glewVertexP3ui) +#define glVertexP3uiv GLEW_GET_FUN(__glewVertexP3uiv) +#define glVertexP4ui GLEW_GET_FUN(__glewVertexP4ui) +#define glVertexP4uiv GLEW_GET_FUN(__glewVertexP4uiv) + +#define GLEW_ARB_vertex_type_2_10_10_10_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_2_10_10_10_rev) + +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ + +/* ------------------------- GL_ARB_viewport_array ------------------------- */ + +#ifndef GL_ARB_viewport_array +#define GL_ARB_viewport_array 1 + +#define GL_DEPTH_RANGE 0x0B70 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_MAX_VIEWPORTS 0x825B +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F + +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd * v); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble* data); +typedef void (GLAPIENTRY * PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint * v); +typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint * v); +typedef void (GLAPIENTRY * PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat * v); +typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat * v); + +#define glDepthRangeArrayv GLEW_GET_FUN(__glewDepthRangeArrayv) +#define glDepthRangeIndexed GLEW_GET_FUN(__glewDepthRangeIndexed) +#define glGetDoublei_v GLEW_GET_FUN(__glewGetDoublei_v) +#define glGetFloati_v GLEW_GET_FUN(__glewGetFloati_v) +#define glScissorArrayv GLEW_GET_FUN(__glewScissorArrayv) +#define glScissorIndexed GLEW_GET_FUN(__glewScissorIndexed) +#define glScissorIndexedv GLEW_GET_FUN(__glewScissorIndexedv) +#define glViewportArrayv GLEW_GET_FUN(__glewViewportArrayv) +#define glViewportIndexedf GLEW_GET_FUN(__glewViewportIndexedf) +#define glViewportIndexedfv GLEW_GET_FUN(__glewViewportIndexedfv) + +#define GLEW_ARB_viewport_array GLEW_GET_VAR(__GLEW_ARB_viewport_array) + +#endif /* GL_ARB_viewport_array */ + +/* --------------------------- GL_ARB_window_pos --------------------------- */ + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p); + +#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB) +#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB) +#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB) +#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB) +#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB) +#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB) +#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB) +#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB) +#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB) +#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB) +#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB) +#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB) +#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB) +#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB) +#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB) +#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB) + +#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos) + +#endif /* GL_ARB_window_pos */ + +/* ------------------------- GL_ATIX_point_sprites ------------------------- */ + +#ifndef GL_ATIX_point_sprites +#define GL_ATIX_point_sprites 1 + +#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0 +#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1 +#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2 +#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3 +#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4 +#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5 + +#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites) + +#endif /* GL_ATIX_point_sprites */ + +/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */ + +#ifndef GL_ATIX_texture_env_combine3 +#define GL_ATIX_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATIX 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745 +#define GL_MODULATE_SUBTRACT_ATIX 0x8746 + +#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3) + +#endif /* GL_ATIX_texture_env_combine3 */ + +/* ----------------------- GL_ATIX_texture_env_route ----------------------- */ + +#ifndef GL_ATIX_texture_env_route +#define GL_ATIX_texture_env_route 1 + +#define GL_SECONDARY_COLOR_ATIX 0x8747 +#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 +#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 + +#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route) + +#endif /* GL_ATIX_texture_env_route */ + +/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */ + +#ifndef GL_ATIX_vertex_shader_output_point_size +#define GL_ATIX_vertex_shader_output_point_size 1 + +#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E + +#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size) + +#endif /* GL_ATIX_vertex_shader_output_point_size */ + +/* -------------------------- GL_ATI_draw_buffers -------------------------- */ + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI) + +#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers) + +#endif /* GL_ATI_draw_buffers */ + +/* -------------------------- GL_ATI_element_array ------------------------- */ + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 + +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer); + +#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) +#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) +#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI) + +#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array) + +#endif /* GL_ATI_element_array */ + +/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */ + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 + +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C + +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); + +#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI) +#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI) +#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI) +#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI) + +#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap) + +#endif /* GL_ATI_envmap_bumpmap */ + +/* ------------------------- GL_ATI_fragment_shader ------------------------ */ + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 + +#define GL_RED_BIT_ATI 0x00000001 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B + +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value); + +#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI) +#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI) +#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI) +#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI) +#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI) +#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI) +#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI) +#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI) +#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI) +#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI) +#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI) +#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI) + +#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader) + +#endif /* GL_ATI_fragment_shader */ + +/* ------------------------ GL_ATI_map_object_buffer ----------------------- */ + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 + +typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); + +#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) +#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI) + +#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer) + +#endif /* GL_ATI_map_object_buffer */ + +/* ----------------------------- GL_ATI_meminfo ---------------------------- */ + +#ifndef GL_ATI_meminfo +#define GL_ATI_meminfo 1 + +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD + +#define GLEW_ATI_meminfo GLEW_GET_VAR(__GLEW_ATI_meminfo) + +#endif /* GL_ATI_meminfo */ + +/* -------------------------- GL_ATI_pn_triangles -------------------------- */ + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 + +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 + +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); + +#define glPNTrianglesfATI GLEW_GET_FUN(__glewPNTrianglesfATI) +#define glPNTrianglesiATI GLEW_GET_FUN(__glewPNTrianglesiATI) + +#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles) + +#endif /* GL_ATI_pn_triangles */ + +/* ------------------------ GL_ATI_separate_stencil ------------------------ */ + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 + +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 + +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + +#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI) +#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI) + +#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil) + +#endif /* GL_ATI_separate_stencil */ + +/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */ + +#ifndef GL_ATI_shader_texture_lod +#define GL_ATI_shader_texture_lod 1 + +#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod) + +#endif /* GL_ATI_shader_texture_lod */ + +/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */ + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 + +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 + +#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader) + +#endif /* GL_ATI_text_fragment_shader */ + +/* --------------------- GL_ATI_texture_compression_3dc -------------------- */ + +#ifndef GL_ATI_texture_compression_3dc +#define GL_ATI_texture_compression_3dc 1 + +#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837 + +#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc) + +#endif /* GL_ATI_texture_compression_3dc */ + +/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */ + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 + +#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3) + +#endif /* GL_ATI_texture_env_combine3 */ + +/* -------------------------- GL_ATI_texture_float ------------------------- */ + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 + +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F + +#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float) + +#endif /* GL_ATI_texture_float */ + +/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */ + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 + +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 + +#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once) + +#endif /* GL_ATI_texture_mirror_once */ + +/* ----------------------- GL_ATI_vertex_array_object ---------------------- */ + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 + +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 + +typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage); +typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve); +typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + +#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) +#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI) +#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI) +#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI) +#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI) +#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI) +#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI) +#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI) +#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI) +#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI) +#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI) + +#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object) + +#endif /* GL_ATI_vertex_array_object */ + +/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */ + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + +#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI) +#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI) + +#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object) + +#endif /* GL_ATI_vertex_attrib_array_object */ + +/* ------------------------- GL_ATI_vertex_streams ------------------------- */ + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 + +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_SOURCE_ATI 0x876C +#define GL_VERTEX_STREAM0_ATI 0x876D +#define GL_VERTEX_STREAM1_ATI 0x876E +#define GL_VERTEX_STREAM2_ATI 0x876F +#define GL_VERTEX_STREAM3_ATI 0x8770 +#define GL_VERTEX_STREAM4_ATI 0x8771 +#define GL_VERTEX_STREAM5_ATI 0x8772 +#define GL_VERTEX_STREAM6_ATI 0x8773 +#define GL_VERTEX_STREAM7_ATI 0x8774 + +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v); + +#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI) +#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI) +#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI) +#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI) +#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI) +#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI) +#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI) +#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI) +#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI) +#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI) +#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI) +#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI) +#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI) +#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI) +#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI) +#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI) +#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI) +#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI) +#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI) +#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI) +#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI) +#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI) +#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI) +#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI) +#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI) +#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI) +#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI) +#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI) +#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI) +#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI) +#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI) +#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI) +#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI) +#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI) +#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI) +#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI) +#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI) + +#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams) + +#endif /* GL_ATI_vertex_streams */ + +/* --------------------------- GL_EXT_422_pixels --------------------------- */ + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 + +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF + +#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels) + +#endif /* GL_EXT_422_pixels */ + +/* ---------------------------- GL_EXT_Cg_shader --------------------------- */ + +#ifndef GL_EXT_Cg_shader +#define GL_EXT_Cg_shader 1 + +#define GL_CG_VERTEX_SHADER_EXT 0x890E +#define GL_CG_FRAGMENT_SHADER_EXT 0x890F + +#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader) + +#endif /* GL_EXT_Cg_shader */ + +/* ------------------------------ GL_EXT_abgr ------------------------------ */ + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 + +#define GL_ABGR_EXT 0x8000 + +#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr) + +#endif /* GL_EXT_abgr */ + +/* ------------------------------ GL_EXT_bgra ------------------------------ */ + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 + +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 + +#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra) + +#endif /* GL_EXT_bgra */ + +/* ------------------------ GL_EXT_bindable_uniform ------------------------ */ + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 + +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF + +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); +typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); +typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); + +#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT) +#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT) +#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT) + +#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform) + +#endif /* GL_EXT_bindable_uniform */ + +/* --------------------------- GL_EXT_blend_color -------------------------- */ + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 + +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 + +typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + +#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT) + +#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color) + +#endif /* GL_EXT_blend_color */ + +/* --------------------- GL_EXT_blend_equation_separate -------------------- */ + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 + +#define GL_BLEND_EQUATION_RGB_EXT 0x8009 +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); + +#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT) + +#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate) + +#endif /* GL_EXT_blend_equation_separate */ + +/* ----------------------- GL_EXT_blend_func_separate ---------------------- */ + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 + +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB + +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + +#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT) + +#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate) + +#endif /* GL_EXT_blend_func_separate */ + +/* ------------------------- GL_EXT_blend_logic_op ------------------------- */ + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 + +#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op) + +#endif /* GL_EXT_blend_logic_op */ + +/* -------------------------- GL_EXT_blend_minmax -------------------------- */ + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 + +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); + +#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT) + +#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax) + +#endif /* GL_EXT_blend_minmax */ + +/* ------------------------- GL_EXT_blend_subtract ------------------------- */ + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 + +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B + +#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract) + +#endif /* GL_EXT_blend_subtract */ + +/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */ + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 + +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 + +#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint) + +#endif /* GL_EXT_clip_volume_hint */ + +/* ------------------------------ GL_EXT_cmyka ----------------------------- */ + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 + +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F + +#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka) + +#endif /* GL_EXT_cmyka */ + +/* ------------------------- GL_EXT_color_subtable ------------------------- */ + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + +#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) +#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT) + +#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable) + +#endif /* GL_EXT_color_subtable */ + +/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */ + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 + +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 + +typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); + +#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT) +#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT) + +#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array) + +#endif /* GL_EXT_compiled_vertex_array */ + +/* --------------------------- GL_EXT_convolution -------------------------- */ + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 + +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 + +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column); + +#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT) +#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT) +#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT) + +#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution) + +#endif /* GL_EXT_convolution */ + +/* ------------------------ GL_EXT_coordinate_frame ------------------------ */ + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 + +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 + +typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); + +#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) +#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) + +#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame) + +#endif /* GL_EXT_coordinate_frame */ + +/* -------------------------- GL_EXT_copy_texture -------------------------- */ + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 + +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT) +#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT) + +#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture) + +#endif /* GL_EXT_copy_texture */ + +/* --------------------------- GL_EXT_cull_vertex -------------------------- */ + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 + +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC + +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params); + +#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT) +#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT) + +#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex) + +#endif /* GL_EXT_cull_vertex */ + +/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */ + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 + +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 + +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); + +#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT) + +#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test) + +#endif /* GL_EXT_depth_bounds_test */ + +/* ----------------------- GL_EXT_direct_state_access ---------------------- */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 + +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F + +typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); +typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); +typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); +typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); +typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); +typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); + +#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT) +#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT) +#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT) +#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT) +#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT) +#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT) +#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT) +#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT) +#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT) +#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT) +#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT) +#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT) +#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT) +#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT) +#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT) +#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT) +#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT) +#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT) +#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT) +#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT) +#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT) +#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT) +#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT) +#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT) +#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT) +#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT) +#define glDisableClientStateiEXT GLEW_GET_FUN(__glewDisableClientStateiEXT) +#define glDisableVertexArrayAttribEXT GLEW_GET_FUN(__glewDisableVertexArrayAttribEXT) +#define glDisableVertexArrayEXT GLEW_GET_FUN(__glewDisableVertexArrayEXT) +#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT) +#define glEnableClientStateiEXT GLEW_GET_FUN(__glewEnableClientStateiEXT) +#define glEnableVertexArrayAttribEXT GLEW_GET_FUN(__glewEnableVertexArrayAttribEXT) +#define glEnableVertexArrayEXT GLEW_GET_FUN(__glewEnableVertexArrayEXT) +#define glFlushMappedNamedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedNamedBufferRangeEXT) +#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT) +#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT) +#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT) +#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT) +#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT) +#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT) +#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT) +#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT) +#define glGetDoublei_vEXT GLEW_GET_FUN(__glewGetDoublei_vEXT) +#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT) +#define glGetFloati_vEXT GLEW_GET_FUN(__glewGetFloati_vEXT) +#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT) +#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT) +#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT) +#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT) +#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT) +#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT) +#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT) +#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT) +#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT) +#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT) +#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT) +#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT) +#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT) +#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT) +#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT) +#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT) +#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT) +#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT) +#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT) +#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT) +#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT) +#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT) +#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT) +#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT) +#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT) +#define glGetPointeri_vEXT GLEW_GET_FUN(__glewGetPointeri_vEXT) +#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT) +#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT) +#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT) +#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT) +#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT) +#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT) +#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT) +#define glGetVertexArrayIntegeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayIntegeri_vEXT) +#define glGetVertexArrayIntegervEXT GLEW_GET_FUN(__glewGetVertexArrayIntegervEXT) +#define glGetVertexArrayPointeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayPointeri_vEXT) +#define glGetVertexArrayPointervEXT GLEW_GET_FUN(__glewGetVertexArrayPointervEXT) +#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT) +#define glMapNamedBufferRangeEXT GLEW_GET_FUN(__glewMapNamedBufferRangeEXT) +#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT) +#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT) +#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT) +#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT) +#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT) +#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT) +#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT) +#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT) +#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT) +#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT) +#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT) +#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT) +#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT) +#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT) +#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT) +#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT) +#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT) +#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT) +#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT) +#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT) +#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT) +#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT) +#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT) +#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT) +#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT) +#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT) +#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT) +#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT) +#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT) +#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT) +#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT) +#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT) +#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT) +#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT) +#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT) +#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT) +#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT) +#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT) +#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT) +#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT) +#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT) +#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT) +#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT) +#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT) +#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT) +#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT) +#define glNamedCopyBufferSubDataEXT GLEW_GET_FUN(__glewNamedCopyBufferSubDataEXT) +#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT) +#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT) +#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT) +#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT) +#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT) +#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT) +#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT) +#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT) +#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT) +#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT) +#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT) +#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT) +#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT) +#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT) +#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT) +#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT) +#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT) +#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT) +#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT) +#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT) +#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT) +#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT) +#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT) +#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT) +#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT) +#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT) +#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT) +#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT) +#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT) +#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT) +#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT) +#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT) +#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT) +#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT) +#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT) +#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT) +#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT) +#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT) +#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT) +#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT) +#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT) +#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT) +#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT) +#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT) +#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT) +#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT) +#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT) +#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT) +#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT) +#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT) +#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT) +#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT) +#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT) +#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT) +#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT) +#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT) +#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT) +#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT) +#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT) +#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT) +#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT) +#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT) +#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT) +#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT) +#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT) +#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT) +#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT) +#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT) +#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT) +#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT) +#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT) +#define glVertexArrayColorOffsetEXT GLEW_GET_FUN(__glewVertexArrayColorOffsetEXT) +#define glVertexArrayEdgeFlagOffsetEXT GLEW_GET_FUN(__glewVertexArrayEdgeFlagOffsetEXT) +#define glVertexArrayFogCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayFogCoordOffsetEXT) +#define glVertexArrayIndexOffsetEXT GLEW_GET_FUN(__glewVertexArrayIndexOffsetEXT) +#define glVertexArrayMultiTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayMultiTexCoordOffsetEXT) +#define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT) +#define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT) +#define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT) +#define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT) +#define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT) +#define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT) + +#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access) + +#endif /* GL_EXT_direct_state_access */ + +/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */ + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 + +typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data); +typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); + +#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT) +#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT) +#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT) +#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT) +#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT) +#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT) + +#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2) + +#endif /* GL_EXT_draw_buffers2 */ + +/* ------------------------- GL_EXT_draw_instanced ------------------------- */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); + +#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT) +#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT) + +#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced) + +#endif /* GL_EXT_draw_instanced */ + +/* ----------------------- GL_EXT_draw_range_elements ---------------------- */ + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 + +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 + +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + +#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT) + +#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements) + +#endif /* GL_EXT_draw_range_elements */ + +/* ---------------------------- GL_EXT_fog_coord --------------------------- */ + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 + +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 + +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); + +#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT) +#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT) +#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT) +#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT) +#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT) + +#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord) + +#endif /* GL_EXT_fog_coord */ + +/* ------------------------ GL_EXT_fragment_lighting ----------------------- */ + +#ifndef GL_EXT_fragment_lighting +#define GL_EXT_fragment_lighting 1 + +#define GL_FRAGMENT_LIGHTING_EXT 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405 +#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406 +#define GL_LIGHT_ENV_MODE_EXT 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B +#define GL_FRAGMENT_LIGHT0_EXT 0x840C +#define GL_FRAGMENT_LIGHT7_EXT 0x8413 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param); + +#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT) +#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT) +#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT) +#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT) +#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT) +#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT) +#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT) +#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT) +#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT) +#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT) +#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT) +#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT) +#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT) +#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT) +#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT) +#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT) +#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT) +#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT) + +#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting) + +#endif /* GL_EXT_fragment_lighting */ + +/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */ + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 + +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA + +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT) + +#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit) + +#endif /* GL_EXT_framebuffer_blit */ + +/* --------------------- GL_EXT_framebuffer_multisample -------------------- */ + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 + +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT) + +#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample) + +#endif /* GL_EXT_framebuffer_multisample */ + +/* ----------------------- GL_EXT_framebuffer_object ----------------------- */ + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT) +#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT) +#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT) +#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT) +#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT) +#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT) +#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT) +#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT) +#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT) +#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT) +#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT) +#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT) +#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT) +#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT) +#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT) +#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT) +#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT) + +#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object) + +#endif /* GL_EXT_framebuffer_object */ + +/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */ + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA + +#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB) + +#endif /* GL_EXT_framebuffer_sRGB */ + +/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */ + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT) +#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT) +#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT) + +#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4) + +#endif /* GL_EXT_geometry_shader4 */ + +/* --------------------- GL_EXT_gpu_program_parameters --------------------- */ + +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters 1 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); + +#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT) +#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT) + +#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters) + +#endif /* GL_EXT_gpu_program_parameters */ + +/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */ + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT) +#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT) +#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT) +#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT) +#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT) +#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT) +#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT) +#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT) +#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT) +#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT) +#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT) +#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT) +#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT) +#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT) +#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT) +#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT) +#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT) +#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT) +#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT) +#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT) +#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT) +#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT) +#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT) +#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT) +#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT) +#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT) +#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT) +#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT) +#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT) +#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT) +#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT) +#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT) +#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT) +#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT) + +#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4) + +#endif /* GL_EXT_gpu_shader4 */ + +/* ---------------------------- GL_EXT_histogram --------------------------- */ + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 + +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 + +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); + +#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT) +#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT) +#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT) +#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT) +#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT) +#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT) +#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT) +#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT) + +#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram) + +#endif /* GL_EXT_histogram */ + +/* ----------------------- GL_EXT_index_array_formats ---------------------- */ + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 + +#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats) + +#endif /* GL_EXT_index_array_formats */ + +/* --------------------------- GL_EXT_index_func --------------------------- */ + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 + +typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref); + +#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT) + +#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func) + +#endif /* GL_EXT_index_func */ + +/* ------------------------- GL_EXT_index_material ------------------------- */ + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 + +typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT) + +#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material) + +#endif /* GL_EXT_index_material */ + +/* -------------------------- GL_EXT_index_texture ------------------------- */ + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 + +#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture) + +#endif /* GL_EXT_index_texture */ + +/* -------------------------- GL_EXT_light_texture ------------------------- */ + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 + +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 + +typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT) +#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT) +#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT) + +#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture) + +#endif /* GL_EXT_light_texture */ + +/* ------------------------- GL_EXT_misc_attribute ------------------------- */ + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 + +#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute) + +#endif /* GL_EXT_misc_attribute */ + +/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount); + +#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) +#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) + +#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays) + +#endif /* GL_EXT_multi_draw_arrays */ + +/* --------------------------- GL_EXT_multisample -------------------------- */ + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 + +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); + +#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT) +#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT) + +#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample) + +#endif /* GL_EXT_multisample */ + +/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */ + +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 + +#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil) + +#endif /* GL_EXT_packed_depth_stencil */ + +/* -------------------------- GL_EXT_packed_float -------------------------- */ + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 + +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C + +#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float) + +#endif /* GL_EXT_packed_float */ + +/* -------------------------- GL_EXT_packed_pixels ------------------------- */ + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 + +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 + +#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels) + +#endif /* GL_EXT_packed_pixels */ + +/* ------------------------ GL_EXT_paletted_texture ------------------------ */ + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 + +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 +#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); + +#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT) +#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT) +#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT) +#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT) + +#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture) + +#endif /* GL_EXT_paletted_texture */ + +/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */ + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF + +#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object) + +#endif /* GL_EXT_pixel_buffer_object */ + +/* ------------------------- GL_EXT_pixel_transform ------------------------ */ + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 + +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 + +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT) +#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT) +#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT) +#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT) +#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT) +#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT) + +#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform) + +#endif /* GL_EXT_pixel_transform */ + +/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */ + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 + +#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table) + +#endif /* GL_EXT_pixel_transform_color_table */ + +/* ------------------------ GL_EXT_point_parameters ------------------------ */ + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 + +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat* params); + +#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT) +#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT) + +#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters) + +#endif /* GL_EXT_point_parameters */ + +/* ------------------------- GL_EXT_polygon_offset ------------------------- */ + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 + +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 + +typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); + +#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT) + +#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset) + +#endif /* GL_EXT_polygon_offset */ + +/* ------------------------ GL_EXT_provoking_vertex ------------------------ */ + +#ifndef GL_EXT_provoking_vertex +#define GL_EXT_provoking_vertex 1 + +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_PROVOKING_VERTEX_EXT 0x8E4F + +typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); + +#define glProvokingVertexEXT GLEW_GET_FUN(__glewProvokingVertexEXT) + +#define GLEW_EXT_provoking_vertex GLEW_GET_VAR(__GLEW_EXT_provoking_vertex) + +#endif /* GL_EXT_provoking_vertex */ + +/* ------------------------- GL_EXT_rescale_normal ------------------------- */ + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 + +#define GL_RESCALE_NORMAL_EXT 0x803A + +#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal) + +#endif /* GL_EXT_rescale_normal */ + +/* -------------------------- GL_EXT_scene_marker -------------------------- */ + +#ifndef GL_EXT_scene_marker +#define GL_EXT_scene_marker 1 + +typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void); + +#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT) +#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT) + +#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker) + +#endif /* GL_EXT_scene_marker */ + +/* ------------------------- GL_EXT_secondary_color ------------------------ */ + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 + +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E + +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT) +#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT) +#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT) +#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT) +#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT) +#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT) +#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT) +#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT) +#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT) +#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT) +#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT) +#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT) +#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT) + +#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color) + +#endif /* GL_EXT_secondary_color */ + +/* --------------------- GL_EXT_separate_shader_objects -------------------- */ + +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 + +#define GL_ACTIVE_PROGRAM_EXT 0x8B8D + +typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string); +typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); + +#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT) +#define glCreateShaderProgramEXT GLEW_GET_FUN(__glewCreateShaderProgramEXT) +#define glUseShaderProgramEXT GLEW_GET_FUN(__glewUseShaderProgramEXT) + +#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects) + +#endif /* GL_EXT_separate_shader_objects */ + +/* --------------------- GL_EXT_separate_specular_color -------------------- */ + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 + +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA + +#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color) + +#endif /* GL_EXT_separate_specular_color */ + +/* --------------------- GL_EXT_shader_image_load_store -------------------- */ + +#ifndef GL_EXT_shader_image_load_store +#define GL_EXT_shader_image_load_store 1 + +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 +#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 +#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 +#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A +#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B +#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C +#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D +#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E +#define GL_IMAGE_1D_EXT 0x904C +#define GL_IMAGE_2D_EXT 0x904D +#define GL_IMAGE_3D_EXT 0x904E +#define GL_IMAGE_2D_RECT_EXT 0x904F +#define GL_IMAGE_CUBE_EXT 0x9050 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_IMAGE_1D_ARRAY_EXT 0x9052 +#define GL_IMAGE_2D_ARRAY_EXT 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 +#define GL_INT_IMAGE_1D_EXT 0x9057 +#define GL_INT_IMAGE_2D_EXT 0x9058 +#define GL_INT_IMAGE_3D_EXT 0x9059 +#define GL_INT_IMAGE_2D_RECT_EXT 0x905A +#define GL_INT_IMAGE_CUBE_EXT 0x905B +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D +#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C +#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D +#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E +#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); +typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); + +#define glBindImageTextureEXT GLEW_GET_FUN(__glewBindImageTextureEXT) +#define glMemoryBarrierEXT GLEW_GET_FUN(__glewMemoryBarrierEXT) + +#define GLEW_EXT_shader_image_load_store GLEW_GET_VAR(__GLEW_EXT_shader_image_load_store) + +#endif /* GL_EXT_shader_image_load_store */ + +/* -------------------------- GL_EXT_shadow_funcs -------------------------- */ + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 + +#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs) + +#endif /* GL_EXT_shadow_funcs */ + +/* --------------------- GL_EXT_shared_texture_palette --------------------- */ + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 + +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB + +#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette) + +#endif /* GL_EXT_shared_texture_palette */ + +/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */ + +#ifndef GL_EXT_stencil_clear_tag +#define GL_EXT_stencil_clear_tag 1 + +#define GL_STENCIL_TAG_BITS_EXT 0x88F2 +#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 + +#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag) + +#endif /* GL_EXT_stencil_clear_tag */ + +/* ------------------------ GL_EXT_stencil_two_side ------------------------ */ + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 + +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 + +typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); + +#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT) + +#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side) + +#endif /* GL_EXT_stencil_two_side */ + +/* -------------------------- GL_EXT_stencil_wrap -------------------------- */ + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 + +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 + +#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap) + +#endif /* GL_EXT_stencil_wrap */ + +/* --------------------------- GL_EXT_subtexture --------------------------- */ + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 + +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); + +#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) +#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) +#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT) + +#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture) + +#endif /* GL_EXT_subtexture */ + +/* ----------------------------- GL_EXT_texture ---------------------------- */ + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 + +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 + +#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture) + +#endif /* GL_EXT_texture */ + +/* ---------------------------- GL_EXT_texture3D --------------------------- */ + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 + +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); + +#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) + +#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D) + +#endif /* GL_EXT_texture3D */ + +/* -------------------------- GL_EXT_texture_array ------------------------- */ + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 + +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + +#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT) + +#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array) + +#endif /* GL_EXT_texture_array */ + +/* ---------------------- GL_EXT_texture_buffer_object --------------------- */ + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT) + +#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object) + +#endif /* GL_EXT_texture_buffer_object */ + +/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */ + +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 + +#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1) + +#endif /* GL_EXT_texture_compression_dxt1 */ + +/* -------------------- GL_EXT_texture_compression_latc -------------------- */ + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 + +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 + +#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc) + +#endif /* GL_EXT_texture_compression_latc */ + +/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */ + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE + +#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc) + +#endif /* GL_EXT_texture_compression_rgtc */ + +/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc) + +#endif /* GL_EXT_texture_compression_s3tc */ + +/* ------------------------ GL_EXT_texture_cube_map ------------------------ */ + +#ifndef GL_EXT_texture_cube_map +#define GL_EXT_texture_cube_map 1 + +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C + +#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map) + +#endif /* GL_EXT_texture_cube_map */ + +/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */ + +#ifndef GL_EXT_texture_edge_clamp +#define GL_EXT_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_EXT 0x812F + +#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp) + +#endif /* GL_EXT_texture_edge_clamp */ + +/* --------------------------- GL_EXT_texture_env -------------------------- */ + +#ifndef GL_EXT_texture_env +#define GL_EXT_texture_env 1 + +#define GL_TEXTURE_ENV0_EXT 0 +#define GL_ENV_BLEND_EXT 0 +#define GL_TEXTURE_ENV_SHIFT_EXT 0 +#define GL_ENV_REPLACE_EXT 0 +#define GL_ENV_ADD_EXT 0 +#define GL_ENV_SUBTRACT_EXT 0 +#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 +#define GL_ENV_REVERSE_SUBTRACT_EXT 0 +#define GL_ENV_REVERSE_BLEND_EXT 0 +#define GL_ENV_COPY_EXT 0 +#define GL_ENV_MODULATE_EXT 0 + +#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env) + +#endif /* GL_EXT_texture_env */ + +/* ------------------------- GL_EXT_texture_env_add ------------------------ */ + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 + +#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add) + +#endif /* GL_EXT_texture_env_add */ + +/* ----------------------- GL_EXT_texture_env_combine ---------------------- */ + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 + +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A + +#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine) + +#endif /* GL_EXT_texture_env_combine */ + +/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */ + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 + +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 + +#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3) + +#endif /* GL_EXT_texture_env_dot3 */ + +/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */ + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 + +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic) + +#endif /* GL_EXT_texture_filter_anisotropic */ + +/* ------------------------- GL_EXT_texture_integer ------------------------ */ + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 + +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E + +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); + +#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT) +#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT) +#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT) +#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT) +#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT) +#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT) + +#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer) + +#endif /* GL_EXT_texture_integer */ + +/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */ + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 + +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 + +#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias) + +#endif /* GL_EXT_texture_lod_bias */ + +/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */ + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 + +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 + +#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp) + +#endif /* GL_EXT_texture_mirror_clamp */ + +/* ------------------------- GL_EXT_texture_object ------------------------- */ + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 + +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A + +typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences); +typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures); +typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures); +typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities); + +#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT) +#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT) +#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT) +#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT) +#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT) +#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT) + +#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object) + +#endif /* GL_EXT_texture_object */ + +/* --------------------- GL_EXT_texture_perturb_normal --------------------- */ + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 + +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF + +typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); + +#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT) + +#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal) + +#endif /* GL_EXT_texture_perturb_normal */ + +/* ------------------------ GL_EXT_texture_rectangle ----------------------- */ + +#ifndef GL_EXT_texture_rectangle +#define GL_EXT_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 + +#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle) + +#endif /* GL_EXT_texture_rectangle */ + +/* -------------------------- GL_EXT_texture_sRGB -------------------------- */ + +#ifndef GL_EXT_texture_sRGB +#define GL_EXT_texture_sRGB 1 + +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F + +#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB) + +#endif /* GL_EXT_texture_sRGB */ + +/* ----------------------- GL_EXT_texture_sRGB_decode ---------------------- */ + +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 + +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A + +#define GLEW_EXT_texture_sRGB_decode GLEW_GET_VAR(__GLEW_EXT_texture_sRGB_decode) + +#endif /* GL_EXT_texture_sRGB_decode */ + +/* --------------------- GL_EXT_texture_shared_exponent -------------------- */ + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 + +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F + +#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent) + +#endif /* GL_EXT_texture_shared_exponent */ + +/* -------------------------- GL_EXT_texture_snorm ------------------------- */ + +#ifndef GL_EXT_texture_snorm +#define GL_EXT_texture_snorm 1 + +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_ALPHA_SNORM 0x9010 +#define GL_LUMINANCE_SNORM 0x9011 +#define GL_LUMINANCE_ALPHA_SNORM 0x9012 +#define GL_INTENSITY_SNORM 0x9013 +#define GL_ALPHA8_SNORM 0x9014 +#define GL_LUMINANCE8_SNORM 0x9015 +#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 +#define GL_INTENSITY8_SNORM 0x9017 +#define GL_ALPHA16_SNORM 0x9018 +#define GL_LUMINANCE16_SNORM 0x9019 +#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A +#define GL_INTENSITY16_SNORM 0x901B + +#define GLEW_EXT_texture_snorm GLEW_GET_VAR(__GLEW_EXT_texture_snorm) + +#endif /* GL_EXT_texture_snorm */ + +/* ------------------------- GL_EXT_texture_swizzle ------------------------ */ + +#ifndef GL_EXT_texture_swizzle +#define GL_EXT_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 + +#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle) + +#endif /* GL_EXT_texture_swizzle */ + +/* --------------------------- GL_EXT_timer_query -------------------------- */ + +#ifndef GL_EXT_timer_query +#define GL_EXT_timer_query 1 + +#define GL_TIME_ELAPSED_EXT 0x88BF + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); + +#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT) +#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT) + +#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query) + +#endif /* GL_EXT_timer_query */ + +/* ----------------------- GL_EXT_transform_feedback ----------------------- */ + +#ifndef GL_EXT_transform_feedback +#define GL_EXT_transform_feedback 1 + +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F + +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode); + +#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT) +#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT) +#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT) +#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT) +#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT) +#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT) +#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT) + +#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback) + +#endif /* GL_EXT_transform_feedback */ + +/* -------------------------- GL_EXT_vertex_array -------------------------- */ + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 + +#define GL_DOUBLE_EXT 0x140A +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 + +typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); + +#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) +#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) +#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT) +#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT) +#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT) +#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT) +#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT) +#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT) + +#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array) + +#endif /* GL_EXT_vertex_array */ + +/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */ + +#ifndef GL_EXT_vertex_array_bgra +#define GL_EXT_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra) + +#endif /* GL_EXT_vertex_array_bgra */ + +/* ----------------------- GL_EXT_vertex_attrib_64bit ---------------------- */ + +#ifndef GL_EXT_vertex_attrib_64bit +#define GL_EXT_vertex_attrib_64bit 1 + +#define GL_DOUBLE_MAT2_EXT 0x8F46 +#define GL_DOUBLE_MAT3_EXT 0x8F47 +#define GL_DOUBLE_MAT4_EXT 0x8F48 +#define GL_DOUBLE_MAT2x3_EXT 0x8F49 +#define GL_DOUBLE_MAT2x4_EXT 0x8F4A +#define GL_DOUBLE_MAT3x2_EXT 0x8F4B +#define GL_DOUBLE_MAT3x4_EXT 0x8F4C +#define GL_DOUBLE_MAT4x2_EXT 0x8F4D +#define GL_DOUBLE_MAT4x3_EXT 0x8F4E +#define GL_DOUBLE_VEC2_EXT 0x8FFC +#define GL_DOUBLE_VEC3_EXT 0x8FFD +#define GL_DOUBLE_VEC4_EXT 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); + +#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT) +#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT) +#define glVertexAttribL1dEXT GLEW_GET_FUN(__glewVertexAttribL1dEXT) +#define glVertexAttribL1dvEXT GLEW_GET_FUN(__glewVertexAttribL1dvEXT) +#define glVertexAttribL2dEXT GLEW_GET_FUN(__glewVertexAttribL2dEXT) +#define glVertexAttribL2dvEXT GLEW_GET_FUN(__glewVertexAttribL2dvEXT) +#define glVertexAttribL3dEXT GLEW_GET_FUN(__glewVertexAttribL3dEXT) +#define glVertexAttribL3dvEXT GLEW_GET_FUN(__glewVertexAttribL3dvEXT) +#define glVertexAttribL4dEXT GLEW_GET_FUN(__glewVertexAttribL4dEXT) +#define glVertexAttribL4dvEXT GLEW_GET_FUN(__glewVertexAttribL4dvEXT) +#define glVertexAttribLPointerEXT GLEW_GET_FUN(__glewVertexAttribLPointerEXT) + +#define GLEW_EXT_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_EXT_vertex_attrib_64bit) + +#endif /* GL_EXT_vertex_attrib_64bit */ + +/* -------------------------- GL_EXT_vertex_shader ------------------------- */ + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 + +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED + +typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components); +typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data); +typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr); +typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + +#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT) +#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT) +#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT) +#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT) +#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT) +#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT) +#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT) +#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT) +#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT) +#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT) +#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT) +#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT) +#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT) +#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT) +#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT) +#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT) +#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT) +#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT) +#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT) +#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT) +#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT) +#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT) +#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT) +#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT) +#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT) +#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT) +#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT) +#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT) +#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT) +#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT) +#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT) +#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT) +#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT) +#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT) +#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT) +#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT) +#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT) +#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT) +#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT) +#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT) +#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT) + +#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader) + +#endif /* GL_EXT_vertex_shader */ + +/* ------------------------ GL_EXT_vertex_weighting ------------------------ */ + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 + +#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 +#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6 +#define GL_MODELVIEW0_EXT 0x1700 +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 + +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); + +#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT) +#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT) +#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT) + +#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting) + +#endif /* GL_EXT_vertex_weighting */ + +/* ------------------------- GL_EXT_x11_sync_object ------------------------ */ + +#ifndef GL_EXT_x11_sync_object +#define GL_EXT_x11_sync_object 1 + +#define GL_SYNC_X11_FENCE_EXT 0x90E1 + +typedef GLsync (GLAPIENTRY * PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags); + +#define glImportSyncEXT GLEW_GET_FUN(__glewImportSyncEXT) + +#define GLEW_EXT_x11_sync_object GLEW_GET_VAR(__GLEW_EXT_x11_sync_object) + +#endif /* GL_EXT_x11_sync_object */ + +/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */ + +#ifndef GL_GREMEDY_frame_terminator +#define GL_GREMEDY_frame_terminator 1 + +typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); + +#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY) + +#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator) + +#endif /* GL_GREMEDY_frame_terminator */ + +/* ------------------------ GL_GREMEDY_string_marker ----------------------- */ + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 + +typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string); + +#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) + +#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker) + +#endif /* GL_GREMEDY_string_marker */ + +/* --------------------- GL_HP_convolution_border_modes -------------------- */ + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 + +#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes) + +#endif /* GL_HP_convolution_border_modes */ + +/* ------------------------- GL_HP_image_transform ------------------------- */ + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 + +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP) +#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP) +#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP) +#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP) +#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP) + +#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform) + +#endif /* GL_HP_image_transform */ + +/* -------------------------- GL_HP_occlusion_test ------------------------- */ + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 + +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 + +#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test) + +#endif /* GL_HP_occlusion_test */ + +/* ------------------------- GL_HP_texture_lighting ------------------------ */ + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 + +#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting) + +#endif /* GL_HP_texture_lighting */ + +/* --------------------------- GL_IBM_cull_vertex -------------------------- */ + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 + +#define GL_CULL_VERTEX_IBM 103050 + +#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex) + +#endif /* GL_IBM_cull_vertex */ + +/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */ + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride); + +#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM) + +#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays) + +#endif /* GL_IBM_multimode_draw_arrays */ + +/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */ + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 + +#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010 + +#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip) + +#endif /* GL_IBM_rasterpos_clip */ + +/* --------------------------- GL_IBM_static_data -------------------------- */ + +#ifndef GL_IBM_static_data +#define GL_IBM_static_data 1 + +#define GL_ALL_STATIC_DATA_IBM 103060 +#define GL_STATIC_VERTEX_ARRAY_IBM 103061 + +#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data) + +#endif /* GL_IBM_static_data */ + +/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */ + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_IBM_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_IBM 0x8370 + +#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat) + +#endif /* GL_IBM_texture_mirrored_repeat */ + +/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */ + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 + +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); + +#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM) +#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM) +#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM) +#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM) +#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM) +#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM) +#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM) + +#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists) + +#endif /* GL_IBM_vertex_array_lists */ + +/* -------------------------- GL_INGR_color_clamp -------------------------- */ + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 + +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 + +#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp) + +#endif /* GL_INGR_color_clamp */ + +/* ------------------------- GL_INGR_interlace_read ------------------------ */ + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 + +#define GL_INTERLACE_READ_INGR 0x8568 + +#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read) + +#endif /* GL_INGR_interlace_read */ + +/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */ + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 + +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); + +#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL) +#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL) +#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL) +#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL) + +#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays) + +#endif /* GL_INTEL_parallel_arrays */ + +/* ------------------------ GL_INTEL_texture_scissor ----------------------- */ + +#ifndef GL_INTEL_texture_scissor +#define GL_INTEL_texture_scissor 1 + +typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc); +typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh); + +#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL) +#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL) + +#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor) + +#endif /* GL_INTEL_texture_scissor */ + +/* -------------------------- GL_KTX_buffer_region ------------------------- */ + +#ifndef GL_KTX_buffer_region +#define GL_KTX_buffer_region 1 + +#define GL_KTX_FRONT_REGION 0x0 +#define GL_KTX_BACK_REGION 0x1 +#define GL_KTX_Z_REGION 0x2 +#define GL_KTX_STENCIL_REGION 0x3 + +typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); +typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT) +#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT) +#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT) +#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT) +#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT) + +#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region) + +#endif /* GL_KTX_buffer_region */ + +/* ------------------------- GL_MESAX_texture_stack ------------------------ */ + +#ifndef GL_MESAX_texture_stack +#define GL_MESAX_texture_stack 1 + +#define GL_TEXTURE_1D_STACK_MESAX 0x8759 +#define GL_TEXTURE_2D_STACK_MESAX 0x875A +#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B +#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C +#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D +#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E + +#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack) + +#endif /* GL_MESAX_texture_stack */ + +/* -------------------------- GL_MESA_pack_invert -------------------------- */ + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 + +#define GL_PACK_INVERT_MESA 0x8758 + +#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert) + +#endif /* GL_MESA_pack_invert */ + +/* ------------------------- GL_MESA_resize_buffers ------------------------ */ + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 + +typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); + +#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA) + +#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers) + +#endif /* GL_MESA_resize_buffers */ + +/* --------------------------- GL_MESA_window_pos -------------------------- */ + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); + +#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA) +#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA) +#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA) +#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA) +#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA) +#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA) +#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA) +#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA) +#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA) +#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA) +#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA) +#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA) +#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA) +#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA) +#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA) +#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA) +#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA) +#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA) +#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA) +#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA) +#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA) +#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA) +#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA) +#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA) + +#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos) + +#endif /* GL_MESA_window_pos */ + +/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */ + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 + +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 + +#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture) + +#endif /* GL_MESA_ycbcr_texture */ + +/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */ + +#ifndef GL_NVX_gpu_memory_info +#define GL_NVX_gpu_memory_info 1 + +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B + +#define GLEW_NVX_gpu_memory_info GLEW_GET_VAR(__GLEW_NVX_gpu_memory_info) + +#endif /* GL_NVX_gpu_memory_info */ + +/* --------------------------- GL_NV_blend_square -------------------------- */ + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 + +#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square) + +#endif /* GL_NV_blend_square */ + +/* ------------------------ GL_NV_conditional_render ----------------------- */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 + +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void); + +#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV) +#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV) + +#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render) + +#endif /* GL_NV_conditional_render */ + +/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */ + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 + +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F + +#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color) + +#endif /* GL_NV_copy_depth_to_color */ + +/* ---------------------------- GL_NV_copy_image --------------------------- */ + +#ifndef GL_NV_copy_image +#define GL_NV_copy_image 1 + +typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define glCopyImageSubDataNV GLEW_GET_FUN(__glewCopyImageSubDataNV) + +#define GLEW_NV_copy_image GLEW_GET_VAR(__GLEW_NV_copy_image) + +#endif /* GL_NV_copy_image */ + +/* ------------------------ GL_NV_depth_buffer_float ----------------------- */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); + +#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV) +#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV) +#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV) + +#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float) + +#endif /* GL_NV_depth_buffer_float */ + +/* --------------------------- GL_NV_depth_clamp --------------------------- */ + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 + +#define GL_DEPTH_CLAMP_NV 0x864F + +#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp) + +#endif /* GL_NV_depth_clamp */ + +/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */ + +#ifndef GL_NV_depth_range_unclamped +#define GL_NV_depth_range_unclamped 1 + +#define GL_SAMPLE_COUNT_BITS_NV 0x8864 +#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865 +#define GL_QUERY_RESULT_NV 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867 +#define GL_SAMPLE_COUNT_NV 0x8914 + +#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped) + +#endif /* GL_NV_depth_range_unclamped */ + +/* ---------------------------- GL_NV_evaluators --------------------------- */ + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 + +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 + +typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV) +#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV) +#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV) +#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV) +#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV) +#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV) +#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV) +#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV) +#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV) + +#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators) + +#endif /* GL_NV_evaluators */ + +/* ----------------------- GL_NV_explicit_multisample ---------------------- */ + +#ifndef GL_NV_explicit_multisample +#define GL_NV_explicit_multisample 1 + +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); + +#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV) +#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV) +#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV) + +#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample) + +#endif /* GL_NV_explicit_multisample */ + +/* ------------------------------ GL_NV_fence ------------------------------ */ + +#ifndef GL_NV_fence +#define GL_NV_fence 1 + +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences); +typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); + +#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV) +#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV) +#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV) +#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV) +#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV) +#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV) +#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV) + +#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence) + +#endif /* GL_NV_fence */ + +/* --------------------------- GL_NV_float_buffer -------------------------- */ + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 + +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E + +#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer) + +#endif /* GL_NV_float_buffer */ + +/* --------------------------- GL_NV_fog_distance -------------------------- */ + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 + +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C + +#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance) + +#endif /* GL_NV_fog_distance */ + +/* ------------------------- GL_NV_fragment_program ------------------------ */ + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 + +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]); + +#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV) +#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV) +#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV) +#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV) +#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV) +#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV) + +#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program) + +#endif /* GL_NV_fragment_program */ + +/* ------------------------ GL_NV_fragment_program2 ------------------------ */ + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 + +#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2) + +#endif /* GL_NV_fragment_program2 */ + +/* ------------------------ GL_NV_fragment_program4 ------------------------ */ + +#ifndef GL_NV_fragment_program4 +#define GL_NV_fragment_program4 1 + +#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4) + +#endif /* GL_NV_fragment_program4 */ + +/* --------------------- GL_NV_fragment_program_option --------------------- */ + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 + +#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option) + +#endif /* GL_NV_fragment_program_option */ + +/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 + +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV) + +#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage) + +#endif /* GL_NV_framebuffer_multisample_coverage */ + +/* ------------------------ GL_NV_geometry_program4 ------------------------ */ + +#ifndef GL_NV_geometry_program4 +#define GL_NV_geometry_program4 1 + +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 + +typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); + +#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV) + +#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4) + +#endif /* GL_NV_geometry_program4 */ + +/* ------------------------- GL_NV_geometry_shader4 ------------------------ */ + +#ifndef GL_NV_geometry_shader4 +#define GL_NV_geometry_shader4 1 + +#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4) + +#endif /* GL_NV_geometry_shader4 */ + +/* --------------------------- GL_NV_gpu_program4 -------------------------- */ + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 + +#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); + +#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV) +#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV) +#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV) +#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV) +#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV) +#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV) +#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV) +#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV) +#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV) +#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV) +#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV) +#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV) + +#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4) + +#endif /* GL_NV_gpu_program4 */ + +/* --------------------------- GL_NV_gpu_program5 -------------------------- */ + +#ifndef GL_NV_gpu_program5 +#define GL_NV_gpu_program5 1 + +#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C +#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F + +#define GLEW_NV_gpu_program5 GLEW_GET_VAR(__GLEW_NV_gpu_program5) + +#endif /* GL_NV_gpu_program5 */ + +/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */ + +#ifndef GL_NV_gpu_program_fp64 +#define GL_NV_gpu_program_fp64 1 + +#define GLEW_NV_gpu_program_fp64 GLEW_GET_VAR(__GLEW_NV_gpu_program_fp64) + +#endif /* GL_NV_gpu_program_fp64 */ + +/* --------------------------- GL_NV_gpu_shader5 --------------------------- */ + +#ifndef GL_NV_gpu_shader5 +#define GL_NV_gpu_shader5 1 + +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F +#define GL_INT8_NV 0x8FE0 +#define GL_INT8_VEC2_NV 0x8FE1 +#define GL_INT8_VEC3_NV 0x8FE2 +#define GL_INT8_VEC4_NV 0x8FE3 +#define GL_INT16_NV 0x8FE4 +#define GL_INT16_VEC2_NV 0x8FE5 +#define GL_INT16_VEC3_NV 0x8FE6 +#define GL_INT16_VEC4_NV 0x8FE7 +#define GL_INT64_VEC2_NV 0x8FE9 +#define GL_INT64_VEC3_NV 0x8FEA +#define GL_INT64_VEC4_NV 0x8FEB +#define GL_UNSIGNED_INT8_NV 0x8FEC +#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED +#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE +#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF +#define GL_UNSIGNED_INT16_NV 0x8FF0 +#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 +#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 +#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 +#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +typedef void (GLAPIENTRY * PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); + +#define glGetUniformi64vNV GLEW_GET_FUN(__glewGetUniformi64vNV) +#define glGetUniformui64vNV GLEW_GET_FUN(__glewGetUniformui64vNV) +#define glProgramUniform1i64NV GLEW_GET_FUN(__glewProgramUniform1i64NV) +#define glProgramUniform1i64vNV GLEW_GET_FUN(__glewProgramUniform1i64vNV) +#define glProgramUniform1ui64NV GLEW_GET_FUN(__glewProgramUniform1ui64NV) +#define glProgramUniform1ui64vNV GLEW_GET_FUN(__glewProgramUniform1ui64vNV) +#define glProgramUniform2i64NV GLEW_GET_FUN(__glewProgramUniform2i64NV) +#define glProgramUniform2i64vNV GLEW_GET_FUN(__glewProgramUniform2i64vNV) +#define glProgramUniform2ui64NV GLEW_GET_FUN(__glewProgramUniform2ui64NV) +#define glProgramUniform2ui64vNV GLEW_GET_FUN(__glewProgramUniform2ui64vNV) +#define glProgramUniform3i64NV GLEW_GET_FUN(__glewProgramUniform3i64NV) +#define glProgramUniform3i64vNV GLEW_GET_FUN(__glewProgramUniform3i64vNV) +#define glProgramUniform3ui64NV GLEW_GET_FUN(__glewProgramUniform3ui64NV) +#define glProgramUniform3ui64vNV GLEW_GET_FUN(__glewProgramUniform3ui64vNV) +#define glProgramUniform4i64NV GLEW_GET_FUN(__glewProgramUniform4i64NV) +#define glProgramUniform4i64vNV GLEW_GET_FUN(__glewProgramUniform4i64vNV) +#define glProgramUniform4ui64NV GLEW_GET_FUN(__glewProgramUniform4ui64NV) +#define glProgramUniform4ui64vNV GLEW_GET_FUN(__glewProgramUniform4ui64vNV) +#define glUniform1i64NV GLEW_GET_FUN(__glewUniform1i64NV) +#define glUniform1i64vNV GLEW_GET_FUN(__glewUniform1i64vNV) +#define glUniform1ui64NV GLEW_GET_FUN(__glewUniform1ui64NV) +#define glUniform1ui64vNV GLEW_GET_FUN(__glewUniform1ui64vNV) +#define glUniform2i64NV GLEW_GET_FUN(__glewUniform2i64NV) +#define glUniform2i64vNV GLEW_GET_FUN(__glewUniform2i64vNV) +#define glUniform2ui64NV GLEW_GET_FUN(__glewUniform2ui64NV) +#define glUniform2ui64vNV GLEW_GET_FUN(__glewUniform2ui64vNV) +#define glUniform3i64NV GLEW_GET_FUN(__glewUniform3i64NV) +#define glUniform3i64vNV GLEW_GET_FUN(__glewUniform3i64vNV) +#define glUniform3ui64NV GLEW_GET_FUN(__glewUniform3ui64NV) +#define glUniform3ui64vNV GLEW_GET_FUN(__glewUniform3ui64vNV) +#define glUniform4i64NV GLEW_GET_FUN(__glewUniform4i64NV) +#define glUniform4i64vNV GLEW_GET_FUN(__glewUniform4i64vNV) +#define glUniform4ui64NV GLEW_GET_FUN(__glewUniform4ui64NV) +#define glUniform4ui64vNV GLEW_GET_FUN(__glewUniform4ui64vNV) + +#define GLEW_NV_gpu_shader5 GLEW_GET_VAR(__GLEW_NV_gpu_shader5) + +#endif /* GL_NV_gpu_shader5 */ + +/* ---------------------------- GL_NV_half_float --------------------------- */ + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 + +#define GL_HALF_FLOAT_NV 0x140B + +typedef unsigned short GLhalf; + +typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha); +typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz); +typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight); + +#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV) +#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV) +#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV) +#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV) +#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV) +#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV) +#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV) +#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV) +#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV) +#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV) +#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV) +#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV) +#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV) +#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV) +#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV) +#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV) +#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV) +#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV) +#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV) +#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV) +#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV) +#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV) +#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV) +#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV) +#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV) +#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV) +#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV) +#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV) +#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV) +#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV) +#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV) +#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV) +#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV) +#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV) +#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV) +#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV) +#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV) +#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV) +#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV) +#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV) +#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV) +#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV) +#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV) +#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV) +#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV) +#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV) + +#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float) + +#endif /* GL_NV_half_float */ + +/* ------------------------ GL_NV_light_max_exponent ----------------------- */ + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 + +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 + +#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent) + +#endif /* GL_NV_light_max_exponent */ + +/* ----------------------- GL_NV_multisample_coverage ---------------------- */ + +#ifndef GL_NV_multisample_coverage +#define GL_NV_multisample_coverage 1 + +#define GL_COVERAGE_SAMPLES_NV 0x80A9 +#define GL_COLOR_SAMPLES_NV 0x8E20 + +#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage) + +#endif /* GL_NV_multisample_coverage */ + +/* --------------------- GL_NV_multisample_filter_hint --------------------- */ + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 + +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint) + +#endif /* GL_NV_multisample_filter_hint */ + +/* ------------------------- GL_NV_occlusion_query ------------------------- */ + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 + +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 + +typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); + +#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV) +#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV) +#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV) +#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV) +#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV) +#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV) + +#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query) + +#endif /* GL_NV_occlusion_query */ + +/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */ + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA + +#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil) + +#endif /* GL_NV_packed_depth_stencil */ + +/* --------------------- GL_NV_parameter_buffer_object --------------------- */ + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 + +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 +#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 +#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 +#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 + +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); + +#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV) +#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV) +#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV) + +#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object) + +#endif /* GL_NV_parameter_buffer_object */ + +/* --------------------- GL_NV_parameter_buffer_object2 -------------------- */ + +#ifndef GL_NV_parameter_buffer_object2 +#define GL_NV_parameter_buffer_object2 1 + +#define GLEW_NV_parameter_buffer_object2 GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object2) + +#endif /* GL_NV_parameter_buffer_object2 */ + +/* ------------------------- GL_NV_pixel_data_range ------------------------ */ + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 + +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D + +typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer); + +#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) +#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) + +#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range) + +#endif /* GL_NV_pixel_data_range */ + +/* --------------------------- GL_NV_point_sprite -------------------------- */ + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 + +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params); + +#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV) +#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV) + +#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite) + +#endif /* GL_NV_point_sprite */ + +/* -------------------------- GL_NV_present_video -------------------------- */ + +#ifndef GL_NV_present_video +#define GL_NV_present_video 1 + +#define GL_FRAME_NV 0x8E26 +#define GL_FIELDS_NV 0x8E27 +#define GL_CURRENT_TIME_NV 0x8E28 +#define GL_NUM_FILL_STREAMS_NV 0x8E29 +#define GL_PRESENT_TIME_NV 0x8E2A +#define GL_PRESENT_DURATION_NV 0x8E2B + +typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); + +#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV) +#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV) +#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV) +#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV) +#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV) +#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV) + +#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video) + +#endif /* GL_NV_present_video */ + +/* ------------------------ GL_NV_primitive_restart ------------------------ */ + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 + +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 + +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void); + +#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV) +#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV) + +#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart) + +#endif /* GL_NV_primitive_restart */ + +/* ------------------------ GL_NV_register_combiners ----------------------- */ + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 + +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 + +typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params); + +#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV) +#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV) +#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV) +#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV) +#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV) +#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV) +#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV) + +#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners) + +#endif /* GL_NV_register_combiners */ + +/* ----------------------- GL_NV_register_combiners2 ----------------------- */ + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 + +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 + +typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params); + +#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV) + +#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2) + +#endif /* GL_NV_register_combiners2 */ + +/* ------------------------ GL_NV_shader_buffer_load ----------------------- */ + +#ifndef GL_NV_shader_buffer_load +#define GL_NV_shader_buffer_load 1 + +#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D +#define GL_GPU_ADDRESS_NV 0x8F34 +#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 + +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT* result); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); +typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); +typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); + +#define glGetBufferParameterui64vNV GLEW_GET_FUN(__glewGetBufferParameterui64vNV) +#define glGetIntegerui64vNV GLEW_GET_FUN(__glewGetIntegerui64vNV) +#define glGetNamedBufferParameterui64vNV GLEW_GET_FUN(__glewGetNamedBufferParameterui64vNV) +#define glIsBufferResidentNV GLEW_GET_FUN(__glewIsBufferResidentNV) +#define glIsNamedBufferResidentNV GLEW_GET_FUN(__glewIsNamedBufferResidentNV) +#define glMakeBufferNonResidentNV GLEW_GET_FUN(__glewMakeBufferNonResidentNV) +#define glMakeBufferResidentNV GLEW_GET_FUN(__glewMakeBufferResidentNV) +#define glMakeNamedBufferNonResidentNV GLEW_GET_FUN(__glewMakeNamedBufferNonResidentNV) +#define glMakeNamedBufferResidentNV GLEW_GET_FUN(__glewMakeNamedBufferResidentNV) +#define glProgramUniformui64NV GLEW_GET_FUN(__glewProgramUniformui64NV) +#define glProgramUniformui64vNV GLEW_GET_FUN(__glewProgramUniformui64vNV) +#define glUniformui64NV GLEW_GET_FUN(__glewUniformui64NV) +#define glUniformui64vNV GLEW_GET_FUN(__glewUniformui64vNV) + +#define GLEW_NV_shader_buffer_load GLEW_GET_VAR(__GLEW_NV_shader_buffer_load) + +#endif /* GL_NV_shader_buffer_load */ + +/* ---------------------- GL_NV_tessellation_program5 ---------------------- */ + +#ifndef GL_NV_tessellation_program5 +#define GL_NV_tessellation_program5 1 + +#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 +#define GL_TESS_CONTROL_PROGRAM_NV 0x891E +#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F +#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74 +#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75 + +#define GLEW_NV_tessellation_program5 GLEW_GET_VAR(__GLEW_NV_tessellation_program5) + +#endif /* GL_NV_tessellation_program5 */ + +/* -------------------------- GL_NV_texgen_emboss -------------------------- */ + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 + +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F + +#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss) + +#endif /* GL_NV_texgen_emboss */ + +/* ------------------------ GL_NV_texgen_reflection ------------------------ */ + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 + +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 + +#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection) + +#endif /* GL_NV_texgen_reflection */ + +/* ------------------------- GL_NV_texture_barrier ------------------------- */ + +#ifndef GL_NV_texture_barrier +#define GL_NV_texture_barrier 1 + +typedef void (GLAPIENTRY * PFNGLTEXTUREBARRIERNVPROC) (void); + +#define glTextureBarrierNV GLEW_GET_FUN(__glewTextureBarrierNV) + +#define GLEW_NV_texture_barrier GLEW_GET_VAR(__GLEW_NV_texture_barrier) + +#endif /* GL_NV_texture_barrier */ + +/* --------------------- GL_NV_texture_compression_vtc --------------------- */ + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 + +#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc) + +#endif /* GL_NV_texture_compression_vtc */ + +/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */ + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 + +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B + +#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4) + +#endif /* GL_NV_texture_env_combine4 */ + +/* ---------------------- GL_NV_texture_expand_normal ---------------------- */ + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 + +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F + +#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal) + +#endif /* GL_NV_texture_expand_normal */ + +/* ----------------------- GL_NV_texture_multisample ----------------------- */ + +#ifndef GL_NV_texture_multisample +#define GL_NV_texture_multisample 1 + +#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045 +#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); + +#define glTexImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage2DMultisampleCoverageNV) +#define glTexImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage3DMultisampleCoverageNV) +#define glTextureImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage2DMultisampleCoverageNV) +#define glTextureImage2DMultisampleNV GLEW_GET_FUN(__glewTextureImage2DMultisampleNV) +#define glTextureImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage3DMultisampleCoverageNV) +#define glTextureImage3DMultisampleNV GLEW_GET_FUN(__glewTextureImage3DMultisampleNV) + +#define GLEW_NV_texture_multisample GLEW_GET_VAR(__GLEW_NV_texture_multisample) + +#endif /* GL_NV_texture_multisample */ + +/* ------------------------ GL_NV_texture_rectangle ------------------------ */ + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 + +#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle) + +#endif /* GL_NV_texture_rectangle */ + +/* -------------------------- GL_NV_texture_shader ------------------------- */ + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 + +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F + +#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader) + +#endif /* GL_NV_texture_shader */ + +/* ------------------------- GL_NV_texture_shader2 ------------------------- */ + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 + +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D + +#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2) + +#endif /* GL_NV_texture_shader2 */ + +/* ------------------------- GL_NV_texture_shader3 ------------------------- */ + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 + +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 + +#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3) + +#endif /* GL_NV_texture_shader3 */ + +/* ------------------------ GL_NV_transform_feedback ----------------------- */ + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 + +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F + +typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); +typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); + +#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV) +#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV) +#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV) +#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV) +#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV) +#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV) +#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV) +#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV) +#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV) +#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV) +#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV) + +#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback) + +#endif /* GL_NV_transform_feedback */ + +/* ----------------------- GL_NV_transform_feedback2 ----------------------- */ + +#ifndef GL_NV_transform_feedback2 +#define GL_NV_transform_feedback2 1 + +#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 + +typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); +typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint* ids); +typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void); + +#define glBindTransformFeedbackNV GLEW_GET_FUN(__glewBindTransformFeedbackNV) +#define glDeleteTransformFeedbacksNV GLEW_GET_FUN(__glewDeleteTransformFeedbacksNV) +#define glDrawTransformFeedbackNV GLEW_GET_FUN(__glewDrawTransformFeedbackNV) +#define glGenTransformFeedbacksNV GLEW_GET_FUN(__glewGenTransformFeedbacksNV) +#define glIsTransformFeedbackNV GLEW_GET_FUN(__glewIsTransformFeedbackNV) +#define glPauseTransformFeedbackNV GLEW_GET_FUN(__glewPauseTransformFeedbackNV) +#define glResumeTransformFeedbackNV GLEW_GET_FUN(__glewResumeTransformFeedbackNV) + +#define GLEW_NV_transform_feedback2 GLEW_GET_VAR(__GLEW_NV_transform_feedback2) + +#endif /* GL_NV_transform_feedback2 */ + +/* -------------------------- GL_NV_vdpau_interop -------------------------- */ + +#ifndef GL_NV_vdpau_interop +#define GL_NV_vdpau_interop 1 + +#define GL_SURFACE_STATE_NV 0x86EB +#define GL_SURFACE_REGISTERED_NV 0x86FD +#define GL_SURFACE_MAPPED_NV 0x8700 +#define GL_WRITE_DISCARD_NV 0x88BE + +typedef GLintptr GLvdpauSurfaceNV; + +typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values); +typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress); +typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); +typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces); +typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef void (GLAPIENTRY * PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); +typedef void (GLAPIENTRY * PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV* surfaces); +typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); + +#define glVDPAUFiniNV GLEW_GET_FUN(__glewVDPAUFiniNV) +#define glVDPAUGetSurfaceivNV GLEW_GET_FUN(__glewVDPAUGetSurfaceivNV) +#define glVDPAUInitNV GLEW_GET_FUN(__glewVDPAUInitNV) +#define glVDPAUIsSurfaceNV GLEW_GET_FUN(__glewVDPAUIsSurfaceNV) +#define glVDPAUMapSurfacesNV GLEW_GET_FUN(__glewVDPAUMapSurfacesNV) +#define glVDPAURegisterOutputSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterOutputSurfaceNV) +#define glVDPAURegisterVideoSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterVideoSurfaceNV) +#define glVDPAUSurfaceAccessNV GLEW_GET_FUN(__glewVDPAUSurfaceAccessNV) +#define glVDPAUUnmapSurfacesNV GLEW_GET_FUN(__glewVDPAUUnmapSurfacesNV) +#define glVDPAUUnregisterSurfaceNV GLEW_GET_FUN(__glewVDPAUUnregisterSurfaceNV) + +#define GLEW_NV_vdpau_interop GLEW_GET_VAR(__GLEW_NV_vdpau_interop) + +#endif /* GL_NV_vdpau_interop */ + +/* ------------------------ GL_NV_vertex_array_range ----------------------- */ + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) +#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) + +#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range) + +#endif /* GL_NV_vertex_array_range */ + +/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */ + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 + +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 + +#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2) + +#endif /* GL_NV_vertex_array_range2 */ + +/* ------------------- GL_NV_vertex_attrib_integer_64bit ------------------- */ + +#ifndef GL_NV_vertex_attrib_integer_64bit +#define GL_NV_vertex_attrib_integer_64bit 1 + +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); + +#define glGetVertexAttribLi64vNV GLEW_GET_FUN(__glewGetVertexAttribLi64vNV) +#define glGetVertexAttribLui64vNV GLEW_GET_FUN(__glewGetVertexAttribLui64vNV) +#define glVertexAttribL1i64NV GLEW_GET_FUN(__glewVertexAttribL1i64NV) +#define glVertexAttribL1i64vNV GLEW_GET_FUN(__glewVertexAttribL1i64vNV) +#define glVertexAttribL1ui64NV GLEW_GET_FUN(__glewVertexAttribL1ui64NV) +#define glVertexAttribL1ui64vNV GLEW_GET_FUN(__glewVertexAttribL1ui64vNV) +#define glVertexAttribL2i64NV GLEW_GET_FUN(__glewVertexAttribL2i64NV) +#define glVertexAttribL2i64vNV GLEW_GET_FUN(__glewVertexAttribL2i64vNV) +#define glVertexAttribL2ui64NV GLEW_GET_FUN(__glewVertexAttribL2ui64NV) +#define glVertexAttribL2ui64vNV GLEW_GET_FUN(__glewVertexAttribL2ui64vNV) +#define glVertexAttribL3i64NV GLEW_GET_FUN(__glewVertexAttribL3i64NV) +#define glVertexAttribL3i64vNV GLEW_GET_FUN(__glewVertexAttribL3i64vNV) +#define glVertexAttribL3ui64NV GLEW_GET_FUN(__glewVertexAttribL3ui64NV) +#define glVertexAttribL3ui64vNV GLEW_GET_FUN(__glewVertexAttribL3ui64vNV) +#define glVertexAttribL4i64NV GLEW_GET_FUN(__glewVertexAttribL4i64NV) +#define glVertexAttribL4i64vNV GLEW_GET_FUN(__glewVertexAttribL4i64vNV) +#define glVertexAttribL4ui64NV GLEW_GET_FUN(__glewVertexAttribL4ui64NV) +#define glVertexAttribL4ui64vNV GLEW_GET_FUN(__glewVertexAttribL4ui64vNV) +#define glVertexAttribLFormatNV GLEW_GET_FUN(__glewVertexAttribLFormatNV) + +#define GLEW_NV_vertex_attrib_integer_64bit GLEW_GET_VAR(__GLEW_NV_vertex_attrib_integer_64bit) + +#endif /* GL_NV_vertex_attrib_integer_64bit */ + +/* ------------------- GL_NV_vertex_buffer_unified_memory ------------------ */ + +#ifndef GL_NV_vertex_buffer_unified_memory +#define GL_NV_vertex_buffer_unified_memory 1 + +#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E +#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F +#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 +#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 +#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 +#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 +#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 +#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 +#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 +#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 +#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 +#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 +#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A +#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B +#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C +#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D +#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E +#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F +#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 +#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 +#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 +#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 +#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 +#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 +#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 + +typedef void (GLAPIENTRY * PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT result[]); +typedef void (GLAPIENTRY * PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); + +#define glBufferAddressRangeNV GLEW_GET_FUN(__glewBufferAddressRangeNV) +#define glColorFormatNV GLEW_GET_FUN(__glewColorFormatNV) +#define glEdgeFlagFormatNV GLEW_GET_FUN(__glewEdgeFlagFormatNV) +#define glFogCoordFormatNV GLEW_GET_FUN(__glewFogCoordFormatNV) +#define glGetIntegerui64i_vNV GLEW_GET_FUN(__glewGetIntegerui64i_vNV) +#define glIndexFormatNV GLEW_GET_FUN(__glewIndexFormatNV) +#define glNormalFormatNV GLEW_GET_FUN(__glewNormalFormatNV) +#define glSecondaryColorFormatNV GLEW_GET_FUN(__glewSecondaryColorFormatNV) +#define glTexCoordFormatNV GLEW_GET_FUN(__glewTexCoordFormatNV) +#define glVertexAttribFormatNV GLEW_GET_FUN(__glewVertexAttribFormatNV) +#define glVertexAttribIFormatNV GLEW_GET_FUN(__glewVertexAttribIFormatNV) +#define glVertexFormatNV GLEW_GET_FUN(__glewVertexFormatNV) + +#define GLEW_NV_vertex_buffer_unified_memory GLEW_GET_VAR(__GLEW_NV_vertex_buffer_unified_memory) + +#endif /* GL_NV_vertex_buffer_unified_memory */ + +/* -------------------------- GL_NV_vertex_program ------------------------- */ + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 + +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F + +typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v); + +#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV) +#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV) +#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV) +#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV) +#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV) +#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV) +#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV) +#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV) +#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV) +#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV) +#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV) +#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV) +#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV) +#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV) +#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV) +#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV) +#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV) +#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV) +#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV) +#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV) +#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV) +#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV) +#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV) +#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV) +#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV) +#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV) +#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV) +#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV) +#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV) +#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV) +#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV) +#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV) +#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV) +#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV) +#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV) +#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV) +#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV) +#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV) +#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV) +#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV) +#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV) +#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV) +#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV) +#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV) +#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV) +#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV) +#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV) +#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV) +#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV) +#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV) +#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV) +#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV) +#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV) +#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV) +#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV) +#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV) +#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV) +#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV) +#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV) +#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV) +#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV) +#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV) +#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV) +#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV) + +#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program) + +#endif /* GL_NV_vertex_program */ + +/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */ + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 + +#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1) + +#endif /* GL_NV_vertex_program1_1 */ + +/* ------------------------- GL_NV_vertex_program2 ------------------------- */ + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 + +#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2) + +#endif /* GL_NV_vertex_program2 */ + +/* ---------------------- GL_NV_vertex_program2_option --------------------- */ + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 + +#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option) + +#endif /* GL_NV_vertex_program2_option */ + +/* ------------------------- GL_NV_vertex_program3 ------------------------- */ + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 + +#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C + +#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3) + +#endif /* GL_NV_vertex_program3 */ + +/* ------------------------- GL_NV_vertex_program4 ------------------------- */ + +#ifndef GL_NV_vertex_program4 +#define GL_NV_vertex_program4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD + +#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4) + +#endif /* GL_NV_vertex_program4 */ + +/* -------------------------- GL_NV_video_capture -------------------------- */ + +#ifndef GL_NV_video_capture +#define GL_NV_video_capture 1 + +#define GL_VIDEO_BUFFER_NV 0x9020 +#define GL_VIDEO_BUFFER_BINDING_NV 0x9021 +#define GL_FIELD_UPPER_NV 0x9022 +#define GL_FIELD_LOWER_NV 0x9023 +#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024 +#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025 +#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026 +#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027 +#define GL_VIDEO_BUFFER_PITCH_NV 0x9028 +#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029 +#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A +#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B +#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C +#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D +#define GL_PARTIAL_SUCCESS_NV 0x902E +#define GL_SUCCESS_NV 0x902F +#define GL_FAILURE_NV 0x9030 +#define GL_YCBYCR8_422_NV 0x9031 +#define GL_YCBAYCR8A_4224_NV 0x9032 +#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033 +#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034 +#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035 +#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036 +#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037 +#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038 +#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039 +#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A +#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B +#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C + +typedef void (GLAPIENTRY * PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); +typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint* params); +typedef GLenum (GLAPIENTRY * PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint* sequence_num, GLuint64EXT *capture_time); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint* params); + +#define glBeginVideoCaptureNV GLEW_GET_FUN(__glewBeginVideoCaptureNV) +#define glBindVideoCaptureStreamBufferNV GLEW_GET_FUN(__glewBindVideoCaptureStreamBufferNV) +#define glBindVideoCaptureStreamTextureNV GLEW_GET_FUN(__glewBindVideoCaptureStreamTextureNV) +#define glEndVideoCaptureNV GLEW_GET_FUN(__glewEndVideoCaptureNV) +#define glGetVideoCaptureStreamdvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamdvNV) +#define glGetVideoCaptureStreamfvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamfvNV) +#define glGetVideoCaptureStreamivNV GLEW_GET_FUN(__glewGetVideoCaptureStreamivNV) +#define glGetVideoCaptureivNV GLEW_GET_FUN(__glewGetVideoCaptureivNV) +#define glVideoCaptureNV GLEW_GET_FUN(__glewVideoCaptureNV) +#define glVideoCaptureStreamParameterdvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterdvNV) +#define glVideoCaptureStreamParameterfvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterfvNV) +#define glVideoCaptureStreamParameterivNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterivNV) + +#define GLEW_NV_video_capture GLEW_GET_VAR(__GLEW_NV_video_capture) + +#endif /* GL_NV_video_capture */ + +/* ------------------------ GL_OES_byte_coordinates ------------------------ */ + +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 + +#define GL_BYTE 0x1400 + +#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates) + +#endif /* GL_OES_byte_coordinates */ + +/* ------------------- GL_OES_compressed_paletted_texture ------------------ */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 + +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 + +#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture) + +#endif /* GL_OES_compressed_paletted_texture */ + +/* --------------------------- GL_OES_read_format -------------------------- */ + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 + +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B + +#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format) + +#endif /* GL_OES_read_format */ + +/* ------------------------ GL_OES_single_precision ------------------------ */ + +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth); +typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + +#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES) +#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES) +#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES) +#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES) +#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES) +#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES) + +#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision) + +#endif /* GL_OES_single_precision */ + +/* ---------------------------- GL_OML_interlace --------------------------- */ + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 + +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 + +#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace) + +#endif /* GL_OML_interlace */ + +/* ---------------------------- GL_OML_resample ---------------------------- */ + +#ifndef GL_OML_resample +#define GL_OML_resample 1 + +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 + +#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample) + +#endif /* GL_OML_resample */ + +/* ---------------------------- GL_OML_subsample --------------------------- */ + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 + +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 + +#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample) + +#endif /* GL_OML_subsample */ + +/* --------------------------- GL_PGI_misc_hints --------------------------- */ + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 + +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000 +#define GL_CONSERVE_MEMORY_HINT_PGI 107005 +#define GL_RECLAIM_MEMORY_HINT_PGI 107006 +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012 +#define GL_ALWAYS_FAST_HINT_PGI 107020 +#define GL_ALWAYS_SOFT_HINT_PGI 107021 +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022 +#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023 +#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030 +#define GL_STRICT_LIGHTING_HINT_PGI 107031 +#define GL_STRICT_SCISSOR_HINT_PGI 107032 +#define GL_FULL_STIPPLE_HINT_PGI 107033 +#define GL_CLIP_NEAR_HINT_PGI 107040 +#define GL_CLIP_FAR_HINT_PGI 107041 +#define GL_WIDE_LINE_HINT_PGI 107042 +#define GL_BACK_NORMALS_HINT_PGI 107043 + +#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints) + +#endif /* GL_PGI_misc_hints */ + +/* -------------------------- GL_PGI_vertex_hints -------------------------- */ + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 + +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_VERTEX_DATA_HINT_PGI 107050 +#define GL_VERTEX_CONSISTENT_HINT_PGI 107051 +#define GL_MATERIAL_SIDE_HINT_PGI 107052 +#define GL_MAX_VERTEX_HINT_PGI 107053 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 + +#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints) + +#endif /* GL_PGI_vertex_hints */ + +/* ----------------------- GL_REND_screen_coordinates ---------------------- */ + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 + +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 + +#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates) + +#endif /* GL_REND_screen_coordinates */ + +/* ------------------------------- GL_S3_s3tc ------------------------------ */ + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 + +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#define GL_RGBA_DXT5_S3TC 0x83A4 +#define GL_RGBA4_DXT5_S3TC 0x83A5 + +#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc) + +#endif /* GL_S3_s3tc */ + +/* -------------------------- GL_SGIS_color_range -------------------------- */ + +#ifndef GL_SGIS_color_range +#define GL_SGIS_color_range 1 + +#define GL_EXTENDED_RANGE_SGIS 0x85A5 +#define GL_MIN_RED_SGIS 0x85A6 +#define GL_MAX_RED_SGIS 0x85A7 +#define GL_MIN_GREEN_SGIS 0x85A8 +#define GL_MAX_GREEN_SGIS 0x85A9 +#define GL_MIN_BLUE_SGIS 0x85AA +#define GL_MAX_BLUE_SGIS 0x85AB +#define GL_MIN_ALPHA_SGIS 0x85AC +#define GL_MAX_ALPHA_SGIS 0x85AD + +#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range) + +#endif /* GL_SGIS_color_range */ + +/* ------------------------- GL_SGIS_detail_texture ------------------------ */ + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 + +typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points); + +#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS) + +#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture) + +#endif /* GL_SGIS_detail_texture */ + +/* -------------------------- GL_SGIS_fog_function ------------------------- */ + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 + +typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points); + +#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS) +#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS) + +#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function) + +#endif /* GL_SGIS_fog_function */ + +/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */ + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 + +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 + +#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap) + +#endif /* GL_SGIS_generate_mipmap */ + +/* -------------------------- GL_SGIS_multisample -------------------------- */ + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 + +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); + +#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS) +#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS) + +#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample) + +#endif /* GL_SGIS_multisample */ + +/* ------------------------- GL_SGIS_pixel_texture ------------------------- */ + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 + +#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture) + +#endif /* GL_SGIS_pixel_texture */ + +/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */ + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 + +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 + +#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen) + +#endif /* GL_SGIS_point_line_texgen */ + +/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */ + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 + +typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points); +typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); + +#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS) +#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS) + +#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture) + +#endif /* GL_SGIS_sharpen_texture */ + +/* --------------------------- GL_SGIS_texture4D --------------------------- */ + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels); + +#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) +#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) + +#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D) + +#endif /* GL_SGIS_texture4D */ + +/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */ + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_SGIS 0x812D + +#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp) + +#endif /* GL_SGIS_texture_border_clamp */ + +/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */ + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_SGIS 0x812F + +#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp) + +#endif /* GL_SGIS_texture_edge_clamp */ + +/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */ + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 + +typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights); +typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights); + +#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS) + +#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4) + +#endif /* GL_SGIS_texture_filter4 */ + +/* -------------------------- GL_SGIS_texture_lod -------------------------- */ + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 + +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D + +#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod) + +#endif /* GL_SGIS_texture_lod */ + +/* ------------------------- GL_SGIS_texture_select ------------------------ */ + +#ifndef GL_SGIS_texture_select +#define GL_SGIS_texture_select 1 + +#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select) + +#endif /* GL_SGIS_texture_select */ + +/* ----------------------------- GL_SGIX_async ----------------------------- */ + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 + +#define GL_ASYNC_MARKER_SGIX 0x8329 + +typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp); +typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp); + +#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX) +#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX) +#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX) +#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX) +#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX) + +#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async) + +#endif /* GL_SGIX_async */ + +/* ------------------------ GL_SGIX_async_histogram ------------------------ */ + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 + +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D + +#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram) + +#endif /* GL_SGIX_async_histogram */ + +/* -------------------------- GL_SGIX_async_pixel -------------------------- */ + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 + +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 + +#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel) + +#endif /* GL_SGIX_async_pixel */ + +/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */ + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 + +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 + +#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax) + +#endif /* GL_SGIX_blend_alpha_minmax */ + +/* ---------------------------- GL_SGIX_clipmap ---------------------------- */ + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 + +#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap) + +#endif /* GL_SGIX_clipmap */ + +/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */ + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 + +#define GL_CONVOLUTION_HINT_SGIX 0x8316 + +#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy) + +#endif /* GL_SGIX_convolution_accuracy */ + +/* ------------------------- GL_SGIX_depth_texture ------------------------- */ + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 + +#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture) + +#endif /* GL_SGIX_depth_texture */ + +/* -------------------------- GL_SGIX_flush_raster ------------------------- */ + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 + +typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); + +#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX) + +#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster) + +#endif /* GL_SGIX_flush_raster */ + +/* --------------------------- GL_SGIX_fog_offset -------------------------- */ + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 + +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 + +#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset) + +#endif /* GL_SGIX_fog_offset */ + +/* -------------------------- GL_SGIX_fog_texture -------------------------- */ + +#ifndef GL_SGIX_fog_texture +#define GL_SGIX_fog_texture 1 + +#define GL_TEXTURE_FOG_SGIX 0 +#define GL_FOG_PATCHY_FACTOR_SGIX 0 +#define GL_FRAGMENT_FOG_SGIX 0 + +typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname); + +#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX) + +#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture) + +#endif /* GL_SGIX_fog_texture */ + +/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */ + +#ifndef GL_SGIX_fragment_specular_lighting +#define GL_SGIX_fragment_specular_lighting 1 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data); + +#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX) +#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX) +#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX) +#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX) +#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX) +#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX) +#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX) + +#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting) + +#endif /* GL_SGIX_fragment_specular_lighting */ + +/* --------------------------- GL_SGIX_framezoom --------------------------- */ + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 + +typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); + +#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX) + +#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom) + +#endif /* GL_SGIX_framezoom */ + +/* --------------------------- GL_SGIX_interlace --------------------------- */ + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 + +#define GL_INTERLACE_SGIX 0x8094 + +#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace) + +#endif /* GL_SGIX_interlace */ + +/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */ + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 + +#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1) + +#endif /* GL_SGIX_ir_instrument1 */ + +/* ------------------------- GL_SGIX_list_priority ------------------------- */ + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 + +#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority) + +#endif /* GL_SGIX_list_priority */ + +/* ------------------------- GL_SGIX_pixel_texture ------------------------- */ + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 + +typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); + +#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX) + +#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture) + +#endif /* GL_SGIX_pixel_texture */ + +/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */ + +#ifndef GL_SGIX_pixel_texture_bits +#define GL_SGIX_pixel_texture_bits 1 + +#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits) + +#endif /* GL_SGIX_pixel_texture_bits */ + +/* ------------------------ GL_SGIX_reference_plane ------------------------ */ + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 + +typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation); + +#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX) + +#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane) + +#endif /* GL_SGIX_reference_plane */ + +/* ---------------------------- GL_SGIX_resample --------------------------- */ + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 + +#define GL_PACK_RESAMPLE_SGIX 0x842E +#define GL_UNPACK_RESAMPLE_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#define GL_RESAMPLE_REPLICATE_SGIX 0x8433 +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434 + +#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample) + +#endif /* GL_SGIX_resample */ + +/* ----------------------------- GL_SGIX_shadow ---------------------------- */ + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 + +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D + +#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow) + +#endif /* GL_SGIX_shadow */ + +/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */ + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 + +#define GL_SHADOW_AMBIENT_SGIX 0x80BF + +#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient) + +#endif /* GL_SGIX_shadow_ambient */ + +/* ----------------------------- GL_SGIX_sprite ---------------------------- */ + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 + +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params); + +#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX) +#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX) +#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX) +#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX) + +#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite) + +#endif /* GL_SGIX_sprite */ + +/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */ + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 + +typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); + +#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX) + +#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer) + +#endif /* GL_SGIX_tag_sample_buffer */ + +/* ------------------------ GL_SGIX_texture_add_env ------------------------ */ + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 + +#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env) + +#endif /* GL_SGIX_texture_add_env */ + +/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */ + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 + +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B + +#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp) + +#endif /* GL_SGIX_texture_coordinate_clamp */ + +/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */ + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 + +#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias) + +#endif /* GL_SGIX_texture_lod_bias */ + +/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */ + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 + +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E + +#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer) + +#endif /* GL_SGIX_texture_multi_buffer */ + +/* ------------------------- GL_SGIX_texture_range ------------------------- */ + +#ifndef GL_SGIX_texture_range +#define GL_SGIX_texture_range 1 + +#define GL_RGB_SIGNED_SGIX 0x85E0 +#define GL_RGBA_SIGNED_SGIX 0x85E1 +#define GL_ALPHA_SIGNED_SGIX 0x85E2 +#define GL_LUMINANCE_SIGNED_SGIX 0x85E3 +#define GL_INTENSITY_SIGNED_SGIX 0x85E4 +#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5 +#define GL_RGB16_SIGNED_SGIX 0x85E6 +#define GL_RGBA16_SIGNED_SGIX 0x85E7 +#define GL_ALPHA16_SIGNED_SGIX 0x85E8 +#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9 +#define GL_INTENSITY16_SIGNED_SGIX 0x85EA +#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB +#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC +#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED +#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE +#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF +#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0 +#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1 +#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2 +#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3 +#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4 +#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5 +#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6 +#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7 +#define GL_MIN_LUMINANCE_SGIS 0x85F8 +#define GL_MAX_LUMINANCE_SGIS 0x85F9 +#define GL_MIN_INTENSITY_SGIS 0x85FA +#define GL_MAX_INTENSITY_SGIS 0x85FB + +#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range) + +#endif /* GL_SGIX_texture_range */ + +/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */ + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 + +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C + +#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias) + +#endif /* GL_SGIX_texture_scale_bias */ + +/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */ + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip) + +#endif /* GL_SGIX_vertex_preclip */ + +/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */ + +#ifndef GL_SGIX_vertex_preclip_hint +#define GL_SGIX_vertex_preclip_hint 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint) + +#endif /* GL_SGIX_vertex_preclip_hint */ + +/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */ + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 + +#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb) + +#endif /* GL_SGIX_ycrcb */ + +/* -------------------------- GL_SGI_color_matrix -------------------------- */ + +#ifndef GL_SGI_color_matrix +#define GL_SGI_color_matrix 1 + +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB + +#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix) + +#endif /* GL_SGI_color_matrix */ + +/* --------------------------- GL_SGI_color_table -------------------------- */ + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 + +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table); + +#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) +#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) +#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI) +#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI) +#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI) +#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI) + +#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table) + +#endif /* GL_SGI_color_table */ + +/* ----------------------- GL_SGI_texture_color_table ---------------------- */ + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 + +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD + +#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table) + +#endif /* GL_SGI_texture_color_table */ + +/* ------------------------- GL_SUNX_constant_data ------------------------- */ + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 + +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 + +typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); + +#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX) + +#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data) + +#endif /* GL_SUNX_constant_data */ + +/* -------------------- GL_SUN_convolution_border_modes -------------------- */ + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 + +#define GL_WRAP_BORDER_SUN 0x81D4 + +#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes) + +#endif /* GL_SUN_convolution_border_modes */ + +/* -------------------------- GL_SUN_global_alpha -------------------------- */ + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 + +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA + +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); + +#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN) +#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN) +#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN) +#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN) +#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN) +#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN) +#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN) + +#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha) + +#endif /* GL_SUN_global_alpha */ + +/* --------------------------- GL_SUN_mesh_array --------------------------- */ + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 + +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 + +#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array) + +#endif /* GL_SUN_mesh_array */ + +/* ------------------------ GL_SUN_read_video_pixels ----------------------- */ + +#ifndef GL_SUN_read_video_pixels +#define GL_SUN_read_video_pixels 1 + +typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); + +#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN) + +#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels) + +#endif /* GL_SUN_read_video_pixels */ + +/* --------------------------- GL_SUN_slice_accum -------------------------- */ + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 + +#define GL_SLICE_ACCUM_SUN 0x85CC + +#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum) + +#endif /* GL_SUN_slice_accum */ + +/* -------------------------- GL_SUN_triangle_list ------------------------- */ + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 + +#define GL_RESTART_SUN 0x01 +#define GL_REPLACE_MIDDLE_SUN 0x02 +#define GL_REPLACE_OLDEST_SUN 0x03 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB + +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code); + +#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN) +#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN) +#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN) +#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN) +#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN) +#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN) +#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN) + +#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list) + +#endif /* GL_SUN_triangle_list */ + +/* ----------------------------- GL_SUN_vertex ----------------------------- */ + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 + +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v); + +#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN) +#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN) +#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN) +#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN) +#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN) + +#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex) + +#endif /* GL_SUN_vertex */ + +/* -------------------------- GL_WIN_phong_shading ------------------------- */ + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 + +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB + +#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading) + +#endif /* GL_WIN_phong_shading */ + +/* -------------------------- GL_WIN_specular_fog -------------------------- */ + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 + +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC + +#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog) + +#endif /* GL_WIN_specular_fog */ + +/* ---------------------------- GL_WIN_swap_hint --------------------------- */ + +#ifndef GL_WIN_swap_hint +#define GL_WIN_swap_hint 1 + +typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height); + +#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN) + +#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint) + +#endif /* GL_WIN_swap_hint */ + +/* ------------------------------------------------------------------------- */ + +#if defined(GLEW_MX) && defined(_WIN32) +#define GLEW_FUN_EXPORT +#else +#define GLEW_FUN_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) +#define GLEW_VAR_EXPORT +#else +#define GLEW_VAR_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) && defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv; +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage; + +GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer; +GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv; +GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv; +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery; +GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer; +GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries; +GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery; +GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers; +GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv; +GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv; +GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer; +GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery; +GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer; + +GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader; +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram; +GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader; +GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform; +GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation; +GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv; +GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource; +GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram; +GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource; +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate; +GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv; +GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv; +GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv; +GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv; +GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv; +GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv; +GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv; +GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer; + +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback; +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation; +GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv; +GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski; +GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei; +GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback; +GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation; +GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv; +GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex; +GLEW_FUN_EXPORT PFNGLTEXBUFFERPROC __glewTexBuffer; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v; +GLEW_FUN_EXPORT PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v; + +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIPROC __glewBlendEquationi; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei; +GLEW_FUN_EXPORT PFNGLBLENDFUNCIPROC __glewBlendFunci; +GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading; + +GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX; + +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD; + +GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD; +GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD; +GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD; + +GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD; +GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD; +GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD; +GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD; +GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD; + +GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD; + +GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD; +GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE; +GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE; +GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE; +GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE; + +GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE; +GLEW_FUN_EXPORT PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE; +GLEW_FUN_EXPORT PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE; + +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE; +GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef; +GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat; +GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler; +GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed; +GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex; + +GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB; + +GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB; + +GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData; + +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB; +GLEW_FUN_EXPORT PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer; +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary; +GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d; +GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv; +GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d; +GLEW_FUN_EXPORT PFNGLUNIFORM2DVPROC __glewUniform2dv; +GLEW_FUN_EXPORT PFNGLUNIFORM3DPROC __glewUniform3d; +GLEW_FUN_EXPORT PFNGLUNIFORM3DVPROC __glewUniform3dv; +GLEW_FUN_EXPORT PFNGLUNIFORM4DPROC __glewUniform4d; +GLEW_FUN_EXPORT PFNGLUNIFORM4DVPROC __glewUniform4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter; +GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram; +GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram; +GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB; + +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange; +GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange; + +GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB; + +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB; +GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB; +GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB; +GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB; + +GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex; + +GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB; +GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB; +GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB; +GLEW_FUN_EXPORT PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB; +GLEW_FUN_EXPORT PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB; +GLEW_FUN_EXPORT PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB; +GLEW_FUN_EXPORT PFNGLGETNMAPIVARBPROC __glewGetnMapivARB; +GLEW_FUN_EXPORT PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB; +GLEW_FUN_EXPORT PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB; +GLEW_FUN_EXPORT PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB; +GLEW_FUN_EXPORT PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB; +GLEW_FUN_EXPORT PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB; + +GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB; + +GLEW_FUN_EXPORT PFNGLBINDSAMPLERPROC __glewBindSampler; +GLEW_FUN_EXPORT PFNGLDELETESAMPLERSPROC __glewDeleteSamplers; +GLEW_FUN_EXPORT PFNGLGENSAMPLERSPROC __glewGenSamplers; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv; +GLEW_FUN_EXPORT PFNGLISSAMPLERPROC __glewIsSampler; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv; + +GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines; +GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline; + +GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB; +GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB; +GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB; +GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB; +GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB; +GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB; +GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB; + +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName; +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName; +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv; +GLEW_FUN_EXPORT PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex; +GLEW_FUN_EXPORT PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv; +GLEW_FUN_EXPORT PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv; + +GLEW_FUN_EXPORT PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB; +GLEW_FUN_EXPORT PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB; +GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB; +GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB; +GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB; +GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB; + +GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync; +GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync; +GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync; +GLEW_FUN_EXPORT PFNGLGETINTEGER64VPROC __glewGetInteger64v; +GLEW_FUN_EXPORT PFNGLGETSYNCIVPROC __glewGetSynciv; +GLEW_FUN_EXPORT PFNGLISSYNCPROC __glewIsSync; +GLEW_FUN_EXPORT PFNGLWAITSYNCPROC __glewWaitSync; + +GLEW_FUN_EXPORT PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv; +GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri; + +GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB; + +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski; +GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v; +GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter; + +GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback; +GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback; +GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks; +GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback; +GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback; +GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream; +GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed; +GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv; + +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv; +GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v; +GLEW_FUN_EXPORT PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex; +GLEW_FUN_EXPORT PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices; +GLEW_FUN_EXPORT PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer; + +GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB; +GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB; +GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB; +GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB; +GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB; +GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB; + +GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB; +GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB; + +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB; + +GLEW_FUN_EXPORT PFNGLCOLORP3UIPROC __glewColorP3ui; +GLEW_FUN_EXPORT PFNGLCOLORP3UIVPROC __glewColorP3uiv; +GLEW_FUN_EXPORT PFNGLCOLORP4UIPROC __glewColorP4ui; +GLEW_FUN_EXPORT PFNGLCOLORP4UIVPROC __glewColorP4uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv; +GLEW_FUN_EXPORT PFNGLNORMALP3UIPROC __glewNormalP3ui; +GLEW_FUN_EXPORT PFNGLNORMALP3UIVPROC __glewNormalP3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP2UIPROC __glewVertexP2ui; +GLEW_FUN_EXPORT PFNGLVERTEXP2UIVPROC __glewVertexP2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP3UIPROC __glewVertexP3ui; +GLEW_FUN_EXPORT PFNGLVERTEXP3UIVPROC __glewVertexP3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP4UIPROC __glewVertexP4ui; +GLEW_FUN_EXPORT PFNGLVERTEXP4UIVPROC __glewVertexP4uiv; + +GLEW_FUN_EXPORT PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed; +GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v; +GLEW_FUN_EXPORT PFNGLGETFLOATI_VPROC __glewGetFloati_v; +GLEW_FUN_EXPORT PFNGLSCISSORARRAYVPROC __glewScissorArrayv; +GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDPROC __glewScissorIndexed; +GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv; +GLEW_FUN_EXPORT PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv; +GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf; +GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI; + +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI; + +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI; +GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI; +GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI; +GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI; + +GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI; + +GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI; +GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI; + +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI; + +GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI; +GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI; +GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI; +GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT; +GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT; + +GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT; + +GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT; +GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT; + +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT; + +GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT; + +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; +GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT; + +GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT; +GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT; +GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT; +GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT; + +GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT; +GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT; + +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT; + +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT; +GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT; +GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT; +GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT; + +GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT; + +GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT; + +GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT; +GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT; + +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT; + +GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT; + +GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT; +GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT; + +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT; + +GLEW_FUN_EXPORT PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT; +GLEW_FUN_EXPORT PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT; + +GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT; +GLEW_FUN_EXPORT PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT; + +GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT; + +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT; + +GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT; + +GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT; +GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT; + +GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT; +GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT; +GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT; +GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT; +GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT; + +GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT; + +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT; + +GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT; +GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT; +GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT; +GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT; +GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT; + +GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT; +GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT; +GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT; +GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT; +GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT; +GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT; +GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT; +GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT; +GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT; +GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT; +GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT; +GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT; + +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT; + +GLEW_FUN_EXPORT PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT; + +GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY; + +GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY; + +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP; + +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM; +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; + +GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; +GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; + +GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT; + +GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV; + +GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV; +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV; + +GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV; +GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV; +GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV; +GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV; +GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV; +GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV; +GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV; +GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV; +GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV; +GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV; + +GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV; +GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV; + +GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV; +GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV; + +GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV; +GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV; + +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV; +GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV; +GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV; + +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV; +GLEW_FUN_EXPORT PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV; +GLEW_FUN_EXPORT PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV; +GLEW_FUN_EXPORT PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV; +GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORMUI64NVPROC __glewUniformui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV; + +GLEW_FUN_EXPORT PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV; + +GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV; +GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV; + +GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV; +GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV; + +GLEW_FUN_EXPORT PFNGLVDPAUFININVPROC __glewVDPAUFiniNV; +GLEW_FUN_EXPORT PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV; +GLEW_FUN_EXPORT PFNGLVDPAUINITNVPROC __glewVDPAUInitNV; +GLEW_FUN_EXPORT PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV; +GLEW_FUN_EXPORT PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV; +GLEW_FUN_EXPORT PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV; +GLEW_FUN_EXPORT PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV; + +GLEW_FUN_EXPORT PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV; +GLEW_FUN_EXPORT PFNGLCOLORFORMATNVPROC __glewColorFormatNV; +GLEW_FUN_EXPORT PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV; +GLEW_FUN_EXPORT PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV; +GLEW_FUN_EXPORT PFNGLINDEXFORMATNVPROC __glewIndexFormatNV; +GLEW_FUN_EXPORT PFNGLNORMALFORMATNVPROC __glewNormalFormatNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV; +GLEW_FUN_EXPORT PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV; + +GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV; +GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV; +GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV; +GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV; +GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV; +GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV; +GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV; + +GLEW_FUN_EXPORT PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV; +GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV; +GLEW_FUN_EXPORT PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES; +GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES; +GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES; +GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES; +GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES; + +GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS; + +GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS; + +GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS; +GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS; + +GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX; +GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX; + +GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX; + +GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX; + +GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX; + +GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX; + +GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX; + +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX; + +GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI; + +GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX; + +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN; + +GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN; + +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN; + +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN; + +GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN; + +#if defined(GLEW_MX) && !defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_blend_minmax_factor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_object_purgeable; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_row_bytes; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_get_program_binary; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader5; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_meminfo; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB_decode; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_snorm; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_x11_sync_object; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; +GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; +GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_barrier; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vdpau_interop; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_attrib_integer_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_buffer_unified_memory; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_video_capture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint; + +#ifdef GLEW_MX +}; /* GLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +/* error codes */ +#define GLEW_OK 0 +#define GLEW_NO_ERROR 0 +#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */ +#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* Need at least OpenGL 1.1 */ +#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* Need at least GLX 1.2 */ + +/* string codes */ +#define GLEW_VERSION 1 +#define GLEW_VERSION_MAJOR 2 +#define GLEW_VERSION_MINOR 3 +#define GLEW_VERSION_MICRO 4 + +/* API */ +#ifdef GLEW_MX + +typedef struct GLEWContextStruct GLEWContext; +GLEWAPI GLenum glewContextInit (GLEWContext* ctx); +GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name); + +#define glewInit() glewContextInit(glewGetContext()) +#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x) +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x)) +#ifdef _WIN32 +# define GLEW_GET_FUN(x) glewGetContext()->x +#else +# define GLEW_GET_FUN(x) x +#endif + +#else /* GLEW_MX */ + +GLEWAPI GLenum glewInit (); +GLEWAPI GLboolean glewIsSupported (const char* name); +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLEW_GET_FUN(x) x + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean glewExperimental; +GLEWAPI GLboolean glewGetExtension (const char* name); +GLEWAPI const GLubyte* glewGetErrorString (GLenum error); +GLEWAPI const GLubyte* glewGetString (GLenum name); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEW_APIENTRY_DEFINED +#undef GLEW_APIENTRY_DEFINED +#undef APIENTRY +#undef GLAPIENTRY +#define GLAPIENTRY +#endif + +#ifdef GLEW_CALLBACK_DEFINED +#undef GLEW_CALLBACK_DEFINED +#undef CALLBACK +#endif + +#ifdef GLEW_WINGDIAPI_DEFINED +#undef GLEW_WINGDIAPI_DEFINED +#undef WINGDIAPI +#endif + +#undef GLAPI +/* #undef GLEWAPI */ + +#endif /* __glew_h__ */ diff --git a/Code/Physics/Glut/GL/glext.h b/Code/Physics/Glut/GL/glext.h new file mode 100644 index 00000000..10c2bc0f --- /dev/null +++ b/Code/Physics/Glut/GL/glext.h @@ -0,0 +1,3326 @@ +#ifndef __glext_h_ +#define __glext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 1998, 1999, 2000, 2001, NVIDIA Corporation. +** All rights Reserved. +** +** THE INFORMATION CONTAINED HEREIN IS PROPRIETARY AND CONFIDENTIAL TO +** NVIDIA, CORPORATION. USE, REPRODUCTION OR DISCLOSURE TO ANY THIRD PARTY +** IS SUBJECT TO WRITTEN PRE-APPROVAL BY NVIDIA, CORPORATION. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +#define GL_GLEXT_VERSION 6 + +#ifndef GL_VERSION_1_2 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#endif + +#ifndef GL_ARB_multitexture +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 +#endif + +#ifndef GL_ARB_multisample +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif + +#ifndef GL_ARB_texture_compression +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +#endif + +#ifndef GL_EXT_abgr +#define GL_ABGR_EXT 0x8000 +#endif + +#ifndef GL_EXT_blend_color +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 +#endif + +#ifndef GL_EXT_texture +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 +#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#endif + +#ifndef GL_EXT_texture3D +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_FILTER4_SGIS 0x8146 +#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 +#endif + +#ifndef GL_EXT_subtexture +#endif + +#ifndef GL_EXT_copy_texture +#endif + +#ifndef GL_EXT_histogram +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 +#define GL_TABLE_TOO_LARGE_EXT 0x8031 +#endif + +#ifndef GL_EXT_convolution +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 +#endif + +#ifndef GL_SGI_color_matrix +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB +#endif + +#ifndef GL_SGI_color_table +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_PIXEL_TEXTURE_SGIS 0x8353 +#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 +#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 +#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_PIXEL_TEX_BUM_SGIX 0x8139 +#define GL_PIXEL_TEX_BUM_MODE_SGIX 0x832B +#endif + +#ifndef GL_SGIS_texture4D +#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 +#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 +#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 +#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 +#define GL_TEXTURE_4D_SGIS 0x8134 +#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 +#define GL_TEXTURE_4DSIZE_SGIS 0x8136 +#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 +#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 +#define GL_TEXTURE_4D_BINDING_SGIS 0x814F +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD +#endif + +#ifndef GL_EXT_cmyka +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F +#endif + +#ifndef GL_EXT_texture_object +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 +#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 +#define GL_LINEAR_DETAIL_SGIS 0x8097 +#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 +#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 +#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A +#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B +#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_LINEAR_SHARPEN_SGIS 0x80AD +#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE +#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF +#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D +#endif + +#ifndef GL_SGIS_multisample +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_RESCALE_NORMAL_EXT 0x803A +#endif + +#ifndef GL_EXT_vertex_array +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +#endif + +#ifndef GL_EXT_misc_attribute +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 +#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 +#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 +#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 +#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 +#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 +#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 +#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 +#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 +#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D +#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E +#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F +#endif + +#ifndef GL_SGIX_shadow +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_CLAMP_TO_EDGE_SGIS 0x812F +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_CLAMP_TO_BORDER_SGIS 0x812D +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#endif + +#ifndef GL_EXT_blend_logic_op +#endif + +#ifndef GL_SGIX_interlace +#define GL_INTERLACE_SGIX 0x8094 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E +#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F +#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 +#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 +#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 +#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 +#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 +#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 +#endif + +#ifndef GL_SGIS_texture_select +#define GL_DUAL_ALPHA4_SGIS 0x8110 +#define GL_DUAL_ALPHA8_SGIS 0x8111 +#define GL_DUAL_ALPHA12_SGIS 0x8112 +#define GL_DUAL_ALPHA16_SGIS 0x8113 +#define GL_DUAL_LUMINANCE4_SGIS 0x8114 +#define GL_DUAL_LUMINANCE8_SGIS 0x8115 +#define GL_DUAL_LUMINANCE12_SGIS 0x8116 +#define GL_DUAL_LUMINANCE16_SGIS 0x8117 +#define GL_DUAL_INTENSITY4_SGIS 0x8118 +#define GL_DUAL_INTENSITY8_SGIS 0x8119 +#define GL_DUAL_INTENSITY12_SGIS 0x811A +#define GL_DUAL_INTENSITY16_SGIS 0x811B +#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C +#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D +#define GL_QUAD_ALPHA4_SGIS 0x811E +#define GL_QUAD_ALPHA8_SGIS 0x811F +#define GL_QUAD_LUMINANCE4_SGIS 0x8120 +#define GL_QUAD_LUMINANCE8_SGIS 0x8121 +#define GL_QUAD_INTENSITY4_SGIS 0x8122 +#define GL_QUAD_INTENSITY8_SGIS 0x8123 +#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 +#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SPRITE_SGIX 0x8148 +#define GL_SPRITE_MODE_SGIX 0x8149 +#define GL_SPRITE_AXIS_SGIX 0x814A +#define GL_SPRITE_TRANSLATION_SGIX 0x814B +#define GL_SPRITE_AXIAL_SGIX 0x814C +#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D +#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E +#endif + +#ifndef GL_SGIS_point_parameters +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +#endif + +#ifndef GL_SGIX_instruments +#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 +#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C +#endif + +#ifndef GL_SGIX_framezoom +#define GL_FRAMEZOOM_SGIX 0x818B +#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C +#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_REFERENCE_PLANE_SGIX 0x817D +#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E +#endif + +#ifndef GL_SGIX_flush_raster +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_FOG_FUNC_SGIS 0x812A +#define GL_FOG_FUNC_POINTS_SGIS 0x812B +#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 +#endif + +#ifndef GL_HP_image_transform +#define GL_IMAGE_SCALE_X_HP 0x8155 +#define GL_IMAGE_SCALE_Y_HP 0x8156 +#define GL_IMAGE_TRANSLATE_X_HP 0x8157 +#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 +#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 +#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A +#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B +#define GL_IMAGE_MAG_FILTER_HP 0x815C +#define GL_IMAGE_MIN_FILTER_HP 0x815D +#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E +#define GL_CUBIC_HP 0x815F +#define GL_AVERAGE_HP 0x8160 +#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 +#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 +#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_IGNORE_BORDER_HP 0x8150 +#define GL_CONSTANT_BORDER_HP 0x8151 +#define GL_REPLICATE_BORDER_HP 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 +#endif + +#ifndef GL_INGR_palette_buffer +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE +#endif + +#ifndef GL_EXT_color_subtable +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_VERTEX_DATA_HINT_PGI 0x1A22A +#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B +#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C +#define GL_MAX_VERTEX_HINT_PGI 0x1A22D +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 +#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD +#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 +#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C +#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E +#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F +#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 +#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 +#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 +#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 +#define GL_CLIP_NEAR_HINT_PGI 0x1A220 +#define GL_CLIP_FAR_HINT_PGI 0x1A221 +#define GL_WIDE_LINE_HINT_PGI 0x1A222 +#define GL_BACK_NORMALS_HINT_PGI 0x1A223 +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_LIST_PRIORITY_SGIX 0x8182 +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_IR_INSTRUMENT1_SGIX 0x817F +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E +#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F +#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SHADOW_AMBIENT_SGIX 0x80BF +#endif + +#ifndef GL_EXT_index_texture +#endif + +#ifndef GL_EXT_index_material +#define GL_INDEX_MATERIAL_EXT 0x81B8 +#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 +#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA +#endif + +#ifndef GL_EXT_index_func +#define GL_INDEX_TEST_EXT 0x81B5 +#define GL_INDEX_TEST_FUNC_EXT 0x81B6 +#define GL_INDEX_TEST_REF_EXT 0x81B7 +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_IUI_V2F_EXT 0x81AD +#define GL_IUI_V3F_EXT 0x81AE +#define GL_IUI_N3F_V2F_EXT 0x81AF +#define GL_IUI_N3F_V3F_EXT 0x81B0 +#define GL_T2F_IUI_V2F_EXT 0x81B1 +#define GL_T2F_IUI_V3F_EXT 0x81B2 +#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 +#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_YCRCB_422_SGIX 0x81BB +#define GL_YCRCB_444_SGIX 0x81BC +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 +#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 +#define GL_LIGHT_ENV_MODE_SGIX 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B +#define GL_FRAGMENT_LIGHT0_SGIX 0x840C +#define GL_FRAGMENT_LIGHT1_SGIX 0x840D +#define GL_FRAGMENT_LIGHT2_SGIX 0x840E +#define GL_FRAGMENT_LIGHT3_SGIX 0x840F +#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 +#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 +#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 +#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 +#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 +#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +#endif + +#ifndef GL_WIN_phong_shading +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB +#endif + +#ifndef GL_WIN_specular_fog +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC +#endif + +#ifndef GL_EXT_light_texture +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +/* reuse GL_FRAGMENT_DEPTH_EXT */ +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 +#endif + +#ifndef GL_EXT_bgra +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 +#endif + +#ifndef GL_INTEL_texture_scissor +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 +#endif + +#ifndef GL_HP_occlusion_test +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA +#endif + +#ifndef GL_EXT_secondary_color +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF +#endif + +#ifndef GL_EXT_multi_draw_arrays +#endif + +#ifndef GL_EXT_fog_coord +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE3_RGB_EXT 0x8583 +#define GL_SOURCE4_RGB_EXT 0x8584 +#define GL_SOURCE5_RGB_EXT 0x8585 +#define GL_SOURCE6_RGB_EXT 0x8586 +#define GL_SOURCE7_RGB_EXT 0x8587 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_SOURCE3_ALPHA_EXT 0x858B +#define GL_SOURCE4_ALPHA_EXT 0x858C +#define GL_SOURCE5_ALPHA_EXT 0x858D +#define GL_SOURCE6_ALPHA_EXT 0x858E +#define GL_SOURCE7_ALPHA_EXT 0x858F +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND3_RGB_EXT 0x8593 +#define GL_OPERAND4_RGB_EXT 0x8594 +#define GL_OPERAND5_RGB_EXT 0x8595 +#define GL_OPERAND6_RGB_EXT 0x8596 +#define GL_OPERAND7_RGB_EXT 0x8597 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A +#define GL_OPERAND3_ALPHA_EXT 0x859B +#define GL_OPERAND4_ALPHA_EXT 0x859C +#define GL_OPERAND5_ALPHA_EXT 0x859D +#define GL_OPERAND6_ALPHA_EXT 0x859E +#define GL_OPERAND7_ALPHA_EXT 0x859F +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_TRANSFORM_HINT_APPLE 0x85B1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_FOG_SCALE_SGIX 0x81FC +#define GL_FOG_SCALE_VALUE_SGIX 0x81FD +#endif + +#ifndef GL_SUNX_constant_data +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 +#endif + +#ifndef GL_SUN_global_alpha +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA +#endif + +#ifndef GL_SUN_triangle_list +#define GL_RESTART_SUN 0x01 +#define GL_REPLACE_MIDDLE_SUN 0x02 +#define GL_REPLACE_OLDEST_SUN 0x03 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB +#endif + +#ifndef GL_SUN_vertex +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#endif + +#ifndef GL_INGR_color_clamp +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INTERLACE_READ_INGR 0x8568 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 +#endif + +#ifndef GL_EXT_texture_cube_map +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_WRAP_BORDER_SUN 0x81D4 +#endif + +#ifndef GL_EXT_texture_env_add +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX +#define GL_MODELVIEW_MATRIX1_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW0_EXT GL_MODELVIEW +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +#endif + +#ifndef GL_NV_register_combiners +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 +/* reuse GL_TEXTURE0_ARB */ +/* reuse GL_TEXTURE1_ARB */ +/* reuse GL_ZERO */ +/* reuse GL_NONE */ +/* reuse GL_FOG */ +#endif + +#ifndef GL_NV_fog_distance +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C +/* reuse GL_EYE_PLANE */ +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F +#endif + +#ifndef GL_NV_blend_square +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B +#endif + + +#ifndef GL_MESA_resize_buffers +#endif + +#ifndef GL_MESA_window_pos +#endif + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_CULL_VERTEX_IBM 103050 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 +#endif + +#ifndef GL_SGIX_subsample +#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 +#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 +#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 +#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 +#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_YCRCB_SGIX 0x8318 +#define GL_YCRCBA_SGIX 0x8319 +#endif + +#ifndef GL_SGI_depth_pass_instrument +#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 +#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 +#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 +#endif + +#ifndef GL_3DFX_tbuffer +#endif + +#ifndef GL_EXT_multisample +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#endif + +#ifndef GL_SGIX_vertex_preclip +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_CONVOLUTION_HINT_SGIX 0x8316 +#endif + +#ifndef GL_SGIX_resample +#define GL_PACK_RESAMPLE_SGIX 0x842C +#define GL_UNPACK_RESAMPLE_SGIX 0x842D +#define GL_RESAMPLE_REPLICATE_SGIX 0x842E +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF +#endif + + +/*************************************************************/ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf); +extern void APIENTRY glBlendEquation (GLenum); +extern void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +extern void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei); +extern void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat); +extern void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint); +extern void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +extern void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +extern void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +extern void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *); +extern void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean); +extern void APIENTRY glMinmax (GLenum, GLenum, GLboolean); +extern void APIENTRY glResetHistogram (GLenum); +extern void APIENTRY glResetMinmax (GLenum); +extern void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (APIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (APIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (APIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (APIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glActiveTextureARB (GLenum); +extern void APIENTRY glClientActiveTextureARB (GLenum); +extern void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble); +extern void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat); +extern void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord1iARB (GLenum, GLint); +extern void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort); +extern void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *); +extern void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble); +extern void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat); +extern void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint); +extern void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort); +extern void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *); +extern void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble); +extern void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint); +extern void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort); +extern void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *); +extern void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +extern void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *); +extern void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *); +extern void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint); +extern void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *); +extern void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort); +extern void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *); +extern void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *); +extern void APIENTRY glMultTransposeMatrixfARB (const GLfloat *); +extern void APIENTRY glMultTransposeMatrixdARB (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +#endif + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSampleCoverageARB (GLclampf, GLboolean); +extern void APIENTRY glSamplePassARB (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRY * PFNGLSAMPLEPASSARBPROC) (GLenum pass); +#endif + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 +#endif + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, void *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img); +#endif + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 +#endif + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); +#endif + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 +#endif + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *); +extern void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); +typedef void (APIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); +#endif + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); +extern void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +extern void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei); +extern void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +extern void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean); +extern void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean); +extern void APIENTRY glResetHistogramEXT (GLenum); +extern void APIENTRY glResetMinmaxEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (APIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); +#endif + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat); +extern void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint); +extern void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +extern void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +extern void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +#endif + +#ifndef GL_EXT_color_matrix +#define GL_EXT_color_matrix 1 +#endif + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *); +extern void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei); +extern void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPixelTexGenSGIX (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint); +extern void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *); +extern void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat); +extern void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *); +extern void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *); +extern void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 +#endif + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 +#endif + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 +#ifdef GL_GLEXT_PROTOTYPES +extern GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *); +extern void APIENTRY glBindTextureEXT (GLenum, GLuint); +extern void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *); +extern void APIENTRY glGenTexturesEXT (GLsizei, GLuint *); +extern GLboolean APIENTRY glIsTextureEXT (GLuint); +extern void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (APIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (APIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (APIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); +typedef GLboolean (APIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (APIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +extern void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +extern void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 +#endif + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean); +extern void APIENTRY glSamplePatternSGIS (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 +#endif + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glArrayElementEXT (GLint); +extern void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei); +extern void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *); +extern void APIENTRY glGetPointervEXT (GLenum, GLvoid* *); +extern void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +extern void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (APIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); +typedef void (APIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); +typedef void (APIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 +#endif + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendEquationEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 +#endif + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 +#endif + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_SGIX_pixel_tiles 1 +#endif + +#ifndef GL_SGIX_texture_select +#define GL_SGIX_texture_select 1 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat); +extern void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *); +extern void APIENTRY glSpriteParameteriSGIX (GLenum, GLint); +extern void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 +#endif + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPointParameterfEXT (GLenum, GLfloat); +extern void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); +extern void APIENTRY glPointParameterfSGIS (GLenum, GLfloat); +extern void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_SGIX_instruments +#define GL_SGIX_instruments 1 +#ifdef GL_GLEXT_PROTOTYPES +extern GLint APIENTRY glGetInstrumentsSGIX (void); +extern void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *); +extern GLint APIENTRY glPollInstrumentsSGIX (GLint *); +extern void APIENTRY glReadInstrumentsSGIX (GLint); +extern void APIENTRY glStartInstrumentsSGIX (void); +extern void APIENTRY glStopInstrumentsSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLint (APIENTRY * PFNGLGETINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRY * PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); +typedef GLint (APIENTRY * PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); +typedef void (APIENTRY * PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); +typedef void (APIENTRY * PFNGLSTARTINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRY * PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 +#endif + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFrameZoomSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTagSampleBufferSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glReferencePlaneSGIX (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); +#endif + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFlushRasterSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *); +extern void APIENTRY glGetFogFuncSGIS (const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); +typedef void (APIENTRY * PFNGLGETFOGFUNCSGISPROC) (const GLfloat *points); +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 +#endif + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint); +extern void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat); +extern void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *); +extern void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *); +extern void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 +#endif + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glHintPGI (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLHINTPGIPROC) (GLenum target, GLint mode); +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +extern void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *); +extern void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *); +extern void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *); +extern void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *); +extern void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat); +extern void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *); +extern void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint); +extern void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_SGIX_calligraphic_fragment 1 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 +#endif + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 +#endif + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glIndexMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glIndexFuncEXT (GLenum, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glLockArraysEXT (GLint, GLsizei); +extern void APIENTRY glUnlockArraysEXT (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *); +extern void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_SGIX_fragment_lighting 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum); +extern void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat); +extern void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint); +extern void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *); +extern void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat); +extern void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *); +extern void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint); +extern void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *); +extern void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat); +extern void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *); +extern void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint); +extern void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *); +extern void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *); +extern void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *); +extern void APIENTRY glLightEnviSGIX (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +#endif + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 +#endif + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 +#endif + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glApplyTextureEXT (GLenum); +extern void APIENTRY glTextureLightEXT (GLenum); +extern void APIENTRY glTextureMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (APIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (APIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 +#endif + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *); +extern void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *); +extern void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *); +extern void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (APIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); +typedef void (APIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (APIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +#endif + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint); +extern void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat); +extern void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *); +extern void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 +#endif + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte); +extern void APIENTRY glSecondaryColor3bvEXT (const GLbyte *); +extern void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glSecondaryColor3dvEXT (const GLdouble *); +extern void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glSecondaryColor3fvEXT (const GLfloat *); +extern void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint); +extern void APIENTRY glSecondaryColor3ivEXT (const GLint *); +extern void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort); +extern void APIENTRY glSecondaryColor3svEXT (const GLshort *); +extern void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte); +extern void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *); +extern void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint); +extern void APIENTRY glSecondaryColor3uivEXT (const GLuint *); +extern void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort); +extern void APIENTRY glSecondaryColor3usvEXT (const GLushort *); +extern void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTextureNormalEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); +extern void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (APIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +#endif + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFogCoordfEXT (GLfloat); +extern void APIENTRY glFogCoordfvEXT (const GLfloat *); +extern void APIENTRY glFogCoorddEXT (GLdouble); +extern void APIENTRY glFogCoorddvEXT (const GLdouble *); +extern void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (APIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); +typedef void (APIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (APIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (APIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte); +extern void APIENTRY glTangent3bvEXT (const GLbyte *); +extern void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glTangent3dvEXT (const GLdouble *); +extern void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTangent3fvEXT (const GLfloat *); +extern void APIENTRY glTangent3iEXT (GLint, GLint, GLint); +extern void APIENTRY glTangent3ivEXT (const GLint *); +extern void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort); +extern void APIENTRY glTangent3svEXT (const GLshort *); +extern void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte); +extern void APIENTRY glBinormal3bvEXT (const GLbyte *); +extern void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glBinormal3dvEXT (const GLdouble *); +extern void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glBinormal3fvEXT (const GLfloat *); +extern void APIENTRY glBinormal3iEXT (GLint, GLint, GLint); +extern void APIENTRY glBinormal3ivEXT (const GLint *); +extern void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort); +extern void APIENTRY glBinormal3svEXT (const GLshort *); +extern void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *); +extern void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); +typedef void (APIENTRY * PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRY * PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); +typedef void (APIENTRY * PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); +typedef void (APIENTRY * PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); +typedef void (APIENTRY * PFNGLTANGENT3IVEXTPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); +typedef void (APIENTRY * PFNGLTANGENT3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); +typedef void (APIENTRY * PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRY * PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); +typedef void (APIENTRY * PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); +typedef void (APIENTRY * PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); +typedef void (APIENTRY * PFNGLBINORMAL3IVEXTPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); +typedef void (APIENTRY * PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_SGIX_fog_scale 1 +#endif + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFinishTextureSUNX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); +#endif + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glGlobalAlphaFactorbSUN (GLbyte); +extern void APIENTRY glGlobalAlphaFactorsSUN (GLshort); +extern void APIENTRY glGlobalAlphaFactoriSUN (GLint); +extern void APIENTRY glGlobalAlphaFactorfSUN (GLfloat); +extern void APIENTRY glGlobalAlphaFactordSUN (GLdouble); +extern void APIENTRY glGlobalAlphaFactorubSUN (GLubyte); +extern void APIENTRY glGlobalAlphaFactorusSUN (GLushort); +extern void APIENTRY glGlobalAlphaFactoruiSUN (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); +typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +#endif + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glReplacementCodeuiSUN (GLuint); +extern void APIENTRY glReplacementCodeusSUN (GLushort); +extern void APIENTRY glReplacementCodeubSUN (GLubyte); +extern void APIENTRY glReplacementCodeuivSUN (const GLuint *); +extern void APIENTRY glReplacementCodeusvSUN (const GLushort *); +extern void APIENTRY glReplacementCodeubvSUN (const GLubyte *); +extern void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); +#endif + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat); +extern void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *); +extern void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *); +extern void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *); +extern void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLenum *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLenum, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLenum *, const GLubyte *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *); +extern void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLenum rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLenum rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLenum *rc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLenum rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 +#endif + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glVertexWeightfEXT (GLfloat); +extern void APIENTRY glVertexWeightfvEXT (const GLfloat *); +extern void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (APIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); +typedef void (APIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glFlushVertexArrayRangeNV (void); +extern void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (APIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei size, const GLvoid *pointer); +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 +#endif + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *); +extern void APIENTRY glCombinerParameterfNV (GLenum, GLfloat); +extern void APIENTRY glCombinerParameterivNV (GLenum, const GLint *); +extern void APIENTRY glCombinerParameteriNV (GLenum, GLint); +extern void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); +extern void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); +extern void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum); +extern void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *); +extern void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *); +extern void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *); +extern void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (APIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (APIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); +#endif + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 +#endif + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 +#endif + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glResizeBuffersMESA (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); +#endif + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble); +extern void APIENTRY glWindowPos2dvMESA (const GLdouble *); +extern void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat); +extern void APIENTRY glWindowPos2fvMESA (const GLfloat *); +extern void APIENTRY glWindowPos2iMESA (GLint, GLint); +extern void APIENTRY glWindowPos2ivMESA (const GLint *); +extern void APIENTRY glWindowPos2sMESA (GLshort, GLshort); +extern void APIENTRY glWindowPos2svMESA (const GLshort *); +extern void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble); +extern void APIENTRY glWindowPos3dvMESA (const GLdouble *); +extern void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat); +extern void APIENTRY glWindowPos3fvMESA (const GLfloat *); +extern void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint); +extern void APIENTRY glWindowPos3ivMESA (const GLint *); +extern void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort); +extern void APIENTRY glWindowPos3svMESA (const GLshort *); +extern void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble); +extern void APIENTRY glWindowPos4dvMESA (const GLdouble *); +extern void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat); +extern void APIENTRY glWindowPos4fvMESA (const GLfloat *); +extern void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint); +extern void APIENTRY glWindowPos4ivMESA (const GLint *); +extern void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort); +extern void APIENTRY glWindowPos4svMESA (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (APIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (APIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); +typedef void (APIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glMultiModeDrawArraysIBM (GLenum, const GLint *, const GLsizei *, GLsizei, GLint); +extern void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* *, GLsizei, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (APIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, GLint modestride); +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint); +extern void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +extern void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +#endif + +#ifndef GL_SGIX_subsample +#define GL_SGIX_subsample 1 +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_SGIX_ycrcba 1 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#define GL_SGIX_ycrcb_subsample 1 +#endif + +#ifndef GL_SGIX_depth_pass_instrument +#define GL_SGIX_depth_pass_instrument 1 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 +#endif + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTbufferMask3DFX (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); +#endif + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glSampleMaskEXT (GLclampf, GLboolean); +extern void APIENTRY glSamplePatternEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); +#endif + +#ifndef GL_SGI_vertex_preclip +#define GL_SGI_vertex_preclip 1 +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 +#endif + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_SGIS_texture_color_mask 1 +#ifdef GL_GLEXT_PROTOTYPES +extern void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRY * PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#endif + + + +/* added by Cass -- this part will be auto-generated in the future*/ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#endif + +/* Extensions */ +#define GL_ARB_texture_border_clamp 1 +#define GL_ARB_texture_env_combine 1 +#define GL_ARB_texture_env_dot3 1 +#define GL_EXT_texture_env_dot3 1 +#define GL_IBM_texture_mirrored_repeat 1 +#define GL_NV_evaluators 1 +#define GL_NV_fence 1 +#define GL_NV_multisample_filter_hint 1 +#define GL_NV_packed_depth_stencil 1 +#define GL_NV_register_combiners2 1 +#define GL_NV_texture_compression_vtc 1 +#define GL_NV_texture_rectangle 1 +#define GL_NV_texture_shader 1 +#define GL_NV_texture_shader2 1 +#define GL_NV_vertex_program 1 +#define GL_NV_point_sprite 1 +#define GL_NV_occlusion_query 1 + +/* ARB_texture_border_clamp */ +#define GL_CLAMP_TO_BORDER_ARB 0x812D + +/* ARB_texture_env_combine */ +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A +#define GL_SUBTRACT_ARB 0x84E7 + +/* ARB_texture_env_dot3 */ +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF + +/* EXT_texture_env_dot3 */ +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 + +/* IBM_texture_mirrored_repeat */ +#define GL_MIRRORED_REPEAT_IBM 0x8370 + +/* NV_vertex_program */ +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F + +/* NV_evaluators */ +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 + +/* NV_fence */ +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +/* NV_occlusion_query */ +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 + +/* NV_point_sprite */ +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 + +/* NV_texture_rectangle */ +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 + +/* NV_texture_shader */ +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV +#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV +#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_ISOTROPIC_BRDF_NV 0x86EB +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F + +/* NV_texture_shader2 */ +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF + +/* NV_register_combiners2 */ +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 + +/* NV_packed_depth_stencil */ +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA + +/* NV_multisample_filter_hint */ +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +/* NV_texture_compression_vtc */ + +/* NV_vertex_program */ +typedef GLboolean (APIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); +typedef void (APIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (APIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); +typedef void (APIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); +typedef void (APIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (APIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (APIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); + +/* NV_evaluators */ +typedef void (APIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); +typedef void (APIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); +typedef void (APIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); + +/* NV_fence */ +typedef void (APIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (APIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (APIENTRY * PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (APIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (APIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (APIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); + +/* NV_occlusion_query */ +typedef void (APIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); +typedef void (APIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (GLvoid); +typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); + +/* NV_point_sprite */ +typedef void (APIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, int param); +typedef void (APIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const int *params); + +/* NV_register_combiners2 */ +typedef void (APIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Code/Physics/Glut/GL/glut.h b/Code/Physics/Glut/GL/glut.h new file mode 100644 index 00000000..612f3327 --- /dev/null +++ b/Code/Physics/Glut/GL/glut.h @@ -0,0 +1,607 @@ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) + +/* GLUT 3.7 now tries to avoid including + to avoid name space pollution, but Win32's + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 +# define WIN32_LEAN_AND_MEAN +# include +# else + /* XXX This is from Win32's */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif + /* XXX This is from Win32's */ +# ifndef CALLBACK +# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif + /* XXX This is from Win32's and */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# define WINGDIAPI __declspec(dllimport) +# endif + /* XXX This is from Win32's */ +# ifndef _WCHAR_T_DEFINED +/* MinGW32 chokes on the next line */ +#ifndef __MINGW32__ +typedef unsigned short int wchar_t; +#endif //__MINGW32__ +# define _WCHAR_T_DEFINED +# endif +# endif + +#pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +#pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +#pragma comment (lib, "glu32.lib") /* link with OpenGL Utility lib */ + +#ifdef _WIN64 +#pragma message("Note: including lib: glut64.lib\n") +#pragma comment (lib, "glut64.lib") /* link with Win32 GLUT lib */ +#else +#pragma message("Note: including lib: glut32.lib\n") +#pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ +#endif + +#pragma warning (disable:4244) /* Disable bogus conversion warnings. */ +#pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ + +#endif + +#include +#include + +/* define APIENTRY and CALLBACK to null string if we aren't on Win32 */ +#if !defined(_WIN32) +#define APIENTRY +#define GLUT_APIENTRY_DEFINED +#define CALLBACK +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +//#define GLUT_API_VERSION 3 +#define GLUT_API_VERSION 4 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 release with GameGLUT support. +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 13 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +/* Layers for use. */ +#define GLUT_NORMAL 0 +#define GLUT_OVERLAY 1 + +#if defined(_WIN32) +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +extern void *glutStrokeRoman; +extern void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +extern void *glutBitmap9By15; +extern void *glutBitmap8By13; +extern void *glutBitmapTimesRoman10; +extern void *glutBitmapTimesRoman24; +extern void *glutBitmapHelvetica10; +extern void *glutBitmapHelvetica12; +extern void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X 100 +#define GLUT_WINDOW_Y 101 +#define GLUT_WINDOW_WIDTH 102 +#define GLUT_WINDOW_HEIGHT 103 +#define GLUT_WINDOW_BUFFER_SIZE 104 +#define GLUT_WINDOW_STENCIL_SIZE 105 +#define GLUT_WINDOW_DEPTH_SIZE 106 +#define GLUT_WINDOW_RED_SIZE 107 +#define GLUT_WINDOW_GREEN_SIZE 108 +#define GLUT_WINDOW_BLUE_SIZE 109 +#define GLUT_WINDOW_ALPHA_SIZE 110 +#define GLUT_WINDOW_ACCUM_RED_SIZE 111 +#define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 +#define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 +#define GLUT_WINDOW_DOUBLEBUFFER 115 +#define GLUT_WINDOW_RGBA 116 +#define GLUT_WINDOW_PARENT 117 +#define GLUT_WINDOW_NUM_CHILDREN 118 +#define GLUT_WINDOW_COLORMAP_SIZE 119 +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES 120 +#define GLUT_WINDOW_STEREO 121 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR 122 +#endif +#define GLUT_SCREEN_WIDTH 200 +#define GLUT_SCREEN_HEIGHT 201 +#define GLUT_SCREEN_WIDTH_MM 202 +#define GLUT_SCREEN_HEIGHT_MM 203 +#define GLUT_MENU_NUM_ITEMS 300 +#define GLUT_DISPLAY_MODE_POSSIBLE 400 +#define GLUT_INIT_WINDOW_X 500 +#define GLUT_INIT_WINDOW_Y 501 +#define GLUT_INIT_WINDOW_WIDTH 502 +#define GLUT_INIT_WINDOW_HEIGHT 503 +#define GLUT_INIT_DISPLAY_MODE 504 +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME 700 +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID 123 +#endif + +#if (GLUT_API_VERSION >= 2) +/* glutDeviceGet parameters. */ +#define GLUT_HAS_KEYBOARD 600 +#define GLUT_HAS_MOUSE 601 +#define GLUT_HAS_SPACEBALL 602 +#define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 +#define GLUT_HAS_TABLET 604 +#define GLUT_NUM_MOUSE_BUTTONS 605 +#define GLUT_NUM_SPACEBALL_BUTTONS 606 +#define GLUT_NUM_BUTTON_BOX_BUTTONS 607 +#define GLUT_NUM_DIALS 608 +#define GLUT_NUM_TABLET_BUTTONS 609 +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_DEVICE_IGNORE_KEY_REPEAT 610 +#define GLUT_DEVICE_KEY_REPEAT 611 +#define GLUT_HAS_JOYSTICK 612 +#define GLUT_OWNS_JOYSTICK 613 +#define GLUT_JOYSTICK_BUTTONS 614 +#define GLUT_JOYSTICK_AXES 615 +#define GLUT_JOYSTICK_POLL_RATE 616 +#endif + +#if (GLUT_API_VERSION >= 3) +/* glutLayerGet parameters. */ +#define GLUT_OVERLAY_POSSIBLE 800 +#define GLUT_LAYER_IN_USE 801 +#define GLUT_HAS_OVERLAY 802 +#define GLUT_TRANSPARENT_INDEX 803 +#define GLUT_NORMAL_DAMAGED 804 +#define GLUT_OVERLAY_DAMAGED 805 + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* glutVideoResizeGet parameters. */ +#define GLUT_VIDEO_RESIZE_POSSIBLE 900 +#define GLUT_VIDEO_RESIZE_IN_USE 901 +#define GLUT_VIDEO_RESIZE_X_DELTA 902 +#define GLUT_VIDEO_RESIZE_Y_DELTA 903 +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 +#define GLUT_VIDEO_RESIZE_X 906 +#define GLUT_VIDEO_RESIZE_Y 907 +#define GLUT_VIDEO_RESIZE_WIDTH 908 +#define GLUT_VIDEO_RESIZE_HEIGHT 909 +#endif + +/* glutUseLayer parameters. */ +#define GLUT_NORMAL 0 +#define GLUT_OVERLAY 1 + +/* glutGetModifiers return mask. */ +#define GLUT_ACTIVE_SHIFT 1 +#define GLUT_ACTIVE_CTRL 2 +#define GLUT_ACTIVE_ALT 4 + +/* glutSetCursor parameters. */ +/* Basic arrows. */ +#define GLUT_CURSOR_RIGHT_ARROW 0 +#define GLUT_CURSOR_LEFT_ARROW 1 +/* Symbolic cursor shapes. */ +#define GLUT_CURSOR_INFO 2 +#define GLUT_CURSOR_DESTROY 3 +#define GLUT_CURSOR_HELP 4 +#define GLUT_CURSOR_CYCLE 5 +#define GLUT_CURSOR_SPRAY 6 +#define GLUT_CURSOR_WAIT 7 +#define GLUT_CURSOR_TEXT 8 +#define GLUT_CURSOR_CROSSHAIR 9 +/* Directional cursors. */ +#define GLUT_CURSOR_UP_DOWN 10 +#define GLUT_CURSOR_LEFT_RIGHT 11 +/* Sizing cursors. */ +#define GLUT_CURSOR_TOP_SIDE 12 +#define GLUT_CURSOR_BOTTOM_SIDE 13 +#define GLUT_CURSOR_LEFT_SIDE 14 +#define GLUT_CURSOR_RIGHT_SIDE 15 +#define GLUT_CURSOR_TOP_LEFT_CORNER 16 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 +/* Inherit from parent window. */ +#define GLUT_CURSOR_INHERIT 100 +/* Blank cursor. */ +#define GLUT_CURSOR_NONE 101 +/* Fullscreen crosshair (if available). */ +#define GLUT_CURSOR_FULL_CROSSHAIR 102 +#endif + +/* GLUT initialization sub-API. */ +extern void APIENTRY glutInit(int *argcp, char **argv); +extern void APIENTRY glutInitDisplayMode(unsigned int mode); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern void APIENTRY glutInitDisplayString(const char *string); +#endif +extern void APIENTRY glutInitWindowPosition(int x, int y); +extern void APIENTRY glutInitWindowSize(int width, int height); +extern void APIENTRY glutMainLoop(void); + +/* GLUT window sub-API. */ +extern int APIENTRY glutCreateWindow(const char *title); +extern int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); +extern void APIENTRY glutDestroyWindow(int win); +extern void APIENTRY glutPostRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +extern void APIENTRY glutPostWindowRedisplay(int win); +#endif +extern void APIENTRY glutSwapBuffers(void); +extern int APIENTRY glutGetWindow(void); +extern void APIENTRY glutSetWindow(int win); +extern void APIENTRY glutSetWindowTitle(const char *title); +extern void APIENTRY glutSetIconTitle(const char *title); +extern void APIENTRY glutPositionWindow(int x, int y); +extern void APIENTRY glutReshapeWindow(int width, int height); +extern void APIENTRY glutPopWindow(void); +extern void APIENTRY glutPushWindow(void); +extern void APIENTRY glutIconifyWindow(void); +extern void APIENTRY glutShowWindow(void); +extern void APIENTRY glutHideWindow(void); +#if (GLUT_API_VERSION >= 3) +extern void APIENTRY glutFullScreen(void); +extern void APIENTRY glutSetCursor(int cursor); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern void APIENTRY glutWarpPointer(int x, int y); +#endif + +/* GLUT overlay sub-API. */ +extern void APIENTRY glutEstablishOverlay(void); +extern void APIENTRY glutRemoveOverlay(void); +extern void APIENTRY glutUseLayer(GLenum layer); +extern void APIENTRY glutPostOverlayRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +extern void APIENTRY glutPostWindowOverlayRedisplay(int win); +#endif +extern void APIENTRY glutShowOverlay(void); +extern void APIENTRY glutHideOverlay(void); +#endif + +/* GLUT menu sub-API. */ +extern int APIENTRY glutCreateMenu(void (*)(int)); +extern void APIENTRY glutDestroyMenu(int menu); +extern int APIENTRY glutGetMenu(void); +extern void APIENTRY glutSetMenu(int menu); +extern void APIENTRY glutAddMenuEntry(const char *label, int value); +extern void APIENTRY glutAddSubMenu(const char *label, int submenu); +extern void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); +extern void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); +extern void APIENTRY glutRemoveMenuItem(int item); +extern void APIENTRY glutAttachMenu(int button); +extern void APIENTRY glutDetachMenu(int button); + +/* GLUT window callback sub-API. */ +extern void APIENTRY glutDisplayFunc(void (*func)(void)); +extern void APIENTRY glutReshapeFunc(void (*func)(int width, int height)); +extern void APIENTRY glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)); +extern void APIENTRY glutMouseFunc(void (*func)(int button, int state, int x, int y)); +extern void APIENTRY glutMotionFunc(void (*func)(int x, int y)); +extern void APIENTRY glutPassiveMotionFunc(void (*func)(int x, int y)); +extern void APIENTRY glutEntryFunc(void (*func)(int state)); +extern void APIENTRY glutVisibilityFunc(void (*func)(int state)); +extern void APIENTRY glutIdleFunc(void (*func)(void)); +extern void APIENTRY glutTimerFunc(unsigned int millis, void (*func)(int value), int value); +extern void APIENTRY glutMenuStateFunc(void (*func)(int state)); +#if (GLUT_API_VERSION >= 2) +extern void APIENTRY glutSpecialFunc(void (*func)(int key, int x, int y)); +extern void APIENTRY glutSpaceballMotionFunc(void (*func)(int x, int y, int z)); +extern void APIENTRY glutSpaceballRotateFunc(void (*func)(int x, int y, int z)); +extern void APIENTRY glutSpaceballButtonFunc(void (*func)(int button, int state)); +extern void APIENTRY glutButtonBoxFunc(void (*func)(int button, int state)); +extern void APIENTRY glutDialsFunc(void (*func)(int dial, int value)); +extern void APIENTRY glutTabletMotionFunc(void (*func)(int x, int y)); +extern void APIENTRY glutTabletButtonFunc(void (*func)(int button, int state, int x, int y)); +#if (GLUT_API_VERSION >= 3) +extern void APIENTRY glutMenuStatusFunc(void (*func)(int status, int x, int y)); +extern void APIENTRY glutOverlayDisplayFunc(void (*func)(void)); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern void APIENTRY glutWindowStatusFunc(void (*func)(int state)); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +extern void APIENTRY glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y)); +extern void APIENTRY glutSpecialUpFunc(void (*func)(int key, int x, int y)); +extern void APIENTRY glutJoystickFunc(void (*func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); +#endif +#endif +#endif + +/* GLUT color index sub-API. */ +extern void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +extern GLfloat APIENTRY glutGetColor(int ndx, int component); +extern void APIENTRY glutCopyColormap(int win); + +/* GLUT state retrieval sub-API. */ +extern int APIENTRY glutGet(GLenum type); +extern int APIENTRY glutDeviceGet(GLenum type); +#if (GLUT_API_VERSION >= 2) +/* GLUT extension support sub-API */ +extern int APIENTRY glutExtensionSupported(const char *name); +#endif +#if (GLUT_API_VERSION >= 3) +extern int APIENTRY glutGetModifiers(void); +extern int APIENTRY glutLayerGet(GLenum type); +#endif + +/* GLUT font sub-API */ +extern void APIENTRY glutBitmapCharacter(void *font, int character); +extern int APIENTRY glutBitmapWidth(void *font, int character); +extern void APIENTRY glutStrokeCharacter(void *font, int character); +extern int APIENTRY glutStrokeWidth(void *font, int character); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +extern int APIENTRY glutBitmapLength(void *font, const unsigned char *string); +extern int APIENTRY glutStrokeLength(void *font, const unsigned char *string); +#endif + +/* GLUT pre-built models sub-API */ +extern void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +extern void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +extern void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void APIENTRY glutWireCube(GLdouble size); +extern void APIENTRY glutSolidCube(GLdouble size); +extern void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void APIENTRY glutWireDodecahedron(void); +extern void APIENTRY glutSolidDodecahedron(void); +extern void APIENTRY glutWireTeapot(GLdouble size); +extern void APIENTRY glutSolidTeapot(GLdouble size); +extern void APIENTRY glutWireOctahedron(void); +extern void APIENTRY glutSolidOctahedron(void); +extern void APIENTRY glutWireTetrahedron(void); +extern void APIENTRY glutSolidTetrahedron(void); +extern void APIENTRY glutWireIcosahedron(void); +extern void APIENTRY glutSolidIcosahedron(void); + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* GLUT video resize sub-API. */ +extern int APIENTRY glutVideoResizeGet(GLenum param); +extern void APIENTRY glutSetupVideoResizing(void); +extern void APIENTRY glutStopVideoResizing(void); +extern void APIENTRY glutVideoResize(int x, int y, int width, int height); +extern void APIENTRY glutVideoPan(int x, int y, int width, int height); + +/* GLUT debugging sub-API. */ +extern void APIENTRY glutReportErrors(void); +#endif + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +/* GLUT device control sub-API. */ +/* glutSetKeyRepeat modes. */ +#define GLUT_KEY_REPEAT_OFF 0 +#define GLUT_KEY_REPEAT_ON 1 +#define GLUT_KEY_REPEAT_DEFAULT 2 + +/* Joystick button masks. */ +#define GLUT_JOYSTICK_BUTTON_A 1 +#define GLUT_JOYSTICK_BUTTON_B 2 +#define GLUT_JOYSTICK_BUTTON_C 4 +#define GLUT_JOYSTICK_BUTTON_D 8 + +extern void APIENTRY glutIgnoreKeyRepeat(int ignore); +extern void APIENTRY glutSetKeyRepeat(int repeatMode); +extern void APIENTRY glutForceJoystickFunc(void); + +/* GLUT game mode sub-API. */ +/* glutGameModeGet. */ +#define GLUT_GAME_MODE_ACTIVE 0 +#define GLUT_GAME_MODE_POSSIBLE 1 +#define GLUT_GAME_MODE_WIDTH 2 +#define GLUT_GAME_MODE_HEIGHT 3 +#define GLUT_GAME_MODE_PIXEL_DEPTH 4 +#define GLUT_GAME_MODE_REFRESH_RATE 5 +#define GLUT_GAME_MODE_DISPLAY_CHANGED 6 + +extern void APIENTRY glutGameModeString(const char *string); +extern int APIENTRY glutEnterGameMode(void); +extern void APIENTRY glutLeaveGameMode(void); +extern int APIENTRY glutGameModeGet(GLenum mode); +#endif + +#ifdef __cplusplus +} + +#endif + +#ifdef GLUT_APIENTRY_DEFINED +# undef GLUT_APIENTRY_DEFINED +# undef APIENTRY +#endif + +#ifdef GLUT_WINGDIAPI_DEFINED +# undef GLUT_WINGDIAPI_DEFINED +# undef WINGDIAPI +#endif + +#endif /* __glut_h__ */ diff --git a/Code/Physics/Glut/GL/glxew.h b/Code/Physics/Glut/GL/glxew.h new file mode 100644 index 00000000..6d249f73 --- /dev/null +++ b/Code/Physics/Glut/GL/glxew.h @@ -0,0 +1,1587 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glxew_h__ +#define __glxew_h__ +#define __GLXEW_H__ + +#ifdef __glxext_h_ +#error glxext.h included before glxew.h +#endif + +#if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__) +#error glx.h included before glxew.h +#endif + +#define __glxext_h_ + +#define GLX_H +#define __GLX_glx_h__ +#define __glx_h__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------- GLX_VERSION_1_0 --------------------------- */ + +#ifndef GLX_VERSION_1_0 +#define GLX_VERSION_1_0 1 + +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + +typedef XID GLXDrawable; +typedef XID GLXPixmap; +#ifdef __sun +typedef struct __glXContextRec *GLXContext; +#else +typedef struct __GLXcontextRec *GLXContext; +#endif + +typedef unsigned int GLXVideoDeviceNV; + +extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase); +extern Bool glXQueryVersion (Display *dpy, int *major, int *minor); +extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value); +extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList); +extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap); +extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix); +extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); +extern void glXDestroyContext (Display *dpy, GLXContext ctx); +extern Bool glXIsDirect (Display *dpy, GLXContext ctx); +extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask); +extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx); +extern GLXContext glXGetCurrentContext (void); +extern GLXDrawable glXGetCurrentDrawable (void); +extern void glXWaitGL (void); +extern void glXWaitX (void); +extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable); +extern void glXUseXFont (Font font, int first, int count, int listBase); + +#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0) + +#endif /* GLX_VERSION_1_0 */ + +/* ---------------------------- GLX_VERSION_1_1 --------------------------- */ + +#ifndef GLX_VERSION_1_1 +#define GLX_VERSION_1_1 + +#define GLX_VENDOR 0x1 +#define GLX_VERSION 0x2 +#define GLX_EXTENSIONS 0x3 + +extern const char* glXQueryExtensionsString (Display *dpy, int screen); +extern const char* glXGetClientString (Display *dpy, int name); +extern const char* glXQueryServerString (Display *dpy, int screen, int name); + +#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1) + +#endif /* GLX_VERSION_1_1 */ + +/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */ + +#ifndef GLX_VERSION_1_2 +#define GLX_VERSION_1_2 1 + +typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void); + +#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay) + +#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2) + +#endif /* GLX_VERSION_1_2 */ + +/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */ + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 + +#define GLX_RGBA_BIT 0x00000001 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_DONT_CARE 0xFFFFFFFF + +typedef XID GLXFBConfigID; +typedef XID GLXPbuffer; +typedef XID GLXWindow; +typedef struct __GLXFBConfigRec *GLXFBConfig; + +typedef struct { + int event_type; + int draw_type; + unsigned long serial; + Bool send_event; + Display *display; + GLXDrawable drawable; + unsigned int buffer_mask; + unsigned int aux_buffer; + int x, y; + int width, height; + int count; +} GLXPbufferClobberEvent; +typedef union __GLXEvent { + GLXPbufferClobberEvent glxpbufferclobber; + long pad[24]; +} GLXEvent; + +typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); + +#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig) +#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext) +#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer) +#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap) +#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow) +#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer) +#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap) +#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow) +#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable) +#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib) +#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs) +#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent) +#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig) +#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent) +#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext) +#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable) +#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent) + +#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3) + +#endif /* GLX_VERSION_1_3 */ + +/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */ + +#ifndef GLX_VERSION_1_4 +#define GLX_VERSION_1_4 1 + +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 + +extern void ( * glXGetProcAddress (const GLubyte *procName)) (void); + +#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4) + +#endif /* GLX_VERSION_1_4 */ + +/* -------------------------- GLX_3DFX_multisample ------------------------- */ + +#ifndef GLX_3DFX_multisample +#define GLX_3DFX_multisample 1 + +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 + +#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample) + +#endif /* GLX_3DFX_multisample */ + +/* ------------------------ GLX_AMD_gpu_association ------------------------ */ + +#ifndef GLX_AMD_gpu_association +#define GLX_AMD_gpu_association 1 + +#define GLX_GPU_VENDOR_AMD 0x1F00 +#define GLX_GPU_RENDERER_STRING_AMD 0x1F01 +#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define GLX_GPU_RAM_AMD 0x21A3 +#define GLX_GPU_CLOCK_AMD 0x21A4 +#define GLX_GPU_NUM_PIPES_AMD 0x21A5 +#define GLX_GPU_NUM_SIMD_AMD 0x21A6 +#define GLX_GPU_NUM_RB_AMD 0x21A7 +#define GLX_GPU_NUM_SPI_AMD 0x21A8 + +#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association) + +#endif /* GLX_AMD_gpu_association */ + +/* ------------------------- GLX_ARB_create_context ------------------------ */ + +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context 1 + +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 + +typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); + +#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB) + +#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context) + +#endif /* GLX_ARB_create_context */ + +/* --------------------- GLX_ARB_create_context_profile -------------------- */ + +#ifndef GLX_ARB_create_context_profile +#define GLX_ARB_create_context_profile 1 + +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define GLXEW_ARB_create_context_profile GLXEW_GET_VAR(__GLXEW_ARB_create_context_profile) + +#endif /* GLX_ARB_create_context_profile */ + +/* ------------------- GLX_ARB_create_context_robustness ------------------- */ + +#ifndef GLX_ARB_create_context_robustness +#define GLX_ARB_create_context_robustness 1 + +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 + +#define GLXEW_ARB_create_context_robustness GLXEW_GET_VAR(__GLXEW_ARB_create_context_robustness) + +#endif /* GLX_ARB_create_context_robustness */ + +/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */ + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 + +#define GLX_RGBA_FLOAT_BIT 0x00000004 +#define GLX_RGBA_FLOAT_TYPE 0x20B9 + +#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float) + +#endif /* GLX_ARB_fbconfig_float */ + +/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_ARB_framebuffer_sRGB +#define GLX_ARB_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 + +#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB) + +#endif /* GLX_ARB_framebuffer_sRGB */ + +/* ------------------------ GLX_ARB_get_proc_address ----------------------- */ + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 + +extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void); + +#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address) + +#endif /* GLX_ARB_get_proc_address */ + +/* -------------------------- GLX_ARB_multisample -------------------------- */ + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample 1 + +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 + +#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample) + +#endif /* GLX_ARB_multisample */ + +/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */ + +#ifndef GLX_ARB_vertex_buffer_object +#define GLX_ARB_vertex_buffer_object 1 + +#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095 + +#define GLXEW_ARB_vertex_buffer_object GLXEW_GET_VAR(__GLXEW_ARB_vertex_buffer_object) + +#endif /* GLX_ARB_vertex_buffer_object */ + +/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */ + +#ifndef GLX_ATI_pixel_format_float +#define GLX_ATI_pixel_format_float 1 + +#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100 + +#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float) + +#endif /* GLX_ATI_pixel_format_float */ + +/* ------------------------- GLX_ATI_render_texture ------------------------ */ + +#ifndef GLX_ATI_render_texture +#define GLX_ATI_render_texture 1 + +#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800 +#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801 +#define GLX_TEXTURE_FORMAT_ATI 0x9802 +#define GLX_TEXTURE_TARGET_ATI 0x9803 +#define GLX_MIPMAP_TEXTURE_ATI 0x9804 +#define GLX_TEXTURE_RGB_ATI 0x9805 +#define GLX_TEXTURE_RGBA_ATI 0x9806 +#define GLX_NO_TEXTURE_ATI 0x9807 +#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808 +#define GLX_TEXTURE_1D_ATI 0x9809 +#define GLX_TEXTURE_2D_ATI 0x980A +#define GLX_MIPMAP_LEVEL_ATI 0x980B +#define GLX_CUBE_MAP_FACE_ATI 0x980C +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810 +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811 +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812 +#define GLX_FRONT_LEFT_ATI 0x9813 +#define GLX_FRONT_RIGHT_ATI 0x9814 +#define GLX_BACK_LEFT_ATI 0x9815 +#define GLX_BACK_RIGHT_ATI 0x9816 +#define GLX_AUX0_ATI 0x9817 +#define GLX_AUX1_ATI 0x9818 +#define GLX_AUX2_ATI 0x9819 +#define GLX_AUX3_ATI 0x981A +#define GLX_AUX4_ATI 0x981B +#define GLX_AUX5_ATI 0x981C +#define GLX_AUX6_ATI 0x981D +#define GLX_AUX7_ATI 0x981E +#define GLX_AUX8_ATI 0x981F +#define GLX_AUX9_ATI 0x9820 +#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821 +#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822 + +typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); +typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); + +#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI) +#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI) +#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI) + +#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture) + +#endif /* GLX_ATI_render_texture */ + +/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */ + +#ifndef GLX_EXT_create_context_es2_profile +#define GLX_EXT_create_context_es2_profile 1 + +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#define GLXEW_EXT_create_context_es2_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es2_profile) + +#endif /* GLX_EXT_create_context_es2_profile */ + +/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */ + +#ifndef GLX_EXT_fbconfig_packed_float +#define GLX_EXT_fbconfig_packed_float 1 + +#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 +#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 + +#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float) + +#endif /* GLX_EXT_fbconfig_packed_float */ + +/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_EXT_framebuffer_sRGB +#define GLX_EXT_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 + +#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB) + +#endif /* GLX_EXT_framebuffer_sRGB */ + +/* ------------------------- GLX_EXT_import_context ------------------------ */ + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 + +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C + +typedef XID GLXContextID; + +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value); + +#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT) +#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT) +#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT) +#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT) + +#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context) + +#endif /* GLX_EXT_import_context */ + +/* -------------------------- GLX_EXT_scene_marker ------------------------- */ + +#ifndef GLX_EXT_scene_marker +#define GLX_EXT_scene_marker 1 + +#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker) + +#endif /* GLX_EXT_scene_marker */ + +/* -------------------------- GLX_EXT_swap_control ------------------------- */ + +#ifndef GLX_EXT_swap_control +#define GLX_EXT_swap_control 1 + +#define GLX_SWAP_INTERVAL_EXT 0x20F1 +#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 + +typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval); + +#define glXSwapIntervalEXT GLXEW_GET_FUN(__glewXSwapIntervalEXT) + +#define GLXEW_EXT_swap_control GLXEW_GET_VAR(__GLXEW_EXT_swap_control) + +#endif /* GLX_EXT_swap_control */ + +/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */ + +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_EXT_texture_from_pixmap 1 + +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB + +typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer); + +#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT) +#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT) + +#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap) + +#endif /* GLX_EXT_texture_from_pixmap */ + +/* -------------------------- GLX_EXT_visual_info -------------------------- */ + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 + +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 + +#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info) + +#endif /* GLX_EXT_visual_info */ + +/* ------------------------- GLX_EXT_visual_rating ------------------------- */ + +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 + +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D + +#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating) + +#endif /* GLX_EXT_visual_rating */ + +/* -------------------------- GLX_INTEL_swap_event ------------------------- */ + +#ifndef GLX_INTEL_swap_event +#define GLX_INTEL_swap_event 1 + +#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180 +#define GLX_COPY_COMPLETE_INTEL 0x8181 +#define GLX_FLIP_COMPLETE_INTEL 0x8182 +#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000 + +#define GLXEW_INTEL_swap_event GLXEW_GET_VAR(__GLXEW_INTEL_swap_event) + +#endif /* GLX_INTEL_swap_event */ + +/* -------------------------- GLX_MESA_agp_offset -------------------------- */ + +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 + +typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer); + +#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA) + +#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset) + +#endif /* GLX_MESA_agp_offset */ + +/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */ + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 + +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height); + +#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA) + +#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer) + +#endif /* GLX_MESA_copy_sub_buffer */ + +/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */ + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 + +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); + +#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA) + +#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap) + +#endif /* GLX_MESA_pixmap_colormap */ + +/* ------------------------ GLX_MESA_release_buffers ----------------------- */ + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 + +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d); + +#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA) + +#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers) + +#endif /* GLX_MESA_release_buffers */ + +/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */ + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 + +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 + +typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode); + +#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA) + +#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode) + +#endif /* GLX_MESA_set_3dfx_mode */ + +/* ------------------------- GLX_MESA_swap_control ------------------------- */ + +#ifndef GLX_MESA_swap_control +#define GLX_MESA_swap_control 1 + +typedef int ( * PFNGLXGETSWAPINTERVALMESAPROC) (void); +typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval); + +#define glXGetSwapIntervalMESA GLXEW_GET_FUN(__glewXGetSwapIntervalMESA) +#define glXSwapIntervalMESA GLXEW_GET_FUN(__glewXSwapIntervalMESA) + +#define GLXEW_MESA_swap_control GLXEW_GET_VAR(__GLXEW_MESA_swap_control) + +#endif /* GLX_MESA_swap_control */ + +/* --------------------------- GLX_NV_copy_image --------------------------- */ + +#ifndef GLX_NV_copy_image +#define GLX_NV_copy_image 1 + +typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define glXCopyImageSubDataNV GLXEW_GET_FUN(__glewXCopyImageSubDataNV) + +#define GLXEW_NV_copy_image GLXEW_GET_VAR(__GLXEW_NV_copy_image) + +#endif /* GLX_NV_copy_image */ + +/* -------------------------- GLX_NV_float_buffer -------------------------- */ + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 + +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 + +#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer) + +#endif /* GLX_NV_float_buffer */ + +/* ---------------------- GLX_NV_multisample_coverage ---------------------- */ + +#ifndef GLX_NV_multisample_coverage +#define GLX_NV_multisample_coverage 1 + +#define GLX_COLOR_SAMPLES_NV 0x20B3 +#define GLX_COVERAGE_SAMPLES_NV 100001 + +#define GLXEW_NV_multisample_coverage GLXEW_GET_VAR(__GLXEW_NV_multisample_coverage) + +#endif /* GLX_NV_multisample_coverage */ + +/* -------------------------- GLX_NV_present_video ------------------------- */ + +#ifndef GLX_NV_present_video +#define GLX_NV_present_video 1 + +#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 + +typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); +typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements); + +#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV) +#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV) + +#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video) + +#endif /* GLX_NV_present_video */ + +/* --------------------------- GLX_NV_swap_group --------------------------- */ + +#ifndef GLX_NV_swap_group +#define GLX_NV_swap_group 1 + +typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier); +typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group); +typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count); +typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); +typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); +typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen); + +#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV) +#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV) +#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV) +#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV) +#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV) +#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV) + +#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group) + +#endif /* GLX_NV_swap_group */ + +/* ----------------------- GLX_NV_vertex_array_range ----------------------- */ + +#ifndef GLX_NV_vertex_array_range +#define GLX_NV_vertex_array_range 1 + +typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer); + +#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV) +#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV) + +#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range) + +#endif /* GLX_NV_vertex_array_range */ + +/* -------------------------- GLX_NV_video_capture ------------------------- */ + +#ifndef GLX_NV_video_capture +#define GLX_NV_video_capture 1 + +#define GLX_DEVICE_ID_NV 0x20CD +#define GLX_UNIQUE_ID_NV 0x20CE +#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF + +typedef XID GLXVideoCaptureDeviceNV; + +typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (Display* dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device); +typedef GLXVideoCaptureDeviceNV * ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (Display* dpy, int screen, int *nelements); +typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); +typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value); +typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); + +#define glXBindVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXBindVideoCaptureDeviceNV) +#define glXEnumerateVideoCaptureDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoCaptureDevicesNV) +#define glXLockVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXLockVideoCaptureDeviceNV) +#define glXQueryVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXQueryVideoCaptureDeviceNV) +#define glXReleaseVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoCaptureDeviceNV) + +#define GLXEW_NV_video_capture GLXEW_GET_VAR(__GLXEW_NV_video_capture) + +#endif /* GLX_NV_video_capture */ + +/* -------------------------- GLX_NV_video_output -------------------------- */ + +#ifndef GLX_NV_video_output +#define GLX_NV_video_output 1 + +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC + +typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); +typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); +typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice); +typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf); +typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); + +#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV) +#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV) +#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV) +#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV) +#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV) +#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV) + +#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output) + +#endif /* GLX_NV_video_output */ + +/* -------------------------- GLX_OML_swap_method -------------------------- */ + +#ifndef GLX_OML_swap_method +#define GLX_OML_swap_method 1 + +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 + +#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method) + +#endif /* GLX_OML_swap_method */ + +/* -------------------------- GLX_OML_sync_control ------------------------- */ + +#ifndef GLX_OML_sync_control +#define GLX_OML_sync_control 1 + +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator); +typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc); + +#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML) +#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML) +#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML) +#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML) +#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML) + +#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control) + +#endif /* GLX_OML_sync_control */ + +/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */ + +#ifndef GLX_SGIS_blended_overlay +#define GLX_SGIS_blended_overlay 1 + +#define GLX_BLENDED_RGBA_SGIS 0x8025 + +#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay) + +#endif /* GLX_SGIS_blended_overlay */ + +/* -------------------------- GLX_SGIS_color_range ------------------------- */ + +#ifndef GLX_SGIS_color_range +#define GLX_SGIS_color_range 1 + +#define GLX_MIN_RED_SGIS 0 +#define GLX_MAX_GREEN_SGIS 0 +#define GLX_MIN_BLUE_SGIS 0 +#define GLX_MAX_ALPHA_SGIS 0 +#define GLX_MIN_GREEN_SGIS 0 +#define GLX_MIN_ALPHA_SGIS 0 +#define GLX_MAX_RED_SGIS 0 +#define GLX_EXTENDED_RANGE_SGIS 0 +#define GLX_MAX_BLUE_SGIS 0 + +#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range) + +#endif /* GLX_SGIS_color_range */ + +/* -------------------------- GLX_SGIS_multisample ------------------------- */ + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 + +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 + +#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample) + +#endif /* GLX_SGIS_multisample */ + +/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */ + +#ifndef GLX_SGIS_shared_multisample +#define GLX_SGIS_shared_multisample 1 + +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 + +#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample) + +#endif /* GLX_SGIS_shared_multisample */ + +/* --------------------------- GLX_SGIX_fbconfig --------------------------- */ + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 + +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_SCREEN_EXT 0x800C +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 + +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; + +typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap); +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config); + +#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX) +#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX) +#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX) +#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX) +#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX) +#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX) + +#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig) + +#endif /* GLX_SGIX_fbconfig */ + +/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */ + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 + +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int networkId; +} GLXHyperpipeNetworkSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int XOrigin; + int YOrigin; + int maxHeight; + int maxWidth; +} GLXPipeRectLimits; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int channel; + unsigned int participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int srcXOrigin; + int srcYOrigin; + int srcWidth; + int srcHeight; + int destXOrigin; + int destYOrigin; + int destWidth; + int destHeight; +} GLXPipeRect; + +typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList); +typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes); +typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes); + +#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX) +#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX) +#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX) +#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX) +#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX) +#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX) +#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX) +#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX) + +#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe) + +#endif /* GLX_SGIX_hyperpipe */ + +/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */ + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 + +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 + +typedef XID GLXPbufferSGIX; +typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX; + +typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask); +typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask); + +#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX) +#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX) +#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX) +#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX) +#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX) + +#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer) + +#endif /* GLX_SGIX_pbuffer */ + +/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */ + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 + +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); + +#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX) +#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX) + +#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier) + +#endif /* GLX_SGIX_swap_barrier */ + +/* -------------------------- GLX_SGIX_swap_group -------------------------- */ + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 + +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); + +#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX) + +#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group) + +#endif /* GLX_SGIX_swap_group */ + +/* ------------------------- GLX_SGIX_video_resize ------------------------- */ + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 + +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 + +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); + +#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX) +#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX) +#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX) +#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX) +#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX) + +#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize) + +#endif /* GLX_SGIX_video_resize */ + +/* ---------------------- GLX_SGIX_visual_select_group --------------------- */ + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 + +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 + +#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group) + +#endif /* GLX_SGIX_visual_select_group */ + +/* ---------------------------- GLX_SGI_cushion ---------------------------- */ + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 + +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion); + +#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI) + +#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion) + +#endif /* GLX_SGI_cushion */ + +/* ----------------------- GLX_SGI_make_current_read ----------------------- */ + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 + +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + +#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI) +#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI) + +#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read) + +#endif /* GLX_SGI_make_current_read */ + +/* -------------------------- GLX_SGI_swap_control ------------------------- */ + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 + +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); + +#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI) + +#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control) + +#endif /* GLX_SGI_swap_control */ + +/* --------------------------- GLX_SGI_video_sync -------------------------- */ + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 + +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int* count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count); + +#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI) +#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI) + +#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync) + +#endif /* GLX_SGI_video_sync */ + +/* --------------------- GLX_SUN_get_transparent_index --------------------- */ + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 + +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex); + +#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN) + +#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index) + +#endif /* GLX_SUN_get_transparent_index */ + +/* -------------------------- GLX_SUN_video_resize ------------------------- */ + +#ifndef GLX_SUN_video_resize +#define GLX_SUN_video_resize 1 + +#define GLX_VIDEO_RESIZE_SUN 0x8171 +#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD + +typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor); +typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor); + +#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN) +#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN) + +#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize) + +#endif /* GLX_SUN_video_resize */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define GLXEW_EXPORT +#else +#define GLXEW_EXPORT extern +#endif /* GLEW_MX */ + +extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; + +extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; +extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; +extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; +extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; +extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow; +extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; +extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; +extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; +extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; +extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; +extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; +extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; +extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; +extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; +extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext; +extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; +extern PFNGLXSELECTEVENTPROC __glewXSelectEvent; + +extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; + +extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; +extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; +extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; + +extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; +extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; +extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; +extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; + +extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT; + +extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; +extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; + +extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; + +extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; + +extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; + +extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; + +extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; + +extern PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA; +extern PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA; + +extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; + +extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; +extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; + +extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; +extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; +extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; +extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; +extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; +extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; + +extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; +extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; + +extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV; +extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV; +extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV; +extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV; +extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV; + +extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; +extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; +extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; +extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; +extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; +extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; + +extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; +extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; +extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; +extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; +extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; + +extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; +extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; +extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; +extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; +extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; +extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; + +extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; +extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; +extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; +extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; +extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; +extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; + +extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; +extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; +extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; +extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; +extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; + +extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; +extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; + +extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; + +extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; +extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; +extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; +extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; +extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; + +extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI; + +extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; +extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; + +extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; + +extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; +extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; + +extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; + +extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; +extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; + +#if defined(GLEW_MX) +struct GLXEWContextStruct +{ +#endif /* GLEW_MX */ + +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4; +GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample; +GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness; +GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; +GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address; +GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample; +GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object; +GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; +GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture; +GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile; +GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; +GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context; +GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker; +GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating; +GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event; +GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset; +GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; +GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; +GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers; +GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; +GLXEW_EXPORT GLboolean __GLXEW_MESA_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image; +GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer; +GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage; +GLXEW_EXPORT GLboolean __GLXEW_NV_present_video; +GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_output; +GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method; +GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; +GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion; +GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read; +GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync; +GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; +GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; + +#ifdef GLEW_MX +}; /* GLXEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------ */ + +#ifdef GLEW_MX + +typedef struct GLXEWContextStruct GLXEWContext; +extern GLenum glxewContextInit (GLXEWContext* ctx); +extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name); + +#define glxewInit() glxewContextInit(glxewGetContext()) +#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x) + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x)) +#define GLXEW_GET_FUN(x) x + +#else /* GLEW_MX */ + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLXEW_GET_FUN(x) x + +extern GLboolean glxewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +extern GLboolean glxewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#endif /* __glxew_h__ */ diff --git a/Code/Physics/Glut/GL/glxext.h b/Code/Physics/Glut/GL/glxext.h new file mode 100644 index 00000000..b3de958d --- /dev/null +++ b/Code/Physics/Glut/GL/glxext.h @@ -0,0 +1,546 @@ +#ifndef __glxext_h_ +#define __glxext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#else +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +#define GLX_GLXEXT_VERSION 2 + +#ifndef GLX_VERSION_1_3 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#endif + +#ifndef GLX_EXT_visual_info +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 +#endif + +#ifndef GLX_SGI_swap_control +#endif + +#ifndef GLX_SGI_video_sync +#endif + +#ifndef GLX_SGI_make_current_read +#endif + +#ifndef GLX_SGIX_video_source +#endif + +#ifndef GLX_EXT_visual_rating +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +/* reuse GLX_NONE_EXT */ +#endif + +#ifndef GLX_EXT_import_context +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 +/* reuse GLX_SCREEN_EXT */ +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#endif + +#ifndef GLX_SGI_cushion +#endif + +#ifndef GLX_SGIX_video_resize +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 +#endif + +#ifndef GLX_SGIX_dmbuffer +#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 +#endif + +#ifndef GLX_SGIX_swap_group +#endif + +#ifndef GLX_SGIX_swap_barrier +#endif + +#ifndef GLX_SGIS_blended_overlay +#define GLX_BLENDED_RGBA_SGIS 0x8025 +#endif + +#ifndef GLX_SGIS_shared_multisample +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 +#endif + +#ifndef GLX_SUN_get_transparent_index +#endif + +#ifndef GLX_3DFX_multisample +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 +#endif + +#ifndef GLX_MESA_copy_sub_buffer +#endif + +#ifndef GLX_MESA_pixmap_colormap +#endif + +#ifndef GLX_MESA_release_buffers +#endif + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 +#endif + + +/*************************************************************/ + +#ifndef GLX_ARB_get_proc_address +typedef void (*__GLXextFuncPtr)(); +#endif + +#ifndef GLX_SGIX_video_source +typedef XID GLXVideoSourceSGIX; +#endif + +#ifndef GLX_SGIX_fbconfig +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +#endif + +#ifndef GLX_SGIX_pbuffer +typedef XID GLXPbufferSGIX; +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came for SendEvent request */ + Display *display; /* display the event was read from */ + GLXDrawable drawable; /* i.d. of Drawable */ + int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ + int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ + unsigned int mask; /* mask indicating which buffers are affected*/ + int x, y; + int width, height; + int count; /* if nonzero, at least this many more */ +} GLXBufferClobberEventSGIX; +#endif + +#ifdef GL_NV_vertex_array_range +#ifndef PFNGLXALLOCATEMEMORYNVPROC +#ifdef GLX_GLXEXT_PROTOTYPES +extern void *glXAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); +#endif +typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei, GLfloat, GLfloat, GLfloat); +#endif +#ifndef PFNGLXFREEMEMORYNVPROC +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXFreeMemoryNV (void *); +#endif +typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *); +#endif +#endif + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXFBConfig * glXGetFBConfigs (Display *, int, int *); +extern GLXFBConfig * glXChooseFBConfig (Display *, int, const int *, int *); +extern int glXGetFBConfigAttrib (Display *, GLXFBConfig, int, int *); +extern XVisualInfo * glXGetVisualFromFBConfig (Display *, GLXFBConfig); +extern GLXWindow glXCreateWindow (Display *, GLXFBConfig, Window, const int *); +extern void glXDestroyWindow (Display *, GLXWindow); +extern GLXPixmap glXCreatePixmap (Display *, GLXFBConfig, Pixmap, const int *); +extern void glXDestroyPixmap (Display *, GLXPixmap); +extern GLXPbuffer glXCreatePbuffer (Display *, GLXFBConfig, const int *); +extern void glXDestroyPbuffer (Display *, GLXPbuffer); +extern void glXQueryDrawable (Display *, GLXDrawable, int, unsigned int *); +extern GLXContext glXCreateNewContext (Display *, GLXFBConfig, int, GLXContext, Bool); +extern Bool glXMakeContextCurrent (Display *, GLXDrawable, GLXDrawable, GLXContext); +extern GLXDrawable glXGetCurrentReadDrawable (void); +extern Display * glXGetCurrentDisplay (void); +extern int glXQueryContext (Display *, GLXContext, int, int *); +extern void glXSelectEvent (Display *, GLXDrawable, unsigned long); +extern void glXGetSelectedEvent (Display *, GLXDrawable, unsigned long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXFBConfig * ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef Display * ( * PFNGLXGETCURRENTDISPLAYPROC) (void); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +#endif + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); +#endif + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 +#endif + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 +#endif + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXSwapIntervalSGI (int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); +#endif + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXGetVideoSyncSGI (unsigned int *); +extern int glXWaitVideoSyncSGI (int, int, unsigned int *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count); +#endif + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXMakeCurrentReadSGI (Display *, GLXDrawable, GLXDrawable, GLXContext); +extern GLXDrawable glXGetCurrentReadDrawableSGI (void); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +#endif + +#ifdef _VL_H +#ifndef GLX_SGIX_video_source +#define GLX_SGIX_video_source 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (Display *, int, VLServer, VLPath, int, VLNode); +extern void glXDestroyGLXVideoSourceSGIX (Display *, GLXVideoSourceSGIX); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXVideoSourceSGIX ( * PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); +typedef void ( * PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (Display *dpy, GLXVideoSourceSGIX glxvideosource); +#endif + +#endif /* _VL_H */ +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 +#endif + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Display * glXGetCurrentDisplayEXT (void); +extern int glXQueryContextInfoEXT (Display *, GLXContext, int, int *); +extern GLXContextID glXGetContextIDEXT (GLXContext); +extern GLXContext glXImportContextEXT (Display *, GLXContextID); +extern void glXFreeContextEXT (Display *, GLXContext); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Display * ( * PFNGLXGETCURRENTDISPLAYEXTPROC) (void); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display *dpy, GLXContext context, int attribute, int *value); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display *dpy, GLXContextID contextID); +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display *dpy, GLXContext context); +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXGetFBConfigAttribSGIX (Display *, GLXFBConfigSGIX, int, int *); +extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (Display *, int, int *, int *); +extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (Display *, GLXFBConfigSGIX, Pixmap); +extern GLXContext glXCreateContextWithConfigSGIX (Display *, GLXFBConfigSGIX, int, GLXContext, Bool); +extern XVisualInfo * glXGetVisualFromFBConfigSGIX (Display *, GLXFBConfigSGIX); +extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (Display *, XVisualInfo *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); +typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display *dpy, XVisualInfo *vis); +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); +extern void glXDestroyGLXPbufferSGIX (Display *, GLXPbufferSGIX); +extern int glXQueryGLXPbufferSGIX (Display *, GLXPbufferSGIX, int, unsigned int *); +extern void glXSelectEventSGIX (Display *, GLXDrawable, unsigned long); +extern void glXGetSelectedEventSGIX (Display *, GLXDrawable, unsigned long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXPbufferSGIX ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf); +typedef int ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long mask); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long *mask); +#endif + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXCushionSGI (Display *, Window, float); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display *dpy, Window window, float cushion); +#endif + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXBindChannelToWindowSGIX (Display *, int, int, Window); +extern int glXChannelRectSGIX (Display *, int, int, int, int, int, int); +extern int glXQueryChannelRectSGIX (Display *, int, int, int *, int *, int *, int *); +extern int glXQueryChannelDeltasSGIX (Display *, int, int, int *, int *, int *, int *); +extern int glXChannelRectSyncSGIX (Display *, int, int, GLenum); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display *display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display *display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display *display, int screen, int channel, GLenum synctype); +#endif + +#ifdef _DM_BUFFER_H_ +#ifndef GLX_SGIX_dmbuffer +#define GLX_SGIX_dmbuffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXAssociateDMPbufferSGIX (Display *, GLXPbufferSGIX, DMparams *, DMbuffer); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); +#endif + +#endif /* _DM_BUFFER_H_ */ +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); +#endif + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXBindSwapBarrierSGIX (Display *, GLXDrawable, int); +extern Bool glXQueryMaxSwapBarriersSGIX (Display *, int, int *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); +#endif + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Status glXGetTransparentIndexSUN (Display *, Window, Window, long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display *dpy, Window overlay, Window underlay, long *pTransparentIndex); +#endif + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXCopySubBufferMESA (Display *, GLXDrawable, int, int, int, int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); +#endif + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXPixmap glXCreateGLXPixmapMESA (Display *, XVisualInfo *, Pixmap, Colormap); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); +#endif + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXReleaseBuffersMESA (Display *, GLXDrawable); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display *dpy, GLXDrawable drawable); +#endif + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXSet3DfxModeMESA (int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXSET3DFXMODEMESAPROC) (int mode); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Code/Physics/Glut/GL/wglew.h b/Code/Physics/Glut/GL/wglew.h new file mode 100644 index 00000000..05f054fc --- /dev/null +++ b/Code/Physics/Glut/GL/wglew.h @@ -0,0 +1,1363 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __wglew_h__ +#define __wglew_h__ +#define __WGLEW_H__ + +#ifdef __wglext_h_ +#error wglext.h included before wglew.h +#endif + +#define __wglext_h_ + +#if !defined(WINAPI) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +#include +# undef WIN32_LEAN_AND_MEAN +#endif + +/* + * GLEW_STATIC needs to be set when using the static version. + * GLEW_BUILD is set when building the DLL version. + */ +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------- WGL_3DFX_multisample ------------------------- */ + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 + +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 + +#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample) + +#endif /* WGL_3DFX_multisample */ + +/* ------------------------- WGL_3DL_stereo_control ------------------------ */ + +#ifndef WGL_3DL_stereo_control +#define WGL_3DL_stereo_control 1 + +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 + +typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); + +#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL) + +#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control) + +#endif /* WGL_3DL_stereo_control */ + +/* ------------------------ WGL_AMD_gpu_association ------------------------ */ + +#ifndef WGL_AMD_gpu_association +#define WGL_AMD_gpu_association 1 + +#define WGL_GPU_VENDOR_AMD 0x1F00 +#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 +#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define WGL_GPU_RAM_AMD 0x21A3 +#define WGL_GPU_CLOCK_AMD 0x21A4 +#define WGL_GPU_NUM_PIPES_AMD 0x21A5 +#define WGL_GPU_NUM_SIMD_AMD 0x21A6 +#define WGL_GPU_NUM_RB_AMD 0x21A7 +#define WGL_GPU_NUM_SPI_AMD 0x21A8 + +typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int* attribList); +typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); +typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT* ids); +typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void* data); +typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); + +#define wglBlitContextFramebufferAMD WGLEW_GET_FUN(__wglewBlitContextFramebufferAMD) +#define wglCreateAssociatedContextAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAMD) +#define wglCreateAssociatedContextAttribsAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAttribsAMD) +#define wglDeleteAssociatedContextAMD WGLEW_GET_FUN(__wglewDeleteAssociatedContextAMD) +#define wglGetContextGPUIDAMD WGLEW_GET_FUN(__wglewGetContextGPUIDAMD) +#define wglGetCurrentAssociatedContextAMD WGLEW_GET_FUN(__wglewGetCurrentAssociatedContextAMD) +#define wglGetGPUIDsAMD WGLEW_GET_FUN(__wglewGetGPUIDsAMD) +#define wglGetGPUInfoAMD WGLEW_GET_FUN(__wglewGetGPUInfoAMD) +#define wglMakeAssociatedContextCurrentAMD WGLEW_GET_FUN(__wglewMakeAssociatedContextCurrentAMD) + +#define WGLEW_AMD_gpu_association WGLEW_GET_VAR(__WGLEW_AMD_gpu_association) + +#endif /* WGL_AMD_gpu_association */ + +/* ------------------------- WGL_ARB_buffer_region ------------------------- */ + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 + +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 + +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); + +#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB) +#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB) +#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB) +#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB) + +#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region) + +#endif /* WGL_ARB_buffer_region */ + +/* ------------------------- WGL_ARB_create_context ------------------------ */ + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 + +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); + +#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB) + +#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context) + +#endif /* WGL_ARB_create_context */ + +/* --------------------- WGL_ARB_create_context_profile -------------------- */ + +#ifndef WGL_ARB_create_context_profile +#define WGL_ARB_create_context_profile 1 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define WGLEW_ARB_create_context_profile WGLEW_GET_VAR(__WGLEW_ARB_create_context_profile) + +#endif /* WGL_ARB_create_context_profile */ + +/* ------------------- WGL_ARB_create_context_robustness ------------------- */ + +#ifndef WGL_ARB_create_context_robustness +#define WGL_ARB_create_context_robustness 1 + +#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 + +#define WGLEW_ARB_create_context_robustness WGLEW_GET_VAR(__WGLEW_ARB_create_context_robustness) + +#endif /* WGL_ARB_create_context_robustness */ + +/* ----------------------- WGL_ARB_extensions_string ----------------------- */ + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); + +#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB) + +#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string) + +#endif /* WGL_ARB_extensions_string */ + +/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_ARB_framebuffer_sRGB +#define WGL_ARB_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 + +#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB) + +#endif /* WGL_ARB_framebuffer_sRGB */ + +/* ----------------------- WGL_ARB_make_current_read ----------------------- */ + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB) +#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB) + +#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read) + +#endif /* WGL_ARB_make_current_read */ + +/* -------------------------- WGL_ARB_multisample -------------------------- */ + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 + +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + +#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample) + +#endif /* WGL_ARB_multisample */ + +/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */ + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 + +DECLARE_HANDLE(HPBUFFERARB); + +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); + +#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB) +#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB) +#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB) +#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB) +#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB) + +#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer) + +#endif /* WGL_ARB_pbuffer */ + +/* -------------------------- WGL_ARB_pixel_format ------------------------- */ + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues); + +#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB) +#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB) +#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB) + +#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format) + +#endif /* WGL_ARB_pixel_format */ + +/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */ + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 + +#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float) + +#endif /* WGL_ARB_pixel_format_float */ + +/* ------------------------- WGL_ARB_render_texture ------------------------ */ + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 + +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 + +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList); + +#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB) +#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB) +#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB) + +#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture) + +#endif /* WGL_ARB_render_texture */ + +/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */ + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#define GL_RGBA_FLOAT_MODE_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 + +#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float) + +#endif /* WGL_ATI_pixel_format_float */ + +/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */ + +#ifndef WGL_ATI_render_texture_rectangle +#define WGL_ATI_render_texture_rectangle 1 + +#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5 + +#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle) + +#endif /* WGL_ATI_render_texture_rectangle */ + +/* ------------------- WGL_EXT_create_context_es2_profile ------------------ */ + +#ifndef WGL_EXT_create_context_es2_profile +#define WGL_EXT_create_context_es2_profile 1 + +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#define WGLEW_EXT_create_context_es2_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es2_profile) + +#endif /* WGL_EXT_create_context_es2_profile */ + +/* -------------------------- WGL_EXT_depth_float -------------------------- */ + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 + +#define WGL_DEPTH_FLOAT_EXT 0x2040 + +#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float) + +#endif /* WGL_EXT_depth_float */ + +/* ---------------------- WGL_EXT_display_color_table ---------------------- */ + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 + +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length); + +#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT) +#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT) + +#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table) + +#endif /* WGL_EXT_display_color_table */ + +/* ----------------------- WGL_EXT_extensions_string ----------------------- */ + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); + +#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT) + +#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string) + +#endif /* WGL_EXT_extensions_string */ + +/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 + +#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB) + +#endif /* WGL_EXT_framebuffer_sRGB */ + +/* ----------------------- WGL_EXT_make_current_read ----------------------- */ + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT) +#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT) + +#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read) + +#endif /* WGL_EXT_make_current_read */ + +/* -------------------------- WGL_EXT_multisample -------------------------- */ + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 + +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 + +#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample) + +#endif /* WGL_EXT_multisample */ + +/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */ + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 + +DECLARE_HANDLE(HPBUFFEREXT); + +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); + +#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT) +#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT) +#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT) +#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT) +#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT) + +#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer) + +#endif /* WGL_EXT_pbuffer */ + +/* -------------------------- WGL_EXT_pixel_format ------------------------- */ + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues); + +#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT) +#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT) +#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT) + +#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format) + +#endif /* WGL_EXT_pixel_format */ + +/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */ + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 + +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 + +#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float) + +#endif /* WGL_EXT_pixel_format_packed_float */ + +/* -------------------------- WGL_EXT_swap_control ------------------------- */ + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 + +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); + +#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT) +#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT) + +#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control) + +#endif /* WGL_EXT_swap_control */ + +/* --------------------- WGL_I3D_digital_video_control --------------------- */ + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 + +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 + +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D) + +#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control) + +#endif /* WGL_I3D_digital_video_control */ + +/* ----------------------------- WGL_I3D_gamma ----------------------------- */ + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 + +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F + +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D) +#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D) +#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D) +#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D) + +#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma) + +#endif /* WGL_I3D_gamma */ + +/* ---------------------------- WGL_I3D_genlock ---------------------------- */ + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 + +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C + +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay); + +#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D) +#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D) +#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D) +#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D) +#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D) +#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D) +#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D) +#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D) +#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D) +#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D) +#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D) + +#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock) + +#endif /* WGL_I3D_genlock */ + +/* -------------------------- WGL_I3D_image_buffer ------------------------- */ + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 + +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 + +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count); +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count); + +#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D) +#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D) +#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D) +#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D) + +#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer) + +#endif /* WGL_I3D_image_buffer */ + +/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */ + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 + +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag); + +#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D) +#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D) +#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D) + +#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock) + +#endif /* WGL_I3D_swap_frame_lock */ + +/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */ + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 + +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); + +#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D) +#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D) +#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D) + +#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage) + +#endif /* WGL_I3D_swap_frame_usage */ + +/* --------------------------- WGL_NV_DX_interop --------------------------- */ + +#ifndef WGL_NV_DX_interop +#define WGL_NV_DX_interop 1 + +#define WGL_ACCESS_READ_ONLY_NV 0x0000 +#define WGL_ACCESS_READ_WRITE_NV 0x0001 +#define WGL_ACCESS_WRITE_DISCARD_NV 0x0002 + +typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); +typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); +typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); +typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice); +typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); +typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle); +typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); +typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); + +#define wglDXCloseDeviceNV WGLEW_GET_FUN(__wglewDXCloseDeviceNV) +#define wglDXLockObjectsNV WGLEW_GET_FUN(__wglewDXLockObjectsNV) +#define wglDXObjectAccessNV WGLEW_GET_FUN(__wglewDXObjectAccessNV) +#define wglDXOpenDeviceNV WGLEW_GET_FUN(__wglewDXOpenDeviceNV) +#define wglDXRegisterObjectNV WGLEW_GET_FUN(__wglewDXRegisterObjectNV) +#define wglDXSetResourceShareHandleNV WGLEW_GET_FUN(__wglewDXSetResourceShareHandleNV) +#define wglDXUnlockObjectsNV WGLEW_GET_FUN(__wglewDXUnlockObjectsNV) +#define wglDXUnregisterObjectNV WGLEW_GET_FUN(__wglewDXUnregisterObjectNV) + +#define WGLEW_NV_DX_interop WGLEW_GET_VAR(__WGLEW_NV_DX_interop) + +#endif /* WGL_NV_DX_interop */ + +/* --------------------------- WGL_NV_copy_image --------------------------- */ + +#ifndef WGL_NV_copy_image +#define WGL_NV_copy_image 1 + +typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define wglCopyImageSubDataNV WGLEW_GET_FUN(__wglewCopyImageSubDataNV) + +#define WGLEW_NV_copy_image WGLEW_GET_VAR(__WGLEW_NV_copy_image) + +#endif /* WGL_NV_copy_image */ + +/* -------------------------- WGL_NV_float_buffer -------------------------- */ + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 + +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 + +#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer) + +#endif /* WGL_NV_float_buffer */ + +/* -------------------------- WGL_NV_gpu_affinity -------------------------- */ + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 + +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 + +DECLARE_HANDLE(HGPUNV); +typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +} GPU_DEVICE, *PGPU_DEVICE; + +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); + +#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV) +#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV) +#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV) +#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV) +#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV) + +#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity) + +#endif /* WGL_NV_gpu_affinity */ + +/* ---------------------- WGL_NV_multisample_coverage ---------------------- */ + +#ifndef WGL_NV_multisample_coverage +#define WGL_NV_multisample_coverage 1 + +#define WGL_COVERAGE_SAMPLES_NV 0x2042 +#define WGL_COLOR_SAMPLES_NV 0x20B9 + +#define WGLEW_NV_multisample_coverage WGLEW_GET_VAR(__WGLEW_NV_multisample_coverage) + +#endif /* WGL_NV_multisample_coverage */ + +/* -------------------------- WGL_NV_present_video ------------------------- */ + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 + +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 + +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList); +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue); + +#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV) +#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV) +#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV) + +#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video) + +#endif /* WGL_NV_present_video */ + +/* ---------------------- WGL_NV_render_depth_texture ---------------------- */ + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 + +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 + +#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture) + +#endif /* WGL_NV_render_depth_texture */ + +/* -------------------- WGL_NV_render_texture_rectangle -------------------- */ + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 + +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 + +#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle) + +#endif /* WGL_NV_render_texture_rectangle */ + +/* --------------------------- WGL_NV_swap_group --------------------------- */ + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 + +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group, GLuint *barrier); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); + +#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV) +#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV) +#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV) +#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV) +#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV) +#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV) + +#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group) + +#endif /* WGL_NV_swap_group */ + +/* ----------------------- WGL_NV_vertex_array_range ----------------------- */ + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 + +typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); + +#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV) +#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV) + +#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range) + +#endif /* WGL_NV_vertex_array_range */ + +/* -------------------------- WGL_NV_video_capture ------------------------- */ + +#ifndef WGL_NV_video_capture +#define WGL_NV_video_capture 1 + +#define WGL_UNIQUE_ID_NV 0x20CE +#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF + +DECLARE_HANDLE(HVIDEOINPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); +typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); + +#define wglBindVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewBindVideoCaptureDeviceNV) +#define wglEnumerateVideoCaptureDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoCaptureDevicesNV) +#define wglLockVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewLockVideoCaptureDeviceNV) +#define wglQueryVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewQueryVideoCaptureDeviceNV) +#define wglReleaseVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoCaptureDeviceNV) + +#define WGLEW_NV_video_capture WGLEW_GET_VAR(__WGLEW_NV_video_capture) + +#endif /* WGL_NV_video_capture */ + +/* -------------------------- WGL_NV_video_output -------------------------- */ + +#ifndef WGL_NV_video_output +#define WGL_NV_video_output 1 + +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC + +DECLARE_HANDLE(HPVIDEODEV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock); + +#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV) +#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV) +#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV) +#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV) +#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV) +#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV) + +#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output) + +#endif /* WGL_NV_video_output */ + +/* -------------------------- WGL_OML_sync_control ------------------------- */ + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 + +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator); +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc); + +#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML) +#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML) +#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML) +#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML) +#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML) + +#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control) + +#endif /* WGL_OML_sync_control */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define WGLEW_EXPORT +#else +#define WGLEW_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#ifdef GLEW_MX +struct WGLEWContextStruct +{ +#endif /* GLEW_MX */ + +WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; + +WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD; +WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD; +WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD; +WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD; +WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD; +WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD; +WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD; +WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD; +WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD; + +WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; +WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; +WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; +WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; + +WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; + +WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; +WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; +WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; +WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; + +WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; +WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; +WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; + +WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; + +WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; +WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; +WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; +WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; + +WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; +WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; + +WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; +WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; + +WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; +WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; + +WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; +WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; +WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; +WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; +WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; + +WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; +WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; +WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; +WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; + +WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; +WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; +WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; + +WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; +WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; +WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; + +WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV; +WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV; +WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV; +WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV; +WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV; +WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV; +WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV; +WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; + +WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; + +WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; +WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; +WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; +WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; +WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; + +WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; +WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; + +WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; +WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; +WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; +WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; +WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; +WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; + +WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; +WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV; +WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; +WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; +WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; +WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; + +WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; +WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; +WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; +WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; +WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; +WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; +WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample; +WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control; +WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association; +WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness; +WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture; +WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile; +WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table; +WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma; +WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; +WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop; +WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image; +WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer; +WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity; +WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage; +WGLEW_EXPORT GLboolean __WGLEW_NV_present_video; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group; +WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_output; +WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; + +#ifdef GLEW_MX +}; /* WGLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX + +typedef struct WGLEWContextStruct WGLEWContext; +GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx); +GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name); + +#define wglewInit() wglewContextInit(wglewGetContext()) +#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x) + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x)) +#define WGLEW_GET_FUN(x) wglewGetContext()->x + +#else /* GLEW_MX */ + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define WGLEW_GET_FUN(x) x + +GLEWAPI GLboolean wglewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean wglewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#undef GLEWAPI + +#endif /* __wglew_h__ */ diff --git a/Code/Physics/Glut/GL/wglext.h b/Code/Physics/Glut/GL/wglext.h new file mode 100644 index 00000000..8c6192c2 --- /dev/null +++ b/Code/Physics/Glut/GL/wglext.h @@ -0,0 +1,466 @@ +#ifndef __wglext_h_ +#define __wglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + +/*************************************************************/ + +/* Header file version number */ +#define WGL_WGLEXT_VERSION 1 + +#ifndef WGL_ARB_buffer_region +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#endif + +#ifndef WGL_ARB_extensions_string +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#endif + +#ifndef WGL_EXT_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +#ifndef WGL_I3D_unknown_genlock_extension_name +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#endif + +#ifndef WGL_I3D_unknown_gamma_extension_name +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#endif + +#ifndef WGL_I3D_unknown_digital_video_cursor_extension_name +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#endif + + +/*************************************************************/ + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif +#ifndef WGL_EXT_pbuffer +DECLARE_HANDLE(HPBUFFEREXT); +#endif + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); +extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); +extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); +extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#endif + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringARB (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCARB (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); +extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); +extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); +extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); +extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); +extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); +extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#endif + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +#endif + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); +extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); +extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); +extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglSwapIntervalEXT (int); +extern int WINAPI wglGetSwapIntervalEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +#endif + +#ifndef WGL_WGL_EXT_depth_float +#define WGL_WGL_EXT_depth_float 1 +#endif + +#ifndef WGL_WGL_3DFX_multisample +#define WGL_WGL_3DFX_multisample 1 +#endif + +#ifndef WGL_WGL_EXT_multisample +#define WGL_WGL_EXT_multisample 1 +#endif + +/* added by Cass -- but this should already be in here! */ +#ifndef WGL_NV_allocate_memory +#define WGL_NV_allocate_memory 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern void * wglAllocateMemoryNV(int size, float readfreq, float writefreq, float priority); +extern void wglFreeMemoryNV(void * pointer); +#endif +typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); +typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#endif + +/* WGL_ARB_render_texture */ +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList); +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Code/Physics/Glut/btGlutInclude.h b/Code/Physics/Glut/btGlutInclude.h new file mode 100644 index 00000000..d79cb565 --- /dev/null +++ b/Code/Physics/Glut/btGlutInclude.h @@ -0,0 +1,43 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_GLUT_INCLUDE_H +#define BT_GLUT_INCLUDE_H + + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#include +#endif //_WINDOWS +#endif //APPLE + +#endif //BT_GLUT_INCLUDE_H diff --git a/Code/Physics/LinearMath/CMakeFiles/generate.stamp b/Code/Physics/LinearMath/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/LinearMath/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend b/Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..eca1700c --- /dev/null +++ b/Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt diff --git a/Code/Physics/LinearMath/INSTALL.vcxproj b/Code/Physics/LinearMath/INSTALL.vcxproj new file mode 100644 index 00000000..30c2d9d0 --- /dev/null +++ b/Code/Physics/LinearMath/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {0A758B62-DE3C-493C-985D-39E48A384A7C} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + false + + + + + F5149B3B-C2B1-4522-9FFD-121CED456BD3 + + + + + + \ No newline at end of file diff --git a/Code/Physics/LinearMath/LinearMath.vcxproj b/Code/Physics/LinearMath/LinearMath.vcxproj new file mode 100644 index 00000000..efa93177 --- /dev/null +++ b/Code/Physics/LinearMath/LinearMath.vcxproj @@ -0,0 +1,303 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {22C0C4D8-6C43-406A-9CDB-76A4F800971A} + Win32Proj + Win32 + LinearMath + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(SolutionDir)Physics\Debug\ + LinearMath.dir\Debug\ + LinearMath_Debug + .lib + $(SolutionDir)Physics\Release + LinearMath.dir\Release\ + LinearMath + .lib + C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\MinSizeRel\ + LinearMath.dir\MinSizeRel\ + LinearMath_MinsizeRel + .lib + C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\RelWithDebInfo\ + LinearMath.dir\RelWithDebInfo\ + LinearMath_RelWithDebugInfo + .lib + + + + $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreadedDLL + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + + + C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Physics/LinearMath/LinearMath.vcxproj.user b/Code/Physics/LinearMath/LinearMath.vcxproj.user new file mode 100644 index 00000000..a375ae35 --- /dev/null +++ b/Code/Physics/LinearMath/LinearMath.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Code/Physics/LinearMath/cmake_install.cmake b/Code/Physics/LinearMath/cmake_install.cmake new file mode 100644 index 00000000..c82b699b --- /dev/null +++ b/Code/Physics/LinearMath/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/src/Bullet-C-Api.h b/Code/Physics/src/Bullet-C-Api.h new file mode 100644 index 00000000..f27a17d5 --- /dev/null +++ b/Code/Physics/src/Bullet-C-Api.h @@ -0,0 +1,176 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* + Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's. + Work in progress, functionality will be added on demand. + + If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h" +*/ + +#ifndef BULLET_C_API_H +#define BULLET_C_API_H + +#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifdef BT_USE_DOUBLE_PRECISION +typedef double plReal; +#else +typedef float plReal; +#endif + +typedef plReal plVector3[3]; +typedef plReal plQuaternion[4]; + +#ifdef __cplusplus +extern "C" { +#endif + +/** Particular physics SDK (C-API) */ + PL_DECLARE_HANDLE(plPhysicsSdkHandle); + +/** Dynamics world, belonging to some physics SDK (C-API)*/ + PL_DECLARE_HANDLE(plDynamicsWorldHandle); + +/** Rigid Body that can be part of a Dynamics World (C-API)*/ + PL_DECLARE_HANDLE(plRigidBodyHandle); + +/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/ + PL_DECLARE_HANDLE(plCollisionShapeHandle); + +/** Constraint for Rigid Bodies (C-API)*/ + PL_DECLARE_HANDLE(plConstraintHandle); + +/** Triangle Mesh interface (C-API)*/ + PL_DECLARE_HANDLE(plMeshInterfaceHandle); + +/** Broadphase Scene/Proxy Handles (C-API)*/ + PL_DECLARE_HANDLE(plCollisionBroadphaseHandle); + PL_DECLARE_HANDLE(plBroadphaseProxyHandle); + PL_DECLARE_HANDLE(plCollisionWorldHandle); + +/** + Create and Delete a Physics SDK +*/ + + extern plPhysicsSdkHandle plNewBulletSdk(void); //this could be also another sdk, like ODE, PhysX etc. + extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk); + +/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */ + + typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2); + + extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback); + + extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp); + + extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + + extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle); + + extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + +/* todo: add pair cache support with queries like add/remove/find pair */ + + extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk); + +/* todo: add/remove objects */ + + +/* Dynamics World */ + + extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk); + + extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world); + + extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep); + + extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + +/* Rigid Body */ + + extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ); + + extern void plDeleteRigidBody(plRigidBodyHandle body); + + +/* Collision Shape definition */ + + extern plCollisionShapeHandle plNewSphereShape(plReal radius); + extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z); + extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCompoundShape(void); + extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn); + + extern void plDeleteShape(plCollisionShapeHandle shape); + + /* Convex Meshes */ + extern plCollisionShapeHandle plNewConvexHullShape(void); + extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z); +/* Concave static triangle meshes */ + extern plMeshInterfaceHandle plNewMeshInterface(void); + extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); + extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling); + +/* SOLID has Response Callback/Table/Management */ +/* PhysX has Triggers, User Callbacks and filtering */ +/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */ + +/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */ +/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */ + + /* get world transform */ + extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + extern void plGetPosition(plRigidBodyHandle object,plVector3 position); + extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation); + + /* set world transform (position/orientation) */ + extern void plSetPosition(plRigidBodyHandle object, const plVector3 position); + extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation); + extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient); + extern void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + + typedef struct plRayCastResult { + plRigidBodyHandle m_body; + plCollisionShapeHandle m_shape; + plVector3 m_positionWorld; + plVector3 m_normalWorld; + } plRayCastResult; + + extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res); + + /* Sweep API */ + + /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */ + + /* Continuous Collision Detection API */ + + // needed for source/blender/blenkernel/intern/collision.c + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); + +#ifdef __cplusplus +} +#endif + + +#endif //BULLET_C_API_H + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp new file mode 100644 index 00000000..77763305 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -0,0 +1,37 @@ + +//Bullet Continuous Collision Detection and Physics Library +//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + + +// +// btAxisSweep3 +// +// Copyright (c) 2006 Simon Hobbs +// +// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +#include "btAxisSweep3.h" + + +btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator) +{ + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 32767); + +} + + +bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator) +{ + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 2147483647); +} diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h new file mode 100644 index 00000000..cd6e1a89 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -0,0 +1,1051 @@ +//Bullet Continuous Collision Detection and Physics Library +//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +// +// btAxisSweep3.h +// +// Copyright (c) 2006 Simon Hobbs +// +// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#ifndef BT_AXIS_SWEEP_3_H +#define BT_AXIS_SWEEP_3_H + +#include "LinearMath/btVector3.h" +#include "btOverlappingPairCache.h" +#include "btBroadphaseInterface.h" +#include "btBroadphaseProxy.h" +#include "btOverlappingPairCallback.h" +#include "btDbvtBroadphase.h" + +//#define DEBUG_BROADPHASE 1 +#define USE_OVERLAP_TEST_ON_REMOVES 1 + +/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. +/// It uses quantized integers to represent the begin and end points for each of the 3 axis. +/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. +template +class btAxisSweep3Internal : public btBroadphaseInterface +{ +protected: + + BP_FP_INT_TYPE m_bpHandleMask; + BP_FP_INT_TYPE m_handleSentinel; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + class Edge + { + public: + BP_FP_INT_TYPE m_pos; // low bit is min/max + BP_FP_INT_TYPE m_handle; + + BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);} + }; + +public: + class Handle : public btBroadphaseProxy + { + public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + // indexes into the edge arrays + BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 +// BP_FP_INT_TYPE m_uniqueId; + btBroadphaseProxy* m_dbvtProxy;//for faster raycast + //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject + + SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry + + +protected: + btVector3 m_worldAabbMin; // overall system bounds + btVector3 m_worldAabbMax; // overall system bounds + + btVector3 m_quantize; // scaling factor for quantization + + BP_FP_INT_TYPE m_numHandles; // number of active handles + BP_FP_INT_TYPE m_maxHandles; // max number of handles + Handle* m_pHandles; // handles pool + + BP_FP_INT_TYPE m_firstFreeHandle; // free handles list + + Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) + void* m_pEdgesRawPtr[3]; + + btOverlappingPairCache* m_pairCache; + + ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. + btOverlappingPairCallback* m_userPairCallback; + + bool m_ownsPairCache; + + int m_invalidPair; + + ///additional dynamic aabb structure, used to accelerate ray cast queries. + ///can be disabled using a optional argument in the constructor + btDbvtBroadphase* m_raycastAccelerator; + btOverlappingPairCache* m_nullPairCache; + + + // allocation/deallocation + BP_FP_INT_TYPE allocHandle(); + void freeHandle(BP_FP_INT_TYPE handle); + + + bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1); + +#ifdef DEBUG_BROADPHASE + void debugPrintAxis(int axis,bool checkCardinality=true); +#endif //DEBUG_BROADPHASE + + //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); + //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); + + + + void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + +public: + + btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false); + + virtual ~btAxisSweep3Internal(); + + BP_FP_INT_TYPE getNumHandles() const + { + return m_numHandles; + } + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); + void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + + virtual void resetPool(btDispatcher* dispatcher); + + void processAllOverlappingPairs(btOverlapCallback* callback); + + //Broadphase Interface + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + + + void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const; + ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result + void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) + { + m_userPairCallback = pairCallback; + } + const btOverlappingPairCallback* getOverlappingPairUserCallback() const + { + return m_userPairCallback; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_worldAabbMin; + aabbMax = m_worldAabbMax; + } + + virtual void printStats() + { +/* printf("btAxisSweep3.h\n"); + printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(), + m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ()); + */ + + } + +}; + +//////////////////////////////////////////////////////////////////// + + + + +#ifdef DEBUG_BROADPHASE +#include + +template +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +{ + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + btAssert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + +template +btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); + + Handle* handle = getHandle(handleId); + + if (m_raycastAccelerator) + { + btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0); + handle->m_dbvtProxy = rayProxy; + } + return handle; +} + + + +template +void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + if (m_raycastAccelerator) + m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher); + removeHandle(static_cast(handle->m_uniqueId), dispatcher); +} + +template +void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + handle->m_aabbMin = aabbMin; + handle->m_aabbMax = aabbMax; + updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher); + if (m_raycastAccelerator) + m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher); + +} + +template +void btAxisSweep3Internal::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_raycastAccelerator) + { + m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax); + } else + { + //choose axis? + BP_FP_INT_TYPE axis = 0; + //for each proxy + for (BP_FP_INT_TYPE i=1;i +void btAxisSweep3Internal::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) +{ + if (m_raycastAccelerator) + { + m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback); + } else + { + //choose axis? + BP_FP_INT_TYPE axis = 0; + //for each proxy + for (BP_FP_INT_TYPE i=1;im_aabbMin,handle->m_aabbMax)) + { + callback.process(handle); + } + } + } + } +} + + + +template +void btAxisSweep3Internal::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + Handle* pHandle = static_cast(proxy); + aabbMin = pHandle->m_aabbMin; + aabbMax = pHandle->m_aabbMax; +} + + +template +void btAxisSweep3Internal::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + Handle* pHandle = static_cast(proxy); + + unsigned short vecInMin[3]; + unsigned short vecInMax[3]; + + vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ; + vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ; + vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ; + vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ; + vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ; + vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ; + + aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ())); + aabbMin += m_worldAabbMin; + + aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ())); + aabbMax += m_worldAabbMin; +} + + + + +template +btAxisSweep3Internal::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator) +:m_bpHandleMask(handleMask), +m_handleSentinel(handleSentinel), +m_pairCache(pairCache), +m_userPairCallback(0), +m_ownsPairCache(false), +m_invalidPair(0), +m_raycastAccelerator(0) +{ + BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle + + if (!m_pairCache) + { + void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16); + m_pairCache = new(ptr) btHashedOverlappingPairCache(); + m_ownsPairCache = true; + } + + if (!disableRaycastAccelerator) + { + m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache(); + m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache); + m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs + } + + //btAssert(bounds.HasVolume()); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = m_handleSentinel; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer, using btAlignedAlloc, and put all handles on free list + m_pHandles = new Handle[maxHandles]; + + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + { + m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); + m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2]; + } + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = m_handleSentinel; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +template +btAxisSweep3Internal::~btAxisSweep3Internal() +{ + if (m_raycastAccelerator) + { + m_nullPairCache->~btOverlappingPairCache(); + btAlignedFree(m_nullPairCache); + m_raycastAccelerator->~btDbvtBroadphase(); + btAlignedFree (m_raycastAccelerator); + } + + for (int i = 2; i >= 0; i--) + { + btAlignedFree(m_pEdgesRawPtr[i]); + } + delete [] m_pHandles; + + if (m_ownsPairCache) + { + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + +template +void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const +{ +#ifdef OLD_CLAMPING_METHOD + ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax] + ///see http://code.google.com/p/bullet/issues/detail?id=87 + btVector3 clampedPoint(point); + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); +#else + btVector3 v = (point - m_worldAabbMin) * m_quantize; + out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax); + out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax); + out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax); +#endif //OLD_CLAMPING_METHOD +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() +{ + btAssert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +template +void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) +{ + btAssert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + + + Handle* pHandle = getHandle(handle); + + pHandle->m_uniqueId = static_cast(handle); + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + pHandle->m_multiSapParentProxy = multiSapProxy; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2); + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = static_cast(limit - 1); + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); + sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); + sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); + sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); + sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); + sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); + + + return handle; +} + + +template +void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + ///@todo: compare performance + if (!m_pairCache->hasDeferredRemoval()) + { + m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); + } + + // compute current limit of edge arrays + int limit = static_cast(m_numHandles * 2); + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = m_handleSentinel; + + sortMaxUp(axis,max,dispatcher,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = m_handleSentinel; + + + sortMinUp(axis,i,dispatcher,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = m_handleSentinel; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +template +void btAxisSweep3Internal::resetPool(btDispatcher* /*dispatcher*/) +{ + if (m_numHandles == 0) + { + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[m_maxHandles - 1].SetNextFree(0); + } + } +} + + +extern int gOverlappingPairs; +//#include + +template +void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + + if (m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + +} + + +template +bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +template +bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || + pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] || + pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] || + pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) + { + return false; + } + return true; +} + +template +void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ +// btAssert(bounds.IsFinite()); + //btAssert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin,dispatcher,true); + + if (dmax > 0) + sortMaxUp(axis, emax,dispatcher,true); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin,dispatcher,true); + + if (dmax < 0) + sortMaxDown(axis, emax,dispatcher,true); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2)) + { + m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + } + + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + //this is done during the overlappingpairarray iteration/narrowphase collision + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + m_pairCache->addOverlappingPair(handle0,handle1); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + +} + + + +//////////////////////////////////////////////////////////////////// + + +/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. +/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. +class btAxisSweep3 : public btAxisSweep3Internal +{ +public: + + btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false); + +}; + +/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. +/// This comes at the cost of more memory per handle, and a bit slower performance. +/// It uses arrays rather then lists for storage of the 3 axis. +class bt32BitAxisSweep3 : public btAxisSweep3Internal +{ +public: + + bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false); + +}; + +#endif + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h new file mode 100644 index 00000000..f1bf0059 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -0,0 +1,82 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BROADPHASE_INTERFACE_H +#define BT_BROADPHASE_INTERFACE_H + + + +struct btDispatcherInfo; +class btDispatcher; +#include "btBroadphaseProxy.h" + +class btOverlappingPairCache; + + + +struct btBroadphaseAabbCallback +{ + virtual ~btBroadphaseAabbCallback() {} + virtual bool process(const btBroadphaseProxy* proxy) = 0; +}; + + +struct btBroadphaseRayCallback : public btBroadphaseAabbCallback +{ + ///added some cached data to accelerate ray-AABB tests + btVector3 m_rayDirectionInverse; + unsigned int m_signs[3]; + btScalar m_lambda_max; + + virtual ~btBroadphaseRayCallback() {} +}; + +#include "LinearMath/btVector3.h" + +///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. +///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase. +///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class. +class btBroadphaseInterface +{ +public: + virtual ~btBroadphaseInterface() {} + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0; + + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0; + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; + + virtual btOverlappingPairCache* getOverlappingPairCache()=0; + virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; }; + + virtual void printStats() = 0; + +}; + +#endif //BT_BROADPHASE_INTERFACE_H diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp new file mode 100644 index 00000000..f4d7341f --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp @@ -0,0 +1,17 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBroadphaseProxy.h" + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h new file mode 100644 index 00000000..bb58b828 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -0,0 +1,270 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BROADPHASE_PROXY_H +#define BT_BROADPHASE_PROXY_H + +#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" + + +/// btDispatcher uses these types +/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave +/// to facilitate type checking +/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code +enum BroadphaseNativeTypes +{ + // polyhedral convex shapes + BOX_SHAPE_PROXYTYPE, + TRIANGLE_SHAPE_PROXYTYPE, + TETRAHEDRAL_SHAPE_PROXYTYPE, + CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, + CONVEX_HULL_SHAPE_PROXYTYPE, + CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE, + CUSTOM_POLYHEDRAL_SHAPE_TYPE, +//implicit convex shapes +IMPLICIT_CONVEX_SHAPES_START_HERE, + SPHERE_SHAPE_PROXYTYPE, + MULTI_SPHERE_SHAPE_PROXYTYPE, + CAPSULE_SHAPE_PROXYTYPE, + CONE_SHAPE_PROXYTYPE, + CONVEX_SHAPE_PROXYTYPE, + CYLINDER_SHAPE_PROXYTYPE, + UNIFORM_SCALING_SHAPE_PROXYTYPE, + MINKOWSKI_SUM_SHAPE_PROXYTYPE, + MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, + BOX_2D_SHAPE_PROXYTYPE, + CONVEX_2D_SHAPE_PROXYTYPE, + CUSTOM_CONVEX_SHAPE_TYPE, +//concave shapes +CONCAVE_SHAPES_START_HERE, + //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! + TRIANGLE_MESH_SHAPE_PROXYTYPE, + SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE, + ///used for demo integration FAST/Swift collision library and Bullet + FAST_CONCAVE_MESH_PROXYTYPE, + //terrain + TERRAIN_SHAPE_PROXYTYPE, +///Used for GIMPACT Trimesh integration + GIMPACT_SHAPE_PROXYTYPE, +///Multimaterial mesh + MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, + + EMPTY_SHAPE_PROXYTYPE, + STATIC_PLANE_PROXYTYPE, + CUSTOM_CONCAVE_SHAPE_TYPE, +CONCAVE_SHAPES_END_HERE, + + COMPOUND_SHAPE_PROXYTYPE, + + SOFTBODY_SHAPE_PROXYTYPE, + HFFLUID_SHAPE_PROXYTYPE, + HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE, + INVALID_SHAPE_PROXYTYPE, + + MAX_BROADPHASE_COLLISION_TYPES + +}; + + +///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. +///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody. +ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy +{ + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + ///optional filtering to cull potential collisions + enum CollisionFilterGroups + { + DefaultFilter = 1, + StaticFilter = 2, + KinematicFilter = 4, + DebrisFilter = 8, + SensorTrigger = 16, + CharacterFilter = 32, + AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger + }; + + //Usually the client btCollisionObject or Rigidbody class + void* m_clientObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + void* m_multiSapParentProxy; + int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + SIMD_FORCE_INLINE int getUid() const + { + return m_uniqueId; + } + + //used for memory pools + btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) + { + } + + btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) + :m_clientObject(userPtr), + m_collisionFilterGroup(collisionFilterGroup), + m_collisionFilterMask(collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax) + { + m_multiSapParentProxy = multiSapParentProxy; + } + + + + static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) + { + return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); + } + + static SIMD_FORCE_INLINE bool isConvex(int proxyType) + { + return (proxyType < CONCAVE_SHAPES_START_HERE); + } + + static SIMD_FORCE_INLINE bool isNonMoving(int proxyType) + { + return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE)); + } + + static SIMD_FORCE_INLINE bool isConcave(int proxyType) + { + return ((proxyType > CONCAVE_SHAPES_START_HERE) && + (proxyType < CONCAVE_SHAPES_END_HERE)); + } + static SIMD_FORCE_INLINE bool isCompound(int proxyType) + { + return (proxyType == COMPOUND_SHAPE_PROXYTYPE); + } + + static SIMD_FORCE_INLINE bool isSoftBody(int proxyType) + { + return (proxyType == SOFTBODY_SHAPE_PROXYTYPE); + } + + static SIMD_FORCE_INLINE bool isInfinite(int proxyType) + { + return (proxyType == STATIC_PLANE_PROXYTYPE); + } + + static SIMD_FORCE_INLINE bool isConvex2d(int proxyType) + { + return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE); + } + + +} +; + +class btCollisionAlgorithm; + +struct btBroadphaseProxy; + + + +///The btBroadphasePair class contains a pair of aabb-overlapping objects. +///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes. +ATTRIBUTE_ALIGNED16(struct) btBroadphasePair +{ + btBroadphasePair () + : + m_pProxy0(0), + m_pProxy1(0), + m_algorithm(0), + m_internalInfo1(0) + { + } + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + btBroadphasePair(const btBroadphasePair& other) + : m_pProxy0(other.m_pProxy0), + m_pProxy1(other.m_pProxy1), + m_algorithm(other.m_algorithm), + m_internalInfo1(other.m_internalInfo1) + { + } + btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1) + { + + //keep them sorted, so the std::set operations work + if (proxy0.m_uniqueId < proxy1.m_uniqueId) + { + m_pProxy0 = &proxy0; + m_pProxy1 = &proxy1; + } + else + { + m_pProxy0 = &proxy1; + m_pProxy1 = &proxy0; + } + + m_algorithm = 0; + m_internalInfo1 = 0; + + } + + btBroadphaseProxy* m_pProxy0; + btBroadphaseProxy* m_pProxy1; + + mutable btCollisionAlgorithm* m_algorithm; + union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version. + +}; + +/* +//comparison for set operation, see Solid DT_Encounter +SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) +{ + return a.m_pProxy0 < b.m_pProxy0 || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); +} +*/ + + + +class btBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const + { + const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1; + const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1; + const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1; + const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1; + + return uidA0 > uidB0 || + (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); + } +}; + + +SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b) +{ + return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1); +} + + +#endif //BT_BROADPHASE_PROXY_H + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp new file mode 100644 index 00000000..c95d1be0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -0,0 +1,23 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btCollisionAlgorithm.h" +#include "btDispatcher.h" + +btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) +{ + m_dispatcher = ci.m_dispatcher1; +} + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h new file mode 100644 index 00000000..40565623 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_ALGORITHM_H +#define BT_COLLISION_ALGORITHM_H + +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" + +struct btBroadphaseProxy; +class btDispatcher; +class btManifoldResult; +class btCollisionObject; +struct btCollisionObjectWrapper; +struct btDispatcherInfo; +class btPersistentManifold; + +typedef btAlignedObjectArray btManifoldArray; + +struct btCollisionAlgorithmConstructionInfo +{ + btCollisionAlgorithmConstructionInfo() + :m_dispatcher1(0), + m_manifold(0) + { + } + btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) + :m_dispatcher1(dispatcher) + { + (void)temp; + } + + btDispatcher* m_dispatcher1; + btPersistentManifold* m_manifold; + +// int getDispatcherId(); + +}; + + +///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher. +///It is persistent over frames +class btCollisionAlgorithm +{ + +protected: + + btDispatcher* m_dispatcher; + +protected: +// int getDispatcherId(); + +public: + + btCollisionAlgorithm() {}; + + btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); + + virtual ~btCollisionAlgorithm() {}; + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0; +}; + + +#endif //BT_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.cpp new file mode 100644 index 00000000..95443af5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -0,0 +1,1295 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvt implementation by Nathanael Presson + +#include "btDbvt.h" + +// +typedef btAlignedObjectArray tNodeArray; +typedef btAlignedObjectArray tConstNodeArray; + +// +struct btDbvtNodeEnumerator : btDbvt::ICollide +{ + tConstNodeArray nodes; + void Process(const btDbvtNode* n) { nodes.push_back(n); } +}; + +// +static DBVT_INLINE int indexof(const btDbvtNode* node) +{ + return(node->parent->childs[1]==node); +} + +// +static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a, + const btDbvtVolume& b) +{ +#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE) + ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]); + btDbvtVolume& res=*(btDbvtVolume*)locals; +#else + btDbvtVolume res; +#endif + Merge(a,b,res); + return(res); +} + +// volume+edge lengths +static DBVT_INLINE btScalar size(const btDbvtVolume& a) +{ + const btVector3 edges=a.Lengths(); + return( edges.x()*edges.y()*edges.z()+ + edges.x()+edges.y()+edges.z()); +} + +// +static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth) +{ + if(node->isinternal()) + { + getmaxdepth(node->childs[0],depth+1,maxdepth); + getmaxdepth(node->childs[1],depth+1,maxdepth); + } else maxdepth=btMax(maxdepth,depth); +} + +// +static DBVT_INLINE void deletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ + btAlignedFree(pdbvt->m_free); + pdbvt->m_free=node; +} + +// +static void recursedeletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ + if(!node->isleaf()) + { + recursedeletenode(pdbvt,node->childs[0]); + recursedeletenode(pdbvt,node->childs[1]); + } + if(node==pdbvt->m_root) pdbvt->m_root=0; + deletenode(pdbvt,node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + void* data) +{ + btDbvtNode* node; + if(pdbvt->m_free) + { node=pdbvt->m_free;pdbvt->m_free=0; } + else + { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); } + node->parent = parent; + node->data = data; + node->childs[1] = 0; + return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume, + void* data) +{ + btDbvtNode* node=createnode(pdbvt,parent,data); + node->volume=volume; + return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume0, + const btDbvtVolume& volume1, + void* data) +{ + btDbvtNode* node=createnode(pdbvt,parent,data); + Merge(volume0,volume1,node->volume); + return(node); +} + +// +static void insertleaf( btDbvt* pdbvt, + btDbvtNode* root, + btDbvtNode* leaf) +{ + if(!pdbvt->m_root) + { + pdbvt->m_root = leaf; + leaf->parent = 0; + } + else + { + if(!root->isleaf()) + { + do { + root=root->childs[Select( leaf->volume, + root->childs[0]->volume, + root->childs[1]->volume)]; + } while(!root->isleaf()); + } + btDbvtNode* prev=root->parent; + btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0); + if(prev) + { + prev->childs[indexof(root)] = node; + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + do { + if(!prev->volume.Contain(node->volume)) + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + else + break; + node=prev; + } while(0!=(prev=node->parent)); + } + else + { + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + pdbvt->m_root = node; + } + } +} + +// +static btDbvtNode* removeleaf( btDbvt* pdbvt, + btDbvtNode* leaf) +{ + if(leaf==pdbvt->m_root) + { + pdbvt->m_root=0; + return(0); + } + else + { + btDbvtNode* parent=leaf->parent; + btDbvtNode* prev=parent->parent; + btDbvtNode* sibling=parent->childs[1-indexof(leaf)]; + if(prev) + { + prev->childs[indexof(parent)]=sibling; + sibling->parent=prev; + deletenode(pdbvt,parent); + while(prev) + { + const btDbvtVolume pb=prev->volume; + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + if(NotEqual(pb,prev->volume)) + { + prev=prev->parent; + } else break; + } + return(prev?prev:pdbvt->m_root); + } + else + { + pdbvt->m_root=sibling; + sibling->parent=0; + deletenode(pdbvt,parent); + return(pdbvt->m_root); + } + } +} + +// +static void fetchleaves(btDbvt* pdbvt, + btDbvtNode* root, + tNodeArray& leaves, + int depth=-1) +{ + if(root->isinternal()&&depth) + { + fetchleaves(pdbvt,root->childs[0],leaves,depth-1); + fetchleaves(pdbvt,root->childs[1],leaves,depth-1); + deletenode(pdbvt,root); + } + else + { + leaves.push_back(root); + } +} + +// +static void split( const tNodeArray& leaves, + tNodeArray& left, + tNodeArray& right, + const btVector3& org, + const btVector3& axis) +{ + left.resize(0); + right.resize(0); + for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) + left.push_back(leaves[i]); + else + right.push_back(leaves[i]); + } +} + +// +static btDbvtVolume bounds( const tNodeArray& leaves) +{ +#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE + ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]); + btDbvtVolume& volume=*(btDbvtVolume*)locals; + volume=leaves[0]->volume; +#else + btDbvtVolume volume=leaves[0]->volume; +#endif + for(int i=1,ni=leaves.size();ivolume,volume); + } + return(volume); +} + +// +static void bottomup( btDbvt* pdbvt, + tNodeArray& leaves) +{ + while(leaves.size()>1) + { + btScalar minsize=SIMD_INFINITY; + int minidx[2]={-1,-1}; + for(int i=0;ivolume,leaves[j]->volume)); + if(szvolume,n[1]->volume,0); + p->childs[0] = n[0]; + p->childs[1] = n[1]; + n[0]->parent = p; + n[1]->parent = p; + leaves[minidx[0]] = p; + leaves.swap(minidx[1],leaves.size()-1); + leaves.pop_back(); + } +} + +// +static btDbvtNode* topdown(btDbvt* pdbvt, + tNodeArray& leaves, + int bu_treshold) +{ + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + if(leaves.size()>1) + { + if(leaves.size()>bu_treshold) + { + const btDbvtVolume vol=bounds(leaves); + const btVector3 org=vol.Center(); + tNodeArray sets[2]; + int bestaxis=-1; + int bestmidp=leaves.size(); + int splitcount[3][2]={{0,0},{0,0},{0,0}}; + int i; + for( i=0;ivolume.Center()-org; + for(int j=0;j<3;++j) + { + ++splitcount[j][btDot(x,axis[j])>0?1:0]; + } + } + for( i=0;i<3;++i) + { + if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) + { + const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1])); + if(midp=0) + { + sets[0].reserve(splitcount[bestaxis][0]); + sets[1].reserve(splitcount[bestaxis][1]); + split(leaves,sets[0],sets[1],org,axis[bestaxis]); + } + else + { + sets[0].reserve(leaves.size()/2+1); + sets[1].reserve(leaves.size()/2); + for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold); + node->childs[1]=topdown(pdbvt,sets[1],bu_treshold); + node->childs[0]->parent=node; + node->childs[1]->parent=node; + return(node); + } + else + { + bottomup(pdbvt,leaves); + return(leaves[0]); + } + } + return(leaves[0]); +} + +// +static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r) +{ + btDbvtNode* p=n->parent; + btAssert(n->isinternal()); + if(p>n) + { + const int i=indexof(n); + const int j=1-i; + btDbvtNode* s=p->childs[j]; + btDbvtNode* q=p->parent; + btAssert(n==p->childs[i]); + if(q) q->childs[indexof(p)]=n; else r=n; + s->parent=n; + p->parent=n; + n->parent=q; + p->childs[0]=n->childs[0]; + p->childs[1]=n->childs[1]; + n->childs[0]->parent=p; + n->childs[1]->parent=p; + n->childs[i]=p; + n->childs[j]=s; + btSwap(p->volume,n->volume); + return(p); + } + return(n); +} + +#if 0 +static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) +{ + while(n&&(count--)) n=n->parent; + return(n); +} +#endif + +// +// Api +// + +// +btDbvt::btDbvt() +{ + m_root = 0; + m_free = 0; + m_lkhd = -1; + m_leaves = 0; + m_opath = 0; +} + +// +btDbvt::~btDbvt() +{ + clear(); +} + +// +void btDbvt::clear() +{ + if(m_root) + recursedeletenode(this,m_root); + btAlignedFree(m_free); + m_free=0; + m_lkhd = -1; + m_stkStack.clear(); + m_opath = 0; + +} + +// +void btDbvt::optimizeBottomUp() +{ + if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + bottomup(this,leaves); + m_root=leaves[0]; + } +} + +// +void btDbvt::optimizeTopDown(int bu_treshold) +{ + if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + m_root=topdown(this,leaves,bu_treshold); + } +} + +// +void btDbvt::optimizeIncremental(int passes) +{ + if(passes<0) passes=m_leaves; + if(m_root&&(passes>0)) + { + do { + btDbvtNode* node=m_root; + unsigned bit=0; + while(node->isinternal()) + { + node=sort(node,m_root)->childs[(m_opath>>bit)&1]; + bit=(bit+1)&(sizeof(unsigned)*8-1); + } + update(node); + ++m_opath; + } while(--passes); + } +} + +// +btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data) +{ + btDbvtNode* leaf=createnode(this,0,volume,data); + insertleaf(this,m_root,leaf); + ++m_leaves; + return(leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,int lookahead) +{ + btDbvtNode* root=removeleaf(this,leaf); + if(root) + { + if(lookahead>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } + insertleaf(this,root,leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume) +{ + btDbvtNode* root=removeleaf(this,leaf); + if(root) + { + if(m_lkhd>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } + leaf->volume=volume; + insertleaf(this,root,leaf); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin) +{ + if(leaf->volume.Contain(volume)) return(false); + volume.Expand(btVector3(margin,margin,margin)); + volume.SignedExpand(velocity); + update(leaf,volume); + return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity) +{ + if(leaf->volume.Contain(volume)) return(false); + volume.SignedExpand(velocity); + update(leaf,volume); + return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin) +{ + if(leaf->volume.Contain(volume)) return(false); + volume.Expand(btVector3(margin,margin,margin)); + update(leaf,volume); + return(true); +} + +// +void btDbvt::remove(btDbvtNode* leaf) +{ + removeleaf(this,leaf); + deletenode(this,leaf); + --m_leaves; +} + +// +void btDbvt::write(IWriter* iwriter) const +{ + btDbvtNodeEnumerator nodes; + nodes.nodes.reserve(m_leaves*2); + enumNodes(m_root,nodes); + iwriter->Prepare(m_root,nodes.nodes.size()); + for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent); + if(n->isinternal()) + { + const int c0=nodes.nodes.findLinearSearch(n->childs[0]); + const int c1=nodes.nodes.findLinearSearch(n->childs[1]); + iwriter->WriteNode(n,i,p,c0,c1); + } + else + { + iwriter->WriteLeaf(n,i,p); + } + } +} + +// +void btDbvt::clone(btDbvt& dest,IClone* iclone) const +{ + dest.clear(); + if(m_root!=0) + { + btAlignedObjectArray stack; + stack.reserve(m_leaves); + stack.push_back(sStkCLN(m_root,0)); + do { + const int i=stack.size()-1; + const sStkCLN e=stack[i]; + btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data); + stack.pop_back(); + if(e.parent!=0) + e.parent->childs[i&1]=n; + else + dest.m_root=n; + if(e.node->isinternal()) + { + stack.push_back(sStkCLN(e.node->childs[0],n)); + stack.push_back(sStkCLN(e.node->childs[1],n)); + } + else + { + iclone->CloneLeaf(n); + } + } while(stack.size()>0); + } +} + +// +int btDbvt::maxdepth(const btDbvtNode* node) +{ + int depth=0; + if(node) getmaxdepth(node,1,depth); + return(depth); +} + +// +int btDbvt::countLeaves(const btDbvtNode* node) +{ + if(node->isinternal()) + return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); + else + return(1); +} + +// +void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves) +{ + if(node->isinternal()) + { + extractLeaves(node->childs[0],leaves); + extractLeaves(node->childs[1],leaves); + } + else + { + leaves.push_back(node); + } +} + +// +#if DBVT_ENABLE_BENCHMARK + +#include +#include +#include "LinearMath/btQuickProf.h" + +/* +q6600,2.4ghz + +/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32" +/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch" +/Fo"..\..\out\release8\build\libbulletcollision\\" +/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb" +/W3 /nologo /c /Wp64 /Zi /errorReport:prompt + +Benchmarking dbvt... +World scale: 100.000000 +Extents base: 1.000000 +Extents range: 4.000000 +Leaves: 8192 +sizeof(btDbvtVolume): 32 bytes +sizeof(btDbvtNode): 44 bytes +[1] btDbvtVolume intersections: 3499 ms (-1%) +[2] btDbvtVolume merges: 1934 ms (0%) +[3] btDbvt::collideTT: 5485 ms (-21%) +[4] btDbvt::collideTT self: 2814 ms (-20%) +[5] btDbvt::collideTT xform: 7379 ms (-1%) +[6] btDbvt::collideTT xform,self: 7270 ms (-2%) +[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s) +[8] insert/remove: 2093 ms (0%),(1001983 ir/s) +[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) +[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) +[11] optimize (incremental): 2514 ms (0%),(1668000 o/s) +[12] btDbvtVolume notequal: 3659 ms (0%) +[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) +[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) +[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) +[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) +[17] btDbvtVolume select: 3419 ms (0%) +*/ + +struct btDbvtBenchmark +{ + struct NilPolicy : btDbvt::ICollide + { + NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} + void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*,btScalar depth) + { + ++m_pcount; + if(m_checksort) + { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); } + } + int m_pcount; + btScalar m_depth; + bool m_checksort; + }; + struct P14 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf,btScalar depth) + { + Node n; + n.leaf = leaf; + n.depth = depth; + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + }; + struct P15 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf) + { + Node n; + n.leaf = leaf; + n.depth = dot(leaf->volume.Center(),m_axis); + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + btVector3 m_axis; + }; + static btScalar RandUnit() + { + return(rand()/(btScalar)RAND_MAX); + } + static btVector3 RandVector3() + { + return(btVector3(RandUnit(),RandUnit(),RandUnit())); + } + static btVector3 RandVector3(btScalar cs) + { + return(RandVector3()*cs-btVector3(cs,cs,cs)/2); + } + static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) + { + return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); + } + static btTransform RandTransform(btScalar cs) + { + btTransform t; + t.setOrigin(RandVector3(cs)); + t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized()); + return(t); + } + static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt) + { + dbvt.clear(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark5_Iterations); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark6_Iterations); + for(int i=0;i rayorg; + btAlignedObjectArray raydir; + btDbvtBenchmark::NilPolicy policy; + rayorg.resize(cfgBenchmark7_Iterations); + raydir.resize(cfgBenchmark7_Iterations); + for(int i=0;i leaves; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + dbvt.extractLeaves(dbvt.m_root,leaves); + printf("[9] updates (teleport): "); + wallclock.reset(); + for(int i=0;i(leaves[rand()%cfgLeaves]), + btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale)); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time); + } + if(cfgBenchmark10_Enable) + {// Benchmark 10 + srand(380843); + btDbvt dbvt; + btAlignedObjectArray leaves; + btAlignedObjectArray vectors; + vectors.resize(cfgBenchmark10_Iterations); + for(int i=0;i(leaves[rand()%cfgLeaves]); + btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d); + dbvt.update(l,v); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time); + } + if(cfgBenchmark11_Enable) + {// Benchmark 11 + srand(380843); + btDbvt dbvt; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + printf("[11] optimize (incremental): "); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i vectors; + btDbvtBenchmark::NilPolicy policy; + vectors.resize(cfgBenchmark13_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P14 policy; + vectors.resize(cfgBenchmark14_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P15 policy; + vectors.resize(cfgBenchmark15_Iterations); + for(int i=0;i batch; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + batch.reserve(cfgBenchmark16_BatchCount); + printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + btAlignedObjectArray indices; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + indices.resize(cfgLeaves); + for(int i=0;i= 1400) +#define DBVT_USE_TEMPLATE 1 +#else +#define DBVT_USE_TEMPLATE 0 +#endif +#else +#define DBVT_USE_TEMPLATE 0 +#endif + +// Use only intrinsics instead of inline asm +#define DBVT_USE_INTRINSIC_SSE 1 + +// Using memmov for collideOCL +#define DBVT_USE_MEMMOVE 1 + +// Enable benchmarking code +#define DBVT_ENABLE_BENCHMARK 0 + +// Inlining +#define DBVT_INLINE SIMD_FORCE_INLINE + +// Specific methods implementation + +//SSE gives errors on a MSVC 7.1 +#if defined (BT_USE_SSE) //&& defined (_WIN32) +#define DBVT_SELECT_IMPL DBVT_IMPL_SSE +#define DBVT_MERGE_IMPL DBVT_IMPL_SSE +#define DBVT_INT0_IMPL DBVT_IMPL_SSE +#else +#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC +#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC +#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC +#endif + +#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_INT0_IMPL==DBVT_IMPL_SSE) +#include +#endif + +// +// Auto config and checks +// + +#if DBVT_USE_TEMPLATE +#define DBVT_VIRTUAL +#define DBVT_VIRTUAL_DTOR(a) +#define DBVT_PREFIX template +#define DBVT_IPOLICY T& policy +#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker; +#else +#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} +#define DBVT_VIRTUAL virtual +#define DBVT_PREFIX +#define DBVT_IPOLICY ICollide& policy +#define DBVT_CHECKTYPE +#endif + +#if DBVT_USE_MEMMOVE +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include +#endif + +#ifndef DBVT_USE_TEMPLATE +#error "DBVT_USE_TEMPLATE undefined" +#endif + +#ifndef DBVT_USE_MEMMOVE +#error "DBVT_USE_MEMMOVE undefined" +#endif + +#ifndef DBVT_ENABLE_BENCHMARK +#error "DBVT_ENABLE_BENCHMARK undefined" +#endif + +#ifndef DBVT_SELECT_IMPL +#error "DBVT_SELECT_IMPL undefined" +#endif + +#ifndef DBVT_MERGE_IMPL +#error "DBVT_MERGE_IMPL undefined" +#endif + +#ifndef DBVT_INT0_IMPL +#error "DBVT_INT0_IMPL undefined" +#endif + +// +// Defaults volumes +// + +/* btDbvtAabbMm */ +struct btDbvtAabbMm +{ + DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); } + DBVT_INLINE btVector3 Lengths() const { return(mx-mi); } + DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); } + DBVT_INLINE const btVector3& Mins() const { return(mi); } + DBVT_INLINE const btVector3& Maxs() const { return(mx); } + static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e); + static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); + static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); + static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); + static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); + DBVT_INLINE void Expand(const btVector3& e); + DBVT_INLINE void SignedExpand(const btVector3& e); + DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; + DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; + DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; + DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + + DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btVector3& b); + + DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + DBVT_INLINE friend int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + DBVT_INLINE friend void Merge( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + btDbvtAabbMm& r); + DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); + + DBVT_INLINE btVector3& tMins() { return(mi); } + DBVT_INLINE btVector3& tMaxs() { return(mx); } + +private: + DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; +private: + btVector3 mi,mx; +}; + +// Types +typedef btDbvtAabbMm btDbvtVolume; + +/* btDbvtNode */ +struct btDbvtNode +{ + btDbvtVolume volume; + btDbvtNode* parent; + DBVT_INLINE bool isleaf() const { return(childs[1]==0); } + DBVT_INLINE bool isinternal() const { return(!isleaf()); } + union + { + btDbvtNode* childs[2]; + void* data; + int dataAsInt; + }; +}; + +///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). +///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. +///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. +struct btDbvt +{ + /* Stack element */ + struct sStkNN + { + const btDbvtNode* a; + const btDbvtNode* b; + sStkNN() {} + sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {} + }; + struct sStkNP + { + const btDbvtNode* node; + int mask; + sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {} + }; + struct sStkNPS + { + const btDbvtNode* node; + int mask; + btScalar value; + sStkNPS() {} + sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} + }; + struct sStkCLN + { + const btDbvtNode* node; + btDbvtNode* parent; + sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {} + }; + // Policies/Interfaces + + /* ICollide */ + struct ICollide + { + DBVT_VIRTUAL_DTOR(ICollide) + DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); } + DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); } + DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); } + }; + /* IWriter */ + struct IWriter + { + virtual ~IWriter() {} + virtual void Prepare(const btDbvtNode* root,int numnodes)=0; + virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0; + virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0; + }; + /* IClone */ + struct IClone + { + virtual ~IClone() {} + virtual void CloneLeaf(btDbvtNode*) {} + }; + + // Constants + enum { + SIMPLE_STACKSIZE = 64, + DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 + }; + + // Fields + btDbvtNode* m_root; + btDbvtNode* m_free; + int m_lkhd; + int m_leaves; + unsigned m_opath; + + + btAlignedObjectArray m_stkStack; + mutable btAlignedObjectArray m_rayTestStack; + + + // Methods + btDbvt(); + ~btDbvt(); + void clear(); + bool empty() const { return(0==m_root); } + void optimizeBottomUp(); + void optimizeTopDown(int bu_treshold=128); + void optimizeIncremental(int passes); + btDbvtNode* insert(const btDbvtVolume& box,void* data); + void update(btDbvtNode* leaf,int lookahead=-1); + void update(btDbvtNode* leaf,btDbvtVolume& volume); + bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin); + bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity); + bool update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin); + void remove(btDbvtNode* leaf); + void write(IWriter* iwriter) const; + void clone(btDbvt& dest,IClone* iclone=0) const; + static int maxdepth(const btDbvtNode* node); + static int countLeaves(const btDbvtNode* node); + static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves); +#if DBVT_ENABLE_BENCHMARK + static void benchmark(); +#else + static void benchmark(){} +#endif + // DBVT_IPOLICY must support ICollide policy/interface + DBVT_PREFIX + static void enumNodes( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + static void enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); + + DBVT_PREFIX + void collideTTpersistentStack( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); +#if 0 + DBVT_PREFIX + void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY); + DBVT_PREFIX + void collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY); +#endif + + DBVT_PREFIX + void collideTV( const btDbvtNode* root, + const btDbvtVolume& volume, + DBVT_IPOLICY) const; + ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc) + ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time + DBVT_PREFIX + static void rayTest( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + DBVT_IPOLICY); + ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections + ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts + DBVT_PREFIX + void rayTestInternal( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayDirectionInverse, + unsigned int signs[3], + btScalar lambda_max, + const btVector3& aabbMin, + const btVector3& aabbMax, + DBVT_IPOLICY) const; + + DBVT_PREFIX + static void collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fullsort=true); + DBVT_PREFIX + static void collideTU( const btDbvtNode* root, + DBVT_IPOLICY); + // Helpers + static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) + { + int m=0; + while(l>1; + if(a[i[m]].value>=v) l=m+1; else h=m; + } + return(h); + } + static DBVT_INLINE int allocate( btAlignedObjectArray& ifree, + btAlignedObjectArray& stock, + const sStkNPS& value) + { + int i; + if(ifree.size()>0) + { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; } + else + { i=stock.size();stock.push_back(value); } + return(i); + } + // +private: + btDbvt(const btDbvt&) {} +}; + +// +// Inline's +// + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) +{ + btDbvtAabbMm box; + box.mi=c-e;box.mx=c+e; + return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r) +{ + return(FromCE(c,btVector3(r,r,r))); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx) +{ + btDbvtAabbMm box; + box.mi=mi;box.mx=mx; + return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n) +{ + btDbvtAabbMm box; + box.mi=box.mx=pts[0]; + for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); + if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); + if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); +} + +// +DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const +{ + return( (mi.x()<=a.mi.x())&& + (mi.y()<=a.mi.y())&& + (mi.z()<=a.mi.z())&& + (mx.x()>=a.mx.x())&& + (mx.y()>=a.mx.y())&& + (mx.z()>=a.mx.z())); +} + +// +DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const +{ + btVector3 pi,px; + switch(s) + { + case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z()); + pi=btVector3(mx.x(),mx.y(),mx.z());break; + case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z()); + pi=btVector3(mi.x(),mx.y(),mx.z());break; + case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z()); + pi=btVector3(mx.x(),mi.y(),mx.z());break; + case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z()); + pi=btVector3(mi.x(),mi.y(),mx.z());break; + case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z()); + pi=btVector3(mx.x(),mx.y(),mi.z());break; + case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z()); + pi=btVector3(mi.x(),mx.y(),mi.z());break; + case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z()); + pi=btVector3(mx.x(),mi.y(),mi.z());break; + case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z()); + pi=btVector3(mi.x(),mi.y(),mi.z());break; + } + if((btDot(n,px)+o)<0) return(-1); + if((btDot(n,pi)+o)>=0) return(+1); + return(0); +} + +// +DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const +{ + const btVector3* b[]={&mx,&mi}; + const btVector3 p( b[(signs>>0)&1]->x(), + b[(signs>>1)&1]->y(), + b[(signs>>2)&1]->z()); + return(btDot(p,v)); +} + +// +DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const +{ + for(int i=0;i<3;++i) + { + if(d[i]<0) + { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; } + else + { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; } + } +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_INT0_IMPL == DBVT_IMPL_SSE + const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), + _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); +#if defined (_WIN32) + const __int32* pu((const __int32*)&rt); +#else + const int* pu((const int*)&rt); +#endif + return((pu[0]|pu[1]|pu[2])==0); +#else + return( (a.mi.x()<=b.mx.x())&& + (a.mx.x()>=b.mi.x())&& + (a.mi.y()<=b.mx.y())&& + (a.mx.y()>=b.mi.y())&& + (a.mi.z()<=b.mx.z())&& + (a.mx.z()>=b.mi.z())); +#endif +} + + + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btVector3& b) +{ + return( (b.x()>=a.mi.x())&& + (b.y()>=a.mi.y())&& + (b.z()>=a.mi.z())&& + (b.x()<=a.mx.x())&& + (b.y()<=a.mx.y())&& + (b.z()<=a.mx.z())); +} + + + + + +////////////////////////////////////// + + +// +DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ + const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); + return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); +} + + + +// +DBVT_INLINE int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE + +#if defined (_WIN32) + static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; +#else + static ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/}; +#endif + ///@todo: the intrinsic version is 11% slower +#if DBVT_USE_INTRINSIC_SSE + + union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory + { + __m128 ssereg; + float floats[4]; + int ints[4]; + }; + + __m128 omi(_mm_load_ps(o.mi)); + omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); + __m128 ami(_mm_load_ps(a.mi)); + ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); + ami=_mm_sub_ps(ami,omi); + ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); + __m128 bmi(_mm_load_ps(b.mi)); + bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); + bmi=_mm_sub_ps(bmi,omi); + bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); + __m128 t0(_mm_movehl_ps(ami,ami)); + ami=_mm_add_ps(ami,t0); + ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); + __m128 t1(_mm_movehl_ps(bmi,bmi)); + bmi=_mm_add_ps(bmi,t1); + bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); + + btSSEUnion tmp; + tmp.ssereg = _mm_cmple_ss(bmi,ami); + return tmp.ints[0]&1; + +#else + ATTRIBUTE_ALIGNED16(__int32 r[1]); + __asm + { + mov eax,o + mov ecx,a + mov edx,b + movaps xmm0,[eax] + movaps xmm5,mask + addps xmm0,[eax+16] + movaps xmm1,[ecx] + movaps xmm2,[edx] + addps xmm1,[ecx+16] + addps xmm2,[edx+16] + subps xmm1,xmm0 + subps xmm2,xmm0 + andps xmm1,xmm5 + andps xmm2,xmm5 + movhlps xmm3,xmm1 + movhlps xmm4,xmm2 + addps xmm1,xmm3 + addps xmm2,xmm4 + pshufd xmm3,xmm1,1 + pshufd xmm4,xmm2,1 + addss xmm1,xmm3 + addss xmm2,xmm4 + cmpless xmm2,xmm1 + movss r,xmm2 + } + return(r[0]&1); +#endif +#else + return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; + } +#endif +} + +// +DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ + return( (a.mi.x()!=b.mi.x())|| + (a.mi.y()!=b.mi.y())|| + (a.mi.z()!=b.mi.z())|| + (a.mx.x()!=b.mx.x())|| + (a.mx.y()!=b.mx.y())|| + (a.mx.z()!=b.mx.z())); +} + +// +// Inline's +// + +// +DBVT_PREFIX +inline void btDbvt::enumNodes( const btDbvtNode* root, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + policy.Process(root); + if(root->isinternal()) + { + enumNodes(root->childs[0],policy); + enumNodes(root->childs[1],policy); + } +} + +// +DBVT_PREFIX +inline void btDbvt::enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root->isinternal()) + { + enumLeaves(root->childs[0],policy); + enumLeaves(root->childs[1],policy); + } + else + { + policy.Process(root); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(DOUBLE_STACKSIZE); + stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=stkStack[--depth]; + if(depth>treshold) + { + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); + } + } + else if(Intersect(p.a->volume,p.b->volume)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + + + +DBVT_PREFIX +inline void btDbvt::collideTTpersistentStack( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + + m_stkStack.resize(DOUBLE_STACKSIZE); + m_stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=m_stkStack[--depth]; + if(depth>treshold) + { + m_stkStack.resize(m_stkStack.size()*2); + treshold=m_stkStack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); + } + } + else if(Intersect(p.a->volume,p.b->volume)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +#if 0 +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root0&&root1) + { + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(DOUBLE_STACKSIZE); + stkStack[0]=sStkNN(root0,root1); + do { + sStkNN p=stkStack[--depth]; + if(Intersect(p.a->volume,p.b->volume,xform)) + { + if(depth>treshold) + { + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; + } + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY) +{ + const btTransform xform=xform0.inverse()*xform1; + collideTT(root0,root1,xform,policy); +} +#endif + +// +DBVT_PREFIX +inline void btDbvt::collideTV( const btDbvtNode* root, + const btDbvtVolume& vol, + DBVT_IPOLICY) const +{ + DBVT_CHECKTYPE + if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + btAlignedObjectArray stack; + stack.resize(0); + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) + { + if(n->isinternal()) + { + stack.push_back(n->childs[0]); + stack.push_back(n->childs[1]); + } + else + { + policy.Process(n); + } + } + } while(stack.size()>0); + } +} + +DBVT_PREFIX +inline void btDbvt::rayTestInternal( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayDirectionInverse, + unsigned int signs[3], + btScalar lambda_max, + const btVector3& aabbMin, + const btVector3& aabbMax, + DBVT_IPOLICY) const +{ + (void) rayTo; + DBVT_CHECKTYPE + if(root) + { + btVector3 resultNormal; + + int depth=1; + int treshold=DOUBLE_STACKSIZE-2; + btAlignedObjectArray& stack = m_rayTestStack; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=root; + btVector3 bounds[2]; + do + { + const btDbvtNode* node=stack[--depth]; + bounds[0] = node->volume.Mins()-aabbMax; + bounds[1] = node->volume.Maxs()-aabbMin; + btScalar tmin=1.f,lambda_min=0.f; + unsigned int result1=false; + result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); + if(result1) + { + if(node->isinternal()) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-2; + } + stack[depth++]=node->childs[0]; + stack[depth++]=node->childs[1]; + } + else + { + policy.Process(node); + } + } + } while(depth); + } +} + +// +DBVT_PREFIX +inline void btDbvt::rayTest( const btDbvtNode* root, + const btVector3& rayFrom, + const btVector3& rayTo, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + btVector3 rayDir = (rayTo-rayFrom); + rayDir.normalize (); + + ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT + btVector3 rayDirectionInverse; + rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; + + btScalar lambda_max = rayDir.dot(rayTo-rayFrom); + + btVector3 resultNormal; + + btAlignedObjectArray stack; + + int depth=1; + int treshold=DOUBLE_STACKSIZE-2; + + stack.resize(DOUBLE_STACKSIZE); + stack[0]=root; + btVector3 bounds[2]; + do { + const btDbvtNode* node=stack[--depth]; + + bounds[0] = node->volume.Mins(); + bounds[1] = node->volume.Maxs(); + + btScalar tmin=1.f,lambda_min=0.f; + unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); + +#ifdef COMPARE_BTRAY_AABB2 + btScalar param=1.f; + bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal); + btAssert(result1 == result2); +#endif //TEST_BTRAY_AABB2 + + if(result1) + { + if(node->isinternal()) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-2; + } + stack[depth++]=node->childs[0]; + stack[depth++]=node->childs[1]; + } + else + { + policy.Process(node); + } + } + } while(depth); + + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + const int inside=(1< stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(sStkNP(root,0)); + do { + sStkNP se=stack[stack.size()-1]; + bool out=false; + stack.pop_back(); + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(!out) + { + if((se.mask!=inside)&&(se.node->isinternal())) + { + stack.push_back(sStkNP(se.node->childs[0],se.mask)); + stack.push_back(sStkNP(se.node->childs[1],se.mask)); + } + else + { + if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fsort) +{ + DBVT_CHECKTYPE + if(root) + { + const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ + (sortaxis[1]>=0?2:0)+ + (sortaxis[2]>=0?4:0); + const int inside=(1< stock; + btAlignedObjectArray ifree; + btAlignedObjectArray stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stock.reserve(SIMPLE_STACKSIZE); + stack.reserve(SIMPLE_STACKSIZE); + ifree.reserve(SIMPLE_STACKSIZE); + stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); + do { + const int id=stack[stack.size()-1]; + sStkNPS se=stock[id]; + stack.pop_back();ifree.push_back(id); + if(se.mask!=inside) + { + bool out=false; + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(out) continue; + } + if(policy.Descent(se.node)) + { + if(se.node->isinternal()) + { + const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]}; + sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), + sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; + const int q=nes[0].value0)) + { + /* Insert 0 */ + j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); + stack.push_back(0); +#if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); +#else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; +#endif + stack[j]=allocate(ifree,stock,nes[q]); + /* Insert 1 */ + j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); + stack.push_back(0); +#if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); +#else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; +#endif + stack[j]=allocate(ifree,stock,nes[1-q]); + } + else + { + stack.push_back(allocate(ifree,stock,nes[q])); + stack.push_back(allocate(ifree,stock,nes[1-q])); + } + } + else + { + policy.Process(se.node,se.value); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTU( const btDbvtNode* root, + DBVT_IPOLICY) +{ + DBVT_CHECKTYPE + if(root) + { + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(policy.Descent(n)) + { + if(n->isinternal()) + { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } + else + { policy.Process(n); } + } + } while(stack.size()>0); + } +} + +// +// PP Cleanup +// + +#undef DBVT_USE_MEMMOVE +#undef DBVT_USE_TEMPLATE +#undef DBVT_VIRTUAL_DTOR +#undef DBVT_VIRTUAL +#undef DBVT_PREFIX +#undef DBVT_IPOLICY +#undef DBVT_CHECKTYPE +#undef DBVT_IMPL_GENERIC +#undef DBVT_IMPL_SSE +#undef DBVT_USE_INTRINSIC_SSE +#undef DBVT_SELECT_IMPL +#undef DBVT_MERGE_IMPL +#undef DBVT_INT0_IMPL + +#endif diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp new file mode 100644 index 00000000..75cfac64 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -0,0 +1,796 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///btDbvtBroadphase implementation by Nathanael Presson + +#include "btDbvtBroadphase.h" + +// +// Profiling +// + +#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK +#include +#endif + +#if DBVT_BP_PROFILE +struct ProfileScope +{ + __forceinline ProfileScope(btClock& clock,unsigned long& value) : + m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds()) + { + } + __forceinline ~ProfileScope() + { + (*m_value)+=m_clock->getTimeMicroseconds()-m_base; + } + btClock* m_clock; + unsigned long* m_value; + unsigned long m_base; +}; +#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_) +#else +#define SPC(_value_) +#endif + +// +// Helpers +// + +// +template +static inline void listappend(T* item,T*& list) +{ + item->links[0]=0; + item->links[1]=list; + if(list) list->links[0]=item; + list=item; +} + +// +template +static inline void listremove(T* item,T*& list) +{ + if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1]; + if(item->links[1]) item->links[1]->links[0]=item->links[0]; +} + +// +template +static inline int listcount(T* root) +{ + int n=0; + while(root) { ++n;root=root->links[1]; } + return(n); +} + +// +template +static inline void clear(T& value) +{ + static const struct ZeroDummy : T {} zerodummy; + value=zerodummy; +} + +// +// Colliders +// + +/* Tree collider */ +struct btDbvtTreeCollider : btDbvt::ICollide +{ + btDbvtBroadphase* pbp; + btDbvtProxy* proxy; + btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} + void Process(const btDbvtNode* na,const btDbvtNode* nb) + { + if(na!=nb) + { + btDbvtProxy* pa=(btDbvtProxy*)na->data; + btDbvtProxy* pb=(btDbvtProxy*)nb->data; +#if DBVT_BP_SORTPAIRS + if(pa->m_uniqueId>pb->m_uniqueId) + btSwap(pa,pb); +#endif + pbp->m_paircache->addOverlappingPair(pa,pb); + ++pbp->m_newpairs; + } + } + void Process(const btDbvtNode* n) + { + Process(n,proxy->leaf); + } +}; + +// +// btDbvtBroadphase +// + +// +btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) +{ + m_deferedcollide = false; + m_needcleanup = true; + m_releasepaircache = (paircache!=0)?false:true; + m_prediction = 0; + m_stageCurrent = 0; + m_fixedleft = 0; + m_fupdates = 1; + m_dupdates = 0; + m_cupdates = 10; + m_newpairs = 1; + m_updates_call = 0; + m_updates_done = 0; + m_updates_ratio = 0; + m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); + m_gid = 0; + m_pid = 0; + m_cid = 0; + for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } +#if DBVT_BP_PROFILE + clear(m_profiling); +#endif +} + +// +btDbvtBroadphase::~btDbvtBroadphase() +{ + if(m_releasepaircache) + { + m_paircache->~btOverlappingPairCache(); + btAlignedFree(m_paircache); + } +} + +// +btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, + const btVector3& aabbMax, + int /*shapeType*/, + void* userPtr, + short int collisionFilterGroup, + short int collisionFilterMask, + btDispatcher* /*dispatcher*/, + void* /*multiSapProxy*/) +{ + btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr, + collisionFilterGroup, + collisionFilterMask); + + btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); + + //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); + proxy->stage = m_stageCurrent; + proxy->m_uniqueId = ++m_gid; + proxy->leaf = m_sets[0].insert(aabb,proxy); + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + collider.proxy=proxy; + m_sets[0].collideTV(m_sets[0].m_root,aabb,collider); + m_sets[1].collideTV(m_sets[1].m_root,aabb,collider); + } + return(proxy); +} + +// +void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy, + btDispatcher* dispatcher) +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + if(proxy->stage==STAGECOUNT) + m_sets[1].remove(proxy->leaf); + else + m_sets[0].remove(proxy->leaf); + listremove(proxy,m_stageRoots[proxy->stage]); + m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); + btAlignedFree(proxy); + m_needcleanup=true; +} + +void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + aabbMin = proxy->m_aabbMin; + aabbMax = proxy->m_aabbMax; +} + +struct BroadphaseRayTester : btDbvt::ICollide +{ + btBroadphaseRayCallback& m_rayCallback; + BroadphaseRayTester(btBroadphaseRayCallback& orgCallback) + :m_rayCallback(orgCallback) + { + } + void Process(const btDbvtNode* leaf) + { + btDbvtProxy* proxy=(btDbvtProxy*)leaf->data; + m_rayCallback.process(proxy); + } +}; + +void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + BroadphaseRayTester callback(rayCallback); + + m_sets[0].rayTestInternal( m_sets[0].m_root, + rayFrom, + rayTo, + rayCallback.m_rayDirectionInverse, + rayCallback.m_signs, + rayCallback.m_lambda_max, + aabbMin, + aabbMax, + callback); + + m_sets[1].rayTestInternal( m_sets[1].m_root, + rayFrom, + rayTo, + rayCallback.m_rayDirectionInverse, + rayCallback.m_signs, + rayCallback.m_lambda_max, + aabbMin, + aabbMax, + callback); + +} + + +struct BroadphaseAabbTester : btDbvt::ICollide +{ + btBroadphaseAabbCallback& m_aabbCallback; + BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback) + :m_aabbCallback(orgCallback) + { + } + void Process(const btDbvtNode* leaf) + { + btDbvtProxy* proxy=(btDbvtProxy*)leaf->data; + m_aabbCallback.process(proxy); + } +}; + +void btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback) +{ + BroadphaseAabbTester callback(aabbCallback); + + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(aabbMin,aabbMax); + //process all children, that overlap with the given AABB bounds + m_sets[0].collideTV(m_sets[0].m_root,bounds,callback); + m_sets[1].collideTV(m_sets[1].m_root,bounds,callback); + +} + + + +// +void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); +#if DBVT_BP_PREVENTFALSEUPDATE + if(NotEqual(aabb,proxy->leaf->volume)) +#endif + { + bool docollide=false; + if(proxy->stage==STAGECOUNT) + {/* fixed -> dynamic set */ + m_sets[1].remove(proxy->leaf); + proxy->leaf=m_sets[0].insert(aabb,proxy); + docollide=true; + } + else + {/* dynamic set */ + ++m_updates_call; + if(Intersect(proxy->leaf->volume,aabb)) + {/* Moving */ + + const btVector3 delta=aabbMin-proxy->m_aabbMin; + btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction); + if(delta[0]<0) velocity[0]=-velocity[0]; + if(delta[1]<0) velocity[1]=-velocity[1]; + if(delta[2]<0) velocity[2]=-velocity[2]; + if ( +#ifdef DBVT_BP_MARGIN + m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN) +#else + m_sets[0].update(proxy->leaf,aabb,velocity) +#endif + ) + { + ++m_updates_done; + docollide=true; + } + } + else + {/* Teleporting */ + m_sets[0].update(proxy->leaf,aabb); + ++m_updates_done; + docollide=true; + } + } + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->m_aabbMin = aabbMin; + proxy->m_aabbMax = aabbMax; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) + { + m_needcleanup=true; + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); + } + } + } +} + + +// +void btDbvtBroadphase::setAabbForceUpdate( btBroadphaseProxy* absproxy, + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) +{ + btDbvtProxy* proxy=(btDbvtProxy*)absproxy; + ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); + bool docollide=false; + if(proxy->stage==STAGECOUNT) + {/* fixed -> dynamic set */ + m_sets[1].remove(proxy->leaf); + proxy->leaf=m_sets[0].insert(aabb,proxy); + docollide=true; + } + else + {/* dynamic set */ + ++m_updates_call; + /* Teleporting */ + m_sets[0].update(proxy->leaf,aabb); + ++m_updates_done; + docollide=true; + } + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->m_aabbMin = aabbMin; + proxy->m_aabbMax = aabbMax; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) + { + m_needcleanup=true; + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider); + } + } +} + +// +void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + collide(dispatcher); +#if DBVT_BP_PROFILE + if(0==(m_pid%DBVT_BP_PROFILING_RATE)) + { + printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs()); + unsigned int total=m_profiling.m_total; + if(total<=0) total=1; + printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE); + printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE); + printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE); + printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE); + const unsigned long sum=m_profiling.m_ddcollide+ + m_profiling.m_fdcollide+ + m_profiling.m_cleanup; + printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE); + printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE)); + clear(m_profiling); + m_clock.reset(); + } +#endif + + performDeferredRemoval(dispatcher); + +} + +void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher) +{ + + if (m_paircache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + int invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;ileaf->volume,pb->leaf->volume); + + if (hasOverlap) + { + needsRemoval = false; + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_paircache->cleanOverlappingPair(pair,dispatcher); + + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + invalidPair++; + } + + } + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + overlappingPairArray.resize(overlappingPairArray.size() - invalidPair); + } +} + +// +void btDbvtBroadphase::collide(btDispatcher* dispatcher) +{ + /*printf("---------------------------------------------------------\n"); + printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves); + printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves); + printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs()); + { + int i; + for (i=0;igetNumOverlappingPairs();i++) + { + printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(), + getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid()); + } + printf("\n"); + } +*/ + + + + SPC(m_profiling.m_total); + /* optimize */ + m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); + if(m_fixedleft) + { + const int count=1+(m_sets[1].m_leaves*m_fupdates)/100; + m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); + m_fixedleft=btMax(0,m_fixedleft-count); + } + /* dynamic -> fixed set */ + m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; + btDbvtProxy* current=m_stageRoots[m_stageCurrent]; + if(current) + { + btDbvtTreeCollider collider(this); + do { + btDbvtProxy* next=current->links[1]; + listremove(current,m_stageRoots[current->stage]); + listappend(current,m_stageRoots[STAGECOUNT]); +#if DBVT_BP_ACCURATESLEEPING + m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher); + collider.proxy=current; + btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider); + btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider); +#endif + m_sets[0].remove(current->leaf); + ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax); + current->leaf = m_sets[1].insert(curAabb,current); + current->stage = STAGECOUNT; + current = next; + } while(current); + m_fixedleft=m_sets[1].m_leaves; + m_needcleanup=true; + } + /* collide dynamics */ + { + btDbvtTreeCollider collider(this); + if(m_deferedcollide) + { + SPC(m_profiling.m_fdcollide); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider); + } + if(m_deferedcollide) + { + SPC(m_profiling.m_ddcollide); + m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider); + } + } + /* clean up */ + if(m_needcleanup) + { + SPC(m_profiling.m_cleanup); + btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); + if(pairs.size()>0) + { + + int ni=btMin(pairs.size(),btMax(m_newpairs,(pairs.size()*m_cupdates)/100)); + for(int i=0;ileaf->volume,pb->leaf->volume)) + { +#if DBVT_BP_SORTPAIRS + if(pa->m_uniqueId>pb->m_uniqueId) + btSwap(pa,pb); +#endif + m_paircache->removeOverlappingPair(pa,pb,dispatcher); + --ni;--i; + } + } + if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0; + } + } + ++m_pid; + m_newpairs=1; + m_needcleanup=false; + if(m_updates_call>0) + { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; } + else + { m_updates_ratio=0; } + m_updates_done/=2; + m_updates_call/=2; +} + +// +void btDbvtBroadphase::optimize() +{ + m_sets[0].optimizeTopDown(); + m_sets[1].optimizeTopDown(); +} + +// +btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() +{ + return(m_paircache); +} + +// +const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const +{ + return(m_paircache); +} + +// +void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds; + + if(!m_sets[0].empty()) + if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume, + m_sets[1].m_root->volume,bounds); + else + bounds=m_sets[0].m_root->volume; + else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume; + else + bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0); + aabbMin=bounds.Mins(); + aabbMax=bounds.Maxs(); +} + +void btDbvtBroadphase::resetPool(btDispatcher* dispatcher) +{ + + int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves; + if (!totalObjects) + { + //reset internal dynamic tree data structures + m_sets[0].clear(); + m_sets[1].clear(); + + m_deferedcollide = false; + m_needcleanup = true; + m_stageCurrent = 0; + m_fixedleft = 0; + m_fupdates = 1; + m_dupdates = 0; + m_cupdates = 10; + m_newpairs = 1; + m_updates_call = 0; + m_updates_done = 0; + m_updates_ratio = 0; + + m_gid = 0; + m_pid = 0; + m_cid = 0; + for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } + } +} + +// +void btDbvtBroadphase::printStats() +{} + +// +#if DBVT_BP_ENABLE_BENCHMARK + +struct btBroadphaseBenchmark +{ + struct Experiment + { + const char* name; + int object_count; + int update_count; + int spawn_count; + int iterations; + btScalar speed; + btScalar amplitude; + }; + struct Object + { + btVector3 center; + btVector3 extents; + btBroadphaseProxy* proxy; + btScalar time; + void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi) + { + time += speed; + center[0] = btCos(time*(btScalar)2.17)*amplitude+ + btSin(time)*amplitude/2; + center[1] = btCos(time*(btScalar)1.38)*amplitude+ + btSin(time)*amplitude; + center[2] = btSin(time*(btScalar)0.777)*amplitude; + pbi->setAabb(proxy,center-extents,center+extents,0); + } + }; + static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); } + static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); } + static void OutputTime(const char* name,btClock& c,unsigned count=0) + { + const unsigned long us=c.getTimeMicroseconds(); + const unsigned long ms=(us+500)/1000; + const btScalar sec=us/(btScalar)(1000*1000); + if(count>0) + printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec); + else + printf("%s : %u us (%u ms)\r\n",name,us,ms); + } +}; + +void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi) +{ + static const btBroadphaseBenchmark::Experiment experiments[]= + { + {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100}, + /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100}, + {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/ + }; + static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]); + btAlignedObjectArray objects; + btClock wallclock; + /* Begin */ + for(int iexp=0;iexpcenter[0]=btBroadphaseBenchmark::UnitRand()*50; + po->center[1]=btBroadphaseBenchmark::UnitRand()*50; + po->center[2]=btBroadphaseBenchmark::UnitRand()*50; + po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2; + po->time=btBroadphaseBenchmark::UnitRand()*2000; + po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0); + objects.push_back(po); + } + btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock); + /* First update */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock); + /* Updates */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + pbi->calculateOverlappingPairs(0); + } + btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations); + /* Clean up */ + wallclock.reset(); + for(int i=0;idestroyProxy(objects[i]->proxy,0); + delete objects[i]; + } + objects.resize(0); + btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); + } + +} +#else +void btDbvtBroadphase::benchmark(btBroadphaseInterface*) +{} +#endif + +#if DBVT_BP_PROFILE +#undef SPC +#endif + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h new file mode 100644 index 00000000..18b64ad0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -0,0 +1,146 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///btDbvtBroadphase implementation by Nathanael Presson +#ifndef BT_DBVT_BROADPHASE_H +#define BT_DBVT_BROADPHASE_H + +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +// +// Compile time config +// + +#define DBVT_BP_PROFILE 0 +//#define DBVT_BP_SORTPAIRS 1 +#define DBVT_BP_PREVENTFALSEUPDATE 0 +#define DBVT_BP_ACCURATESLEEPING 0 +#define DBVT_BP_ENABLE_BENCHMARK 0 +#define DBVT_BP_MARGIN (btScalar)0.05 + +#if DBVT_BP_PROFILE +#define DBVT_BP_PROFILING_RATE 256 +#include "LinearMath/btQuickprof.h" +#endif + +// +// btDbvtProxy +// +struct btDbvtProxy : btBroadphaseProxy +{ + /* Fields */ + //btDbvtAabbMm aabb; + btDbvtNode* leaf; + btDbvtProxy* links[2]; + int stage; + /* ctor */ + btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : + btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask) + { + links[0]=links[1]=0; + } +}; + +typedef btAlignedObjectArray btDbvtProxyArray; + +///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt). +///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other. +///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3. +struct btDbvtBroadphase : btBroadphaseInterface +{ + /* Config */ + enum { + DYNAMIC_SET = 0, /* Dynamic set index */ + FIXED_SET = 1, /* Fixed set index */ + STAGECOUNT = 2 /* Number of stages */ + }; + /* Fields */ + btDbvt m_sets[2]; // Dbvt sets + btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list + btOverlappingPairCache* m_paircache; // Pair cache + btScalar m_prediction; // Velocity prediction + int m_stageCurrent; // Current stage + int m_fupdates; // % of fixed updates per frame + int m_dupdates; // % of dynamic updates per frame + int m_cupdates; // % of cleanup updates per frame + int m_newpairs; // Number of pairs created + int m_fixedleft; // Fixed optimization left + unsigned m_updates_call; // Number of updates call + unsigned m_updates_done; // Number of updates done + btScalar m_updates_ratio; // m_updates_done/m_updates_call + int m_pid; // Parse id + int m_cid; // Cleanup index + int m_gid; // Gen id + bool m_releasepaircache; // Release pair cache on delete + bool m_deferedcollide; // Defere dynamic/static collision to collide call + bool m_needcleanup; // Need to run cleanup? +#if DBVT_BP_PROFILE + btClock m_clock; + struct { + unsigned long m_total; + unsigned long m_ddcollide; + unsigned long m_fdcollide; + unsigned long m_cleanup; + unsigned long m_jobcount; + } m_profiling; +#endif + /* Methods */ + btDbvtBroadphase(btOverlappingPairCache* paircache=0); + ~btDbvtBroadphase(); + void collide(btDispatcher* dispatcher); + void optimize(); + + /* btBroadphaseInterface Implementation */ + btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)); + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + virtual btOverlappingPairCache* getOverlappingPairCache(); + virtual const btOverlappingPairCache* getOverlappingPairCache() const; + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; + virtual void printStats(); + + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + + void performDeferredRemoval(btDispatcher* dispatcher); + + void setVelocityPrediction(btScalar prediction) + { + m_prediction = prediction; + } + btScalar getVelocityPrediction() const + { + return m_prediction; + } + + ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update. + ///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase. + ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see + ///http://code.google.com/p/bullet/issues/detail?id=223 + void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/); + + static void benchmark(btBroadphaseInterface*); + + +}; + +#endif diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp new file mode 100644 index 00000000..20768225 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btDispatcher.h" + +btDispatcher::~btDispatcher() +{ + +} + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.h new file mode 100644 index 00000000..89c307d1 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DISPATCHER_H +#define BT_DISPATCHER_H +#include "LinearMath/btScalar.h" + +class btCollisionAlgorithm; +struct btBroadphaseProxy; +class btRigidBody; +class btCollisionObject; +class btOverlappingPairCache; +struct btCollisionObjectWrapper; + +class btPersistentManifold; +class btPoolAllocator; + +struct btDispatcherInfo +{ + enum DispatchFunc + { + DISPATCH_DISCRETE = 1, + DISPATCH_CONTINUOUS + }; + btDispatcherInfo() + :m_timeStep(btScalar(0.)), + m_stepCount(0), + m_dispatchFunc(DISPATCH_DISCRETE), + m_timeOfImpact(btScalar(1.)), + m_useContinuous(true), + m_debugDraw(0), + m_enableSatConvex(false), + m_enableSPU(true), + m_useEpa(true), + m_allowedCcdPenetration(btScalar(0.04)), + m_useConvexConservativeDistanceUtil(false), + m_convexConservativeDistanceThreshold(0.0f) + { + + } + btScalar m_timeStep; + int m_stepCount; + int m_dispatchFunc; + mutable btScalar m_timeOfImpact; + bool m_useContinuous; + class btIDebugDraw* m_debugDraw; + bool m_enableSatConvex; + bool m_enableSPU; + bool m_useEpa; + btScalar m_allowedCcdPenetration; + bool m_useConvexConservativeDistanceUtil; + btScalar m_convexConservativeDistanceThreshold; +}; + +///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. +///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). +class btDispatcher +{ + + +public: + virtual ~btDispatcher() ; + + virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold=0) = 0; + + virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0; + + virtual void releaseManifold(btPersistentManifold* manifold)=0; + + virtual void clearManifold(btPersistentManifold* manifold)=0; + + virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0; + + virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0; + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0; + + virtual int getNumManifolds() const = 0; + + virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; + + virtual btPersistentManifold** getInternalManifoldPointer() = 0; + + virtual btPoolAllocator* getInternalManifoldPool() = 0; + + virtual const btPoolAllocator* getInternalManifoldPool() const = 0; + + virtual void* allocateCollisionAlgorithm(int size) = 0; + + virtual void freeCollisionAlgorithm(void* ptr) = 0; + +}; + + +#endif //BT_DISPATCHER_H diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp new file mode 100644 index 00000000..81369fe9 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -0,0 +1,489 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btMultiSapBroadphase.h" + +#include "btSimpleBroadphase.h" +#include "LinearMath/btAabbUtil2.h" +#include "btQuantizedBvh.h" + +/// btSapBroadphaseArray m_sapBroadphases; + +/// btOverlappingPairCache* m_overlappingPairs; +extern int gOverlappingPairs; + +/* +class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache +{ +public: + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); + } +}; + +*/ + +btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) +:m_overlappingPairs(pairCache), +m_optimizedAabbTree(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + if (!m_overlappingPairs) + { + m_ownsPairCache = true; + void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); + m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); + } + + struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback + { + virtual ~btMultiSapOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const + { + btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; + btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; + + bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; + collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); + + return collides; + } + }; + + void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); + m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); + + m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); +// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); +// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); +} + +btMultiSapBroadphase::~btMultiSapBroadphase() +{ + if (m_ownsPairCache) + { + m_overlappingPairs->~btOverlappingPairCache(); + btAlignedFree(m_overlappingPairs); + } +} + + +void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) +{ + m_optimizedAabbTree = new btQuantizedBvh(); + m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); + QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray(); + for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + int partId = 0; + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; + nodes.push_back(node); + } + m_optimizedAabbTree->buildInternal(); +} + +btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) +{ + //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested + + void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); + btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); + m_multiSapProxies.push_back(proxy); + + ///this should deal with inserting/removal into child broadphases + setAabb(proxy,aabbMin,aabbMax,dispatcher); + return proxy; +} + +void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) +{ + ///not yet + btAssert(0); + +} + + +void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase) +{ + void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); + btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; + bridgeProxyRef->m_childProxy = childProxy; + bridgeProxyRef->m_childBroadphase = childBroadphase; + parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); +} + + +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) +{ +return +amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && +amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && +amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); +} + + + + + + +void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + aabbMin = multiProxy->m_aabbMin; + aabbMax = multiProxy->m_aabbMax; +} + +void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) +{ + for (int i=0;i + +void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + multiProxy->m_aabbMin = aabbMin; + multiProxy->m_aabbMax = aabbMax; + + +// bool fullyContained = false; +// bool alreadyInSimple = false; + + + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btMultiSapBroadphase* m_multiSap; + btMultiSapProxy* m_multiProxy; + btDispatcher* m_dispatcher; + + MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) + :m_multiSap(multiSap), + m_multiProxy(multiProxy), + m_dispatcher(dispatcher) + { + + } + + virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) + { + btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; + + int containingBroadphaseIndex = -1; + //already found? + for (int i=0;im_bridgeProxies.size();i++) + { + + if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + break; + } + } + if (containingBroadphaseIndex<0) + { + //add it + btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); + m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); + + } + } + }; + + MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); + + + + + if (m_optimizedAabbTree) + m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + + int i; + + for ( i=0;im_bridgeProxies.size();i++) + { + btVector3 worldAabbMin,worldAabbMax; + multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + if (!overlapsBroadphase) + { + //remove it now + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + + } + } + + + /* + + if (1) + { + + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + + // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + int containingBroadphaseIndex = -1; + + //if already contains this + + for (int i=0;im_bridgeProxies.size();i++) + { + if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + } + alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); + } + + if (overlapsBroadphase) + { + if (containingBroadphaseIndex<0) + { + btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,childBroadphase); + } + } else + { + if (containingBroadphaseIndex>=0) + { + //remove + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + } + } + } + + + ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) + ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) + if (0)//!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } + } + + if (!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } +*/ + + + //update + for ( i=0;im_bridgeProxies.size();i++) + { + btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; + bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); + } + +} +bool stopUpdating=false; + + + +class btMultiSapBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const + { + btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; + + return aProxy0 > bProxy0 || + (aProxy0 == bProxy0 && aProxy1 > bProxy1) || + (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); + } +}; + + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb +void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + +// m_simpleBroadphase->calculateOverlappingPairs(dispatcher); + + if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); + + // quicksort(overlappingPairArray,0,overlappingPairArray.size()); + + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;im_multiSapParentProxy : 0; + btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; + + bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); + + previousPair = pair; + + bool needsRemoval = false; + + if (!isDuplicate) + { + bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); + + if (hasOverlap) + { + needsRemoval = false;//callback->processOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + + +} + + +bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) +{ + btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; + btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; + + return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, + multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); + +} + + +void btMultiSapBroadphase::printStats() +{ +/* printf("---------------------------------\n"); + + printf("btMultiSapBroadphase.h\n"); + printf("numHandles = %d\n",m_multiSapProxies.size()); + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;iprintStats(); + + } + */ + +} + +void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher) +{ + // not yet +} diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h new file mode 100644 index 00000000..7bcfe6b1 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_MULTI_SAP_BROADPHASE +#define BT_MULTI_SAP_BROADPHASE + +#include "btBroadphaseInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCache.h" + + +class btBroadphaseInterface; +class btSimpleBroadphase; + + +typedef btAlignedObjectArray btSapBroadphaseArray; + +///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead. +///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. +///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. +///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. +///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 +///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 +class btMultiSapBroadphase :public btBroadphaseInterface +{ + btSapBroadphaseArray m_sapBroadphases; + + btSimpleBroadphase* m_simpleBroadphase; + + btOverlappingPairCache* m_overlappingPairs; + + class btQuantizedBvh* m_optimizedAabbTree; + + + bool m_ownsPairCache; + + btOverlapFilterCallback* m_filterCallback; + + int m_invalidPair; + + struct btBridgeProxy + { + btBroadphaseProxy* m_childProxy; + btBroadphaseInterface* m_childBroadphase; + }; + + +public: + + struct btMultiSapProxy : public btBroadphaseProxy + { + + ///array with all the entries that this proxy belongs to + btAlignedObjectArray m_bridgeProxies; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + int m_shapeType; + +/* void* m_userPtr; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; +*/ + btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) + :btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax), + m_shapeType(shapeType) + { + m_multiSapParentProxy =this; + } + + + }; + +protected: + + + btAlignedObjectArray m_multiSapProxies; + +public: + + btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); + + + btSapBroadphaseArray& getBroadphaseArray() + { + return m_sapBroadphases; + } + + const btSapBroadphaseArray& getBroadphaseArray() const + { + return m_sapBroadphases; + } + + virtual ~btMultiSapBroadphase(); + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); + + void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + virtual btOverlappingPairCache* getOverlappingPairCache() + { + return m_overlappingPairs; + } + virtual const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_overlappingPairs; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + } + + void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + + virtual void printStats(); + + void quicksort (btBroadphasePairArray& a, int lo, int hi); + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + +}; + +#endif //BT_MULTI_SAP_BROADPHASE diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp new file mode 100644 index 00000000..ae22dadc --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -0,0 +1,633 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "btOverlappingPairCache.h" + +#include "btDispatcher.h" +#include "btCollisionAlgorithm.h" +#include "LinearMath/btAabbUtil2.h" + +#include + +int gOverlappingPairs = 0; + +int gRemovePairs =0; +int gAddedPairs =0; +int gFindPairs =0; + + + + +btHashedOverlappingPairCache::btHashedOverlappingPairCache(): + m_overlapFilterCallback(0), + m_blockedForChanges(false), + m_ghostPairCallback(0) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); + growTables(); +} + + + + +btHashedOverlappingPairCache::~btHashedOverlappingPairCache() +{ +} + + + +void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) +{ + if (pair.m_algorithm && dispatcher) + { + { + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + pair.m_algorithm=0; + } + } +} + + + + +void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + + + + +void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} + + + + + +btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + gFindPairs++; + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + if (hash >= m_hashTable.size()) + { + return NULL; + } + + int index = m_hashTable[hash]; + while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if (index == BT_NULL_PAIR) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; +} + +//#include + +void btHashedOverlappingPairCache::growTables() +{ + + int newCapacity = m_overlappingPairArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_NULL_PAIR; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_NULL_PAIR; + } + + for(i=0;igetUid(); + int proxyId2 = pair.m_pProxy1->getUid(); + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + m_next[i] = m_hashTable[hashValue]; + m_hashTable[hashValue] = i; + } + + + } +} + +btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair != NULL) + { + return pair; + } + /*for(int i=0;i%u\r\n",proxyId1,proxyId2); + internalFindPair(proxy0, proxy1, hash); + } + }*/ + int count = m_overlappingPairArray.size(); + int oldCapacity = m_overlappingPairArray.capacity(); + void* mem = &m_overlappingPairArray.expandNonInitializing(); + + //this is where we add an actual pair, so also call the 'ghost' + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0,proxy1); + + int newCapacity = m_overlappingPairArray.capacity(); + + if (oldCapacity < newCapacity) + { + growTables(); + //hash with new capacity + hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + } + + pair = new (mem) btBroadphasePair(*proxy0,*proxy1); +// pair->m_pProxy0 = proxy0; +// pair->m_pProxy1 = proxy1; + pair->m_algorithm = 0; + pair->m_internalTmpValue = 0; + + + m_next[count] = m_hashTable[hash]; + m_hashTable[hash] = count; + + return pair; +} + + + +void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) +{ + gRemovePairs++; + if(proxy0->m_uniqueId>proxy1->m_uniqueId) + btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair == NULL) + { + return 0; + } + + cleanOverlappingPair(*pair,dispatcher); + + void* userData = pair->m_internalInfo1; + + btAssert(pair->m_pProxy0->getUid() == proxyId1); + btAssert(pair->m_pProxy1->getUid() == proxyId2); + + int pairIndex = int(pair - &m_overlappingPairArray[0]); + btAssert(pairIndex < m_overlappingPairArray.size()); + + // Remove the pair from the hash table. + int index = m_hashTable[hash]; + btAssert(index != BT_NULL_PAIR); + + int previous = BT_NULL_PAIR; + while (index != pairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == pairIndex); + m_next[previous] = m_next[pairIndex]; + } + else + { + m_hashTable[hash] = m_next[pairIndex]; + } + + // We now move the last pair into spot of the + // pair being removed. We need to fix the hash + // table indices to support the move. + + int lastPairIndex = m_overlappingPairArray.size() - 1; + + if (m_ghostPairCallback) + m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); + + // If the removed pair is the last pair, we are done. + if (lastPairIndex == pairIndex) + { + m_overlappingPairArray.pop_back(); + return userData; + } + + // Remove the last pair from the hash table. + const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; + /* missing swap here too, Nat. */ + int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1)); + + index = m_hashTable[lastHash]; + btAssert(index != BT_NULL_PAIR); + + previous = BT_NULL_PAIR; + while (index != lastPairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == lastPairIndex); + m_next[previous] = m_next[lastPairIndex]; + } + else + { + m_hashTable[lastHash] = m_next[lastPairIndex]; + } + + // Copy the last pair into the remove pair's spot. + m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; + + // Insert the last pair into the hash table + m_next[pairIndex] = m_hashTable[lastHash]; + m_hashTable[lastHash] = pairIndex; + + m_overlappingPairArray.pop_back(); + + return userData; +} +//#include + +void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + +// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); + for (i=0;iprocessOverlap(*pair)) + { + removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); + + gOverlappingPairs--; + } else + { + i++; + } + } +} + +void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) +{ + ///need to keep hashmap in sync with pair address, so rebuild all + btBroadphasePairArray tmpPairs; + int i; + for (i=0;iremoveOverlappingPair(proxy0, proxy1,dispatcher); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); + m_overlappingPairArray.pop_back(); + return userData; + } + } + + return 0; +} + + + + + + + + +btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + //don't add overlap with own + btAssert(proxy0 != proxy1); + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + void* mem = &m_overlappingPairArray.expandNonInitializing(); + btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + + gOverlappingPairs++; + gAddedPairs++; + + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0, proxy1); + return pair; + +} + +///this findPair becomes really slow. Either sort the list to speedup the query, or +///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. +///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) +///Also we can use a 2D bitmap, which can be useful for a future GPU implementation + btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + btBroadphasePair tmpPair(*proxy0,*proxy1); + int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); + + if (findIndex < m_overlappingPairArray.size()) + { + //btAssert(it != m_overlappingPairSet.end()); + btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; + return pair; + } + return 0; +} + + + + + + + + + + +//#include + +void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + + for (i=0;iprocessOverlap(*pair)) + { + cleanOverlappingPair(*pair,dispatcher); + pair->m_pProxy0 = 0; + pair->m_pProxy1 = 0; + m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.pop_back(); + gOverlappingPairs--; + } else + { + i++; + } + } +} + + + + +btSortedOverlappingPairCache::btSortedOverlappingPairCache(): + m_blockedForChanges(false), + m_hasDeferredRemoval(true), + m_overlapFilterCallback(0), + m_ghostPairCallback(0) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); +} + +btSortedOverlappingPairCache::~btSortedOverlappingPairCache() +{ +} + +void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) +{ + if (pair.m_algorithm) + { + { + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + pair.m_algorithm=0; + gRemovePairs--; + } + } +} + + +void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + + +void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} + +void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher) +{ + //should already be sorted +} + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h new file mode 100644 index 00000000..eee90e47 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -0,0 +1,470 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OVERLAPPING_PAIR_CACHE_H +#define BT_OVERLAPPING_PAIR_CACHE_H + + +#include "btBroadphaseInterface.h" +#include "btBroadphaseProxy.h" +#include "btOverlappingPairCallback.h" + +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; + +typedef btAlignedObjectArray btBroadphasePairArray; + +struct btOverlapCallback +{ + virtual ~btOverlapCallback() + {} + //return true for deletion of the pair + virtual bool processOverlap(btBroadphasePair& pair) = 0; + +}; + +struct btOverlapFilterCallback +{ + virtual ~btOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; +}; + + + + + + + +extern int gRemovePairs; +extern int gAddedPairs; +extern int gFindPairs; + +const int BT_NULL_PAIR=0xffffffff; + +///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. +///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. +class btOverlappingPairCache : public btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor + + virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0; + + virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0; + + virtual btBroadphasePairArray& getOverlappingPairArray() = 0; + + virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; + + virtual int getNumOverlappingPairs() const = 0; + + virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; + + virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; + + virtual bool hasDeferredRemoval() = 0; + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; + + virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0; + + +}; + +/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com +class btHashedOverlappingPairCache : public btOverlappingPairCache +{ + btBroadphasePairArray m_overlappingPairArray; + btOverlapFilterCallback* m_overlapFilterCallback; + bool m_blockedForChanges; + +protected: + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + btOverlappingPairCallback* m_ghostPairCallback; + + +public: + btHashedOverlappingPairCache(); + virtual ~btHashedOverlappingPairCache(); + + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + // Add a pair and return the new pair. If the pair already exists, + // no new pair is created and the old one is returned. + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + gAddedPairs++; + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + return internalAddPair(proxy0,proxy1); + } + + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); + + int GetCount() const { return m_overlappingPairArray.size(); } +// btBroadphasePair* GetPairs() { return m_pairs; } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } +private: + + btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + void growTables(); + + SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) + { + return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; + } + + /* + // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm + // This assumes proxyId1 and proxyId2 are 16-bit. + SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) + { + int key = (proxyId2 << 16) | proxyId1; + key = ~key + (key << 15); + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key * 2057; + key = key ^ (key >> 16); + return key; + } + */ + + + + SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) + { + int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); + // Thomas Wang's hash + + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return static_cast(key); + } + + + + + + SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) + { + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + #endif + + int index = m_hashTable[hash]; + + while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if ( index == BT_NULL_PAIR ) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; + } + + virtual bool hasDeferredRemoval() + { + return false; + } + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher); + + + +}; + + + + +///btSortedOverlappingPairCache maintains the objects with overlapping AABB +///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase +class btSortedOverlappingPairCache : public btOverlappingPairCache +{ + protected: + //avoid brute-force finding all the time + btBroadphasePairArray m_overlappingPairArray; + + //during the dispatch, check that user doesn't destroy/create proxy + bool m_blockedForChanges; + + ///by default, do the removal during the pair traversal + bool m_hasDeferredRemoval; + + //if set, use the callback instead of the built in filter in needBroadphaseCollision + btOverlapFilterCallback* m_overlapFilterCallback; + + btOverlappingPairCallback* m_ghostPairCallback; + + public: + + btSortedOverlappingPairCache(); + virtual ~btSortedOverlappingPairCache(); + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + + + + btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + virtual bool hasDeferredRemoval() + { + return m_hasDeferredRemoval; + } + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher); + + +}; + + + +///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing. +class btNullPairCache : public btOverlappingPairCache +{ + + btBroadphasePairArray m_overlappingPairArray; + +public: + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual int getNumOverlappingPairs() const + { + return 0; + } + + virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) + { + } + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) + { + } + + virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual bool hasDeferredRemoval() + { + return true; + } + + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */) + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) + { + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) + { + } + + virtual void sortOverlappingPairs(btDispatcher* dispatcher) + { + (void) dispatcher; + } + + +}; + + +#endif //BT_OVERLAPPING_PAIR_CACHE_H + + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h new file mode 100644 index 00000000..9c7b6f81 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h @@ -0,0 +1,40 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef OVERLAPPING_PAIR_CALLBACK_H +#define OVERLAPPING_PAIR_CALLBACK_H + +class btDispatcher; +struct btBroadphasePair; + +///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. +class btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0; + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0; + +}; + +#endif //OVERLAPPING_PAIR_CALLBACK_H diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp new file mode 100644 index 00000000..889216df --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @@ -0,0 +1,1393 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btQuantizedBvh.h" + +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btSerializer.h" + +#define RAYAABB2 + +btQuantizedBvh::btQuantizedBvh() : + m_bulletVersion(BT_BULLET_VERSION), + m_useQuantization(false), + //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) + m_traversalMode(TRAVERSAL_STACKLESS) + //m_traversalMode(TRAVERSAL_RECURSIVE) + ,m_subtreeHeaderCount(0) //PCK: add this line +{ + m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY); + m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY); +} + + + + + +void btQuantizedBvh::buildInternal() +{ + ///assumes that caller filled in the m_quantizedLeafNodes + m_useQuantization = true; + int numLeafNodes = 0; + + if (m_useQuantization) + { + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); +} + + + +///just for debugging, to visualize the individual patches/subtrees +#ifdef DEBUG_PATCH_COLORS +btVector3 color[4]= +{ + btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1), + btVector3(0,1,1) +}; +#endif //DEBUG_PATCH_COLORS + + + +void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +{ + //enlarge the AABB to avoid division by zero when initializing the quantization values + btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); + m_bvhAabbMin = bvhAabbMin - clampValue; + m_bvhAabbMax = bvhAabbMax + clampValue; + btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; + + m_useQuantization = true; + + { + unsigned short vecIn[3]; + btVector3 v; + { + quantize(vecIn,m_bvhAabbMin,false); + v = unQuantize(vecIn); + m_bvhAabbMin.setMin(v-clampValue); + } + { + quantize(vecIn,m_bvhAabbMax,true); + v = unQuantize(vecIn); + m_bvhAabbMax.setMax(v+clampValue); + } + aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; + } +} + + + + +btQuantizedBvh::~btQuantizedBvh() +{ +} + +#ifdef DEBUG_TREE_BUILDING +int gStackDepth = 0; +int gMaxStackDepth = 0; +#endif //DEBUG_TREE_BUILDING + +void btQuantizedBvh::buildTree (int startIndex,int endIndex) +{ +#ifdef DEBUG_TREE_BUILDING + gStackDepth++; + if (gStackDepth > gMaxStackDepth) + gMaxStackDepth = gStackDepth; +#endif //DEBUG_TREE_BUILDING + + + int splitAxis, splitIndex, i; + int numIndices =endIndex-startIndex; + int curIndex = m_curNodeIndex; + + btAssert(numIndices>0); + + if (numIndices==1) + { +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); + + m_curNodeIndex++; + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + splitAxis = calcSplittingAxis(startIndex,endIndex); + + splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); + + int internalNodeIndex = m_curNodeIndex; + + //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value. + //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values + setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization + setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization + + + for (i=startIndex;im_escapeIndex; + + int leftChildNodexIndex = m_curNodeIndex; + + //build left child tree + buildTree(startIndex,splitIndex); + + int rightChildNodexIndex = m_curNodeIndex; + //build right child tree + buildTree(splitIndex,endIndex); + +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + int escapeIndex = m_curNodeIndex - curIndex; + + if (m_useQuantization) + { + //escapeIndex is the number of nodes of this subtree + const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); + const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; + if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) + { + updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); + } + } else + { + + } + + setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); + +} + +void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) +{ + btAssert(m_useQuantization); + + btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; + int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); + int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; + int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); + int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(leftChildNode); + subtree.m_rootNodeIndex = leftChildNodexIndex; + subtree.m_subtreeSize = leftSubTreeSize; + } + + if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(rightChildNode); + subtree.m_rootNodeIndex = rightChildNodexIndex; + subtree.m_subtreeSize = rightSubTreeSize; + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); +} + + +int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) +{ + int i; + int splitIndex =startIndex; + int numIndices = endIndex - startIndex; + btScalar splitValue; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + for (i=startIndex;i splitValue) + { + //swap + swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + (void)unbal; + btAssert(!unbal); + + return splitIndex; +} + + +int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex) +{ + int i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + int numIndices = endIndex-startIndex; + + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (aabbOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +/* +///this was the original recursive traversal, before we optimized towards stackless traversal +void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); + if (aabbOverlap) + { + isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); + if (isLeafNode) + { + nodeCallback->processNode(rootNode); + } else + { + walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); + walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); + } + } + +} +*/ + +void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); + isLeafNode = currentNode->isLeafNode(); + + //PCK: unsigned instead of bool + if (aabbOverlap != 0) + { + if (isLeafNode) + { + nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex()); + } else + { + //process left and right children + const btQuantizedBvhNode* leftChildNode = currentNode+1; + walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + + const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); + walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + } + } +} + + + +void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(!m_useQuantization); + + const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0]; + int escapeIndex, curIndex = 0; + int walkIterations = 0; + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap=0; + unsigned rayBoxOverlap=0; + btScalar lambda_max = 1.0; + + /* Quick pruning by quantized box */ + btVector3 rayAabbMin = raySource; + btVector3 rayAabbMax = raySource; + rayAabbMin.setMin(rayTarget); + rayAabbMax.setMax(rayTarget); + + /* Add box cast extents to bounding box */ + rayAabbMin += aabbMin; + rayAabbMax += aabbMax; + +#ifdef RAYAABB2 + btVector3 rayDir = (rayTarget-raySource); + rayDir.normalize (); + lambda_max = rayDir.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + btVector3 rayDirectionInverse; + rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; +#endif + + btVector3 bounds[2]; + + while (curIndex < m_curNodeIndex) + { + btScalar param = 1.0; + //catch bugs in tree data + btAssert (walkIterations < m_curNodeIndex); + + walkIterations++; + + bounds[0] = rootNode->m_aabbMinOrg; + bounds[1] = rootNode->m_aabbMaxOrg; + /* Add box cast extents */ + bounds[0] -= aabbMax; + bounds[1] -= aabbMin; + + aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg); + //perhaps profile if it is worth doing the aabbOverlap test first + +#ifdef RAYAABB2 + ///careful with this check: need to check division by zero (above) and fix the unQuantize method + ///thanks Joerg/hiker for the reproduction case! + ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false; + +#else + btVector3 normal; + rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal); +#endif + + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (rayBoxOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + + + +void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned boxBoxOverlap = 0; + unsigned rayBoxOverlap = 0; + + btScalar lambda_max = 1.0; + +#ifdef RAYAABB2 + btVector3 rayDirection = (rayTarget-raySource); + rayDirection.normalize (); + lambda_max = rayDirection.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0]; + rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1]; + rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2]; + unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0}; +#endif + + /* Quick pruning by quantized box */ + btVector3 rayAabbMin = raySource; + btVector3 rayAabbMax = raySource; + rayAabbMin.setMin(rayTarget); + rayAabbMax.setMax(rayTarget); + + /* Add box cast extents to bounding box */ + rayAabbMin += aabbMin; + rayAabbMax += aabbMax; + + unsigned short int quantizedQueryAabbMin[3]; + unsigned short int quantizedQueryAabbMax[3]; + quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0); + quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1); + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + btAssert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + // only interested if this is closer than any previous hit + btScalar param = 1.0; + rayBoxOverlap = 0; + boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + if (boxBoxOverlap) + { + btVector3 bounds[2]; + bounds[0] = unQuantize(rootNode->m_quantizedAabbMin); + bounds[1] = unQuantize(rootNode->m_quantizedAabbMax); + /* Add box cast extents */ + bounds[0] -= aabbMax; + bounds[1] -= aabbMin; + btVector3 normal; +#if 0 + bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max); + bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal); + if (ra2 != ra) + { + printf("functions don't match\n"); + } +#endif +#ifdef RAYAABB2 + ///careful with this check: need to check division by zero (above) and fix the unQuantize method + ///thanks Joerg/hiker for the reproduction case! + ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + + //BT_PROFILE("btRayAabb2"); + rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max); + +#else + rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal); +#endif + } + + if (isLeafNode && rayBoxOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + btAssert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +//This traversal can be called from Playstation 3 SPU +void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + int i; + + + for (i=0;im_SubtreeHeaders.size();i++) + { + const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) + { + walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + subtree.m_rootNodeIndex, + subtree.m_rootNodeIndex+subtree.m_subtreeSize); + } + } +} + + +void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const +{ + reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0)); +} + + +void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const +{ + //always use stackless + + if (m_useQuantization) + { + walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } + else + { + walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } + /* + { + //recursive traversal + btVector3 qaabbMin = raySource; + btVector3 qaabbMax = raySource; + qaabbMin.setMin(rayTarget); + qaabbMax.setMax(rayTarget); + qaabbMin += aabbMin; + qaabbMax += aabbMax; + reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax); + } + */ + +} + + +void btQuantizedBvh::swapLeafNodes(int i,int splitIndex) +{ + if (m_useQuantization) + { + btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; + m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; + m_quantizedLeafNodes[splitIndex] = tmp; + } else + { + btOptimizedBvhNode tmp = m_leafNodes[i]; + m_leafNodes[i] = m_leafNodes[splitIndex]; + m_leafNodes[splitIndex] = tmp; + } +} + +void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) +{ + if (m_useQuantization) + { + m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; + } else + { + m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; + } +} + +//PCK: include +#include + +#if 0 +//PCK: consts +static const unsigned BVH_ALIGNMENT = 16; +static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; + +static const unsigned BVH_ALIGNMENT_BLOCKS = 2; +#endif + + +unsigned int btQuantizedBvh::getAlignmentSerializationPadding() +{ + // I changed this to 0 since the extra padding is not needed or used. + return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; +} + +unsigned btQuantizedBvh::calculateSerializeBufferSize() const +{ + unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding(); + baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + if (m_useQuantization) + { + return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); + } + return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); +} + +bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const +{ + btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + +/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + ///check alignedment for buffer? + btAssert(0); + return false; + } +*/ + + btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer; + + // construct the class so the virtual function table, etc will be set up + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (targetBvh) btQuantizedBvh; + + if (i_swapEndian) + { + targetBvh->m_curNodeIndex = static_cast(btSwapEndian(m_curNodeIndex)); + + + btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); + btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); + btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); + + targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); + targetBvh->m_subtreeHeaderCount = static_cast(btSwapEndian(m_subtreeHeaderCount)); + } + else + { + targetBvh->m_curNodeIndex = m_curNodeIndex; + targetBvh->m_bvhAabbMin = m_bvhAabbMin; + targetBvh->m_bvhAabbMax = m_bvhAabbMax; + targetBvh->m_bvhQuantization = m_bvhQuantization; + targetBvh->m_traversalMode = m_traversalMode; + targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; + } + + targetBvh->m_useQuantization = m_useQuantization; + + unsigned char *nodeData = (unsigned char *)targetBvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = m_curNodeIndex; + + if (m_useQuantization) + { + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; + + + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0); + } + else + { + targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex)); + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart)); + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0); + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex)); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize)); + } + } + else + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); + + // need to clear padding in destination buffer + targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0; + targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0; + targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0; + } + } + nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + + // this clears the pointer in the member variable it doesn't really do anything to the data + // it does call the destructor on the contained objects, but they are all classes with no destructor defined + // so the memory (which is not freed) is left alone + targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0); + + // this wipes the virtual function table pointer at the start of the buffer for the class + *((void**)o_alignedDataBuffer) = NULL; + + return true; +} + +btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +{ + + if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + return NULL; + } + btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer; + + if (i_swapEndian) + { + bvh->m_curNodeIndex = static_cast(btSwapEndian(bvh->m_curNodeIndex)); + + btUnSwapVector3Endian(bvh->m_bvhAabbMin); + btUnSwapVector3Endian(bvh->m_bvhAabbMax); + btUnSwapVector3Endian(bvh->m_bvhQuantization); + + bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); + bvh->m_subtreeHeaderCount = static_cast(btSwapEndian(bvh->m_subtreeHeaderCount)); + } + + unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize(); + btAssert(calculatedBufSize <= i_dataBufferSize); + + if (calculatedBufSize > i_dataBufferSize) + { + return NULL; + } + + unsigned char *nodeData = (unsigned char *)bvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = bvh->m_curNodeIndex; + + // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (bvh) btQuantizedBvh(*bvh, false); + + if (bvh->m_useQuantization) + { + bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex)); + bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart)); + bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) + { + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex)); + bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize)); + } + } + + return bvh; +} + +// Constructor that prevents btVector3's default constructor from being called +btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) : +m_bvhAabbMin(self.m_bvhAabbMin), +m_bvhAabbMax(self.m_bvhAabbMax), +m_bvhQuantization(self.m_bvhQuantization), +m_bulletVersion(BT_BULLET_VERSION) +{ + +} + +void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData) +{ + m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax); + m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin); + m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization); + + m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex; + m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0; + + { + int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes; + m_contiguousNodes.resize(numElem); + + if (numElem) + { + btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr; + + for (int i=0;im_aabbMaxOrg); + m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg); + m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex; + m_contiguousNodes[i].m_subPart = memPtr->m_subPart; + m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex; + } + } + } + + { + int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes; + m_quantizedContiguousNodes.resize(numElem); + + if (numElem) + { + btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr; + for (int i=0;im_escapeIndexOrTriangleIndex; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + } + } + } + + m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode); + + { + int numElem = quantizedBvhFloatData.m_numSubtreeHeaders; + m_SubtreeHeaders.resize(numElem); + if (numElem) + { + btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr; + for (int i=0;im_quantizedAabbMax[0] ; + m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex; + m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize; + } + } + } +} + +void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData) +{ + m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax); + m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin); + m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization); + + m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex; + m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0; + + { + int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes; + m_contiguousNodes.resize(numElem); + + if (numElem) + { + btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr; + + for (int i=0;im_aabbMaxOrg); + m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg); + m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex; + m_contiguousNodes[i].m_subPart = memPtr->m_subPart; + m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex; + } + } + } + + { + int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes; + m_quantizedContiguousNodes.resize(numElem); + + if (numElem) + { + btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr; + for (int i=0;im_escapeIndexOrTriangleIndex; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + } + } + } + + m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode); + + { + int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders; + m_SubtreeHeaders.resize(numElem); + if (numElem) + { + btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr; + for (int i=0;im_quantizedAabbMax[0] ; + m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1]; + m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2]; + m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0]; + m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1]; + m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2]; + m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex; + m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize; + } + } + } + +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer; + + m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax); + m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin); + m_bvhQuantization.serialize(quantizedData->m_bvhQuantization); + + quantizedData->m_curNodeIndex = m_curNodeIndex; + quantizedData->m_useQuantization = m_useQuantization; + + quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size(); + quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*) (m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0); + if (quantizedData->m_contiguousNodesPtr) + { + int sz = sizeof(btOptimizedBvhNodeData); + int numElem = m_contiguousNodes.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr; + for (int i=0;im_aabbMaxOrg); + m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg); + memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex; + memPtr->m_subPart = m_contiguousNodes[i].m_subPart; + memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex; + } + serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]); + } + + quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size(); +// printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes); + quantizedData->m_quantizedContiguousNodesPtr =(btQuantizedBvhNodeData*) (m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0); + if (quantizedData->m_quantizedContiguousNodesPtr) + { + int sz = sizeof(btQuantizedBvhNodeData); + int numElem = m_quantizedContiguousNodes.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr; + for (int i=0;im_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex; + memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0]; + memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1]; + memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2]; + memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0]; + memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1]; + memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2]; + } + serializer->finalizeChunk(chunk,"btQuantizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_quantizedContiguousNodes[0]); + } + + quantizedData->m_traversalMode = int(m_traversalMode); + quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size(); + + quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*) (m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0); + if (quantizedData->m_subTreeInfoPtr) + { + int sz = sizeof(btBvhSubtreeInfoData); + int numElem = m_SubtreeHeaders.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr; + for (int i=0;im_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0]; + memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1]; + memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2]; + memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0]; + memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1]; + memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2]; + + memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex; + memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize; + } + serializer->finalizeChunk(chunk,"btBvhSubtreeInfoData",BT_ARRAY_CODE,(void*)&m_SubtreeHeaders[0]); + } + return btQuantizedBvhDataName; +} + + + + + diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h new file mode 100644 index 00000000..78382da7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -0,0 +1,581 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_QUANTIZED_BVH_H +#define BT_QUANTIZED_BVH_H + +class btSerializer; + +//#define DEBUG_CHECK_DEQUANTIZATION 1 +#ifdef DEBUG_CHECK_DEQUANTIZATION +#ifdef __SPU__ +#define printf spu_printf +#endif //__SPU__ + +#include +#include +#endif //DEBUG_CHECK_DEQUANTIZATION + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btQuantizedBvhData btQuantizedBvhDoubleData +#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData +#define btQuantizedBvhDataName "btQuantizedBvhDoubleData" +#else +#define btQuantizedBvhData btQuantizedBvhFloatData +#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData +#define btQuantizedBvhDataName "btQuantizedBvhFloatData" +#endif + + + +//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp + + +//Note: currently we have 16 bytes per quantized node +#define MAX_SUBTREE_SIZE_IN_BYTES 2048 + +// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one +// actually) triangles each (since the sign bit is reserved +#define MAX_NUM_PARTS_IN_BITS 10 + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrTriangleIndex; + + bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrTriangleIndex >= 0); + } + int getEscapeIndex() const + { + btAssert(!isLeafNode()); + return -m_escapeIndexOrTriangleIndex; + } + int getTriangleIndex() const + { + btAssert(isLeafNode()); + unsigned int x=0; + unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS); + // Get only the lower bits where the triangle index is stored + return (m_escapeIndexOrTriangleIndex&~(y)); + } + int getPartId() const + { + btAssert(isLeafNode()); + // Get only the highest bits where the part index is stored + return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); + } +} +; + +/// btOptimizedBvhNode contains both internal and leaf node information. +/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. +ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //32 bytes + btVector3 m_aabbMinOrg; + btVector3 m_aabbMaxOrg; + + //4 + int m_escapeIndex; + + //8 + //for child nodes + int m_subPart; + int m_triangleIndex; + +//pad the size to 64 bytes + char m_padding[20]; +}; + + +///btBvhSubtreeInfo provides info to gather a subtree of limited size +ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo +{ +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes, points to the root of the subtree + int m_rootNodeIndex; + //4 bytes + int m_subtreeSize; + int m_padding[3]; + + btBvhSubtreeInfo() + { + //memset(&m_padding[0], 0, sizeof(m_padding)); + } + + + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) + { + m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; + m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; + m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; + m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; + m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; + m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; + } +} +; + + +class btNodeOverlapCallback +{ +public: + virtual ~btNodeOverlapCallback() {}; + + virtual void processNode(int subPart, int triangleIndex) = 0; +}; + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" + + + +///for code readability: +typedef btAlignedObjectArray NodeArray; +typedef btAlignedObjectArray QuantizedNodeArray; +typedef btAlignedObjectArray BvhSubtreeInfoArray; + + +///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. +///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. +///It is recommended to use quantization for better performance and lower memory requirements. +ATTRIBUTE_ALIGNED16(class) btQuantizedBvh +{ +public: + enum btTraversalMode + { + TRAVERSAL_STACKLESS = 0, + TRAVERSAL_STACKLESS_CACHE_FRIENDLY, + TRAVERSAL_RECURSIVE + }; + +protected: + + + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; + + int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess. + + int m_curNodeIndex; + //quantization data + bool m_useQuantization; + + + + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + QuantizedNodeArray m_quantizedLeafNodes; + QuantizedNodeArray m_quantizedContiguousNodes; + + btTraversalMode m_traversalMode; + BvhSubtreeInfoArray m_SubtreeHeaders; + + //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray + mutable int m_subtreeHeaderCount; + + + + + + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) + ///this might be refactored into a virtual, it is usually not calculated at run-time + void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; + + } + } + void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; + } + } + + btVector3 getAabbMin(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMinOrg; + + } + btVector3 getAabbMax(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMaxOrg; + + } + + + void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) + { + if (m_useQuantization) + { + m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; + } + else + { + m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; + } + + } + + void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) + { + if (m_useQuantization) + { + unsigned short int quantizedAabbMin[3]; + unsigned short int quantizedAabbMax[3]; + quantize(quantizedAabbMin,newAabbMin,0); + quantize(quantizedAabbMax,newAabbMax,1); + for (int i=0;i<3;i++) + { + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; + + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; + + } + } else + { + //non-quantized + m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); + m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); + } + } + + void swapLeafNodes(int firstIndex,int secondIndex); + + void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + +protected: + + + + void buildTree (int startIndex,int endIndex); + + int calcSplittingAxis(int startIndex,int endIndex); + + int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); + + void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; + void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; + void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; + + ///tree traversal designed for small-memory processors like PS3 SPU + void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; + + + + + void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btQuantizedBvh(); + + virtual ~btQuantizedBvh(); + + + ///***************************************** expert/internal use only ************************* + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); + QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; } + ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized + void buildInternal(); + ///***************************************** expert/internal use only ************************* + + void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const; + void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const; + + SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const + { + + btAssert(m_useQuantization); + + btAssert(point.getX() <= m_bvhAabbMax.getX()); + btAssert(point.getY() <= m_bvhAabbMax.getY()); + btAssert(point.getZ() <= m_bvhAabbMax.getZ()); + + btAssert(point.getX() >= m_bvhAabbMin.getX()); + btAssert(point.getY() >= m_bvhAabbMin.getY()); + btAssert(point.getZ() >= m_bvhAabbMin.getZ()); + + btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization; + ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative + ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly) + ///@todo: double-check this + if (isMax) + { + out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); + out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1)); + } else + { + out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe)); + out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe)); + } + + +#ifdef DEBUG_CHECK_DEQUANTIZATION + btVector3 newPoint = unQuantize(out); + if (isMax) + { + if (newPoint.getX() < point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() < point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() < point.getZ()) + { + + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } else + { + if (newPoint.getX() > point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() > point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() > point.getZ()) + { + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } +#endif //DEBUG_CHECK_DEQUANTIZATION + + } + + + SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const + { + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point2); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + quantize(out,clampedPoint,isMax); + + } + + SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const + { + btVector3 vecOut; + vecOut.setValue( + (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), + (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), + (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); + vecOut += m_bvhAabbMin; + return vecOut; + } + + ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. + void setTraversalMode(btTraversalMode traversalMode) + { + m_traversalMode = traversalMode; + } + + + SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() + { + return m_quantizedContiguousNodes; + } + + + SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() + { + return m_SubtreeHeaders; + } + +//////////////////////////////////////////////////////////////////// + + /////Calculate space needed to store BVH for serialization + unsigned calculateSerializeBufferSize() const; + + /// Data buffer MUST be 16 byte aligned + virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const; + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + static unsigned int getAlignmentSerializationPadding(); +////////////////////////////////////////////////////////////////////// + + + virtual int calculateSerializeBufferSizeNew() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData); + + virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData); + + +//////////////////////////////////////////////////////////////////// + + SIMD_FORCE_INLINE bool isQuantized() + { + return m_useQuantization; + } + +private: + // Special "copy" constructor that allows for in-place deserialization + // Prevents btVector3's default constructor from being called, but doesn't inialize much else + // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) + btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory); + +} +; + + +struct btBvhSubtreeInfoData +{ + int m_rootNodeIndex; + int m_subtreeSize; + unsigned short m_quantizedAabbMin[3]; + unsigned short m_quantizedAabbMax[3]; +}; + +struct btOptimizedBvhNodeFloatData +{ + btVector3FloatData m_aabbMinOrg; + btVector3FloatData m_aabbMaxOrg; + int m_escapeIndex; + int m_subPart; + int m_triangleIndex; + char m_pad[4]; +}; + +struct btOptimizedBvhNodeDoubleData +{ + btVector3DoubleData m_aabbMinOrg; + btVector3DoubleData m_aabbMaxOrg; + int m_escapeIndex; + int m_subPart; + int m_triangleIndex; + char m_pad[4]; +}; + + +struct btQuantizedBvhNodeData +{ + unsigned short m_quantizedAabbMin[3]; + unsigned short m_quantizedAabbMax[3]; + int m_escapeIndexOrTriangleIndex; +}; + +struct btQuantizedBvhFloatData +{ + btVector3FloatData m_bvhAabbMin; + btVector3FloatData m_bvhAabbMax; + btVector3FloatData m_bvhQuantization; + int m_curNodeIndex; + int m_useQuantization; + int m_numContiguousLeafNodes; + int m_numQuantizedContiguousNodes; + btOptimizedBvhNodeFloatData *m_contiguousNodesPtr; + btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr; + btBvhSubtreeInfoData *m_subTreeInfoPtr; + int m_traversalMode; + int m_numSubtreeHeaders; + +}; + +struct btQuantizedBvhDoubleData +{ + btVector3DoubleData m_bvhAabbMin; + btVector3DoubleData m_bvhAabbMax; + btVector3DoubleData m_bvhQuantization; + int m_curNodeIndex; + int m_useQuantization; + int m_numContiguousLeafNodes; + int m_numQuantizedContiguousNodes; + btOptimizedBvhNodeDoubleData *m_contiguousNodesPtr; + btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr; + + int m_traversalMode; + int m_numSubtreeHeaders; + btBvhSubtreeInfoData *m_subTreeInfoPtr; +}; + + +SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const +{ + return sizeof(btQuantizedBvhData); +} + + + +#endif //BT_QUANTIZED_BVH_H diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp new file mode 100644 index 00000000..752fcd0f --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -0,0 +1,349 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAabbUtil2.h" + +#include + +extern int gOverlappingPairs; + +void btSimpleBroadphase::validate() +{ + for (int i=0;i~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + + +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) +{ + if (m_numHandles >= m_maxHandles) + { + btAssert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); + + int newHandleIndex = allocHandle(); + btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + + return proxy; +} + +class RemovingOverlapCallback : public btOverlapCallback +{ +protected: + virtual bool processOverlap(btBroadphasePair& pair) + { + (void)pair; + btAssert(0); + return false; + } +}; + +class RemovePairContainingProxy +{ + + btBroadphaseProxy* m_targetProxy; + public: + virtual ~RemovePairContainingProxy() + { + } +protected: + virtual bool processOverlap(btBroadphasePair& pair) + { + btSimpleBroadphaseProxy* proxy0 = static_cast(pair.m_pProxy0); + btSimpleBroadphaseProxy* proxy1 = static_cast(pair.m_pProxy1); + + return ((m_targetProxy == proxy0 || m_targetProxy == proxy1)); + }; +}; + +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) +{ + + btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); + freeHandle(proxy0); + + m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); + + //validate(); + +} + +void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const +{ + const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); + aabbMin = sbp->m_aabbMin; + aabbMax = sbp->m_aabbMax; +} + +void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/) +{ + btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); + sbp->m_aabbMin = aabbMin; + sbp->m_aabbMax = aabbMax; +} + +void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax) +{ + for (int i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + rayCallback.process(proxy); + } +} + + +void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) +{ + for (int i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax)) + { + callback.process(proxy); + } + } +} + + + + + + + +bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1) +{ + return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] && + proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] && + proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2]; + +} + + + +//then remove non-overlapping ones +class CheckOverlapCallback : public btOverlapCallback +{ +public: + virtual bool processOverlap(btBroadphasePair& pair) + { + return (!btSimpleBroadphase::aabbOverlap(static_cast(pair.m_pProxy0),static_cast(pair.m_pProxy1))); + } +}; + +void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + //first check for new overlapping pairs + int i,j; + if (m_numHandles >= 0) + { + int new_largest_index = -1; + for (i=0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + for (j=i+1; j <= m_LastHandleIndex; j++) + { + btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j]; + btAssert(proxy0 != proxy1); + if(!proxy1->m_clientObject) + { + continue; + } + + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + + if (aabbOverlap(p0,p1)) + { + if ( !m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } else + { + if (!m_pairCache->hasDeferredRemoval()) + { + if ( m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } + } + } + } + + m_LastHandleIndex = new_largest_index; + + if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: +#define CLEAN_INVALID_PAIRS 1 +#ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif//CLEAN_INVALID_PAIRS + + } + } +} + + +bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + return aabbOverlap(p0,p1); +} + +void btSimpleBroadphase::resetPool(btDispatcher* dispatcher) +{ + //not yet +} diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h new file mode 100644 index 00000000..7cb3c40a --- /dev/null +++ b/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -0,0 +1,171 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SIMPLE_BROADPHASE_H +#define BT_SIMPLE_BROADPHASE_H + + +#include "btOverlappingPairCache.h" + + +struct btSimpleBroadphaseProxy : public btBroadphaseProxy +{ + int m_nextFree; + +// int m_handleId; + + + btSimpleBroadphaseProxy() {}; + + btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) + :btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy) + { + (void)shapeType; + } + + + SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} + SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} + + + + +}; + +///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead. +///It is a brute force aabb culling broadphase based on O(n^2) aabb checks +class btSimpleBroadphase : public btBroadphaseInterface +{ + +protected: + + int m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + int m_LastHandleIndex; + + btSimpleBroadphaseProxy* m_pHandles; // handles pool + + void* m_pHandlesRawPtr; + int m_firstFreeHandle; // free handles list + + int allocHandle() + { + btAssert(m_numHandles < m_maxHandles); + int freeHandle = m_firstFreeHandle; + m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); + m_numHandles++; + if(freeHandle > m_LastHandleIndex) + { + m_LastHandleIndex = freeHandle; + } + return freeHandle; + } + + void freeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy-m_pHandles); + btAssert(handle >= 0 && handle < m_maxHandles); + if(handle == m_LastHandleIndex) + { + m_LastHandleIndex--; + } + proxy->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + proxy->m_clientObject = 0; + + m_numHandles--; + } + + btOverlappingPairCache* m_pairCache; + bool m_ownsPairCache; + + int m_invalidPair; + + + + inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) + { + btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const + { + const btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + return proxy0; + } + + ///reset broadphase internal structures, to ensure determinism/reproducability + virtual void resetPool(btDispatcher* dispatcher); + + + void validate(); + +protected: + + + + +public: + btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); + virtual ~btSimpleBroadphase(); + + + static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); + + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const; + + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); + virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + } + + virtual void printStats() + { +// printf("btSimpleBroadphase.h\n"); +// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + } +}; + + + +#endif //BT_SIMPLE_BROADPHASE_H + diff --git a/Code/Physics/src/BulletCollision/CMakeLists.txt b/Code/Physics/src/BulletCollision/CMakeLists.txt new file mode 100644 index 00000000..c4723ae2 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CMakeLists.txt @@ -0,0 +1,286 @@ +INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ) + +SET(BulletCollision_SRCS + BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btDbvt.cpp + BroadphaseCollision/btDbvtBroadphase.cpp + BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btMultiSapBroadphase.cpp + BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btQuantizedBvh.cpp + BroadphaseCollision/btSimpleBroadphase.cpp + CollisionDispatch/btActivatingCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxDetector.cpp + CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp + CollisionDispatch/btDefaultCollisionConfiguration.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btGhostObject.cpp + CollisionDispatch/btHashedSimplePairCache.cpp + CollisionDispatch/btInternalEdgeUtility.cpp + CollisionDispatch/btInternalEdgeUtility.h + CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp + CollisionDispatch/btUnionFind.cpp + CollisionDispatch/SphereTriangleDetector.cpp + CollisionShapes/btBoxShape.cpp + CollisionShapes/btBox2dShape.cpp + CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btCapsuleShape.cpp + CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCompoundShape.cpp + CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConeShape.cpp + CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexInternalShape.cpp + CollisionShapes/btConvexPointCloudShape.cpp + CollisionShapes/btConvexPolyhedron.cpp + CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvex2dShape.cpp + CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btCylinderShape.cpp + CollisionShapes/btEmptyShape.cpp + CollisionShapes/btHeightfieldTerrainShape.cpp + CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMultimaterialTriangleMeshShape.cpp + CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btScaledBvhTriangleMeshShape.cpp + CollisionShapes/btShapeHull.cpp + CollisionShapes/btSphereShape.cpp + CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleIndexVertexMaterialArray.cpp + CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btUniformScalingShape.cpp + Gimpact/btContactProcessing.cpp + Gimpact/btGenericPoolAllocator.cpp + Gimpact/btGImpactBvh.cpp + Gimpact/btGImpactCollisionAlgorithm.cpp + Gimpact/btGImpactQuantizedBvh.cpp + Gimpact/btGImpactShape.cpp + Gimpact/btTriangleShapeEx.cpp + Gimpact/gim_box_set.cpp + Gimpact/gim_contact.cpp + Gimpact/gim_memory.cpp + Gimpact/gim_tri_collision.cpp + NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkEpa2.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.cpp + NarrowPhaseCollision/btPolyhedralContactClipping.cpp +) + +SET(Root_HDRS + ../btBulletCollisionCommon.h +) +SET(BroadphaseCollision_HDRS + BroadphaseCollision/btAxisSweep3.h + BroadphaseCollision/btBroadphaseInterface.h + BroadphaseCollision/btBroadphaseProxy.h + BroadphaseCollision/btCollisionAlgorithm.h + BroadphaseCollision/btDbvt.h + BroadphaseCollision/btDbvtBroadphase.h + BroadphaseCollision/btDispatcher.h + BroadphaseCollision/btMultiSapBroadphase.h + BroadphaseCollision/btOverlappingPairCache.h + BroadphaseCollision/btOverlappingPairCallback.h + BroadphaseCollision/btQuantizedBvh.h + BroadphaseCollision/btSimpleBroadphase.h +) +SET(CollisionDispatch_HDRS + CollisionDispatch/btActivatingCollisionAlgorithm.h + CollisionDispatch/btBoxBoxCollisionAlgorithm.h + CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h + CollisionDispatch/btBoxBoxDetector.h + CollisionDispatch/btCollisionConfiguration.h + CollisionDispatch/btCollisionCreateFunc.h + CollisionDispatch/btCollisionDispatcher.h + CollisionDispatch/btCollisionObject.h + CollisionDispatch/btCollisionObjectWrapper.h + CollisionDispatch/btCollisionWorld.h + CollisionDispatch/btCompoundCollisionAlgorithm.h + CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h + CollisionDispatch/btConvexConcaveCollisionAlgorithm.h + CollisionDispatch/btConvexConvexAlgorithm.h + CollisionDispatch/btConvex2dConvex2dAlgorithm.h + CollisionDispatch/btConvexPlaneCollisionAlgorithm.h + CollisionDispatch/btDefaultCollisionConfiguration.h + CollisionDispatch/btEmptyCollisionAlgorithm.h + CollisionDispatch/btGhostObject.h + CollisionDispatch/btHashedSimplePairCache.h + CollisionDispatch/btManifoldResult.h + CollisionDispatch/btSimulationIslandManager.h + CollisionDispatch/btSphereBoxCollisionAlgorithm.h + CollisionDispatch/btSphereSphereCollisionAlgorithm.h + CollisionDispatch/btSphereTriangleCollisionAlgorithm.h + CollisionDispatch/btUnionFind.h + CollisionDispatch/SphereTriangleDetector.h +) +SET(CollisionShapes_HDRS + CollisionShapes/btBoxShape.h + CollisionShapes/btBox2dShape.h + CollisionShapes/btBvhTriangleMeshShape.h + CollisionShapes/btCapsuleShape.h + CollisionShapes/btCollisionMargin.h + CollisionShapes/btCollisionShape.h + CollisionShapes/btCompoundShape.h + CollisionShapes/btConcaveShape.h + CollisionShapes/btConeShape.h + CollisionShapes/btConvexHullShape.h + CollisionShapes/btConvexInternalShape.h + CollisionShapes/btConvexPointCloudShape.h + CollisionShapes/btConvexPolyhedron.h + CollisionShapes/btConvexShape.h + CollisionShapes/btConvex2dShape.h + CollisionShapes/btConvexTriangleMeshShape.h + CollisionShapes/btCylinderShape.h + CollisionShapes/btEmptyShape.h + CollisionShapes/btHeightfieldTerrainShape.h + CollisionShapes/btMaterial.h + CollisionShapes/btMinkowskiSumShape.h + CollisionShapes/btMultimaterialTriangleMeshShape.h + CollisionShapes/btMultiSphereShape.h + CollisionShapes/btOptimizedBvh.h + CollisionShapes/btPolyhedralConvexShape.h + CollisionShapes/btScaledBvhTriangleMeshShape.h + CollisionShapes/btShapeHull.h + CollisionShapes/btSphereShape.h + CollisionShapes/btStaticPlaneShape.h + CollisionShapes/btStridingMeshInterface.h + CollisionShapes/btTetrahedronShape.h + CollisionShapes/btTriangleBuffer.h + CollisionShapes/btTriangleCallback.h + CollisionShapes/btTriangleIndexVertexArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.h + CollisionShapes/btTriangleInfoMap.h + CollisionShapes/btTriangleMesh.h + CollisionShapes/btTriangleMeshShape.h + CollisionShapes/btTriangleShape.h + CollisionShapes/btUniformScalingShape.h +) +SET(Gimpact_HDRS + Gimpact/btBoxCollision.h + Gimpact/btClipPolygon.h + Gimpact/btContactProcessing.h + Gimpact/btGenericPoolAllocator.h + Gimpact/btGeometryOperations.h + Gimpact/btGImpactBvh.h + Gimpact/btGImpactCollisionAlgorithm.h + Gimpact/btGImpactMassUtil.h + Gimpact/btGImpactQuantizedBvh.h + Gimpact/btGImpactShape.h + Gimpact/btQuantization.h + Gimpact/btTriangleShapeEx.h + Gimpact/gim_array.h + Gimpact/gim_basic_geometry_operations.h + Gimpact/gim_bitset.h + Gimpact/gim_box_collision.h + Gimpact/gim_box_set.h + Gimpact/gim_clip_polygon.h + Gimpact/gim_contact.h + Gimpact/gim_geom_types.h + Gimpact/gim_geometry.h + Gimpact/gim_hash_table.h + Gimpact/gim_linear_math.h + Gimpact/gim_math.h + Gimpact/gim_memory.h + Gimpact/gim_radixsort.h + Gimpact/gim_tri_collision.h +) +SET(NarrowPhaseCollision_HDRS + NarrowPhaseCollision/btContinuousConvexCollision.h + NarrowPhaseCollision/btConvexCast.h + NarrowPhaseCollision/btConvexPenetrationDepthSolver.h + NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h + NarrowPhaseCollision/btGjkConvexCast.h + NarrowPhaseCollision/btGjkEpa2.h + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h + NarrowPhaseCollision/btGjkPairDetector.h + NarrowPhaseCollision/btManifoldPoint.h + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h + NarrowPhaseCollision/btPersistentManifold.h + NarrowPhaseCollision/btPointCollector.h + NarrowPhaseCollision/btRaycastCallback.h + NarrowPhaseCollision/btSimplexSolverInterface.h + NarrowPhaseCollision/btSubSimplexConvexCast.h + NarrowPhaseCollision/btVoronoiSimplexSolver.h + NarrowPhaseCollision/btPolyhedralContactClipping.h +) + +SET(BulletCollision_HDRS + ${Root_HDRS} + ${BroadphaseCollision_HDRS} + ${CollisionDispatch_HDRS} + ${CollisionShapes_HDRS} + ${Gimpact_HDRS} + ${NarrowPhaseCollision_HDRS} +) + + +ADD_LIBRARY(BulletCollision ${BulletCollision_SRCS} ${BulletCollision_HDRS}) +SET_TARGET_PROPERTIES(BulletCollision PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletCollision PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletCollision LinearMath) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletCollision DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletCollision RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + INSTALL(FILES ../btBulletCollisionCommon.h +DESTINATION ${INCLUDE_INSTALL_DIR}/BulletCollision) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletCollision PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(BulletCollision PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision) + SET_PROPERTY(SOURCE ${CollisionDispatch_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionDispatch) + SET_PROPERTY(SOURCE ${CollisionShapes_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionShapes) + SET_PROPERTY(SOURCE ${Gimpact_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Gimpact) + SET_PROPERTY(SOURCE ${NarrowPhaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/NarrowPhaseCollision) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp new file mode 100644 index 00000000..63401780 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -0,0 +1,200 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btScalar.h" +#include "SphereTriangleDetector.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + + +SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold) +:m_sphere(sphere), +m_triangle(triangle), +m_contactBreakingThreshold(contactBreakingThreshold) +{ + +} + +void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) +{ + + (void)debugDraw; + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + btVector3 point,normal; + btScalar timeOfImpact = btScalar(1.); + btScalar depth = btScalar(0.); +// output.m_distance = btScalar(BT_LARGE_FLOAT); + //move sphere into triangle space + btTransform sphereInTr = transformB.inverseTimes(transformA); + + if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold)) + { + if (swapResults) + { + btVector3 normalOnB = transformB.getBasis()*normal; + btVector3 normalOnA = -normalOnB; + btVector3 pointOnA = transformB*point+normalOnB*depth; + output.addContactPoint(normalOnA,pointOnA,depth); + } else + { + output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + } + } + +} + + + +// See also geometrictools.com +// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest); + +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { + btVector3 diff = p - from; + btVector3 v = to - from; + btScalar t = v.dot(diff); + + if (t > 0) { + btScalar dotVV = v.dot(v); + if (t < dotVV) { + t /= dotVV; + diff -= t*v; + } else { + t = 1; + diff -= v; + } + } else + t = 0; + + nearest = from + t*v; + return diff.dot(diff); +} + +bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) { + btVector3 lp(p); + btVector3 lnormal(normal); + + return pointInTriangle(vertices, lnormal, &lp); +} + +bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold) +{ + + const btVector3* vertices = &m_triangle->getVertexPtr(0); + + btScalar radius = m_sphere->getRadius(); + btScalar radiusWithThreshold = radius + contactBreakingThreshold; + + btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); + normal.normalize(); + btVector3 p1ToCentre = sphereCenter - vertices[0]; + btScalar distanceFromPlane = p1ToCentre.dot(normal); + + if (distanceFromPlane < btScalar(0.)) + { + //triangle facing the other way + distanceFromPlane *= btScalar(-1.); + normal *= btScalar(-1.); + } + + bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold; + + // Check for contact / intersection + bool hasContact = false; + btVector3 contactPoint; + if (isInsideContactPlane) { + if (facecontains(sphereCenter,vertices,normal)) { + // Inside the contact wedge - touches a point on the shell plane + hasContact = true; + contactPoint = sphereCenter - normal*distanceFromPlane; + } else { + // Could be inside one of the contact capsules + btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold; + btVector3 nearestOnEdge; + for (int i = 0; i < m_triangle->getNumEdges(); i++) { + + btVector3 pa; + btVector3 pb; + + m_triangle->getEdge(i,pa,pb); + + btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge); + if (distanceSqr < contactCapsuleRadiusSqr) { + // Yep, we're inside a capsule + hasContact = true; + contactPoint = nearestOnEdge; + } + + } + } + } + + if (hasContact) { + btVector3 contactToCentre = sphereCenter - contactPoint; + btScalar distanceSqr = contactToCentre.length2(); + + if (distanceSqr < radiusWithThreshold*radiusWithThreshold) + { + if (distanceSqr>SIMD_EPSILON) + { + btScalar distance = btSqrt(distanceSqr); + resultNormal = contactToCentre; + resultNormal.normalize(); + point = contactPoint; + depth = -(radius-distance); + } else + { + resultNormal = normal; + point = contactPoint; + depth = -radius; + } + return true; + } + } + + return false; +} + + +bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ) +{ + const btVector3* p1 = &vertices[0]; + const btVector3* p2 = &vertices[1]; + const btVector3* p3 = &vertices[2]; + + btVector3 edge1( *p2 - *p1 ); + btVector3 edge2( *p3 - *p2 ); + btVector3 edge3( *p1 - *p3 ); + + btVector3 p1_to_p( *p - *p1 ); + btVector3 p2_to_p( *p - *p2 ); + btVector3 p3_to_p( *p - *p3 ); + + btVector3 edge1_normal( edge1.cross(normal)); + btVector3 edge2_normal( edge2.cross(normal)); + btVector3 edge3_normal( edge3.cross(normal)); + + btScalar r1, r2, r3; + r1 = edge1_normal.dot( p1_to_p ); + r2 = edge2_normal.dot( p2_to_p ); + r3 = edge3_normal.dot( p3_to_p ); + if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) || + ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) ) + return true; + return false; + +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h new file mode 100644 index 00000000..22953af4 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_TRIANGLE_DETECTOR_H +#define BT_SPHERE_TRIANGLE_DETECTOR_H + +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + + + +class btSphereShape; +class btTriangleShape; + + + +/// sphere-triangle to match the btDiscreteCollisionDetectorInterface +struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface +{ + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + + SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold); + + virtual ~SphereTriangleDetector() {}; + + bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold); + +private: + + + bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ); + bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal); + + btSphereShape* m_sphere; + btTriangleShape* m_triangle; + btScalar m_contactBreakingThreshold; + +}; +#endif //BT_SPHERE_TRIANGLE_DETECTOR_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp new file mode 100644 index 00000000..57f14649 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp @@ -0,0 +1,47 @@ +/* +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 "btActivatingCollisionAlgorithm.h" +#include "btCollisionDispatcher.h" +#include "btCollisionObject.h" + +btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci) +:btCollisionAlgorithm(ci) +//, +//m_colObj0(0), +//m_colObj1(0) +{ +} +btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ) +:btCollisionAlgorithm(ci) +//, +//m_colObj0(0), +//m_colObj1(0) +{ +// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1)) +// { +// m_colObj0 = colObj0; +// m_colObj1 = colObj1; +// +// m_colObj0->activate(); +// m_colObj1->activate(); +// } +} + +btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm() +{ +// m_colObj0->activate(); +// m_colObj1->activate(); +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h new file mode 100644 index 00000000..489812b9 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h @@ -0,0 +1,36 @@ +/* +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 __BT_ACTIVATING_COLLISION_ALGORITHM_H +#define __BT_ACTIVATING_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +///This class is not enabled yet (work-in-progress) to more aggressively activate objects. +class btActivatingCollisionAlgorithm : public btCollisionAlgorithm +{ +// btCollisionObject* m_colObj0; +// btCollisionObject* m_colObj1; + +public: + + btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci); + + btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btActivatingCollisionAlgorithm(); + +}; +#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp new file mode 100644 index 00000000..2c362778 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp @@ -0,0 +1,421 @@ +/* +Bullet Continuous Collision Detection and Physics Library +* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.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. +*/ + +///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library. +///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross + +#include "btBox2dBox2dCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h" +#include "BulletCollision/CollisionShapes/btBox2dShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap) +: btActivatingCollisionAlgorithm(ci,obj0Wrap,obj1Wrap), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject())) + { + m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject()); + m_ownManifold = true; + } +} + +btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm() +{ + + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } + +} + + +void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB); + +//#include +void btBox2dBox2dCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + + const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape(); + const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape(); + + resultOut->setPersistentManifold(m_manifoldPtr); + + b2CollidePolygons(resultOut,box0,body0Wrap->getWorldTransform(),box1,body1Wrap->getWorldTransform()); + + // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + +btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} + + +struct ClipVertex +{ + btVector3 v; + int id; + //b2ContactID id; + //b2ContactID id; +}; + +#define b2Dot(a,b) (a).dot(b) +#define b2Mul(a,b) (a)*(b) +#define b2MulT(a,b) (a).transpose()*(b) +#define b2Cross(a,b) (a).cross(b) +#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f) + +int b2_maxManifoldPoints =2; + +static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2], + const btVector3& normal, btScalar offset) +{ + // Start with no output points + int numOut = 0; + + // Calculate the distance of end points to the line + btScalar distance0 = b2Dot(normal, vIn[0].v) - offset; + btScalar distance1 = b2Dot(normal, vIn[1].v) - offset; + + // If the points are behind the plane + if (distance0 <= 0.0f) vOut[numOut++] = vIn[0]; + if (distance1 <= 0.0f) vOut[numOut++] = vIn[1]; + + // If the points are on different sides of the plane + if (distance0 * distance1 < 0.0f) + { + // Find intersection point of edge and plane + btScalar interp = distance0 / (distance0 - distance1); + vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v); + if (distance0 > 0.0f) + { + vOut[numOut].id = vIn[0].id; + } + else + { + vOut[numOut].id = vIn[1].id; + } + ++numOut; + } + + return numOut; +} + +// Find the separation between poly1 and poly2 for a give edge normal on poly1. +static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1, + const btBox2dShape* poly2, const btTransform& xf2) +{ + const btVector3* vertices1 = poly1->getVertices(); + const btVector3* normals1 = poly1->getNormals(); + + int count2 = poly2->getVertexCount(); + const btVector3* vertices2 = poly2->getVertices(); + + btAssert(0 <= edge1 && edge1 < poly1->getVertexCount()); + + // Convert normal from poly1's frame into poly2's frame. + btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]); + btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World); + + // Find support vertex on poly2 for -normal. + int index = 0; + btScalar minDot = BT_LARGE_FLOAT; + + if( count2 > 0 ) + index = (int) normal1.minDot( vertices2, count2, minDot); + + btVector3 v1 = b2Mul(xf1, vertices1[edge1]); + btVector3 v2 = b2Mul(xf2, vertices2[index]); + btScalar separation = b2Dot(v2 - v1, normal1World); + return separation; +} + +// Find the max separation between poly1 and poly2 using edge normals from poly1. +static btScalar FindMaxSeparation(int* edgeIndex, + const btBox2dShape* poly1, const btTransform& xf1, + const btBox2dShape* poly2, const btTransform& xf2) +{ + int count1 = poly1->getVertexCount(); + const btVector3* normals1 = poly1->getNormals(); + + // Vector pointing from the centroid of poly1 to the centroid of poly2. + btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid()); + btVector3 dLocal1 = b2MulT(xf1.getBasis(), d); + + // Find edge normal on poly1 that has the largest projection onto d. + int edge = 0; + btScalar maxDot; + if( count1 > 0 ) + edge = (int) dLocal1.maxDot( normals1, count1, maxDot); + + // Get the separation for the edge normal. + btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); + if (s > 0.0f) + { + return s; + } + + // Check the separation for the previous edge normal. + int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1; + btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2); + if (sPrev > 0.0f) + { + return sPrev; + } + + // Check the separation for the next edge normal. + int nextEdge = edge + 1 < count1 ? edge + 1 : 0; + btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2); + if (sNext > 0.0f) + { + return sNext; + } + + // Find the best edge and the search direction. + int bestEdge; + btScalar bestSeparation; + int increment; + if (sPrev > s && sPrev > sNext) + { + increment = -1; + bestEdge = prevEdge; + bestSeparation = sPrev; + } + else if (sNext > s) + { + increment = 1; + bestEdge = nextEdge; + bestSeparation = sNext; + } + else + { + *edgeIndex = edge; + return s; + } + + // Perform a local search for the best edge normal. + for ( ; ; ) + { + if (increment == -1) + edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1; + else + edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0; + + s = EdgeSeparation(poly1, xf1, edge, poly2, xf2); + if (s > 0.0f) + { + return s; + } + + if (s > bestSeparation) + { + bestEdge = edge; + bestSeparation = s; + } + else + { + break; + } + } + + *edgeIndex = bestEdge; + return bestSeparation; +} + +static void FindIncidentEdge(ClipVertex c[2], + const btBox2dShape* poly1, const btTransform& xf1, int edge1, + const btBox2dShape* poly2, const btTransform& xf2) +{ + const btVector3* normals1 = poly1->getNormals(); + + int count2 = poly2->getVertexCount(); + const btVector3* vertices2 = poly2->getVertices(); + const btVector3* normals2 = poly2->getNormals(); + + btAssert(0 <= edge1 && edge1 < poly1->getVertexCount()); + + // Get the normal of the reference edge in poly2's frame. + btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1])); + + // Find the incident edge on poly2. + int index = 0; + btScalar minDot = BT_LARGE_FLOAT; + for (int i = 0; i < count2; ++i) + { + btScalar dot = b2Dot(normal1, normals2[i]); + if (dot < minDot) + { + minDot = dot; + index = i; + } + } + + // Build the clip vertices for the incident edge. + int i1 = index; + int i2 = i1 + 1 < count2 ? i1 + 1 : 0; + + c[0].v = b2Mul(xf2, vertices2[i1]); +// c[0].id.features.referenceEdge = (unsigned char)edge1; +// c[0].id.features.incidentEdge = (unsigned char)i1; +// c[0].id.features.incidentVertex = 0; + + c[1].v = b2Mul(xf2, vertices2[i2]); +// c[1].id.features.referenceEdge = (unsigned char)edge1; +// c[1].id.features.incidentEdge = (unsigned char)i2; +// c[1].id.features.incidentVertex = 1; +} + +// Find edge normal of max separation on A - return if separating axis is found +// Find edge normal of max separation on B - return if separation axis is found +// Choose reference edge as min(minA, minB) +// Find incident edge +// Clip + +// The normal points from 1 to 2 +void b2CollidePolygons(btManifoldResult* manifold, + const btBox2dShape* polyA, const btTransform& xfA, + const btBox2dShape* polyB, const btTransform& xfB) +{ + + int edgeA = 0; + btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB); + if (separationA > 0.0f) + return; + + int edgeB = 0; + btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA); + if (separationB > 0.0f) + return; + + const btBox2dShape* poly1; // reference poly + const btBox2dShape* poly2; // incident poly + btTransform xf1, xf2; + int edge1; // reference edge + unsigned char flip; + const btScalar k_relativeTol = 0.98f; + const btScalar k_absoluteTol = 0.001f; + + // TODO_ERIN use "radius" of poly for absolute tolerance. + if (separationB > k_relativeTol * separationA + k_absoluteTol) + { + poly1 = polyB; + poly2 = polyA; + xf1 = xfB; + xf2 = xfA; + edge1 = edgeB; + flip = 1; + } + else + { + poly1 = polyA; + poly2 = polyB; + xf1 = xfA; + xf2 = xfB; + edge1 = edgeA; + flip = 0; + } + + ClipVertex incidentEdge[2]; + FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2); + + int count1 = poly1->getVertexCount(); + const btVector3* vertices1 = poly1->getVertices(); + + btVector3 v11 = vertices1[edge1]; + btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0]; + + //btVector3 dv = v12 - v11; + btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11); + sideNormal.normalize(); + btVector3 frontNormal = btCrossS(sideNormal, 1.0f); + + + v11 = b2Mul(xf1, v11); + v12 = b2Mul(xf1, v12); + + btScalar frontOffset = b2Dot(frontNormal, v11); + btScalar sideOffset1 = -b2Dot(sideNormal, v11); + btScalar sideOffset2 = b2Dot(sideNormal, v12); + + // Clip incident edge against extruded edge1 side edges. + ClipVertex clipPoints1[2]; + clipPoints1[0].v.setValue(0,0,0); + clipPoints1[1].v.setValue(0,0,0); + + ClipVertex clipPoints2[2]; + clipPoints2[0].v.setValue(0,0,0); + clipPoints2[1].v.setValue(0,0,0); + + + int np; + + // Clip to box side 1 + np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1); + + if (np < 2) + return; + + // Clip to negative box side 1 + np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2); + + if (np < 2) + { + return; + } + + // Now clipPoints2 contains the clipped points. + btVector3 manifoldNormal = flip ? -frontNormal : frontNormal; + + int pointCount = 0; + for (int i = 0; i < b2_maxManifoldPoints; ++i) + { + btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset; + + if (separation <= 0.0f) + { + + //b2ManifoldPoint* cp = manifold->points + pointCount; + //btScalar separation = separation; + //cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v); + //cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v); + + manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation); + +// cp->id = clipPoints2[i].id; +// cp->id.features.flip = flip; + ++pointCount; + } + } + +// manifold->pointCount = pointCount;} +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h new file mode 100644 index 00000000..6ea6e89b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H +#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; + +///box-box collision detection +class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btBox2dBox2dCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0Wrap,body1Wrap); + } + }; + +}; + +#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp new file mode 100644 index 00000000..ac68968f --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btBoxBoxDetector.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" +#define USE_PERSISTENT_CONTACTS 1 + +btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject())) + { + m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + m_ownManifold = true; + } +} + +btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + + const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape(); + const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape(); + + + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); +#ifndef USE_PERSISTENT_CONTACTS + m_manifoldPtr->clearManifold(); +#endif //USE_PERSISTENT_CONTACTS + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = BT_LARGE_FLOAT; + input.m_transformA = body0Wrap->getWorldTransform(); + input.m_transformB = body1Wrap->getWorldTransform(); + + btBoxBoxDetector detector(box0,box1); + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + +#ifdef USE_PERSISTENT_CONTACTS + // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } +#endif //USE_PERSISTENT_CONTACTS + +} + +btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h new file mode 100644 index 00000000..59808df5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BOX_BOX__COLLISION_ALGORITHM_H +#define BT_BOX_BOX__COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; + +///box-box collision detection +class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btBoxBoxCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + int bbsize = sizeof(btBoxBoxCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap); + } + }; + +}; + +#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp new file mode 100644 index 00000000..7043bde3 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp @@ -0,0 +1,718 @@ +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + Bullet Continuous Collision Detection and Physics Library + Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///ODE box-box collision detection is adapted to work with Bullet + +#include "btBoxBoxDetector.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" + +#include +#include + +btBoxBoxDetector::btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2) +: m_box1(box1), +m_box2(box2) +{ + +} + + +// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and +// generate contact points. this returns 0 if there is no contact otherwise +// it returns the number of contacts generated. +// `normal' returns the contact normal. +// `depth' returns the maximum penetration depth along that normal. +// `return_code' returns a number indicating the type of contact that was +// detected: +// 1,2,3 = box 2 intersects with a face of box 1 +// 4,5,6 = box 1 intersects with a face of box 2 +// 7..15 = edge-edge contact +// `maxc' is the maximum number of contacts allowed to be generated, i.e. +// the size of the `contact' array. +// `contact' and `skip' are the contact array information provided to the +// collision functions. this function only fills in the position and depth +// fields. +struct dContactGeom; +#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) +#define dInfinity FLT_MAX + + +/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); } +PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); } +PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); } +*/ +static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); } +static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); } +static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); } +#define dMULTIPLYOP1_331(A,op,B,C) \ +{\ + (A)[0] op dDOT41((B),(C)); \ + (A)[1] op dDOT41((B+1),(C)); \ + (A)[2] op dDOT41((B+2),(C)); \ +} + +#define dMULTIPLYOP0_331(A,op,B,C) \ +{ \ + (A)[0] op dDOT((B),(C)); \ + (A)[1] op dDOT((B+4),(C)); \ + (A)[2] op dDOT((B+8),(C)); \ +} + +#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) +#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) + +typedef btScalar dMatrix3[4*3]; + +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta); +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta) +{ + btVector3 p; + p[0] = pb[0] - pa[0]; + p[1] = pb[1] - pa[1]; + p[2] = pb[2] - pa[2]; + btScalar uaub = dDOT(ua,ub); + btScalar q1 = dDOT(ua,p); + btScalar q2 = -dDOT(ub,p); + btScalar d = 1-uaub*uaub; + if (d <= btScalar(0.0001f)) { + // @@@ this needs to be made more robust + *alpha = 0; + *beta = 0; + } + else { + d = 1.f/d; + *alpha = (q1 + uaub*q2)*d; + *beta = (uaub*q1 + q2)*d; + } +} + + + +// find all the intersection points between the 2D rectangle with vertices +// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), +// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). +// +// the intersection points are returned as x,y pairs in the 'ret' array. +// the number of intersection points is returned by the function (this will +// be in the range 0 to 8). + +static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16]) +{ + // q (and r) contain nq (and nr) coordinate points for the current (and + // chopped) polygons + int nq=4,nr=0; + btScalar buffer[16]; + btScalar *q = p; + btScalar *r = ret; + for (int dir=0; dir <= 1; dir++) { + // direction notation: xy[0] = x axis, xy[1] = y axis + for (int sign=-1; sign <= 1; sign += 2) { + // chop q along the line xy[dir] = sign*h[dir] + btScalar *pq = q; + btScalar *pr = r; + nr = 0; + for (int i=nq; i > 0; i--) { + // go through all points in q and all lines between adjacent points + if (sign*pq[dir] < h[dir]) { + // this point is inside the chopping line + pr[0] = pq[0]; + pr[1] = pq[1]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + btScalar *nextq = (i > 1) ? pq+2 : q; + if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { + // this line crosses the chopping line + pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / + (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); + pr[dir] = sign*h[dir]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + pq += 2; + } + q = r; + r = (q==ret) ? buffer : ret; + nq = nr; + } + } + done: + if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar)); + return nr; +} + + +#define M__PI 3.14159265f + +// given n points in the plane (array p, of size 2*n), generate m points that +// best represent the whole set. the definition of 'best' here is not +// predetermined - the idea is to select points that give good box-box +// collision detection behavior. the chosen point indexes are returned in the +// array iret (of size m). 'i0' is always the first entry in the array. +// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be +// in the range [0..n-1]. + +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]); +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) +{ + // compute the centroid of the polygon in cx,cy + int i,j; + btScalar a,cx,cy,q; + if (n==1) { + cx = p[0]; + cy = p[1]; + } + else if (n==2) { + cx = btScalar(0.5)*(p[0] + p[2]); + cy = btScalar(0.5)*(p[1] + p[3]); + } + else { + a = 0; + cx = 0; + cy = 0; + for (i=0; i<(n-1); i++) { + q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; + a += q; + cx += q*(p[i*2]+p[i*2+2]); + cy += q*(p[i*2+1]+p[i*2+3]); + } + q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; + if (btFabs(a+q) > SIMD_EPSILON) + { + a = 1.f/(btScalar(3.0)*(a+q)); + } else + { + a=BT_LARGE_FLOAT; + } + cx = a*(cx + q*(p[n*2-2]+p[0])); + cy = a*(cy + q*(p[n*2-1]+p[1])); + } + + // compute the angle of each point w.r.t. the centroid + btScalar A[8]; + for (i=0; i M__PI) a -= 2*M__PI; + btScalar maxdiff=1e9,diff; + + *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0 + + for (i=0; i M__PI) diff = 2*M__PI - diff; + if (diff < maxdiff) { + maxdiff = diff; + *iret = i; + } + } + } +#if defined(DEBUG) || defined (_DEBUG) + btAssert (*iret != i0); // ensure iret got set +#endif + avail[*iret] = 0; + iret++; + } +} + + + +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output); +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output) +{ + const btScalar fudge_factor = btScalar(1.05); + btVector3 p,pp,normalC(0.f,0.f,0.f); + const btScalar *normalR = 0; + btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, + Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l; + int i,j,invert_normal,code; + + // get vector from centers of box 1 to box 2, relative to box 1 + p = p2 - p1; + dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1 + + // get side lengths / 2 + A[0] = side1[0]*btScalar(0.5); + A[1] = side1[1]*btScalar(0.5); + A[2] = side1[2]*btScalar(0.5); + B[0] = side2[0]*btScalar(0.5); + B[1] = side2[1]*btScalar(0.5); + B[2] = side2[2]*btScalar(0.5); + + // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 + R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); + R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); + R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); + + Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13); + Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23); + Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33); + + // for all 15 possible separating axes: + // * see if the axis separates the boxes. if so, return 0. + // * find the depth of the penetration along the separating axis (s2) + // * if this is the largest depth so far, record it. + // the normal vector will be set to the separating axis with the smallest + // depth. note: normalR is set to point to a column of R1 or R2 if that is + // the smallest depth normal so far. otherwise normalR is 0 and normalC is + // set to a vector relative to body 1. invert_normal is 1 if the sign of + // the normal should be flipped. + +#define TST(expr1,expr2,norm,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > 0) return 0; \ + if (s2 > s) { \ + s = s2; \ + normalR = norm; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } + + s = -dInfinity; + invert_normal = 0; + code = 0; + + // separating axis = u1,u2,u3 + TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); + TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); + TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); + + // separating axis = v1,v2,v3 + TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); + TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); + TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); + + // note: cross product axes need to be scaled when s is computed. + // normal (n1,n2,n3) is relative to box 1. +#undef TST +#define TST(expr1,expr2,n1,n2,n3,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > SIMD_EPSILON) return 0; \ + l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ + if (l > SIMD_EPSILON) { \ + s2 /= l; \ + if (s2*fudge_factor > s) { \ + s = s2; \ + normalR = 0; \ + normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } \ + } + + btScalar fudge2 (1.0e-5f); + + Q11 += fudge2; + Q12 += fudge2; + Q13 += fudge2; + + Q21 += fudge2; + Q22 += fudge2; + Q23 += fudge2; + + Q31 += fudge2; + Q32 += fudge2; + Q33 += fudge2; + + // separating axis = u1 x (v1,v2,v3) + TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); + TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); + TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); + + // separating axis = u2 x (v1,v2,v3) + TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); + TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); + TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); + + // separating axis = u3 x (v1,v2,v3) + TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); + TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); + TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); + +#undef TST + + if (!code) return 0; + + // if we get to this point, the boxes interpenetrate. compute the normal + // in global coordinates. + if (normalR) { + normal[0] = normalR[0]; + normal[1] = normalR[4]; + normal[2] = normalR[8]; + } + else { + dMULTIPLY0_331 (normal,R1,normalC); + } + if (invert_normal) { + normal[0] = -normal[0]; + normal[1] = -normal[1]; + normal[2] = -normal[2]; + } + *depth = -s; + + // compute contact point(s) + + if (code > 6) { + // an edge from box 1 touches an edge from box 2. + // find a point pa on the intersecting edge of box 1 + btVector3 pa; + btScalar sign; + for (i=0; i<3; i++) pa[i] = p1[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0); + for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; + } + + // find a point pb on the intersecting edge of box 2 + btVector3 pb; + for (i=0; i<3; i++) pb[i] = p2[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0); + for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; + } + + btScalar alpha,beta; + btVector3 ua,ub; + for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; + for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; + + dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); + for (i=0; i<3; i++) pa[i] += ua[i]*alpha; + for (i=0; i<3; i++) pb[i] += ub[i]*beta; + + { + + //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]); + //contact[0].depth = *depth; + btVector3 pointInWorld; + +#ifdef USE_CENTER_POINT + for (i=0; i<3; i++) + pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5); + output.addContactPoint(-normal,pointInWorld,-*depth); +#else + output.addContactPoint(-normal,pb,-*depth); + +#endif // + *return_code = code; + } + return 1; + } + + // okay, we have a face-something intersection (because the separating + // axis is perpendicular to a face). define face 'a' to be the reference + // face (i.e. the normal vector is perpendicular to this) and face 'b' to be + // the incident face (the closest face of the other box). + + const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb; + if (code <= 3) { + Ra = R1; + Rb = R2; + pa = p1; + pb = p2; + Sa = A; + Sb = B; + } + else { + Ra = R2; + Rb = R1; + pa = p2; + pb = p1; + Sa = B; + Sb = A; + } + + // nr = normal vector of reference face dotted with axes of incident box. + // anr = absolute values of nr. + btVector3 normal2,nr,anr; + if (code <= 3) { + normal2[0] = normal[0]; + normal2[1] = normal[1]; + normal2[2] = normal[2]; + } + else { + normal2[0] = -normal[0]; + normal2[1] = -normal[1]; + normal2[2] = -normal[2]; + } + dMULTIPLY1_331 (nr,Rb,normal2); + anr[0] = btFabs (nr[0]); + anr[1] = btFabs (nr[1]); + anr[2] = btFabs (nr[2]); + + // find the largest compontent of anr: this corresponds to the normal + // for the indident face. the other axis numbers of the indicent face + // are stored in a1,a2. + int lanr,a1,a2; + if (anr[1] > anr[0]) { + if (anr[1] > anr[2]) { + a1 = 0; + lanr = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + else { + if (anr[0] > anr[2]) { + lanr = 0; + a1 = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + + // compute center point of incident face, in reference-face coordinates + btVector3 center; + if (nr[lanr] < 0) { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; + } + else { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; + } + + // find the normal and non-normal axis numbers of the reference box + int codeN,code1,code2; + if (code <= 3) codeN = code-1; else codeN = code-4; + if (codeN==0) { + code1 = 1; + code2 = 2; + } + else if (codeN==1) { + code1 = 0; + code2 = 2; + } + else { + code1 = 0; + code2 = 1; + } + + // find the four corners of the incident face, in reference-face coordinates + btScalar quad[8]; // 2D coordinate of incident face (x,y pairs) + btScalar c1,c2,m11,m12,m21,m22; + c1 = dDOT14 (center,Ra+code1); + c2 = dDOT14 (center,Ra+code2); + // optimize this? - we have already computed this data above, but it is not + // stored in an easy-to-index format. for now it's quicker just to recompute + // the four dot products. + m11 = dDOT44 (Ra+code1,Rb+a1); + m12 = dDOT44 (Ra+code1,Rb+a2); + m21 = dDOT44 (Ra+code2,Rb+a1); + m22 = dDOT44 (Ra+code2,Rb+a2); + { + btScalar k1 = m11*Sb[a1]; + btScalar k2 = m21*Sb[a1]; + btScalar k3 = m12*Sb[a2]; + btScalar k4 = m22*Sb[a2]; + quad[0] = c1 - k1 - k3; + quad[1] = c2 - k2 - k4; + quad[2] = c1 - k1 + k3; + quad[3] = c2 - k2 + k4; + quad[4] = c1 + k1 + k3; + quad[5] = c2 + k2 + k4; + quad[6] = c1 + k1 - k3; + quad[7] = c2 + k2 - k4; + } + + // find the size of the reference face + btScalar rect[2]; + rect[0] = Sa[code1]; + rect[1] = Sa[code2]; + + // intersect the incident and reference faces + btScalar ret[16]; + int n = intersectRectQuad2 (rect,quad,ret); + if (n < 1) return 0; // this should never happen + + // convert the intersection points into reference-face coordinates, + // and compute the contact position and depth for each point. only keep + // those points that have a positive (penetrating) depth. delete points in + // the 'ret' array as necessary so that 'point' and 'ret' correspond. + btScalar point[3*8]; // penetrating contact points + btScalar dep[8]; // depths for those points + btScalar det1 = 1.f/(m11*m22 - m12*m21); + m11 *= det1; + m12 *= det1; + m21 *= det1; + m22 *= det1; + int cnum = 0; // number of penetrating contact points found + for (j=0; j < n; j++) { + btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); + btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); + for (i=0; i<3; i++) point[cnum*3+i] = + center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; + dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3); + if (dep[cnum] >= 0) { + ret[cnum*2] = ret[j*2]; + ret[cnum*2+1] = ret[j*2+1]; + cnum++; + } + } + if (cnum < 1) return 0; // this should never happen + + // we can't generate more contacts than we actually have + if (maxc > cnum) maxc = cnum; + if (maxc < 1) maxc = 1; + + if (cnum <= maxc) { + + if (code<4) + { + // we have less contacts than we need, so we use them all + for (j=0; j < cnum; j++) + { + btVector3 pointInWorld; + for (i=0; i<3; i++) + pointInWorld[i] = point[j*3+i] + pa[i]; + output.addContactPoint(-normal,pointInWorld,-dep[j]); + + } + } else + { + // we have less contacts than we need, so we use them all + for (j=0; j < cnum; j++) + { + btVector3 pointInWorld; + for (i=0; i<3; i++) + pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j]; + //pointInWorld[i] = point[j*3+i] + pa[i]; + output.addContactPoint(-normal,pointInWorld,-dep[j]); + } + } + } + else { + // we have more contacts than are wanted, some of them must be culled. + // find the deepest point, it is always the first contact. + int i1 = 0; + btScalar maxdepth = dep[0]; + for (i=1; i maxdepth) { + maxdepth = dep[i]; + i1 = i; + } + } + + int iret[8]; + cullPoints2 (cnum,ret,maxc,i1,iret); + + for (j=0; j < maxc; j++) { +// dContactGeom *con = CONTACT(contact,skip*j); + // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; + // con->depth = dep[iret[j]]; + + btVector3 posInWorld; + for (i=0; i<3; i++) + posInWorld[i] = point[iret[j]*3+i] + pa[i]; + if (code<4) + { + output.addContactPoint(-normal,posInWorld,-dep[iret[j]]); + } else + { + output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]); + } + } + cnum = maxc; + } + + *return_code = code; + return cnum; +} + +void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/) +{ + + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + int skip = 0; + dContactGeom *contact = 0; + + dMatrix3 R1; + dMatrix3 R2; + + for (int j=0;j<3;j++) + { + R1[0+4*j] = transformA.getBasis()[j].x(); + R2[0+4*j] = transformB.getBasis()[j].x(); + + R1[1+4*j] = transformA.getBasis()[j].y(); + R2[1+4*j] = transformB.getBasis()[j].y(); + + + R1[2+4*j] = transformA.getBasis()[j].z(); + R2[2+4*j] = transformB.getBasis()[j].z(); + + } + + + + btVector3 normal; + btScalar depth; + int return_code; + int maxc = 4; + + + dBoxBox2 (transformA.getOrigin(), + R1, + 2.f*m_box1->getHalfExtentsWithMargin(), + transformB.getOrigin(), + R2, + 2.f*m_box2->getHalfExtentsWithMargin(), + normal, &depth, &return_code, + maxc, contact, skip, + output + ); + +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h new file mode 100644 index 00000000..39243777 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h @@ -0,0 +1,44 @@ +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_BOX_BOX_DETECTOR_H +#define BT_BOX_BOX_DETECTOR_H + + +class btBoxShape; +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + + +/// btBoxBoxDetector wraps the ODE box-box collision detector +/// re-distributed under the Zlib license with permission from Russell L. Smith +struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface +{ + const btBoxShape* m_box1; + const btBoxShape* m_box2; + +public: + + btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2); + + virtual ~btBoxBoxDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + +}; + +#endif //BT_BOX_BOX_DETECTOR_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h new file mode 100644 index 00000000..66949849 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_CONFIGURATION +#define BT_COLLISION_CONFIGURATION + +struct btCollisionAlgorithmCreateFunc; + +class btPoolAllocator; + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator size, default collision algorithms and persistent manifold pool size +///@todo: describe the meaning +class btCollisionConfiguration +{ + +public: + + virtual ~btCollisionConfiguration() + { + } + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() = 0; + + virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; + + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; + +}; + +#endif //BT_COLLISION_CONFIGURATION + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h new file mode 100644 index 00000000..62ee66c4 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -0,0 +1,45 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_CREATE_FUNC +#define BT_COLLISION_CREATE_FUNC + +#include "LinearMath/btAlignedObjectArray.h" +class btCollisionAlgorithm; +class btCollisionObject; +struct btCollisionObjectWrapper; +struct btCollisionAlgorithmConstructionInfo; + +///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm +struct btCollisionAlgorithmCreateFunc +{ + bool m_swapped; + + btCollisionAlgorithmCreateFunc() + :m_swapped(false) + { + } + virtual ~btCollisionAlgorithmCreateFunc(){}; + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + + (void)body0Wrap; + (void)body1Wrap; + return 0; + } +}; +#endif //BT_COLLISION_CREATE_FUNC + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp new file mode 100644 index 00000000..669d0b6b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -0,0 +1,314 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "btCollisionDispatcher.h" + + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btPoolAllocator.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +int gNumManifold = 0; + +#ifdef BT_DEBUG +#include +#endif + + +btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): +m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD), + m_collisionConfiguration(collisionConfiguration) +{ + int i; + + setNearCallback(defaultNearCallback); + + m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool(); + + m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); + + for (i=0;igetCollisionAlgorithmCreateFunc(i,j); + btAssert(m_doubleDispatch[i][j]); + } + } + + +} + + +void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) +{ + m_doubleDispatch[proxyType0][proxyType1] = createFunc; +} + +btCollisionDispatcher::~btCollisionDispatcher() +{ +} + +btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1) +{ + gNumManifold++; + + //btAssert(gNumManifold < 65535); + + + + //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance) + + btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? + btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold)) + : gContactBreakingThreshold ; + + btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold()); + + void* mem = 0; + + if (m_persistentManifoldPoolAllocator->getFreeCount()) + { + mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); + } else + { + //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert. + if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0) + { + mem = btAlignedAlloc(sizeof(btPersistentManifold),16); + } else + { + btAssert(0); + //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration + return 0; + } + } + btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold); + manifold->m_index1a = m_manifoldsPtr.size(); + m_manifoldsPtr.push_back(manifold); + + return manifold; +} + +void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold) +{ + manifold->clearManifold(); +} + + +void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) +{ + + gNumManifold--; + + //printf("releaseManifold: gNumManifold %d\n",gNumManifold); + clearManifold(manifold); + + int findIndex = manifold->m_index1a; + btAssert(findIndex < m_manifoldsPtr.size()); + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr[findIndex]->m_index1a = findIndex; + m_manifoldsPtr.pop_back(); + + manifold->~btPersistentManifold(); + if (m_persistentManifoldPoolAllocator->validPtr(manifold)) + { + m_persistentManifoldPoolAllocator->freeMemory(manifold); + } else + { + btAlignedFree(manifold); + } + +} + + + +btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold) +{ + + btCollisionAlgorithmConstructionInfo ci; + + ci.m_dispatcher1 = this; + ci.m_manifold = sharedManifold; + btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap); + + return algo; +} + + + + +bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1) +{ + //here you can do filtering + bool hasResponse = + (body0->hasContactResponse() && body1->hasContactResponse()); + //no response between two static/kinematic bodies: + hasResponse = hasResponse && + ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject())); + return hasResponse; +} + +bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) +{ + btAssert(body0); + btAssert(body1); + + bool needsCollision = true; + +#ifdef BT_DEBUG + if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED)) + { + //broadphase filtering already deals with this + if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject()) + { + m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED; + printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + } + } +#endif //BT_DEBUG + + if ((!body0->isActive()) && (!body1->isActive())) + needsCollision = false; + else if (!body0->checkCollideWith(body1)) + needsCollision = false; + + return needsCollision ; + +} + + + +///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) +///this is useful for the collision dispatcher. +class btCollisionPairCallback : public btOverlapCallback +{ + const btDispatcherInfo& m_dispatchInfo; + btCollisionDispatcher* m_dispatcher; + +public: + + btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + :m_dispatchInfo(dispatchInfo), + m_dispatcher(dispatcher) + { + } + + /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) + { + m_dispatchInfo = other.m_dispatchInfo; + m_dispatcher = other.m_dispatcher; + return *this; + } + */ + + + virtual ~btCollisionPairCallback() {} + + + virtual bool processOverlap(btBroadphasePair& pair) + { + (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); + + return false; + } +}; + + + +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) +{ + //m_blockedForChanges = true; + + btCollisionPairCallback collisionCallback(dispatchInfo,this); + + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); + + //m_blockedForChanges = false; + +} + + + + +//by default, Bullet will use this near callback +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) +{ + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher.needsCollision(colObj0,colObj1)) + { + btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1); + btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1); + + + //dispatcher will keep algorithms persistent in the collision pair + if (!collisionPair.m_algorithm) + { + collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap); + } + + if (collisionPair.m_algorithm) + { + btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + + collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + +} + + +void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) +{ + if (m_collisionAlgorithmPoolAllocator->getFreeCount()) + { + return m_collisionAlgorithmPoolAllocator->allocate(size); + } + + //warn user for overflow? + return btAlignedAlloc(static_cast(size), 16); +} + +void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) +{ + if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) + { + m_collisionAlgorithmPoolAllocator->freeMemory(ptr); + } else + { + btAlignedFree(ptr); + } +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h new file mode 100644 index 00000000..92696ee5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -0,0 +1,171 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION__DISPATCHER_H +#define BT_COLLISION__DISPATCHER_H + +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" + +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btIDebugDraw; +class btOverlappingPairCache; +class btPoolAllocator; +class btCollisionConfiguration; + +#include "btCollisionCreateFunc.h" + +#define USE_DISPATCH_REGISTRY_ARRAY 1 + +class btCollisionDispatcher; +///user can override this nearcallback for collision filtering and more finegrained control over collision detection +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + + +///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. +///Time of Impact, Closest Points and Penetration Depth. +class btCollisionDispatcher : public btDispatcher +{ + +protected: + + int m_dispatcherFlags; + + btAlignedObjectArray m_manifoldsPtr; + + btManifoldResult m_defaultManifoldResult; + + btNearCallback m_nearCallback; + + btPoolAllocator* m_collisionAlgorithmPoolAllocator; + + btPoolAllocator* m_persistentManifoldPoolAllocator; + + btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; + + btCollisionConfiguration* m_collisionConfiguration; + + +public: + + enum DispatcherFlags + { + CD_STATIC_STATIC_REPORTED = 1, + CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2, + CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4 + }; + + int getDispatcherFlags() const + { + return m_dispatcherFlags; + } + + void setDispatcherFlags(int flags) + { + m_dispatcherFlags = flags; + } + + ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions + void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); + + int getNumManifolds() const + { + return int( m_manifoldsPtr.size()); + } + + btPersistentManifold** getInternalManifoldPointer() + { + return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0; + } + + btPersistentManifold* getManifoldByIndexInternal(int index) + { + return m_manifoldsPtr[index]; + } + + const btPersistentManifold* getManifoldByIndexInternal(int index) const + { + return m_manifoldsPtr[index]; + } + + btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); + + virtual ~btCollisionDispatcher(); + + virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1); + + virtual void releaseManifold(btPersistentManifold* manifold); + + + virtual void clearManifold(btPersistentManifold* manifold); + + btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold = 0); + + virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1); + + virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1); + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; + + void setNearCallback(btNearCallback nearCallback) + { + m_nearCallback = nearCallback; + } + + btNearCallback getNearCallback() const + { + return m_nearCallback; + } + + //by default, Bullet will use this near callback + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + + virtual void* allocateCollisionAlgorithm(int size); + + virtual void freeCollisionAlgorithm(void* ptr); + + btCollisionConfiguration* getCollisionConfiguration() + { + return m_collisionConfiguration; + } + + const btCollisionConfiguration* getCollisionConfiguration() const + { + return m_collisionConfiguration; + } + + void setCollisionConfiguration(btCollisionConfiguration* config) + { + m_collisionConfiguration = config; + } + + virtual btPoolAllocator* getInternalManifoldPool() + { + return m_persistentManifoldPoolAllocator; + } + + virtual const btPoolAllocator* getInternalManifoldPool() const + { + return m_persistentManifoldPoolAllocator; + } + +}; + +#endif //BT_COLLISION__DISPATCHER_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp new file mode 100644 index 00000000..d0924100 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -0,0 +1,117 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btCollisionObject.h" +#include "LinearMath/btSerializer.h" + +btCollisionObject::btCollisionObject() + : m_anisotropicFriction(1.f,1.f,1.f), + m_hasAnisotropicFriction(false), + m_contactProcessingThreshold(BT_LARGE_FLOAT), + m_broadphaseHandle(0), + m_collisionShape(0), + m_extensionPointer(0), + m_rootCollisionShape(0), + m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), + m_islandTag1(-1), + m_companionId(-1), + m_activationState1(1), + m_deactivationTime(btScalar(0.)), + m_friction(btScalar(0.5)), + m_rollingFriction(0.0f), + m_restitution(btScalar(0.)), + m_internalType(CO_COLLISION_OBJECT), + m_userObjectPointer(0), + m_hitFraction(btScalar(1.)), + m_ccdSweptSphereRadius(btScalar(0.)), + m_ccdMotionThreshold(btScalar(0.)), + m_checkCollideWith(false), + m_updateRevision(0) +{ + m_worldTransform.setIdentity(); +} + +btCollisionObject::~btCollisionObject() +{ +} + +void btCollisionObject::setActivationState(int newState) const +{ + if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION)) + m_activationState1 = newState; +} + +void btCollisionObject::forceActivationState(int newState) const +{ + m_activationState1 = newState; +} + +void btCollisionObject::activate(bool forceActivation) const +{ + if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT))) + { + setActivationState(ACTIVE_TAG); + m_deactivationTime = btScalar(0.); + } +} + +const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer; + + m_worldTransform.serialize(dataOut->m_worldTransform); + m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform); + m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity); + m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity); + m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction); + dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction; + dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold; + dataOut->m_broadphaseHandle = 0; + dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape); + dataOut->m_rootCollisionShape = 0;//@todo + dataOut->m_collisionFlags = m_collisionFlags; + dataOut->m_islandTag1 = m_islandTag1; + dataOut->m_companionId = m_companionId; + dataOut->m_activationState1 = m_activationState1; + dataOut->m_deactivationTime = m_deactivationTime; + dataOut->m_friction = m_friction; + dataOut->m_rollingFriction = m_rollingFriction; + dataOut->m_restitution = m_restitution; + dataOut->m_internalType = m_internalType; + + char* name = (char*) serializer->findNameForPointer(this); + dataOut->m_name = (char*)serializer->getUniquePointer(name); + if (dataOut->m_name) + { + serializer->serializeName(name); + } + dataOut->m_hitFraction = m_hitFraction; + dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius; + dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold; + dataOut->m_checkCollideWith = m_checkCollideWith; + + return btCollisionObjectDataName; +} + + +void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const +{ + int len = calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this); +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.h new file mode 100644 index 00000000..89cad168 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -0,0 +1,565 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_OBJECT_H +#define BT_COLLISION_OBJECT_H + +#include "LinearMath/btTransform.h" + +//island management, m_activationState1 +#define ACTIVE_TAG 1 +#define ISLAND_SLEEPING 2 +#define WANTS_DEACTIVATION 3 +#define DISABLE_DEACTIVATION 4 +#define DISABLE_SIMULATION 5 + +struct btBroadphaseProxy; +class btCollisionShape; +struct btCollisionShapeData; +#include "LinearMath/btMotionState.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" + +typedef btAlignedObjectArray btCollisionObjectArray; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btCollisionObjectData btCollisionObjectDoubleData +#define btCollisionObjectDataName "btCollisionObjectDoubleData" +#else +#define btCollisionObjectData btCollisionObjectFloatData +#define btCollisionObjectDataName "btCollisionObjectFloatData" +#endif + + +/// btCollisionObject can be used to manage collision detection objects. +/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. +/// They can be added to the btCollisionWorld. +ATTRIBUTE_ALIGNED16(class) btCollisionObject +{ + +protected: + + btTransform m_worldTransform; + + ///m_interpolationWorldTransform is used for CCD and interpolation + ///it can be either previous or future (predicted) transform + btTransform m_interpolationWorldTransform; + //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) + //without destroying the continuous interpolated motion (which uses this interpolation velocities) + btVector3 m_interpolationLinearVelocity; + btVector3 m_interpolationAngularVelocity; + + btVector3 m_anisotropicFriction; + int m_hasAnisotropicFriction; + btScalar m_contactProcessingThreshold; + + btBroadphaseProxy* m_broadphaseHandle; + btCollisionShape* m_collisionShape; + ///m_extensionPointer is used by some internal low-level Bullet extensions. + void* m_extensionPointer; + + ///m_rootCollisionShape is temporarily used to store the original collision shape + ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes + ///If it is NULL, the m_collisionShape is not temporarily replaced. + btCollisionShape* m_rootCollisionShape; + + int m_collisionFlags; + + int m_islandTag1; + int m_companionId; + + mutable int m_activationState1; + mutable btScalar m_deactivationTime; + + btScalar m_friction; + btScalar m_restitution; + btScalar m_rollingFriction; + + ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc. + ///do not assign your own m_internalType unless you write a new dynamics object class. + int m_internalType; + + ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer + union + { + void* m_userObjectPointer; + int m_userIndex; + }; + + ///time of impact calculation + btScalar m_hitFraction; + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + btScalar m_ccdSweptSphereRadius; + + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + btScalar m_ccdMotionThreshold; + + /// If some object should have elaborate collision filtering by sub-classes + int m_checkCollideWith; + + ///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation. + int m_updateRevision; + + virtual bool checkCollideWithOverride(const btCollisionObject* /* co */) const + { + return true; + } + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + enum CollisionFlags + { + CF_STATIC_OBJECT= 1, + CF_KINEMATIC_OBJECT= 2, + CF_NO_CONTACT_RESPONSE = 4, + CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) + CF_CHARACTER_OBJECT = 16, + CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing + CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing + }; + + enum CollisionObjectTypes + { + CO_COLLISION_OBJECT =1, + CO_RIGID_BODY=2, + ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter + ///It is useful for collision sensors, explosion objects, character controller etc. + CO_GHOST_OBJECT=4, + CO_SOFT_BODY=8, + CO_HF_FLUID=16, + CO_USER_TYPE=32, + CO_FEATHERSTONE_LINK=64 + }; + + enum AnisotropicFrictionFlags + { + CF_ANISOTROPIC_FRICTION_DISABLED=0, + CF_ANISOTROPIC_FRICTION = 1, + CF_ANISOTROPIC_ROLLING_FRICTION = 2 + }; + + SIMD_FORCE_INLINE bool mergesSimulationIslands() const + { + ///static objects, kinematic and object without contact response don't merge islands + return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); + } + + const btVector3& getAnisotropicFriction() const + { + return m_anisotropicFriction; + } + void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION) + { + m_anisotropicFriction = anisotropicFriction; + bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f); + m_hasAnisotropicFriction = isUnity?frictionMode : 0; + } + bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const + { + return (m_hasAnisotropicFriction&frictionMode)!=0; + } + + ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default. + ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges + void setContactProcessingThreshold( btScalar contactProcessingThreshold) + { + m_contactProcessingThreshold = contactProcessingThreshold; + } + btScalar getContactProcessingThreshold() const + { + return m_contactProcessingThreshold; + } + + SIMD_FORCE_INLINE bool isStaticObject() const { + return (m_collisionFlags & CF_STATIC_OBJECT) != 0; + } + + SIMD_FORCE_INLINE bool isKinematicObject() const + { + return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; + } + + SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const + { + return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; + } + + SIMD_FORCE_INLINE bool hasContactResponse() const { + return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; + } + + + btCollisionObject(); + + virtual ~btCollisionObject(); + + virtual void setCollisionShape(btCollisionShape* collisionShape) + { + m_updateRevision++; + m_collisionShape = collisionShape; + m_rootCollisionShape = collisionShape; + } + + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const + { + return m_collisionShape; + } + + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() + { + return m_collisionShape; + } + + + + + + ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions. + ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. + void* internalGetExtensionPointer() const + { + return m_extensionPointer; + } + ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions + ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead. + void internalSetExtensionPointer(void* pointer) + { + m_extensionPointer = pointer; + } + + SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;} + + void setActivationState(int newState) const; + + void setDeactivationTime(btScalar time) + { + m_deactivationTime = time; + } + btScalar getDeactivationTime() const + { + return m_deactivationTime; + } + + void forceActivationState(int newState) const; + + void activate(bool forceActivation = false) const; + + SIMD_FORCE_INLINE bool isActive() const + { + return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); + } + + void setRestitution(btScalar rest) + { + m_updateRevision++; + m_restitution = rest; + } + btScalar getRestitution() const + { + return m_restitution; + } + void setFriction(btScalar frict) + { + m_updateRevision++; + m_friction = frict; + } + btScalar getFriction() const + { + return m_friction; + } + + void setRollingFriction(btScalar frict) + { + m_updateRevision++; + m_rollingFriction = frict; + } + btScalar getRollingFriction() const + { + return m_rollingFriction; + } + + + ///reserved for Bullet internal usage + int getInternalType() const + { + return m_internalType; + } + + btTransform& getWorldTransform() + { + return m_worldTransform; + } + + const btTransform& getWorldTransform() const + { + return m_worldTransform; + } + + void setWorldTransform(const btTransform& worldTrans) + { + m_updateRevision++; + m_worldTransform = worldTrans; + } + + + SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle() + { + return m_broadphaseHandle; + } + + SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const + { + return m_broadphaseHandle; + } + + void setBroadphaseHandle(btBroadphaseProxy* handle) + { + m_broadphaseHandle = handle; + } + + + const btTransform& getInterpolationWorldTransform() const + { + return m_interpolationWorldTransform; + } + + btTransform& getInterpolationWorldTransform() + { + return m_interpolationWorldTransform; + } + + void setInterpolationWorldTransform(const btTransform& trans) + { + m_updateRevision++; + m_interpolationWorldTransform = trans; + } + + void setInterpolationLinearVelocity(const btVector3& linvel) + { + m_updateRevision++; + m_interpolationLinearVelocity = linvel; + } + + void setInterpolationAngularVelocity(const btVector3& angvel) + { + m_updateRevision++; + m_interpolationAngularVelocity = angvel; + } + + const btVector3& getInterpolationLinearVelocity() const + { + return m_interpolationLinearVelocity; + } + + const btVector3& getInterpolationAngularVelocity() const + { + return m_interpolationAngularVelocity; + } + + SIMD_FORCE_INLINE int getIslandTag() const + { + return m_islandTag1; + } + + void setIslandTag(int tag) + { + m_islandTag1 = tag; + } + + SIMD_FORCE_INLINE int getCompanionId() const + { + return m_companionId; + } + + void setCompanionId(int id) + { + m_companionId = id; + } + + SIMD_FORCE_INLINE btScalar getHitFraction() const + { + return m_hitFraction; + } + + void setHitFraction(btScalar hitFraction) + { + m_hitFraction = hitFraction; + } + + + SIMD_FORCE_INLINE int getCollisionFlags() const + { + return m_collisionFlags; + } + + void setCollisionFlags(int flags) + { + m_collisionFlags = flags; + } + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + btScalar getCcdSweptSphereRadius() const + { + return m_ccdSweptSphereRadius; + } + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + void setCcdSweptSphereRadius(btScalar radius) + { + m_ccdSweptSphereRadius = radius; + } + + btScalar getCcdMotionThreshold() const + { + return m_ccdMotionThreshold; + } + + btScalar getCcdSquareMotionThreshold() const + { + return m_ccdMotionThreshold*m_ccdMotionThreshold; + } + + + + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + void setCcdMotionThreshold(btScalar ccdMotionThreshold) + { + m_ccdMotionThreshold = ccdMotionThreshold; + } + + ///users can point to their objects, userPointer is not used by Bullet + void* getUserPointer() const + { + return m_userObjectPointer; + } + + int getUserIndex() const + { + return m_userIndex; + } + ///users can point to their objects, userPointer is not used by Bullet + void setUserPointer(void* userPointer) + { + m_userObjectPointer = userPointer; + } + + ///users can point to their objects, userPointer is not used by Bullet + void setUserIndex(int index) + { + m_userIndex = index; + } + + int getUpdateRevisionInternal() const + { + return m_updateRevision; + } + + + inline bool checkCollideWith(const btCollisionObject* co) const + { + if (m_checkCollideWith) + return checkCollideWithOverride(co); + + return true; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; + + virtual void serializeSingleObject(class btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCollisionObjectDoubleData +{ + void *m_broadphaseHandle; + void *m_collisionShape; + btCollisionShapeData *m_rootCollisionShape; + char *m_name; + + btTransformDoubleData m_worldTransform; + btTransformDoubleData m_interpolationWorldTransform; + btVector3DoubleData m_interpolationLinearVelocity; + btVector3DoubleData m_interpolationAngularVelocity; + btVector3DoubleData m_anisotropicFriction; + double m_contactProcessingThreshold; + double m_deactivationTime; + double m_friction; + double m_rollingFriction; + double m_restitution; + double m_hitFraction; + double m_ccdSweptSphereRadius; + double m_ccdMotionThreshold; + + int m_hasAnisotropicFriction; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + int m_internalType; + int m_checkCollideWith; + + char m_padding[4]; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCollisionObjectFloatData +{ + void *m_broadphaseHandle; + void *m_collisionShape; + btCollisionShapeData *m_rootCollisionShape; + char *m_name; + + btTransformFloatData m_worldTransform; + btTransformFloatData m_interpolationWorldTransform; + btVector3FloatData m_interpolationLinearVelocity; + btVector3FloatData m_interpolationAngularVelocity; + btVector3FloatData m_anisotropicFriction; + float m_contactProcessingThreshold; + float m_deactivationTime; + float m_friction; + float m_rollingFriction; + + float m_restitution; + float m_hitFraction; + float m_ccdSweptSphereRadius; + float m_ccdMotionThreshold; + + int m_hasAnisotropicFriction; + int m_collisionFlags; + int m_islandTag1; + int m_companionId; + int m_activationState1; + int m_internalType; + int m_checkCollideWith; + char m_padding[4]; +}; + + + +SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const +{ + return sizeof(btCollisionObjectData); +} + + + +#endif //BT_COLLISION_OBJECT_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h new file mode 100644 index 00000000..952440b7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h @@ -0,0 +1,43 @@ +#ifndef BT_COLLISION_OBJECT_WRAPPER_H +#define BT_COLLISION_OBJECT_WRAPPER_H + +///btCollisionObjectWrapperis an internal data structure. +///Most users can ignore this and use btCollisionObject and btCollisionShape instead +class btCollisionShape; +class btCollisionObject; +class btTransform; +#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition + +#define BT_DECLARE_STACK_ONLY_OBJECT \ + private: \ + void* operator new(size_t size); \ + void operator delete(void*); + +struct btCollisionObjectWrapper; +struct btCollisionObjectWrapper +{ +BT_DECLARE_STACK_ONLY_OBJECT + +private: + btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed. + btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&); + +public: + const btCollisionObjectWrapper* m_parent; + const btCollisionShape* m_shape; + const btCollisionObject* m_collisionObject; + const btTransform& m_worldTransform; + int m_partId; + int m_index; + + btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index) + : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), + m_partId(partId), m_index(index) + {} + + SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; } + SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; } + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; } +}; + +#endif //BT_COLLISION_OBJECT_WRAPPER_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp new file mode 100644 index 00000000..093c6f9b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -0,0 +1,1552 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btCollisionWorld.h" +#include "btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btSerializer.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" +//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION + + +//#define USE_BRUTEFORCE_RAYBROADPHASE 1 +//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest +//#define RECALCULATE_AABB_RAYCAST 1 + +//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" + + +///for debug drawing + +//for debug rendering +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + + + +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) +:m_dispatcher1(dispatcher), +m_broadphasePairCache(pairCache), +m_debugDrawer(0), +m_forceUpdateAllAabbs(true) +{ +} + + +btCollisionWorld::~btCollisionWorld() +{ + + //clean up remaining objects + int i; + for (i=0;igetBroadphaseHandle(); + if (bp) + { + // + // only clear the cached algorithms + // + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); + collisionObject->setBroadphaseHandle(0); + } + } + + +} + + + + + + + + + + +void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +{ + + btAssert(collisionObject); + + //check that the object isn't already added + btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size()); + + m_collisionObjects.push_back(collisionObject); + + //calculate new AABB + btTransform trans = collisionObject->getWorldTransform(); + + btVector3 minAabb; + btVector3 maxAabb; + collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb); + + int type = collisionObject->getCollisionShape()->getShapeType(); + collisionObject->setBroadphaseHandle( getBroadphase()->createProxy( + minAabb, + maxAabb, + type, + collisionObject, + collisionFilterGroup, + collisionFilterMask, + m_dispatcher1,0 + )) ; + + + + + +} + + + +void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj) +{ + btVector3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + //need to increase the aabb for contact thresholds + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + + if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) + { + btVector3 minAabb2,maxAabb2; + colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); + minAabb2 -= contactThreshold; + maxAabb2 += contactThreshold; + minAabb.setMin(minAabb2); + maxAabb.setMax(maxAabb2); + } + + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; + + //moving objects should be moderately sized, probably something wrong if not + if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + { + bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + } else + { + //something went wrong, investigate + //this assert is unwanted in 3D modelers (danger of loosing work) + colObj->setActivationState(DISABLE_SIMULATION); + + static bool reportMe = true; + if (reportMe && m_debugDrawer) + { + reportMe = false; + m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); + m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); + m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); + m_debugDrawer->reportErrorWarning("Thanks.\n"); + } + } +} + +void btCollisionWorld::updateAabbs() +{ + BT_PROFILE("updateAabbs"); + + btTransform predictedTrans; + for ( int i=0;iisActive()) + { + updateSingleAabb(colObj); + } + } +} + + +void btCollisionWorld::computeOverlappingPairs() +{ + BT_PROFILE("calculateOverlappingPairs"); + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); +} + +void btCollisionWorld::performDiscreteCollisionDetection() +{ + BT_PROFILE("performDiscreteCollisionDetection"); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + + updateAabbs(); + + computeOverlappingPairs(); + + btDispatcher* dispatcher = getDispatcher(); + { + BT_PROFILE("dispatchAllCollisionPairs"); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + } + +} + + + +void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + + + //bool removeFromBroadphase = false; + + { + + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); + if (bp) + { + // + // only clear the cached algorithms + // + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); + collisionObject->setBroadphaseHandle(0); + } + } + + + //swapremove + m_collisionObjects.remove(collisionObject); + +} + + +void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback) +{ + btCollisionObjectWrapper colObWrap(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1); + btCollisionWorld::rayTestSingleInternal(rayFromTrans,rayToTrans,&colObWrap,resultCallback); +} + +void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans, + const btCollisionObjectWrapper* collisionObjectWrap, + RayResultCallback& resultCallback) +{ + btSphereShape pointShape(btScalar(0.0)); + pointShape.setMargin(0.f); + const btConvexShape* castShape = &pointShape; + const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape(); + const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform(); + + if (collisionShape->isConvex()) + { + // BT_PROFILE("rayTestConvex"); + btConvexCast::CastResult castResult; + castResult.m_fraction = resultCallback.m_closestHitFraction; + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast subSimplexConvexCaster(castShape,convexShape,&simplexSolver); + + btGjkConvexCast gjkConvexCaster(castShape,convexShape,&simplexSolver); + + //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); + bool condition = true; + btConvexCast* convexCasterPtr = 0; + if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseSubSimplexConvexCastRaytest) + convexCasterPtr = &subSimplexConvexCaster; + else + convexCasterPtr = &gjkConvexCaster; + + btConvexCast& convexCaster = *convexCasterPtr; + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST + + castResult.m_normal.normalize(); + btCollisionWorld::LocalRayResult localRayResult + ( + collisionObjectWrap->getCollisionObject(), + 0, + castResult.m_normal, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localRayResult, normalInWorldSpace); + + } + } + } + } else { + if (collisionShape->isConcave()) + { + + //ConvexCast::CastResult + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + const btCollisionObject* m_collisionObject; + const btConcaveShape* m_triangleMesh; + + btTransform m_colObjWorldTransform; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,const btConcaveShape* triangleMesh,const btTransform& colObjWorldTransform): + //@BP Mod + btTriangleRaycastCallback(from,to, resultCallback->m_flags), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh), + m_colObjWorldTransform(colObjWorldTransform) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalWorld, + hitFraction); + + bool normalInWorldSpace = true; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + } + + }; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + // BT_PROFILE("rayTestConcave"); + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + ///optimized version for btBvhTriangleMeshShape + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),triangleMesh,colObjWorldTransform); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); + } + else if(collisionShape->getShapeType()==GIMPACT_SHAPE_PROXYTYPE) + { + btGImpactMeshShape* concaveShape = (btGImpactMeshShape*)collisionShape; + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + concaveShape->processAllTrianglesRay(&rcb,rayFromLocal,rayToLocal); + }else + { + //generic (slower) case + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + const btCollisionObject* m_collisionObject; + btConcaveShape* m_triangleMesh; + + btTransform m_colObjWorldTransform; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform): + //@BP Mod + btTriangleRaycastCallback(from,to, resultCallback->m_flags), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh), + m_colObjWorldTransform(colObjWorldTransform) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalWorld, + hitFraction); + + bool normalInWorldSpace = true; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + } + + }; + + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + + btVector3 rayAabbMinLocal = rayFromLocal; + rayAabbMinLocal.setMin(rayToLocal); + btVector3 rayAabbMaxLocal = rayFromLocal; + rayAabbMaxLocal.setMax(rayToLocal); + + concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + } + } else { + // BT_PROFILE("rayTestCompound"); + if (collisionShape->isCompound()) + { + struct LocalInfoAdder2 : public RayResultCallback + { + RayResultCallback* m_userCallback; + int m_i; + + LocalInfoAdder2 (int i, RayResultCallback *user) + : m_userCallback(user), m_i(i) + { + m_closestHitFraction = m_userCallback->m_closestHitFraction; + m_flags = m_userCallback->m_flags; + } + virtual bool needsCollision(btBroadphaseProxy* p) const + { + return m_userCallback->needsCollision(p); + } + + virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; + } + }; + + struct RayTester : btDbvt::ICollide + { + const btCollisionObject* m_collisionObject; + const btCompoundShape* m_compoundShape; + const btTransform& m_colObjWorldTransform; + const btTransform& m_rayFromTrans; + const btTransform& m_rayToTrans; + RayResultCallback& m_resultCallback; + + RayTester(const btCollisionObject* collisionObject, + const btCompoundShape* compoundShape, + const btTransform& colObjWorldTransform, + const btTransform& rayFromTrans, + const btTransform& rayToTrans, + RayResultCallback& resultCallback): + m_collisionObject(collisionObject), + m_compoundShape(compoundShape), + m_colObjWorldTransform(colObjWorldTransform), + m_rayFromTrans(rayFromTrans), + m_rayToTrans(rayToTrans), + m_resultCallback(resultCallback) + { + + } + + void ProcessLeaf(int i) + { + const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i); + const btTransform& childTrans = m_compoundShape->getChildTransform(i); + btTransform childWorldTrans = m_colObjWorldTransform * childTrans; + + btCollisionObjectWrapper tmpOb(0,childCollisionShape,m_collisionObject,childWorldTrans,-1,i); + // replace collision shape so that callback can determine the triangle + + + + LocalInfoAdder2 my_cb(i, &m_resultCallback); + + rayTestSingleInternal( + m_rayFromTrans, + m_rayToTrans, + &tmpOb, + my_cb); + + } + + void Process(const btDbvtNode* leaf) + { + ProcessLeaf(leaf->dataAsInt); + } + }; + + const btCompoundShape* compoundShape = static_cast(collisionShape); + const btDbvt* dbvt = compoundShape->getDynamicAabbTree(); + + + RayTester rayCB( + collisionObjectWrap->getCollisionObject(), + compoundShape, + colObjWorldTransform, + rayFromTrans, + rayToTrans, + resultCallback); +#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION + if (dbvt) + { + btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin(); + btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin(); + btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB); + } + else +#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION + { + for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i) + { + rayCB.ProcessLeaf(i); + } + } + } + } + } +} + +void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback, btScalar allowedPenetration) +{ + btCollisionObjectWrapper tmpOb(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1); + btCollisionWorld::objectQuerySingleInternal(castShape,convexFromTrans,convexToTrans,&tmpOb,resultCallback,allowedPenetration); +} + +void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, + const btCollisionObjectWrapper* colObjWrap, + ConvexResultCallback& resultCallback, btScalar allowedPenetration) +{ + const btCollisionShape* collisionShape = colObjWrap->getCollisionShape(); + const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform(); + + if (collisionShape->isConvex()) + { + //BT_PROFILE("convexSweepConvex"); + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//?? + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + + btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); + //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); + //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); + + btConvexCast* castPtr = &convexCaster1; + + + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult + ( + colObjWrap->getCollisionObject(), + 0, + castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); + + } + } + } + } else { + if (collisionShape->isConcave()) + { + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + //BT_PROFILE("convexSweepbtBvhTriangleMesh"); + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + const btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = true; + + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),triangleMesh, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + tccb.m_allowedPenetration = allowedPenetration; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); + } else + { + if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE) + { + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = resultCallback.m_closestHitFraction; + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape; + btContinuousConvexCollision convexCaster1(castShape,planeShape); + btConvexCast* castPtr = &convexCaster1; + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult + ( + colObjWrap->getCollisionObject(), + 0, + castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); + } + } + } + + } else + { + //BT_PROFILE("convexSweepConcave"); + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + const btCollisionObject* m_collisionObject; + btConcaveShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = false; + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),concaveShape, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + tccb.m_allowedPenetration = allowedPenetration; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + + btVector3 rayAabbMinLocal = convexFromLocal; + rayAabbMinLocal.setMin(convexToLocal); + btVector3 rayAabbMaxLocal = convexFromLocal; + rayAabbMaxLocal.setMax(convexToLocal); + rayAabbMinLocal += boxMinLocal; + rayAabbMaxLocal += boxMaxLocal; + concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); + } + } + } else { + ///@todo : use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + BT_PROFILE("convexSweepCompound"); + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + + struct LocalInfoAdder : public ConvexResultCallback { + ConvexResultCallback* m_userCallback; + int m_i; + + LocalInfoAdder (int i, ConvexResultCallback *user) + : m_userCallback(user), m_i(i) + { + m_closestHitFraction = m_userCallback->m_closestHitFraction; + } + virtual bool needsCollision(btBroadphaseProxy* p) const + { + return m_userCallback->needsCollision(p); + } + virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult& r, bool b) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = -1; + shapeInfo.m_triangleIndex = m_i; + if (r.m_localShapeInfo == NULL) + r.m_localShapeInfo = &shapeInfo; + const btScalar result = m_userCallback->addSingleResult(r, b); + m_closestHitFraction = m_userCallback->m_closestHitFraction; + return result; + + } + }; + + LocalInfoAdder my_cb(i, &resultCallback); + + btCollisionObjectWrapper tmpObj(colObjWrap,childCollisionShape,colObjWrap->getCollisionObject(),childWorldTrans,-1,i); + + objectQuerySingleInternal(castShape, convexFromTrans,convexToTrans, + &tmpObj,my_cb, allowedPenetration); + + } + } + } + } +} + + +struct btSingleRayCallback : public btBroadphaseRayCallback +{ + + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; + + const btCollisionWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; + + btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_world(world), + m_resultCallback(resultCallback) + { + m_rayFromTrans.setIdentity(); + m_rayFromTrans.setOrigin(m_rayFromWorld); + m_rayToTrans.setIdentity(); + m_rayToTrans.setOrigin(m_rayToWorld); + + btVector3 rayDir = (rayToWorld-rayFromWorld); + + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); + + } + + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + //BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;igetNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + +} + + +struct btSingleSweepCallback : public btBroadphaseRayCallback +{ + + btTransform m_convexFromTrans; + btTransform m_convexToTrans; + btVector3 m_hitNormal; + const btCollisionWorld* m_world; + btCollisionWorld::ConvexResultCallback& m_resultCallback; + btScalar m_allowedCcdPenetration; + const btConvexShape* m_castShape; + + + btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration) + :m_convexFromTrans(convexFromTrans), + m_convexToTrans(convexToTrans), + m_world(world), + m_resultCallback(resultCallback), + m_allowedCcdPenetration(allowedPenetration), + m_castShape(castShape) + { + btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin()); + btVector3 rayDir = unnormalizedRayDir.normalized(); + ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(unnormalizedRayDir); + + } + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further convex sweep tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback, + m_allowedCcdPenetration); + } + + return true; + } +}; + + + +void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const +{ + + BT_PROFILE("convexSweepTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical + + + + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0f, linVel, angVel); + btVector3 zeroLinVel; + zeroLinVel.setValue(0,0,0); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax); + } + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + + btSingleSweepCallback convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration); + + m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax); + +#else + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + allowedCcdPenetration); + } + } + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE +} + + + +struct btBridgedManifoldResult : public btManifoldResult +{ + + btCollisionWorld::ContactResultCallback& m_resultCallback; + + btBridgedManifoldResult( const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap,btCollisionWorld::ContactResultCallback& resultCallback ) + :btManifoldResult(obj0Wrap,obj1Wrap), + m_resultCallback(resultCallback) + { + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); + btVector3 pointA = pointInWorld + normalOnBInWorld * depth; + btVector3 localA; + btVector3 localB; + if (isSwapped) + { + localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA ); + localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld); + } else + { + localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA ); + localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + + //BP mod, store contact triangles. + if (isSwapped) + { + newPt.m_partId0 = m_partId1; + newPt.m_partId1 = m_partId0; + newPt.m_index0 = m_index1; + newPt.m_index1 = m_index0; + } else + { + newPt.m_partId0 = m_partId0; + newPt.m_partId1 = m_partId1; + newPt.m_index0 = m_index0; + newPt.m_index1 = m_index1; + } + + //experimental feature info, for per-triangle material etc. + const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap; + const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap; + m_resultCallback.addSingleResult(newPt,obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1); + + } + +}; + + + +struct btSingleContactCallback : public btBroadphaseAabbCallback +{ + + btCollisionObject* m_collisionObject; + btCollisionWorld* m_world; + btCollisionWorld::ContactResultCallback& m_resultCallback; + + + btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback) + :m_collisionObject(collisionObject), + m_world(world), + m_resultCallback(resultCallback) + { + } + + virtual bool process(const btBroadphaseProxy* proxy) + { + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + if (collisionObject == m_collisionObject) + return true; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1); + btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1); + + btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1); + if (algorithm) + { + btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback); + //discrete collision detection query + + algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult); + + algorithm->~btCollisionAlgorithm(); + m_world->getDispatcher()->freeCollisionAlgorithm(algorithm); + } + } + return true; + } +}; + + +///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback. +///it reports one or more contact points for every overlapping object (including the one with deepest penetration) +void btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback) +{ + btVector3 aabbMin,aabbMax; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax); + btSingleContactCallback contactCB(colObj,this,resultCallback); + + m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB); +} + + +///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. +///it reports one or more contact points (including the one with deepest penetration) +void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback) +{ + btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1); + btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1); + + btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB); + if (algorithm) + { + btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback); + //discrete collision detection query + algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult); + + algorithm->~btCollisionAlgorithm(); + getDispatcher()->freeCollisionAlgorithm(algorithm); + } + +} + + + + +class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback +{ + btIDebugDraw* m_debugDrawer; + btVector3 m_color; + btTransform m_worldTrans; + +public: + + DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) : + m_debugDrawer(debugDrawer), + m_color(color), + m_worldTrans(worldTrans) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + processTriangle(triangle,partId,triangleIndex); + } + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + + btVector3 wv0,wv1,wv2; + wv0 = m_worldTrans*triangle[0]; + wv1 = m_worldTrans*triangle[1]; + wv2 = m_worldTrans*triangle[2]; + btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.); + + if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals ) + { + btVector3 normal = (wv1-wv0).cross(wv2-wv0); + normal.normalize(); + btVector3 normalColor(1,1,0); + m_debugDrawer->drawLine(center,center+normal,normalColor); + } + m_debugDrawer->drawLine(wv0,wv1,m_color); + m_debugDrawer->drawLine(wv1,wv2,m_color); + m_debugDrawer->drawLine(wv2,wv0,m_color); + } +}; + + +void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color) +{ + // Draw a small simplex at the center of the object + getDebugDrawer()->drawTransform(worldTransform,1); + + if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + debugDrawObject(worldTransform*childTrans,colShape,color); + } + + } else + { + + switch (shape->getShapeType()) + { + + case BOX_SHAPE_PROXYTYPE: + { + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtents = boxShape->getHalfExtentsWithMargin(); + getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color); + break; + } + + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + + getDebugDrawer()->drawSphere(radius, worldTransform, color); + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + const btMultiSphereShape* multiSphereShape = static_cast(shape); + + btTransform childTransform; + childTransform.setIdentity(); + + for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + { + childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); + getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color); + } + + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + const btCapsuleShape* capsuleShape = static_cast(shape); + + btScalar radius = capsuleShape->getRadius(); + btScalar halfHeight = capsuleShape->getHalfHeight(); + + int upAxis = capsuleShape->getUpAxis(); + getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color); + break; + } + case CONE_SHAPE_PROXYTYPE: + { + const btConeShape* coneShape = static_cast(shape); + btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); + btScalar height = coneShape->getHeight();//+coneShape->getMargin(); + + int upAxis= coneShape->getConeUpIndex(); + getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color); + break; + + } + case CYLINDER_SHAPE_PROXYTYPE: + { + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + btScalar radius = cylinder->getRadius(); + btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color); + break; + } + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color); + break; + + } + default: + { + + /// for polyhedral shapes + if (shape->isPolyhedral()) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; + + int i; + if (polyshape->getConvexPolyhedron()) + { + const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron(); + for (i=0;im_faces.size();i++) + { + btVector3 centroid(0,0,0); + int numVerts = poly->m_faces[i].m_indices.size(); + if (numVerts) + { + int lastV = poly->m_faces[i].m_indices[numVerts-1]; + for (int v=0;vm_faces[i].m_indices.size();v++) + { + int curVert = poly->m_faces[i].m_indices[v]; + centroid+=poly->m_vertices[curVert]; + getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color); + lastV = curVert; + } + } + centroid*= btScalar(1.f)/btScalar(numVerts); + if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals) + { + btVector3 normalColor(1,1,0); + btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]); + getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor); + } + + } + + + } else + { + for (i=0;igetNumEdges();i++) + { + btVector3 a,b; + polyshape->getEdge(i,a,b); + btVector3 wa = worldTransform * a; + btVector3 wb = worldTransform * b; + getDebugDrawer()->drawLine(wa,wb,color); + } + } + + + } + + if (shape->isConcave()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + ///@todo pass camera, for some culling? no -> we are not a graphics lib + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); + + } + + if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) + { + btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; + //todo: pass camera for some culling + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + //DebugDrawcallback drawCallback; + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + } + + + + } + + } + } +} + + +void btCollisionWorld::debugDrawWorld() +{ + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) + { + int numManifolds = getDispatcher()->getNumManifolds(); + btVector3 color(1,1,0); + for (int i=0;igetManifoldByIndexInternal(i); + //btCollisionObject* obA = static_cast(contactManifold->getBody0()); + //btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } + } + } + + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))) + { + int i; + + for ( i=0;igetCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0) + { + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)) + { + btVector3 color(btScalar(1.),btScalar(1.),btScalar(1.)); + switch(colObj->getActivationState()) + { + case ACTIVE_TAG: + color = btVector3(btScalar(1.),btScalar(1.),btScalar(1.)); break; + case ISLAND_SLEEPING: + color = btVector3(btScalar(0.),btScalar(1.),btScalar(0.));break; + case WANTS_DEACTIVATION: + color = btVector3(btScalar(0.),btScalar(1.),btScalar(1.));break; + case DISABLE_DEACTIVATION: + color = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));break; + case DISABLE_SIMULATION: + color = btVector3(btScalar(1.),btScalar(1.),btScalar(0.));break; + default: + { + color = btVector3(btScalar(1),btScalar(0.),btScalar(0.)); + } + }; + + debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); + } + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 minAabb,maxAabb; + btVector3 colorvec(1,0,0); + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + + btVector3 minAabb2,maxAabb2; + + if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) + { + colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); + minAabb2 -= contactThreshold; + maxAabb2 += contactThreshold; + minAabb.setMin(minAabb2); + maxAabb.setMax(maxAabb2); + } + + m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); + } + } + + } + } +} + + +void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() == btCollisionObject::CO_COLLISION_OBJECT) + { + colObj->serializeSingleObject(serializer); + } + } + + ///keep track of shapes already serialized + btHashMap serializedShapes; + + for (i=0;igetCollisionShape(); + + if (!serializedShapes.find(shape)) + { + serializedShapes.insert(shape,shape); + shape->serializeSingleShape(serializer); + } + } + +} + + +void btCollisionWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.h new file mode 100644 index 00000000..b3fffdec --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -0,0 +1,526 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +/** + * @mainpage Bullet Documentation + * + * @section intro_sec Introduction + * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ). + * + * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution. + * There is the Physics Forum for feedback and general Collision Detection and Physics discussions. + * Please visit http://www.bulletphysics.org + * + * @section install_sec Installation + * + * @subsection step1 Step 1: Download + * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list + * + * @subsection step2 Step 2: Building + * Bullet has multiple build systems, including premake, cmake and autotools. Premake and cmake support all platforms. + * Premake is included in the Bullet/build folder for Windows, Mac OSX and Linux. + * Under Windows you can click on Bullet/build/vs2010.bat to create Microsoft Visual Studio projects. + * On Mac OSX and Linux you can open a terminal and generate Makefile, codeblocks or Xcode4 projects: + * cd Bullet/build + * ./premake4_osx gmake or ./premake4_linux gmake or ./premake4_linux64 gmake or (for Mac) ./premake4_osx xcode4 + * cd Bullet/build/gmake + * make + * + * An alternative to premake is cmake. You can download cmake from http://www.cmake.org + * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles. + * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles. + * You can also use cmake in the command-line. Here are some examples for various platforms: + * cmake . -G "Visual Studio 9 2008" + * cmake . -G Xcode + * cmake . -G "Unix Makefiles" + * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make. + * + * @subsection step3 Step 3: Testing demos + * Try to run and experiment with BasicDemo executable as a starting point. + * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation. + * The Dependencies can be seen in this documentation under Directories + * + * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation + * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. + * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld. + * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras) + * Bullet Collision Detection can also be used without the Dynamics/Extras. + * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. + * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation. + * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector. + * + * @section copyright Copyright + * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf + * + */ + + + +#ifndef BT_COLLISION_WORLD_H +#define BT_COLLISION_WORLD_H + +class btCollisionShape; +class btConvexShape; +class btBroadphaseInterface; +class btSerializer; + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "btCollisionObject.h" +#include "btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btAlignedObjectArray.h" + +///CollisionWorld is interface and container for the collision detection +class btCollisionWorld +{ + + +protected: + + btAlignedObjectArray m_collisionObjects; + + btDispatcher* m_dispatcher1; + + btDispatcherInfo m_dispatchInfo; + + btBroadphaseInterface* m_broadphasePairCache; + + btIDebugDraw* m_debugDrawer; + + ///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs + ///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB) + bool m_forceUpdateAllAabbs; + + void serializeCollisionObjects(btSerializer* serializer); + +public: + + //this constructor doesn't own the dispatcher and paircache/broadphase + btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); + + virtual ~btCollisionWorld(); + + void setBroadphase(btBroadphaseInterface* pairCache) + { + m_broadphasePairCache = pairCache; + } + + const btBroadphaseInterface* getBroadphase() const + { + return m_broadphasePairCache; + } + + btBroadphaseInterface* getBroadphase() + { + return m_broadphasePairCache; + } + + btOverlappingPairCache* getPairCache() + { + return m_broadphasePairCache->getOverlappingPairCache(); + } + + + btDispatcher* getDispatcher() + { + return m_dispatcher1; + } + + const btDispatcher* getDispatcher() const + { + return m_dispatcher1; + } + + void updateSingleAabb(btCollisionObject* colObj); + + virtual void updateAabbs(); + + ///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation) + ///it can be useful to use if you perform ray tests without collision detection/simulation + virtual void computeOverlappingPairs(); + + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + } + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + virtual void debugDrawWorld(); + + virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); + + + ///LocalShapeInfo gives extra information for complex shapes + ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart + struct LocalShapeInfo + { + int m_shapePart; + int m_triangleIndex; + + //const btCollisionShape* m_shapeTemp; + //const btTransform* m_shapeLocalTransform; + }; + + struct LocalRayResult + { + LocalRayResult(const btCollisionObject* collisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + btScalar hitFraction) + :m_collisionObject(collisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitFraction(hitFraction) + { + } + + const btCollisionObject* m_collisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btScalar m_hitFraction; + + }; + + ///RayResultCallback is used to report new raycast results + struct RayResultCallback + { + btScalar m_closestHitFraction; + const btCollisionObject* m_collisionObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke. + unsigned int m_flags; + + virtual ~RayResultCallback() + { + } + bool hasHit() const + { + return (m_collisionObject != 0); + } + + RayResultCallback() + :m_closestHitFraction(btScalar(1.)), + m_collisionObject(0), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter), + //@BP Mod + m_flags(0) + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; + }; + + struct ClosestRayResultCallback : public RayResultCallback + { + ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld) + { + } + + btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_rayToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) + { + //caller already does the filter on the m_closestHitFraction + btAssert(rayResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = rayResult.m_hitFraction; + m_collisionObject = rayResult.m_collisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } + m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); + return rayResult.m_hitFraction; + } + }; + + struct AllHitsRayResultCallback : public RayResultCallback + { + AllHitsRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld) + { + } + + btAlignedObjectArray m_collisionObjects; + + btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_rayToWorld; + + btAlignedObjectArray m_hitNormalWorld; + btAlignedObjectArray m_hitPointWorld; + btAlignedObjectArray m_hitFractions; + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) + { + m_collisionObject = rayResult.m_collisionObject; + m_collisionObjects.push_back(rayResult.m_collisionObject); + btVector3 hitNormalWorld; + if (normalInWorldSpace) + { + hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } + m_hitNormalWorld.push_back(hitNormalWorld); + btVector3 hitPointWorld; + hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); + m_hitPointWorld.push_back(hitPointWorld); + m_hitFractions.push_back(rayResult.m_hitFraction); + return m_closestHitFraction; + } + }; + + + struct LocalConvexResult + { + LocalConvexResult(const btCollisionObject* hitCollisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + const btVector3& hitPointLocal, + btScalar hitFraction + ) + :m_hitCollisionObject(hitCollisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitPointLocal(hitPointLocal), + m_hitFraction(hitFraction) + { + } + + const btCollisionObject* m_hitCollisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btVector3 m_hitPointLocal; + btScalar m_hitFraction; + }; + + ///RayResultCallback is used to report new raycast results + struct ConvexResultCallback + { + btScalar m_closestHitFraction; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + ConvexResultCallback() + :m_closestHitFraction(btScalar(1.)), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) + { + } + + virtual ~ConvexResultCallback() + { + } + + bool hasHit() const + { + return (m_closestHitFraction < btScalar(1.)); + } + + + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0; + }; + + struct ClosestConvexResultCallback : public ConvexResultCallback + { + ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld) + :m_convexFromWorld(convexFromWorld), + m_convexToWorld(convexToWorld), + m_hitCollisionObject(0) + { + } + + btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_convexToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + const btCollisionObject* m_hitCollisionObject; + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) + { +//caller already does the filter on the m_closestHitFraction + btAssert(convexResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = convexResult.m_hitFraction; + m_hitCollisionObject = convexResult.m_hitCollisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = convexResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + m_hitPointWorld = convexResult.m_hitPointLocal; + return convexResult.m_hitFraction; + } + }; + + ///ContactResultCallback is used to report contact points + struct ContactResultCallback + { + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + ContactResultCallback() + :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) + { + } + + virtual ~ContactResultCallback() + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0; + }; + + + + int getNumCollisionObjects() const + { + return int(m_collisionObjects.size()); + } + + /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback + /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + /// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback + /// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. + void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const; + + ///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback. + ///it reports one or more contact points for every overlapping object (including the one with deepest penetration) + void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback); + + ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected. + ///it reports one or more contact points (including the one with deepest penetration) + void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback); + + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback); + + static void rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans, + const btCollisionObjectWrapper* collisionObjectWrap, + RayResultCallback& resultCallback); + + /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. + static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + ConvexResultCallback& resultCallback, btScalar allowedPenetration); + + static void objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, + const btCollisionObjectWrapper* colObjWrap, + ConvexResultCallback& resultCallback, btScalar allowedPenetration); + + virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + + btCollisionObjectArray& getCollisionObjectArray() + { + return m_collisionObjects; + } + + const btCollisionObjectArray& getCollisionObjectArray() const + { + return m_collisionObjects; + } + + + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + virtual void performDiscreteCollisionDetection(); + + btDispatcherInfo& getDispatchInfo() + { + return m_dispatchInfo; + } + + const btDispatcherInfo& getDispatchInfo() const + { + return m_dispatchInfo; + } + + bool getForceUpdateAllAabbs() const + { + return m_forceUpdateAllAabbs; + } + void setForceUpdateAllAabbs( bool forceUpdateAllAabbs) + { + m_forceUpdateAllAabbs = forceUpdateAllAabbs; + } + + ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo) + virtual void serialize(btSerializer* serializer); + +}; + + +#endif //BT_COLLISION_WORLD_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp new file mode 100644 index 00000000..991841ee --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -0,0 +1,375 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btAabbUtil2.h" +#include "btManifoldResult.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +btShapePairCallback gCompoundChildShapePairCallback = 0; + +btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) +:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_isSwapped(isSwapped), +m_sharedManifold(ci.m_manifold) +{ + m_ownsManifold = false; + + const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap; + btAssert (colObjWrap->getCollisionShape()->isCompound()); + + const btCompoundShape* compoundShape = static_cast(colObjWrap->getCollisionShape()); + m_compoundShapeRevision = compoundShape->getUpdateRevision(); + + + preallocateChildAlgorithms(body0Wrap,body1Wrap); +} + +void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) +{ + const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap; + const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap; + btAssert (colObjWrap->getCollisionShape()->isCompound()); + + const btCompoundShape* compoundShape = static_cast(colObjWrap->getCollisionShape()); + + int numChildren = compoundShape->getNumChildShapes(); + int i; + + m_childCollisionAlgorithms.resize(numChildren); + for (i=0;igetDynamicAabbTree()) + { + m_childCollisionAlgorithms[i] = 0; + } else + { + + const btCollisionShape* childShape = compoundShape->getChildShape(i); + + btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully) + m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold); + } + } +} + +void btCompoundCollisionAlgorithm::removeChildAlgorithms() +{ + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;i~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + } + } +} + +btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() +{ + removeChildAlgorithms(); +} + + + + +struct btCompoundLeafCallback : btDbvt::ICollide +{ + +public: + + const btCollisionObjectWrapper* m_compoundColObjWrap; + const btCollisionObjectWrapper* m_otherObjWrap; + btDispatcher* m_dispatcher; + const btDispatcherInfo& m_dispatchInfo; + btManifoldResult* m_resultOut; + btCollisionAlgorithm** m_childCollisionAlgorithms; + btPersistentManifold* m_sharedManifold; + + btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold) + :m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), + m_childCollisionAlgorithms(childCollisionAlgorithms), + m_sharedManifold(sharedManifold) + { + + } + + + void ProcessChildShape(const btCollisionShape* childShape,int index) + { + btAssert(index>=0); + const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); + btAssert(indexgetNumChildShapes()); + + + //backup + btTransform orgTrans = m_compoundColObjWrap->getWorldTransform(); + btTransform orgInterpolationTrans = m_compoundColObjWrap->getWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(index); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1); + + if (gCompoundChildShapePairCallback) + { + if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape)) + return; + } + + if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + + btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index); + + + //the contactpoint is still projected back using the original inverted worldtrans + if (!m_childCollisionAlgorithms[index]) + m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap,m_otherObjWrap,m_sharedManifold); + + + const btCollisionObjectWrapper* tmpWrap = 0; + + ///detect swapping case + if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject()) + { + tmpWrap = m_resultOut->getBody0Wrap(); + m_resultOut->setBody0Wrap(&compoundWrap); + m_resultOut->setShapeIdentifiersA(-1,index); + } else + { + tmpWrap = m_resultOut->getBody1Wrap(); + m_resultOut->setBody1Wrap(&compoundWrap); + m_resultOut->setShapeIdentifiersB(-1,index); + } + + + m_childCollisionAlgorithms[index]->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut); + +#if 0 + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); + } +#endif + + if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject()) + { + m_resultOut->setBody0Wrap(tmpWrap); + } else + { + m_resultOut->setBody1Wrap(tmpWrap); + } + + } + } + void Process(const btDbvtNode* leaf) + { + int index = leaf->dataAsInt; + + const btCompoundShape* compoundShape = static_cast(m_compoundColObjWrap->getCollisionShape()); + const btCollisionShape* childShape = compoundShape->getChildShape(index); + +#if 0 + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + btTransform orgTrans = m_compoundColObjWrap->getWorldTransform(); + btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); + m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); + } +#endif + + ProcessChildShape(childShape,index); + + } +}; + + + + + + +void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap; + const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap; + + btAssert (colObjWrap->getCollisionShape()->isCompound()); + const btCompoundShape* compoundShape = static_cast(colObjWrap->getCollisionShape()); + + ///btCompoundShape might have changed: + ////make sure the internal child collision algorithm caches are still valid + if (compoundShape->getUpdateRevision() != m_compoundShapeRevision) + { + ///clear and update all + removeChildAlgorithms(); + + preallocateChildAlgorithms(body0Wrap,body1Wrap); + } + + + const btDbvt* tree = compoundShape->getDynamicAabbTree(); + //use a dynamic aabb tree to cull potential child-overlaps + btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); + + ///we need to refresh all contact manifolds + ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep + ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm + { + int i; + btManifoldArray manifoldArray; + for (i=0;igetAllContactManifolds(manifoldArray); + for (int m=0;mgetNumContacts()) + { + resultOut->setPersistentManifold(manifoldArray[m]); + resultOut->refreshContactPoints(); + resultOut->setPersistentManifold(0);//??necessary? + } + } + manifoldArray.resize(0); + } + } + } + + if (tree) + { + + btVector3 localAabbMin,localAabbMax; + btTransform otherInCompoundSpace; + otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform(); + otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); + + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //process all children, that overlap with the given AABB bounds + tree->collideTV(tree->m_root,bounds,callback); + + } else + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i),i); + } + } + + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btManifoldArray manifoldArray; + const btCollisionShape* childShape = 0; + btTransform orgTrans; + btTransform orgInterpolationTrans; + btTransform newChildWorldTrans; + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + + for (i=0;igetChildShape(i); + //if not longer overlapping, remove the algorithm + orgTrans = colObjWrap->getWorldTransform(); + orgInterpolationTrans = colObjWrap->getWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(i); + newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1); + + if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + m_childCollisionAlgorithms[i] = 0; + } + } + } + } +} + +btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btAssert(0); + //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + + btAssert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + + //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps + //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals + //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: + //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 + //then use each overlapping node AABB against Tree0 + //and vise versa. + + btScalar hitFraction = btScalar(1.); + + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btTransform orgTrans; + btScalar frac; + for (i=0;igetChildShape(i); + + //backup + orgTrans = colObj->getWorldTransform(); + + const btTransform& childTrans = compoundShape->getChildTransform(i); + //btTransform newChildWorldTrans = orgTrans*childTrans ; + colObj->setWorldTransform( orgTrans*childTrans ); + + //btCollisionShape* tmpShape = colObj->getCollisionShape(); + //colObj->internalSetTemporaryCollisionShape( childShape ); + frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); + if (fracinternalSetTemporaryCollisionShape( tmpShape); + colObj->setWorldTransform( orgTrans); + } + return hitFraction; + +} + + + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h new file mode 100644 index 00000000..53675145 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -0,0 +1,99 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_COMPOUND_COLLISION_ALGORITHM_H +#define BT_COMPOUND_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" + +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; +class btCollisionObject; + +class btCollisionShape; +typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1); +extern btShapePairCallback gCompoundChildShapePairCallback; + +/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes +class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + btAlignedObjectArray m_childCollisionAlgorithms; + bool m_isSwapped; + + class btPersistentManifold* m_sharedManifold; + bool m_ownsManifold; + + + int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated + + void removeChildAlgorithms(); + + void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + +public: + + btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); + + virtual ~btCompoundCollisionAlgorithm(); + + btCollisionAlgorithm* getChildAlgorithm (int n) const + { + return m_childCollisionAlgorithms[n]; + } + + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + int i; + for (i=0;igetAllContactManifolds(manifoldArray); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true); + } + }; + +}; + +#endif //BT_COMPOUND_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp new file mode 100644 index 00000000..a52dd34f --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp @@ -0,0 +1,421 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +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 "btCompoundCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btAabbUtil2.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + + +btShapePairCallback gCompoundCompoundChildShapePairCallback = 0; + +btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) +:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_sharedManifold(ci.m_manifold) +{ + m_ownsManifold = false; + + void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16); + m_childCollisionAlgorithmCache= new(ptr) btHashedSimplePairCache(); + + const btCollisionObjectWrapper* col0ObjWrap = body0Wrap; + btAssert (col0ObjWrap->getCollisionShape()->isCompound()); + + const btCollisionObjectWrapper* col1ObjWrap = body1Wrap; + btAssert (col1ObjWrap->getCollisionShape()->isCompound()); + + const btCompoundShape* compoundShape0 = static_cast(col0ObjWrap->getCollisionShape()); + m_compoundShapeRevision0 = compoundShape0->getUpdateRevision(); + + const btCompoundShape* compoundShape1 = static_cast(col1ObjWrap->getCollisionShape()); + m_compoundShapeRevision1 = compoundShape1->getUpdateRevision(); + + +} + + +btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm() +{ + removeChildAlgorithms(); + m_childCollisionAlgorithmCache->~btHashedSimplePairCache(); + btAlignedFree(m_childCollisionAlgorithmCache); +} + +void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) +{ + int i; + btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); + for (i=0;igetAllContactManifolds(manifoldArray); + } + } +} + + +void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms() +{ + btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); + + int numChildren = pairs.size(); + int i; + for (i=0;i~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(algo); + } + } + m_childCollisionAlgorithmCache->removeAllPairs(); +} + +struct btCompoundCompoundLeafCallback : btDbvt::ICollide +{ + int m_numOverlapPairs; + + + const btCollisionObjectWrapper* m_compound0ColObjWrap; + const btCollisionObjectWrapper* m_compound1ColObjWrap; + btDispatcher* m_dispatcher; + const btDispatcherInfo& m_dispatchInfo; + btManifoldResult* m_resultOut; + + + class btHashedSimplePairCache* m_childCollisionAlgorithmCache; + + btPersistentManifold* m_sharedManifold; + + btCompoundCompoundLeafCallback (const btCollisionObjectWrapper* compound1ObjWrap, + const btCollisionObjectWrapper* compound0ObjWrap, + btDispatcher* dispatcher, + const btDispatcherInfo& dispatchInfo, + btManifoldResult* resultOut, + btHashedSimplePairCache* childAlgorithmsCache, + btPersistentManifold* sharedManifold) + :m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), + m_childCollisionAlgorithmCache(childAlgorithmsCache), + m_sharedManifold(sharedManifold), + m_numOverlapPairs(0) + { + + } + + + + + void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1) + { + m_numOverlapPairs++; + + + int childIndex0 = leaf0->dataAsInt; + int childIndex1 = leaf1->dataAsInt; + + + btAssert(childIndex0>=0); + btAssert(childIndex1>=0); + + + const btCompoundShape* compoundShape0 = static_cast(m_compound0ColObjWrap->getCollisionShape()); + btAssert(childIndex0getNumChildShapes()); + + const btCompoundShape* compoundShape1 = static_cast(m_compound1ColObjWrap->getCollisionShape()); + btAssert(childIndex1getNumChildShapes()); + + const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0); + const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1); + + //backup + btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform(); + const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0); + btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ; + + btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform(); + const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1); + btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ; + + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0); + childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1); + + if (gCompoundCompoundChildShapePairCallback) + { + if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1)) + return; + } + + if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0); + btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1); + + + btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1); + + btCollisionAlgorithm* colAlgo = 0; + + if (pair) + { + colAlgo = (btCollisionAlgorithm*)pair->m_userPointer; + + } else + { + colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0,&compoundWrap1,m_sharedManifold); + pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0,childIndex1); + btAssert(pair); + pair->m_userPointer = colAlgo; + } + + btAssert(colAlgo); + + const btCollisionObjectWrapper* tmpWrap0 = 0; + const btCollisionObjectWrapper* tmpWrap1 = 0; + + tmpWrap0 = m_resultOut->getBody0Wrap(); + tmpWrap1 = m_resultOut->getBody1Wrap(); + + m_resultOut->setBody0Wrap(&compoundWrap0); + m_resultOut->setBody1Wrap(&compoundWrap1); + + m_resultOut->setShapeIdentifiersA(-1,childIndex0); + m_resultOut->setShapeIdentifiersB(-1,childIndex1); + + + colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut); + + m_resultOut->setBody0Wrap(tmpWrap0); + m_resultOut->setBody1Wrap(tmpWrap1); + + + + } + } +}; + + +static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, const btTransform& xform) +{ + btVector3 newmin,newmax; + btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax); + btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax); + return Intersect(a,newb); +} + + +static inline void MycollideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + btCompoundCompoundLeafCallback* callback) +{ + + if(root0&&root1) + { + int depth=1; + int treshold=btDbvt::DOUBLE_STACKSIZE-4; + btAlignedObjectArray stkStack; + stkStack.resize(btDbvt::DOUBLE_STACKSIZE); + stkStack[0]=btDbvt::sStkNN(root0,root1); + do { + btDbvt::sStkNN p=stkStack[--depth]; + if(MyIntersect(p.a->volume,p.b->volume,xform)) + { + if(depth>treshold) + { + stkStack.resize(stkStack.size()*2); + treshold=stkStack.size()-4; + } + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]); + stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]); + stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]); + stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b); + stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]); + stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]); + } + else + { + callback->Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + const btCollisionObjectWrapper* col0ObjWrap = body0Wrap; + const btCollisionObjectWrapper* col1ObjWrap= body1Wrap; + + btAssert (col0ObjWrap->getCollisionShape()->isCompound()); + btAssert (col1ObjWrap->getCollisionShape()->isCompound()); + const btCompoundShape* compoundShape0 = static_cast(col0ObjWrap->getCollisionShape()); + const btCompoundShape* compoundShape1 = static_cast(col1ObjWrap->getCollisionShape()); + + ///btCompoundShape might have changed: + ////make sure the internal child collision algorithm caches are still valid + if ((compoundShape0->getUpdateRevision() != m_compoundShapeRevision0) || (compoundShape1->getUpdateRevision() != m_compoundShapeRevision1)) + { + ///clear all + removeChildAlgorithms(); + } + + + ///we need to refresh all contact manifolds + ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep + ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm + { + int i; + btManifoldArray manifoldArray; + btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); + for (i=0;igetAllContactManifolds(manifoldArray); + for (int m=0;mgetNumContacts()) + { + resultOut->setPersistentManifold(manifoldArray[m]); + resultOut->refreshContactPoints(); + resultOut->setPersistentManifold(0); + } + } + manifoldArray.resize(0); + } + } + } + + + const btDbvt* tree0 = compoundShape0->getDynamicAabbTree(); + const btDbvt* tree1 = compoundShape1->getDynamicAabbTree(); + + btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold); + + + const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform(); + MycollideTT(tree0->m_root,tree1->m_root,xform,&callback); + + //printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs); + + //remove non-overlapping child pairs + + { + btAssert(m_removePairs.size()==0); + + //iterate over all children, perform an AABB check inside ProcessChildShape + btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); + + int i; + btManifoldArray manifoldArray; + + + + + + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + + for (i=0;igetChildShape(pairs[i].m_indexA); + orgTrans0 = col0ObjWrap->getWorldTransform(); + orgInterpolationTrans0 = col0ObjWrap->getWorldTransform(); + const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA); + newChildWorldTrans0 = orgTrans0*childTrans0 ; + childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0); + } + + { + btTransform orgInterpolationTrans1; + const btCollisionShape* childShape1 = 0; + btTransform orgTrans1; + btTransform newChildWorldTrans1; + + childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB); + orgTrans1 = col1ObjWrap->getWorldTransform(); + orgInterpolationTrans1 = col1ObjWrap->getWorldTransform(); + const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB); + newChildWorldTrans1 = orgTrans1*childTrans1 ; + childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1); + } + + + + if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + algo->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(algo); + m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB)); + } + } + } + for (int i=0;iremoveOverlappingPair(m_removePairs[i].m_indexA,m_removePairs[i].m_indexB); + } + m_removePairs.clear(); + } + +} + +btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btAssert(0); + return 0.f; + +} + + + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h new file mode 100644 index 00000000..7e2d7ad7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h @@ -0,0 +1,90 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H +#define BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" + +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.h" +class btDispatcher; +class btCollisionObject; + +class btCollisionShape; +typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1); +extern btShapePairCallback gCompoundCompoundChildShapePairCallback; + +/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes +class btCompoundCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + + class btHashedSimplePairCache* m_childCollisionAlgorithmCache; + btSimplePairArray m_removePairs; + + class btPersistentManifold* m_sharedManifold; + bool m_ownsManifold; + + + int m_compoundShapeRevision0;//to keep track of changes, so that childAlgorithm array can be updated + int m_compoundShapeRevision1; + + void removeChildAlgorithms(); + +// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + +public: + + btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); + + virtual ~btCompoundCompoundCollisionAlgorithm(); + + + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray); + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm)); + return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm)); + return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true); + } + }; + +}; + +#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp new file mode 100644 index 00000000..4ec9ae71 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp @@ -0,0 +1,246 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConvex2dConvex2dAlgorithm.h" + +//#include +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +{ + m_numPerturbationIterations = 0; + m_minimumPointsPerturbationThreshold = 3; + m_simplexSolver = simplexSolver; + m_pdSolver = pdSolver; +} + +btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc() +{ +} + +btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_simplexSolver(simplexSolver), +m_pdSolver(pdSolver), +m_ownManifold (false), +m_manifoldPtr(mf), +m_lowLevelOfDetail(false), + m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +{ + (void)body0Wrap; + (void)body1Wrap; +} + + + + +btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel) +{ + m_lowLevelOfDetail = useLowLevel; +} + + + +extern btScalar gContactBreakingThreshold; + + +// +// Convex-Convex collision algorithm +// +void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + + //comment-out next line to test multi-contact generation + //resultOut->getPersistentManifold()->clearManifold(); + + + const btConvexShape* min0 = static_cast(body0Wrap->getCollisionShape()); + const btConvexShape* min1 = static_cast(body1Wrap->getCollisionShape()); + + btVector3 normalOnB; + btVector3 pointOnBWorld; + + { + + + btGjkPairDetector::ClosestPointInput input; + + btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); + //TODO: if (dispatchInfo.m_useContinuous) + gjkPairDetector.setMinkowskiA(min0); + gjkPairDetector.setMinkowskiB(min1); + + { + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + } + + input.m_transformA = body0Wrap->getWorldTransform(); + input.m_transformB = body1Wrap->getWorldTransform(); + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + + btVector3 v0,v1; + btVector3 sepNormalWorldSpace; + + } + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + + + + +btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold + + ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold + ///col0->m_worldTransform, + btScalar resultFraction = btScalar(1.); + + + btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); + btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); + + if (squareMot0 < col0->getCcdSquareMotionThreshold() && + squareMot1 < col1->getCcdSquareMotionThreshold()) + return resultFraction; + + + //An adhoc way of testing the Continuous Collision Detection algorithms + //One object is approximated as a sphere, to simplify things + //Starting in penetration should report no time of impact + //For proper CCD, better accuracy and handling of 'allowed' penetration should be added + //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) + + + /// Convex0 against sphere for Convex1 + { + btConvexShape* convex0 = static_cast(col0->getCollisionShape()); + + btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction()> result.m_fraction) + col0->setHitFraction( result.m_fraction ); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + + + + + } + + /// Sphere (for convex0) against Convex1 + { + btConvexShape* convex1 = static_cast(col1->getCollisionShape()); + + btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction() > result.m_fraction) + col0->setHitFraction( result.m_fraction); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + } + + return resultFraction; + +} + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h new file mode 100644 index 00000000..18d9385a --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h @@ -0,0 +1,95 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H +#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil + +class btConvexPenetrationDepthSolver; + + +///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape +///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation +class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm +{ + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_lowLevelOfDetail; + + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + +public: + + btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + + + virtual ~btConvex2dConvex2dAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + + void setLowLevelOfDetail(bool useLowLevel); + + + const btPersistentManifold* getManifold() + { + return m_manifoldPtr; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + btConvexPenetrationDepthSolver* m_pdSolver; + btSimplexSolverInterface* m_simplexSolver; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm)); + return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + }; + + +}; + +#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp new file mode 100644 index 00000000..e23f5f7a --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -0,0 +1,335 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_isSwapped(isSwapped), +m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped) +{ +} + +btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() +{ +} + +void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) +{ + if (m_btConvexTriangleCallback.m_manifoldPtr) + { + manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); + } +} + + +btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped): + m_dispatcher(dispatcher), + m_dispatchInfoPtr(0) +{ + m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap; + m_triBodyWrap = isSwapped? body0Wrap:body1Wrap; + + // + // create the manifold from the dispatcher 'manifold pool' + // + m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject()); + + clearCache(); +} + +btConvexTriangleCallback::~btConvexTriangleCallback() +{ + clearCache(); + m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btConvexTriangleCallback::clearCache() +{ + m_dispatcher->clearManifold(m_manifoldPtr); +} + + +void btConvexTriangleCallback::processTriangle(btVector3* triangle,int +partId, int triangleIndex) +{ + + if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax)) + { + return; + } + + //just for debugging purposes + //printf("triangle %d",m_triangleCount++); + + const btCollisionObject* ob = const_cast(m_triBodyWrap->getCollisionObject()); + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + + //const btCollisionObject* ob = static_cast(m_triBodyWrap->getCollisionObject()); + + + + +#if 0 + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe )) + { + btVector3 color(1,1,0); + btTransform& tr = ob->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + } +#endif + + if (m_convexBodyWrap->getCollisionShape()->isConvex()) + { + btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + tm.setMargin(m_collisionMarginTriangle); + + + btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform? + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap,&triObWrap,m_manifoldPtr); + + const btCollisionObjectWrapper* tmpWrap = 0; + + if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject()) + { + tmpWrap = m_resultOut->getBody0Wrap(); + m_resultOut->setBody0Wrap(&triObWrap); + m_resultOut->setShapeIdentifiersA(partId,triangleIndex); + } + else + { + tmpWrap = m_resultOut->getBody1Wrap(); + m_resultOut->setBody1Wrap(&triObWrap); + m_resultOut->setShapeIdentifiersB(partId,triangleIndex); + } + + colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut); + + if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject()) + { + m_resultOut->setBody0Wrap(tmpWrap); + } else + { + m_resultOut->setBody1Wrap(tmpWrap); + } + + + + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + } + +} + + + +void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut) +{ + m_convexBodyWrap = convexBodyWrap; + m_triBodyWrap = triBodyWrap; + + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle; + m_resultOut = resultOut; + + //recalc aabbs + btTransform convexInTriangleSpace; + convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform(); + const btCollisionShape* convexShape = static_cast(m_convexBodyWrap->getCollisionShape()); + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); + btScalar extraMargin = collisionMarginTriangle; + btVector3 extra(extraMargin,extraMargin,extraMargin); + + m_aabbMax += extra; + m_aabbMin -= extra; + +} + +void btConvexConcaveCollisionAlgorithm::clearCache() +{ + m_btConvexTriangleCallback.clearCache(); + +} + +void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap; + const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap; + + if (triBodyWrap->getCollisionShape()->isConcave()) + { + + + + const btConcaveShape* concaveShape = static_cast( triBodyWrap->getCollisionShape()); + + if (convexBodyWrap->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + + resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr); + m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut); + + m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject()); + + concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); + + resultOut->refreshContactPoints(); + + m_btConvexTriangleCallback.clearWrapperData(); + + } + + } + +} + + +btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h new file mode 100644 index 00000000..e90d06eb --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -0,0 +1,121 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H +#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "btCollisionCreateFunc.h" + +///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. +class btConvexTriangleCallback : public btTriangleCallback +{ + const btCollisionObjectWrapper* m_convexBodyWrap; + const btCollisionObjectWrapper* m_triBodyWrap; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + + btManifoldResult* m_resultOut; + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + +public: +int m_triangleCount; + + btPersistentManifold* m_manifoldPtr; + + btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut); + + void clearWrapperData() + { + m_convexBodyWrap = 0; + m_triBodyWrap = 0; + } + virtual ~btConvexTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + SIMD_FORCE_INLINE const btVector3& getAabbMin() const + { + return m_aabbMin; + } + SIMD_FORCE_INLINE const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes. +class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + + bool m_isSwapped; + + btConvexTriangleCallback m_btConvexTriangleCallback; + + + +public: + + btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); + + virtual ~btConvexConcaveCollisionAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray); + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true); + } + }; + +}; + +#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp new file mode 100644 index 00000000..7f2722aa --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -0,0 +1,783 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance +///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums +///with reproduction case +//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1 +//#define ZERO_MARGIN + +#include "btConvexConvexAlgorithm.h" + +//#include +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +/////////// + + + +static SIMD_FORCE_INLINE void segmentsClosestPoints( + btVector3& ptsVector, + btVector3& offsetA, + btVector3& offsetB, + btScalar& tA, btScalar& tB, + const btVector3& translation, + const btVector3& dirA, btScalar hlenA, + const btVector3& dirB, btScalar hlenB ) +{ + // compute the parameters of the closest points on each line segment + + btScalar dirA_dot_dirB = btDot(dirA,dirB); + btScalar dirA_dot_trans = btDot(dirA,translation); + btScalar dirB_dot_trans = btDot(dirB,translation); + + btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB; + + if ( denom == 0.0f ) { + tA = 0.0f; + } else { + tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom; + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + tB = tA * dirA_dot_dirB - dirB_dot_trans; + + if ( tB < -hlenB ) { + tB = -hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } else if ( tB > hlenB ) { + tB = hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + // compute the closest points relative to segment centers. + + offsetA = dirA * tA; + offsetB = dirB * tB; + + ptsVector = translation - offsetA + offsetB; +} + + +static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance( + btVector3& normalOnB, + btVector3& pointOnB, + btScalar capsuleLengthA, + btScalar capsuleRadiusA, + btScalar capsuleLengthB, + btScalar capsuleRadiusB, + int capsuleAxisA, + int capsuleAxisB, + const btTransform& transformA, + const btTransform& transformB, + btScalar distanceThreshold ) +{ + btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA); + btVector3 translationA = transformA.getOrigin(); + btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB); + btVector3 translationB = transformB.getOrigin(); + + // translation between centers + + btVector3 translation = translationB - translationA; + + // compute the closest points of the capsule line segments + + btVector3 ptsVector; // the vector between the closest points + + btVector3 offsetA, offsetB; // offsets from segment centers to their closest points + btScalar tA, tB; // parameters on line segment + + segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation, + directionA, capsuleLengthA, directionB, capsuleLengthB ); + + btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB; + + if ( distance > distanceThreshold ) + return distance; + + btScalar lenSqr = ptsVector.length2(); + if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON)) + { + //degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA' + btVector3 q; + btPlaneSpace1(directionA,normalOnB,q); + } else + { + // compute the contact normal + normalOnB = ptsVector*-btRecipSqrt(lenSqr); + } + pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB; + + return distance; +} + + + + + + + +////////// + + + + + +btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +{ + m_numPerturbationIterations = 0; + m_minimumPointsPerturbationThreshold = 3; + m_simplexSolver = simplexSolver; + m_pdSolver = pdSolver; +} + +btConvexConvexAlgorithm::CreateFunc::~CreateFunc() +{ +} + +btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_simplexSolver(simplexSolver), +m_pdSolver(pdSolver), +m_ownManifold (false), +m_manifoldPtr(mf), +m_lowLevelOfDetail(false), +#ifdef USE_SEPDISTANCE_UTIL2 +m_sepDistance((static_cast(body0->getCollisionShape()))->getAngularMotionDisc(), + (static_cast(body1->getCollisionShape()))->getAngularMotionDisc()), +#endif +m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +{ + (void)body0Wrap; + (void)body1Wrap; +} + + + + +btConvexConvexAlgorithm::~btConvexConvexAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel) +{ + m_lowLevelOfDetail = useLowLevel; +} + + +struct btPerturbedContactResult : public btManifoldResult +{ + btManifoldResult* m_originalManifoldResult; + btTransform m_transformA; + btTransform m_transformB; + btTransform m_unPerturbedTransform; + bool m_perturbA; + btIDebugDraw* m_debugDrawer; + + + btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer) + :m_originalManifoldResult(originalResult), + m_transformA(transformA), + m_transformB(transformB), + m_unPerturbedTransform(unPerturbedTransform), + m_perturbA(perturbA), + m_debugDrawer(debugDrawer) + { + } + virtual ~ btPerturbedContactResult() + { + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth) + { + btVector3 endPt,startPt; + btScalar newDepth; + btVector3 newNormal; + + if (m_perturbA) + { + btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth; + endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg); + newDepth = (endPt - pointInWorld).dot(normalOnBInWorld); + startPt = endPt+normalOnBInWorld*newDepth; + } else + { + endPt = pointInWorld + normalOnBInWorld*orgDepth; + startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld); + newDepth = (endPt - startPt).dot(normalOnBInWorld); + + } + +//#define DEBUG_CONTACTS 1 +#ifdef DEBUG_CONTACTS + m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0)); + m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0)); + m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1)); +#endif //DEBUG_CONTACTS + + + m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth); + } + +}; + +extern btScalar gContactBreakingThreshold; + + +// +// Convex-Convex collision algorithm +// +void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + + //comment-out next line to test multi-contact generation + //resultOut->getPersistentManifold()->clearManifold(); + + + const btConvexShape* min0 = static_cast(body0Wrap->getCollisionShape()); + const btConvexShape* min1 = static_cast(body1Wrap->getCollisionShape()); + + btVector3 normalOnB; + btVector3 pointOnBWorld; +#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER + if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE)) + { + btCapsuleShape* capsuleA = (btCapsuleShape*) min0; + btCapsuleShape* capsuleB = (btCapsuleShape*) min1; + // btVector3 localScalingA = capsuleA->getLocalScaling(); + // btVector3 localScalingB = capsuleB->getLocalScaling(); + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(), + capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(), + body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold); + + if (dist=(SIMD_EPSILON*SIMD_EPSILON)); + resultOut->addContactPoint(normalOnB,pointOnBWorld,dist); + } + resultOut->refreshContactPoints(); + return; + } +#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER + + + + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform()); + } + + if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f) +#endif //USE_SEPDISTANCE_UTIL2 + + { + + + btGjkPairDetector::ClosestPointInput input; + + btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver); + //TODO: if (dispatchInfo.m_useContinuous) + gjkPairDetector.setMinkowskiA(min0); + gjkPairDetector.setMinkowskiB(min1); + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + input.m_maximumDistanceSquared = BT_LARGE_FLOAT; + } else +#endif //USE_SEPDISTANCE_UTIL2 + { + //if (dispatchInfo.m_convexMaxDistanceUseCPT) + //{ + // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); + //} else + //{ + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); +// } + + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + } + + input.m_transformA = body0Wrap->getWorldTransform(); + input.m_transformB = body1Wrap->getWorldTransform(); + + + + + +#ifdef USE_SEPDISTANCE_UTIL2 + btScalar sepDist = 0.f; + if (dispatchInfo.m_useConvexConservativeDistanceUtil) + { + sepDist = gjkPairDetector.getCachedSeparatingDistance(); + if (sepDist>SIMD_EPSILON) + { + sepDist += dispatchInfo.m_convexConservativeDistanceThreshold; + //now perturbe directions to get multiple contact points + + } + } +#endif //USE_SEPDISTANCE_UTIL2 + + if (min0->isPolyhedral() && min1->isPolyhedral()) + { + + + struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result + { + virtual void setShapeIdentifiersA(int partId0,int index0){} + virtual void setShapeIdentifiersB(int partId1,int index1){} + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + } + }; + + + struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result + { + btDiscreteCollisionDetectorInterface::Result* m_originalResult; + btVector3 m_reportedNormalOnWorld; + btScalar m_marginOnA; + btScalar m_marginOnB; + btScalar m_reportedDistance; + + bool m_foundResult; + btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB) + :m_originalResult(result), + m_marginOnA(marginOnA), + m_marginOnB(marginOnB), + m_foundResult(false) + { + } + + virtual void setShapeIdentifiersA(int partId0,int index0){} + virtual void setShapeIdentifiersB(int partId1,int index1){} + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorldOrg,btScalar depthOrg) + { + m_reportedDistance = depthOrg; + m_reportedNormalOnWorld = normalOnBInWorld; + + btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld*m_marginOnB; + m_reportedDistance = depthOrg+(m_marginOnA+m_marginOnB); + if (m_reportedDistance<0.f) + { + m_foundResult = true; + } + m_originalResult->addContactPoint(normalOnBInWorld,adjustedPointB,m_reportedDistance); + } + }; + + + btDummyResult dummy; + +///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it + + btScalar min0Margin = min0->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min0->getMargin(); + btScalar min1Margin = min1->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min1->getMargin(); + + btWithoutMarginResult withoutMargin(resultOut, min0Margin,min1Margin); + + btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0; + btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1; + if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron()) + { + + + + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar minDist = -1e30f; + btVector3 sepNormalWorldSpace; + bool foundSepAxis = true; + + if (dispatchInfo.m_enableSatConvex) + { + foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis( + *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0Wrap->getWorldTransform(), + body1Wrap->getWorldTransform(), + sepNormalWorldSpace,*resultOut); + } else + { +#ifdef ZERO_MARGIN + gjkPairDetector.setIgnoreMargin(true); + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#else + + + gjkPairDetector.getClosestPoints(input,withoutMargin,dispatchInfo.m_debugDraw); + //gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw); +#endif //ZERO_MARGIN + //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + //if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld;//gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance(); + minDist = withoutMargin.m_reportedDistance;//gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin(); + +#ifdef ZERO_MARGIN + foundSepAxis = true;//gjkPairDetector.getCachedSeparatingDistance()<0.f; +#else + foundSepAxis = withoutMargin.m_foundResult && minDist<0;//-(min0->getMargin()+min1->getMargin()); +#endif + } + } + if (foundSepAxis) + { + +// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + + btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0Wrap->getWorldTransform(), + body1Wrap->getWorldTransform(), minDist-threshold, threshold, *resultOut); + + } + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + return; + + } else + { + //we can also deal with convex versus triangle (without connectivity data) + if (polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE) + { + + btVertexArray vertices; + btTriangleShape* tri = (btTriangleShape*)polyhedronB; + vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[0]); + vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[1]); + vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[2]); + + //tri->initializePolyhedralFeatures(); + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btVector3 sepNormalWorldSpace; + btScalar minDist =-1e30f; + btScalar maxDist = threshold; + + bool foundSepAxis = false; + if (0) + { + polyhedronB->initializePolyhedralFeatures(); + foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis( + *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0Wrap->getWorldTransform(), + body1Wrap->getWorldTransform(), + sepNormalWorldSpace,*resultOut); + // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + + } else + { +#ifdef ZERO_MARGIN + gjkPairDetector.setIgnoreMargin(true); + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#else + gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw); +#endif//ZERO_MARGIN + + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + //minDist = gjkPairDetector.getCachedSeparatingDistance(); + //maxDist = threshold; + minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin(); + foundSepAxis = true; + } + } + + + if (foundSepAxis) + { + btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), + body0Wrap->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut); + } + + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + + return; + } + + } + + + } + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + + //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects + + //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points + if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold) + { + + int i; + btVector3 v0,v1; + btVector3 sepNormalWorldSpace; + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + + btPlaneSpace1(sepNormalWorldSpace,v0,v1); + + + bool perturbeA = true; + const btScalar angleLimit = 0.125f * SIMD_PI; + btScalar perturbeAngle; + btScalar radiusA = min0->getAngularMotionDisc(); + btScalar radiusB = min1->getAngularMotionDisc(); + if (radiusA < radiusB) + { + perturbeAngle = gContactBreakingThreshold /radiusA; + perturbeA = true; + } else + { + perturbeAngle = gContactBreakingThreshold / radiusB; + perturbeA = false; + } + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btTransform unPerturbedTransform; + if (perturbeA) + { + unPerturbedTransform = input.m_transformA; + } else + { + unPerturbedTransform = input.m_transformB; + } + + for ( i=0;iSIMD_EPSILON) + { + btQuaternion perturbeRot(v0,perturbeAngle); + btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); + btQuaternion rotq(sepNormalWorldSpace,iterationAngle); + + + if (perturbeA) + { + input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0Wrap->getWorldTransform().getBasis()); + input.m_transformB = body1Wrap->getWorldTransform(); + #ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); + #endif //DEBUG_CONTACTS + } else + { + input.m_transformA = body0Wrap->getWorldTransform(); + input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1Wrap->getWorldTransform().getBasis()); + #ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); + #endif + } + + btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); + gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); + } + } + } + } + + + +#ifdef USE_SEPDISTANCE_UTIL2 + if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON)) + { + m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform()); + } +#endif //USE_SEPDISTANCE_UTIL2 + + + } + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + + + +bool disableCcd = false; +btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold + + ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold + ///col0->m_worldTransform, + btScalar resultFraction = btScalar(1.); + + + btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); + btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); + + if (squareMot0 < col0->getCcdSquareMotionThreshold() && + squareMot1 < col1->getCcdSquareMotionThreshold()) + return resultFraction; + + if (disableCcd) + return btScalar(1.); + + + //An adhoc way of testing the Continuous Collision Detection algorithms + //One object is approximated as a sphere, to simplify things + //Starting in penetration should report no time of impact + //For proper CCD, better accuracy and handling of 'allowed' penetration should be added + //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) + + + /// Convex0 against sphere for Convex1 + { + btConvexShape* convex0 = static_cast(col0->getCollisionShape()); + + btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction()> result.m_fraction) + col0->setHitFraction( result.m_fraction ); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + + + + + } + + /// Sphere (for convex0) against Convex1 + { + btConvexShape* convex1 = static_cast(col1->getCollisionShape()); + + btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction() > result.m_fraction) + col0->setHitFraction( result.m_fraction); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + } + + return resultFraction; + +} + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h new file mode 100644 index 00000000..51db0c65 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -0,0 +1,108 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_CONVEX_ALGORITHM_H +#define BT_CONVEX_CONVEX_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" +#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil + +class btConvexPenetrationDepthSolver; + +///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise +///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions. +///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util +///for certain pairs that have a small size ratio + +//#define USE_SEPDISTANCE_UTIL2 1 + +///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects. +///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal. +///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888 +class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm +{ +#ifdef USE_SEPDISTANCE_UTIL2 + btConvexSeparatingDistanceUtil m_sepDistance; +#endif + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_lowLevelOfDetail; + + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + + ///cache separating vector to speedup collision detection + + +public: + + btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold); + + virtual ~btConvexConvexAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + + void setLowLevelOfDetail(bool useLowLevel); + + + const btPersistentManifold* getManifold() + { + return m_manifoldPtr; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + btConvexPenetrationDepthSolver* m_pdSolver; + btSimplexSolverInterface* m_simplexSolver; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); + return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + }; + + +}; + +#endif //BT_CONVEX_CONVEX_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp new file mode 100644 index 00000000..cce2d95b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp @@ -0,0 +1,174 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConvexPlaneCollisionAlgorithm.h" + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +//#include + +btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped), +m_numPerturbationIterations(numPerturbationIterations), +m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold) +{ + const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? col1Wrap : col0Wrap; + const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? col0Wrap : col1Wrap; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject())) + { + m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject()); + m_ownManifold = true; + } +} + + +btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap; + const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap; + + btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape(); + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape(); + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + btTransform convexWorldTransform = convexObjWrap->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexWorldTransform; + //now perturbe the convex-world transform + convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot); + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * planeObjWrap->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected; + + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); + } +} + + +void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + if (!m_manifoldPtr) + return; + + const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap; + const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap; + + btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape(); + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape(); + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + btTransform planeInConvex; + planeInConvex= convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected; + + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); + } + + //the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones: + //they keep on rolling forever because of the additional off-center contact points + //so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc) + if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()getAngularMotionDisc(); + perturbeAngle = gContactBreakingThreshold / radius; + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btQuaternion perturbeRot(v0,perturbeAngle); + for (int i=0;igetNumContacts()) + { + resultOut->refreshContactPoints(); + } + } +} + +btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h new file mode 100644 index 00000000..d28c430c --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_PLANE_COLLISION_ALGORITHM_H +#define BT_CONVEX_PLANE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + +public: + + btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold); + + virtual ~btConvexPlaneCollisionAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + void collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + int m_numPerturbationIterations; + int m_minimumPointsPerturbationThreshold; + + CreateFunc() + : m_numPerturbationIterations(1), + m_minimumPointsPerturbationThreshold(0) + { + } + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } else + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold); + } + } + }; + +}; + +#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp new file mode 100644 index 00000000..c3cacec4 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -0,0 +1,307 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btDefaultCollisionConfiguration.h" + +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h" + +#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" + + + +#include "LinearMath/btPoolAllocator.h" + + + + + +btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) +{ + + void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); + m_simplexSolver = new (mem)btVoronoiSimplexSolver(); + + if (constructionInfo.m_useEpaPenetrationAlgorithm) + { + mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); + m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; + }else + { + mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); + m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; + } + + //default CreationFunctions, filling the m_doubleDispatch table + mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); + m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); + m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc),16); + m_compoundCompoundCreateFunc = new (mem)btCompoundCompoundCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); + m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); + m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); + m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; + m_boxSphereCF->m_swapped = true; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + m_triangleSphereCF->m_swapped = true; + + mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); + m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; + + //convex versus plane + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + m_planeConvexCF->m_swapped = true; + + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + int maxSize = sizeof(btConvexConvexAlgorithm); + int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); + int maxSize3 = sizeof(btCompoundCollisionAlgorithm); + int sl = sizeof(btConvexSeparatingDistanceUtil); + sl = sizeof(btGjkPairDetector); + int collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); + + + if (constructionInfo.m_persistentManifoldPool) + { + m_ownsPersistentManifoldPool = false; + m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; + } else + { + m_ownsPersistentManifoldPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); + } + + if (constructionInfo.m_collisionAlgorithmPool) + { + m_ownsCollisionAlgorithmPool = false; + m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; + } else + { + m_ownsCollisionAlgorithmPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + + +} + +btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() +{ + if (m_ownsCollisionAlgorithmPool) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + } + if (m_ownsPersistentManifoldPool) + { + m_persistentManifoldPool->~btPoolAllocator(); + btAlignedFree(m_persistentManifoldPool); + } + + m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConvexCreateFunc); + + m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConcaveCreateFunc); + m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedConvexConcaveCreateFunc); + + m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_compoundCreateFunc); + + m_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree(m_compoundCompoundCreateFunc); + + m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedCompoundCreateFunc); + + m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_emptyCreateFunc); + + m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereSphereCF); + +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereBoxCF); + m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxSphereCF); +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereTriangleCF); + m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_triangleSphereCF); + m_boxBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxBoxCF); + + m_convexPlaneCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexPlaneCF); + m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_planeConvexCF); + + m_simplexSolver->~btVoronoiSimplexSolver(); + btAlignedFree(m_simplexSolver); + + m_pdSolver->~btConvexPenetrationDepthSolver(); + + btAlignedFree(m_pdSolver); + + +} + + +btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_sphereSphereCF; + } +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) + { + return m_sphereBoxCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_boxSphereCF; + } +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) + { + return m_sphereTriangleCF; + } + + if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_triangleSphereCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) + { + return m_boxBoxCF; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) + { + return m_convexPlaneCF; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) + { + return m_planeConvexCF; + } + + + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + + if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1)) + { + return m_compoundCompoundCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} + +void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) +{ + btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc; + convexConvex->m_numPerturbationIterations = numPerturbationIterations; + convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; +} + +void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) +{ + btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF; + cpCF->m_numPerturbationIterations = numPerturbationIterations; + cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; + + btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF; + pcCF->m_numPerturbationIterations = numPerturbationIterations; + pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h new file mode 100644 index 00000000..2078420e --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -0,0 +1,127 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DEFAULT_COLLISION_CONFIGURATION +#define BT_DEFAULT_COLLISION_CONFIGURATION + +#include "btCollisionConfiguration.h" +class btVoronoiSimplexSolver; +class btConvexPenetrationDepthSolver; + +struct btDefaultCollisionConstructionInfo +{ + btPoolAllocator* m_persistentManifoldPool; + btPoolAllocator* m_collisionAlgorithmPool; + int m_defaultMaxPersistentManifoldPoolSize; + int m_defaultMaxCollisionAlgorithmPoolSize; + int m_customCollisionAlgorithmMaxElementSize; + int m_useEpaPenetrationAlgorithm; + + btDefaultCollisionConstructionInfo() + :m_persistentManifoldPool(0), + m_collisionAlgorithmPool(0), + m_defaultMaxPersistentManifoldPoolSize(4096), + m_defaultMaxCollisionAlgorithmPoolSize(4096), + m_customCollisionAlgorithmMaxElementSize(0), + m_useEpaPenetrationAlgorithm(true) + { + } +}; + + + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator, pool memory allocators +///@todo: describe the meaning +class btDefaultCollisionConfiguration : public btCollisionConfiguration +{ + +protected: + + int m_persistentManifoldPoolSize; + + + btPoolAllocator* m_persistentManifoldPool; + bool m_ownsPersistentManifoldPool; + + + btPoolAllocator* m_collisionAlgorithmPool; + bool m_ownsCollisionAlgorithmPool; + + //default simplex/penetration depth solvers + btVoronoiSimplexSolver* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc; + + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionAlgorithmCreateFunc* m_sphereSphereCF; + btCollisionAlgorithmCreateFunc* m_sphereBoxCF; + btCollisionAlgorithmCreateFunc* m_boxSphereCF; + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; + btCollisionAlgorithmCreateFunc* m_triangleSphereCF; + btCollisionAlgorithmCreateFunc* m_planeConvexCF; + btCollisionAlgorithmCreateFunc* m_convexPlaneCF; + +public: + + + btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btDefaultCollisionConfiguration(); + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() + { + return m_persistentManifoldPool; + } + + virtual btPoolAllocator* getCollisionAlgorithmPool() + { + return m_collisionAlgorithmPool; + } + + + virtual btVoronoiSimplexSolver* getSimplexSolver() + { + return m_simplexSolver; + } + + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + + ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm. + ///By default, this feature is disabled for best performance. + ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature. + ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled + ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first. + ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points. + ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection. + void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); + + void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); + +}; + +#endif //BT_DEFAULT_COLLISION_CONFIGURATION + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp new file mode 100644 index 00000000..5fa1c8be --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp @@ -0,0 +1,34 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btEmptyCollisionAlgorithm.h" + + + +btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) +{ +} + +void btEmptyAlgorithm::processCollision (const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ,const btDispatcherInfo& ,btManifoldResult* ) +{ +} + +btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) +{ + return btScalar(1.); +} + + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h new file mode 100644 index 00000000..cb0f1521 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -0,0 +1,54 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_EMPTY_ALGORITH +#define BT_EMPTY_ALGORITH +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + +#define ATTRIBUTE_ALIGNED(a) + +///EmptyAlgorithm is a stub for unsupported collision pairs. +///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame. +class btEmptyAlgorithm : public btCollisionAlgorithm +{ + +public: + + btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + (void)body0Wrap; + (void)body1Wrap; + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); + return new(mem) btEmptyAlgorithm(ci); + } + }; + +} ATTRIBUTE_ALIGNED(16); + +#endif //BT_EMPTY_ALGORITH diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.cpp new file mode 100644 index 00000000..86141fa6 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.cpp @@ -0,0 +1,171 @@ +/* +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 "btGhostObject.h" +#include "btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btAabbUtil2.h" + +btGhostObject::btGhostObject() +{ + m_internalType = CO_GHOST_OBJECT; +} + +btGhostObject::~btGhostObject() +{ + ///btGhostObject should have been removed from the world, so no overlapping objects + btAssert(!m_overlappingObjects.size()); +} + + +void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + //not found + m_overlappingObjects.push_back(otherObject); + } +} + +void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index~btHashedOverlappingPairCache(); + btAlignedFree( m_hashPairCache ); +} + +void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy) +{ + btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle(); + btAssert(actualThisProxy); + + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + m_overlappingObjects.push_back(otherObject); + m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy); + } +} + +void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle(); + btAssert(actualThisProxy); + + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (indexremoveOverlappingPair(actualThisProxy,otherProxy,dispatcher); + } +} + + +void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const +{ + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + } + + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + allowedCcdPenetration); + } + } + } + +} + +void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const +{ + btTransform rayFromTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFromWorld); + btTransform rayToTrans; + rayToTrans.setIdentity(); + rayToTrans.setOrigin(rayToWorld); + + + int i; + for (i=0;igetBroadphaseHandle())) + { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback); + } + } +} + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.h new file mode 100644 index 00000000..8ec86138 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.h @@ -0,0 +1,175 @@ +/* +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 BT_GHOST_OBJECT_H +#define BT_GHOST_OBJECT_H + + +#include "btCollisionObject.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h" +#include "LinearMath/btAlignedAllocator.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "btCollisionWorld.h" + +class btConvexShape; + +class btDispatcher; + +///The btGhostObject can keep track of all objects that are overlapping +///By default, this overlap is based on the AABB +///This is useful for creating a character controller, collision sensors/triggers, explosions etc. +///We plan on adding rayTest and other queries for the btGhostObject +ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject +{ +protected: + + btAlignedObjectArray m_overlappingObjects; + +public: + + btGhostObject(); + + virtual ~btGhostObject(); + + void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const; + + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; + + ///this method is mainly for expert/internal use only. + virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); + ///this method is mainly for expert/internal use only. + virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); + + int getNumOverlappingObjects() const + { + return m_overlappingObjects.size(); + } + + btCollisionObject* getOverlappingObject(int index) + { + return m_overlappingObjects[index]; + } + + const btCollisionObject* getOverlappingObject(int index) const + { + return m_overlappingObjects[index]; + } + + btAlignedObjectArray& getOverlappingPairs() + { + return m_overlappingObjects; + } + + const btAlignedObjectArray getOverlappingPairs() const + { + return m_overlappingObjects; + } + + // + // internal cast + // + + static const btGhostObject* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_GHOST_OBJECT) + return (const btGhostObject*)colObj; + return 0; + } + static btGhostObject* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_GHOST_OBJECT) + return (btGhostObject*)colObj; + return 0; + } + +}; + +class btPairCachingGhostObject : public btGhostObject +{ + btHashedOverlappingPairCache* m_hashPairCache; + +public: + + btPairCachingGhostObject(); + + virtual ~btPairCachingGhostObject(); + + ///this method is mainly for expert/internal use only. + virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0); + + virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0); + + btHashedOverlappingPairCache* getOverlappingPairCache() + { + return m_hashPairCache; + } + +}; + + + +///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject. +class btGhostPairCallback : public btOverlappingPairCallback +{ + +public: + btGhostPairCallback() + { + } + + virtual ~btGhostPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; + btGhostObject* ghost0 = btGhostObject::upcast(colObj0); + btGhostObject* ghost1 = btGhostObject::upcast(colObj1); + if (ghost0) + ghost0->addOverlappingObjectInternal(proxy1, proxy0); + if (ghost1) + ghost1->addOverlappingObjectInternal(proxy0, proxy1); + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) + { + btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject; + btGhostObject* ghost0 = btGhostObject::upcast(colObj0); + btGhostObject* ghost1 = btGhostObject::upcast(colObj1); + if (ghost0) + ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0); + if (ghost1) + ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1); + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) + { + btAssert(0); + //need to keep track of all ghost objects and call them here + //m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher); + } + + + +}; + +#endif + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp new file mode 100644 index 00000000..cfcca565 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp @@ -0,0 +1,278 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "btHashedSimplePairCache.h" + + +#include + +int gOverlappingSimplePairs = 0; +int gRemoveSimplePairs =0; +int gAddedSimplePairs =0; +int gFindSimplePairs =0; + + + + +btHashedSimplePairCache::btHashedSimplePairCache(): + m_blockedForChanges(false) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); + growTables(); +} + + + + +btHashedSimplePairCache::~btHashedSimplePairCache() +{ +} + + + + + + +void btHashedSimplePairCache::removeAllPairs() +{ + m_overlappingPairArray.clear(); + m_hashTable.clear(); + m_next.clear(); + + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); + growTables(); +} + + + +btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB) +{ + gFindSimplePairs++; + + + /*if (indexA > indexB) + btSwap(indexA, indexB);*/ + + int hash = static_cast(getHash(static_cast(indexA), static_cast(indexB)) & (m_overlappingPairArray.capacity()-1)); + + if (hash >= m_hashTable.size()) + { + return NULL; + } + + int index = m_hashTable[hash]; + while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], indexA, indexB) == false) + { + index = m_next[index]; + } + + if (index == BT_SIMPLE_NULL_PAIR) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; +} + +//#include + +void btHashedSimplePairCache::growTables() +{ + + int newCapacity = m_overlappingPairArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_SIMPLE_NULL_PAIR; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_SIMPLE_NULL_PAIR; + } + + for(i=0;i(getHash(static_cast(indexA),static_cast(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + m_next[i] = m_hashTable[hashValue]; + m_hashTable[hashValue] = i; + } + + + } +} + +btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB) +{ + + int hash = static_cast(getHash(static_cast(indexA),static_cast(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + + + btSimplePair* pair = internalFindPair(indexA, indexB, hash); + if (pair != NULL) + { + return pair; + } + + int count = m_overlappingPairArray.size(); + int oldCapacity = m_overlappingPairArray.capacity(); + void* mem = &m_overlappingPairArray.expandNonInitializing(); + + int newCapacity = m_overlappingPairArray.capacity(); + + if (oldCapacity < newCapacity) + { + growTables(); + //hash with new capacity + hash = static_cast(getHash(static_cast(indexA),static_cast(indexB)) & (m_overlappingPairArray.capacity()-1)); + } + + pair = new (mem) btSimplePair(indexA,indexB); + + pair->m_userPointer = 0; + + m_next[count] = m_hashTable[hash]; + m_hashTable[hash] = count; + + return pair; +} + + + +void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB) +{ + gRemoveSimplePairs++; + + + /*if (indexA > indexB) + btSwap(indexA, indexB);*/ + + int hash = static_cast(getHash(static_cast(indexA),static_cast(indexB)) & (m_overlappingPairArray.capacity()-1)); + + btSimplePair* pair = internalFindPair(indexA, indexB, hash); + if (pair == NULL) + { + return 0; + } + + + void* userData = pair->m_userPointer; + + + int pairIndex = int(pair - &m_overlappingPairArray[0]); + btAssert(pairIndex < m_overlappingPairArray.size()); + + // Remove the pair from the hash table. + int index = m_hashTable[hash]; + btAssert(index != BT_SIMPLE_NULL_PAIR); + + int previous = BT_SIMPLE_NULL_PAIR; + while (index != pairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_SIMPLE_NULL_PAIR) + { + btAssert(m_next[previous] == pairIndex); + m_next[previous] = m_next[pairIndex]; + } + else + { + m_hashTable[hash] = m_next[pairIndex]; + } + + // We now move the last pair into spot of the + // pair being removed. We need to fix the hash + // table indices to support the move. + + int lastPairIndex = m_overlappingPairArray.size() - 1; + + // If the removed pair is the last pair, we are done. + if (lastPairIndex == pairIndex) + { + m_overlappingPairArray.pop_back(); + return userData; + } + + // Remove the last pair from the hash table. + const btSimplePair* last = &m_overlappingPairArray[lastPairIndex]; + /* missing swap here too, Nat. */ + int lastHash = static_cast(getHash(static_cast(last->m_indexA), static_cast(last->m_indexB)) & (m_overlappingPairArray.capacity()-1)); + + index = m_hashTable[lastHash]; + btAssert(index != BT_SIMPLE_NULL_PAIR); + + previous = BT_SIMPLE_NULL_PAIR; + while (index != lastPairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_SIMPLE_NULL_PAIR) + { + btAssert(m_next[previous] == lastPairIndex); + m_next[previous] = m_next[lastPairIndex]; + } + else + { + m_hashTable[lastHash] = m_next[lastPairIndex]; + } + + // Copy the last pair into the remove pair's spot. + m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; + + // Insert the last pair into the hash table + m_next[pairIndex] = m_hashTable[lastHash]; + m_hashTable[lastHash] = pairIndex; + + m_overlappingPairArray.pop_back(); + + return userData; +} +//#include + + + + + + + + + + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h new file mode 100644 index 00000000..e88ef97e --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h @@ -0,0 +1,174 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_HASHED_SIMPLE_PAIR_CACHE_H +#define BT_HASHED_SIMPLE_PAIR_CACHE_H + + + +#include "LinearMath/btAlignedObjectArray.h" + +const int BT_SIMPLE_NULL_PAIR=0xffffffff; + +struct btSimplePair +{ + btSimplePair(int indexA,int indexB) + :m_indexA(indexA), + m_indexB(indexB), + m_userPointer(0) + { + } + + int m_indexA; + int m_indexB; + union + { + void* m_userPointer; + int m_userValue; + }; +}; + +typedef btAlignedObjectArray btSimplePairArray; + + + +extern int gOverlappingSimplePairs; +extern int gRemoveSimplePairs; +extern int gAddedSimplePairs; +extern int gFindSimplePairs; + + + + +class btHashedSimplePairCache +{ + btSimplePairArray m_overlappingPairArray; + + bool m_blockedForChanges; + + +protected: + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + + +public: + btHashedSimplePairCache(); + virtual ~btHashedSimplePairCache(); + + void removeAllPairs(); + + virtual void* removeOverlappingPair(int indexA,int indexB); + + // Add a pair and return the new pair. If the pair already exists, + // no new pair is created and the old one is returned. + virtual btSimplePair* addOverlappingPair(int indexA,int indexB) + { + gAddedSimplePairs++; + + return internalAddPair(indexA,indexB); + } + + + virtual btSimplePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btSimplePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + btSimplePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btSimplePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + + btSimplePair* findPair(int indexA,int indexB); + + int GetCount() const { return m_overlappingPairArray.size(); } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } +private: + + btSimplePair* internalAddPair(int indexA, int indexB); + + void growTables(); + + SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB) + { + return pair.m_indexA == indexA && pair.m_indexB == indexB; + } + + + + SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB) + { + int key = static_cast(((unsigned int)indexA) | (((unsigned int)indexB) <<16)); + // Thomas Wang's hash + + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return static_cast(key); + } + + + + + + SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA , int proxyIdB, int hash) + { + + int index = m_hashTable[hash]; + + while( index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false) + { + index = m_next[index]; + } + + if ( index == BT_SIMPLE_NULL_PAIR ) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; + } + + +}; + + + + +#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H + + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp new file mode 100644 index 00000000..73fa4e87 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp @@ -0,0 +1,842 @@ +#include "btInternalEdgeUtility.h" + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +//#define DEBUG_INTERNAL_EDGE + +#ifdef DEBUG_INTERNAL_EDGE +#include +#endif //DEBUG_INTERNAL_EDGE + + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW +static btIDebugDraw* gDebugDrawer = 0; + +void btSetDebugDrawer(btIDebugDraw* debugDrawer) +{ + gDebugDrawer = debugDrawer; +} + +static void btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color) +{ + if (gDebugDrawer) + gDebugDrawer->drawLine(from,to,color); +} +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + +static int btGetHash(int partId, int triangleIndex) +{ + int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + return hash; +} + + + +static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB) +{ + const btVector3 refAxis0 = edgeA; + const btVector3 refAxis1 = normalA; + const btVector3 swingAxis = normalB; + btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + return angle; +} + + +struct btConnectivityProcessor : public btTriangleCallback +{ + int m_partIdA; + int m_triangleIndexA; + btVector3* m_triangleVerticesA; + btTriangleInfoMap* m_triangleInfoMap; + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + //skip self-collisions + if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex)) + return; + + //skip duplicates (disabled for now) + //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex)) + // return; + + //search for shared vertices and edges + int numshared = 0; + int sharedVertsA[3]={-1,-1,-1}; + int sharedVertsB[3]={-1,-1,-1}; + + ///skip degenerate triangles + btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2(); + if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold) + return; + + + btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2(); + ///skip degenerate triangles + if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold) + return; + +#if 0 + printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n", + m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(), + m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(), + m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ()); + + printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex); + printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n", + triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(), + triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(), + triangle[2].getX(),triangle[2].getY(),triangle[2].getZ()); +#endif + + for (int i=0;i<3;i++) + { + for (int j=0;j<3;j++) + { + if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold) + { + sharedVertsA[numshared] = i; + sharedVertsB[numshared] = j; + numshared++; + ///degenerate case + if(numshared >= 3) + return; + } + } + ///degenerate case + if(numshared >= 3) + return; + } + switch (numshared) + { + case 0: + { + break; + } + case 1: + { + //shared vertex + break; + } + case 2: + { + //shared edge + //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct + if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2) + { + sharedVertsA[0] = 2; + sharedVertsA[1] = 0; + int tmp = sharedVertsB[1]; + sharedVertsB[1] = sharedVertsB[0]; + sharedVertsB[0] = tmp; + } + + int hash = btGetHash(m_partIdA,m_triangleIndexA); + + btTriangleInfo* info = m_triangleInfoMap->find(hash); + if (!info) + { + btTriangleInfo tmp; + m_triangleInfoMap->insert(hash,tmp); + info = m_triangleInfoMap->find(hash); + } + + int sumvertsA = sharedVertsA[0]+sharedVertsA[1]; + int otherIndexA = 3-sumvertsA; + + + btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]); + + btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]); + int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]); + + btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]); + //btTriangleShape tB(triangle[0],triangle[1],triangle[2]); + + btVector3 normalA; + btVector3 normalB; + tA.calcNormal(normalA); + tB.calcNormal(normalB); + edge.normalize(); + btVector3 edgeCrossA = edge.cross(normalA).normalize(); + + { + btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]]; + if (edgeCrossA.dot(tmp) < 0) + { + edgeCrossA*=-1; + } + } + + btVector3 edgeCrossB = edge.cross(normalB).normalize(); + + { + btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]]; + if (edgeCrossB.dot(tmp) < 0) + { + edgeCrossB*=-1; + } + } + + btScalar angle2 = 0; + btScalar ang4 = 0.f; + + + btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB); + btScalar len2 = calculatedEdge.length2(); + + btScalar correctedAngle(0); + btVector3 calculatedNormalB = normalA; + bool isConvex = false; + + if (len2m_planarEpsilon) + { + angle2 = 0.f; + ang4 = 0.f; + } else + { + + calculatedEdge.normalize(); + btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA); + calculatedNormalA.normalize(); + angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB); + ang4 = SIMD_PI-angle2; + btScalar dotA = normalA.dot(edgeCrossB); + ///@todo: check if we need some epsilon, due to floating point imprecision + isConvex = (dotA<0.); + + correctedAngle = isConvex ? ang4 : -ang4; + btQuaternion orn2(calculatedEdge,-correctedAngle); + calculatedNormalB = btMatrix3x3(orn2)*normalA; + + + } + + + + + + //alternatively use + //btVector3 calculatedNormalB2 = quatRotate(orn,normalA); + + + switch (sumvertsA) + { + case 1: + { + btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1]; + btQuaternion orn(edge,-correctedAngle); + btVector3 computedNormalB = quatRotate(orn,normalA); + btScalar bla = computedNormalB.dot(normalB); + if (bla<0) + { + computedNormalB*=-1; + info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB; + } +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif//DEBUG_INTERNAL_EDGE + + info->m_edgeV0V1Angle = -correctedAngle; + + if (isConvex) + info->m_flags |= TRI_INFO_V0V1_CONVEX; + break; + } + case 2: + { + btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0]; + btQuaternion orn(edge,-correctedAngle); + btVector3 computedNormalB = quatRotate(orn,normalA); + if (computedNormalB.dot(normalB)<0) + { + computedNormalB*=-1; + info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB; + } + +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif //DEBUG_INTERNAL_EDGE + info->m_edgeV2V0Angle = -correctedAngle; + if (isConvex) + info->m_flags |= TRI_INFO_V2V0_CONVEX; + break; + } + case 3: + { + btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2]; + btQuaternion orn(edge,-correctedAngle); + btVector3 computedNormalB = quatRotate(orn,normalA); + if (computedNormalB.dot(normalB)<0) + { + info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB; + computedNormalB*=-1; + } +#ifdef DEBUG_INTERNAL_EDGE + if ((computedNormalB-normalB).length()>0.0001) + { + printf("warning: normals not identical\n"); + } +#endif //DEBUG_INTERNAL_EDGE + info->m_edgeV1V2Angle = -correctedAngle; + + if (isConvex) + info->m_flags |= TRI_INFO_V1V2_CONVEX; + break; + } + } + + break; + } + default: + { + // printf("warning: duplicate triangle\n"); + } + + } + } +}; +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// + +void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap) +{ + //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there! + if (trimeshShape->getTriangleInfoMap()) + return; + + trimeshShape->setTriangleInfoMap(triangleInfoMap); + + btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface(); + const btVector3& meshScaling = meshInterface->getScaling(); + + for (int partId = 0; partId< meshInterface->getNumSubParts();partId++) + { + const unsigned char *vertexbase = 0; + int numverts = 0; + PHY_ScalarType type = PHY_INTEGER; + int stride = 0; + const unsigned char *indexbase = 0; + int indexstride = 0; + int numfaces = 0; + PHY_ScalarType indicestype = PHY_INTEGER; + //PHY_ScalarType indexType=0; + + btVector3 triangleVerts[3]; + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId); + btVector3 aabbMin,aabbMax; + + for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++) + { + unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride); + + for (int j=2;j>=0;j--) + { + + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); + } + } + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangleVerts[0]); + aabbMax.setMax(triangleVerts[0]); + aabbMin.setMin(triangleVerts[1]); + aabbMax.setMax(triangleVerts[1]); + aabbMin.setMin(triangleVerts[2]); + aabbMax.setMax(triangleVerts[2]); + + btConnectivityProcessor connectivityProcessor; + connectivityProcessor.m_partIdA = partId; + connectivityProcessor.m_triangleIndexA = triangleIndex; + connectivityProcessor.m_triangleVerticesA = &triangleVerts[0]; + connectivityProcessor.m_triangleInfoMap = triangleInfoMap; + + trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax); + } + + } + +} + + + + +// Given a point and a line segment (defined by two points), compute the closest point +// in the line. Cap the point at the endpoints of the line segment. +void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint) +{ + btVector3 lineDelta = line1 - line0; + + // Handle degenerate lines + if ( lineDelta.fuzzyZero()) + { + nearestPoint = line0; + } + else + { + btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta); + + // Clamp the point to conform to the segment's endpoints + if ( delta < 0 ) + delta = 0; + else if ( delta > 1 ) + delta = 1; + + nearestPoint = line0 + lineDelta*delta; + } +} + + + + +bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal) +{ + btVector3 tri_normal = tri_normal_org; + //we only have a local triangle normal, not a local contact normal -> only normal in world space... + //either compute the current angle all in local space, or all in world space + + btVector3 edgeCross = edge.cross(tri_normal).normalize(); + btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB); + + if (correctedEdgeAngle<0) + { + if (curAngle < correctedEdgeAngle) + { + btScalar diffAngle = correctedEdgeAngle-curAngle; + btQuaternion rotation(edge,diffAngle ); + clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; + return true; + } + } + + if (correctedEdgeAngle>=0) + { + if (curAngle > correctedEdgeAngle) + { + btScalar diffAngle = correctedEdgeAngle-curAngle; + btQuaternion rotation(edge,diffAngle ); + clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB; + return true; + } + } + return false; +} + + + +/// Changes a btManifoldPoint collision normal to the normal from the mesh. +void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags) +{ + //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE); + if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE) + return; + + btBvhTriangleMeshShape* trimesh = 0; + + if( colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE ) + trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape(); + else + trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape(); + + btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap(); + if (!triangleInfoMapPtr) + return; + + int hash = btGetHash(partId0,index0); + + + btTriangleInfo* info = triangleInfoMapPtr->find(hash); + if (!info) + return; + + btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f; + + const btTriangleShape* tri_shape = static_cast(colObj0Wrap->getCollisionShape()); + btVector3 v0,v1,v2; + tri_shape->getVertex(0,v0); + tri_shape->getVertex(1,v1); + tri_shape->getVertex(2,v2); + + //btVector3 center = (v0+v1+v2)*btScalar(1./3.); + + btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0); + btVector3 tri_normal; + tri_shape->calcNormal(tri_normal); + + //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB); + btVector3 nearest; + btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest); + + btVector3 contact = cp.m_localPointB; +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + const btTransform& tr = colObj0->getWorldTransform(); + btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + + + bool isNearEdge = false; + + int numConcaveEdgeHits = 0; + int numConvexEdgeHits = 0; + + btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; + localContactNormalOnB.normalize();//is this necessary? + + // Get closest edge + int bestedge=-1; + btScalar disttobestedge=BT_LARGE_FLOAT; + // + // Edge 0 -> 1 + if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v0, v1, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=0; + disttobestedge=len; + } + } + // Edge 1 -> 2 + if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v1, v2, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=1; + disttobestedge=len; + } + } + // Edge 2 -> 0 + if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v2, v0, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=2; + disttobestedge=len; + } + } + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btVector3 upfix=tri_normal * btVector3(0.1f,0.1f,0.1f); + btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red ); +#endif + if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); +#endif + btScalar len = (contact-nearest).length(); + if(lenm_edgeDistanceThreshold) + if( bestedge==0 ) + { + btVector3 edge(v0-v1); + isNearEdge = true; + + if (info->m_edgeV0V1Angle==btScalar(0)) + { + numConcaveEdgeHits++; + } else + { + + bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX); + btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); + #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); + #endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 nA = swapFactor * tri_normal; + + btQuaternion orn(edge,info->m_edgeV0V1Angle); + btVector3 computedNormalB = quatRotate(orn,tri_normal); + if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB) + computedNormalB*=-1; + btVector3 nB = swapFactor*computedNormalB; + + btScalar NdotA = localContactNormalOnB.dot(nA); + btScalar NdotB = localContactNormalOnB.dot(nB); + bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); + +#ifdef DEBUG_INTERNAL_EDGE + { + + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + + if (backFacingNormal) + { + numConcaveEdgeHits++; + } + else + { + numConvexEdgeHits++; + btVector3 clampedLocalNormal; + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal); + if (isClamped) + { + if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) + { + btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal; + // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); + cp.m_normalWorldOnB = newNormal; + // Reproject collision point along normal. (what about cp.m_distance1?) + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB); + + } + } + } + } + } + } + + btNearestPointInLineSegment(contact,v1,v2,nearest); +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix , green ); +#endif + + if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + + + btScalar len = (contact-nearest).length(); + if(lenm_edgeDistanceThreshold) + if( bestedge==1 ) + { + isNearEdge = true; +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 edge(v1-v2); + + isNearEdge = true; + + if (info->m_edgeV1V2Angle == btScalar(0)) + { + numConcaveEdgeHits++; + } else + { + bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0; + btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); + #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); + #endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 nA = swapFactor * tri_normal; + + btQuaternion orn(edge,info->m_edgeV1V2Angle); + btVector3 computedNormalB = quatRotate(orn,tri_normal); + if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB) + computedNormalB*=-1; + btVector3 nB = swapFactor*computedNormalB; + +#ifdef DEBUG_INTERNAL_EDGE + { + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + + btScalar NdotA = localContactNormalOnB.dot(nA); + btScalar NdotB = localContactNormalOnB.dot(nB); + bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); + + if (backFacingNormal) + { + numConcaveEdgeHits++; + } + else + { + numConvexEdgeHits++; + btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; + btVector3 clampedLocalNormal; + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal); + if (isClamped) + { + if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) + { + btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal; + // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); + cp.m_normalWorldOnB = newNormal; + // Reproject collision point along normal. + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB); + } + } + } + } + } + } + + btNearestPointInLineSegment(contact,v2,v0,nearest); +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix , blue ); +#endif + + if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btScalar len = (contact-nearest).length(); + if(lenm_edgeDistanceThreshold) + if( bestedge==2 ) + { + isNearEdge = true; +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 edge(v2-v0); + + if (info->m_edgeV2V0Angle==btScalar(0)) + { + numConcaveEdgeHits++; + } else + { + + bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0; + btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1); + #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white); + #endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + btVector3 nA = swapFactor * tri_normal; + btQuaternion orn(edge,info->m_edgeV2V0Angle); + btVector3 computedNormalB = quatRotate(orn,tri_normal); + if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB) + computedNormalB*=-1; + btVector3 nB = swapFactor*computedNormalB; + +#ifdef DEBUG_INTERNAL_EDGE + { + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red); + } +#endif //DEBUG_INTERNAL_EDGE + + btScalar NdotA = localContactNormalOnB.dot(nA); + btScalar NdotB = localContactNormalOnB.dot(nB); + bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotBm_convexEpsilon); + + if (backFacingNormal) + { + numConcaveEdgeHits++; + } + else + { + numConvexEdgeHits++; + // printf("hitting convex edge\n"); + + + btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; + btVector3 clampedLocalNormal; + bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal); + if (isClamped) + { + if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0)) + { + btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal; + // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB); + cp.m_normalWorldOnB = newNormal; + // Reproject collision point along normal. + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB); + } + } + } + } + + + } + } + +#ifdef DEBUG_INTERNAL_EDGE + { + btVector3 color(0,1,1); + btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color); + } +#endif //DEBUG_INTERNAL_EDGE + + if (isNearEdge) + { + + if (numConcaveEdgeHits>0) + { + if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0) + { + //fix tri_normal so it pointing the same direction as the current local contact normal + if (tri_normal.dot(localContactNormalOnB) < 0) + { + tri_normal *= -1; + } + cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis()*tri_normal; + } else + { + btVector3 newNormal = tri_normal *frontFacing; + //if the tri_normal is pointing opposite direction as the current local contact normal, skip it + btScalar d = newNormal.dot(localContactNormalOnB) ; + if (d< 0) + { + return; + } + //modify the normal to be the triangle normal (or backfacing normal) + cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() *newNormal; + } + + // Reproject collision point along normal. + cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; + cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB); + } + } +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h new file mode 100644 index 00000000..7d9aafee --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h @@ -0,0 +1,47 @@ + +#ifndef BT_INTERNAL_EDGE_UTILITY_H +#define BT_INTERNAL_EDGE_UTILITY_H + +#include "LinearMath/btHashMap.h" +#include "LinearMath/btVector3.h" + +#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h" + +///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges. +///See also http://code.google.com/p/bullet/issues/detail?id=27 + +class btBvhTriangleMeshShape; +class btCollisionObject; +struct btCollisionObjectWrapper; +class btManifoldPoint; +class btIDebugDraw; + + + +enum btInternalEdgeAdjustFlags +{ + BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1, + BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended + BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4 +}; + + +///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo' +void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap); + + +///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo) +///If this info map is missing, or the triangle is not store in this map, nothing will be done +void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap,const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0); + +///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly. +///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap +//#define BT_INTERNAL_EDGE_DEBUG_DRAW + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW +void btSetDebugDrawer(btIDebugDraw* debugDrawer); +#endif //BT_INTERNAL_EDGE_DEBUG_DRAW + + +#endif //BT_INTERNAL_EDGE_UTILITY_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp new file mode 100644 index 00000000..4b2986a0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -0,0 +1,154 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +///This is to allow MaterialCombiner/Custom Friction/Restitution values +ContactAddedCallback gContactAddedCallback=0; + + + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1) +{ + btScalar friction = body0->getRollingFriction() * body1->getRollingFriction(); + + const btScalar MAX_FRICTION = btScalar(10.); + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1) +{ + btScalar friction = body0->getFriction() * body1->getFriction(); + + const btScalar MAX_FRICTION = btScalar(10.); + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1) +{ + return body0->getRestitution() * body1->getRestitution(); +} + + + +btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + :m_manifoldPtr(0), + m_body0Wrap(body0Wrap), + m_body1Wrap(body1Wrap) +#ifdef DEBUG_PART_INDEX + ,m_partId0(-1), + m_partId1(-1), + m_index0(-1), + m_index1(-1) +#endif //DEBUG_PART_INDEX +{ +} + + +void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) +{ + btAssert(m_manifoldPtr); + //order in manifold needs to match + + if (depth > m_manifoldPtr->getContactBreakingThreshold()) +// if (depth > m_manifoldPtr->getContactProcessingThreshold()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); + + btVector3 pointA = pointInWorld + normalOnBInWorld * depth; + + btVector3 localA; + btVector3 localB; + + if (isSwapped) + { + localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA ); + localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld); + } else + { + localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA ); + localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); + + newPt.m_combinedFriction = calculateCombinedFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + newPt.m_combinedRollingFriction = calculateCombinedRollingFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject()); + btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2); + + + + //BP mod, store contact triangles. + if (isSwapped) + { + newPt.m_partId0 = m_partId1; + newPt.m_partId1 = m_partId0; + newPt.m_index0 = m_index1; + newPt.m_index1 = m_index0; + } else + { + newPt.m_partId0 = m_partId0; + newPt.m_partId1 = m_partId1; + newPt.m_index0 = m_index0; + newPt.m_index1 = m_index1; + } + //printf("depth=%f\n",depth); + ///@todo, check this for any side effects + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + insertIndex = m_manifoldPtr->addManifoldPoint(newPt); + } + + //User can override friction and/or restitution + if (gContactAddedCallback && + //and if either of the two bodies requires custom material + ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) || + (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK))) + { + //experimental feature info, for per-triangle material etc. + const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap; + const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap; + (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1); + } + +} + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.h new file mode 100644 index 00000000..977b9a02 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -0,0 +1,150 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_MANIFOLD_RESULT_H +#define BT_MANIFOLD_RESULT_H + +class btCollisionObject; +struct btCollisionObjectWrapper; + +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btManifoldPoint; + +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + +#include "LinearMath/btTransform.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1); +extern ContactAddedCallback gContactAddedCallback; + +//#define DEBUG_PART_INDEX 1 + + +///btManifoldResult is a helper class to manage contact results. +class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result +{ +protected: + + btPersistentManifold* m_manifoldPtr; + + const btCollisionObjectWrapper* m_body0Wrap; + const btCollisionObjectWrapper* m_body1Wrap; + int m_partId0; + int m_partId1; + int m_index0; + int m_index1; + + +public: + + btManifoldResult() +#ifdef DEBUG_PART_INDEX + : + m_partId0(-1), + m_partId1(-1), + m_index0(-1), + m_index1(-1) +#endif //DEBUG_PART_INDEX + { + } + + btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btManifoldResult() {}; + + void setPersistentManifold(btPersistentManifold* manifoldPtr) + { + m_manifoldPtr = manifoldPtr; + } + + const btPersistentManifold* getPersistentManifold() const + { + return m_manifoldPtr; + } + btPersistentManifold* getPersistentManifold() + { + return m_manifoldPtr; + } + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + m_partId0=partId0; + m_index0=index0; + } + + virtual void setShapeIdentifiersB( int partId1,int index1) + { + m_partId1=partId1; + m_index1=index1; + } + + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + + SIMD_FORCE_INLINE void refreshContactPoints() + { + btAssert(m_manifoldPtr); + if (!m_manifoldPtr->getNumContacts()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); + + if (isSwapped) + { + m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(),m_body0Wrap->getCollisionObject()->getWorldTransform()); + } else + { + m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(),m_body1Wrap->getCollisionObject()->getWorldTransform()); + } + } + + const btCollisionObjectWrapper* getBody0Wrap() const + { + return m_body0Wrap; + } + const btCollisionObjectWrapper* getBody1Wrap() const + { + return m_body1Wrap; + } + + void setBody0Wrap(const btCollisionObjectWrapper* obj0Wrap) + { + m_body0Wrap = obj0Wrap; + } + + void setBody1Wrap(const btCollisionObjectWrapper* obj1Wrap) + { + m_body1Wrap = obj1Wrap; + } + + const btCollisionObject* getBody0Internal() const + { + return m_body0Wrap->getCollisionObject(); + } + + const btCollisionObject* getBody1Internal() const + { + return m_body1Wrap->getCollisionObject(); + } + + /// in the future we can let the user override the methods to combine restitution and friction + static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1); + static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1); +}; + +#endif //BT_MANIFOLD_RESULT_H diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp new file mode 100644 index 00000000..13447822 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -0,0 +1,450 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "LinearMath/btScalar.h" +#include "btSimulationIslandManager.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" + +//#include +#include "LinearMath/btQuickprof.h" + +btSimulationIslandManager::btSimulationIslandManager(): +m_splitIslands(true) +{ +} + +btSimulationIslandManager::~btSimulationIslandManager() +{ +} + + +void btSimulationIslandManager::initUnionFind(int n) +{ + m_unionFind.reset(n); +} + + +void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) +{ + + { + btOverlappingPairCache* pairCachePtr = colWorld->getPairCache(); + const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs(); + if (numOverlappingPairs) + { + btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr(); + + for (int i=0;im_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && + ((colObj1) && ((colObj1)->mergesSimulationIslands()))) + { + + m_unionFind.unite((colObj0)->getIslandTag(), + (colObj1)->getIslandTag()); + } + } + } + } +} + +#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION +void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) +{ + + // put the index into m_controllers into m_tag + int index = 0; + { + + int i; + for (i=0;igetCollisionObjectArray().size(); i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + //Adding filtering here + if (!collisionObject->isStaticOrKinematicObject()) + { + collisionObject->setIslandTag(index++); + } + collisionObject->setCompanionId(-1); + collisionObject->setHitFraction(btScalar(1.)); + } + } + // do the union find + + initUnionFind( index ); + + findUnions(dispatcher,colWorld); +} + +void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) +{ + // put the islandId ('find' value) into m_tag + { + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + if (!collisionObject->isStaticOrKinematicObject()) + { + collisionObject->setIslandTag( m_unionFind.find(index) ); + //Set the correct object offset in Collision Object Array + m_unionFind.getElement(index).m_sz = i; + collisionObject->setCompanionId(-1); + index++; + } else + { + collisionObject->setIslandTag(-1); + collisionObject->setCompanionId(-2); + } + } + } +} + + +#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION +void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) +{ + + initUnionFind( int (colWorld->getCollisionObjectArray().size())); + + // put the index into m_controllers into m_tag + { + + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size(); i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + collisionObject->setIslandTag(index); + collisionObject->setCompanionId(-1); + collisionObject->setHitFraction(btScalar(1.)); + index++; + + } + } + // do the union find + + findUnions(dispatcher,colWorld); +} + +void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) +{ + // put the islandId ('find' value) into m_tag + { + + + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + if (!collisionObject->isStaticOrKinematicObject()) + { + collisionObject->setIslandTag( m_unionFind.find(index) ); + collisionObject->setCompanionId(-1); + } else + { + collisionObject->setIslandTag(-1); + collisionObject->setCompanionId(-2); + } + index++; + } + } +} + +#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION + +inline int getIslandId(const btPersistentManifold* lhs) +{ + int islandId; + const btCollisionObject* rcolObj0 = static_cast(lhs->getBody0()); + const btCollisionObject* rcolObj1 = static_cast(lhs->getBody1()); + islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag(); + return islandId; + +} + + + +/// function object that routes calls to operator< +class btPersistentManifoldSortPredicate +{ + public: + + SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const + { + return getIslandId(lhs) < getIslandId(rhs); + } +}; + + +void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld) +{ + + BT_PROFILE("islandUnionFindAndQuickSort"); + + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + + m_islandmanifold.resize(0); + + //we are going to sort the unionfind array, and store the element id in the size + //afterwards, we clean unionfind, to make sure no-one uses it anymore + + getUnionFind().sortIslands(); + int numElem = getUnionFind().getNumElements(); + + int endIslandIndex=1; + int startIslandIndex; + + + //update the sleeping state for bodies, if all are sleeping + for ( startIslandIndex=0;startIslandIndexgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + if (colObj0->getIslandTag() == islandId) + { + if (colObj0->getActivationState()== ACTIVE_TAG) + { + allSleeping = false; + } + if (colObj0->getActivationState()== DISABLE_DEACTIVATION) + { + allSleeping = false; + } + } + } + + + if (allSleeping) + { + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + colObj0->setActivationState( ISLAND_SLEEPING ); + } + } + } else + { + + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { +// printf("error in island management\n"); + } + + btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + if ( colObj0->getActivationState() == ISLAND_SLEEPING) + { + colObj0->setActivationState( WANTS_DEACTIVATION); + colObj0->setDeactivationTime(0.f); + } + } + } + } + } + + + int i; + int maxNumManifolds = dispatcher->getNumManifolds(); + +//#define SPLIT_ISLANDS 1 +//#ifdef SPLIT_ISLANDS + + +//#endif //SPLIT_ISLANDS + + + for (i=0;igetManifoldByIndexInternal(i); + + const btCollisionObject* colObj0 = static_cast(manifold->getBody0()); + const btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + + ///@todo: check sleeping conditions! + if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || + ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) + { + + //kinematic objects don't merge islands, but wake up all connected objects + if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + { + if (colObj0->hasContactResponse()) + colObj1->activate(); + } + if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + { + if (colObj1->hasContactResponse()) + colObj0->activate(); + } + if(m_splitIslands) + { + //filtering for response + if (dispatcher->needsResponse(colObj0,colObj1)) + m_islandmanifold.push_back(manifold); + } + } + } +} + + + +///@todo: this is random access, it can be walked 'cache friendly'! +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback) +{ + btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); + + buildIslands(dispatcher,collisionWorld); + + int endIslandIndex=1; + int startIslandIndex; + int numElem = getUnionFind().getNumElements(); + + BT_PROFILE("processIslands"); + + if(!m_splitIslands) + { + btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); + int maxNumManifolds = dispatcher->getNumManifolds(); + callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); + } + else + { + // Sort manifolds, based on islands + // Sort the vector using predicate and std::sort + //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); + + int numManifolds = int (m_islandmanifold.size()); + + //tried a radix sort, but quicksort/heapsort seems still faster + //@todo rewrite island management + m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); + //m_islandmanifold.heapSort(btPersistentManifoldSortPredicate()); + + //now process all active islands (sets of manifolds for now) + + int startManifoldIndex = 0; + int endManifoldIndex = 1; + + //int islandId; + + + + // printf("Start Islands\n"); + + //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated + for ( startIslandIndex=0;startIslandIndexisActive()) + islandSleeping = false; + } + + + //find the accompanying contact manifold for this islandId + int numIslandManifolds = 0; + btPersistentManifold** startManifold = 0; + + if (startManifoldIndexprocessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); + // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); + } + + if (numIslandManifolds) + { + startManifoldIndex = endManifoldIndex; + } + + m_islandBodies.resize(0); + } + } // else if(!splitIslands) + +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h new file mode 100644 index 00000000..e24c6afe --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SIMULATION_ISLAND_MANAGER_H +#define BT_SIMULATION_ISLAND_MANAGER_H + +#include "BulletCollision/CollisionDispatch/btUnionFind.h" +#include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btCollisionObject.h" + +class btCollisionObject; +class btCollisionWorld; +class btDispatcher; +class btPersistentManifold; + + +///SimulationIslandManager creates and handles simulation islands, using btUnionFind +class btSimulationIslandManager +{ + btUnionFind m_unionFind; + + btAlignedObjectArray m_islandmanifold; + btAlignedObjectArray m_islandBodies; + + bool m_splitIslands; + +public: + btSimulationIslandManager(); + virtual ~btSimulationIslandManager(); + + + void initUnionFind(int n); + + + btUnionFind& getUnionFind() { return m_unionFind;} + + virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher); + virtual void storeIslandActivationState(btCollisionWorld* world); + + + void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); + + + + struct IslandCallback + { + virtual ~IslandCallback() {}; + + virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; + }; + + void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback); + + void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld); + + bool getSplitIslands() + { + return m_splitIslands; + } + void setSplitIslands(bool doSplitIslands) + { + m_splitIslands = doSplitIslands; + } + +}; + +#endif //BT_SIMULATION_ISLAND_MANAGER_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp new file mode 100644 index 00000000..e8b567e0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -0,0 +1,214 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" +//#include + +btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped) +: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ + const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? col1Wrap : col0Wrap; + const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? col0Wrap : col1Wrap; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject())) + { + m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject()); + m_ownManifold = true; + } +} + + +btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + + + +void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + if (!m_manifoldPtr) + return; + + const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? body1Wrap : body0Wrap; + const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? body0Wrap : body1Wrap; + + btVector3 pOnBox; + + btVector3 normalOnSurfaceB; + btScalar penetrationDepth; + btVector3 sphereCenter = sphereObjWrap->getWorldTransform().getOrigin(); + const btSphereShape* sphere0 = (const btSphereShape*)sphereObjWrap->getCollisionShape(); + btScalar radius = sphere0->getRadius(); + btScalar maxContactDistance = m_manifoldPtr->getContactBreakingThreshold(); + + resultOut->setPersistentManifold(m_manifoldPtr); + + if (getSphereDistance(boxObjWrap, pOnBox, normalOnSurfaceB, penetrationDepth, sphereCenter, radius, maxContactDistance)) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->addContactPoint(normalOnSurfaceB, pOnBox, penetrationDepth); + } + + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } + +} + +btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + +bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance ) +{ + const btBoxShape* boxShape= (const btBoxShape*)boxObjWrap->getCollisionShape(); + btVector3 const &boxHalfExtent = boxShape->getHalfExtentsWithoutMargin(); + btScalar boxMargin = boxShape->getMargin(); + penetrationDepth = 1.0f; + + // convert the sphere position to the box's local space + btTransform const &m44T = boxObjWrap->getWorldTransform(); + btVector3 sphereRelPos = m44T.invXform(sphereCenter); + + // Determine the closest point to the sphere center in the box + btVector3 closestPoint = sphereRelPos; + closestPoint.setX( btMin(boxHalfExtent.getX(), closestPoint.getX()) ); + closestPoint.setX( btMax(-boxHalfExtent.getX(), closestPoint.getX()) ); + closestPoint.setY( btMin(boxHalfExtent.getY(), closestPoint.getY()) ); + closestPoint.setY( btMax(-boxHalfExtent.getY(), closestPoint.getY()) ); + closestPoint.setZ( btMin(boxHalfExtent.getZ(), closestPoint.getZ()) ); + closestPoint.setZ( btMax(-boxHalfExtent.getZ(), closestPoint.getZ()) ); + + btScalar intersectionDist = fRadius + boxMargin; + btScalar contactDist = intersectionDist + maxContactDistance; + normal = sphereRelPos - closestPoint; + + //if there is no penetration, we are done + btScalar dist2 = normal.length2(); + if (dist2 > contactDist * contactDist) + { + return false; + } + + btScalar distance; + + //special case if the sphere center is inside the box + if (dist2 <= SIMD_EPSILON) + { + distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal); + } + else //compute the penetration details + { + distance = normal.length(); + normal /= distance; + } + + pointOnBox = closestPoint + normal * boxMargin; +// v3PointOnSphere = sphereRelPos - (normal * fRadius); + penetrationDepth = distance - intersectionDist; + + // transform back in world space + btVector3 tmp = m44T(pointOnBox); + pointOnBox = tmp; +// tmp = m44T(v3PointOnSphere); +// v3PointOnSphere = tmp; + tmp = m44T.getBasis() * normal; + normal = tmp; + + return true; +} + +btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal ) +{ + //project the center of the sphere on the closest face of the box + btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX(); + btScalar minDist = faceDist; + closestPoint.setX( boxHalfExtent.getX() ); + normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f)); + + faceDist = boxHalfExtent.getX() + sphereRelPos.getX(); + if (faceDist < minDist) + { + minDist = faceDist; + closestPoint = sphereRelPos; + closestPoint.setX( -boxHalfExtent.getX() ); + normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f)); + } + + faceDist = boxHalfExtent.getY() - sphereRelPos.getY(); + if (faceDist < minDist) + { + minDist = faceDist; + closestPoint = sphereRelPos; + closestPoint.setY( boxHalfExtent.getY() ); + normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f)); + } + + faceDist = boxHalfExtent.getY() + sphereRelPos.getY(); + if (faceDist < minDist) + { + minDist = faceDist; + closestPoint = sphereRelPos; + closestPoint.setY( -boxHalfExtent.getY() ); + normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f)); + } + + faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ(); + if (faceDist < minDist) + { + minDist = faceDist; + closestPoint = sphereRelPos; + closestPoint.setZ( boxHalfExtent.getZ() ); + normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f)); + } + + faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ(); + if (faceDist < minDist) + { + minDist = faceDist; + closestPoint = sphereRelPos; + closestPoint.setZ( -boxHalfExtent.getZ() ); + normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f)); + } + + return minDist; +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h new file mode 100644 index 00000000..eefaedc9 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_BOX_COLLISION_ALGORITHM_H +#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + +public: + + btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped); + + virtual ~btSphereBoxCollisionAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + bool getSphereDistance( const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance ); + + btScalar getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal ); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false); + } else + { + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true); + } + } + }; + +}; + +#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp new file mode 100644 index 00000000..36ba21f5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -0,0 +1,106 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap) +: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr) + { + m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(),col1Wrap->getCollisionObject()); + m_ownManifold = true; + } +} + +btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + + if (!m_manifoldPtr) + return; + + resultOut->setPersistentManifold(m_manifoldPtr); + + btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape(); + btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape(); + + btVector3 diff = col0Wrap->getWorldTransform().getOrigin()- col1Wrap->getWorldTransform().getOrigin(); + btScalar len = diff.length(); + btScalar radius0 = sphere0->getRadius(); + btScalar radius1 = sphere1->getRadius(); + +#ifdef CLEAR_MANIFOLD + m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting +#endif + + ///iff distance positive, don't generate a new contact + if ( len > (radius0+radius1)) + { +#ifndef CLEAR_MANIFOLD + resultOut->refreshContactPoints(); +#endif //CLEAR_MANIFOLD + return; + } + ///distance (negative means penetration) + btScalar dist = len - (radius0+radius1); + + btVector3 normalOnSurfaceB(1,0,0); + if (len > SIMD_EPSILON) + { + normalOnSurfaceB = diff / len; + } + + ///point on A (worldspace) + ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; + ///point on B (worldspace) + btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; + + /// report a contact. internally this will be kept persistent, and contact reduction is done + + + resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); + +#ifndef CLEAR_MANIFOLD + resultOut->refreshContactPoints(); +#endif //CLEAR_MANIFOLD + +} + +btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)col0; + (void)col1; + (void)dispatchInfo; + (void)resultOut; + + //not yet + return btScalar(1.); +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h new file mode 100644 index 00000000..3517a568 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H +#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + +class btPersistentManifold; + +/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +/// Also provides the most basic sample for custom/user btCollisionAlgorithm +class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap); + + btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + virtual ~btSphereSphereCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); + return new(mem) btSphereSphereCollisionAlgorithm(0,ci,col0Wrap,col1Wrap); + } + }; + +}; + +#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp new file mode 100644 index 00000000..280a4d35 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "SphereTriangleDetector.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_ownManifold(false), +m_manifoldPtr(mf), +m_swapped(swapped) +{ + if (!m_manifoldPtr) + { + m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + m_ownManifold = true; + } +} + +btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + const btCollisionObjectWrapper* sphereObjWrap = m_swapped? col1Wrap : col0Wrap; + const btCollisionObjectWrapper* triObjWrap = m_swapped? col0Wrap : col1Wrap; + + btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape(); + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); + SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold()); + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds + input.m_transformA = sphereObjWrap->getWorldTransform(); + input.m_transformB = triObjWrap->getWorldTransform(); + + bool swapResults = m_swapped; + + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); + + if (m_ownManifold) + resultOut->refreshContactPoints(); + +} + +btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h new file mode 100644 index 00000000..6b6e39a7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H +#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H + +#include "btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +/// Also provides the most basic sample for custom/user btCollisionAlgorithm +class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_swapped; + +public: + btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped); + + btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btActivatingCollisionAlgorithm(ci) {} + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + virtual ~btSphereTriangleCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); + + return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_swapped); + } + }; + +}; + +#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H + diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.cpp new file mode 100644 index 00000000..52229335 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -0,0 +1,82 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btUnionFind.h" + + + +btUnionFind::~btUnionFind() +{ + Free(); + +} + +btUnionFind::btUnionFind() +{ + +} + +void btUnionFind::allocate(int N) +{ + m_elements.resize(N); +} +void btUnionFind::Free() +{ + m_elements.clear(); +} + + +void btUnionFind::reset(int N) +{ + allocate(N); + + for (int i = 0; i < N; i++) + { + m_elements[i].m_id = i; m_elements[i].m_sz = 1; + } +} + + +class btUnionFindElementSortPredicate +{ + public: + + bool operator() ( const btElement& lhs, const btElement& rhs ) const + { + return lhs.m_id < rhs.m_id; + } +}; + +///this is a special operation, destroying the content of btUnionFind. +///it sorts the elements, based on island id, in order to make it easy to iterate over islands +void btUnionFind::sortIslands() +{ + + //first store the original body index, and islandId + int numElements = m_elements.size(); + + for (int i=0;i m_elements; + + public: + + btUnionFind(); + ~btUnionFind(); + + + //this is a special operation, destroying the content of btUnionFind. + //it sorts the elements, based on island id, in order to make it easy to iterate over islands + void sortIslands(); + + void reset(int N); + + SIMD_FORCE_INLINE int getNumElements() const + { + return int(m_elements.size()); + } + SIMD_FORCE_INLINE bool isRoot(int x) const + { + return (x == m_elements[x].m_id); + } + + btElement& getElement(int index) + { + return m_elements[index]; + } + const btElement& getElement(int index) const + { + return m_elements[index]; + } + + void allocate(int N); + void Free(); + + + + + int find(int p, int q) + { + return (find(p) == find(q)); + } + + void unite(int p, int q) + { + int i = find(p), j = find(q); + if (i == j) + return; + +#ifndef USE_PATH_COMPRESSION + //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) ) + if (m_elements[i].m_sz < m_elements[j].m_sz) + { + m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; + } + else + { + m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz; + } +#else + m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; +#endif //USE_PATH_COMPRESSION + } + + int find(int x) + { + //btAssert(x < m_N); + //btAssert(x >= 0); + + while (x != m_elements[x].m_id) + { + //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically + + #ifdef USE_PATH_COMPRESSION + const btElement* elementPtr = &m_elements[m_elements[x].m_id]; + m_elements[x].m_id = elementPtr->m_id; + x = elementPtr->m_id; + #else// + x = m_elements[x].m_id; + #endif + //btAssert(x < m_N); + //btAssert(x >= 0); + + } + return x; + } + + + }; + + +#endif //BT_UNION_FIND_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.cpp new file mode 100644 index 00000000..ecce028c --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.cpp @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBox2dShape.h" + + +//{ + + +void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); +} + + +void btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //btScalar margin = btScalar(0.); + btVector3 halfExtents = getHalfExtentsWithMargin(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.h new file mode 100644 index 00000000..ce333783 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.h @@ -0,0 +1,371 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OBB_BOX_2D_SHAPE_H +#define BT_OBB_BOX_2D_SHAPE_H + +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMinMax.h" + +///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. +ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape +{ + + //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead + + btVector3 m_centroid; + btVector3 m_vertices[4]; + btVector3 m_normals[4]; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + for (int i=0;iboxHalfExtents.getY()) + minDimension = boxHalfExtents.getY(); + setSafeMargin(minDimension); + + m_shapeType = BOX_2D_SHAPE_PROXYTYPE; + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; + }; + + virtual void setMargin(btScalar collisionMargin) + { + //correct the m_implicitShapeDimensions for the margin + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + + btConvexInternalShape::setMargin(collisionMargin); + btVector3 newMargin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; + + } + virtual void setLocalScaling(const btVector3& scaling) + { + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; + + btConvexInternalShape::setLocalScaling(scaling); + + m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; + + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + + + + int getVertexCount() const + { + return 4; + } + + virtual int getNumVertices()const + { + return 4; + } + + const btVector3* getVertices() const + { + return &m_vertices[0]; + } + + const btVector3* getNormals() const + { + return &m_normals[0]; + } + + + + + + + + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const + { + //this plane might not be aligned... + btVector4 plane ; + getPlaneEquation(plane,i); + planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ()); + planeSupport = localGetSupportingVertex(-planeNormal); + } + + + const btVector3& getCentroid() const + { + return m_centroid; + } + + virtual int getNumPlanes() const + { + return 6; + } + + + + virtual int getNumEdges() const + { + return 12; + } + + + virtual void getVertex(int i,btVector3& vtx) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + vtx = btVector3( + halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1), + halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1), + halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); + } + + + virtual void getPlaneEquation(btVector4& plane,int i) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + switch (i) + { + case 0: + plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 1: + plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 2: + plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); + break; + case 3: + plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); + break; + case 4: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); + break; + case 5: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); + break; + default: + btAssert(0); + } + } + + + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const + //virtual void getEdge(int i,Edge& edge) const + { + int edgeVert0 = 0; + int edgeVert1 = 0; + + switch (i) + { + case 0: + edgeVert0 = 0; + edgeVert1 = 1; + break; + case 1: + edgeVert0 = 0; + edgeVert1 = 2; + break; + case 2: + edgeVert0 = 1; + edgeVert1 = 3; + + break; + case 3: + edgeVert0 = 2; + edgeVert1 = 3; + break; + case 4: + edgeVert0 = 0; + edgeVert1 = 4; + break; + case 5: + edgeVert0 = 1; + edgeVert1 = 5; + + break; + case 6: + edgeVert0 = 2; + edgeVert1 = 6; + break; + case 7: + edgeVert0 = 3; + edgeVert1 = 7; + break; + case 8: + edgeVert0 = 4; + edgeVert1 = 5; + break; + case 9: + edgeVert0 = 4; + edgeVert1 = 6; + break; + case 10: + edgeVert0 = 5; + edgeVert1 = 7; + break; + case 11: + edgeVert0 = 6; + edgeVert1 = 7; + break; + default: + btAssert(0); + + } + + getVertex(edgeVert0,pa ); + getVertex(edgeVert1,pb ); + } + + + + + + virtual bool isInside(const btVector3& pt,btScalar tolerance) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + //btScalar minDist = 2*tolerance; + + bool result = (pt.x() <= (halfExtents.x()+tolerance)) && + (pt.x() >= (-halfExtents.x()-tolerance)) && + (pt.y() <= (halfExtents.y()+tolerance)) && + (pt.y() >= (-halfExtents.y()-tolerance)) && + (pt.z() <= (halfExtents.z()+tolerance)) && + (pt.z() >= (-halfExtents.z()-tolerance)); + + return result; + } + + + //debugging + virtual const char* getName()const + { + return "Box2d"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 6; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + switch (index) + { + case 0: + penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); + break; + case 1: + penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); + break; + case 2: + penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); + break; + case 3: + penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); + break; + case 4: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); + break; + case 5: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); + break; + default: + btAssert(0); + } + } + +}; + +#endif //BT_OBB_BOX_2D_SHAPE_H + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.cpp new file mode 100644 index 00000000..3859138f --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include "btBoxShape.h" + +btBoxShape::btBoxShape( const btVector3& boxHalfExtents) +: btPolyhedralConvexShape() +{ + m_shapeType = BOX_SHAPE_PROXYTYPE; + + setSafeMargin(boxHalfExtents); + + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; +}; + + + + +void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); +} + + +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //btScalar margin = btScalar(0.); + btVector3 halfExtents = getHalfExtentsWithMargin(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.h new file mode 100644 index 00000000..715e3f2a --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -0,0 +1,314 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OBB_BOX_MINKOWSKI_H +#define BT_OBB_BOX_MINKOWSKI_H + +#include "btPolyhedralConvexShape.h" +#include "btCollisionMargin.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMinMax.h" + +///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. +ATTRIBUTE_ALIGNED16(class) btBoxShape: public btPolyhedralConvexShape +{ + + //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead + + +public: + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//scaling is included, margin is not + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + for (int i=0;i>1)) - halfExtents.y() * ((i&2)>>1), + halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); + } + + + virtual void getPlaneEquation(btVector4& plane,int i) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + switch (i) + { + case 0: + plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 1: + plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x()); + break; + case 2: + plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y()); + break; + case 3: + plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y()); + break; + case 4: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z()); + break; + case 5: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z()); + break; + default: + btAssert(0); + } + } + + + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const + //virtual void getEdge(int i,Edge& edge) const + { + int edgeVert0 = 0; + int edgeVert1 = 0; + + switch (i) + { + case 0: + edgeVert0 = 0; + edgeVert1 = 1; + break; + case 1: + edgeVert0 = 0; + edgeVert1 = 2; + break; + case 2: + edgeVert0 = 1; + edgeVert1 = 3; + + break; + case 3: + edgeVert0 = 2; + edgeVert1 = 3; + break; + case 4: + edgeVert0 = 0; + edgeVert1 = 4; + break; + case 5: + edgeVert0 = 1; + edgeVert1 = 5; + + break; + case 6: + edgeVert0 = 2; + edgeVert1 = 6; + break; + case 7: + edgeVert0 = 3; + edgeVert1 = 7; + break; + case 8: + edgeVert0 = 4; + edgeVert1 = 5; + break; + case 9: + edgeVert0 = 4; + edgeVert1 = 6; + break; + case 10: + edgeVert0 = 5; + edgeVert1 = 7; + break; + case 11: + edgeVert0 = 6; + edgeVert1 = 7; + break; + default: + btAssert(0); + + } + + getVertex(edgeVert0,pa ); + getVertex(edgeVert1,pb ); + } + + + + + + virtual bool isInside(const btVector3& pt,btScalar tolerance) const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + + //btScalar minDist = 2*tolerance; + + bool result = (pt.x() <= (halfExtents.x()+tolerance)) && + (pt.x() >= (-halfExtents.x()-tolerance)) && + (pt.y() <= (halfExtents.y()+tolerance)) && + (pt.y() >= (-halfExtents.y()-tolerance)) && + (pt.z() <= (halfExtents.z()+tolerance)) && + (pt.z() >= (-halfExtents.z()-tolerance)); + + return result; + } + + + //debugging + virtual const char* getName()const + { + return "Box"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 6; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + switch (index) + { + case 0: + penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); + break; + case 1: + penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); + break; + case 2: + penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); + break; + case 3: + penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); + break; + case 4: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); + break; + case 5: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); + break; + default: + btAssert(0); + } + } + +}; + + +#endif //BT_OBB_BOX_MINKOWSKI_H + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp new file mode 100644 index 00000000..ace4cfa2 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @@ -0,0 +1,466 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +//#define DISABLE_BVH + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" +#include "LinearMath/btSerializer.h" + +///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. +///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_triangleInfoMap(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) +{ + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + //construct bvh from meshInterface +#ifndef DISABLE_BVH + + if (buildBvh) + { + buildOptimizedBvh(); + } + +#endif //DISABLE_BVH + +} + +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_triangleInfoMap(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) +{ + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + //construct bvh from meshInterface +#ifndef DISABLE_BVH + + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } + +#endif //DISABLE_BVH + +} + +void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax) +{ + m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax ); + + m_localAabbMin.setMin(aabbMin); + m_localAabbMax.setMax(aabbMax); +} + + +void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax) +{ + m_bvh->refit( m_meshInterface, aabbMin,aabbMax ); + + recalcLocalAabb(); +} + +btBvhTriangleMeshShape::~btBvhTriangleMeshShape() +{ + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } +} + +void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ()); + } + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget); +} + +void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ()); + } + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); +} + +//perform bvh tree traversal and report overlapping triangles to 'callback' +void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + +#ifdef DISABLE_BVH + //brute force traverse all triangles + btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax); +#else + + //first get all the nodes + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + btVector3 m_triangle[3]; + + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j]; + + +#ifdef DEBUG_TRIANGLE_MESH + printf("%d ,",graphicsindex); +#endif //DEBUG_TRIANGLE_MESH + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3( + btScalar(graphicsbase[0])*meshScaling.getX(), + btScalar(graphicsbase[1])*meshScaling.getY(), + btScalar(graphicsbase[2])*meshScaling.getZ()); + } +#ifdef DEBUG_TRIANGLE_MESH + printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); +#endif //DEBUG_TRIANGLE_MESH + } + + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + + +#endif//DISABLE_BVH + + +} + +void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + buildOptimizedBvh(); + } +} + +void btBvhTriangleMeshShape::buildOptimizedBvh() +{ + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } + ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new(mem) btOptimizedBvh(); + //rebuild the bvh... + m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); + m_ownsBvh = true; +} + +void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling) +{ + btAssert(!m_bvh); + btAssert(!m_ownsBvh); + + m_bvh = bvh; + m_ownsBvh = false; + // update the scaling without rebuilding the bvh + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + } +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer; + + btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer); + + m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer); + + trimeshData->m_collisionMargin = float(m_collisionMargin); + + + + if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH)) + { + void* chunk = serializer->findPointer(m_bvh); + if (chunk) + { +#ifdef BT_USE_DOUBLE_PRECISION + trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk; + trimeshData->m_quantizedFloatBvh = 0; +#else + trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk; + trimeshData->m_quantizedDoubleBvh= 0; +#endif //BT_USE_DOUBLE_PRECISION + } else + { + +#ifdef BT_USE_DOUBLE_PRECISION + trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh); + trimeshData->m_quantizedFloatBvh = 0; +#else + trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh); + trimeshData->m_quantizedDoubleBvh= 0; +#endif //BT_USE_DOUBLE_PRECISION + + int sz = m_bvh->calculateSerializeBufferSizeNew(); + btChunk* chunk = serializer->allocate(sz,1); + const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh); + } + } else + { + trimeshData->m_quantizedFloatBvh = 0; + trimeshData->m_quantizedDoubleBvh = 0; + } + + + + if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP)) + { + void* chunk = serializer->findPointer(m_triangleInfoMap); + if (chunk) + { + trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk; + } else + { + trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap); + int sz = m_triangleInfoMap->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(sz,1); + const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap); + } + } else + { + trimeshData->m_triangleInfoMap = 0; + } + + return "btTriangleMeshShapeData"; +} + +void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const +{ + if (m_bvh) + { + int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place + btChunk* chunk = serializer->allocate(len,1); + const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh); + } +} + +void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const +{ + if (m_triangleInfoMap) + { + int len = m_triangleInfoMap->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap); + } +} + + + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h new file mode 100644 index 00000000..493d6355 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -0,0 +1,145 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BVH_TRIANGLE_MESH_SHAPE_H +#define BT_BVH_TRIANGLE_MESH_SHAPE_H + +#include "btTriangleMeshShape.h" +#include "btOptimizedBvh.h" +#include "LinearMath/btAlignedAllocator.h" +#include "btTriangleInfoMap.h" + +///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects. +///If you required moving concave triangle meshes, it is recommended to perform convex decomposition +///using HACD, see Bullet/Demos/ConvexDecompositionDemo. +///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes. +///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and +///cache friendly traversal for PlayStation 3 Cell SPU. +///It is recommended to enable useQuantizedAabbCompression for better memory usage. +///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method. +///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk. +///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example. +ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape +{ + + btOptimizedBvh* m_bvh; + btTriangleInfoMap* m_triangleInfoMap; + + bool m_useQuantizedAabbCompression; + bool m_ownsBvh; + bool m_pad[11];////need padding due to alignment + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); + + virtual ~btBvhTriangleMeshShape(); + + bool getOwnsBvh () const + { + return m_ownsBvh; + } + + + + void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget); + void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax); + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void refitTree(const btVector3& aabbMin,const btVector3& aabbMax); + + ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks + void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); + + //debugging + virtual const char* getName()const {return "BVHTRIANGLEMESH";} + + + virtual void setLocalScaling(const btVector3& scaling); + + btOptimizedBvh* getOptimizedBvh() + { + return m_bvh; + } + + void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1)); + + void buildOptimizedBvh(); + + bool usesQuantizedAabbCompression() const + { + return m_useQuantizedAabbCompression; + } + + void setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap) + { + m_triangleInfoMap = triangleInfoMap; + } + + const btTriangleInfoMap* getTriangleInfoMap() const + { + return m_triangleInfoMap; + } + + btTriangleInfoMap* getTriangleInfoMap() + { + return m_triangleInfoMap; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + virtual void serializeSingleBvh(btSerializer* serializer) const; + + virtual void serializeSingleTriangleInfoMap(btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btTriangleMeshShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btStridingMeshInterfaceData m_meshInterface; + + btQuantizedBvhFloatData *m_quantizedFloatBvh; + btQuantizedBvhDoubleData *m_quantizedDoubleBvh; + + btTriangleInfoMapData *m_triangleInfoMap; + + float m_collisionMargin; + + char m_pad3[4]; + +}; + + +SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const +{ + return sizeof(btTriangleMeshShapeData); +} + + + +#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp new file mode 100644 index 00000000..864df26e --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -0,0 +1,171 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btQuaternion.h" + +btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape () +{ + m_shapeType = CAPSULE_SHAPE_PROXYTYPE; + m_upAxis = 1; + m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); +} + + + btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + btVector3 vtx; + btScalar newDot; + + btScalar radius = getRadius(); + + + { + btVector3 pos(0,0,0); + pos[getUpAxis()] = getHalfHeight(); + + vtx = pos +vec*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); + + vtx = pos +vec*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + return supVec; + +} + + void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + + + btScalar radius = getRadius(); + + for (int j=0;j maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); + vtx = pos +vec*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + + } +} + + +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //as an approximation, take the inertia of the box that bounds the spheres + + btTransform ident; + ident.setIdentity(); + + + btScalar radius = getRadius(); + + btVector3 halfExtents(radius,radius,radius); + halfExtents[getUpAxis()]+=getHalfHeight(); + + btScalar margin = CONVEX_DISTANCE_MARGIN; + + btScalar lx=btScalar(2.)*(halfExtents[0]+margin); + btScalar ly=btScalar(2.)*(halfExtents[1]+margin); + btScalar lz=btScalar(2.)*(halfExtents[2]+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(.08333333); + + inertia[0] = scaledmass * (y2+z2); + inertia[1] = scaledmass * (x2+z2); + inertia[2] = scaledmass * (x2+y2); + +} + +btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) +{ + m_upAxis = 0; + m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); +} + + + + + + +btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) +{ + m_upAxis = 2; + m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); +} + + + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.h new file mode 100644 index 00000000..7578bb25 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -0,0 +1,184 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CAPSULE_SHAPE_H +#define BT_CAPSULE_SHAPE_H + +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + + +///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis. +///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres. +ATTRIBUTE_ALIGNED16(class) btCapsuleShape : public btConvexInternalShape +{ +protected: + int m_upAxis; + +protected: + ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. + btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;}; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btCapsuleShape(btScalar radius,btScalar height); + + ///CollisionShape Interface + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + /// btConvexShape Interface + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void setMargin(btScalar collisionMargin) + { + //correct the m_implicitShapeDimensions for the margin + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + + btConvexInternalShape::setMargin(collisionMargin); + btVector3 newMargin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin; + + } + + virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const + { + btVector3 halfExtents(getRadius(),getRadius(),getRadius()); + halfExtents[m_upAxis] = getRadius() + getHalfHeight(); + halfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + + aabbMin = center - extent; + aabbMax = center + extent; + } + + virtual const char* getName()const + { + return "CapsuleShape"; + } + + int getUpAxis() const + { + return m_upAxis; + } + + btScalar getRadius() const + { + int radiusAxis = (m_upAxis+2)%3; + return m_implicitShapeDimensions[radiusAxis]; + } + + btScalar getHalfHeight() const + { + return m_implicitShapeDimensions[m_upAxis]; + } + + virtual void setLocalScaling(const btVector3& scaling) + { + btVector3 oldMargin(getMargin(),getMargin(),getMargin()); + btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin; + btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling; + + btConvexInternalShape::setLocalScaling(scaling); + + m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin; + + } + + virtual btVector3 getAnisotropicRollingFrictionDirection() const + { + btVector3 aniDir(0,0,0); + aniDir[getUpAxis()]=1; + return aniDir; + } + + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///btCapsuleShapeX represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeX : public btCapsuleShape +{ +public: + + btCapsuleShapeX(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleX"; + } + + + +}; + +///btCapsuleShapeZ represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeZ : public btCapsuleShape +{ +public: + btCapsuleShapeZ(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleZ"; + } + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCapsuleShapeData +{ + btConvexInternalShapeData m_convexInternalShapeData; + + int m_upAxis; + + char m_padding[4]; +}; + +SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const +{ + return sizeof(btCapsuleShapeData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer; + + btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer); + + shapeData->m_upAxis = m_upAxis; + + return "btCapsuleShapeData"; +} + +#endif //BT_CAPSULE_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionMargin.h new file mode 100644 index 00000000..474bf1fb --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionMargin.h @@ -0,0 +1,27 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_MARGIN_H +#define BT_COLLISION_MARGIN_H + +///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape. +///This collision margin is used by Gjk and some other algorithms +///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API +#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01) + + + +#endif //BT_COLLISION_MARGIN_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.cpp new file mode 100644 index 00000000..39ee21ca --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -0,0 +1,119 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "LinearMath/btSerializer.h" + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" +{ +void btBulletCollisionProbe (); + +void btBulletCollisionProbe () {} +} + + + +void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const +{ + btTransform tr; + tr.setIdentity(); + btVector3 aabbMin,aabbMax; + + getAabb(tr,aabbMin,aabbMax); + + radius = (aabbMax-aabbMin).length()*btScalar(0.5); + center = (aabbMin+aabbMax)*btScalar(0.5); +} + + +btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const +{ + return getAngularMotionDisc() * defaultContactThreshold; +} + +btScalar btCollisionShape::getAngularMotionDisc() const +{ + ///@todo cache this value, to improve performance + btVector3 center; + btScalar disc; + getBoundingSphere(center,disc); + disc += (center).length(); + return disc; +} + +void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const +{ + //start with static aabb + getAabb(curTrans,temporalAabbMin,temporalAabbMax); + + btScalar temporalAabbMaxx = temporalAabbMax.getX(); + btScalar temporalAabbMaxy = temporalAabbMax.getY(); + btScalar temporalAabbMaxz = temporalAabbMax.getZ(); + btScalar temporalAabbMinx = temporalAabbMin.getX(); + btScalar temporalAabbMiny = temporalAabbMin.getY(); + btScalar temporalAabbMinz = temporalAabbMin.getZ(); + + // add linear motion + btVector3 linMotion = linvel*timeStep; + ///@todo: simd would have a vector max/min operation, instead of per-element access + if (linMotion.x() > btScalar(0.)) + temporalAabbMaxx += linMotion.x(); + else + temporalAabbMinx += linMotion.x(); + if (linMotion.y() > btScalar(0.)) + temporalAabbMaxy += linMotion.y(); + else + temporalAabbMiny += linMotion.y(); + if (linMotion.z() > btScalar(0.)) + temporalAabbMaxz += linMotion.z(); + else + temporalAabbMinz += linMotion.z(); + + //add conservative angular motion + btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep; + btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); + temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); + temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); + + temporalAabbMin -= angularMotion3d; + temporalAabbMax += angularMotion3d; +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer; + char* name = (char*) serializer->findNameForPointer(this); + shapeData->m_name = (char*)serializer->getUniquePointer(name); + if (shapeData->m_name) + { + serializer->serializeName(name); + } + shapeData->m_shapeType = m_shapeType; + //shapeData->m_padding//?? + return "btCollisionShapeData"; +} + +void btCollisionShape::serializeSingleShape(btSerializer* serializer) const +{ + int len = calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this); +} \ No newline at end of file diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.h new file mode 100644 index 00000000..ff017a20 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -0,0 +1,159 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_SHAPE_H +#define BT_COLLISION_SHAPE_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types +class btSerializer; + + +///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. +ATTRIBUTE_ALIGNED16(class) btCollisionShape +{ +protected: + int m_shapeType; + void* m_userPointer; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0) + { + } + + virtual ~btCollisionShape() + { + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void getBoundingSphere(btVector3& center,btScalar& radius) const; + + ///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. + virtual btScalar getAngularMotionDisc() const; + + virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const; + + + ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) + ///result is conservative + void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const; + + + + SIMD_FORCE_INLINE bool isPolyhedral() const + { + return btBroadphaseProxy::isPolyhedral(getShapeType()); + } + + SIMD_FORCE_INLINE bool isConvex2d() const + { + return btBroadphaseProxy::isConvex2d(getShapeType()); + } + + SIMD_FORCE_INLINE bool isConvex() const + { + return btBroadphaseProxy::isConvex(getShapeType()); + } + SIMD_FORCE_INLINE bool isNonMoving() const + { + return btBroadphaseProxy::isNonMoving(getShapeType()); + } + SIMD_FORCE_INLINE bool isConcave() const + { + return btBroadphaseProxy::isConcave(getShapeType()); + } + SIMD_FORCE_INLINE bool isCompound() const + { + return btBroadphaseProxy::isCompound(getShapeType()); + } + + SIMD_FORCE_INLINE bool isSoftBody() const + { + return btBroadphaseProxy::isSoftBody(getShapeType()); + } + + ///isInfinite is used to catch simulation error (aabb check) + SIMD_FORCE_INLINE bool isInfinite() const + { + return btBroadphaseProxy::isInfinite(getShapeType()); + } + +#ifndef __SPU__ + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; + + +//debugging support + virtual const char* getName()const =0 ; +#endif //__SPU__ + + + int getShapeType() const { return m_shapeType; } + + ///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction + ///See Bullet/Demos/RollingFrictionDemo for an example + virtual btVector3 getAnisotropicRollingFrictionDirection() const + { + return btVector3(1,1,1); + } + virtual void setMargin(btScalar margin) = 0; + virtual btScalar getMargin() const = 0; + + + ///optional user data pointer + void setUserPointer(void* userPtr) + { + m_userPointer = userPtr; + } + + void* getUserPointer() const + { + return m_userPointer; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + virtual void serializeSingleShape(btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCollisionShapeData +{ + char *m_name; + int m_shapeType; + char m_padding[4]; +}; + +SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const +{ + return sizeof(btCollisionShapeData); +} + + + +#endif //BT_COLLISION_SHAPE_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.cpp new file mode 100644 index 00000000..0aa75f2b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -0,0 +1,356 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btCompoundShape.h" +#include "btCollisionShape.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btSerializer.h" + +btCompoundShape::btCompoundShape(bool enableDynamicAabbTree) +: m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)), +m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)), +m_dynamicAabbTree(0), +m_updateRevision(1), +m_collisionMargin(btScalar(0.)), +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) +{ + m_shapeType = COMPOUND_SHAPE_PROXYTYPE; + + if (enableDynamicAabbTree) + { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); + } +} + + +btCompoundShape::~btCompoundShape() +{ + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->~btDbvt(); + btAlignedFree(m_dynamicAabbTree); + } +} + +void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) +{ + m_updateRevision++; + //m_childTransforms.push_back(localTransform); + //m_childShapes.push_back(shape); + btCompoundShapeChild child; + child.m_node = 0; + child.m_transform = localTransform; + child.m_childShape = shape; + child.m_childShapeType = shape->getShapeType(); + child.m_childMargin = shape->getMargin(); + + + //extend the local aabbMin/aabbMax + btVector3 localAabbMin,localAabbMax; + shape->getAabb(localTransform,localAabbMin,localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + { + m_localAabbMin[i] = localAabbMin[i]; + } + if (m_localAabbMax[i] < localAabbMax[i]) + { + m_localAabbMax[i] = localAabbMax[i]; + } + + } + if (m_dynamicAabbTree) + { + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + int index = m_children.size(); + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + + m_children.push_back(child); + +} + +void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb) +{ + m_children[childIndex].m_transform = newChildTransform; + + if (m_dynamicAabbTree) + { + ///update the dynamic aabb tree + btVector3 localAabbMin,localAabbMax; + m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax); + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //int index = m_children.size()-1; + m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds); + } + + if (shouldRecalculateLocalAabb) + { + recalculateLocalAabb(); + } +} + +void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) +{ + m_updateRevision++; + btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); + } + m_children.swap(childShapeIndex,m_children.size()-1); + if (m_dynamicAabbTree) + m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex; + m_children.pop_back(); + +} + + + +void btCompoundShape::removeChildShape(btCollisionShape* shape) +{ + m_updateRevision++; + // Find the children containing the shape specified, and remove those children. + //note: there might be multiple children using the same shape! + for(int i = m_children.size()-1; i >= 0 ; i--) + { + if(m_children[i].m_childShape == shape) + { + removeChildShapeByIndex(i); + } + } + + + + recalculateLocalAabb(); +} + +void btCompoundShape::recalculateLocalAabb() +{ + // Recalculate the local aabb + // Brute force, it iterates over all the shapes left. + + m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + + //extend the local aabbMin/aabbMax + for (int j = 0; j < m_children.size(); j++) + { + btVector3 localAabbMin,localAabbMax; + m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + m_localAabbMin[i] = localAabbMin[i]; + if (m_localAabbMax[i] < localAabbMax[i]) + m_localAabbMax[i] = localAabbMax[i]; + } + } +} + +///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + //avoid an illegal AABB when there are no children + if (!m_children.size()) + { + localHalfExtents.setValue(0,0,0); + localCenter.setValue(0,0,0); + } + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); + + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btVector3 center = trans(localCenter); + + btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + aabbMin = center-extent; + aabbMax = center+extent; + +} + +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //approximation: take the inertia from the aabb for now + btTransform ident; + ident.setIdentity(); + btVector3 aabbMin,aabbMax; + getAabb(ident,aabbMin,aabbMax); + + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz); + inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz); + inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly); + +} + + + + +void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const +{ + int n = m_children.size(); + + btScalar totalMass = 0; + btVector3 center(0, 0, 0); + int k; + + for (k = 0; k < n; k++) + { + btAssert(masses[k]>0); + center += m_children[k].m_transform.getOrigin() * masses[k]; + totalMass += masses[k]; + } + + btAssert(totalMass>0); + + center /= totalMass; + principal.setOrigin(center); + + btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); + for ( k = 0; k < n; k++) + { + btVector3 i; + m_children[k].m_childShape->calculateLocalInertia(masses[k], i); + + const btTransform& t = m_children[k].m_transform; + btVector3 o = t.getOrigin() - center; + + //compute inertia tensor in coordinate system of compound shape + btMatrix3x3 j = t.getBasis().transpose(); + j[0] *= i[0]; + j[1] *= i[1]; + j[2] *= i[2]; + j = t.getBasis() * j; + + //add inertia tensor + tensor[0] += j[0]; + tensor[1] += j[1]; + tensor[2] += j[2]; + + //compute inertia tensor of pointmass at o + btScalar o2 = o.length2(); + j[0].setValue(o2, 0, 0); + j[1].setValue(0, o2, 0); + j[2].setValue(0, 0, o2); + j[0] += o * -o.x(); + j[1] += o * -o.y(); + j[2] += o * -o.z(); + + //add inertia tensor of pointmass + tensor[0] += masses[k] * j[0]; + tensor[1] += masses[k] * j[1]; + tensor[2] += masses[k] * j[2]; + } + + tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); +} + + + + + +void btCompoundShape::setLocalScaling(const btVector3& scaling) +{ + + for(int i = 0; i < m_children.size(); i++) + { + btTransform childTrans = getChildTransform(i); + btVector3 childScale = m_children[i].m_childShape->getLocalScaling(); +// childScale = childScale * (childTrans.getBasis() * scaling); + childScale = childScale * scaling / m_localScaling; + m_children[i].m_childShape->setLocalScaling(childScale); + childTrans.setOrigin((childTrans.getOrigin()) * scaling / m_localScaling); + updateChildTransform(i, childTrans,false); + } + + m_localScaling = scaling; + recalculateLocalAabb(); + +} + + +void btCompoundShape::createAabbTreeFromChildren() +{ + if ( !m_dynamicAabbTree ) + { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); + + for ( int index = 0; index < m_children.size(); index++ ) + { + btCompoundShapeChild &child = m_children[index]; + + //extend the local aabbMin/aabbMax + btVector3 localAabbMin,localAabbMax; + child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax); + + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + } +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer; + btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer); + + shapeData->m_collisionMargin = float(m_collisionMargin); + shapeData->m_numChildShapes = m_children.size(); + shapeData->m_childShapePtr = 0; + if (shapeData->m_numChildShapes) + { + btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes); + btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr; + shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr); + + for (int i=0;im_numChildShapes;i++,memPtr++) + { + memPtr->m_childMargin = float(m_children[i].m_childMargin); + memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape); + //don't serialize shapes that already have been serialized + if (!serializer->findPointer(m_children[i].m_childShape)) + { + btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1); + const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer); + serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape); + } + + memPtr->m_childShapeType = m_children[i].m_childShapeType; + m_children[i].m_transform.serializeFloat(memPtr->m_transform); + } + serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr); + } + return "btCompoundShapeData"; +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.h new file mode 100644 index 00000000..141034a8 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -0,0 +1,212 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COMPOUND_SHAPE_H +#define BT_COMPOUND_SHAPE_H + +#include "btCollisionShape.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" +#include "LinearMath/btAlignedObjectArray.h" + +//class btOptimizedBvh; +struct btDbvt; + +ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTransform m_transform; + btCollisionShape* m_childShape; + int m_childShapeType; + btScalar m_childMargin; + struct btDbvtNode* m_node; +}; + +SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) +{ + return ( c1.m_transform == c2.m_transform && + c1.m_childShape == c2.m_childShape && + c1.m_childShapeType == c2.m_childShapeType && + c1.m_childMargin == c2.m_childMargin ); +} + +/// The btCompoundShape allows to store multiple other btCollisionShapes +/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. +/// It has an (optional) dynamic aabb tree to accelerate early rejection tests. +/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25 +/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape) +ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape +{ + btAlignedObjectArray m_children; + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + btDbvt* m_dynamicAabbTree; + + ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated + int m_updateRevision; + + btScalar m_collisionMargin; + +protected: + btVector3 m_localScaling; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btCompoundShape(bool enableDynamicAabbTree = true); + + virtual ~btCompoundShape(); + + void addChildShape(const btTransform& localTransform,btCollisionShape* shape); + + /// Remove all children shapes that contain the specified shape + virtual void removeChildShape(btCollisionShape* shape); + + void removeChildShapeByIndex(int childShapeindex); + + + int getNumChildShapes() const + { + return int (m_children.size()); + } + + btCollisionShape* getChildShape(int index) + { + return m_children[index].m_childShape; + } + const btCollisionShape* getChildShape(int index) const + { + return m_children[index].m_childShape; + } + + btTransform& getChildTransform(int index) + { + return m_children[index].m_transform; + } + const btTransform& getChildTransform(int index) const + { + return m_children[index].m_transform; + } + + ///set a new transform for a child, and update internal data structures (local aabb and dynamic tree) + void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true); + + + btCompoundShapeChild* getChildList() + { + return &m_children[0]; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. + Use this yourself if you modify the children or their transforms. */ + virtual void recalculateLocalAabb(); + + virtual void setLocalScaling(const btVector3& scaling); + + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + virtual const char* getName()const + { + return "Compound"; + } + + const btDbvt* getDynamicAabbTree() const + { + return m_dynamicAabbTree; + } + + btDbvt* getDynamicAabbTree() + { + return m_dynamicAabbTree; + } + + void createAabbTreeFromChildren(); + + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform + ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. + void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; + + int getUpdateRevision() const + { + return m_updateRevision; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCompoundShapeChildData +{ + btTransformFloatData m_transform; + btCollisionShapeData *m_childShape; + int m_childShapeType; + float m_childMargin; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btCompoundShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btCompoundShapeChildData *m_childShapePtr; + + int m_numChildShapes; + + float m_collisionMargin; + +}; + + +SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const +{ + return sizeof(btCompoundShapeData); +} + + + + + + + +#endif //BT_COMPOUND_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.cpp new file mode 100644 index 00000000..58ff84a5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.cpp @@ -0,0 +1,27 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConcaveShape.h" + +btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.)) +{ + +} + +btConcaveShape::~btConcaveShape() +{ + +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.h new file mode 100644 index 00000000..2917cc5b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONCAVE_SHAPE_H +#define BT_CONCAVE_SHAPE_H + +#include "btCollisionShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btTriangleCallback.h" + +/// PHY_ScalarType enumerates possible scalar types. +/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use +typedef enum PHY_ScalarType { + PHY_FLOAT, + PHY_DOUBLE, + PHY_INTEGER, + PHY_SHORT, + PHY_FIXEDPOINT88, + PHY_UCHAR +} PHY_ScalarType; + +///The btConcaveShape class provides an interface for non-moving (static) concave shapes. +///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. +ATTRIBUTE_ALIGNED16(class) btConcaveShape : public btCollisionShape +{ +protected: + btScalar m_collisionMargin; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConcaveShape(); + + virtual ~btConcaveShape(); + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0; + + virtual btScalar getMargin() const { + return m_collisionMargin; + } + virtual void setMargin(btScalar collisionMargin) + { + m_collisionMargin = collisionMargin; + } + + + +}; + +#endif //BT_CONCAVE_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.cpp new file mode 100644 index 00000000..2d83c8bf --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.cpp @@ -0,0 +1,147 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConeShape.h" + + + +btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (), +m_radius (radius), +m_height(height) +{ + m_shapeType = CONE_SHAPE_PROXYTYPE; + setConeUpIndex(1); + btVector3 halfExtents; + m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height)); +} + +btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height): +btConeShape(radius,height) +{ + setConeUpIndex(2); +} + +btConeShapeX::btConeShapeX (btScalar radius,btScalar height): +btConeShape(radius,height) +{ + setConeUpIndex(0); +} + +///choose upAxis index +void btConeShape::setConeUpIndex(int upIndex) +{ + switch (upIndex) + { + case 0: + m_coneIndices[0] = 1; + m_coneIndices[1] = 0; + m_coneIndices[2] = 2; + break; + case 1: + m_coneIndices[0] = 0; + m_coneIndices[1] = 1; + m_coneIndices[2] = 2; + break; + case 2: + m_coneIndices[0] = 0; + m_coneIndices[1] = 2; + m_coneIndices[2] = 1; + break; + default: + btAssert(0); + }; + + m_implicitShapeDimensions[m_coneIndices[0]] = m_radius; + m_implicitShapeDimensions[m_coneIndices[1]] = m_height; + m_implicitShapeDimensions[m_coneIndices[2]] = m_radius; +} + +btVector3 btConeShape::coneLocalSupport(const btVector3& v) const +{ + + btScalar halfHeight = m_height * btScalar(0.5); + + if (v[m_coneIndices[1]] > v.length() * m_sinAngle) + { + btVector3 tmp; + + tmp[m_coneIndices[0]] = btScalar(0.); + tmp[m_coneIndices[1]] = halfHeight; + tmp[m_coneIndices[2]] = btScalar(0.); + return tmp; + } + else { + btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]); + if (s > SIMD_EPSILON) { + btScalar d = m_radius / s; + btVector3 tmp; + tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d; + tmp[m_coneIndices[1]] = -halfHeight; + tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d; + return tmp; + } + else { + btVector3 tmp; + tmp[m_coneIndices[0]] = btScalar(0.); + tmp[m_coneIndices[1]] = -halfHeight; + tmp[m_coneIndices[2]] = btScalar(0.); + return tmp; + } + } + +} + +btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const +{ + return coneLocalSupport(vec); +} + +void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for (int i=0;im_convexInternalShapeData,serializer); + + shapeData->m_upIndex = m_coneIndices[1]; + + return "btConeShapeData"; +} + +#endif //BT_CONE_MINKOWSKI_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp new file mode 100644 index 00000000..10ea3e98 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp @@ -0,0 +1,92 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvex2dShape.h" + +btConvex2dShape::btConvex2dShape( btConvexShape* convexChildShape): +btConvexShape (), m_childConvexShape(convexChildShape) +{ + m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE; +} + +btConvex2dShape::~btConvex2dShape() +{ +} + + + +btVector3 btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); +} + +void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); +} + + +btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const +{ + return m_childConvexShape->localGetSupportingVertex(vec); +} + + +void btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + m_childConvexShape->calculateLocalInertia(mass,inertia); +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabb(t,aabbMin,aabbMax); +} + +void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); +} + +void btConvex2dShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btConvex2dShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btConvex2dShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btConvex2dShape::getMargin() const +{ + return m_childConvexShape->getMargin(); +} + +int btConvex2dShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.h new file mode 100644 index 00000000..bbd1caf4 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.h @@ -0,0 +1,82 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_2D_SHAPE_H +#define BT_CONVEX_2D_SHAPE_H + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0. +///For 2d boxes, the btBox2dShape is recommended. +ATTRIBUTE_ALIGNED16(class) btConvex2dShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvex2dShape( btConvexShape* convexChildShape); + + virtual ~btConvex2dShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "Convex2dShape"; + } + + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_CONVEX_2D_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp new file mode 100644 index 00000000..0623e351 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp @@ -0,0 +1,250 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +#if defined (_WIN32) || defined (__i386__) +#define BT_USE_SSE_IN_API +#endif + +#include "btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btSerializer.h" + +btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape () +{ + m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE; + m_unscaledPoints.resize(numPoints); + + unsigned char* pointsAddress = (unsigned char*)points; + + for (int i=0;im_convexInternalShapeData, serializer); + + int numElem = m_unscaledPoints.size(); + shapeData->m_numUnscaledPoints = numElem; +#ifdef BT_USE_DOUBLE_PRECISION + shapeData->m_unscaledPointsFloatPtr = 0; + shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0; +#else + shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]): 0; + shapeData->m_unscaledPointsDoublePtr = 0; +#endif + + if (numElem) + { + int sz = sizeof(btVector3Data); + // int sz2 = sizeof(btVector3DoubleData); + // int sz3 = sizeof(btVector3FloatData); + btChunk* chunk = serializer->allocate(sz,numElem); + btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]); + } + + return "btConvexHullShapeData"; +} + +void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const +{ +#if 1 + minProj = FLT_MAX; + maxProj = -FLT_MAX; + + int numVerts = m_unscaledPoints.size(); + for(int i=0;i maxProj) + { + maxProj = dp; + witnesPtMax=pt; + } + } +#else + btVector3 localAxis = dir*trans.getBasis(); + witnesPtMin = trans(localGetSupportingVertex(localAxis)); + witnesPtMax = trans(localGetSupportingVertex(-localAxis)); + + minProj = witnesPtMin.dot(dir); + maxProj = witnesPtMax.dot(dir); +#endif + + if(minProj>maxProj) + { + btSwap(minProj,maxProj); + btSwap(witnesPtMin,witnesPtMax); + } + + +} + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.h new file mode 100644 index 00000000..3bd598ec --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -0,0 +1,122 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_HULL_SHAPE_H +#define BT_CONVEX_HULL_SHAPE_H + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" + + +///The btConvexHullShape implements an implicit convex hull of an array of vertices. +///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex. +ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape +{ + btAlignedObjectArray m_unscaledPoints; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. + ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint. + ///btConvexHullShape make an internal copy of the points. + btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3)); + + void addPoint(const btVector3& point, bool recalculateLocalAabb = true); + + + btVector3* getUnscaledPoints() + { + return &m_unscaledPoints[0]; + } + + const btVector3* getUnscaledPoints() const + { + return &m_unscaledPoints[0]; + } + + ///getPoints is obsolete, please use getUnscaledPoints + const btVector3* getPoints() const + { + return getUnscaledPoints(); + } + + + + + SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const + { + return m_unscaledPoints[i] * m_localScaling; + } + + SIMD_FORCE_INLINE int getNumPoints() const + { + return m_unscaledPoints.size(); + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const; + + + //debugging + virtual const char* getName()const {return "Convex";} + + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + ///in case we receive negative scaling + virtual void setLocalScaling(const btVector3& scaling); + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btConvexHullShapeData +{ + btConvexInternalShapeData m_convexInternalShapeData; + + btVector3FloatData *m_unscaledPointsFloatPtr; + btVector3DoubleData *m_unscaledPointsDoublePtr; + + int m_numUnscaledPoints; + char m_padding3[4]; + +}; + + +SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const +{ + return sizeof(btConvexHullShapeData); +} + + +#endif //BT_CONVEX_HULL_SHAPE_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp new file mode 100644 index 00000000..083d60b1 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConvexInternalShape.h" + + + +btConvexInternalShape::btConvexInternalShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexInternalShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling.absolute(); +} + + + +void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ +#ifndef __SPU__ + //use localGetSupportingVertexWithoutMargin? + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +#endif +} + + + +btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + btAssert(0); + return btVector3(0,0,0); +#endif //__SPU__ + + } + + +btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape() + : btConvexInternalShape(), +m_localAabbMin(1,1,1), +m_localAabbMax(-1,-1,-1), +m_isLocalAabbValid(false) +{ +} + + +void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); +} + +void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling) +{ + btConvexInternalShape::setLocalScaling(scaling); + recalcLocalAabb(); +} + + +void btConvexInternalAabbCachingShape::recalcLocalAabb() +{ + m_isLocalAabbValid = true; + + #if 1 + static const btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + for ( int i = 0; i < 3; ++i ) + { + m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; + m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; + } + + #else + + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]+m_collisionMargin; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]-m_collisionMargin; + } + #endif +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.h new file mode 100644 index 00000000..37e04f5f --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -0,0 +1,224 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_INTERNAL_SHAPE_H +#define BT_CONVEX_INTERNAL_SHAPE_H + +#include "btConvexShape.h" +#include "LinearMath/btAabbUtil2.h" + + +///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. +///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN. +///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h +///Note that when creating small shapes (derived from btConvexInternalShape), +///you need to make sure to set a smaller collision margin, using the 'setMargin' API +///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape +ATTRIBUTE_ALIGNED16(class) btConvexInternalShape : public btConvexShape +{ + + protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding; + + btConvexInternalShape(); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + virtual ~btConvexInternalShape() + { + + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } + + ///warning: use setImplicitShapeDimensions with care + ///changing a collision shape while the body is in the world is not recommended, + ///it is best to remove the body from the world, then make the change, and re-add it + ///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs' + void setImplicitShapeDimensions(const btVector3& dimensions) + { + m_implicitShapeDimensions = dimensions; + } + + void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f) + { + btScalar safeMargin = defaultMarginMultiplier*minDimension; + if (safeMargin < getMargin()) + { + setMargin(safeMargin); + } + } + void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f) + { + //see http://code.google.com/p/bullet/issues/detail?id=349 + //this margin check could could be added to other collision shapes too, + //or add some assert/warning somewhere + btScalar minDimension=halfExtents[halfExtents.minAxis()]; + setSafeMargin(minDimension, defaultMarginMultiplier); + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } + + + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btConvexInternalShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btVector3FloatData m_localScaling; + + btVector3FloatData m_implicitShapeDimensions; + + float m_collisionMargin; + + int m_padding; + +}; + + + +SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const +{ + return sizeof(btConvexInternalShapeData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer; + btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer); + + m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions); + m_localScaling.serializeFloat(shapeData->m_localScaling); + shapeData->m_collisionMargin = float(m_collisionMargin); + + return "btConvexInternalShapeData"; +} + + + + +///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations +class btConvexInternalAabbCachingShape : public btConvexInternalShape +{ + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + bool m_isLocalAabbValid; + +protected: + + btConvexInternalAabbCachingShape(); + + void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax) + { + m_isLocalAabbValid = true; + m_localAabbMin = aabbMin; + m_localAabbMax = aabbMax; + } + + inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const + { + btAssert(m_isLocalAabbValid); + aabbMin = m_localAabbMin; + aabbMax = m_localAabbMax; + } + + inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const + { + + //lazy evaluation of local aabb + btAssert(m_isLocalAabbValid); + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); + } + +public: + + virtual void setLocalScaling(const btVector3& scaling); + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + void recalcLocalAabb(); + +}; + +#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp new file mode 100644 index 00000000..ad1d1bf7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp @@ -0,0 +1,139 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvexPointCloudShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" + +void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; + recalcLocalAabb(); +} + +#ifndef __SPU__ +btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + btScalar maxDot = btScalar(-BT_LARGE_FLOAT); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + if( m_numPoints > 0 ) + { + // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically. + // btVector3 scaled = vec * m_localScaling; + int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot); //FIXME: may violate encapsulation of m_unscaledPoints + return getScaledPoint(index); + } + + return supVec; +} + +void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for( int j = 0; j < numVectors; j++ ) + { + const btVector3& vec = vectors[j] * m_localScaling; // dot( a*c, b) = dot(a, b*c) + btScalar maxDot; + int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot); + supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT); + if( 0 <= index ) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = getScaledPoint(index); + supportVerticesOut[j][3] = maxDot; + } + } + +} + + + +btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + +#endif + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo +int btConvexPointCloudShape::getNumVertices() const +{ + return m_numPoints; +} + +int btConvexPointCloudShape::getNumEdges() const +{ + return 0; +} + +void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const +{ + btAssert (0); +} + +void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const +{ + vtx = m_unscaledPoints[i]*m_localScaling; +} + +int btConvexPointCloudShape::getNumPlanes() const +{ + return 0; +} + +void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const +{ + + btAssert(0); +} + +//not yet +bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const +{ + btAssert(0); + return false; +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h new file mode 100644 index 00000000..54b5afac --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h @@ -0,0 +1,105 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H +#define BT_CONVEX_POINT_CLOUD_SHAPE_H + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" + +///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices. +ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape +{ + btVector3* m_unscaledPoints; + int m_numPoints; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexPointCloudShape() + { + m_localScaling.setValue(1.f,1.f,1.f); + m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; + m_unscaledPoints = 0; + m_numPoints = 0; + } + + btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true) + { + m_localScaling = localScaling; + m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE; + m_unscaledPoints = points; + m_numPoints = numPoints; + + if (computeAabb) + recalcLocalAabb(); + } + + void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f)) + { + m_unscaledPoints = points; + m_numPoints = numPoints; + m_localScaling = localScaling; + + if (computeAabb) + recalcLocalAabb(); + } + + SIMD_FORCE_INLINE btVector3* getUnscaledPoints() + { + return m_unscaledPoints; + } + + SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const + { + return m_unscaledPoints; + } + + SIMD_FORCE_INLINE int getNumPoints() const + { + return m_numPoints; + } + + SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const + { + return m_unscaledPoints[index] * m_localScaling; + } + +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; +#endif + + + //debugging + virtual const char* getName()const {return "ConvexPointCloud";} + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + ///in case we receive negative scaling + virtual void setLocalScaling(const btVector3& scaling); +}; + + +#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp new file mode 100644 index 00000000..f4324c1f --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp @@ -0,0 +1,302 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + + +///This file was written by Erwin Coumans +///Separating axis rest based on work from Pierre Terdiman, see +///And contact clipping based on work from Simon Hobbs + +#include "btConvexPolyhedron.h" +#include "LinearMath/btHashMap.h" + +btConvexPolyhedron::btConvexPolyhedron() +{ + +} +btConvexPolyhedron::~btConvexPolyhedron() +{ + +} + + +inline bool IsAlmostZero(const btVector3& v) +{ + if(fabsf(v.x())>1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +struct btInternalVertexPair +{ + btInternalVertexPair(short int v0,short int v1) + :m_v0(v0), + m_v1(v1) + { + if (m_v1>m_v0) + btSwap(m_v0,m_v1); + } + short int m_v0; + short int m_v1; + int getHash() const + { + return m_v0+(m_v1<<16); + } + bool equals(const btInternalVertexPair& other) const + { + return m_v0==other.m_v0 && m_v1==other.m_v1; + } +}; + +struct btInternalEdge +{ + btInternalEdge() + :m_face0(-1), + m_face1(-1) + { + } + short int m_face0; + short int m_face1; +}; + +// + +#ifdef TEST_INTERNAL_OBJECTS +bool btConvexPolyhedron::testContainment() const +{ + for(int p=0;p<8;p++) + { + btVector3 LocalPt; + if(p==0) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]); + else if(p==1) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]); + else if(p==2) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]); + else if(p==3) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]); + else if(p==4) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]); + else if(p==5) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]); + else if(p==6) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]); + else if(p==7) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]); + + for(int i=0;i0.0f) + return false; + } + } + return true; +} +#endif + +void btConvexPolyhedron::initialize() +{ + + btHashMap edges; + + btScalar TotalArea = 0.0f; + + m_localCenter.setValue(0, 0, 0); + for(int i=0;im_face0>=0); + btAssert(edptr->m_face1<0); + edptr->m_face1 = i; + } else + { + btInternalEdge ed; + ed.m_face0 = i; + edges.insert(vp,ed); + } + } + } + +#ifdef USE_CONNECTED_FACES + for(int i=0;im_face0>=0); + btAssert(edptr->m_face1>=0); + + int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0; + m_faces[i].m_connectedFaces[j] = connectedFace; + } + } +#endif//USE_CONNECTED_FACES + + for(int i=0;iMaxX) MaxX = pt.x(); + if(pt.y()MaxY) MaxY = pt.y(); + if(pt.z()MaxZ) MaxZ = pt.z(); + } + mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ); + mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ); + + + +// const btScalar r = m_radius / sqrtf(2.0f); + const btScalar r = m_radius / sqrtf(3.0f); + const int LargestExtent = mE.maxAxis(); + const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f; + m_extents[0] = m_extents[1] = m_extents[2] = r; + m_extents[LargestExtent] = mE[LargestExtent]*0.5f; + bool FoundBox = false; + for(int j=0;j<1024;j++) + { + if(testContainment()) + { + FoundBox = true; + break; + } + + m_extents[LargestExtent] -= Step; + } + if(!FoundBox) + { + m_extents[0] = m_extents[1] = m_extents[2] = r; + } + else + { + // Refine the box + const btScalar Step = (m_radius - r)/1024.0f; + const int e0 = (1< maxProj) + { + maxProj = dp; + witnesPtMax = pt; + } + } + if(minProj>maxProj) + { + btSwap(minProj,maxProj); + btSwap(witnesPtMin,witnesPtMax); + } +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h new file mode 100644 index 00000000..d3cd066a --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h @@ -0,0 +1,65 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + + +///This file was written by Erwin Coumans + + +#ifndef _BT_POLYHEDRAL_FEATURES_H +#define _BT_POLYHEDRAL_FEATURES_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btAlignedObjectArray.h" + +#define TEST_INTERNAL_OBJECTS 1 + + +struct btFace +{ + btAlignedObjectArray m_indices; +// btAlignedObjectArray m_connectedFaces; + btScalar m_plane[4]; +}; + + +ATTRIBUTE_ALIGNED16(class) btConvexPolyhedron +{ + public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexPolyhedron(); + virtual ~btConvexPolyhedron(); + + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_faces; + btAlignedObjectArray m_uniqueEdges; + + btVector3 m_localCenter; + btVector3 m_extents; + btScalar m_radius; + btVector3 mC; + btVector3 mE; + + void initialize(); + bool testContainment() const; + + void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const; +}; + + +#endif //_BT_POLYHEDRAL_FEATURES_H + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.cpp new file mode 100644 index 00000000..f03d0b21 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -0,0 +1,455 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +#if defined (_WIN32) || defined (__i386__) +#define BT_USE_SSE_IN_API +#endif + +#include "btConvexShape.h" +#include "btTriangleShape.h" +#include "btSphereShape.h" +#include "btCylinderShape.h" +#include "btConeShape.h" +#include "btCapsuleShape.h" +#include "btConvexHullShape.h" +#include "btConvexPointCloudShape.h" + +///not supported on IBM SDK, until we fix the alignment of btVector3 +#if defined (__CELLOS_LV2__) && defined (__SPU__) +#include +static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); +} +#endif //__SPU__ + +btConvexShape::btConvexShape () +{ +} + +btConvexShape::~btConvexShape() +{ + +} + + +void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const +{ + btVector3 localAxis = dir*trans.getBasis(); + btVector3 vtx1 = trans(localGetSupportingVertex(localAxis)); + btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis)); + + min = vtx1.dot(dir); + max = vtx2.dot(dir); + + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } +} + + +static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling) +{ + + btVector3 vec = localDirOrg * localScaling; + +#if defined (__CELLOS_LV2__) && defined (__SPU__) + + btVector3 localDir = vec; + + vec_float4 v_distMax = {-FLT_MAX,0,0,0}; + vec_int4 v_idxMax = {-999,0,0,0}; + int v=0; + int numverts = numPoints; + + for(;v<(int)numverts-4;v+=4) { + vec_float4 p0 = vec_dot3(points[v ].get128(),localDir.get128()); + vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128()); + vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128()); + vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128()); + const vec_int4 i0 = {v ,0,0,0}; + const vec_int4 i1 = {v+1,0,0,0}; + const vec_int4 i2 = {v+2,0,0,0}; + const vec_int4 i3 = {v+3,0,0,0}; + vec_uint4 retGt01 = spu_cmpgt(p0,p1); + vec_float4 pmax01 = spu_sel(p1,p0,retGt01); + vec_int4 imax01 = spu_sel(i1,i0,retGt01); + vec_uint4 retGt23 = spu_cmpgt(p2,p3); + vec_float4 pmax23 = spu_sel(p3,p2,retGt23); + vec_int4 imax23 = spu_sel(i3,i2,retGt23); + vec_uint4 retGt0123 = spu_cmpgt(pmax01,pmax23); + vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123); + vec_int4 imax0123 = spu_sel(imax23,imax01,retGt0123); + vec_uint4 retGtMax = spu_cmpgt(v_distMax,pmax0123); + v_distMax = spu_sel(pmax0123,v_distMax,retGtMax); + v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax); + } + for(;v<(int)numverts;v++) { + vec_float4 p = vec_dot3(points[v].get128(),localDir.get128()); + const vec_int4 i = {v,0,0,0}; + vec_uint4 retGtMax = spu_cmpgt(v_distMax,p); + v_distMax = spu_sel(p,v_distMax,retGtMax); + v_idxMax = spu_sel(i,v_idxMax,retGtMax); + } + int ptIndex = spu_extract(v_idxMax,0); + const btVector3& supVec= points[ptIndex] * localScaling; + return supVec; +#else + + btScalar maxDot; + long ptIndex = vec.maxDot( points, numPoints, maxDot); + btAssert(ptIndex >= 0); + btVector3 supVec = points[ptIndex] * localScaling; + return supVec; +#endif //__SPU__ +} + +btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + return btVector3(0,0,0); + } + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + const btVector3& halfExtents = convexShape->getImplicitShapeDimensions(); + +#if defined( __APPLE__ ) && (defined( BT_USE_SSE )||defined( BT_USE_NEON )) + #if defined( BT_USE_SSE ) + return btVector3( _mm_xor_ps( _mm_and_ps( localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f }), halfExtents.mVec128 )); + #elif defined( BT_USE_NEON ) + return btVector3( (float32x4_t) (((uint32x4_t) localDir.mVec128 & (uint32x4_t){ 0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t) halfExtents.mVec128 )); + #else + #error unknown vector arch + #endif +#else + return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()), + btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()), + btFsels(localDir.z(), halfExtents.z(), -halfExtents.z())); +#endif + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ()); + btVector3* vertices = &triangleShape->m_vertices1[0]; + btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]); + btVector3 sup = vertices[dots.maxAxis()]; + return btVector3(sup.getX(),sup.getY(),sup.getZ()); + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylShape = (btCylinderShape*)this; + //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis) + + btVector3 halfExtents = cylShape->getImplicitShapeDimensions(); + btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ()); + int cylinderUpAxis = cylShape->getUpAxis(); + int XX(1),YY(0),ZZ(2); + + switch (cylinderUpAxis) + { + case 0: + { + XX = 1; + YY = 0; + ZZ = 2; + } + break; + case 1: + { + XX = 0; + YY = 1; + ZZ = 2; + } + break; + case 2: + { + XX = 0; + YY = 2; + ZZ = 1; + + } + break; + default: + btAssert(0); + break; + }; + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } else { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return btVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ()); + + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + btScalar halfHeight = capsuleShape->getHalfHeight(); + int capsuleUpAxis = capsuleShape->getUpAxis(); + + btScalar radius = capsuleShape->getRadius(); + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + btVector3 vtx; + btScalar newDot; + { + btVector3 pos(0,0,0); + pos[capsuleUpAxis] = halfHeight; + + //vtx = pos +vec*(radius); + vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); + newDot = vec.dot(vtx); + + + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + { + btVector3 pos(0,0,0); + pos[capsuleUpAxis] = -halfHeight; + + //vtx = pos +vec*(radius); + vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return btVector3(supVec.getX(),supVec.getY(),supVec.getZ()); + } + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + { + btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this; + btVector3* points = convexPointCloudShape->getUnscaledPoints (); + int numPoints = convexPointCloudShape->getNumPoints (); + return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV()); + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexHullShape* convexHullShape = (btConvexHullShape*)this; + btVector3* points = convexHullShape->getUnscaledPoints(); + int numPoints = convexHullShape->getNumPoints (); + return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV()); + } + default: +#ifndef __SPU__ + return this->localGetSupportingVertexWithoutMargin (localDir); +#else + btAssert (0); +#endif + } + + // should never reach here + btAssert (0); + return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f)); +} + +btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const +{ + btVector3 localDirNorm = localDir; + if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + localDirNorm.normalize (); + + return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm; +} + +/* TODO: This should be bumped up to btCollisionShape () */ +btScalar btConvexShape::getMarginNonVirtual () const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + btSphereShape* sphereShape = (btSphereShape*)this; + return sphereShape->getRadius (); + } + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + return convexShape->getMarginNV (); + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + return triangleShape->getMarginNV (); + } + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShape* cylShape = (btCylinderShape*)this; + return cylShape->getMarginNV(); + } + case CONE_SHAPE_PROXYTYPE: + { + btConeShape* conShape = (btConeShape*)this; + return conShape->getMarginNV(); + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + return capsuleShape->getMarginNV(); + } + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + /* fall through */ + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this; + return convexHullShape->getMarginNV(); + } + default: +#ifndef __SPU__ + return this->getMargin (); +#else + btAssert (0); +#endif + } + + // should never reach here + btAssert (0); + return btScalar(0.0f); +} +#ifndef __SPU__ +void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const +{ + switch (m_shapeType) + { + case SPHERE_SHAPE_PROXYTYPE: + { + btSphereShape* sphereShape = (btSphereShape*)this; + btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); + btScalar margin = radius + sphereShape->getMarginNonVirtual(); + const btVector3& center = t.getOrigin(); + btVector3 extent(margin,margin,margin); + aabbMin = center - extent; + aabbMax = center + extent; + } + break; + case CYLINDER_SHAPE_PROXYTYPE: + /* fall through */ + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* convexShape = (btBoxShape*)this; + btScalar margin=convexShape->getMarginNonVirtual(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + halfExtents += btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case TRIANGLE_SHAPE_PROXYTYPE: + { + btTriangleShape* triangleShape = (btTriangleShape*)this; + btScalar margin = triangleShape->getMarginNonVirtual(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()); + + btVector3 tmp = t(sv); + aabbMax[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis())); + aabbMin[i] = tmp[i]-margin; + } + } + break; + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShape* capsuleShape = (btCapsuleShape*)this; + btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius()); + int m_upAxis = capsuleShape->getUpAxis(); + halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight(); + halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + aabbMin = center - extent; + aabbMax = center + extent; + } + break; + case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this; + btScalar margin = convexHullShape->getMarginNonVirtual(); + convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin); + } + break; + default: +#ifndef __SPU__ + this->getAabb (t, aabbMin, aabbMax); +#else + btAssert (0); +#endif + break; + } + + // should never reach here + btAssert (0); +} + +#endif //__SPU__ diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.h new file mode 100644 index 00000000..290cd9fd --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_SHAPE_INTERFACE1 +#define BT_CONVEX_SHAPE_INTERFACE1 + +#include "btCollisionShape.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" +#include "LinearMath/btAlignedAllocator.h" + +#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 + +/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc. +/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector. +ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape +{ + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexShape (); + + virtual ~btConvexShape(); + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const = 0; + + //////// + #ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0; + #endif //#ifndef __SPU__ + + btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const; + btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const; + btScalar getMarginNonVirtual () const; + void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const; + + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; + + + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + + virtual void setMargin(btScalar margin)=0; + + virtual btScalar getMargin() const=0; + + virtual int getNumPreferredPenetrationDirections() const=0; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; + + + + +}; + + + +#endif //BT_CONVEX_SHAPE_INTERFACE1 diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp new file mode 100644 index 00000000..0f9ced55 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -0,0 +1,315 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" + + +btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) +: btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface) +{ + m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; + if ( calcAabb ) + recalcLocalAabb(); +} + + + + +///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once +///but then we are duplicating +class LocalSupportVertexCallback: public btInternalTriangleIndexCallback +{ + + btVector3 m_supportVertexLocal; +public: + + btScalar m_maxDot; + btVector3 m_supportVecLocal; + + LocalSupportVertexCallback(const btVector3& supportVecLocal) + : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), + m_maxDot(btScalar(-BT_LARGE_FLOAT)), + m_supportVecLocal(supportVecLocal) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)triangleIndex; + (void)partId; + + for (int i=0;i<3;i++) + { + btScalar dot = m_supportVecLocal.dot(triangle[i]); + if (dot > m_maxDot) + { + m_maxDot = dot; + m_supportVertexLocal = triangle[i]; + } + } + } + + btVector3 GetSupportVertexLocal() + { + return m_supportVertexLocal; + } + +}; + + + + + +btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + LocalSupportVertexCallback supportCallback(vec); + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); + supVec = supportCallback.GetSupportVertexLocal(); + + return supVec; +} + +void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + //use 'w' component of supportVerticesOut? + { + for (int i=0;iInternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); + supportVerticesOut[j] = supportCallback.GetSupportVertexLocal(); + } + +} + + + +btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + + + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo +int btConvexTriangleMeshShape::getNumVertices() const +{ + //cache this? + return 0; + +} + +int btConvexTriangleMeshShape::getNumEdges() const +{ + return 0; +} + +void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const +{ + btAssert(0); +} + +void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const +{ + btAssert(0); +} + +int btConvexTriangleMeshShape::getNumPlanes() const +{ + return 0; +} + +void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int ) const +{ + btAssert(0); +} + +//not yet +bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const +{ + btAssert(0); + return false; +} + + + +void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_stridingMesh->setScaling(scaling); + + recalcLocalAabb(); + +} + + +const btVector3& btConvexTriangleMeshShape::getLocalScaling() const +{ + return m_stridingMesh->getScaling(); +} + +void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const +{ + class CenterCallback: public btInternalTriangleIndexCallback + { + bool first; + btVector3 ref; + btVector3 sum; + btScalar volume; + + public: + + CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + if (first) + { + ref = triangle[0]; + first = false; + } + else + { + btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); + sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); + volume += vol; + } + } + + btVector3 getCenter() + { + return (volume > 0) ? sum / volume : ref; + } + + btScalar getVolume() + { + return volume * btScalar(1. / 6); + } + + }; + + class InertiaCallback: public btInternalTriangleIndexCallback + { + btMatrix3x3 sum; + btVector3 center; + + public: + + InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + btMatrix3x3 i; + btVector3 a = triangle[0] - center; + btVector3 b = triangle[1] - center; + btVector3 c = triangle[2] - center; + btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); + for (int j = 0; j < 3; j++) + { + for (int k = 0; k <= j; k++) + { + i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); + } + } + btScalar i00 = -i[0][0]; + btScalar i11 = -i[1][1]; + btScalar i22 = -i[2][2]; + i[0][0] = i11 + i22; + i[1][1] = i22 + i00; + i[2][2] = i00 + i11; + sum[0] += i[0]; + sum[1] += i[1]; + sum[2] += i[2]; + } + + btMatrix3x3& getInertia() + { + return sum; + } + + }; + + CenterCallback centerCallback; + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); + btVector3 center = centerCallback.getCenter(); + principal.setOrigin(center); + volume = centerCallback.getVolume(); + + InertiaCallback inertiaCallback(center); + m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); + + btMatrix3x3& i = inertiaCallback.getInertia(); + i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(i[0][0], i[1][1], i[2][2]); + inertia /= volume; +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h new file mode 100644 index 00000000..f338865c --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -0,0 +1,77 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_CONVEX_TRIANGLEMESH_SHAPE_H +#define BT_CONVEX_TRIANGLEMESH_SHAPE_H + + +#include "btPolyhedralConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + + +/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape. +/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead. +ATTRIBUTE_ALIGNED16(class) btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape +{ + + class btStridingMeshInterface* m_stridingMesh; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true); + + class btStridingMeshInterface* getMeshInterface() + { + return m_stridingMesh; + } + const class btStridingMeshInterface* getMeshInterface() const + { + return m_stridingMesh; + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + //debugging + virtual const char* getName()const {return "ConvexTrimesh";} + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const; + virtual void getVertex(int i,btVector3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const; + virtual bool isInside(const btVector3& pt,btScalar tolerance) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" + ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. This method also computes the volume of the convex mesh. + void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; + +}; + + + +#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H + + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.cpp new file mode 100644 index 00000000..6cfe43be --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -0,0 +1,281 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btCylinderShape.h" + +btCylinderShape::btCylinderShape (const btVector3& halfExtents) +:btConvexInternalShape(), +m_upAxis(1) +{ + setSafeMargin(halfExtents); + + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin; + m_shapeType = CYLINDER_SHAPE_PROXYTYPE; +} + + +btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents) +:btCylinderShape(halfExtents) +{ + m_upAxis = 0; + +} + + +btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents) +:btCylinderShape(halfExtents) +{ + m_upAxis = 2; + +} + +void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); +} + +void btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + +//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility +//#define USE_BOX_INERTIA_APPROXIMATION 1 +#ifndef USE_BOX_INERTIA_APPROXIMATION + + /* + cylinder is defined as following: + * + * - principle axis aligned along y by default, radius in x, z-value not used + * - for btCylinderShapeX: principle axis aligned along x, radius in y direction, z-value not used + * - for btCylinderShapeZ: principle axis aligned along z, radius in x direction, y-value not used + * + */ + + btScalar radius2; // square of cylinder radius + btScalar height2; // square of cylinder height + btVector3 halfExtents = getHalfExtentsWithMargin(); // get cylinder dimension + btScalar div12 = mass / 12.f; + btScalar div4 = mass / 4.f; + btScalar div2 = mass / 2.f; + int idxRadius, idxHeight; + + switch (m_upAxis) // get indices of radius and height of cylinder + { + case 0: // cylinder is aligned along x + idxRadius = 1; + idxHeight = 0; + break; + case 2: // cylinder is aligned along z + idxRadius = 0; + idxHeight = 2; + break; + default: // cylinder is aligned along y + idxRadius = 0; + idxHeight = 1; + } + + // calculate squares + radius2 = halfExtents[idxRadius] * halfExtents[idxRadius]; + height2 = btScalar(4.) * halfExtents[idxHeight] * halfExtents[idxHeight]; + + // calculate tensor terms + btScalar t1 = div12 * height2 + div4 * radius2; + btScalar t2 = div2 * radius2; + + switch (m_upAxis) // set diagonal elements of inertia tensor + { + case 0: // cylinder is aligned along x + inertia.setValue(t2,t1,t1); + break; + case 2: // cylinder is aligned along z + inertia.setValue(t1,t1,t2); + break; + default: // cylinder is aligned along y + inertia.setValue(t1,t2,t1); + } +#else //USE_BOX_INERTIA_APPROXIMATION + //approximation of box shape + btVector3 halfExtents = getHalfExtentsWithMargin(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); +#endif //USE_BOX_INERTIA_APPROXIMATION +} + + +SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +{ +const int cylinderUpAxis = 0; +const int XX = 1; +const int YY = 0; +const int ZZ = 2; + + //mapping depends on how cylinder local orientation is + // extents of the cylinder is: X,Y is for radius, and Z for height + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + + +} + + + + + + +inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v) +{ + +const int cylinderUpAxis = 1; +const int XX = 0; +const int YY = 1; +const int ZZ = 2; + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + +} + +inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v) +{ +const int cylinderUpAxis = 2; +const int XX = 0; +const int YY = 2; +const int ZZ = 1; + + //mapping depends on how cylinder local orientation is + // extents of the cylinder is: X,Y is for radius, and Z for height + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + + +} + +btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); +} + + +btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); +} +btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); +} + +void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for (int i=0;im_convexInternalShapeData,serializer); + + shapeData->m_upAxis = m_upAxis; + + return "btCylinderShapeData"; +} + + + +#endif //BT_CYLINDER_MINKOWSKI_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.cpp new file mode 100644 index 00000000..a9e6df5c --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.cpp @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btEmptyShape.h" + + +#include "btCollisionShape.h" + + +btEmptyShape::btEmptyShape() : btConcaveShape () +{ + m_shapeType = EMPTY_SHAPE_PROXYTYPE; +} + + +btEmptyShape::~btEmptyShape() +{ +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 margin(getMargin(),getMargin(),getMargin()); + + aabbMin = t.getOrigin() - margin; + + aabbMax = t.getOrigin() + margin; + +} + +void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const +{ + btAssert(0); +} + + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.h new file mode 100644 index 00000000..069a7940 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.h @@ -0,0 +1,72 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_EMPTY_SHAPE_H +#define BT_EMPTY_SHAPE_H + +#include "btConcaveShape.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" + + + + +/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class. +/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed. +ATTRIBUTE_ALIGNED16(class) btEmptyShape : public btConcaveShape +{ +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btEmptyShape(); + + virtual ~btEmptyShape(); + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling) + { + m_localScaling = scaling; + } + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual const char* getName()const + { + return "Empty"; + } + + virtual void processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const + { + } + +protected: + btVector3 m_localScaling; + +}; + + + +#endif //BT_EMPTY_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp new file mode 100644 index 00000000..26322791 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp @@ -0,0 +1,410 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btHeightfieldTerrainShape.h" + +#include "LinearMath/btTransformUtil.h" + + + +btHeightfieldTerrainShape::btHeightfieldTerrainShape +( +int heightStickWidth, int heightStickLength, const void* heightfieldData, +btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis, +PHY_ScalarType hdt, bool flipQuadEdges +) +{ + initialize(heightStickWidth, heightStickLength, heightfieldData, + heightScale, minHeight, maxHeight, upAxis, hdt, + flipQuadEdges); +} + + + +btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,const void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges) +{ + // legacy constructor: support only float or unsigned char, + // and min height is zero + PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR; + btScalar minHeight = 0.0f; + + // previously, height = uchar * maxHeight / 65535. + // So to preserve legacy behavior, heightScale = maxHeight / 65535 + btScalar heightScale = maxHeight / 65535; + + initialize(heightStickWidth, heightStickLength, heightfieldData, + heightScale, minHeight, maxHeight, upAxis, hdt, + flipQuadEdges); +} + + + +void btHeightfieldTerrainShape::initialize +( +int heightStickWidth, int heightStickLength, const void* heightfieldData, +btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, +PHY_ScalarType hdt, bool flipQuadEdges +) +{ + // validation + btAssert(heightStickWidth > 1 && "bad width"); + btAssert(heightStickLength > 1 && "bad length"); + btAssert(heightfieldData && "null heightfield data"); + // btAssert(heightScale) -- do we care? Trust caller here + btAssert(minHeight <= maxHeight && "bad min/max height"); + btAssert(upAxis >= 0 && upAxis < 3 && + "bad upAxis--should be in range [0,2]"); + btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT && + "Bad height data type enum"); + + // initialize member variables + m_shapeType = TERRAIN_SHAPE_PROXYTYPE; + m_heightStickWidth = heightStickWidth; + m_heightStickLength = heightStickLength; + m_minHeight = minHeight; + m_maxHeight = maxHeight; + m_width = (btScalar) (heightStickWidth - 1); + m_length = (btScalar) (heightStickLength - 1); + m_heightScale = heightScale; + m_heightfieldDataUnknown = heightfieldData; + m_heightDataType = hdt; + m_flipQuadEdges = flipQuadEdges; + m_useDiamondSubdivision = false; + m_useZigzagSubdivision = false; + m_upAxis = upAxis; + m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.)); + + // determine min/max axis-aligned bounding box (aabb) values + switch (m_upAxis) + { + case 0: + { + m_localAabbMin.setValue(m_minHeight, 0, 0); + m_localAabbMax.setValue(m_maxHeight, m_width, m_length); + break; + } + case 1: + { + m_localAabbMin.setValue(0, m_minHeight, 0); + m_localAabbMax.setValue(m_width, m_maxHeight, m_length); + break; + }; + case 2: + { + m_localAabbMin.setValue(0, 0, m_minHeight); + m_localAabbMax.setValue(m_width, m_length, m_maxHeight); + break; + } + default: + { + //need to get valid m_upAxis + btAssert(0 && "Bad m_upAxis"); + } + } + + // remember origin (defined as exact middle of aabb) + m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax); +} + + + +btHeightfieldTerrainShape::~btHeightfieldTerrainShape() +{ +} + + + +void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5); + + btVector3 localOrigin(0, 0, 0); + localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5); + localOrigin *= m_localScaling; + + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + extent += btVector3(getMargin(),getMargin(),getMargin()); + + aabbMin = center - extent; + aabbMax = center + extent; +} + + +/// This returns the "raw" (user's initial) height, not the actual height. +/// The actual height needs to be adjusted to be relative to the center +/// of the heightfield's AABB. +btScalar +btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const +{ + btScalar val = 0.f; + switch (m_heightDataType) + { + case PHY_FLOAT: + { + val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x]; + break; + } + + case PHY_UCHAR: + { + unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x]; + val = heightFieldValue * m_heightScale; + break; + } + + case PHY_SHORT: + { + short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x]; + val = hfValue * m_heightScale; + break; + } + + default: + { + btAssert(!"Bad m_heightDataType"); + } + } + + return val; +} + + + + +/// this returns the vertex in bullet-local coordinates +void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const +{ + btAssert(x>=0); + btAssert(y>=0); + btAssert(xstartX) + startX = quantizedAabbMin[1]; + if (quantizedAabbMax[1]startJ) + startJ = quantizedAabbMin[2]; + if (quantizedAabbMax[2]startX) + startX = quantizedAabbMin[0]; + if (quantizedAabbMax[0]startJ) + startJ = quantizedAabbMin[2]; + if (quantizedAabbMax[2]startX) + startX = quantizedAabbMin[0]; + if (quantizedAabbMax[0]startJ) + startJ = quantizedAabbMin[1]; + if (quantizedAabbMax[1]processTriangle(vertices,x,j); + //second triangle + // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman + getVertex(x+1,j+1,vertices[1]); + getVertex(x,j+1,vertices[2]); + callback->processTriangle(vertices,x,j); + } else + { + //first triangle + getVertex(x,j,vertices[0]); + getVertex(x,j+1,vertices[1]); + getVertex(x+1,j,vertices[2]); + callback->processTriangle(vertices,x,j); + //second triangle + getVertex(x+1,j,vertices[0]); + //getVertex(x,j+1,vertices[1]); + getVertex(x+1,j+1,vertices[2]); + callback->processTriangle(vertices,x,j); + } + } + } + + + +} + +void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const +{ + //moving concave objects not supported + + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} +const btVector3& btHeightfieldTerrainShape::getLocalScaling() const +{ + return m_localScaling; +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h new file mode 100644 index 00000000..4a7a4a4b --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h @@ -0,0 +1,167 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_HEIGHTFIELD_TERRAIN_SHAPE_H +#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H + +#include "btConcaveShape.h" + +///btHeightfieldTerrainShape simulates a 2D heightfield terrain +/** + The caller is responsible for maintaining the heightfield array; this + class does not make a copy. + + The heightfield can be dynamic so long as the min/max height values + capture the extremes (heights must always be in that range). + + The local origin of the heightfield is assumed to be the exact + center (as determined by width and length and height, with each + axis multiplied by the localScaling). + + \b NOTE: be careful with coordinates. If you have a heightfield with a local + min height of -100m, and a max height of +500m, you may be tempted to place it + at the origin (0,0) and expect the heights in world coordinates to be + -100 to +500 meters. + Actually, the heights will be -300 to +300m, because bullet will re-center + the heightfield based on its AABB (which is determined by the min/max + heights). So keep in mind that once you create a btHeightfieldTerrainShape + object, the heights will be adjusted relative to the center of the AABB. This + is different to the behavior of many rendering engines, but is useful for + physics engines. + + Most (but not all) rendering and heightfield libraries assume upAxis = 1 + (that is, the y-axis is "up"). This class allows any of the 3 coordinates + to be "up". Make sure your choice of axis is consistent with your rendering + system. + + The heightfield heights are determined from the data type used for the + heightfieldData array. + + - PHY_UCHAR: height at a point is the uchar value at the + grid point, multipled by heightScale. uchar isn't recommended + because of its inability to deal with negative values, and + low resolution (8-bit). + + - PHY_SHORT: height at a point is the short int value at that grid + point, multipled by heightScale. + + - PHY_FLOAT: height at a point is the float value at that grid + point. heightScale is ignored when using the float heightfield + data type. + + Whatever the caller specifies as minHeight and maxHeight will be honored. + The class will not inspect the heightfield to discover the actual minimum + or maximum heights. These values are used to determine the heightfield's + axis-aligned bounding box, multiplied by localScaling. + + For usage and testing see the TerrainDemo. + */ +ATTRIBUTE_ALIGNED16(class) btHeightfieldTerrainShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + btVector3 m_localOrigin; + + ///terrain data + int m_heightStickWidth; + int m_heightStickLength; + btScalar m_minHeight; + btScalar m_maxHeight; + btScalar m_width; + btScalar m_length; + btScalar m_heightScale; + union + { + const unsigned char* m_heightfieldDataUnsignedChar; + const short* m_heightfieldDataShort; + const btScalar* m_heightfieldDataFloat; + const void* m_heightfieldDataUnknown; + }; + + PHY_ScalarType m_heightDataType; + bool m_flipQuadEdges; + bool m_useDiamondSubdivision; + bool m_useZigzagSubdivision; + + int m_upAxis; + + btVector3 m_localScaling; + + virtual btScalar getRawHeightFieldValue(int x,int y) const; + void quantizeWithClamp(int* out, const btVector3& point,int isMax) const; + void getVertex(int x,int y,btVector3& vertex) const; + + + + /// protected initialization + /** + Handles the work of constructors so that public constructors can be + backwards-compatible without a lot of copy/paste. + */ + void initialize(int heightStickWidth, int heightStickLength, + const void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, int upAxis, + PHY_ScalarType heightDataType, bool flipQuadEdges); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + /// preferred constructor + /** + This constructor supports a range of heightfield + data types, and allows for a non-zero minimum height value. + heightScale is needed for any integer-based heightfield data types. + */ + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength, + const void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, + int upAxis, PHY_ScalarType heightDataType, + bool flipQuadEdges); + + /// legacy constructor + /** + The legacy constructor assumes the heightfield has a minimum height + of zero. Only unsigned char or floats are supported. For legacy + compatibility reasons, heightScale is calculated as maxHeight / 65535 + (and is only used when useFloatData = false). + */ + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,const void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); + + virtual ~btHeightfieldTerrainShape(); + + + void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;} + + ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625 + void setUseZigzagSubdivision(bool useZigzagSubdivision=true) { m_useZigzagSubdivision = useZigzagSubdivision;} + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setLocalScaling(const btVector3& scaling); + + virtual const btVector3& getLocalScaling() const; + + //debugging + virtual const char* getName()const {return "HEIGHTFIELD";} + +}; + +#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMaterial.h b/Code/Physics/src/BulletCollision/CollisionShapes/btMaterial.h new file mode 100644 index 00000000..866f9b4d --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMaterial.h @@ -0,0 +1,35 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// This file was created by Alex Silverman + +#ifndef BT_MATERIAL_H +#define BT_MATERIAL_H + +// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties +class btMaterial +{ + // public members so that materials can change due to world events +public: + btScalar m_friction; + btScalar m_restitution; + int pad[2]; + + btMaterial(){} + btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; } +}; + +#endif // BT_MATERIAL_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp new file mode 100644 index 00000000..06707e24 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp @@ -0,0 +1,60 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btMinkowskiSumShape.h" + + +btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB) +: btConvexInternalShape (), +m_shapeA(shapeA), +m_shapeB(shapeB) +{ + m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE; + m_transA.setIdentity(); + m_transB.setIdentity(); +} + +btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); + btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis())); + return supVertexA - supVertexB; +} + +void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + ///@todo: could make recursive use of batching. probably this shape is not used frequently. + for (int i=0;igetMargin() + m_shapeB->getMargin(); +} + + +void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + (void)mass; + btAssert(0); + inertia.setValue(0,0,0); +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h new file mode 100644 index 00000000..a3f9a472 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MINKOWSKI_SUM_SHAPE_H +#define BT_MINKOWSKI_SUM_SHAPE_H + +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes. +ATTRIBUTE_ALIGNED16(class) btMinkowskiSumShape : public btConvexInternalShape +{ + + btTransform m_transA; + btTransform m_transB; + const btConvexShape* m_shapeA; + const btConvexShape* m_shapeB; + +public: + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + void setTransformA(const btTransform& transA) { m_transA = transA;} + void setTransformB(const btTransform& transB) { m_transB = transB;} + + const btTransform& getTransformA()const { return m_transA;} + const btTransform& GetTransformB()const { return m_transB;} + + + virtual btScalar getMargin() const; + + const btConvexShape* getShapeA() const { return m_shapeA;} + const btConvexShape* getShapeB() const { return m_shapeB;} + + virtual const char* getName()const + { + return "MinkowskiSum"; + } +}; + +#endif //BT_MINKOWSKI_SUM_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp new file mode 100644 index 00000000..a7362ea0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -0,0 +1,182 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +#if defined (_WIN32) || defined (__i386__) +#define BT_USE_SSE_IN_API +#endif + +#include "btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btSerializer.h" + +btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres) +:btConvexInternalAabbCachingShape () +{ + m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE; + //btScalar startMargin = btScalar(BT_LARGE_FLOAT); + + m_localPositionArray.resize(numSpheres); + m_radiArray.resize(numSpheres); + for (int i=0;i maxDot ) + { + maxDot = newDot; + supVec = temp[i]; + } + } + + return supVec; + +} + + void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + + for (int j=0;j maxDot ) + { + maxDot = newDot; + supportVerticesOut[j] = temp[i]; + } + } + + } +} + + + + + + + + +void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + //as an approximation, take the inertia of the box that bounds the spheres + + btVector3 localAabbMin,localAabbMax; + getCachedLocalAabb(localAabbMin,localAabbMax); + btVector3 halfExtents = (localAabbMax-localAabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*) dataBuffer; + btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer); + + int numElem = m_localPositionArray.size(); + shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]): 0; + + shapeData->m_localPositionArraySize = numElem; + if (numElem) + { + btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius),numElem); + btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr; + for (int i=0;im_pos); + memPtr->m_radius = float(m_radiArray[i]); + } + serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]); + } + + return "btMultiSphereShapeData"; +} + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.h new file mode 100644 index 00000000..5d3b4026 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -0,0 +1,101 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTI_SPHERE_MINKOWSKI_H +#define BT_MULTI_SPHERE_MINKOWSKI_H + +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAabbUtil2.h" + + + +///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes. +///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius +ATTRIBUTE_ALIGNED16(class) btMultiSphereShape : public btConvexInternalAabbCachingShape +{ + + btAlignedObjectArray m_localPositionArray; + btAlignedObjectArray m_radiArray; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres); + + ///CollisionShape Interface + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + /// btConvexShape Interface + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + int getSphereCount() const + { + return m_localPositionArray.size(); + } + + const btVector3& getSpherePosition(int index) const + { + return m_localPositionArray[index]; + } + + btScalar getSphereRadius(int index) const + { + return m_radiArray[index]; + } + + + virtual const char* getName()const + { + return "MultiSphere"; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + + +struct btPositionAndRadius +{ + btVector3FloatData m_pos; + float m_radius; +}; + +struct btMultiSphereShapeData +{ + btConvexInternalShapeData m_convexInternalShapeData; + + btPositionAndRadius *m_localPositionArrayPtr; + int m_localPositionArraySize; + char m_padding[4]; +}; + + + +SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const +{ + return sizeof(btMultiSphereShapeData); +} + + + +#endif //BT_MULTI_SPHERE_MINKOWSKI_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp new file mode 100644 index 00000000..58799ac9 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp @@ -0,0 +1,45 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// This file was created by Alex Silverman + +#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h" +//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" + + +///Obtains the material for a specific triangle +const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex) +{ + const unsigned char * materialBase = 0; + int numMaterials; + PHY_ScalarType materialType; + int materialStride; + const unsigned char * triangleMaterialBase = 0; + int numTriangles; + int triangleMaterialStride; + PHY_ScalarType triangleType; + + ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, + &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID); + + // return the pointer to the place with the friction for the triangle + // TODO: This depends on whether it's a moving mesh or not + // BUG IN GIMPACT + //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]); + int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)])); + btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride])); + return (matVal); +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h new file mode 100644 index 00000000..2b92ab7d --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h @@ -0,0 +1,120 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +/// This file was created by Alex Silverman + +#ifndef BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#define BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H + +#include "btBvhTriangleMeshShape.h" +#include "btMaterial.h" + +///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution. +ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape +{ + btAlignedObjectArray m_materialList; + int ** m_triangleMaterials; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh) + { + m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; + + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16)); + } + } + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh) + { + m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; + + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16)); + } + } + + virtual ~btMultimaterialTriangleMeshShape() + { +/* + for(int i = 0; i < m_meshInterface->getNumSubParts(); i++) + { + btAlignedFree(m_materialValues[i]); + m_materialLookup[i] = NULL; + } + btAlignedFree(m_materialValues); + m_materialLookup = NULL; +*/ + } + //debugging + virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";} + + ///Obtains the material for a specific triangle + const btMaterial * getMaterialProperties(int partID, int triIndex); + +} +; + +#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp new file mode 100644 index 00000000..6f36775f --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -0,0 +1,391 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btOptimizedBvh.h" +#include "btStridingMeshInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" + + +btOptimizedBvh::btOptimizedBvh() +{ +} + +btOptimizedBvh::~btOptimizedBvh() +{ +} + + +void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax) +{ + m_useQuantization = useQuantizedAabbCompression; + + + // NodeArray triangleNodes; + + struct NodeTriangleCallback : public btInternalTriangleIndexCallback + { + + NodeArray& m_triangleNodes; + + NodeTriangleCallback& operator=(NodeTriangleCallback& other) + { + m_triangleNodes.copyFromArray(other.m_triangleNodes); + return *this; + } + + NodeTriangleCallback(NodeArray& triangleNodes) + :m_triangleNodes(triangleNodes) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + btOptimizedBvhNode node; + btVector3 aabbMin,aabbMax; + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangle[0]); + aabbMax.setMax(triangle[0]); + aabbMin.setMin(triangle[1]); + aabbMax.setMax(triangle[1]); + aabbMin.setMin(triangle[2]); + aabbMax.setMax(triangle[2]); + + //with quantization? + node.m_aabbMinOrg = aabbMin; + node.m_aabbMaxOrg = aabbMax; + + node.m_escapeIndex = -1; + + //for child nodes + node.m_subPart = partId; + node.m_triangleIndex = triangleIndex; + m_triangleNodes.push_back(node); + } + }; + struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback + { + QuantizedNodeArray& m_triangleNodes; + const btQuantizedBvh* m_optimizedTree; // for quantization + + QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) + { + m_triangleNodes.copyFromArray(other.m_triangleNodes); + m_optimizedTree = other.m_optimizedTree; + return *this; + } + + QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree) + :m_triangleNodes(triangleNodes),m_optimizedTree(tree) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + // The partId and triangle index must fit in the same (positive) integer + btAssert(partId < (1<=0); + + btQuantizedBvhNode node; + btVector3 aabbMin,aabbMax; + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangle[0]); + aabbMax.setMax(triangle[0]); + aabbMin.setMin(triangle[1]); + aabbMax.setMax(triangle[1]); + aabbMin.setMin(triangle[2]); + aabbMax.setMax(triangle[2]); + + //PCK: add these checks for zero dimensions of aabb + const btScalar MIN_AABB_DIMENSION = btScalar(0.002); + const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); + if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) + { + aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); + aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) + { + aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); + aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) + { + aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); + aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); + } + + m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + + m_triangleNodes.push_back(node); + } + }; + + + + int numLeafNodes = 0; + + + if (m_useQuantization) + { + + //initialize quantization values + setQuantizationValues(bvhAabbMin,bvhAabbMax); + + QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this); + + + triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax); + + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + + } else + { + NodeTriangleCallback callback(m_leafNodes); + + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + + triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax); + + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_leafNodes.size(); + + m_contiguousNodes.resize(2*numLeafNodes); + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); +} + + + + +void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_useQuantization) + { + + setQuantizationValues(aabbMin,aabbMax); + + updateBvhNodes(meshInterface,0,m_curNodeIndex,0); + + ///now update all subtree headers + + int i; + for (i=0;i m_bvhAabbMin.getX()); + btAssert(aabbMin.getY() > m_bvhAabbMin.getY()); + btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ()); + + btAssert(aabbMax.getX() < m_bvhAabbMax.getX()); + btAssert(aabbMax.getY() < m_bvhAabbMax.getY()); + btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ()); + + ///we should update all quantization values, using updateBvhNodes(meshInterface); + ///but we only update chunks that overlap the given aabb + + unsigned short quantizedQueryAabbMin[3]; + unsigned short quantizedQueryAabbMax[3]; + + quantize(&quantizedQueryAabbMin[0],aabbMin,0); + quantize(&quantizedQueryAabbMax[0],aabbMax,1); + + int i; + for (i=0;im_SubtreeHeaders.size();i++) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) + { + updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); + + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]); + } + } + +} + +void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) +{ + (void)index; + + btAssert(m_useQuantization); + + int curNodeSubPart=-1; + + //get access info to trianglemesh data + const unsigned char *vertexbase = 0; + int numverts = 0; + PHY_ScalarType type = PHY_INTEGER; + int stride = 0; + const unsigned char *indexbase = 0; + int indexstride = 0; + int numfaces = 0; + PHY_ScalarType indicestype = PHY_INTEGER; + + btVector3 triangleVerts[3]; + btVector3 aabbMin,aabbMax; + const btVector3& meshScaling = meshInterface->getScaling(); + + int i; + for (i=endNode-1;i>=firstNode;i--) + { + + + btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i]; + if (curNode.isLeafNode()) + { + //recalc aabb from triangle data + int nodeSubPart = curNode.getPartId(); + int nodeTriangleIndex = curNode.getTriangleIndex(); + if (nodeSubPart != curNodeSubPart) + { + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + + curNodeSubPart = nodeSubPart; + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + } + //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + + + for (int j=2;j>=0;j--) + { + + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + if (type == PHY_FLOAT) + { + float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + else + { + double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); + triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); + } + } + + + + aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMin.setMin(triangleVerts[0]); + aabbMax.setMax(triangleVerts[0]); + aabbMin.setMin(triangleVerts[1]); + aabbMax.setMax(triangleVerts[1]); + aabbMin.setMin(triangleVerts[2]); + aabbMax.setMax(triangleVerts[2]); + + quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0); + quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1); + + } else + { + //combine aabb from both children + + btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1]; + + btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] : + &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()]; + + + { + for (int i=0;i<3;i++) + { + curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i]; + if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i]) + curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i]; + + curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i]; + if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i]) + curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i]; + } + } + } + + } + + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + + +} + +///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' +btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +{ + btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + + //we don't add additional data so just do a static upcast + return static_cast(bvh); +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.h new file mode 100644 index 00000000..715961f5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -0,0 +1,65 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///Contains contributions from Disney Studio's + +#ifndef BT_OPTIMIZED_BVH_H +#define BT_OPTIMIZED_BVH_H + +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" + +class btStridingMeshInterface; + + +///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface. +ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh +{ + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + +protected: + +public: + + btOptimizedBvh(); + + virtual ~btOptimizedBvh(); + + void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); + + void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax); + + void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); + + void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); + + /// Data buffer MUST be 16 byte aligned + virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const + { + return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + + } + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + +}; + + +#endif //BT_OPTIMIZED_BVH_H + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp new file mode 100644 index 00000000..4854f370 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -0,0 +1,500 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ +#if defined (_WIN32) || defined (__i386__) +#define BT_USE_SSE_IN_API +#endif + +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "btConvexPolyhedron.h" +#include "LinearMath/btConvexHullComputer.h" +#include +#include "LinearMath/btGeometryUtil.h" +#include "LinearMath/btGrahamScan2dConvexHull.h" + + +btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(), +m_polyhedron(0) +{ + +} + +btPolyhedralConvexShape::~btPolyhedralConvexShape() +{ + if (m_polyhedron) + { + m_polyhedron->~btConvexPolyhedron(); + btAlignedFree(m_polyhedron); + } +} + + +bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin) +{ + + if (m_polyhedron) + { + m_polyhedron->~btConvexPolyhedron(); + btAlignedFree(m_polyhedron); + } + + void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16); + m_polyhedron = new (mem) btConvexPolyhedron; + + btAlignedObjectArray orgVertices; + + for (int i=0;i planeEquations; + btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations); + + btAlignedObjectArray shiftedPlaneEquations; + for (int p=0;p tmpVertices; + + btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices); + + conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f); + } else + { + + conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f); + } + + + + btAlignedObjectArray faceNormals; + int numFaces = conv.faces.size(); + faceNormals.resize(numFaces); + btConvexHullComputer* convexUtil = &conv; + + + btAlignedObjectArray tmpFaces; + tmpFaces.resize(numFaces); + + int numVertices = convexUtil->vertices.size(); + m_polyhedron->m_vertices.resize(numVertices); + for (int p=0;pm_vertices[p] = convexUtil->vertices[p]; + } + + + for (int i=0;ifaces[i]; + //printf("face=%d\n",face); + const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; + const btConvexHullComputer::Edge* edge = firstEdge; + + btVector3 edges[3]; + int numEdges = 0; + //compute face normals + + do + { + + int src = edge->getSourceVertex(); + tmpFaces[i].m_indices.push_back(src); + int targ = edge->getTargetVertex(); + btVector3 wa = convexUtil->vertices[src]; + + btVector3 wb = convexUtil->vertices[targ]; + btVector3 newEdge = wb-wa; + newEdge.normalize(); + if (numEdges<2) + edges[numEdges++] = newEdge; + + edge = edge->getNextEdgeOfFace(); + } while (edge!=firstEdge); + + btScalar planeEq = 1e30f; + + + if (numEdges==2) + { + faceNormals[i] = edges[0].cross(edges[1]); + faceNormals[i].normalize(); + tmpFaces[i].m_plane[0] = faceNormals[i].getX(); + tmpFaces[i].m_plane[1] = faceNormals[i].getY(); + tmpFaces[i].m_plane[2] = faceNormals[i].getZ(); + tmpFaces[i].m_plane[3] = planeEq; + + } + else + { + btAssert(0);//degenerate? + faceNormals[i].setZero(); + } + + for (int v=0;vm_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]); + if (planeEq>eq) + { + planeEq=eq; + } + } + tmpFaces[i].m_plane[3] = -planeEq; + } + + //merge coplanar faces and copy them to m_polyhedron + + btScalar faceWeldThreshold= 0.999f; + btAlignedObjectArray todoFaces; + for (int i=0;i coplanarFaceGroup; + int refFace = todoFaces[todoFaces.size()-1]; + + coplanarFaceGroup.push_back(refFace); + btFace& faceA = tmpFaces[refFace]; + todoFaces.pop_back(); + + btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]); + for (int j=todoFaces.size()-1;j>=0;j--) + { + int i = todoFaces[j]; + btFace& faceB = tmpFaces[i]; + btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]); + if (faceNormalA.dot(faceNormalB)>faceWeldThreshold) + { + coplanarFaceGroup.push_back(i); + todoFaces.remove(i); + } + } + + + bool did_merge = false; + if (coplanarFaceGroup.size()>1) + { + //do the merge: use Graham Scan 2d convex hull + + btAlignedObjectArray orgpoints; + btVector3 averageFaceNormal(0,0,0); + + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + + btFace& face = tmpFaces[coplanarFaceGroup[i]]; + btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]); + averageFaceNormal+=faceNormal; + for (int f=0;fm_vertices[orgIndex]; + + bool found = false; + + for (int i=0;i hull; + + averageFaceNormal.normalize(); + GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal); + + for (int i=0;im_faces.push_back(combinedFace); + } + } + if(!did_merge) + { + for (int i=0;im_faces.push_back(face); + } + + } + + + + } + + m_polyhedron->initialize(); + + return true; +} + +#ifndef MIN + #define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) +#endif + +btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + + + btVector3 supVec(0,0,0); +#ifndef __SPU__ + int i; + btScalar maxDot(btScalar(-BT_LARGE_FLOAT)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + btVector3 vtx; + btScalar newDot; + + for( int k = 0; k < getNumVertices(); k += 128 ) + { + btVector3 temp[128]; + int inner_count = MIN(getNumVertices() - k, 128); + for( i = 0; i < inner_count; i++ ) + getVertex(i,temp[i]); + i = (int) vec.maxDot( temp, inner_count, newDot); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = temp[i]; + } + } + +#endif //__SPU__ + return supVec; +} + + + +void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ +#ifndef __SPU__ + int i; + + btVector3 vtx; + btScalar newDot; + + for (i=0;i supportVerticesOut[j][3]) + { + supportVerticesOut[j] = temp[i]; + supportVerticesOut[j][3] = newDot; + } + } + } + +#endif //__SPU__ +} + + + +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ +#ifndef __SPU__ + //not yet, return box inertia + + btScalar margin = getMargin(); + + btTransform ident; + ident.setIdentity(); + btVector3 aabbMin,aabbMax; + getAabb(ident,aabbMin,aabbMax); + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()+margin); + btScalar ly=btScalar(2.)*(halfExtents.y()+margin); + btScalar lz=btScalar(2.)*(halfExtents.z()+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); +#endif //__SPU__ +} + + + +void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling) +{ + btConvexInternalShape::setLocalScaling(scaling); + recalcLocalAabb(); +} + +btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape() +:btPolyhedralConvexShape(), +m_localAabbMin(1,1,1), +m_localAabbMax(-1,-1,-1), +m_isLocalAabbValid(false) +{ +} + +void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); +} + +void btPolyhedralConvexAabbCachingShape::recalcLocalAabb() +{ + m_isLocalAabbValid = true; + + #if 1 + static const btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + for ( int i = 0; i < 3; ++i ) + { + m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; + m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; + } + + #else + + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]; + } + #endif +} + + + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h new file mode 100644 index 00000000..961d001a --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -0,0 +1,116 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_POLYHEDRAL_CONVEX_SHAPE_H +#define BT_POLYHEDRAL_CONVEX_SHAPE_H + +#include "LinearMath/btMatrix3x3.h" +#include "btConvexInternalShape.h" +class btConvexPolyhedron; + + +///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes. +ATTRIBUTE_ALIGNED16(class) btPolyhedralConvexShape : public btConvexInternalShape +{ + + +protected: + + btConvexPolyhedron* m_polyhedron; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + btPolyhedralConvexShape(); + + virtual ~btPolyhedralConvexShape(); + + ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges) + ///experimental/work-in-progress + virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin=0); + + const btConvexPolyhedron* getConvexPolyhedron() const + { + return m_polyhedron; + } + + //brute force implementations + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + virtual int getNumVertices() const = 0 ; + virtual int getNumEdges() const = 0; + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const = 0; + virtual void getVertex(int i,btVector3& vtx) const = 0; + virtual int getNumPlanes() const = 0; + virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const = 0; +// virtual int getIndex(int i) const = 0 ; + + virtual bool isInside(const btVector3& pt,btScalar tolerance) const = 0; + +}; + + +///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape +class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape +{ + + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + bool m_isLocalAabbValid; + +protected: + + void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax) + { + m_isLocalAabbValid = true; + m_localAabbMin = aabbMin; + m_localAabbMax = aabbMax; + } + + inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const + { + btAssert(m_isLocalAabbValid); + aabbMin = m_localAabbMin; + aabbMax = m_localAabbMax; + } + +public: + + btPolyhedralConvexAabbCachingShape(); + + inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const + { + + //lazy evaluation of local aabb + btAssert(m_isLocalAabbValid); + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); + } + + virtual void setLocalScaling(const btVector3& scaling); + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + void recalcLocalAabb(); + +}; + +#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp new file mode 100644 index 00000000..6a337c78 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -0,0 +1,121 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btScaledBvhTriangleMeshShape.h" + +btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling) +:m_localScaling(localScaling),m_bvhTriMeshShape(childShape) +{ + m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE; +} + +btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape() +{ +} + + +class btScaledTriangleCallback : public btTriangleCallback +{ + btTriangleCallback* m_originalCallback; + + btVector3 m_localScaling; + +public: + + btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling) + :m_originalCallback(originalCallback), + m_localScaling(localScaling) + { + } + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btVector3 newTriangle[3]; + newTriangle[0] = triangle[0]*m_localScaling; + newTriangle[1] = triangle[1]*m_localScaling; + newTriangle[2] = triangle[2]*m_localScaling; + m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex); + } +}; + +void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + btScaledTriangleCallback scaledCallback(callback,m_localScaling); + + btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ()); + btVector3 scaledAabbMin,scaledAabbMax; + + ///support negative scaling + scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0]; + scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1]; + scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2]; + scaledAabbMin[3] = 0.f; + + scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0]; + scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1]; + scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2]; + scaledAabbMax[3] = 0.f; + + + m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax); +} + + +void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin(); + btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax(); + + btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling; + btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling; + + localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0]; + localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1]; + localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2]; + localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0]; + localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1]; + localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2]; + + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + btScalar margin = m_bvhTriMeshShape->getMargin(); + localHalfExtents += btVector3(margin,margin,margin); + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btVector3 center = trans(localCenter); + + btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + aabbMin = center - extent; + aabbMax = center + extent; + +} + +void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + +const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const +{ + return m_localScaling; +} + +void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///don't make this a movable object! +// btAssert(0); +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h new file mode 100644 index 00000000..39049eaf --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -0,0 +1,95 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" + + +///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape. +///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling' +ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape +{ + + + btVector3 m_localScaling; + + btBvhTriangleMeshShape* m_bvhTriMeshShape; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling); + + virtual ~btScaledBvhTriangleMeshShape(); + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + btBvhTriangleMeshShape* getChildShape() + { + return m_bvhTriMeshShape; + } + + const btBvhTriangleMeshShape* getChildShape() const + { + return m_bvhTriMeshShape; + } + + //debugging + virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btScaledTriangleMeshShapeData +{ + btTriangleMeshShapeData m_trimeshShapeData; + + btVector3FloatData m_localScaling; +}; + + +SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const +{ + return sizeof(btScaledTriangleMeshShapeData); +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*) dataBuffer; + m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData,serializer); + scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE; + m_localScaling.serializeFloat(scaledMeshData->m_localScaling); + return "btScaledTriangleMeshShapeData"; +} + + +#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.cpp new file mode 100644 index 00000000..3beaf865 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.cpp @@ -0,0 +1,170 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +//btShapeHull was implemented by John McCutchan. + + +#include "btShapeHull.h" +#include "LinearMath/btConvexHull.h" + +#define NUM_UNITSPHERE_POINTS 42 + +btShapeHull::btShapeHull (const btConvexShape* shape) +{ + m_shape = shape; + m_vertices.clear (); + m_indices.clear(); + m_numIndices = 0; +} + +btShapeHull::~btShapeHull () +{ + m_indices.clear(); + m_vertices.clear (); +} + +bool +btShapeHull::buildHull (btScalar /*margin*/) +{ + int numSampleDirections = NUM_UNITSPHERE_POINTS; + { + int numPDA = m_shape->getNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + getUnitSpherePoints()[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + for (i = 0; i < numSampleDirections; i++) + { + supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints()[i]); + } + + HullDesc hd; + hd.mFlags = QF_TRIANGLES; + hd.mVcount = static_cast(numSampleDirections); + +#ifdef BT_USE_DOUBLE_PRECISION + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof(btVector3); +#else + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof (btVector3); +#endif + + HullLibrary hl; + HullResult hr; + if (hl.CreateConvexHull (hd, hr) == QE_FAIL) + { + return false; + } + + m_vertices.resize (static_cast(hr.mNumOutputVertices)); + + + for (i = 0; i < static_cast(hr.mNumOutputVertices); i++) + { + m_vertices[i] = hr.m_OutputVertices[i]; + } + m_numIndices = hr.mNumIndices; + m_indices.resize(static_cast(m_numIndices)); + for (i = 0; i < static_cast(m_numIndices); i++) + { + m_indices[i] = hr.m_Indices[i]; + } + + // free temporary hull result that we just copied + hl.ReleaseResult (hr); + + return true; +} + +int +btShapeHull::numTriangles () const +{ + return static_cast(m_numIndices / 3); +} + +int +btShapeHull::numVertices () const +{ + return m_vertices.size (); +} + +int +btShapeHull::numIndices () const +{ + return static_cast(m_numIndices); +} + + +btVector3* btShapeHull::getUnitSpherePoints() +{ + static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = + { + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) + }; + return sUnitSpherePoints; +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.h b/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.h new file mode 100644 index 00000000..e959f198 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.h @@ -0,0 +1,61 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///btShapeHull implemented by John McCutchan. + +#ifndef BT_SHAPE_HULL_H +#define BT_SHAPE_HULL_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + + +///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices. +///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object. +///It approximates the convex hull using the supporting vertex of 42 directions. +ATTRIBUTE_ALIGNED16(class) btShapeHull +{ +protected: + + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_indices; + unsigned int m_numIndices; + const btConvexShape* m_shape; + + static btVector3* getUnitSpherePoints(); + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btShapeHull (const btConvexShape* shape); + ~btShapeHull (); + + bool buildHull (btScalar margin); + + int numTriangles () const; + int numVertices () const; + int numIndices () const; + + const btVector3* getVertexPointer() const + { + return &m_vertices[0]; + } + const unsigned int* getIndexPointer() const + { + return &m_indices[0]; + } +}; + +#endif //BT_SHAPE_HULL_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.cpp new file mode 100644 index 00000000..b9a736c0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" + +btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + (void)vec; + return btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + (void)vectors; + + for (int i=0;iprocessTriangle(triangle,0,0); + + triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius; + triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius; + triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius; + + callback->processTriangle(triangle,0,1); + +} + +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + (void)mass; + + //moving concave objects not supported + + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btStaticPlaneShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} +const btVector3& btStaticPlaneShape::getLocalScaling() const +{ + return m_localScaling; +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h new file mode 100644 index 00000000..e6e32883 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -0,0 +1,105 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_STATIC_PLANE_SHAPE_H +#define BT_STATIC_PLANE_SHAPE_H + +#include "btConcaveShape.h" + + +///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane. +ATTRIBUTE_ALIGNED16(class) btStaticPlaneShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + btVector3 m_planeNormal; + btScalar m_planeConstant; + btVector3 m_localScaling; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant); + + virtual ~btStaticPlaneShape(); + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + const btVector3& getPlaneNormal() const + { + return m_planeNormal; + } + + const btScalar& getPlaneConstant() const + { + return m_planeConstant; + } + + //debugging + virtual const char* getName()const {return "STATICPLANE";} + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btStaticPlaneShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btVector3FloatData m_localScaling; + btVector3FloatData m_planeNormal; + float m_planeConstant; + char m_pad[4]; +}; + + +SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const +{ + return sizeof(btStaticPlaneShapeData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) dataBuffer; + btCollisionShape::serialize(&planeData->m_collisionShapeData,serializer); + + m_localScaling.serializeFloat(planeData->m_localScaling); + m_planeNormal.serializeFloat(planeData->m_planeNormal); + planeData->m_planeConstant = float(m_planeConstant); + + return "btStaticPlaneShapeData"; +} + + +#endif //BT_STATIC_PLANE_SHAPE_H + + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp new file mode 100644 index 00000000..b3d44967 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -0,0 +1,381 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btStridingMeshInterface.h" +#include "LinearMath/btSerializer.h" + +btStridingMeshInterface::~btStridingMeshInterface() +{ + +} + + +void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + (void)aabbMin; + (void)aabbMax; + int numtotalphysicsverts = 0; + int part,graphicssubparts = getNumSubParts(); + const unsigned char * vertexbase; + const unsigned char * indexbase; + int indexstride; + PHY_ScalarType type; + PHY_ScalarType gfxindextype; + int stride,numverts,numtriangles; + int gfxindex; + btVector3 triangle[3]; + + btVector3 meshScaling = getScaling(); + + ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype + for (part=0;partinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_SHORT: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_UCHAR: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + default: + btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT)); + } + break; + } + + case PHY_DOUBLE: + { + double* graphicsbase; + + switch (gfxindextype) + { + case PHY_INTEGER: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_SHORT: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_UCHAR: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + default: + btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT)); + } + break; + } + default: + btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE)); + } + + unLockReadOnlyVertexBase(part); + } +} + +void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax) +{ + + struct AabbCalculationCallback : public btInternalTriangleIndexCallback + { + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + AabbCalculationCallback() + { + m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)partId; + (void)triangleIndex; + + m_aabbMin.setMin(triangle[0]); + m_aabbMax.setMax(triangle[0]); + m_aabbMin.setMin(triangle[1]); + m_aabbMax.setMax(triangle[1]); + m_aabbMin.setMin(triangle[2]); + m_aabbMax.setMax(triangle[2]); + } + }; + + //first calculate the total aabb for all triangles + AabbCalculationCallback aabbCallback; + aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax); + + aabbMin = aabbCallback.m_aabbMin; + aabbMax = aabbCallback.m_aabbMax; +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer; + + trimeshData->m_numMeshParts = getNumSubParts(); + + //void* uniquePtr = 0; + + trimeshData->m_meshPartsPtr = 0; + + if (trimeshData->m_numMeshParts) + { + btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts); + btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr; + trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr); + + + // int numtotalphysicsverts = 0; + int part,graphicssubparts = getNumSubParts(); + const unsigned char * vertexbase; + const unsigned char * indexbase; + int indexstride; + PHY_ScalarType type; + PHY_ScalarType gfxindextype; + int stride,numverts,numtriangles; + int gfxindex; + // btVector3 triangle[3]; + + // btVector3 meshScaling = getScaling(); + + ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype + for (part=0;partm_numTriangles = numtriangles;//indices = 3*numtriangles + memPtr->m_numVertices = numverts; + memPtr->m_indices16 = 0; + memPtr->m_indices32 = 0; + memPtr->m_3indices16 = 0; + memPtr->m_3indices8 = 0; + memPtr->m_vertices3f = 0; + memPtr->m_vertices3d = 0; + + + switch (gfxindextype) + { + case PHY_INTEGER: + { + int numindices = numtriangles*3; + + if (numindices) + { + btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices); + btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr; + memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices); + for (gfxindex=0;gfxindexfinalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + case PHY_SHORT: + { + if (numtriangles) + { + btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles); + btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr; + memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices); + for (gfxindex=0;gfxindexfinalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + case PHY_UCHAR: + { + if (numtriangles) + { + btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles); + btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr; + memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices); + for (gfxindex=0;gfxindexfinalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + default: + { + btAssert(0); + //unknown index type + } + } + + switch (type) + { + case PHY_FLOAT: + { + float* graphicsbase; + + if (numverts) + { + btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts); + btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr; + memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices); + for (int i=0;ifinalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + + case PHY_DOUBLE: + { + if (numverts) + { + btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts); + btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr; + memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices); + for (int i=0;ifinalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr); + } + break; + } + + default: + btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE)); + } + + unLockReadOnlyVertexBase(part); + } + + serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr); + } + + + m_scaling.serializeFloat(trimeshData->m_scaling); + return "btStridingMeshInterfaceData"; +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h new file mode 100644 index 00000000..9fbe1397 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h @@ -0,0 +1,164 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_STRIDING_MESHINTERFACE_H +#define BT_STRIDING_MESHINTERFACE_H + +#include "LinearMath/btVector3.h" +#include "btTriangleCallback.h" +#include "btConcaveShape.h" + + + + + +/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes. +/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips. +/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory. +ATTRIBUTE_ALIGNED16(class ) btStridingMeshInterface +{ + protected: + + btVector3 m_scaling; + + public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.)) + { + + } + + virtual ~btStridingMeshInterface(); + + + + virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + ///brute force method to calculate aabb + void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax); + + /// get read and write access to a subpart of a triangle mesh + /// this subpart has a continuous array of vertices and indices + /// in this way the mesh can be handled as chunks of memory with striding + /// very similar to OpenGL vertexarray support + /// make a call to unLockVertexBase when the read and write access is finished + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0; + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart)=0; + + virtual void unLockReadOnlyVertexBase(int subpart) const=0; + + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const=0; + + virtual void preallocateVertices(int numverts)=0; + virtual void preallocateIndices(int numindices)=0; + + virtual bool hasPremadeAabb() const { return false; } + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const + { + (void) aabbMin; + (void) aabbMax; + } + virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const + { + (void) aabbMin; + (void) aabbMax; + } + + const btVector3& getScaling() const { + return m_scaling; + } + void setScaling(const btVector3& scaling) + { + m_scaling = scaling; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +struct btIntIndexData +{ + int m_value; +}; + +struct btShortIntIndexData +{ + short m_value; + char m_pad[2]; +}; + +struct btShortIntIndexTripletData +{ + short m_values[3]; + char m_pad[2]; +}; + +struct btCharIndexTripletData +{ + unsigned char m_values[3]; + char m_pad; +}; + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btMeshPartData +{ + btVector3FloatData *m_vertices3f; + btVector3DoubleData *m_vertices3d; + + btIntIndexData *m_indices32; + btShortIntIndexTripletData *m_3indices16; + btCharIndexTripletData *m_3indices8; + + btShortIntIndexData *m_indices16;//backwards compatibility + + int m_numTriangles;//length of m_indices = m_numTriangles + int m_numVertices; +}; + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btStridingMeshInterfaceData +{ + btMeshPartData *m_meshPartsPtr; + btVector3FloatData m_scaling; + int m_numMeshParts; + char m_padding[4]; +}; + + + + +SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const +{ + return sizeof(btStridingMeshInterfaceData); +} + + + +#endif //BT_STRIDING_MESHINTERFACE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp new file mode 100644 index 00000000..52f346bf --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp @@ -0,0 +1,218 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTetrahedronShape.h" +#include "LinearMath/btMatrix3x3.h" + +btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); + addVertex(pt1); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); + addVertex(pt1); + addVertex(pt2); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3) : btPolyhedralConvexAabbCachingShape (), +m_numVertices(0) +{ + m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE; + addVertex(pt0); + addVertex(pt1); + addVertex(pt2); + addVertex(pt3); +} + + +void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ +#if 1 + btPolyhedralConvexAabbCachingShape::getAabb(t,aabbMin,aabbMax); +#else + aabbMin.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT); + aabbMax.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT); + + //just transform the vertices in worldspace, and take their AABB + for (int i=0;iprocessAllTriangles(&triBuf,aabbMin, aabbMax); +/// for (int i=0;i m_triangleBuffer; + +public: + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + int getNumTriangles() const + { + return int(m_triangleBuffer.size()); + } + + const btTriangle& getTriangle(int index) const + { + return m_triangleBuffer[index]; + } + + void clearBuffer() + { + m_triangleBuffer.clear(); + } + +}; + + +#endif //BT_TRIANGLE_BUFFER_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp new file mode 100644 index 00000000..f558bf6d --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp @@ -0,0 +1,28 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTriangleCallback.h" + +btTriangleCallback::~btTriangleCallback() +{ + +} + + +btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback() +{ + +} + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.h new file mode 100644 index 00000000..461c57f8 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.h @@ -0,0 +1,42 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TRIANGLE_CALLBACK_H +#define BT_TRIANGLE_CALLBACK_H + +#include "LinearMath/btVector3.h" + + +///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles. +///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape. +class btTriangleCallback +{ +public: + + virtual ~btTriangleCallback(); + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0; +}; + +class btInternalTriangleIndexCallback +{ +public: + + virtual ~btInternalTriangleIndexCallback(); + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) = 0; +}; + + + +#endif //BT_TRIANGLE_CALLBACK_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp new file mode 100644 index 00000000..a665024c --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp @@ -0,0 +1,95 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTriangleIndexVertexArray.h" + +btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride) +: m_hasAabb(0) +{ + btIndexedMesh mesh; + + mesh.m_numTriangles = numTriangles; + mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase; + mesh.m_triangleIndexStride = triangleIndexStride; + mesh.m_numVertices = numVertices; + mesh.m_vertexBase = (const unsigned char *)vertexBase; + mesh.m_vertexStride = vertexStride; + + addIndexedMesh(mesh); + +} + +btTriangleIndexVertexArray::~btTriangleIndexVertexArray() +{ + +} + +void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btIndexedMesh& mesh = m_indexedMeshes[subpart]; + + numverts = mesh.m_numVertices; + (*vertexbase) = (unsigned char *) mesh.m_vertexBase; + + type = mesh.m_vertexType; + + vertexStride = mesh.m_vertexStride; + + numfaces = mesh.m_numTriangles; + + (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase; + indexstride = mesh.m_triangleIndexStride; + indicestype = mesh.m_indexType; +} + +void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const +{ + const btIndexedMesh& mesh = m_indexedMeshes[subpart]; + + numverts = mesh.m_numVertices; + (*vertexbase) = (const unsigned char *)mesh.m_vertexBase; + + type = mesh.m_vertexType; + + vertexStride = mesh.m_vertexStride; + + numfaces = mesh.m_numTriangles; + (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase; + indexstride = mesh.m_triangleIndexStride; + indicestype = mesh.m_indexType; +} + +bool btTriangleIndexVertexArray::hasPremadeAabb() const +{ + return (m_hasAabb == 1); +} + + +void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const +{ + m_aabbMin = aabbMin; + m_aabbMax = aabbMax; + m_hasAabb = 1; // this is intentionally an int see notes in header +} + +void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const +{ + *aabbMin = m_aabbMin; + *aabbMax = m_aabbMax; +} + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h new file mode 100644 index 00000000..9e1544e8 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h @@ -0,0 +1,133 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btStridingMeshInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btScalar.h" + + +///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh. +///Instead of the number of indices, we pass the number of triangles. +ATTRIBUTE_ALIGNED16( struct) btIndexedMesh +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_numTriangles; + const unsigned char * m_triangleIndexBase; + // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed) + int m_triangleIndexStride; + int m_numVertices; + const unsigned char * m_vertexBase; + // Size of a vertex, in bytes + int m_vertexStride; + + // The index type is set when adding an indexed mesh to the + // btTriangleIndexVertexArray, do not set it manually + PHY_ScalarType m_indexType; + + // The vertex type has a default type similar to Bullet's precision mode (float or double) + // but can be set manually if you for example run Bullet with double precision but have + // mesh data in single precision.. + PHY_ScalarType m_vertexType; + + + btIndexedMesh() + :m_indexType(PHY_INTEGER), +#ifdef BT_USE_DOUBLE_PRECISION + m_vertexType(PHY_DOUBLE) +#else // BT_USE_DOUBLE_PRECISION + m_vertexType(PHY_FLOAT) +#endif // BT_USE_DOUBLE_PRECISION + { + } +} +; + + +typedef btAlignedObjectArray IndexedMeshArray; + +///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays. +///Additional meshes can be added using addIndexedMesh +///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. +///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. +ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface +{ +protected: + IndexedMeshArray m_indexedMeshes; + int m_pad[2]; + mutable int m_hasAabb; // using int instead of bool to maintain alignment + mutable btVector3 m_aabbMin; + mutable btVector3 m_aabbMax; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexArray() : m_hasAabb(0) + { + } + + virtual ~btTriangleIndexVertexArray(); + + //just to be backwards compatible + btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); + + void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER) + { + m_indexedMeshes.push_back(mesh); + m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType; + } + + + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart) {(void)subpart;} + + virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;} + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const { + return (int)m_indexedMeshes.size(); + } + + IndexedMeshArray& getIndexedMeshArray() + { + return m_indexedMeshes; + } + + const IndexedMeshArray& getIndexedMeshArray() const + { + return m_indexedMeshes; + } + + virtual void preallocateVertices(int numverts){(void) numverts;} + virtual void preallocateIndices(int numindices){(void) numindices;} + + virtual bool hasPremadeAabb() const; + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const; + virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const; + +} +; + +#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp new file mode 100644 index 00000000..dc562941 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was created by Alex Silverman + +#include "btTriangleIndexVertexMaterialArray.h" + +btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride) : +btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride) +{ + btMaterialProperties mat; + + mat.m_numMaterials = numMaterials; + mat.m_materialBase = materialBase; + mat.m_materialStride = materialStride; +#ifdef BT_USE_DOUBLE_PRECISION + mat.m_materialType = PHY_DOUBLE; +#else + mat.m_materialType = PHY_FLOAT; +#endif + + mat.m_numTriangles = numTriangles; + mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase; + mat.m_triangleMaterialStride = materialIndexStride; + mat.m_triangleType = PHY_INTEGER; + + addMaterialProperties(mat); +} + + +void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} + +void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (const unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h new file mode 100644 index 00000000..ba4f7b46 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was created by Alex Silverman + +#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btTriangleIndexVertexArray.h" + + +ATTRIBUTE_ALIGNED16( struct) btMaterialProperties +{ + ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution + int m_numMaterials; + const unsigned char * m_materialBase; + int m_materialStride; + PHY_ScalarType m_materialType; + ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're + /// padding the structure, it can be reproduced at no real cost + ///m_triangleMaterials =====> 1 integer value makes up one entry + /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5 + int m_numTriangles; + const unsigned char * m_triangleMaterialsBase; + int m_triangleMaterialStride; + ///m_triangleType <========== Automatically set in addMaterialProperties + PHY_ScalarType m_triangleType; +}; + +typedef btAlignedObjectArray MaterialArray; + +///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray +///The addition of a material array allows for the utilization of the partID and +///triangleIndex that are returned in the ContactAddedCallback. As with +///TriangleIndexVertexArray, no duplicate is made of the material data, so it +///is the users responsibility to maintain the array during the lifetime of the +///TriangleIndexVertexMaterialArray. +ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray +{ +protected: + MaterialArray m_materials; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexMaterialArray() + { + } + + btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride); + + virtual ~btTriangleIndexVertexMaterialArray() {} + + void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER) + { + m_materials.push_back(mat); + m_materials[m_materials.size()-1].m_triangleType = triangleType; + } + + virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0); + + virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0); + +} +; + +#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h new file mode 100644 index 00000000..17deef89 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h @@ -0,0 +1,241 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2010 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _BT_TRIANGLE_INFO_MAP_H +#define _BT_TRIANGLE_INFO_MAP_H + + +#include "LinearMath/btHashMap.h" +#include "LinearMath/btSerializer.h" + + +///for btTriangleInfo m_flags +#define TRI_INFO_V0V1_CONVEX 1 +#define TRI_INFO_V1V2_CONVEX 2 +#define TRI_INFO_V2V0_CONVEX 4 + +#define TRI_INFO_V0V1_SWAP_NORMALB 8 +#define TRI_INFO_V1V2_SWAP_NORMALB 16 +#define TRI_INFO_V2V0_SWAP_NORMALB 32 + + +///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges +///it can be generated using +struct btTriangleInfo +{ + btTriangleInfo() + { + m_edgeV0V1Angle = SIMD_2_PI; + m_edgeV1V2Angle = SIMD_2_PI; + m_edgeV2V0Angle = SIMD_2_PI; + m_flags=0; + } + + int m_flags; + + btScalar m_edgeV0V1Angle; + btScalar m_edgeV1V2Angle; + btScalar m_edgeV2V0Angle; + +}; + +typedef btHashMap btInternalTriangleInfoMap; + + +///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo. +struct btTriangleInfoMap : public btInternalTriangleInfoMap +{ + btScalar m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product + btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle + btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared' + btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge" + btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold + btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold) + + + btTriangleInfoMap() + { + m_convexEpsilon = 0.00f; + m_planarEpsilon = 0.0001f; + m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001); + m_edgeDistanceThreshold = btScalar(0.1); + m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001); + m_maxEdgeAngleThreshold = SIMD_2_PI; + } + virtual ~btTriangleInfoMap() {} + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + void deSerialize(struct btTriangleInfoMapData& data); + +}; + +///those fields have to be float and not btScalar for the serialization to work properly +struct btTriangleInfoData +{ + int m_flags; + float m_edgeV0V1Angle; + float m_edgeV1V2Angle; + float m_edgeV2V0Angle; +}; + +struct btTriangleInfoMapData +{ + int *m_hashTablePtr; + int *m_nextPtr; + btTriangleInfoData *m_valueArrayPtr; + int *m_keyArrayPtr; + + float m_convexEpsilon; + float m_planarEpsilon; + float m_equalVertexThreshold; + float m_edgeDistanceThreshold; + float m_zeroAreaThreshold; + + int m_nextSize; + int m_hashTableSize; + int m_numValues; + int m_numKeys; + char m_padding[4]; +}; + +SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const +{ + return sizeof(btTriangleInfoMapData); +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer; + tmapData->m_convexEpsilon = (float)m_convexEpsilon; + tmapData->m_planarEpsilon = (float)m_planarEpsilon; + tmapData->m_equalVertexThreshold =(float) m_equalVertexThreshold; + tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold; + tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold; + + tmapData->m_hashTableSize = m_hashTable.size(); + + tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0; + if (tmapData->m_hashTablePtr) + { + //serialize an int buffer + int sz = sizeof(int); + int numElem = tmapData->m_hashTableSize; + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]); + + } + + tmapData->m_nextSize = m_next.size(); + tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0; + if (tmapData->m_nextPtr) + { + int sz = sizeof(int); + int numElem = tmapData->m_nextSize; + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]); + } + + tmapData->m_numValues = m_valueArray.size(); + tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0; + if (tmapData->m_valueArrayPtr) + { + int sz = sizeof(btTriangleInfoData); + int numElem = tmapData->m_numValues; + btChunk* chunk = serializer->allocate(sz,numElem); + btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr; + for (int i=0;im_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle; + memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle; + memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle; + memPtr->m_flags = m_valueArray[i].m_flags; + } + serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]); + } + + tmapData->m_numKeys = m_keyArray.size(); + tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0; + if (tmapData->m_keyArrayPtr) + { + int sz = sizeof(int); + int numElem = tmapData->m_numValues; + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]); + + } + return "btTriangleInfoMapData"; +} + + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData ) +{ + + + m_convexEpsilon = tmapData.m_convexEpsilon; + m_planarEpsilon = tmapData.m_planarEpsilon; + m_equalVertexThreshold = tmapData.m_equalVertexThreshold; + m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold; + m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold; + m_hashTable.resize(tmapData.m_hashTableSize); + int i =0; + for (i=0;i m_4componentVertices; + btAlignedObjectArray m_3componentVertices; + + btAlignedObjectArray m_32bitIndices; + btAlignedObjectArray m_16bitIndices; + bool m_use32bitIndices; + bool m_use4componentVertices; + + + public: + btScalar m_weldingThreshold; + + btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); + + bool getUse32bitIndices() const + { + return m_use32bitIndices; + } + + bool getUse4componentVertices() const + { + return m_use4componentVertices; + } + ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes. + ///In general it is better to directly use btTriangleIndexVertexArray instead. + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false); + + int getNumTriangles() const; + + virtual void preallocateVertices(int numverts); + virtual void preallocateIndices(int numindices); + + ///findOrAddVertex is an internal method, use addTriangle instead + int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices); + ///addIndex is an internal method, use addTriangle instead + void addIndex(int index); + +}; + +#endif //BT_TRIANGLE_MESH_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp new file mode 100644 index 00000000..0e179514 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -0,0 +1,207 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btTriangleMeshShape.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "btStridingMeshInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + + +btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) +: btConcaveShape (), m_meshInterface(meshInterface) +{ + m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + if(meshInterface->hasPremadeAabb()) + { + meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax); + } + else + { + recalcLocalAabb(); + } +} + + +btTriangleMeshShape::~btTriangleMeshShape() +{ + +} + + + + +void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btVector3 center = trans(localCenter); + + btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]); + aabbMin = center - extent; + aabbMax = center + extent; +} + +void btTriangleMeshShape::recalcLocalAabb() +{ + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]+m_collisionMargin; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]-m_collisionMargin; + } +} + + + +class SupportVertexCallback : public btTriangleCallback +{ + + btVector3 m_supportVertexLocal; +public: + + btTransform m_worldTrans; + btScalar m_maxDot; + btVector3 m_supportVecLocal; + + SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans) + : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-BT_LARGE_FLOAT)) + + { + m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis(); + } + + virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + for (int i=0;i<3;i++) + { + btScalar dot = m_supportVecLocal.dot(triangle[i]); + if (dot > m_maxDot) + { + m_maxDot = dot; + m_supportVertexLocal = triangle[i]; + } + } + } + + btVector3 GetSupportVertexWorldSpace() + { + return m_worldTrans(m_supportVertexLocal); + } + + btVector3 GetSupportVertexLocal() + { + return m_supportVertexLocal; + } + +}; + + +void btTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_meshInterface->setScaling(scaling); + recalcLocalAabb(); +} + +const btVector3& btTriangleMeshShape::getLocalScaling() const +{ + return m_meshInterface->getScaling(); +} + + + + + + +//#define DEBUG_TRIANGLE_MESH + + + +void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + struct FilteredCallback : public btInternalTriangleIndexCallback + { + btTriangleCallback* m_callback; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) + :m_callback(callback), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax)) + { + //check aabb in triangle-space, before doing this + m_callback->processTriangle(triangle,partId,triangleIndex); + } + + } + + }; + + FilteredCallback filterCallback(callback,aabbMin,aabbMax); + + m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax); +} + + + + + +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + (void)mass; + //moving concave objects not supported + btAssert(0); + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + + +btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const +{ + btVector3 supportVertex; + + btTransform ident; + ident.setIdentity(); + + SupportVertexCallback supportCallback(vec,ident); + + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + + processAllTriangles(&supportCallback,-aabbMax,aabbMax); + + supportVertex = supportCallback.GetSupportVertexLocal(); + + return supportVertex; +} + + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h new file mode 100644 index 00000000..453e5800 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -0,0 +1,90 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TRIANGLE_MESH_SHAPE_H +#define BT_TRIANGLE_MESH_SHAPE_H + +#include "btConcaveShape.h" +#include "btStridingMeshInterface.h" + + +///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. +ATTRIBUTE_ALIGNED16(class) btTriangleMeshShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + btStridingMeshInterface* m_meshInterface; + + ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. + ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! + btTriangleMeshShape(btStridingMeshInterface* meshInterface); + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + virtual ~btTriangleMeshShape(); + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const; + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + btAssert(0); + return localGetSupportingVertex(vec); + } + + void recalcLocalAabb(); + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + btStridingMeshInterface* getMeshInterface() + { + return m_meshInterface; + } + + const btStridingMeshInterface* getMeshInterface() const + { + return m_meshInterface; + } + + const btVector3& getLocalAabbMin() const + { + return m_localAabbMin; + } + const btVector3& getLocalAabbMax() const + { + return m_localAabbMax; + } + + + + //debugging + virtual const char* getName()const {return "TRIANGLEMESH";} + + + +}; + + + + +#endif //BT_TRIANGLE_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleShape.h new file mode 100644 index 00000000..a8a80f82 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -0,0 +1,184 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_OBB_TRIANGLE_MINKOWSKI_H +#define BT_OBB_TRIANGLE_MINKOWSKI_H + +#include "btConvexShape.h" +#include "btBoxShape.h" + +ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape +{ + + +public: + +BT_DECLARE_ALIGNED_ALLOCATOR(); + + btVector3 m_vertices1[3]; + + virtual int getNumVertices() const + { + return 3; + } + + btVector3& getVertexPtr(int index) + { + return m_vertices1[index]; + } + + const btVector3& getVertexPtr(int index) const + { + return m_vertices1[index]; + } + virtual void getVertex(int index,btVector3& vert) const + { + vert = m_vertices1[index]; + } + + virtual int getNumEdges() const + { + return 3; + } + + virtual void getEdge(int i,btVector3& pa,btVector3& pb) const + { + getVertex(i,pa); + getVertex((i+1)%3,pb); + } + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const + { +// btAssert(0); + getAabbSlow(t,aabbMin,aabbMax); + } + + btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const + { + btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]); + return m_vertices1[dots.maxAxis()]; + + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + for (int i=0;i= -tolerance && dist <= tolerance) + { + //inside check on edge-planes + int i; + for (i=0;i<3;i++) + { + btVector3 pa,pb; + getEdge(i,pa,pb); + btVector3 edge = pb-pa; + btVector3 edgeNormal = edge.cross(normal); + edgeNormal.normalize(); + btScalar dist = pt.dot( edgeNormal); + btScalar edgeConst = pa.dot(edgeNormal); + dist -= edgeConst; + if (dist < -tolerance) + return false; + } + + return true; + } + + return false; + } + //debugging + virtual const char* getName()const + { + return "Triangle"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 2; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + calcNormal(penetrationVector); + if (index) + penetrationVector *= btScalar(-1.); + } + + +}; + +#endif //BT_OBB_TRIANGLE_MINKOWSKI_H + diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp new file mode 100644 index 00000000..b148bbd9 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp @@ -0,0 +1,160 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btUniformScalingShape.h" + +btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): +btConvexShape (), m_childConvexShape(convexChildShape), +m_uniformScalingFactor(uniformScalingFactor) +{ + m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE; +} + +btUniformScalingShape::~btUniformScalingShape() +{ +} + + +btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 tmpVertex; + tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); + return tmpVertex*m_uniformScalingFactor; +} + +void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); + int i; + for (i=0;ilocalGetSupportingVertex(vec); + return tmpVertex*m_uniformScalingFactor; +} + + +void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + btVector3 tmpInertia; + m_childConvexShape->calculateLocalInertia(mass,tmpInertia); + inertia = tmpInertia * m_uniformScalingFactor; +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btUniformScalingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getAabbSlow(trans,aabbMin,aabbMax); + +} + +void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ +#if 1 + btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + for (int i=0;i<6;i++) + { + _directions[i] = _directions[i]*t.getBasis(); + } + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + btVector3 aabbMin1(0,0,0),aabbMax1(0,0,0); + + for ( int i = 0; i < 3; ++i ) + { + aabbMax1[i] = t(_supporting[i])[i]; + aabbMin1[i] = t(_supporting[i + 3])[i]; + } + btVector3 marginVec(getMargin(),getMargin(),getMargin()); + aabbMin = aabbMin1-marginVec; + aabbMax = aabbMax1+marginVec; + +#else + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 sv = localGetSupportingVertex(vec*t.getBasis()); + btVector3 tmp = t(sv); + aabbMax[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + sv = localGetSupportingVertex(vec*t.getBasis()); + tmp = t(sv); + aabbMin[i] = tmp[i]-margin; + } + +#endif +} + +void btUniformScalingShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btUniformScalingShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btUniformScalingShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btUniformScalingShape::getMargin() const +{ + return m_childConvexShape->getMargin() * m_uniformScalingFactor; +} + +int btUniformScalingShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.h new file mode 100644 index 00000000..a10f58d2 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.h @@ -0,0 +1,89 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_UNIFORM_SCALING_SHAPE_H +#define BT_UNIFORM_SCALING_SHAPE_H + +#include "btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way. +///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it. +ATTRIBUTE_ALIGNED16(class) btUniformScalingShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + btScalar m_uniformScalingFactor; + + public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); + + virtual ~btUniformScalingShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btScalar getUniformScalingFactor() const + { + return m_uniformScalingFactor; + } + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "UniformScalingShape"; + } + + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/Doxyfile b/Code/Physics/src/BulletCollision/Doxyfile new file mode 100644 index 00000000..4ecb6acb --- /dev/null +++ b/Code/Physics/src/BulletCollision/Doxyfile @@ -0,0 +1,746 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = "Bullet Continuous Collision Detection Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.h *.cpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../../generic/extern + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/Code/Physics/src/BulletCollision/Gimpact/btBoxCollision.h b/Code/Physics/src/BulletCollision/Gimpact/btBoxCollision.h new file mode 100644 index 00000000..0a0357e5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btBoxCollision.h @@ -0,0 +1,645 @@ +#ifndef BT_BOX_COLLISION_H_INCLUDED +#define BT_BOX_COLLISION_H_INCLUDED + +/*! \file gim_box_collision.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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/btTransform.h" + + +///Swap numbers +#define BT_SWAP_NUMBERS(a,b){ \ + a = a+b; \ + b = a-b; \ + a = a-b; \ +}\ + + +#define BT_MAX(a,b) (ab?b:a) + +#define BT_GREATER(x, y) btFabs(x) > (y) + +#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c)) +#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c)) + + + + + + +enum eBT_PLANE_INTERSECTION_TYPE +{ + BT_CONST_BACK_PLANE = 0, + BT_CONST_COLLIDE_PLANE, + BT_CONST_FRONT_PLANE +}; + +//SIMD_FORCE_INLINE bool test_cross_edge_box( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, const btVector3 & extend, +// int dir_index0, +// int dir_index1 +// int component_index0, +// int component_index1) +//{ +// // dir coords are -z and y +// +// const btScalar dir0 = -edge[dir_index0]; +// const btScalar dir1 = edge[dir_index1]; +// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1; +// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1; +// //find minmax +// if(pmin>pmax) +// { +// BT_SWAP_NUMBERS(pmin,pmax); +// } +// //find extends +// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] + +// extend[component_index1] * absolute_edge[dir_index1]; +// +// if(pmin>rad || -rad>pmax) return false; +// return true; +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2); +//} +// +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0); +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1); +//} + + +#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\ +{\ + const btScalar dir0 = -edge[i_dir_0];\ + const btScalar dir1 = edge[i_dir_1];\ + btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\ + btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\ + if(pmin>pmax)\ + {\ + BT_SWAP_NUMBERS(pmin,pmax); \ + }\ + const btScalar abs_dir0 = absolute_edge[i_dir_0];\ + const btScalar abs_dir1 = absolute_edge[i_dir_1];\ + const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\ + if(pmin>rad || -rad>pmax) return false;\ +}\ + + +#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\ +}\ + + +//! Returns the dot product between a vec3f and the col of a matrix +SIMD_FORCE_INLINE btScalar bt_mat3_dot_col( +const btMatrix3x3 & mat, const btVector3 & vec3, int colindex) +{ + return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex]; +} + + +//! Class for transforming a model1 to the space of model0 +ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE +{ +public: + btVector3 m_T1to0;//!< Transforms translation of model1 to model 0 + btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1 + btMatrix3x3 m_AR;//!< Absolute value of m_R1to0 + + SIMD_FORCE_INLINE void calc_absolute_matrix() + { +// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f); +// m_AR[0] = vepsi + m_R1to0[0].absolute(); +// m_AR[1] = vepsi + m_R1to0[1].absolute(); +// m_AR[2] = vepsi + m_R1to0[2].absolute(); + + int i,j; + + for(i=0;i<3;i++) + { + for(j=0;j<3;j++ ) + { + m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]); + } + } + + } + + BT_BOX_BOX_TRANSFORM_CACHE() + { + } + + + + //! Calc the transformation relative 1 to 0. Inverts matrics by transposing + SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1) + { + + btTransform temp_trans = trans0.inverse(); + temp_trans = temp_trans * trans1; + + m_T1to0 = temp_trans.getOrigin(); + m_R1to0 = temp_trans.getBasis(); + + + calc_absolute_matrix(); + } + + //! Calcs the full invertion of the matrices. Useful for scaling matrices + SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1) + { + m_R1to0 = trans0.getBasis().inverse(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const + { + return point.dot3( m_R1to0[0], m_R1to0[1], m_R1to0[2] ) + m_T1to0; + } +}; + + +#define BOX_PLANE_EPSILON 0.000001f + +//! Axis aligned box +ATTRIBUTE_ALIGNED16 (class) btAABB +{ +public: + btVector3 m_min; + btVector3 m_max; + + btAABB() + {} + + + btAABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + } + + btAABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3, + btScalar margin) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + btAABB(const btAABB &other): + m_min(other.m_min),m_max(other.m_max) + { + } + + btAABB(const btAABB &other,btScalar margin ): + m_min(other.m_min),m_max(other.m_max) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void invalidate() + { + m_min[0] = SIMD_INFINITY; + m_min[1] = SIMD_INFINITY; + m_min[2] = SIMD_INFINITY; + m_max[0] = -SIMD_INFINITY; + m_max[1] = -SIMD_INFINITY; + m_max[2] = -SIMD_INFINITY; + } + + SIMD_FORCE_INLINE void increment_margin(btScalar margin) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin) + { + m_min[0] = other.m_min[0] - margin; + m_min[1] = other.m_min[1] - margin; + m_min[2] = other.m_min[2] - margin; + + m_max[0] = other.m_max[0] + margin; + m_max[1] = other.m_max[1] + margin; + m_max[2] = other.m_max[2] + margin; + } + + template + SIMD_FORCE_INLINE void calc_from_triangle( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + } + + template + SIMD_FORCE_INLINE void calc_from_triangle_margin( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3, btScalar margin) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform(const btTransform & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans(center); + + btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(), + trans.getBasis().getRow(1).absolute(), + trans.getBasis().getRow(2).absolute()); + + m_min = center - textends; + m_max = center + textends; + } + + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans.transform(center); + + btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(), + trans.m_R1to0.getRow(1).absolute(), + trans.m_R1to0.getRow(2).absolute()); + + m_min = center - textends; + m_max = center + textends; + } + + //! Merges a Box + SIMD_FORCE_INLINE void merge(const btAABB & box) + { + m_min[0] = BT_MIN(m_min[0],box.m_min[0]); + m_min[1] = BT_MIN(m_min[1],box.m_min[1]); + m_min[2] = BT_MIN(m_min[2],box.m_min[2]); + + m_max[0] = BT_MAX(m_max[0],box.m_max[0]); + m_max[1] = BT_MAX(m_max[1],box.m_max[1]); + m_max[2] = BT_MAX(m_max[2],box.m_max[2]); + } + + //! Merges a point + template + SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point) + { + m_min[0] = BT_MIN(m_min[0],point[0]); + m_min[1] = BT_MIN(m_min[1],point[1]); + m_min[2] = BT_MIN(m_min[2],point[2]); + + m_max[0] = BT_MAX(m_max[0],point[0]); + m_max[1] = BT_MAX(m_max[1],point[1]); + m_max[2] = BT_MAX(m_max[2],point[2]); + } + + //! Gets the extend and center + SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const + { + center = (m_max+m_min)*0.5f; + extend = m_max - center; + } + + //! Finds the intersecting box between this box and the other. + SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const + { + intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]); + intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]); + intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]); + + intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]); + intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]); + intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]); + } + + + SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const + { + if(m_min[0] > other.m_max[0] || + m_max[0] < other.m_min[0] || + m_min[1] > other.m_max[1] || + m_max[1] < other.m_min[1] || + m_min[2] > other.m_max[2] || + m_max[2] < other.m_min[2]) + { + return false; + } + return true; + } + + /*! \brief Finds the Ray intersection parameter. + \param aabb Aligned box + \param vorigin A vec3f with the origin of the ray + \param vdir A vec3f with the direction of the ray + */ + SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const + { + btVector3 extents,center; + this->get_center_extend(center,extents);; + + btScalar Dx = vorigin[0] - center[0]; + if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false; + btScalar Dy = vorigin[1] - center[1]; + if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false; + btScalar Dz = vorigin[2] - center[2]; + if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false; + + + btScalar f = vdir[1] * Dz - vdir[2] * Dy; + if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false; + f = vdir[2] * Dx - vdir[0] * Dz; + if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false; + f = vdir[0] * Dy - vdir[1] * Dx; + if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false; + return true; + } + + + SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extend = m_max-center; + + btScalar _fOrigin = direction.dot(center); + btScalar _fMaximumExtent = extend.dot(direction.absolute()); + vmin = _fOrigin - _fMaximumExtent; + vmax = _fOrigin + _fMaximumExtent; + } + + SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const + { + btScalar _fmin,_fmax; + this->projection_interval(plane,_fmin,_fmax); + + if(plane[3] > _fmax + BOX_PLANE_EPSILON) + { + return BT_CONST_BACK_PLANE; // 0 + } + + if(plane[3]+BOX_PLANE_EPSILON >=_fmin) + { + return BT_CONST_COLLIDE_PLANE; //1 + } + return BT_CONST_FRONT_PLANE;//2 + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const + { + btAABB tbox = box; + tbox.appy_transform(trans1_to_0); + return has_collision(tbox); + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box, + const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const + { + btAABB tbox = box; + tbox.appy_transform_trans_cache(trans1_to_0); + return has_collision(tbox); + } + + //! transcache is the transformation cache from box to this AABB + SIMD_FORCE_INLINE bool overlapping_trans_cache( + const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const + { + + //Taken from OPCODE + btVector3 ea,eb;//extends + btVector3 ca,cb;//extends + get_center_extend(ca,ea); + box.get_center_extend(cb,eb); + + + btVector3 T; + btScalar t,t2; + int i; + + // Class I : A's basis vectors + for(i=0;i<3;i++) + { + T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i]; + t = transcache.m_AR[i].dot(eb) + ea[i]; + if(BT_GREATER(T[i], t)) return false; + } + // Class II : B's basis vectors + for(i=0;i<3;i++) + { + t = bt_mat3_dot_col(transcache.m_R1to0,T,i); + t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i]; + if(BT_GREATER(t,t2)) return false; + } + // Class III : 9 cross products + if(fulltest) + { + int j,m,n,o,p,q,r; + for(i=0;i<3;i++) + { + m = (i+1)%3; + n = (i+2)%3; + o = i==0?1:0; + p = i==2?1:2; + for(j=0;j<3;j++) + { + q = j==2?1:2; + r = j==0?1:0; + t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j]; + t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] + + eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r]; + if(BT_GREATER(t,t2)) return false; + } + } + } + return true; + } + + //! Simple test for planes. + SIMD_FORCE_INLINE bool collide_plane( + const btVector4 & plane) const + { + eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane); + return (classify == BT_CONST_COLLIDE_PLANE); + } + + //! test for a triangle, with edges + SIMD_FORCE_INLINE bool collide_triangle_exact( + const btVector3 & p1, + const btVector3 & p2, + const btVector3 & p3, + const btVector4 & triangle_plane) const + { + if(!collide_plane(triangle_plane)) return false; + + btVector3 center,extends; + this->get_center_extend(center,extends); + + const btVector3 v1(p1 - center); + const btVector3 v2(p2 - center); + const btVector3 v3(p3 - center); + + //First axis + btVector3 diff(v2 - v1); + btVector3 abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends); + + + diff = v3 - v2; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends); + + diff = v1 - v3; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends); + + return true; + } +}; + + +//! Compairison of transformation objects +SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2) +{ + if(!(t1.getOrigin() == t2.getOrigin()) ) return false; + + if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false; + if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false; + if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false; + return true; +} + + + +#endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/btClipPolygon.h b/Code/Physics/src/BulletCollision/Gimpact/btClipPolygon.h new file mode 100644 index 00000000..de0a5231 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btClipPolygon.h @@ -0,0 +1,182 @@ +#ifndef BT_CLIP_POLYGON_H_INCLUDED +#define BT_CLIP_POLYGON_H_INCLUDED + +/*! \file btClipPolygon.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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/btTransform.h" +#include "LinearMath/btGeometryUtil.h" + + +SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point) +{ + return point.dot(plane) - plane[3]; +} + +/*! Vector blending +Takes two vectors a, b, blends them together*/ +SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor) +{ + vr = (1-blend_factor)*va + blend_factor*vb; +} + +//! This function calcs the distance from a 3D plane +SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect( + const btVector3 & point0, + const btVector3 & point1, + btScalar dist0, + btScalar dist1, + btVector3 * clipped, + int & clipped_count) +{ + bool _prevclassif = (dist0>SIMD_EPSILON); + bool _classif = (dist1>SIMD_EPSILON); + if(_classif!=_prevclassif) + { + btScalar blendfactor = -dist0/(dist1-dist0); + bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor); + clipped_count++; + } + if(!_classif) + { + clipped[clipped_count] = point1; + clipped_count++; + } +} + + +//! Clips a polygon by a plane +/*! +*\return The count of the clipped counts +*/ +SIMD_FORCE_INLINE int bt_plane_clip_polygon( + const btVector4 & plane, + const btVector3 * polygon_points, + int polygon_point_count, + btVector3 * clipped) +{ + int clipped_count = 0; + + + //clip first point + btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);; + if(!(firstdist>SIMD_EPSILON)) + { + clipped[clipped_count] = polygon_points[0]; + clipped_count++; + } + + btScalar olddist = firstdist; + for(int i=1;iSIMD_EPSILON)) + { + clipped[clipped_count] = point0; + clipped_count++; + } + + // point 1 + btScalar olddist = firstdist; + btScalar dist = bt_distance_point_plane(plane,point1); + + bt_plane_clip_polygon_collect( + point0,point1, + olddist, + dist, + clipped, + clipped_count); + + olddist = dist; + + + // point 2 + dist = bt_distance_point_plane(plane,point2); + + bt_plane_clip_polygon_collect( + point1,point2, + olddist, + dist, + clipped, + clipped_count); + olddist = dist; + + + + //RETURN TO FIRST point0 + bt_plane_clip_polygon_collect( + point2,point0, + olddist, + firstdist, + clipped, + clipped_count); + + return clipped_count; +} + + + + + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/btCompoundFromGimpact.h b/Code/Physics/src/BulletCollision/Gimpact/btCompoundFromGimpact.h new file mode 100644 index 00000000..02f8b678 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btCompoundFromGimpact.h @@ -0,0 +1,93 @@ +#ifndef BT_COMPOUND_FROM_GIMPACT +#define BT_COMPOUND_FROM_GIMPACT + +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "btGImpactShape.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" + +struct MyCallback : public btTriangleRaycastCallback + { + int m_ignorePart; + int m_ignoreTriangleIndex; + + + MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex) + :btTriangleRaycastCallback(from,to), + m_ignorePart(ignorePart), + m_ignoreTriangleIndex(ignoreTriangleIndex) + { + + } + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex) + { + if (partId!=m_ignorePart || triangleIndex!=m_ignoreTriangleIndex) + { + if (hitFraction < m_hitFraction) + return hitFraction; + } + + return m_hitFraction; + } + }; + struct MyInternalTriangleIndexCallback :public btInternalTriangleIndexCallback + { + const btGImpactMeshShape* m_gimpactShape; + btCompoundShape* m_colShape; + btScalar m_depth; + + MyInternalTriangleIndexCallback (btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth) + :m_colShape(colShape), + m_gimpactShape(meshShape), + m_depth(depth) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + btVector3 scale = m_gimpactShape->getLocalScaling(); + btVector3 v0=triangle[0]*scale; + btVector3 v1=triangle[1]*scale; + btVector3 v2=triangle[2]*scale; + + btVector3 centroid = (v0+v1+v2)/3; + btVector3 normal = (v1-v0).cross(v2-v0); + normal.normalize(); + btVector3 rayFrom = centroid; + btVector3 rayTo = centroid-normal*m_depth; + + MyCallback cb(rayFrom,rayTo,partId,triangleIndex); + + m_gimpactShape->processAllTrianglesRay(&cb,rayFrom, rayTo); + if (cb.m_hitFraction<1) + { + rayTo.setInterpolate3(cb.m_from,cb.m_to,cb.m_hitFraction); + //rayTo = cb.m_from; + //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction); + //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0)); + } + + + + btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0,v1,v2,rayTo); + btTransform ident; + ident.setIdentity(); + m_colShape->addChildShape(ident,tet); + } + }; + +btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth) +{ + btCompoundShape* colShape = new btCompoundShape(); + + btTransform tr; + tr.setIdentity(); + + MyInternalTriangleIndexCallback cb(colShape,gimpactMesh, depth); + btVector3 aabbMin,aabbMax; + gimpactMesh->getAabb(tr,aabbMin,aabbMax); + gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb,aabbMin,aabbMax); + + return colShape; +} + +#endif //BT_COMPOUND_FROM_GIMPACT \ No newline at end of file diff --git a/Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.cpp b/Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.cpp new file mode 100644 index 00000000..eed31d83 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.cpp @@ -0,0 +1,181 @@ + +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 "btContactProcessing.h" + +#define MAX_COINCIDENT 8 + +struct CONTACT_KEY_TOKEN +{ + unsigned int m_key; + int m_value; + CONTACT_KEY_TOKEN() + { + } + + CONTACT_KEY_TOKEN(unsigned int key,int token) + { + m_key = key; + m_value = token; + } + + CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken) + { + m_key = rtoken.m_key; + m_value = rtoken.m_value; + } + + inline bool operator <(const CONTACT_KEY_TOKEN& other) const + { + return (m_key < other.m_key); + } + + inline bool operator >(const CONTACT_KEY_TOKEN& other) const + { + return (m_key > other.m_key); + } + +}; + +class CONTACT_KEY_TOKEN_COMP +{ + public: + + bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) const + { + return ( a < b ); + } +}; + + +void btContactArray::merge_contacts( + const btContactArray & contacts, bool normal_contact_average) +{ + clear(); + + int i; + if(contacts.size()==0) return; + + + if(contacts.size()==1) + { + push_back(contacts[0]); + return; + } + + btAlignedObjectArray keycontacts; + + keycontacts.reserve(contacts.size()); + + //fill key contacts + + for ( i = 0;im_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &(*this)[this->size()-1]; + } + last_key = key; + } +} + +void btContactArray::merge_contacts_unique(const btContactArray & contacts) +{ + clear(); + + if(contacts.size()==0) return; + + if(contacts.size()==1) + { + push_back(contacts[0]); + return; + } + + GIM_CONTACT average_contact = contacts[0]; + + for (int i=1;i +{ +public: + btContactArray() + { + reserve(64); + } + + SIMD_FORCE_INLINE void push_contact( + const btVector3 &point,const btVector3 & normal, + btScalar depth, int feature1, int feature2) + { + push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) ); + } + + SIMD_FORCE_INLINE void push_triangle_contacts( + const GIM_TRIANGLE_CONTACT & tricontact, + int feature1,int feature2) + { + for(int i = 0;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + //swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); + + return splitIndex; + +} + + +void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +{ + int curIndex = m_num_nodes; + m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if ((endIndex-startIndex)==1) + { + //We have a leaf node + setNodeBound(curIndex,primitive_boxes[startIndex].m_bound); + m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data); + + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + //split axis + int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); + + splitIndex = _sort_and_calc_splitting_index( + primitive_boxes,startIndex,endIndex, + splitIndex//split axis + ); + + + //calc this node bounding box + + btAABB node_bound; + node_bound.invalidate(); + + for (int i=startIndex;iget_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //get left bound + btAABB bound; + bound.invalidate(); + + btAABB temp_box; + + int child_node = getLeftNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + child_node = getRightNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + setNodeBound(nodecount,bound); + } + } +} + +//! this rebuild the entire set +void btGImpactBvh::buildSet() +{ + //obtain primitive boxes + GIM_BVH_DATA_ARRAY primitive_boxes; + primitive_boxes.resize(m_primitive_manager->get_primitive_count()); + + for (int i = 0;iget_primitive_box(i,primitive_boxes[i].m_bound); + primitive_boxes[i].m_data = i; + } + + m_box_tree.build_tree(primitive_boxes); +} + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.has_collision(box); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactBvh::rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + +SIMD_FORCE_INLINE bool _node_collision( + btGImpactBvh * boxset0, btGImpactBvh * boxset1, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0 ,int node1, bool complete_primitive_tests) +{ + btAABB box0; + boxset0->getNodeBound(node0,box0); + btAABB box1; + boxset1->getNodeBound(node1,box1); + + return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests ); +// box1.appy_transform_trans_cache(trans_cache_1to0); +// return box0.has_collision(box1); + +} + + +//stackless recursive collision routine +static void _find_collision_pairs_recursive( + btGImpactBvh * boxset0, btGImpactBvh * boxset1, + btPairSet * collision_pairs, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0, int node1, bool complete_primitive_tests) +{ + + + + if( _node_collision( + boxset0,boxset1,trans_cache_1to0, + node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes + + if(boxset0->isLeafNode(node0)) + { + if(boxset1->isLeafNode(node1)) + { + // collision result + collision_pairs->push_pair( + boxset0->getNodeData(node0),boxset1->getNodeData(node1)); + return; + } + else + { + + //collide left recursive + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getLeftNode(node1),false); + + //collide right recursive + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getRightNode(node1),false); + + + } + } + else + { + if(boxset1->isLeafNode(node1)) + { + + //collide left recursive + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),node1,false); + + + //collide right recursive + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),node1,false); + + + } + else + { + //collide left0 left1 + + + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false); + + //collide left0 right1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false); + + + //collide right0 left1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false); + + //collide right0 right1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getRightNode(node1),false); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf +} + + +void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0, + btGImpactBvh * boxset1, const btTransform & trans1, + btPairSet & collision_pairs) +{ + + if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return; + + BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + + trans_cache_1to0.calc_from_homogenic(trans0,trans1); + +#ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_tree_time(); +#endif //TRI_COLLISION_PROFILING + + _find_collision_pairs_recursive( + boxset0,boxset1, + &collision_pairs,trans_cache_1to0,0,0,true); +#ifdef TRI_COLLISION_PROFILING + bt_end_gim02_tree_time(); +#endif //TRI_COLLISION_PROFILING + +} + diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.h b/Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.h new file mode 100644 index 00000000..6174ae97 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.h @@ -0,0 +1,396 @@ +#ifndef GIM_BOX_SET_H_INCLUDED +#define GIM_BOX_SET_H_INCLUDED + +/*! \file gim_box_set.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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/btAlignedObjectArray.h" + +#include "btBoxCollision.h" +#include "btTriangleShapeEx.h" + + + + + +//! Overlapping pair +struct GIM_PAIR +{ + int m_index1; + int m_index2; + GIM_PAIR() + {} + + GIM_PAIR(const GIM_PAIR & p) + { + m_index1 = p.m_index1; + m_index2 = p.m_index2; + } + + GIM_PAIR(int index1, int index2) + { + m_index1 = index1; + m_index2 = index2; + } +}; + +//! A pairset array +class btPairSet: public btAlignedObjectArray +{ +public: + btPairSet() + { + reserve(32); + } + inline void push_pair(int index1,int index2) + { + push_back(GIM_PAIR(index1,index2)); + } + + inline void push_pair_inv(int index1,int index2) + { + push_back(GIM_PAIR(index2,index1)); + } +}; + + +///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box +struct GIM_BVH_DATA +{ + btAABB m_bound; + int m_data; +}; + +//! Node Structure for trees +class GIM_BVH_TREE_NODE +{ +public: + btAABB m_bound; +protected: + int m_escapeIndexOrDataIndex; +public: + GIM_BVH_TREE_NODE() + { + m_escapeIndexOrDataIndex = 0; + } + + SIMD_FORCE_INLINE bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrDataIndex>=0); + } + + SIMD_FORCE_INLINE int getEscapeIndex() const + { + //btAssert(m_escapeIndexOrDataIndex < 0); + return -m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setEscapeIndex(int index) + { + m_escapeIndexOrDataIndex = -index; + } + + SIMD_FORCE_INLINE int getDataIndex() const + { + //btAssert(m_escapeIndexOrDataIndex >= 0); + + return m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setDataIndex(int index) + { + m_escapeIndexOrDataIndex = index; + } + +}; + + +class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray +{ +}; + + +class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray +{ +}; + + + + +//! Basic Box tree structure +class btBvhTree +{ +protected: + int m_num_nodes; + GIM_BVH_TREE_NODE_ARRAY m_node_array; +protected: + int _sort_and_calc_splitting_index( + GIM_BVH_DATA_ARRAY & primitive_boxes, + int startIndex, int endIndex, int splitAxis); + + int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + + void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); +public: + btBvhTree() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_node_array[nodeindex].isLeafNode(); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_node_array[nodeindex].getDataIndex(); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + bound = m_node_array[nodeindex].m_bound; + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_node_array[nodeindex].m_bound = bound; + } + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return nodeindex+1; + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; + return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_node_array[nodeindex].getEscapeIndex(); + } + + SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const + { + return &m_node_array[index]; + } + + //!@} +}; + + +//! Prototype Base class for primitive classification +/*! +This class is a wrapper for primitive collections. +This tells relevant info for the Bounding Box set classes, which take care of space classification. +This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons. +*/ +class btPrimitiveManagerBase +{ +public: + + virtual ~btPrimitiveManagerBase() {} + + //! determines if this manager consist on only triangles, which special case will be optimized + virtual bool is_trimesh() const = 0; + virtual int get_primitive_count() const = 0; + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0; + //! retrieves only the points of the triangle, and the collision margin + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0; +}; + + +//! Structure for containing Boxes +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like btPrimitiveManagerBase ) +*/ +class btGImpactBvh +{ +protected: + btBvhTree m_box_tree; + btPrimitiveManagerBase * m_primitive_manager; + +protected: + //stackless refit + void refit(); +public: + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactBvh() + { + m_primitive_manager = NULL; + } + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactBvh(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btAABB getGlobalBox() const + { + btAABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const + { + return m_primitive_manager; + } + + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + void buildSet(); + + //! returns the indices of the primitives in the m_primitive_manager + bool boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const; + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, + const btTransform & transform, btAlignedObjectArray & collided_results) const + { + btAABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const; + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager->is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return m_box_tree.getLeftNode(nodeindex); + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + return m_box_tree.getRightNode(nodeindex); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_box_tree.getEscapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const + { + m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); + } + + + SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const + { + return m_box_tree.get_node_pointer(index); + } + +#ifdef TRI_COLLISION_PROFILING + static float getAverageTreeCollisionTime(); +#endif //TRI_COLLISION_PROFILING + + static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1, + btGImpactBvh * boxset2, const btTransform & trans2, + btPairSet & collision_pairs); +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp new file mode 100644 index 00000000..2e87475e --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp @@ -0,0 +1,932 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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. +*/ +/* +Author: Francisco Len Nßjera +Concave-Concave Collision + +*/ + +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "btGImpactCollisionAlgorithm.h" +#include "btContactProcessing.h" +#include "LinearMath/btQuickprof.h" + + +//! Class for accessing the plane equation +class btPlaneShape : public btStaticPlaneShape +{ +public: + + btPlaneShape(const btVector3& v, float f) + :btStaticPlaneShape(v,f) + { + } + + void get_plane_equation(btVector4 &equation) + { + equation[0] = m_planeNormal[0]; + equation[1] = m_planeNormal[1]; + equation[2] = m_planeNormal[2]; + equation[3] = m_planeConstant; + } + + + void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) const + { + equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal); + equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal); + equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal); + equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant; + } +}; + + + +////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef TRI_COLLISION_PROFILING + +btClock g_triangle_clock; + +float g_accum_triangle_collision_time = 0; +int g_count_triangle_collision = 0; + +void bt_begin_gim02_tri_time() +{ + g_triangle_clock.reset(); +} + +void bt_end_gim02_tri_time() +{ + g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds(); + g_count_triangle_collision++; +} +#endif //TRI_COLLISION_PROFILING +//! Retrieving shapes shapes +/*! +Declared here due of insuficent space on Pool allocators +*/ +//!@{ +class GIM_ShapeRetriever +{ +public: + const btGImpactShapeInterface * m_gim_shape; + btTriangleShapeEx m_trishape; + btTetrahedronShapeEx m_tetrashape; + +public: + class ChildShapeRetriever + { + public: + GIM_ShapeRetriever * m_parent; + virtual const btCollisionShape * getChildShape(int index) + { + return m_parent->m_gim_shape->getChildShape(index); + } + virtual ~ChildShapeRetriever() {} + }; + + class TriangleShapeRetriever:public ChildShapeRetriever + { + public: + + virtual btCollisionShape * getChildShape(int index) + { + m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape); + return &m_parent->m_trishape; + } + virtual ~TriangleShapeRetriever() {} + }; + + class TetraShapeRetriever:public ChildShapeRetriever + { + public: + + virtual btCollisionShape * getChildShape(int index) + { + m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape); + return &m_parent->m_tetrashape; + } + }; +public: + ChildShapeRetriever m_child_retriever; + TriangleShapeRetriever m_tri_retriever; + TetraShapeRetriever m_tetra_retriever; + ChildShapeRetriever * m_current_retriever; + + GIM_ShapeRetriever(const btGImpactShapeInterface * gim_shape) + { + m_gim_shape = gim_shape; + //select retriever + if(m_gim_shape->needsRetrieveTriangles()) + { + m_current_retriever = &m_tri_retriever; + } + else if(m_gim_shape->needsRetrieveTetrahedrons()) + { + m_current_retriever = &m_tetra_retriever; + } + else + { + m_current_retriever = &m_child_retriever; + } + + m_current_retriever->m_parent = this; + } + + const btCollisionShape * getChildShape(int index) + { + return m_current_retriever->getChildShape(index); + } + + +}; + + + +//!@} + + +#ifdef TRI_COLLISION_PROFILING + +//! Gets the average time in miliseconds of tree collisions +float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime() +{ + return btGImpactBoxSet::getAverageTreeCollisionTime(); + +} + +//! Gets the average time in miliseconds of triangle collisions +float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime() +{ + if(g_count_triangle_collision == 0) return 0; + + float avgtime = g_accum_triangle_collision_time; + avgtime /= (float)g_count_triangle_collision; + + g_accum_triangle_collision_time = 0; + g_count_triangle_collision = 0; + + return avgtime; +} + +#endif //TRI_COLLISION_PROFILING + + + +btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap) +{ + m_manifoldPtr = NULL; + m_convex_algorithm = NULL; +} + +btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm() +{ + clearCache(); +} + + + + + +void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btVector3 & point, + const btVector3 & normal, + btScalar distance) +{ + m_resultOut->setShapeIdentifiersA(m_part0,m_triface0); + m_resultOut->setShapeIdentifiersB(m_part1,m_triface1); + checkManifold(body0Wrap,body1Wrap); + m_resultOut->addContactPoint(normal,point,distance); +} + + +void btGImpactCollisionAlgorithm::shape_vs_shape_collision( + const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btCollisionShape * shape0, + const btCollisionShape * shape1) +{ + + + { + + btCollisionAlgorithm* algor = newAlgorithm(body0Wrap,body1Wrap); + // post : checkManifold is called + + m_resultOut->setShapeIdentifiersA(m_part0,m_triface0); + m_resultOut->setShapeIdentifiersB(m_part1,m_triface1); + + algor->processCollision(body0Wrap,body1Wrap,*m_dispatchInfo,m_resultOut); + + algor->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(algor); + } + +} + +void btGImpactCollisionAlgorithm::convex_vs_convex_collision( + const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btCollisionShape* shape0, + const btCollisionShape* shape1) +{ + + m_resultOut->setShapeIdentifiersA(m_part0,m_triface0); + m_resultOut->setShapeIdentifiersB(m_part1,m_triface1); + + btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0); + btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),m_part1,m_triface1); + checkConvexAlgorithm(&ob0,&ob1); + m_convex_algorithm->processCollision(&ob0,&ob1,*m_dispatchInfo,m_resultOut); + + +} + + + + +void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + const btGImpactShapeInterface * shape0, + const btGImpactShapeInterface * shape1,btPairSet & pairset) +{ + if(shape0->hasBoxSet() && shape1->hasBoxSet()) + { + btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset); + } + else + { + btAABB boxshape0; + btAABB boxshape1; + int i = shape0->getNumChildShapes(); + + while(i--) + { + shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max); + + int j = shape1->getNumChildShapes(); + while(j--) + { + shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max); + + if(boxshape1.has_collision(boxshape0)) + { + pairset.push_pair(i,j); + } + } + } + } + + +} + + +void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + const btGImpactShapeInterface * shape0, + const btCollisionShape * shape1, + btAlignedObjectArray & collided_primitives) +{ + + btAABB boxshape; + + + if(shape0->hasBoxSet()) + { + btTransform trans1to0 = trans0.inverse(); + trans1to0 *= trans1; + + shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max); + + shape0->getBoxSet()->boxQuery(boxshape, collided_primitives); + } + else + { + shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max); + + btAABB boxshape0; + int i = shape0->getNumChildShapes(); + + while(i--) + { + shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max); + + if(boxshape.has_collision(boxshape0)) + { + collided_primitives.push_back(i); + } + } + + } + +} + + +void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactMeshShapePart * shape0, + const btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count) +{ + btTriangleShapeEx tri0; + btTriangleShapeEx tri1; + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + const int * pair_pointer = pairs; + + while(pair_count--) + { + + m_triface0 = *(pair_pointer); + m_triface1 = *(pair_pointer+1); + pair_pointer+=2; + + + + shape0->getBulletTriangle(m_triface0,tri0); + shape1->getBulletTriangle(m_triface1,tri1); + + + //collide two convex shapes + if(tri0.overlap_test_conservative(tri1)) + { + convex_vs_convex_collision(body0Wrap,body1Wrap,&tri0,&tri1); + } + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); +} + +void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btGImpactMeshShapePart * shape0, + const btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count) +{ + btTransform orgtrans0 = body0Wrap->getWorldTransform(); + btTransform orgtrans1 = body1Wrap->getWorldTransform(); + + btPrimitiveTriangle ptri0; + btPrimitiveTriangle ptri1; + GIM_TRIANGLE_CONTACT contact_data; + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + const int * pair_pointer = pairs; + + while(pair_count--) + { + + m_triface0 = *(pair_pointer); + m_triface1 = *(pair_pointer+1); + pair_pointer+=2; + + + shape0->getPrimitiveTriangle(m_triface0,ptri0); + shape1->getPrimitiveTriangle(m_triface1,ptri1); + + #ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_tri_time(); + #endif + + ptri0.applyTransform(orgtrans0); + ptri1.applyTransform(orgtrans1); + + + //build planes + ptri0.buildTriPlane(); + ptri1.buildTriPlane(); + // test conservative + + + + if(ptri0.overlap_test_conservative(ptri1)) + { + if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data)) + { + + int j = contact_data.m_point_count; + while(j--) + { + + addContactPoint(body0Wrap, body1Wrap, + contact_data.m_points[j], + contact_data.m_separating_normal, + -contact_data.m_penetration_depth); + } + } + } + + #ifdef TRI_COLLISION_PROFILING + bt_end_gim02_tri_time(); + #endif + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); + +} + + +void btGImpactCollisionAlgorithm::gimpact_vs_gimpact( + const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactShapeInterface * shape0, + const btGImpactShapeInterface * shape1) +{ + + if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + const btGImpactMeshShape * meshshape0 = static_cast(shape0); + m_part0 = meshshape0->getMeshPartCount(); + + while(m_part0--) + { + gimpact_vs_gimpact(body0Wrap,body1Wrap,meshshape0->getMeshPart(m_part0),shape1); + } + + return; + } + + if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + const btGImpactMeshShape * meshshape1 = static_cast(shape1); + m_part1 = meshshape1->getMeshPartCount(); + + while(m_part1--) + { + + gimpact_vs_gimpact(body0Wrap,body1Wrap,shape0,meshshape1->getMeshPart(m_part1)); + + } + + return; + } + + + btTransform orgtrans0 = body0Wrap->getWorldTransform(); + btTransform orgtrans1 = body1Wrap->getWorldTransform(); + + btPairSet pairset; + + gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset); + + if(pairset.size()== 0) return; + + if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART && + shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART) + { + const btGImpactMeshShapePart * shapepart0 = static_cast(shape0); + const btGImpactMeshShapePart * shapepart1 = static_cast(shape1); + //specialized function + #ifdef BULLET_TRIANGLE_COLLISION + collide_gjk_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size()); + #else + collide_sat_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size()); + #endif + + return; + } + + //general function + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + GIM_ShapeRetriever retriever0(shape0); + GIM_ShapeRetriever retriever1(shape1); + + bool child_has_transform0 = shape0->childrenHasTransform(); + bool child_has_transform1 = shape1->childrenHasTransform(); + + int i = pairset.size(); + while(i--) + { + GIM_PAIR * pair = &pairset[i]; + m_triface0 = pair->m_index1; + m_triface1 = pair->m_index2; + const btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0); + const btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1); + + btTransform tr0 = body0Wrap->getWorldTransform(); + btTransform tr1 = body1Wrap->getWorldTransform(); + + if(child_has_transform0) + { + tr0 = orgtrans0*shape0->getChildTransform(m_triface0); + } + + if(child_has_transform1) + { + tr1 = orgtrans1*shape1->getChildTransform(m_triface1); + } + + btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),tr0,m_part0,m_triface0); + btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),tr1,m_part1,m_triface1); + + //collide two convex shapes + convex_vs_convex_collision(&ob0,&ob1,colshape0,colshape1); + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); +} + +void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactShapeInterface * shape0, + const btCollisionShape * shape1,bool swapped) +{ + if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + const btGImpactMeshShape * meshshape0 = static_cast(shape0); + int& part = swapped ? m_part1 : m_part0; + part = meshshape0->getMeshPartCount(); + + while(part--) + { + + gimpact_vs_shape(body0Wrap, + body1Wrap, + meshshape0->getMeshPart(part), + shape1,swapped); + + } + + return; + } + + #ifdef GIMPACT_VS_PLANE_COLLISION + if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART && + shape1->getShapeType() == STATIC_PLANE_PROXYTYPE) + { + const btGImpactMeshShapePart * shapepart = static_cast(shape0); + const btStaticPlaneShape * planeshape = static_cast(shape1); + gimpacttrimeshpart_vs_plane_collision(body0Wrap,body1Wrap,shapepart,planeshape,swapped); + return; + } + + #endif + + + + if(shape1->isCompound()) + { + const btCompoundShape * compoundshape = static_cast(shape1); + gimpact_vs_compoundshape(body0Wrap,body1Wrap,shape0,compoundshape,swapped); + return; + } + else if(shape1->isConcave()) + { + const btConcaveShape * concaveshape = static_cast(shape1); + gimpact_vs_concave(body0Wrap,body1Wrap,shape0,concaveshape,swapped); + return; + } + + + btTransform orgtrans0 = body0Wrap->getWorldTransform(); + + btTransform orgtrans1 = body1Wrap->getWorldTransform(); + + btAlignedObjectArray collided_results; + + gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results); + + if(collided_results.size() == 0) return; + + + shape0->lockChildShapes(); + + GIM_ShapeRetriever retriever0(shape0); + + + bool child_has_transform0 = shape0->childrenHasTransform(); + + + int i = collided_results.size(); + + while(i--) + { + int child_index = collided_results[i]; + if(swapped) + m_triface1 = child_index; + else + m_triface0 = child_index; + + const btCollisionShape * colshape0 = retriever0.getChildShape(child_index); + + btTransform tr0 = body0Wrap->getWorldTransform(); + + if(child_has_transform0) + { + tr0 = orgtrans0*shape0->getChildTransform(child_index); + } + + btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0); + const btCollisionObjectWrapper* prevObj0 = m_resultOut->getBody0Wrap(); + + if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob0.getCollisionObject()) + { + m_resultOut->setBody0Wrap(&ob0); + } else + { + m_resultOut->setBody1Wrap(&ob0); + } + + //collide two shapes + if(swapped) + { + + shape_vs_shape_collision(body1Wrap,&ob0,shape1,colshape0); + } + else + { + + shape_vs_shape_collision(&ob0,body1Wrap,colshape0,shape1); + } + m_resultOut->setBody0Wrap(prevObj0); + + } + + shape0->unlockChildShapes(); + +} + +void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btGImpactShapeInterface * shape0, + const btCompoundShape * shape1,bool swapped) +{ + btTransform orgtrans1 = body1Wrap->getWorldTransform(); + + int i = shape1->getNumChildShapes(); + while(i--) + { + + const btCollisionShape * colshape1 = shape1->getChildShape(i); + btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i); + + btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),childtrans1,-1,i); + + const btCollisionObjectWrapper* tmp = 0; + if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject()) + { + tmp = m_resultOut->getBody0Wrap(); + m_resultOut->setBody0Wrap(&ob1); + } else + { + tmp = m_resultOut->getBody1Wrap(); + m_resultOut->setBody1Wrap(&ob1); + } + //collide child shape + gimpact_vs_shape(body0Wrap, &ob1, + shape0,colshape1,swapped); + + if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject()) + { + m_resultOut->setBody0Wrap(tmp); + } else + { + m_resultOut->setBody1Wrap(tmp); + } + } +} + +void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision( + const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactMeshShapePart * shape0, + const btStaticPlaneShape * shape1,bool swapped) +{ + + + btTransform orgtrans0 = body0Wrap->getWorldTransform(); + btTransform orgtrans1 = body1Wrap->getWorldTransform(); + + const btPlaneShape * planeshape = static_cast(shape1); + btVector4 plane; + planeshape->get_plane_equation_transformed(orgtrans1,plane); + + //test box against plane + + btAABB tribox; + shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max); + tribox.increment_margin(planeshape->getMargin()); + + if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return; + + shape0->lockChildShapes(); + + btScalar margin = shape0->getMargin() + planeshape->getMargin(); + + btVector3 vertex; + int vi = shape0->getVertexCount(); + while(vi--) + { + shape0->getVertex(vi,vertex); + vertex = orgtrans0(vertex); + + btScalar distance = vertex.dot(plane) - plane[3] - margin; + + if(distance<0.0)//add contact + { + if(swapped) + { + addContactPoint(body1Wrap, body0Wrap, + vertex, + -plane, + distance); + } + else + { + addContactPoint(body0Wrap, body1Wrap, + vertex, + plane, + distance); + } + } + } + + shape0->unlockChildShapes(); +} + + + + +class btGImpactTriangleCallback: public btTriangleCallback +{ +public: + btGImpactCollisionAlgorithm * algorithm; + const btCollisionObjectWrapper * body0Wrap; + const btCollisionObjectWrapper * body1Wrap; + const btGImpactShapeInterface * gimpactshape0; + bool swapped; + btScalar margin; + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]); + tri1.setMargin(margin); + if(swapped) + { + algorithm->setPart0(partId); + algorithm->setFace0(triangleIndex); + } + else + { + algorithm->setPart1(partId); + algorithm->setFace1(triangleIndex); + } + + btCollisionObjectWrapper ob1Wrap(body1Wrap,&tri1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),partId,triangleIndex); + const btCollisionObjectWrapper * tmp = 0; + + if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject()) + { + tmp = algorithm->internalGetResultOut()->getBody0Wrap(); + algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap); + } else + { + tmp = algorithm->internalGetResultOut()->getBody1Wrap(); + algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap); + } + + algorithm->gimpact_vs_shape( + body0Wrap,&ob1Wrap,gimpactshape0,&tri1,swapped); + + if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject()) + { + algorithm->internalGetResultOut()->setBody0Wrap(tmp); + } else + { + algorithm->internalGetResultOut()->setBody1Wrap(tmp); + } + + } +}; + + + + +void btGImpactCollisionAlgorithm::gimpact_vs_concave( + const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactShapeInterface * shape0, + const btConcaveShape * shape1,bool swapped) +{ + //create the callback + btGImpactTriangleCallback tricallback; + tricallback.algorithm = this; + tricallback.body0Wrap = body0Wrap; + tricallback.body1Wrap = body1Wrap; + tricallback.gimpactshape0 = shape0; + tricallback.swapped = swapped; + tricallback.margin = shape1->getMargin(); + + //getting the trimesh AABB + btTransform gimpactInConcaveSpace; + + gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform(); + + btVector3 minAABB,maxAABB; + shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB); + + shape1->processAllTriangles(&tricallback,minAABB,maxAABB); + +} + + + +void btGImpactCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + clearCache(); + + m_resultOut = resultOut; + m_dispatchInfo = &dispatchInfo; + const btGImpactShapeInterface * gimpactshape0; + const btGImpactShapeInterface * gimpactshape1; + + if (body0Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE) + { + gimpactshape0 = static_cast(body0Wrap->getCollisionShape()); + + if( body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE ) + { + gimpactshape1 = static_cast(body1Wrap->getCollisionShape()); + + gimpact_vs_gimpact(body0Wrap,body1Wrap,gimpactshape0,gimpactshape1); + } + else + { + gimpact_vs_shape(body0Wrap,body1Wrap,gimpactshape0,body1Wrap->getCollisionShape(),false); + } + + } + else if (body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE ) + { + gimpactshape1 = static_cast(body1Wrap->getCollisionShape()); + + gimpact_vs_shape(body1Wrap,body0Wrap,gimpactshape1,body0Wrap->getCollisionShape(),true); + } +} + + +btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + return 1.f; + +} + +///////////////////////////////////// REGISTERING ALGORITHM ////////////////////////////////////////////// + + + +//! Use this function for register the algorithm externally +void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher) +{ + + static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf; + + int i; + + for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ ) + { + dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&s_gimpact_cf); + } + + for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ ) + { + dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&s_gimpact_cf); + } + +} diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h new file mode 100644 index 00000000..f85a94cb --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h @@ -0,0 +1,310 @@ +/*! \file btGImpactShape.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H +#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btGImpactShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + + +//! Collision Algorithm for GImpact Shapes +/*! +For register this algorithm in Bullet, proceed as following: + \code +btCollisionDispatcher * dispatcher = static_cast(m_dynamicsWorld ->getDispatcher()); +btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); + \endcode +*/ +class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm +{ +protected: + btCollisionAlgorithm * m_convex_algorithm; + btPersistentManifold * m_manifoldPtr; + btManifoldResult* m_resultOut; + const btDispatcherInfo * m_dispatchInfo; + int m_triface0; + int m_part0; + int m_triface1; + int m_part1; + + + //! Creates a new contact point + SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0,const btCollisionObject* body1) + { + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + return m_manifoldPtr; + } + + SIMD_FORCE_INLINE void destroyConvexAlgorithm() + { + if(m_convex_algorithm) + { + m_convex_algorithm->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm); + m_convex_algorithm = NULL; + } + } + + SIMD_FORCE_INLINE void destroyContactManifolds() + { + if(m_manifoldPtr == NULL) return; + m_dispatcher->releaseManifold(m_manifoldPtr); + m_manifoldPtr = NULL; + } + + SIMD_FORCE_INLINE void clearCache() + { + destroyContactManifolds(); + destroyConvexAlgorithm(); + + m_triface0 = -1; + m_part0 = -1; + m_triface1 = -1; + m_part1 = -1; + } + + SIMD_FORCE_INLINE btPersistentManifold* getLastManifold() + { + return m_manifoldPtr; + } + + + // Call before process collision + SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + if(getLastManifold() == 0) + { + newContactManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + } + + m_resultOut->setPersistentManifold(getLastManifold()); + } + + // Call before process collision + SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + checkManifold(body0Wrap,body1Wrap); + + btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm( + body0Wrap,body1Wrap,getLastManifold()); + return convex_algorithm ; + } + + // Call before process collision + SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + if(m_convex_algorithm) return; + m_convex_algorithm = newAlgorithm(body0Wrap,body1Wrap); + } + + + + + void addContactPoint(const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btVector3 & point, + const btVector3 & normal, + btScalar distance); + +//! Collision routines +//!@{ + + void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btGImpactMeshShapePart * shape0, + const btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count); + + void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btGImpactMeshShapePart * shape0, + const btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count); + + + + + void shape_vs_shape_collision( + const btCollisionObjectWrapper* body0, + const btCollisionObjectWrapper* body1, + const btCollisionShape * shape0, + const btCollisionShape * shape1); + + void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btCollisionShape* shape0, + const btCollisionShape* shape1); + + + + void gimpact_vs_gimpact_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + const btGImpactShapeInterface * shape0, + const btGImpactShapeInterface * shape1,btPairSet & pairset); + + void gimpact_vs_shape_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + const btGImpactShapeInterface * shape0, + const btCollisionShape * shape1, + btAlignedObjectArray & collided_primitives); + + + void gimpacttrimeshpart_vs_plane_collision( + const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactMeshShapePart * shape0, + const btStaticPlaneShape * shape1,bool swapped); + + +public: + + btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btGImpactCollisionAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr) + manifoldArray.push_back(m_manifoldPtr); + } + + btManifoldResult* internalGetResultOut() + { + return m_resultOut; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm)); + return new(mem) btGImpactCollisionAlgorithm(ci,body0Wrap,body1Wrap); + } + }; + + //! Use this function for register the algorithm externally + static void registerAlgorithm(btCollisionDispatcher * dispatcher); +#ifdef TRI_COLLISION_PROFILING + //! Gets the average time in miliseconds of tree collisions + static float getAverageTreeCollisionTime(); + + //! Gets the average time in miliseconds of triangle collisions + static float getAverageTriangleCollisionTime(); +#endif //TRI_COLLISION_PROFILING + + //! Collides two gimpact shapes + /*! + \pre shape0 and shape1 couldn't be btGImpactMeshShape objects + */ + + + void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactShapeInterface * shape0, + const btGImpactShapeInterface * shape1); + + void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap, + const btCollisionObjectWrapper* body1Wrap, + const btGImpactShapeInterface * shape0, + const btCollisionShape * shape1,bool swapped); + + void gimpact_vs_compoundshape(const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactShapeInterface * shape0, + const btCompoundShape * shape1,bool swapped); + + void gimpact_vs_concave( + const btCollisionObjectWrapper * body0Wrap, + const btCollisionObjectWrapper * body1Wrap, + const btGImpactShapeInterface * shape0, + const btConcaveShape * shape1,bool swapped); + + + + + /// Accessor/Mutator pairs for Part and triangleID + void setFace0(int value) + { + m_triface0 = value; + } + int getFace0() + { + return m_triface0; + } + void setFace1(int value) + { + m_triface1 = value; + } + int getFace1() + { + return m_triface1; + } + void setPart0(int value) + { + m_part0 = value; + } + int getPart0() + { + return m_part0; + } + void setPart1(int value) + { + m_part1 = value; + } + int getPart1() + { + return m_part1; + } + +}; + + +//algorithm details +//#define BULLET_TRIANGLE_COLLISION 1 +#define GIMPACT_VS_PLANE_COLLISION 1 + + + +#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/Code/Physics/src/BulletCollision/Gimpact/btGImpactMassUtil.h new file mode 100644 index 00000000..2543aefc --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactMassUtil.h @@ -0,0 +1,60 @@ +/*! \file btGImpactMassUtil.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 GIMPACT_MASS_UTIL_H +#define GIMPACT_MASS_UTIL_H + +#include "LinearMath/btTransform.h" + + + +SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed( + const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform) +{ + btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose(); + + btScalar x2 = transform.getOrigin()[0]; + x2*= x2; + btScalar y2 = transform.getOrigin()[1]; + y2*= y2; + btScalar z2 = transform.getOrigin()[2]; + z2*= z2; + + btScalar ix = rotatedTensor[0][0]*(y2+z2); + btScalar iy = rotatedTensor[1][1]*(x2+z2); + btScalar iz = rotatedTensor[2][2]*(x2+y2); + + return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz); +} + +SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass) +{ + btScalar x2 = point[0]*point[0]; + btScalar y2 = point[1]*point[1]; + btScalar z2 = point[2]*point[2]; + return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2)); +} + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp new file mode 100644 index 00000000..4528758c --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp @@ -0,0 +1,528 @@ +/*! \file gim_box_set.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 "btGImpactQuantizedBvh.h" +#include "LinearMath/btQuickprof.h" + +#ifdef TRI_COLLISION_PROFILING +btClock g_q_tree_clock; + + +float g_q_accum_tree_collision_time = 0; +int g_q_count_traversing = 0; + + +void bt_begin_gim02_q_tree_time() +{ + g_q_tree_clock.reset(); +} + +void bt_end_gim02_q_tree_time() +{ + g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds(); + g_q_count_traversing++; +} + + +//! Gets the average time in miliseconds of tree collisions +float btGImpactQuantizedBvh::getAverageTreeCollisionTime() +{ + if(g_q_count_traversing == 0) return 0; + + float avgtime = g_q_accum_tree_collision_time; + avgtime /= (float)g_q_count_traversing; + + g_q_accum_tree_collision_time = 0; + g_q_count_traversing = 0; + return avgtime; + +// float avgtime = g_q_count_traversing; +// g_q_count_traversing = 0; +// return avgtime; + +} + +#endif //TRI_COLLISION_PROFILING + +/////////////////////// btQuantizedBvhTree ///////////////////////////////// + +void btQuantizedBvhTree::calc_quantization( + GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin) +{ + //calc globa box + btAABB global_bound; + global_bound.invalidate(); + + for (int i=0;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + //swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); + + return splitIndex; + +} + + +void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +{ + int curIndex = m_num_nodes; + m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if ((endIndex-startIndex)==1) + { + //We have a leaf node + setNodeBound(curIndex,primitive_boxes[startIndex].m_bound); + m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data); + + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + //split axis + int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); + + splitIndex = _sort_and_calc_splitting_index( + primitive_boxes,startIndex,endIndex, + splitIndex//split axis + ); + + + //calc this node bounding box + + btAABB node_bound; + node_bound.invalidate(); + + for (int i=startIndex;iget_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //get left bound + btAABB bound; + bound.invalidate(); + + btAABB temp_box; + + int child_node = getLeftNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + child_node = getRightNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + setNodeBound(nodecount,bound); + } + } +} + +//! this rebuild the entire set +void btGImpactQuantizedBvh::buildSet() +{ + //obtain primitive boxes + GIM_BVH_DATA_ARRAY primitive_boxes; + primitive_boxes.resize(m_primitive_manager->get_primitive_count()); + + for (int i = 0;iget_primitive_box(i,primitive_boxes[i].m_bound); + primitive_boxes[i].m_data = i; + } + + m_box_tree.build_tree(primitive_boxes); +} + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + //quantize box + + unsigned short quantizedMin[3]; + unsigned short quantizedMax[3]; + + m_box_tree.quantizePoint(quantizedMin,box.m_min); + m_box_tree.quantizePoint(quantizedMax,box.m_max); + + + while (curIndex < numNodes) + { + + //catch bugs in tree data + + bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactQuantizedBvh::rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + +SIMD_FORCE_INLINE bool _quantized_node_collision( + const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0 ,int node1, bool complete_primitive_tests) +{ + btAABB box0; + boxset0->getNodeBound(node0,box0); + btAABB box1; + boxset1->getNodeBound(node1,box1); + + return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests ); +// box1.appy_transform_trans_cache(trans_cache_1to0); +// return box0.has_collision(box1); + +} + + +//stackless recursive collision routine +static void _find_quantized_collision_pairs_recursive( + const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1, + btPairSet * collision_pairs, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0, int node1, bool complete_primitive_tests) +{ + + + + if( _quantized_node_collision( + boxset0,boxset1,trans_cache_1to0, + node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes + + if(boxset0->isLeafNode(node0)) + { + if(boxset1->isLeafNode(node1)) + { + // collision result + collision_pairs->push_pair( + boxset0->getNodeData(node0),boxset1->getNodeData(node1)); + return; + } + else + { + + //collide left recursive + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getLeftNode(node1),false); + + //collide right recursive + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getRightNode(node1),false); + + + } + } + else + { + if(boxset1->isLeafNode(node1)) + { + + //collide left recursive + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),node1,false); + + + //collide right recursive + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),node1,false); + + + } + else + { + //collide left0 left1 + + + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false); + + //collide left0 right1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false); + + + //collide right0 left1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false); + + //collide right0 right1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getRightNode(node1),false); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf +} + + +void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh * boxset0, const btTransform & trans0, + const btGImpactQuantizedBvh * boxset1, const btTransform & trans1, + btPairSet & collision_pairs) +{ + + if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return; + + BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + + trans_cache_1to0.calc_from_homogenic(trans0,trans1); + +#ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_q_tree_time(); +#endif //TRI_COLLISION_PROFILING + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + &collision_pairs,trans_cache_1to0,0,0,true); +#ifdef TRI_COLLISION_PROFILING + bt_end_gim02_q_tree_time(); +#endif //TRI_COLLISION_PROFILING + +} + + diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h new file mode 100644 index 00000000..e6e52fff --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h @@ -0,0 +1,372 @@ +#ifndef GIM_QUANTIZED_SET_H_INCLUDED +#define GIM_QUANTIZED_SET_H_INCLUDED + +/*! \file btGImpactQuantizedBvh.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 "btGImpactBvh.h" +#include "btQuantization.h" + + + + + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE +{ + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrDataIndex; + + BT_QUANTIZED_BVH_NODE() + { + m_escapeIndexOrDataIndex = 0; + } + + SIMD_FORCE_INLINE bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrDataIndex>=0); + } + + SIMD_FORCE_INLINE int getEscapeIndex() const + { + //btAssert(m_escapeIndexOrDataIndex < 0); + return -m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setEscapeIndex(int index) + { + m_escapeIndexOrDataIndex = -index; + } + + SIMD_FORCE_INLINE int getDataIndex() const + { + //btAssert(m_escapeIndexOrDataIndex >= 0); + + return m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setDataIndex(int index) + { + m_escapeIndexOrDataIndex = index; + } + + SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( + unsigned short * quantizedMin,unsigned short * quantizedMax) const + { + if(m_quantizedAabbMin[0] > quantizedMax[0] || + m_quantizedAabbMax[0] < quantizedMin[0] || + m_quantizedAabbMin[1] > quantizedMax[1] || + m_quantizedAabbMax[1] < quantizedMin[1] || + m_quantizedAabbMin[2] > quantizedMax[2] || + m_quantizedAabbMax[2] < quantizedMin[2]) + { + return false; + } + return true; + } + +}; + + + +class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray +{ +}; + + + + +//! Basic Box tree structure +class btQuantizedBvhTree +{ +protected: + int m_num_nodes; + GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array; + btAABB m_global_bound; + btVector3 m_bvhQuantization; +protected: + void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) ); + + int _sort_and_calc_splitting_index( + GIM_BVH_DATA_ARRAY & primitive_boxes, + int startIndex, int endIndex, int splitAxis); + + int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + + void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); +public: + btQuantizedBvhTree() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes); + + SIMD_FORCE_INLINE void quantizePoint( + unsigned short * quantizedpoint, const btVector3 & point) const + { + bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization); + } + + + SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( + int node_index, + unsigned short * quantizedMin,unsigned short * quantizedMax) const + { + return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax); + } + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_node_array[nodeindex].isLeafNode(); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_node_array[nodeindex].getDataIndex(); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + bound.m_min = bt_unquantize( + m_node_array[nodeindex].m_quantizedAabbMin, + m_global_bound.m_min,m_bvhQuantization); + + bound.m_max = bt_unquantize( + m_node_array[nodeindex].m_quantizedAabbMax, + m_global_bound.m_min,m_bvhQuantization); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin, + bound.m_min, + m_global_bound.m_min, + m_global_bound.m_max, + m_bvhQuantization); + + bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax, + bound.m_max, + m_global_bound.m_min, + m_global_bound.m_max, + m_bvhQuantization); + } + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return nodeindex+1; + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; + return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_node_array[nodeindex].getEscapeIndex(); + } + + SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const + { + return &m_node_array[index]; + } + + //!@} +}; + + + +//! Structure for containing Boxes +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like btPrimitiveManagerBase ) +*/ +class btGImpactQuantizedBvh +{ +protected: + btQuantizedBvhTree m_box_tree; + btPrimitiveManagerBase * m_primitive_manager; + +protected: + //stackless refit + void refit(); +public: + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactQuantizedBvh() + { + m_primitive_manager = NULL; + } + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btAABB getGlobalBox() const + { + btAABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const + { + return m_primitive_manager; + } + + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + void buildSet(); + + //! returns the indices of the primitives in the m_primitive_manager + bool boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const; + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, + const btTransform & transform, btAlignedObjectArray & collided_results) const + { + btAABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const; + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager->is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return m_box_tree.getLeftNode(nodeindex); + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + return m_box_tree.getRightNode(nodeindex); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_box_tree.getEscapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const + { + m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); + } + + + SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const + { + return m_box_tree.get_node_pointer(index); + } + +#ifdef TRI_COLLISION_PROFILING + static float getAverageTreeCollisionTime(); +#endif //TRI_COLLISION_PROFILING + + static void find_collision(const btGImpactQuantizedBvh * boxset1, const btTransform & trans1, + const btGImpactQuantizedBvh * boxset2, const btTransform & trans2, + btPairSet & collision_pairs); +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.cpp b/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.cpp new file mode 100644 index 00000000..ac8efdf3 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.cpp @@ -0,0 +1,238 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 "btGImpactShape.h" +#include "btGImpactMassUtil.h" + + +#define CALC_EXACT_INERTIA 1 + + +void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + lockChildShapes(); +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getNumChildShapes(); + btScalar shapemass = mass/btScalar(i); + + while(i--) + { + btVector3 temp_inertia; + m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia); + if(childrenHasTransform()) + { + inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]); + } + else + { + inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity()); + } + + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif + unlockChildShapes(); +} + + + +void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + lockChildShapes(); + + +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getVertexCount(); + btScalar pointmass = mass/btScalar(i); + + while(i--) + { + btVector3 pointintertia; + this->getVertex(i,pointintertia); + pointintertia = gim_get_point_inertia(pointintertia,pointmass); + inertia+=pointintertia; + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif + + unlockChildShapes(); +} + +void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getMeshPartCount(); + btScalar partmass = mass/btScalar(i); + + while(i--) + { + btVector3 partinertia; + getMeshPart(i)->calculateLocalInertia(partmass,partinertia); + inertia+=partinertia; + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif +} + +void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const +{ +} + +void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const +{ + lockChildShapes(); + + btAlignedObjectArray collided; + btVector3 rayDir(rayTo - rayFrom); + rayDir.normalize(); + m_box_set.rayQuery(rayDir, rayFrom, collided); + + if(collided.size()==0) + { + unlockChildShapes(); + return; + } + + int part = (int)getPart(); + btPrimitiveTriangle triangle; + int i = collided.size(); + while(i--) + { + getPrimitiveTriangle(collided[i],triangle); + callback->processTriangle(triangle.m_vertices,part,collided[i]); + } + unlockChildShapes(); +} + +void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + lockChildShapes(); + btAABB box; + box.m_min = aabbMin; + box.m_max = aabbMax; + + btAlignedObjectArray collided; + m_box_set.boxQuery(box,collided); + + if(collided.size()==0) + { + unlockChildShapes(); + return; + } + + int part = (int)getPart(); + btPrimitiveTriangle triangle; + int i = collided.size(); + while(i--) + { + this->getPrimitiveTriangle(collided[i],triangle); + callback->processTriangle(triangle.m_vertices,part,collided[i]); + } + unlockChildShapes(); + +} + +void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax); + } +} + +void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const +{ + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo); + } +} + + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*) dataBuffer; + + btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer); + + m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer); + + trimeshData->m_collisionMargin = float(m_collisionMargin); + + localScaling.serializeFloat(trimeshData->m_localScaling); + + trimeshData->m_gimpactSubType = int(getGImpactShapeType()); + + return "btGImpactMeshShapeData"; +} + diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.h b/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.h new file mode 100644 index 00000000..3d1f48d4 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.h @@ -0,0 +1,1184 @@ +/*! \file btGImpactShape.h +\author Francisco Len Nßjera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 GIMPACT_SHAPE_H +#define GIMPACT_SHAPE_H + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAlignedObjectArray.h" + +#include "btGImpactQuantizedBvh.h" // box tree class + + +//! declare Quantized trees, (you can change to float based trees) +typedef btGImpactQuantizedBvh btGImpactBoxSet; + +enum eGIMPACT_SHAPE_TYPE +{ + CONST_GIMPACT_COMPOUND_SHAPE = 0, + CONST_GIMPACT_TRIMESH_SHAPE_PART, + CONST_GIMPACT_TRIMESH_SHAPE +}; + + + +//! Helper class for tetrahedrons +class btTetrahedronShapeEx:public btBU_Simplex1to4 +{ +public: + btTetrahedronShapeEx() + { + m_numVertices = 4; + } + + + SIMD_FORCE_INLINE void setVertices( + const btVector3 & v0,const btVector3 & v1, + const btVector3 & v2,const btVector3 & v3) + { + m_vertices[0] = v0; + m_vertices[1] = v1; + m_vertices[2] = v2; + m_vertices[3] = v3; + recalcLocalAabb(); + } +}; + + +//! Base class for gimpact shapes +class btGImpactShapeInterface : public btConcaveShape +{ +protected: + btAABB m_localAABB; + bool m_needs_update; + btVector3 localScaling; + btGImpactBoxSet m_box_set;// optionally boxset + + //! use this function for perfofm refit in bounding boxes + //! use this function for perfofm refit in bounding boxes + virtual void calcLocalAABB() + { + lockChildShapes(); + if(m_box_set.getNodeCount() == 0) + { + m_box_set.buildSet(); + } + else + { + m_box_set.update(); + } + unlockChildShapes(); + + m_localAABB = m_box_set.getGlobalBox(); + } + + +public: + btGImpactShapeInterface() + { + m_shapeType=GIMPACT_SHAPE_PROXYTYPE; + m_localAABB.invalidate(); + m_needs_update = true; + localScaling.setValue(1.f,1.f,1.f); + } + + + //! performs refit operation + /*! + Updates the entire Box set of this shape. + \pre postUpdate() must be called for attemps to calculating the box set, else this function + will does nothing. + \post if m_needs_update == true, then it calls calcLocalAABB(); + */ + SIMD_FORCE_INLINE void updateBound() + { + if(!m_needs_update) return; + calcLocalAABB(); + m_needs_update = false; + } + + //! If the Bounding box is not updated, then this class attemps to calculate it. + /*! + \post Calls updateBound() for update the box set. + */ + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAABB transformedbox = m_localAABB; + transformedbox.appy_transform(t); + aabbMin = transformedbox.m_min; + aabbMax = transformedbox.m_max; + } + + //! Tells to this object that is needed to refit the box set + virtual void postUpdate() + { + m_needs_update = true; + } + + //! Obtains the local box, which is the global calculated box of the total of subshapes + SIMD_FORCE_INLINE const btAABB & getLocalBox() + { + return m_localAABB; + } + + + virtual int getShapeType() const + { + return GIMPACT_SHAPE_PROXYTYPE; + } + + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setLocalScaling(const btVector3& scaling) + { + localScaling = scaling; + postUpdate(); + } + + virtual const btVector3& getLocalScaling() const + { + return localScaling; + } + + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + int i = getNumChildShapes(); + while(i--) + { + btCollisionShape* child = getChildShape(i); + child->setMargin(margin); + } + + m_needs_update = true; + } + + + //! Subshape member functions + //!@{ + + //! Base method for determinig which kind of GIMPACT shape we get + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ; + + //! gets boxset + SIMD_FORCE_INLINE const btGImpactBoxSet * getBoxSet() const + { + return &m_box_set; + } + + //! Determines if this class has a hierarchy structure for sorting its primitives + SIMD_FORCE_INLINE bool hasBoxSet() const + { + if(m_box_set.getNodeCount() == 0) return false; + return true; + } + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0; + + + //! Gets the number of children + virtual int getNumChildShapes() const = 0; + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const = 0; + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const = 0; + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const = 0; + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0; + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0; + + + + //! call when reading child shapes + virtual void lockChildShapes() const + { + } + + virtual void unlockChildShapes() const + { + } + + //! if this trimesh + SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const + { + getPrimitiveManager()->get_primitive_triangle(index,triangle); + } + + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAABB child_aabb; + getPrimitiveManager()->get_primitive_box(child_index,child_aabb); + child_aabb.appy_transform(t); + aabbMin = child_aabb.m_min; + aabbMax = child_aabb.m_max; + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) = 0; + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const = 0; + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const = 0; + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) = 0; + + //!@} + + + //! virtual method for ray collision + virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const + { + (void) rayFrom; (void) rayTo; (void) resultCallback; + } + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const + { + (void) callback; (void) aabbMin; (void) aabbMax; + } + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/,const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const + { + + } + + //!@} + +}; + + +//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once +/*! +This class only can manage Convex subshapes +*/ +class btGImpactCompoundShape : public btGImpactShapeInterface +{ +public: + //! compound primitive manager + class CompoundPrimitiveManager:public btPrimitiveManagerBase + { + public: + virtual ~CompoundPrimitiveManager() {} + btGImpactCompoundShape * m_compoundShape; + + + CompoundPrimitiveManager(const CompoundPrimitiveManager& compound) + : btPrimitiveManagerBase() + { + m_compoundShape = compound.m_compoundShape; + } + + CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape) + { + m_compoundShape = compoundShape; + } + + CompoundPrimitiveManager() + { + m_compoundShape = NULL; + } + + virtual bool is_trimesh() const + { + return false; + } + + virtual int get_primitive_count() const + { + return (int )m_compoundShape->getNumChildShapes(); + } + + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const + { + btTransform prim_trans; + if(m_compoundShape->childrenHasTransform()) + { + prim_trans = m_compoundShape->getChildTransform(prim_index); + } + else + { + prim_trans.setIdentity(); + } + const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index); + shape->getAabb(prim_trans,primbox.m_min,primbox.m_max); + } + + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const + { + btAssert(0); + (void) prim_index; (void) triangle; + } + + }; + + + +protected: + CompoundPrimitiveManager m_primitive_manager; + btAlignedObjectArray m_childTransforms; + btAlignedObjectArray m_childShapes; + + +public: + + btGImpactCompoundShape(bool children_has_transform = true) + { + (void) children_has_transform; + m_primitive_manager.m_compoundShape = this; + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + virtual ~btGImpactCompoundShape() + { + } + + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + if(m_childTransforms.size()==0) return false; + return true; + } + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + return &m_primitive_manager; + } + + //! Obtains the compopund primitive manager + SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager() + { + return &m_primitive_manager; + } + + //! Gets the number of children + virtual int getNumChildShapes() const + { + return m_childShapes.size(); + } + + + //! Use this method for adding children. Only Convex shapes are allowed. + void addChildShape(const btTransform& localTransform,btCollisionShape* shape) + { + btAssert(shape->isConvex()); + m_childTransforms.push_back(localTransform); + m_childShapes.push_back(shape); + } + + //! Use this method for adding children. Only Convex shapes are allowed. + void addChildShape(btCollisionShape* shape) + { + btAssert(shape->isConvex()); + m_childShapes.push_back(shape); + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + return m_childShapes[index]; + } + + //! Gets the children + virtual const btCollisionShape* getChildShape(int index) const + { + return m_childShapes[index]; + } + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + + if(childrenHasTransform()) + { + m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax); + } + else + { + m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax); + } + } + + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + btAssert(m_childTransforms.size() == m_childShapes.size()); + return m_childTransforms[index]; + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + btAssert(m_childTransforms.size() == m_childShapes.size()); + m_childTransforms[index] = transform; + postUpdate(); + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + return false; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + return false; + } + + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + (void) prim_index; (void) triangle; + btAssert(0); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + (void) prim_index; (void) tetrahedron; + btAssert(0); + } + + + //! Calculates the exact inertia tensor for this shape + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual const char* getName()const + { + return "GImpactCompound"; + } + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const + { + return CONST_GIMPACT_COMPOUND_SHAPE; + } + +}; + + + +//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface. +/*! +- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh +- When making operations with this shape, you must call lock before accessing to the trimesh primitives, and then call unlock +- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. + +*/ +class btGImpactMeshShapePart : public btGImpactShapeInterface +{ +public: + //! Trimesh primitive manager + /*! + Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism + */ + class TrimeshPrimitiveManager:public btPrimitiveManagerBase + { + public: + btScalar m_margin; + btStridingMeshInterface * m_meshInterface; + btVector3 m_scale; + int m_part; + int m_lock_count; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + TrimeshPrimitiveManager() + { + m_meshInterface = NULL; + m_part = 0; + m_margin = 0.01f; + m_scale = btVector3(1.f,1.f,1.f); + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + } + + TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager) + : btPrimitiveManagerBase() + { + m_meshInterface = manager.m_meshInterface; + m_part = manager.m_part; + m_margin = manager.m_margin; + m_scale = manager.m_scale; + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + + } + + TrimeshPrimitiveManager( + btStridingMeshInterface * meshInterface, int part) + { + m_meshInterface = meshInterface; + m_part = part; + m_scale = m_meshInterface->getScaling(); + m_margin = 0.1f; + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + + } + + virtual ~TrimeshPrimitiveManager() {} + + void lock() + { + if(m_lock_count>0) + { + m_lock_count++; + return; + } + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase,numverts, + type, stride,&indexbase, indexstride, numfaces,indicestype,m_part); + + m_lock_count = 1; + } + + void unlock() + { + if(m_lock_count == 0) return; + if(m_lock_count>1) + { + --m_lock_count; + return; + } + m_meshInterface->unLockReadOnlyVertexBase(m_part); + vertexbase = NULL; + m_lock_count = 0; + } + + virtual bool is_trimesh() const + { + return true; + } + + virtual int get_primitive_count() const + { + return (int )numfaces; + } + + SIMD_FORCE_INLINE int get_vertex_count() const + { + return (int )numverts; + } + + SIMD_FORCE_INLINE void get_indices(int face_index,unsigned int &i0,unsigned int &i1,unsigned int &i2) const + { + if(indicestype == PHY_SHORT) + { + unsigned short* s_indices = (unsigned short *)(indexbase + face_index * indexstride); + i0 = s_indices[0]; + i1 = s_indices[1]; + i2 = s_indices[2]; + } + else + { + unsigned int * i_indices = (unsigned int *)(indexbase + face_index*indexstride); + i0 = i_indices[0]; + i1 = i_indices[1]; + i2 = i_indices[2]; + } + } + + SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3 & vertex) const + { + if(type == PHY_DOUBLE) + { + double * dvertices = (double *)(vertexbase + vertex_index*stride); + vertex[0] = btScalar(dvertices[0]*m_scale[0]); + vertex[1] = btScalar(dvertices[1]*m_scale[1]); + vertex[2] = btScalar(dvertices[2]*m_scale[2]); + } + else + { + float * svertices = (float *)(vertexbase + vertex_index*stride); + vertex[0] = svertices[0]*m_scale[0]; + vertex[1] = svertices[1]*m_scale[1]; + vertex[2] = svertices[2]*m_scale[2]; + } + } + + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const + { + btPrimitiveTriangle triangle; + get_primitive_triangle(prim_index,triangle); + primbox.calc_from_triangle_margin( + triangle.m_vertices[0], + triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin); + } + + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const + { + unsigned int indices[3]; + get_indices(prim_index,indices[0],indices[1],indices[2]); + get_vertex(indices[0],triangle.m_vertices[0]); + get_vertex(indices[1],triangle.m_vertices[1]); + get_vertex(indices[2],triangle.m_vertices[2]); + triangle.m_margin = m_margin; + } + + SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const + { + unsigned int indices[3]; + get_indices(prim_index,indices[0],indices[1],indices[2]); + get_vertex(indices[0],triangle.m_vertices1[0]); + get_vertex(indices[1],triangle.m_vertices1[1]); + get_vertex(indices[2],triangle.m_vertices1[2]); + triangle.setMargin(m_margin); + } + + }; + + +protected: + TrimeshPrimitiveManager m_primitive_manager; +public: + + btGImpactMeshShapePart() + { + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + + btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part) + { + m_primitive_manager.m_meshInterface = meshInterface; + m_primitive_manager.m_part = part; + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + virtual ~btGImpactMeshShapePart() + { + } + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + return false; + } + + + //! call when reading child shapes + virtual void lockChildShapes() const + { + void * dummy = (void*)(m_box_set.getPrimitiveManager()); + TrimeshPrimitiveManager * dummymanager = static_cast(dummy); + dummymanager->lock(); + } + + virtual void unlockChildShapes() const + { + void * dummy = (void*)(m_box_set.getPrimitiveManager()); + TrimeshPrimitiveManager * dummymanager = static_cast(dummy); + dummymanager->unlock(); + } + + //! Gets the number of children + virtual int getNumChildShapes() const + { + return m_primitive_manager.get_primitive_count(); + } + + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + (void) index; + btAssert(0); + return NULL; + } + + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const + { + (void) index; + btAssert(0); + return NULL; + } + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + (void) index; + btAssert(0); + return btTransform(); + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + (void) index; + (void) transform; + btAssert(0); + } + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + return &m_primitive_manager; + } + + SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager() + { + return &m_primitive_manager; + } + + + + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + + + virtual const char* getName()const + { + return "GImpactMeshShapePart"; + } + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const + { + return CONST_GIMPACT_TRIMESH_SHAPE_PART; + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + return true; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + return false; + } + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + m_primitive_manager.get_bullet_triangle(prim_index,triangle); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + (void) prim_index; + (void) tetrahedron; + btAssert(0); + } + + + + SIMD_FORCE_INLINE int getVertexCount() const + { + return m_primitive_manager.get_vertex_count(); + } + + SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const + { + m_primitive_manager.get_vertex(vertex_index,vertex); + } + + SIMD_FORCE_INLINE void setMargin(btScalar margin) + { + m_primitive_manager.m_margin = margin; + postUpdate(); + } + + SIMD_FORCE_INLINE btScalar getMargin() const + { + return m_primitive_manager.m_margin; + } + + virtual void setLocalScaling(const btVector3& scaling) + { + m_primitive_manager.m_scale = scaling; + postUpdate(); + } + + virtual const btVector3& getLocalScaling() const + { + return m_primitive_manager.m_scale; + } + + SIMD_FORCE_INLINE int getPart() const + { + return (int)m_primitive_manager.m_part; + } + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + virtual void processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const; +}; + + +//! This class manages a mesh supplied by the btStridingMeshInterface interface. +/*! +Set of btGImpactMeshShapePart parts +- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh + +- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. + +*/ +class btGImpactMeshShape : public btGImpactShapeInterface +{ + btStridingMeshInterface* m_meshInterface; + +protected: + btAlignedObjectArray m_mesh_parts; + void buildMeshParts(btStridingMeshInterface * meshInterface) + { + for (int i=0;igetNumSubParts() ;++i ) + { + btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i); + m_mesh_parts.push_back(newpart); + } + } + + //! use this function for perfofm refit in bounding boxes + virtual void calcLocalAABB() + { + m_localAABB.invalidate(); + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->updateBound(); + m_localAABB.merge(m_mesh_parts[i]->getLocalBox()); + } + } + +public: + btGImpactMeshShape(btStridingMeshInterface * meshInterface) + { + m_meshInterface = meshInterface; + buildMeshParts(meshInterface); + } + + virtual ~btGImpactMeshShape() + { + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + delete part; + } + m_mesh_parts.clear(); + } + + + btStridingMeshInterface* getMeshInterface() + { + return m_meshInterface; + } + + const btStridingMeshInterface* getMeshInterface() const + { + return m_meshInterface; + } + + int getMeshPartCount() const + { + return m_mesh_parts.size(); + } + + btGImpactMeshShapePart * getMeshPart(int index) + { + return m_mesh_parts[index]; + } + + + + const btGImpactMeshShapePart * getMeshPart(int index) const + { + return m_mesh_parts[index]; + } + + + virtual void setLocalScaling(const btVector3& scaling) + { + localScaling = scaling; + + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->setLocalScaling(scaling); + } + + m_needs_update = true; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->setMargin(margin); + } + + m_needs_update = true; + } + + //! Tells to this object that is needed to refit all the meshes + virtual void postUpdate() + { + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->postUpdate(); + } + + m_needs_update = true; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + btAssert(0); + return NULL; + } + + + //! Gets the number of children + virtual int getNumChildShapes() const + { + btAssert(0); + return 0; + } + + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + btAssert(0); + return false; + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + btAssert(0); + return false; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + btAssert(0); + return false; + } + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + (void) prim_index; (void) triangle; + btAssert(0); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + (void) prim_index; (void) tetrahedron; + btAssert(0); + } + + //! call when reading child shapes + virtual void lockChildShapes() const + { + btAssert(0); + } + + virtual void unlockChildShapes() const + { + btAssert(0); + } + + + + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + (void) child_index; (void) t; (void) aabbMin; (void) aabbMax; + btAssert(0); + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + (void) index; + btAssert(0); + return NULL; + } + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const + { + (void) index; + btAssert(0); + return NULL; + } + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + (void) index; + btAssert(0); + return btTransform(); + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + (void) index; (void) transform; + btAssert(0); + } + + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const + { + return CONST_GIMPACT_TRIMESH_SHAPE; + } + + + virtual const char* getName()const + { + return "GImpactMesh"; + } + + virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const; + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void processAllTrianglesRay (btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btGImpactMeshShapeData +{ + btCollisionShapeData m_collisionShapeData; + + btStridingMeshInterfaceData m_meshInterface; + + btVector3FloatData m_localScaling; + + float m_collisionMargin; + + int m_gimpactSubType; +}; + +SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const +{ + return sizeof(btGImpactMeshShapeData); +} + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp new file mode 100644 index 00000000..5d07d1ad --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp @@ -0,0 +1,283 @@ +/*! \file btGenericPoolAllocator.cpp +\author Francisco Leon Najera. email projectileman@yahoo.com + +General purpose allocator class +*/ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btGenericPoolAllocator.h" + + + +/// *************** btGenericMemoryPool ******************/////////// + +size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements) +{ + size_t ptr = BT_UINT_MAX; + + if(m_free_nodes_count == 0) return BT_UINT_MAX; + // find an avaliable free node with the correct size + size_t revindex = m_free_nodes_count; + + while(revindex-- && ptr == BT_UINT_MAX) + { + if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements) + { + ptr = revindex; + } + } + if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found + + + revindex = ptr; + ptr = m_free_nodes[revindex]; + // post: ptr contains the node index, and revindex the index in m_free_nodes + + size_t finalsize = m_allocated_sizes[ptr]; + finalsize -= num_elements; + + m_allocated_sizes[ptr] = num_elements; + + // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size + + if(finalsize>0) // preserve free node, there are some free memory + { + m_free_nodes[revindex] = ptr + num_elements; + m_allocated_sizes[ptr + num_elements] = finalsize; + } + else // delete free node + { + // swap with end + m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1]; + m_free_nodes_count--; + } + + return ptr; +} + +size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements) +{ + if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX; + + size_t ptr = m_allocated_count; + + m_allocated_sizes[m_allocated_count] = num_elements; + m_allocated_count+=num_elements; + + return ptr; +} + + +void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count) +{ + m_allocated_count = 0; + m_free_nodes_count = 0; + + m_element_size = element_size; + m_max_element_count = element_count; + + + + + m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16); + m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16); + m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16); + + for (size_t i = 0;i< m_max_element_count;i++ ) + { + m_allocated_sizes[i] = 0; + } +} + +void btGenericMemoryPool::end_pool() +{ + btAlignedFree(m_pool); + btAlignedFree(m_free_nodes); + btAlignedFree(m_allocated_sizes); + m_allocated_count = 0; + m_free_nodes_count = 0; +} + + +//! Allocates memory in pool +/*! +\param size_bytes size in bytes of the buffer +*/ +void * btGenericMemoryPool::allocate(size_t size_bytes) +{ + + size_t module = size_bytes%m_element_size; + size_t element_count = size_bytes/m_element_size; + if(module>0) element_count++; + + size_t alloc_pos = allocate_from_free_nodes(element_count); + // a free node is found + if(alloc_pos != BT_UINT_MAX) + { + return get_element_data(alloc_pos); + } + // allocate directly on pool + alloc_pos = allocate_from_pool(element_count); + + if(alloc_pos == BT_UINT_MAX) return NULL; // not space + return get_element_data(alloc_pos); +} + +bool btGenericMemoryPool::freeMemory(void * pointer) +{ + unsigned char * pointer_pos = (unsigned char *)pointer; + unsigned char * pool_pos = (unsigned char *)m_pool; + // calc offset + if(pointer_pos=get_pool_capacity()) return false;// far away + + // find free position + m_free_nodes[m_free_nodes_count] = offset/m_element_size; + m_free_nodes_count++; + return true; +} + + +/// *******************! btGenericPoolAllocator *******************!/// + + +btGenericPoolAllocator::~btGenericPoolAllocator() +{ + // destroy pools + size_t i; + for (i=0;iend_pool(); + btAlignedFree(m_pools[i]); + } +} + + +// creates a pool +btGenericMemoryPool * btGenericPoolAllocator::push_new_pool() +{ + if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL; + + btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16); + + m_pools[m_pool_count] = newptr; + + m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count); + + m_pool_count++; + return newptr; +} + +void * btGenericPoolAllocator::failback_alloc(size_t size_bytes) +{ + + btGenericMemoryPool * pool = NULL; + + + if(size_bytes<=get_pool_capacity()) + { + pool = push_new_pool(); + } + + if(pool==NULL) // failback + { + return btAlignedAlloc(size_bytes,16); + } + + return pool->allocate(size_bytes); +} + +bool btGenericPoolAllocator::failback_free(void * pointer) +{ + btAlignedFree(pointer); + return true; +} + + +//! Allocates memory in pool +/*! +\param size_bytes size in bytes of the buffer +*/ +void * btGenericPoolAllocator::allocate(size_t size_bytes) +{ + void * ptr = NULL; + + size_t i = 0; + while(iallocate(size_bytes); + ++i; + } + + if(ptr) return ptr; + + return failback_alloc(size_bytes); +} + +bool btGenericPoolAllocator::freeMemory(void * pointer) +{ + bool result = false; + + size_t i = 0; + while(ifreeMemory(pointer); + ++i; + } + + if(result) return true; + + return failback_free(pointer); +} + +/// ************** STANDARD ALLOCATOR ***************************/// + + +#define BT_DEFAULT_POOL_SIZE 32768 +#define BT_DEFAULT_POOL_ELEMENT_SIZE 8 + +// main allocator +class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator +{ +public: + GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE) + { + } +}; + +// global allocator +GIM_STANDARD_ALLOCATOR g_main_allocator; + + +void * btPoolAlloc(size_t size) +{ + return g_main_allocator.allocate(size); +} + +void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize) +{ + void * newptr = btPoolAlloc(newsize); + size_t copysize = oldsize +#include +#include +#include "LinearMath/btAlignedAllocator.h" + +#define BT_UINT_MAX UINT_MAX +#define BT_DEFAULT_MAX_POOLS 16 + + +//! Generic Pool class +class btGenericMemoryPool +{ +public: + unsigned char * m_pool; //[m_element_size*m_max_element_count]; + size_t * m_free_nodes; //[m_max_element_count];//! free nodes + size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node + size_t m_allocated_count; + size_t m_free_nodes_count; +protected: + size_t m_element_size; + size_t m_max_element_count; + + size_t allocate_from_free_nodes(size_t num_elements); + size_t allocate_from_pool(size_t num_elements); + +public: + + void init_pool(size_t element_size, size_t element_count); + + void end_pool(); + + + btGenericMemoryPool(size_t element_size, size_t element_count) + { + init_pool(element_size, element_count); + } + + ~btGenericMemoryPool() + { + end_pool(); + } + + + inline size_t get_pool_capacity() + { + return m_element_size*m_max_element_count; + } + + inline size_t gem_element_size() + { + return m_element_size; + } + + inline size_t get_max_element_count() + { + return m_max_element_count; + } + + inline size_t get_allocated_count() + { + return m_allocated_count; + } + + inline size_t get_free_positions_count() + { + return m_free_nodes_count; + } + + inline void * get_element_data(size_t element_index) + { + return &m_pool[element_index*m_element_size]; + } + + //! Allocates memory in pool + /*! + \param size_bytes size in bytes of the buffer + */ + void * allocate(size_t size_bytes); + + bool freeMemory(void * pointer); +}; + + + + +//! Generic Allocator with pools +/*! +General purpose Allocator which can create Memory Pools dynamiacally as needed. +*/ +class btGenericPoolAllocator +{ +protected: + size_t m_pool_element_size; + size_t m_pool_element_count; +public: + btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS]; + size_t m_pool_count; + + + inline size_t get_pool_capacity() + { + return m_pool_element_size*m_pool_element_count; + } + + +protected: + // creates a pool + btGenericMemoryPool * push_new_pool(); + + void * failback_alloc(size_t size_bytes); + + bool failback_free(void * pointer); +public: + + btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count) + { + m_pool_count = 0; + m_pool_element_size = pool_element_size; + m_pool_element_count = pool_element_count; + } + + virtual ~btGenericPoolAllocator(); + + //! Allocates memory in pool + /*! + \param size_bytes size in bytes of the buffer + */ + void * allocate(size_t size_bytes); + + bool freeMemory(void * pointer); +}; + + + +void * btPoolAlloc(size_t size); +void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize); +void btPoolFree(void *ptr); + + +#endif diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGeometryOperations.h b/Code/Physics/src/BulletCollision/Gimpact/btGeometryOperations.h new file mode 100644 index 00000000..60f06510 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btGeometryOperations.h @@ -0,0 +1,212 @@ +#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED +#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED + +/*! \file btGeometryOperations.h +*\author Francisco Leon Najera + +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 "btBoxCollision.h" + + + + + +#define PLANEDIREPSILON 0.0000001f +#define PARALELENORMALS 0.000001f + + +#define BT_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) + +/// Calc a plane from a triangle edge an a normal. plane is a vec4f +SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane) +{ + btVector3 planenormal = (e2-e1).cross(normal); + planenormal.normalize(); + plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal)); +} + + + +//***************** SEGMENT and LINE FUNCTIONS **********************************/// + +/*! Finds the closest point(cp) to (v) on a segment (e1,e2) + */ +SIMD_FORCE_INLINE void bt_closest_point_on_segment( + btVector3 & cp, const btVector3 & v, + const btVector3 &e1,const btVector3 &e2) +{ + btVector3 n = e2-e1; + cp = v - e1; + btScalar _scalar = cp.dot(n)/n.dot(n); + if(_scalar <0.0f) + { + cp = e1; + } + else if(_scalar >1.0f) + { + cp = e2; + } + else + { + cp = _scalar*n + e1; + } +} + + +//! line plane collision +/*! +*\return + -0 if the ray never intersects + -1 if the ray collides in front + -2 if the ray collides in back +*/ + +SIMD_FORCE_INLINE int bt_line_plane_collision( + const btVector4 & plane, + const btVector3 & vDir, + const btVector3 & vPoint, + btVector3 & pout, + btScalar &tparam, + btScalar tmin, btScalar tmax) +{ + + btScalar _dotdir = vDir.dot(plane); + + if(btFabs(_dotdir)tmax) + { + returnvalue = 0; + tparam = tmax; + } + pout = tparam*vDir + vPoint; + return returnvalue; +} + + +//! Find closest points on segments +SIMD_FORCE_INLINE void bt_segment_collision( + const btVector3 & vA1, + const btVector3 & vA2, + const btVector3 & vB1, + const btVector3 & vB2, + btVector3 & vPointA, + btVector3 & vPointB) +{ + btVector3 AD = vA2 - vA1; + btVector3 BD = vB2 - vB1; + btVector3 N = AD.cross(BD); + btScalar tp = N.length2(); + + btVector4 _M;//plane + + if(tp_M[1]) + { + invert_b_order = true; + BT_SWAP_NUMBERS(_M[0],_M[1]); + } + _M[2] = vA1.dot(AD); + _M[3] = vA2.dot(AD); + //mid points + N[0] = (_M[0]+_M[1])*0.5f; + N[1] = (_M[2]+_M[3])*0.5f; + + if(N[0]=0.0f) + { + if (_dist>m_penetration_depth) + { + m_penetration_depth = _dist; + point_indices[0] = _k; + m_point_count=1; + } + else if ((_dist+SIMD_EPSILON)>=m_penetration_depth) + { + point_indices[m_point_count] = _k; + m_point_count++; + } + } + } + + for ( _k=0;_k0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + // classify points on this triangle + dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin; + + dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin; + + dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin; + + if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + return true; +} + +int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points ) +{ + // edge 0 + + btVector3 temp_points[MAX_TRI_CLIPPING]; + + + btVector4 edgeplane; + + get_edge_plane(0,edgeplane); + + + int clipped_count = bt_plane_clip_triangle( + edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points); + + if (clipped_count == 0) return 0; + + btVector3 temp_points1[MAX_TRI_CLIPPING]; + + + // edge 1 + get_edge_plane(1,edgeplane); + + + clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1); + + if (clipped_count == 0) return 0; + + // edge 2 + get_edge_plane(2,edgeplane); + + clipped_count = bt_plane_clip_polygon( + edgeplane,temp_points1,clipped_count,clipped_points); + + return clipped_count; +} + +bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts) +{ + btScalar margin = m_margin + other.m_margin; + + btVector3 clipped_points[MAX_TRI_CLIPPING]; + int clipped_count; + //create planes + // plane v vs U points + + GIM_TRIANGLE_CONTACT contacts1; + + contacts1.m_separating_normal = m_plane; + + + clipped_count = clip_triangle(other,clipped_points); + + if (clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); + if (contacts1.m_point_count == 0) return false; // too far + //Normal pointing to this triangle + contacts1.m_separating_normal *= -1.f; + + + //Clip tri1 by tri2 edges + GIM_TRIANGLE_CONTACT contacts2; + contacts2.m_separating_normal = other.m_plane; + + clipped_count = other.clip_triangle(*this,clipped_points); + + if (clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); + if (contacts2.m_point_count == 0) return false; // too far + + + + + ////check most dir for contacts + if (contacts2.m_penetration_depth0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + // classify points on this triangle + dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin; + + dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin; + + dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin; + + if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + return true; +} + + diff --git a/Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.h new file mode 100644 index 00000000..973c2ed1 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.h @@ -0,0 +1,180 @@ +/*! \file btGImpactShape.h +\author Francisco Leon Najera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.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 GIMPACT_TRIANGLE_SHAPE_EX_H +#define GIMPACT_TRIANGLE_SHAPE_EX_H + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "btBoxCollision.h" +#include "btClipPolygon.h" +#include "btGeometryOperations.h" + + +#define MAX_TRI_CLIPPING 16 + +//! Structure for collision +struct GIM_TRIANGLE_CONTACT +{ + btScalar m_penetration_depth; + int m_point_count; + btVector4 m_separating_normal; + btVector3 m_points[MAX_TRI_CLIPPING]; + + SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other) + { + m_penetration_depth = other.m_penetration_depth; + m_separating_normal = other.m_separating_normal; + m_point_count = other.m_point_count; + int i = m_point_count; + while(i--) + { + m_points[i] = other.m_points[i]; + } + } + + GIM_TRIANGLE_CONTACT() + { + } + + GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other) + { + copy_from(other); + } + + //! classify points that are closer + void merge_points(const btVector4 & plane, + btScalar margin, const btVector3 * points, int point_count); + +}; + + + +class btPrimitiveTriangle +{ +public: + btVector3 m_vertices[3]; + btVector4 m_plane; + btScalar m_margin; + btScalar m_dummy; + btPrimitiveTriangle():m_margin(0.01f) + { + + } + + + SIMD_FORCE_INLINE void buildTriPlane() + { + btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]); + normal.normalize(); + m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal)); + } + + //! Test if triangles could collide + bool overlap_test_conservative(const btPrimitiveTriangle& other); + + //! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane + /*! + \pre this triangle must have its plane calculated. + */ + SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const + { + const btVector3 & e0 = m_vertices[edge_index]; + const btVector3 & e1 = m_vertices[(edge_index+1)%3]; + bt_edge_plane(e0,e1,m_plane,plane); + } + + void applyTransform(const btTransform& t) + { + m_vertices[0] = t(m_vertices[0]); + m_vertices[1] = t(m_vertices[1]); + m_vertices[2] = t(m_vertices[2]); + } + + //! Clips the triangle against this + /*! + \pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated. + \return the number of clipped points + */ + int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points ); + + //! Find collision using the clipping method + /*! + \pre this triangle and other must have their triangles calculated + */ + bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts); +}; + + + +//! Helper class for colliding Bullet Triangle Shapes +/*! +This class implements a better getAabb method than the previous btTriangleShape class +*/ +class btTriangleShapeEx: public btTriangleShape +{ +public: + + btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0)) + { + } + + btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2) + { + } + + btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2]) + { + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const + { + btVector3 tv0 = t(m_vertices1[0]); + btVector3 tv1 = t(m_vertices1[1]); + btVector3 tv2 = t(m_vertices1[2]); + + btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin); + aabbMin = trianglebox.m_min; + aabbMax = trianglebox.m_max; + } + + void applyTransform(const btTransform& t) + { + m_vertices1[0] = t(m_vertices1[0]); + m_vertices1[1] = t(m_vertices1[1]); + m_vertices1[2] = t(m_vertices1[2]); + } + + SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const + { + btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]); + normal.normalize(); + plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal)); + } + + bool overlap_test_conservative(const btTriangleShapeEx& other); +}; + + +#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_array.h b/Code/Physics/src/BulletCollision/Gimpact/gim_array.h new file mode 100644 index 00000000..27e6f32f --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_array.h @@ -0,0 +1,324 @@ +#ifndef GIM_ARRAY_H_INCLUDED +#define GIM_ARRAY_H_INCLUDED +/*! \file gim_array.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_memory.h" + + +#define GIM_ARRAY_GROW_INCREMENT 2 +#define GIM_ARRAY_GROW_FACTOR 2 + +//! Very simple array container with fast access and simd memory +template +class gim_array +{ +public: +//! properties +//!@{ + T *m_data; + GUINT m_size; + GUINT m_allocated_size; +//!@} +//! protected operations +//!@{ + + inline void destroyData() + { + m_allocated_size = 0; + if(m_data==NULL) return; + gim_free(m_data); + m_data = NULL; + } + + inline bool resizeData(GUINT newsize) + { + if(newsize==0) + { + destroyData(); + return true; + } + + if(m_size>0) + { + m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T)); + } + else + { + m_data = (T*)gim_alloc(newsize*sizeof(T)); + } + m_allocated_size = newsize; + return true; + } + + inline bool growingCheck() + { + if(m_allocated_size<=m_size) + { + GUINT requestsize = m_size; + m_size = m_allocated_size; + if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false; + } + return true; + } + +//!@} +//! public operations +//!@{ + inline bool reserve(GUINT size) + { + if(m_allocated_size>=size) return false; + return resizeData(size); + } + + inline void clear_range(GUINT start_range) + { + while(m_size>start_range) + { + m_data[--m_size].~T(); + } + } + + inline void clear() + { + if(m_size==0)return; + clear_range(0); + } + + inline void clear_memory() + { + clear(); + destroyData(); + } + + gim_array() + { + m_data = 0; + m_size = 0; + m_allocated_size = 0; + } + + gim_array(GUINT reservesize) + { + m_data = 0; + m_size = 0; + + m_allocated_size = 0; + reserve(reservesize); + } + + ~gim_array() + { + clear_memory(); + } + + inline GUINT size() const + { + return m_size; + } + + inline GUINT max_size() const + { + return m_allocated_size; + } + + inline T & operator[](size_t i) + { + return m_data[i]; + } + inline const T & operator[](size_t i) const + { + return m_data[i]; + } + + inline T * pointer(){ return m_data;} + inline const T * pointer() const + { return m_data;} + + + inline T * get_pointer_at(GUINT i) + { + return m_data + i; + } + + inline const T * get_pointer_at(GUINT i) const + { + return m_data + i; + } + + inline T & at(GUINT i) + { + return m_data[i]; + } + + inline const T & at(GUINT i) const + { + return m_data[i]; + } + + inline T & front() + { + return *m_data; + } + + inline const T & front() const + { + return *m_data; + } + + inline T & back() + { + return m_data[m_size-1]; + } + + inline const T & back() const + { + return m_data[m_size-1]; + } + + + inline void swap(GUINT i, GUINT j) + { + gim_swap_elements(m_data,i,j); + } + + inline void push_back(const T & obj) + { + this->growingCheck(); + m_data[m_size] = obj; + m_size++; + } + + //!Simply increase the m_size, doesn't call the new element constructor + inline void push_back_mem() + { + this->growingCheck(); + m_size++; + } + + inline void push_back_memcpy(const T & obj) + { + this->growingCheck(); + irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T)); + m_size++; + } + + inline void pop_back() + { + m_size--; + m_data[m_size].~T(); + } + + //!Simply decrease the m_size, doesn't call the deleted element destructor + inline void pop_back_mem() + { + m_size--; + } + + //! fast erase + inline void erase(GUINT index) + { + if(indexgrowingCheck(); + for(GUINT i = m_size;i>index;i--) + { + gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T)); + } + m_size++; + } + + inline void insert(const T & obj,GUINT index) + { + insert_mem(index); + m_data[index] = obj; + } + + inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T()) + { + if(size>m_size) + { + reserve(size); + if(call_constructor) + { + while(m_size +SIMD_FORCE_INLINE bool POINT_IN_HULL( + const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count) +{ + GREAL _dis; + for (GUINT _i = 0;_i< plane_count;++_i) + { + _dis = DISTANCE_PLANE_POINT(planes[_i],point); + if(_dis>0.0f) return false; + } + return true; +} + +template +SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT( + const CLASS_POINT& s1, + const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped) +{ + GREAL _dis1,_dis2; + _dis1 = DISTANCE_PLANE_POINT(plane,s1); + VEC_DIFF(clipped,s2,s1); + _dis2 = VEC_DOT(clipped,plane); + VEC_SCALE(clipped,-_dis1/_dis2,clipped); + VEC_SUM(clipped,clipped,s1); +} + +enum ePLANE_INTERSECTION_TYPE +{ + G_BACK_PLANE = 0, + G_COLLIDE_PLANE, + G_FRONT_PLANE +}; + +enum eLINE_PLANE_INTERSECTION_TYPE +{ + G_FRONT_PLANE_S1 = 0, + G_FRONT_PLANE_S2, + G_BACK_PLANE_S1, + G_BACK_PLANE_S2, + G_COLLIDE_PLANE_S1, + G_COLLIDE_PLANE_S2 +}; + +//! Confirms if the plane intersect the edge or nor +/*! +intersection type must have the following values +
    +
  • 0 : Segment in front of plane, s1 closest +
  • 1 : Segment in front of plane, s2 closest +
  • 2 : Segment in back of plane, s1 closest +
  • 3 : Segment in back of plane, s2 closest +
  • 4 : Segment collides plane, s1 in back +
  • 5 : Segment collides plane, s2 in back +
+*/ + +template +SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2( + const CLASS_POINT& s1, + const CLASS_POINT &s2, + const CLASS_PLANE &plane,CLASS_POINT &clipped) +{ + GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1); + GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2); + if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON) + { + if(_dis1<_dis2) return G_FRONT_PLANE_S1; + return G_FRONT_PLANE_S2; + } + else if(_dis1 _dis2) return G_BACK_PLANE_S1; + return G_BACK_PLANE_S2; + } + + VEC_DIFF(clipped,s2,s1); + _dis2 = VEC_DOT(clipped,plane); + VEC_SCALE(clipped,-_dis1/_dis2,clipped); + VEC_SUM(clipped,clipped,s1); + if(_dis1<_dis2) return G_COLLIDE_PLANE_S1; + return G_COLLIDE_PLANE_S2; +} + +//! Confirms if the plane intersect the edge or not +/*! +clipped1 and clipped2 are the vertices behind the plane. +clipped1 is the closest + +intersection_type must have the following values +
    +
  • 0 : Segment in front of plane, s1 closest +
  • 1 : Segment in front of plane, s2 closest +
  • 2 : Segment in back of plane, s1 closest +
  • 3 : Segment in back of plane, s2 closest +
  • 4 : Segment collides plane, s1 in back +
  • 5 : Segment collides plane, s2 in back +
+*/ +template +SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST( + const CLASS_POINT& s1, + const CLASS_POINT &s2, + const CLASS_PLANE &plane, + CLASS_POINT &clipped1,CLASS_POINT &clipped2) +{ + eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1); + switch(intersection_type) + { + case G_FRONT_PLANE_S1: + VEC_COPY(clipped1,s1); + VEC_COPY(clipped2,s2); + break; + case G_FRONT_PLANE_S2: + VEC_COPY(clipped1,s2); + VEC_COPY(clipped2,s1); + break; + case G_BACK_PLANE_S1: + VEC_COPY(clipped1,s1); + VEC_COPY(clipped2,s2); + break; + case G_BACK_PLANE_S2: + VEC_COPY(clipped1,s2); + VEC_COPY(clipped2,s1); + break; + case G_COLLIDE_PLANE_S1: + VEC_COPY(clipped2,s1); + break; + case G_COLLIDE_PLANE_S2: + VEC_COPY(clipped2,s2); + break; + } + return intersection_type; +} + + +//! Finds the 2 smallest cartesian coordinates of a plane normal +#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1) + +//! Ray plane collision in one way +/*! +Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).
+It uses the PLANEDIREPSILON constant. +*/ +template +SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION( + const CLASS_PLANE & plane, + const CLASS_POINT & vDir, + const CLASS_POINT & vPoint, + CLASS_POINT & pout,T &tparam) +{ + GREAL _dis,_dotdir; + _dotdir = VEC_DOT(plane,vDir); + if(_dotdir +SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION( + const CLASS_PLANE & plane, + const CLASS_POINT & vDir, + const CLASS_POINT & vPoint, + CLASS_POINT & pout, + T &tparam, + T tmin, T tmax) +{ + GREAL _dis,_dotdir; + _dotdir = VEC_DOT(plane,vDir); + if(btFabs(_dotdir)tmax) + { + returnvalue = 0; + tparam = tmax; + } + + VEC_SCALE(pout,tparam,vDir); + VEC_SUM(pout,vPoint,pout); + return returnvalue; +} + +/*! \brief Returns the Ray on which 2 planes intersect if they do. + Written by Rodrigo Hernandez on ODE convex collision + + \param p1 Plane 1 + \param p2 Plane 2 + \param p Contains the origin of the ray upon returning if planes intersect + \param d Contains the direction of the ray upon returning if planes intersect + \return true if the planes intersect, 0 if paralell. + +*/ +template +SIMD_FORCE_INLINE bool INTERSECT_PLANES( + const CLASS_PLANE &p1, + const CLASS_PLANE &p2, + CLASS_POINT &p, + CLASS_POINT &d) +{ + VEC_CROSS(d,p1,p2); + GREAL denom = VEC_DOT(d, d); + if(GIM_IS_ZERO(denom)) return false; + vec3f _n; + _n[0]=p1[3]*p2[0] - p2[3]*p1[0]; + _n[1]=p1[3]*p2[1] - p2[3]*p1[1]; + _n[2]=p1[3]*p2[2] - p2[3]*p1[2]; + VEC_CROSS(p,_n,d); + p[0]/=denom; + p[1]/=denom; + p[2]/=denom; + return true; +} + +//***************** SEGMENT and LINE FUNCTIONS **********************************/// + +/*! Finds the closest point(cp) to (v) on a segment (e1,e2) + */ +template +SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT( + CLASS_POINT & cp, const CLASS_POINT & v, + const CLASS_POINT &e1,const CLASS_POINT &e2) +{ + vec3f _n; + VEC_DIFF(_n,e2,e1); + VEC_DIFF(cp,v,e1); + GREAL _scalar = VEC_DOT(cp, _n); + _scalar/= VEC_DOT(_n, _n); + if(_scalar <0.0f) + { + VEC_COPY(cp,e1); + } + else if(_scalar >1.0f) + { + VEC_COPY(cp,e2); + } + else + { + VEC_SCALE(cp,_scalar,_n); + VEC_SUM(cp,cp,e1); + } +} + + +/*! \brief Finds the line params where these lines intersect. + +\param dir1 Direction of line 1 +\param point1 Point of line 1 +\param dir2 Direction of line 2 +\param point2 Point of line 2 +\param t1 Result Parameter for line 1 +\param t2 Result Parameter for line 2 +\param dointersect 0 if the lines won't intersect, else 1 + +*/ +template +SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS( + const CLASS_POINT & dir1, + CLASS_POINT & point1, + const CLASS_POINT & dir2, + CLASS_POINT & point2, + T& t1,T& t2) +{ + GREAL det; + GREAL e1e1 = VEC_DOT(dir1,dir1); + GREAL e1e2 = VEC_DOT(dir1,dir2); + GREAL e2e2 = VEC_DOT(dir2,dir2); + vec3f p1p2; + VEC_DIFF(p1p2,point1,point2); + GREAL p1p2e1 = VEC_DOT(p1p2,dir1); + GREAL p1p2e2 = VEC_DOT(p1p2,dir2); + det = e1e2*e1e2 - e1e1*e2e2; + if(GIM_IS_ZERO(det)) return false; + t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det; + t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det; + return true; +} + +//! Find closest points on segments +template +SIMD_FORCE_INLINE void SEGMENT_COLLISION( + const CLASS_POINT & vA1, + const CLASS_POINT & vA2, + const CLASS_POINT & vB1, + const CLASS_POINT & vB2, + CLASS_POINT & vPointA, + CLASS_POINT & vPointB) +{ + CLASS_POINT _AD,_BD,_N; + vec4f _M;//plane + VEC_DIFF(_AD,vA2,vA1); + VEC_DIFF(_BD,vB2,vB1); + VEC_CROSS(_N,_AD,_BD); + GREAL _tp = VEC_DOT(_N,_N); + if(_tp_M[1]) + { + invert_b_order = true; + GIM_SWAP_NUMBERS(_M[0],_M[1]); + } + _M[2] = VEC_DOT(vA1,_AD); + _M[3] = VEC_DOT(vA2,_AD); + //mid points + _N[0] = (_M[0]+_M[1])*0.5f; + _N[1] = (_M[2]+_M[3])*0.5f; + + if(_N[0]<_N[1]) + { + if(_M[1]<_M[2]) + { + vPointB = invert_b_order?vB1:vB2; + vPointA = vA1; + } + else if(_M[1]<_M[3]) + { + vPointB = invert_b_order?vB1:vB2; + CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2); + } + else + { + vPointA = vA2; + CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2); + } + } + else + { + if(_M[3]<_M[0]) + { + vPointB = invert_b_order?vB2:vB1; + vPointA = vA2; + } + else if(_M[3]<_M[1]) + { + vPointA = vA2; + CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2); + } + else + { + vPointB = invert_b_order?vB1:vB2; + CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2); + } + } + return; + } + + + VEC_CROSS(_M,_N,_BD); + _M[3] = VEC_DOT(_M,vB1); + + LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1)); + /*Closest point on segment*/ + VEC_DIFF(vPointB,vPointA,vB1); + _tp = VEC_DOT(vPointB, _BD); + _tp/= VEC_DOT(_BD, _BD); + _tp = GIM_CLAMP(_tp,0.0f,1.0f); + VEC_SCALE(vPointB,_tp,_BD); + VEC_SUM(vPointB,vPointB,vB1); +} + + + + +//! Line box intersection in one dimension +/*! + +*\param pos Position of the ray +*\param dir Projection of the Direction of the ray +*\param bmin Minimum bound of the box +*\param bmax Maximum bound of the box +*\param tfirst the minimum projection. Assign to 0 at first. +*\param tlast the maximum projection. Assign to INFINITY at first. +*\return true if there is an intersection. +*/ +template +SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast) +{ + if(GIM_IS_ZERO(dir)) + { + return !(pos < bmin || pos > bmax); + } + GREAL a0 = (bmin - pos) / dir; + GREAL a1 = (bmax - pos) / dir; + if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1); + tfirst = GIM_MAX(a0, tfirst); + tlast = GIM_MIN(a1, tlast); + if (tlast < tfirst) return false; + return true; +} + + +//! Sorts 3 componets +template +SIMD_FORCE_INLINE void SORT_3_INDICES( + const T * values, + GUINT * order_indices) +{ + //get minimum + order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2); + + //get second and third + GUINT i0 = (order_indices[0] + 1)%3; + GUINT i1 = (i0 + 1)%3; + + if(values[i0] < values[i1]) + { + order_indices[1] = i0; + order_indices[2] = i1; + } + else + { + order_indices[1] = i1; + order_indices[2] = i0; + } +} + + + + + +#endif // GIM_VECTOR_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_bitset.h b/Code/Physics/src/BulletCollision/Gimpact/gim_bitset.h new file mode 100644 index 00000000..7dee48a4 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_bitset.h @@ -0,0 +1,123 @@ +#ifndef GIM_BITSET_H_INCLUDED +#define GIM_BITSET_H_INCLUDED +/*! \file gim_bitset.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_array.h" + + +#define GUINT_BIT_COUNT 32 +#define GUINT_EXPONENT 5 + +class gim_bitset +{ +public: + gim_array m_container; + + gim_bitset() + { + + } + + gim_bitset(GUINT bits_count) + { + resize(bits_count); + } + + ~gim_bitset() + { + } + + inline bool resize(GUINT newsize) + { + GUINT oldsize = m_container.size(); + m_container.resize(newsize/GUINT_BIT_COUNT + 1,false); + while(oldsize=size()) + { + resize(bit_index); + } + m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1))); + } + + ///Return 0 or 1 + inline char get(GUINT bit_index) + { + if(bit_index>=size()) + { + return 0; + } + char value = m_container[bit_index >> GUINT_EXPONENT] & + (1 << (bit_index & (GUINT_BIT_COUNT-1))); + return value; + } + + inline void clear(GUINT bit_index) + { + m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1))); + } +}; + + + + + +#endif // GIM_CONTAINERS_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_box_collision.h b/Code/Physics/src/BulletCollision/Gimpact/gim_box_collision.h new file mode 100644 index 00000000..9c572638 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_box_collision.h @@ -0,0 +1,588 @@ +#ifndef GIM_BOX_COLLISION_H_INCLUDED +#define GIM_BOX_COLLISION_H_INCLUDED + +/*! \file gim_box_collision.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ +#include "gim_basic_geometry_operations.h" +#include "LinearMath/btTransform.h" + + + +//SIMD_FORCE_INLINE bool test_cross_edge_box( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, const btVector3 & extend, +// int dir_index0, +// int dir_index1 +// int component_index0, +// int component_index1) +//{ +// // dir coords are -z and y +// +// const btScalar dir0 = -edge[dir_index0]; +// const btScalar dir1 = edge[dir_index1]; +// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1; +// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1; +// //find minmax +// if(pmin>pmax) +// { +// GIM_SWAP_NUMBERS(pmin,pmax); +// } +// //find extends +// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] + +// extend[component_index1] * absolute_edge[dir_index1]; +// +// if(pmin>rad || -rad>pmax) return false; +// return true; +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2); +//} +// +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0); +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1); +//} + +#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\ +{\ + const btScalar dir0 = -edge[i_dir_0];\ + const btScalar dir1 = edge[i_dir_1];\ + btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\ + btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\ + if(pmin>pmax)\ + {\ + GIM_SWAP_NUMBERS(pmin,pmax); \ + }\ + const btScalar abs_dir0 = absolute_edge[i_dir_0];\ + const btScalar abs_dir1 = absolute_edge[i_dir_1];\ + const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\ + if(pmin>rad || -rad>pmax) return false;\ +}\ + + +#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\ +}\ + + + +//! Class for transforming a model1 to the space of model0 +class GIM_BOX_BOX_TRANSFORM_CACHE +{ +public: + btVector3 m_T1to0;//!< Transforms translation of model1 to model 0 + btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1 + btMatrix3x3 m_AR;//!< Absolute value of m_R1to0 + + SIMD_FORCE_INLINE void calc_absolute_matrix() + { + static const btVector3 vepsi(1e-6f,1e-6f,1e-6f); + m_AR[0] = vepsi + m_R1to0[0].absolute(); + m_AR[1] = vepsi + m_R1to0[1].absolute(); + m_AR[2] = vepsi + m_R1to0[2].absolute(); + } + + GIM_BOX_BOX_TRANSFORM_CACHE() + { + } + + + GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0) + { + COPY_MATRIX_3X3(m_R1to0,trans1_to_0) + MAT_GET_TRANSLATION(trans1_to_0,m_T1to0) + calc_absolute_matrix(); + } + + //! Calc the transformation relative 1 to 0. Inverts matrics by transposing + SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1) + { + + m_R1to0 = trans0.getBasis().transpose(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + //! Calcs the full invertion of the matrices. Useful for scaling matrices + SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1) + { + m_R1to0 = trans0.getBasis().inverse(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) + { + return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0; + } +}; + + +#define BOX_PLANE_EPSILON 0.000001f + +//! Axis aligned box +class GIM_AABB +{ +public: + btVector3 m_min; + btVector3 m_max; + + GIM_AABB() + {} + + + GIM_AABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + } + + GIM_AABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3, + GREAL margin) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + GIM_AABB(const GIM_AABB &other): + m_min(other.m_min),m_max(other.m_max) + { + } + + GIM_AABB(const GIM_AABB &other,btScalar margin ): + m_min(other.m_min),m_max(other.m_max) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void invalidate() + { + m_min[0] = G_REAL_INFINITY; + m_min[1] = G_REAL_INFINITY; + m_min[2] = G_REAL_INFINITY; + m_max[0] = -G_REAL_INFINITY; + m_max[1] = -G_REAL_INFINITY; + m_max[2] = -G_REAL_INFINITY; + } + + SIMD_FORCE_INLINE void increment_margin(btScalar margin) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin) + { + m_min[0] = other.m_min[0] - margin; + m_min[1] = other.m_min[1] - margin; + m_min[2] = other.m_min[2] - margin; + + m_max[0] = other.m_max[0] + margin; + m_max[1] = other.m_max[1] + margin; + m_max[2] = other.m_max[2] + margin; + } + + template + SIMD_FORCE_INLINE void calc_from_triangle( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + } + + template + SIMD_FORCE_INLINE void calc_from_triangle_margin( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3, btScalar margin) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform(const btTransform & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans(center); + + btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(), + trans.getBasis().getRow(1).absolute(), + trans.getBasis().getRow(2).absolute()); + + m_min = center - textends; + m_max = center + textends; + } + + //! Merges a Box + SIMD_FORCE_INLINE void merge(const GIM_AABB & box) + { + m_min[0] = GIM_MIN(m_min[0],box.m_min[0]); + m_min[1] = GIM_MIN(m_min[1],box.m_min[1]); + m_min[2] = GIM_MIN(m_min[2],box.m_min[2]); + + m_max[0] = GIM_MAX(m_max[0],box.m_max[0]); + m_max[1] = GIM_MAX(m_max[1],box.m_max[1]); + m_max[2] = GIM_MAX(m_max[2],box.m_max[2]); + } + + //! Merges a point + template + SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point) + { + m_min[0] = GIM_MIN(m_min[0],point[0]); + m_min[1] = GIM_MIN(m_min[1],point[1]); + m_min[2] = GIM_MIN(m_min[2],point[2]); + + m_max[0] = GIM_MAX(m_max[0],point[0]); + m_max[1] = GIM_MAX(m_max[1],point[1]); + m_max[2] = GIM_MAX(m_max[2],point[2]); + } + + //! Gets the extend and center + SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const + { + center = (m_max+m_min)*0.5f; + extend = m_max - center; + } + + //! Finds the intersecting box between this box and the other. + SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const + { + intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]); + intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]); + intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]); + + intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]); + intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]); + intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]); + } + + + SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const + { + if(m_min[0] > other.m_max[0] || + m_max[0] < other.m_min[0] || + m_min[1] > other.m_max[1] || + m_max[1] < other.m_min[1] || + m_min[2] > other.m_max[2] || + m_max[2] < other.m_min[2]) + { + return false; + } + return true; + } + + /*! \brief Finds the Ray intersection parameter. + \param aabb Aligned box + \param vorigin A vec3f with the origin of the ray + \param vdir A vec3f with the direction of the ray + */ + SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) + { + btVector3 extents,center; + this->get_center_extend(center,extents);; + + btScalar Dx = vorigin[0] - center[0]; + if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false; + btScalar Dy = vorigin[1] - center[1]; + if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false; + btScalar Dz = vorigin[2] - center[2]; + if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false; + + + btScalar f = vdir[1] * Dz - vdir[2] * Dy; + if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false; + f = vdir[2] * Dx - vdir[0] * Dz; + if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false; + f = vdir[0] * Dy - vdir[1] * Dx; + if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false; + return true; + } + + + SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extend = m_max-center; + + btScalar _fOrigin = direction.dot(center); + btScalar _fMaximumExtent = extend.dot(direction.absolute()); + vmin = _fOrigin - _fMaximumExtent; + vmax = _fOrigin + _fMaximumExtent; + } + + SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const + { + btScalar _fmin,_fmax; + this->projection_interval(plane,_fmin,_fmax); + + if(plane[3] > _fmax + BOX_PLANE_EPSILON) + { + return G_BACK_PLANE; // 0 + } + + if(plane[3]+BOX_PLANE_EPSILON >=_fmin) + { + return G_COLLIDE_PLANE; //1 + } + return G_FRONT_PLANE;//2 + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0) + { + GIM_AABB tbox = box; + tbox.appy_transform(trans1_to_0); + return has_collision(tbox); + } + + //! transcache is the transformation cache from box to this AABB + SIMD_FORCE_INLINE bool overlapping_trans_cache( + const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) + { + + //Taken from OPCODE + btVector3 ea,eb;//extends + btVector3 ca,cb;//extends + get_center_extend(ca,ea); + box.get_center_extend(cb,eb); + + + btVector3 T; + btScalar t,t2; + int i; + + // Class I : A's basis vectors + for(i=0;i<3;i++) + { + T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i]; + t = transcache.m_AR[i].dot(eb) + ea[i]; + if(GIM_GREATER(T[i], t)) return false; + } + // Class II : B's basis vectors + for(i=0;i<3;i++) + { + t = MAT_DOT_COL(transcache.m_R1to0,T,i); + t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i]; + if(GIM_GREATER(t,t2)) return false; + } + // Class III : 9 cross products + if(fulltest) + { + int j,m,n,o,p,q,r; + for(i=0;i<3;i++) + { + m = (i+1)%3; + n = (i+2)%3; + o = i==0?1:0; + p = i==2?1:2; + for(j=0;j<3;j++) + { + q = j==2?1:2; + r = j==0?1:0; + t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j]; + t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] + + eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r]; + if(GIM_GREATER(t,t2)) return false; + } + } + } + return true; + } + + //! Simple test for planes. + SIMD_FORCE_INLINE bool collide_plane( + const btVector4 & plane) + { + ePLANE_INTERSECTION_TYPE classify = plane_classify(plane); + return (classify == G_COLLIDE_PLANE); + } + + //! test for a triangle, with edges + SIMD_FORCE_INLINE bool collide_triangle_exact( + const btVector3 & p1, + const btVector3 & p2, + const btVector3 & p3, + const btVector4 & triangle_plane) + { + if(!collide_plane(triangle_plane)) return false; + + btVector3 center,extends; + this->get_center_extend(center,extends); + + const btVector3 v1(p1 - center); + const btVector3 v2(p2 - center); + const btVector3 v3(p3 - center); + + //First axis + btVector3 diff(v2 - v1); + btVector3 abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends); + + + diff = v3 - v2; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends); + + diff = v1 - v3; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends); + + return true; + } +}; + + +//! Compairison of transformation objects +SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2) +{ + if(!(t1.getOrigin() == t2.getOrigin()) ) return false; + + if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false; + if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false; + if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false; + return true; +} + + + +#endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.cpp b/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.cpp new file mode 100644 index 00000000..0c3d7ba8 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.cpp @@ -0,0 +1,182 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_box_set.h" + + +GUINT GIM_BOX_TREE::_calc_splitting_axis( + gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex) +{ + GUINT i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + GUINT numIndices = endIndex-startIndex; + + for (i=startIndex;i & primitive_boxes, GUINT startIndex, + GUINT endIndex, GUINT splitAxis) +{ + GUINT i; + GUINT splitIndex =startIndex; + GUINT numIndices = endIndex - startIndex; + + // average of centers + btScalar splitValue = 0.0f; + for (i=startIndex;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + GUINT rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); + + return splitIndex; +} + + +void GIM_BOX_TREE::_build_sub_tree(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex) +{ + GUINT current_index = m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if((endIndex-startIndex) == 1) //we got a leaf + { + m_node_array[current_index].m_left = 0; + m_node_array[current_index].m_right = 0; + m_node_array[current_index].m_escapeIndex = 0; + + m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound; + m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data; + return; + } + + //configure inner node + + GUINT splitIndex; + + //calc this node bounding box + m_node_array[current_index].m_bound.invalidate(); + for (splitIndex=startIndex;splitIndex & primitive_boxes) +{ + // initialize node count to 0 + m_num_nodes = 0; + // allocate nodes + m_node_array.resize(primitive_boxes.size()*2); + + _build_sub_tree(primitive_boxes, 0, primitive_boxes.size()); +} + + diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.h b/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.h new file mode 100644 index 00000000..61d190a7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.h @@ -0,0 +1,674 @@ +#ifndef GIM_BOX_SET_H_INCLUDED +#define GIM_BOX_SET_H_INCLUDED + +/*! \file gim_box_set.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_array.h" +#include "gim_radixsort.h" +#include "gim_box_collision.h" +#include "gim_tri_collision.h" + + + +//! Overlapping pair +struct GIM_PAIR +{ + GUINT m_index1; + GUINT m_index2; + GIM_PAIR() + {} + + GIM_PAIR(const GIM_PAIR & p) + { + m_index1 = p.m_index1; + m_index2 = p.m_index2; + } + + GIM_PAIR(GUINT index1, GUINT index2) + { + m_index1 = index1; + m_index2 = index2; + } +}; + +//! A pairset array +class gim_pair_set: public gim_array +{ +public: + gim_pair_set():gim_array(32) + { + } + inline void push_pair(GUINT index1,GUINT index2) + { + push_back(GIM_PAIR(index1,index2)); + } + + inline void push_pair_inv(GUINT index1,GUINT index2) + { + push_back(GIM_PAIR(index2,index1)); + } +}; + + +//! Prototype Base class for primitive classification +/*! +This class is a wrapper for primitive collections. +This tells relevant info for the Bounding Box set classes, which take care of space classification. +This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons. +*/ +class GIM_PRIMITIVE_MANAGER_PROTOTYPE +{ +public: + + virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {} + //! determines if this manager consist on only triangles, which special case will be optimized + virtual bool is_trimesh() = 0; + virtual GUINT get_primitive_count() = 0; + virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0; + virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0; +}; + + +struct GIM_AABB_DATA +{ + GIM_AABB m_bound; + GUINT m_data; +}; + +//! Node Structure for trees +struct GIM_BOX_TREE_NODE +{ + GIM_AABB m_bound; + GUINT m_left;//!< Left subtree + GUINT m_right;//!< Right subtree + GUINT m_escapeIndex;//!< Scape index for traversing + GUINT m_data;//!< primitive index if apply + + GIM_BOX_TREE_NODE() + { + m_left = 0; + m_right = 0; + m_escapeIndex = 0; + m_data = 0; + } + + SIMD_FORCE_INLINE bool is_leaf_node() const + { + return (!m_left && !m_right); + } +}; + +//! Basic Box tree structure +class GIM_BOX_TREE +{ +protected: + GUINT m_num_nodes; + gim_array m_node_array; +protected: + GUINT _sort_and_calc_splitting_index( + gim_array & primitive_boxes, + GUINT startIndex, GUINT endIndex, GUINT splitAxis); + + GUINT _calc_splitting_axis(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex); + + void _build_sub_tree(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex); +public: + GIM_BOX_TREE() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(gim_array & primitive_boxes); + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE GUINT getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const + { + return m_node_array[nodeindex].is_leaf_node(); + } + + SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_data; + } + + SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const + { + bound = m_node_array[nodeindex].m_bound; + } + + SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound) + { + m_node_array[nodeindex].m_bound = bound; + } + + SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_left; + } + + SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_right; + } + + SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_escapeIndex; + } + + //!@} +}; + + +//! Generic Box Tree Template +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and +a Box tree structure ( like GIM_BOX_TREE). +*/ +template +class GIM_BOX_TREE_TEMPLATE_SET +{ +protected: + _GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager; + _GIM_BOX_TREE_PROTOTYPE m_box_tree; +protected: + //stackless refit + SIMD_FORCE_INLINE void refit() + { + GUINT nodecount = getNodeCount(); + while(nodecount--) + { + if(isLeafNode(nodecount)) + { + GIM_AABB leafbox; + m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //get left bound + GUINT childindex = getLeftNodeIndex(nodecount); + GIM_AABB bound; + getNodeBound(childindex,bound); + //get right bound + childindex = getRightNodeIndex(nodecount); + GIM_AABB bound2; + getNodeBound(childindex,bound2); + bound.merge(bound2); + + setNodeBound(nodecount,bound); + } + } + } +public: + + GIM_BOX_TREE_TEMPLATE_SET() + { + } + + SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const + { + GIM_AABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const + { + return m_primitive_manager; + } + + _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() + { + return m_primitive_manager; + } + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + SIMD_FORCE_INLINE void buildSet() + { + //obtain primitive boxes + gim_array primitive_boxes; + primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false); + + for (GUINT i = 0;i & collided_results) const + { + GUINT curIndex = 0; + GUINT numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + GIM_AABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.has_collision(box); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getScapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; + } + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box, + const btTransform & transform, gim_array & collided_results) const + { + GIM_AABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + gim_array & collided_results) const + { + GUINT curIndex = 0; + GUINT numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + GIM_AABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getScapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; + } + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager.is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE GUINT getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getLeftNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getRightNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getScapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const + { + m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle); + } + +}; + +//! Class for Box Tree Sets +/*! +this has the GIM_BOX_TREE implementation for bounding boxes. +*/ +template +class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE> +{ +public: + +}; + + + + + +/// GIM_BOX_SET collision methods +template +class GIM_TREE_TREE_COLLIDER +{ +public: + gim_pair_set * m_collision_pairs; + BOX_SET_CLASS0 * m_boxset0; + BOX_SET_CLASS1 * m_boxset1; + GUINT current_node0; + GUINT current_node1; + bool node0_is_leaf; + bool node1_is_leaf; + bool t0_is_trimesh; + bool t1_is_trimesh; + bool node0_has_triangle; + bool node1_has_triangle; + GIM_AABB m_box0; + GIM_AABB m_box1; + GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + btTransform trans_cache_0to1; + GIM_TRIANGLE m_tri0; + btVector4 m_tri0_plane; + GIM_TRIANGLE m_tri1; + btVector4 m_tri1_plane; + + +public: + GIM_TREE_TREE_COLLIDER() + { + current_node0 = G_UINT_INFINITY; + current_node1 = G_UINT_INFINITY; + } +protected: + SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0) + { + if(node0_has_triangle) return; + m_boxset0->getNodeTriangle(node0,m_tri0); + //transform triangle + m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]); + m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]); + m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]); + m_tri0.get_plane(m_tri0_plane); + + node0_has_triangle = true; + } + + SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1) + { + if(node1_has_triangle) return; + m_boxset1->getNodeTriangle(node1,m_tri1); + //transform triangle + m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]); + m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]); + m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]); + m_tri1.get_plane(m_tri1_plane); + + node1_has_triangle = true; + } + + SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0) + { + if(node0 == current_node0) return; + m_boxset0->getNodeBound(node0,m_box0); + node0_is_leaf = m_boxset0->isLeafNode(node0); + node0_has_triangle = false; + current_node0 = node0; + } + + SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1) + { + if(node1 == current_node1) return; + m_boxset1->getNodeBound(node1,m_box1); + node1_is_leaf = m_boxset1->isLeafNode(node1); + node1_has_triangle = false; + current_node1 = node1; + } + + SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1) + { + retrieve_node0_info(node0); + retrieve_node1_info(node1); + bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true); + if(!result) return false; + + if(t0_is_trimesh && node0_is_leaf) + { + //perform primitive vs box collision + retrieve_node0_triangle(node0); + //do triangle vs box collision + m_box1.increment_margin(m_tri0.m_margin); + + result = m_box1.collide_triangle_exact( + m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane); + + m_box1.increment_margin(-m_tri0.m_margin); + + if(!result) return false; + return true; + } + else if(t1_is_trimesh && node1_is_leaf) + { + //perform primitive vs box collision + retrieve_node1_triangle(node1); + //do triangle vs box collision + m_box0.increment_margin(m_tri1.m_margin); + + result = m_box0.collide_triangle_exact( + m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane); + + m_box0.increment_margin(-m_tri1.m_margin); + + if(!result) return false; + return true; + } + return true; + } + + //stackless collision routine + void find_collision_pairs() + { + gim_pair_set stack_collisions; + stack_collisions.reserve(32); + + //add the first pair + stack_collisions.push_pair(0,0); + + + while(stack_collisions.size()) + { + //retrieve the last pair and pop + GUINT node0 = stack_collisions.back().m_index1; + GUINT node1 = stack_collisions.back().m_index2; + stack_collisions.pop_back(); + if(node_collision(node0,node1)) // a collision is found + { + if(node0_is_leaf) + { + if(node1_is_leaf) + { + m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1)); + } + else + { + //collide left + stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1)); + + //collide right + stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1)); + } + } + else + { + if(node1_is_leaf) + { + //collide left + stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1); + //collide right + stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1); + } + else + { + GUINT left0 = m_boxset0->getLeftNodeIndex(node0); + GUINT right0 = m_boxset0->getRightNodeIndex(node0); + GUINT left1 = m_boxset1->getLeftNodeIndex(node1); + GUINT right1 = m_boxset1->getRightNodeIndex(node1); + //collide left + stack_collisions.push_pair(left0,left1); + //collide right + stack_collisions.push_pair(left0,right1); + //collide left + stack_collisions.push_pair(right0,left1); + //collide right + stack_collisions.push_pair(right0,right1); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf + + }// if(node_collision(node0,node1)) + }//while(stack_collisions.size()) + } +public: + void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1, + BOX_SET_CLASS1 * boxset2, const btTransform & trans2, + gim_pair_set & collision_pairs, bool complete_primitive_tests = true) + { + m_collision_pairs = &collision_pairs; + m_boxset0 = boxset1; + m_boxset1 = boxset2; + + trans_cache_1to0.calc_from_homogenic(trans1,trans2); + + trans_cache_0to1 = trans2.inverse(); + trans_cache_0to1 *= trans1; + + + if(complete_primitive_tests) + { + t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh(); + t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh(); + } + else + { + t0_is_trimesh = false; + t1_is_trimesh = false; + } + + find_collision_pairs(); + } +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED + + diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_clip_polygon.h b/Code/Physics/src/BulletCollision/Gimpact/gim_clip_polygon.h new file mode 100644 index 00000000..e342459c --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_clip_polygon.h @@ -0,0 +1,210 @@ +#ifndef GIM_CLIP_POLYGON_H_INCLUDED +#define GIM_CLIP_POLYGON_H_INCLUDED + +/*! \file gim_tri_collision.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +//! This function calcs the distance from a 3D plane +class DISTANCE_PLANE_3D_FUNC +{ +public: + template + inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point) + { + return DISTANCE_PLANE_POINT(plane, point); + } +}; + + + +template +SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT( + const CLASS_POINT & point0, + const CLASS_POINT & point1, + GREAL dist0, + GREAL dist1, + CLASS_POINT * clipped, + GUINT & clipped_count) +{ + GUINT _prevclassif = (dist0>G_EPSILON); + GUINT _classif = (dist1>G_EPSILON); + if(_classif!=_prevclassif) + { + GREAL blendfactor = -dist0/(dist1-dist0); + VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor); + clipped_count++; + } + if(!_classif) + { + VEC_COPY(clipped[clipped_count],point1); + clipped_count++; + } +} + + +//! Clips a polygon by a plane +/*! +*\return The count of the clipped counts +*/ +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC( + const CLASS_PLANE & plane, + const CLASS_POINT * polygon_points, + GUINT polygon_point_count, + CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func) +{ + GUINT clipped_count = 0; + + + //clip first point + GREAL firstdist = distance_func(plane,polygon_points[0]);; + if(!(firstdist>G_EPSILON)) + { + VEC_COPY(clipped[clipped_count],polygon_points[0]); + clipped_count++; + } + + GREAL olddist = firstdist; + for(GUINT _i=1;_i +SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC( + const CLASS_PLANE & plane, + const CLASS_POINT & point0, + const CLASS_POINT & point1, + const CLASS_POINT & point2, + CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func) +{ + GUINT clipped_count = 0; + + //clip first point + GREAL firstdist = distance_func(plane,point0);; + if(!(firstdist>G_EPSILON)) + { + VEC_COPY(clipped[clipped_count],point0); + clipped_count++; + } + + // point 1 + GREAL olddist = firstdist; + GREAL dist = distance_func(plane,point1); + + PLANE_CLIP_POLYGON_COLLECT( + point0,point1, + olddist, + dist, + clipped, + clipped_count); + + olddist = dist; + + + // point 2 + dist = distance_func(plane,point2); + + PLANE_CLIP_POLYGON_COLLECT( + point1,point2, + olddist, + dist, + clipped, + clipped_count); + olddist = dist; + + + + //RETURN TO FIRST point + PLANE_CLIP_POLYGON_COLLECT( + point2,point0, + olddist, + firstdist, + clipped, + clipped_count); + + return clipped_count; +} + + +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D( + const CLASS_PLANE & plane, + const CLASS_POINT * polygon_points, + GUINT polygon_point_count, + CLASS_POINT * clipped) +{ + return PLANE_CLIP_POLYGON_GENERIC(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC()); +} + + +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D( + const CLASS_PLANE & plane, + const CLASS_POINT & point0, + const CLASS_POINT & point1, + const CLASS_POINT & point2, + CLASS_POINT * clipped) +{ + return PLANE_CLIP_TRIANGLE_GENERIC(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC()); +} + + + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_contact.cpp b/Code/Physics/src/BulletCollision/Gimpact/gim_contact.cpp new file mode 100644 index 00000000..20e41de0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_contact.cpp @@ -0,0 +1,146 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_contact.h" + +#define MAX_COINCIDENT 8 + +void gim_contact_array::merge_contacts( + const gim_contact_array & contacts, bool normal_contact_average) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + gim_array keycontacts(contacts.size()); + keycontacts.resize(contacts.size(),false); + + //fill key contacts + + GUINT i; + + for (i = 0;im_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &back(); + } + last_key = key; + } +} + +void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + GIM_CONTACT average_contact = contacts.back(); + + for (GUINT i=1;i +{ +public: + gim_contact_array():gim_array(64) + { + } + + SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal, + GREAL depth, GUINT feature1, GUINT feature2) + { + push_back_mem(); + GIM_CONTACT & newele = back(); + newele.m_point = point; + newele.m_normal = normal; + newele.m_depth = depth; + newele.m_feature1 = feature1; + newele.m_feature2 = feature2; + } + + SIMD_FORCE_INLINE void push_triangle_contacts( + const GIM_TRIANGLE_CONTACT_DATA & tricontact, + GUINT feature1,GUINT feature2) + { + for(GUINT i = 0;i +struct GIM_HASH_TABLE_NODE +{ + GUINT m_key; + T m_data; + GIM_HASH_TABLE_NODE() + { + } + + GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value) + { + m_key = value.m_key; + m_data = value.m_data; + } + + GIM_HASH_TABLE_NODE(GUINT key, const T & data) + { + m_key = key; + m_data = data; + } + + bool operator <(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key < other.m_key) return true; + return false; + } + + bool operator >(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key > other.m_key) return true; + return false; + } + + bool operator ==(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key == other.m_key) return true; + return false; + } +}; + +///Macro for getting the key +class GIM_HASH_NODE_GET_KEY +{ +public: + template + inline GUINT operator()( const T& a) + { + return a.m_key; + } +}; + + + +///Macro for comparing the key and the element +class GIM_HASH_NODE_CMP_KEY_MACRO +{ +public: + template + inline int operator() ( const T& a, GUINT key) + { + return ((int)(a.m_key - key)); + } +}; + +///Macro for comparing Hash nodes +class GIM_HASH_NODE_CMP_MACRO +{ +public: + template + inline int operator() ( const T& a, const T& b ) + { + return ((int)(a.m_key - b.m_key)); + } +}; + + + + + +//! Sorting for hash table +/*! +switch automatically between quicksort and radixsort +*/ +template +void gim_sort_hash_node_array(T * array, GUINT array_count) +{ + if(array_count + +
    +
  • if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes. +When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable. +
  • If node_size != 0, then this container becomes a hash table for ever +
+ +*/ +template +class gim_hash_table +{ +protected: + typedef GIM_HASH_TABLE_NODE _node_type; + + //!The nodes + //array< _node_type, SuperAllocator<_node_type> > m_nodes; + gim_array< _node_type > m_nodes; + //SuperBufferedArray< _node_type > m_nodes; + bool m_sorted; + + ///Hash table data management. The hash table has the indices to the corresponding m_nodes array + GUINT * m_hash_table;//!< + GUINT m_table_size;//!< + GUINT m_node_size;//!< + GUINT m_min_hash_table_size; + + + + //! Returns the cell index + inline GUINT _find_cell(GUINT hashkey) + { + _node_type * nodesptr = m_nodes.pointer(); + GUINT start_index = (hashkey%m_table_size)*m_node_size; + GUINT end_index = start_index + m_node_size; + + while(start_index= m_nodes.size()) return false; + if(m_nodes[index].m_key != GIM_INVALID_HASH) + { + //Search for the avaliable cell in buffer + GUINT cell_index = _find_cell(m_nodes[index].m_key); + + btAssert(cell_index!=GIM_INVALID_HASH); + btAssert(m_hash_table[cell_index]==index); + + m_hash_table[cell_index] = GIM_INVALID_HASH; + } + + return this->_erase_unsorted(index); + } + + //! erase by key in hash table + inline bool _erase_hash_table(GUINT hashkey) + { + if(hashkey == GIM_INVALID_HASH) return false; + + //Search for the avaliable cell in buffer + GUINT cell_index = _find_cell(hashkey); + if(cell_index ==GIM_INVALID_HASH) return false; + + GUINT index = m_hash_table[cell_index]; + m_hash_table[cell_index] = GIM_INVALID_HASH; + + return this->_erase_unsorted(index); + } + + + + //! insert an element in hash table + /*! + If the element exists, this won't insert the element + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT _insert_hash_table(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH) + { + //Insert anyway + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + GUINT cell_index = _assign_hash_table_cell(hashkey); + + GUINT value_key = m_hash_table[cell_index]; + + if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited + + m_hash_table[cell_index] = m_nodes.size(); + + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + //! insert an element in hash table. + /*! + If the element exists, this replaces the element. + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH) + { + //Insert anyway + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + GUINT cell_index = _assign_hash_table_cell(hashkey); + + GUINT value_key = m_hash_table[cell_index]; + + if(value_key!= GIM_INVALID_HASH) + {//replaces the existing + m_nodes[value_key] = _node_type(hashkey,value); + return value_key;// index of the replaced element + } + + m_hash_table[cell_index] = m_nodes.size(); + + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + + } + + + ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array + inline bool _erase_sorted(GUINT index) + { + if(index>=(GUINT)m_nodes.size()) return false; + m_nodes.erase_sorted(index); + if(m_nodes.size()<2) m_sorted = false; + return true; + } + + //! faster, but unsorted + inline bool _erase_unsorted(GUINT index) + { + if(index>=m_nodes.size()) return false; + + GUINT lastindex = m_nodes.size()-1; + if(indexcheck_for_switching_to_hashtable(); + } + + //! Insert an element in an ordered array + inline GUINT _insert_sorted(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH || size()==0) + { + m_nodes.push_back(_node_type(hashkey,value)); + return GIM_INVALID_HASH; + } + //Insert at last position + //Sort element + + + GUINT result_ind=0; + GUINT last_index = m_nodes.size()-1; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex( + ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + + //Insert before found index + if(found) + { + return result_ind; + } + else + { + _insert_in_pos(hashkey, value, result_ind); + } + return GIM_INVALID_HASH; + } + + inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH || size()==0) + { + m_nodes.push_back(_node_type(hashkey,value)); + return GIM_INVALID_HASH; + } + //Insert at last position + //Sort element + GUINT result_ind; + GUINT last_index = m_nodes.size()-1; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex( + ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + //Insert before found index + if(found) + { + m_nodes[result_ind] = _node_type(hashkey,value); + } + else + { + _insert_in_pos(hashkey, value, result_ind); + } + return result_ind; + } + + //! Fast insertion in m_nodes array + inline GUINT _insert_unsorted(GUINT hashkey, const T & value) + { + m_nodes.push_back(_node_type(hashkey,value)); + m_sorted = false; + return GIM_INVALID_HASH; + } + + + +public: + + /*! +
  • if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes. + When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable. +
  • If node_size != 0, then this container becomes a hash table for ever + + */ + gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE, + GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE, + GUINT min_hash_table_size = GIM_INVALID_HASH) + { + m_hash_table = NULL; + m_table_size = 0; + m_sorted = false; + m_node_size = node_size; + m_min_hash_table_size = min_hash_table_size; + + if(m_node_size!=0) + { + if(reserve_size!=0) + { + m_nodes.reserve(reserve_size); + _reserve_table_memory(reserve_size); + _invalidate_keys(); + } + else + { + m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE); + _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE); + _invalidate_keys(); + } + } + else if(reserve_size!=0) + { + m_nodes.reserve(reserve_size); + } + + } + + ~gim_hash_table() + { + _destroy(); + } + + inline bool is_hash_table() + { + if(m_hash_table) return true; + return false; + } + + inline bool is_sorted() + { + if(size()<2) return true; + return m_sorted; + } + + bool sort() + { + if(is_sorted()) return true; + if(m_nodes.size()<2) return false; + + + _node_type * ptr = m_nodes.pointer(); + GUINT siz = m_nodes.size(); + gim_sort_hash_node_array(ptr,siz); + m_sorted=true; + + + + if(m_hash_table) + { + _rehash(); + } + return true; + } + + bool switch_to_hashtable() + { + if(m_hash_table) return false; + if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; + if(m_nodes.size()m_hash_table) return true; + + if(!(m_nodes.size()< m_min_hash_table_size)) + { + if(m_node_size == 0) + { + m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; + } + + _resize_table(m_nodes.size()+1); + return true; + } + return false; + } + + inline void set_sorted(bool value) + { + m_sorted = value; + } + + //! Retrieves the amount of keys. + inline GUINT size() const + { + return m_nodes.size(); + } + + //! Retrieves the hash key. + inline GUINT get_key(GUINT index) const + { + return m_nodes[index].m_key; + } + + //! Retrieves the value by index + /*! + */ + inline T * get_value_by_index(GUINT index) + { + return &m_nodes[index].m_data; + } + + inline const T& operator[](GUINT index) const + { + return m_nodes[index].m_data; + } + + inline T& operator[](GUINT index) + { + return m_nodes[index].m_data; + } + + //! Finds the index of the element with the key + /*! + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT find(GUINT hashkey) + { + if(m_hash_table) + { + GUINT cell_index = _find_cell(hashkey); + if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH; + return m_hash_table[cell_index]; + } + GUINT last_index = m_nodes.size(); + if(last_index<2) + { + if(last_index==0) return GIM_INVALID_HASH; + if(m_nodes[0].m_key == hashkey) return 0; + return GIM_INVALID_HASH; + } + else if(m_sorted) + { + //Binary search + GUINT result_ind = 0; + last_index--; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + + if(found) return result_ind; + } + return GIM_INVALID_HASH; + } + + //! Retrieves the value associated with the index + /*! + \return the found element, or null + */ + inline T * get_value(GUINT hashkey) + { + GUINT index = find(hashkey); + if(index == GIM_INVALID_HASH) return NULL; + return &m_nodes[index].m_data; + } + + + /*! + */ + inline bool erase_by_index(GUINT index) + { + if(index > m_nodes.size()) return false; + + if(m_hash_table == NULL) + { + if(is_sorted()) + { + return this->_erase_sorted(index); + } + else + { + return this->_erase_unsorted(index); + } + } + else + { + return this->_erase_by_index_hash_table(index); + } + return false; + } + + + + inline bool erase_by_index_unsorted(GUINT index) + { + if(index > m_nodes.size()) return false; + + if(m_hash_table == NULL) + { + return this->_erase_unsorted(index); + } + else + { + return this->_erase_by_index_hash_table(index); + } + return false; + } + + + + /*! + + */ + inline bool erase_by_key(GUINT hashkey) + { + if(size()==0) return false; + + if(m_hash_table) + { + return this->_erase_hash_table(hashkey); + } + //Binary search + + if(is_sorted()==false) return false; + + GUINT result_ind = find(hashkey); + if(result_ind!= GIM_INVALID_HASH) + { + return this->_erase_sorted(result_ind); + } + return false; + } + + void clear() + { + m_nodes.clear(); + + if(m_hash_table==NULL) return; + GUINT datasize = m_table_size*m_node_size; + //Initialize the hashkeys. + GUINT i; + for(i=0;i_insert_hash_table(hashkey,element); + } + if(this->is_sorted()) + { + return this->_insert_sorted(hashkey,element); + } + return this->_insert_unsorted(hashkey,element); + } + + //! Insert an element into the hash, and could overrite an existing object with the same hash. + /*! + \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position + of the replaced element. + */ + inline GUINT insert_override(GUINT hashkey, const T & element) + { + if(m_hash_table) + { + return this->_insert_hash_table_replace(hashkey,element); + } + if(this->is_sorted()) + { + return this->_insert_sorted_replace(hashkey,element); + } + this->_insert_unsorted(hashkey,element); + return m_nodes.size(); + } + + + + //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted + /*! + */ + inline GUINT insert_unsorted(GUINT hashkey,const T & element) + { + if(m_hash_table) + { + return this->_insert_hash_table(hashkey,element); + } + return this->_insert_unsorted(hashkey,element); + } + + +}; + + + +#endif // GIM_CONTAINERS_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_linear_math.h b/Code/Physics/src/BulletCollision/Gimpact/gim_linear_math.h new file mode 100644 index 00000000..64f11b49 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_linear_math.h @@ -0,0 +1,1573 @@ +#ifndef GIM_LINEAR_H_INCLUDED +#define GIM_LINEAR_H_INCLUDED + +/*! \file gim_linear_math.h +*\author Francisco Leon Najera +Type Independant Vector and matrix operations. +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_math.h" +#include "gim_geom_types.h" + + + + +//! Zero out a 2D vector +#define VEC_ZERO_2(a) \ +{ \ + (a)[0] = (a)[1] = 0.0f; \ +}\ + + +//! Zero out a 3D vector +#define VEC_ZERO(a) \ +{ \ + (a)[0] = (a)[1] = (a)[2] = 0.0f; \ +}\ + + +/// Zero out a 4D vector +#define VEC_ZERO_4(a) \ +{ \ + (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \ +}\ + + +/// Vector copy +#define VEC_COPY_2(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ +}\ + + +/// Copy 3D vector +#define VEC_COPY(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ + (b)[2] = (a)[2]; \ +}\ + + +/// Copy 4D vector +#define VEC_COPY_4(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ + (b)[2] = (a)[2]; \ + (b)[3] = (a)[3]; \ +}\ + +/// VECTOR SWAP +#define VEC_SWAP(b,a) \ +{ \ + GIM_SWAP_NUMBERS((b)[0],(a)[0]);\ + GIM_SWAP_NUMBERS((b)[1],(a)[1]);\ + GIM_SWAP_NUMBERS((b)[2],(a)[2]);\ +}\ + +/// Vector difference +#define VEC_DIFF_2(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ +}\ + + +/// Vector difference +#define VEC_DIFF(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ + (v21)[2] = (v2)[2] - (v1)[2]; \ +}\ + + +/// Vector difference +#define VEC_DIFF_4(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ + (v21)[2] = (v2)[2] - (v1)[2]; \ + (v21)[3] = (v2)[3] - (v1)[3]; \ +}\ + + +/// Vector sum +#define VEC_SUM_2(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ +}\ + + +/// Vector sum +#define VEC_SUM(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ + (v21)[2] = (v2)[2] + (v1)[2]; \ +}\ + + +/// Vector sum +#define VEC_SUM_4(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ + (v21)[2] = (v2)[2] + (v1)[2]; \ + (v21)[3] = (v2)[3] + (v1)[3]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE_2(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ + (c)[2] = (a)*(b)[2]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE_4(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ + (c)[2] = (a)*(b)[2]; \ + (c)[3] = (a)*(b)[3]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM_2(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ + (c)[2] += (a)*(b)[2]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM_4(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ + (c)[2] += (a)*(b)[2]; \ + (c)[3] += (a)*(b)[3]; \ +}\ + + +/// Vector dot product +#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1]) + + +/// Vector dot product +#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2]) + +/// Vector dot product +#define VEC_DOT_4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3]) + +/// vector impact parameter (squared) +#define VEC_IMPACT_SQ(bsq,direction,position) {\ + GREAL _llel_ = VEC_DOT(direction, position);\ + bsq = VEC_DOT(position, position) - _llel_*_llel_;\ +}\ + + +/// vector impact parameter +#define VEC_IMPACT(bsq,direction,position) {\ + VEC_IMPACT_SQ(bsq,direction,position); \ + GIM_SQRT(bsq,bsq); \ +}\ + +/// Vector length +#define VEC_LENGTH_2(a,l)\ +{\ + GREAL _pp = VEC_DOT_2(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_LENGTH(a,l)\ +{\ + GREAL _pp = VEC_DOT(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_LENGTH_4(a,l)\ +{\ + GREAL _pp = VEC_DOT_4(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + +/// Vector inv length +#define VEC_INV_LENGTH_2(a,l)\ +{\ + GREAL _pp = VEC_DOT_2(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + +/// Vector inv length +#define VEC_INV_LENGTH(a,l)\ +{\ + GREAL _pp = VEC_DOT(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + +/// Vector inv length +#define VEC_INV_LENGTH_4(a,l)\ +{\ + GREAL _pp = VEC_DOT_4(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + + +/// distance between two points +#define VEC_DISTANCE(_len,_va,_vb) {\ + vec3f _tmp_; \ + VEC_DIFF(_tmp_, _vb, _va); \ + VEC_LENGTH(_tmp_,_len); \ +}\ + + +/// Vector length +#define VEC_CONJUGATE_LENGTH(a,l)\ +{\ + GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_NORMALIZE(a) { \ + GREAL len;\ + VEC_INV_LENGTH(a,len); \ + if(lenA[1]?(A[0]>A[2]?0:2):(A[1]>A[2]?1:2);\ +}\ + +//! Finds the 2 smallest cartesian coordinates from a vector +#define VEC_MINOR_AXES(vec, i0, i1)\ +{\ + VEC_MAYOR_COORD(vec,i0);\ + i0 = (i0+1)%3;\ + i1 = (i0+1)%3;\ +}\ + + + + +#define VEC_EQUAL(v1,v2) (v1[0]==v2[0]&&v1[1]==v2[1]&&v1[2]==v2[2]) + +#define VEC_NEAR_EQUAL(v1,v2) (GIM_NEAR_EQUAL(v1[0],v2[0])&&GIM_NEAR_EQUAL(v1[1],v2[1])&&GIM_NEAR_EQUAL(v1[2],v2[2])) + + +/// Vector cross +#define X_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = 0.0f; \ + dst[1] = -src[2]; \ + dst[2] = src[1]; \ +}\ + +#define Y_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = src[2]; \ + dst[1] = 0.0f; \ + dst[2] = -src[0]; \ +}\ + +#define Z_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = -src[1]; \ + dst[1] = src[0]; \ + dst[2] = 0.0f; \ +}\ + + + + + + +/// initialize matrix +#define IDENTIFY_MATRIX_3X3(m) \ +{ \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ +}\ + +/*! initialize matrix */ +#define IDENTIFY_MATRIX_4X4(m) \ +{ \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! initialize matrix */ +#define ZERO_MATRIX_4X4(m) \ +{ \ + m[0][0] = 0.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 0.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 0.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 0.0; \ +}\ + +/*! matrix rotation X */ +#define ROTX_CS(m,cosine,sine) \ +{ \ + /* rotation about the x-axis */ \ + \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = (cosine); \ + m[1][2] = (sine); \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = -(sine); \ + m[2][2] = (cosine); \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix rotation Y */ +#define ROTY_CS(m,cosine,sine) \ +{ \ + /* rotation about the y-axis */ \ + \ + m[0][0] = (cosine); \ + m[0][1] = 0.0; \ + m[0][2] = -(sine); \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = (sine); \ + m[2][1] = 0.0; \ + m[2][2] = (cosine); \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix rotation Z */ +#define ROTZ_CS(m,cosine,sine) \ +{ \ + /* rotation about the z-axis */ \ + \ + m[0][0] = (cosine); \ + m[0][1] = (sine); \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = -(sine); \ + m[1][1] = (cosine); \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix copy */ +#define COPY_MATRIX_2X2(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_2X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_3X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ + \ + b[2][0] = a[2][0]; \ + b[2][1] = a[2][1]; \ + b[2][2] = a[2][2]; \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_4X4(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + b[0][3] = a[0][3]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ + b[1][3] = a[1][3]; \ + \ + b[2][0] = a[2][0]; \ + b[2][1] = a[2][1]; \ + b[2][2] = a[2][2]; \ + b[2][3] = a[2][3]; \ + \ + b[3][0] = a[3][0]; \ + b[3][1] = a[3][1]; \ + b[3][2] = a[3][2]; \ + b[3][3] = a[3][3]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_2X2(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_3X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + b[0][2] = a[2][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[2][1]; \ + \ + b[2][0] = a[0][2]; \ + b[2][1] = a[1][2]; \ + b[2][2] = a[2][2]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_4X4(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + b[0][2] = a[2][0]; \ + b[0][3] = a[3][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[2][1]; \ + b[1][3] = a[3][1]; \ + \ + b[2][0] = a[0][2]; \ + b[2][1] = a[1][2]; \ + b[2][2] = a[2][2]; \ + b[2][3] = a[3][2]; \ + \ + b[3][0] = a[0][3]; \ + b[3][1] = a[1][3]; \ + b[3][2] = a[2][3]; \ + b[3][3] = a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_2X2(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_3X3(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + b[0][2] = (s) * a[0][2]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ + b[1][2] = (s) * a[1][2]; \ + \ + b[2][0] = (s) * a[2][0]; \ + b[2][1] = (s) * a[2][1]; \ + b[2][2] = (s) * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_4X4(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + b[0][2] = (s) * a[0][2]; \ + b[0][3] = (s) * a[0][3]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ + b[1][2] = (s) * a[1][2]; \ + b[1][3] = (s) * a[1][3]; \ + \ + b[2][0] = (s) * a[2][0]; \ + b[2][1] = (s) * a[2][1]; \ + b[2][2] = (s) * a[2][2]; \ + b[2][3] = (s) * a[2][3]; \ + \ + b[3][0] = s * a[3][0]; \ + b[3][1] = s * a[3][1]; \ + b[3][2] = s * a[3][2]; \ + b[3][3] = s * a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_VEC_MATRIX_2X2(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */ +#define SCALE_VEC_MATRIX_3X3(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + b[2][0] = svec[0] * a[2][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ + b[2][1] = svec[1] * a[2][1]; \ + \ + b[0][2] = svec[2] * a[0][2]; \ + b[1][2] = svec[2] * a[1][2]; \ + b[2][2] = svec[2] * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_VEC_MATRIX_4X4(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + b[2][0] = svec[0] * a[2][0]; \ + b[3][0] = svec[0] * a[3][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ + b[2][1] = svec[1] * a[2][1]; \ + b[3][1] = svec[1] * a[3][1]; \ + \ + b[0][2] = svec[2] * a[0][2]; \ + b[1][2] = svec[2] * a[1][2]; \ + b[2][2] = svec[2] * a[2][2]; \ + b[3][2] = svec[2] * a[3][2]; \ + \ + b[0][3] = svec[3] * a[0][3]; \ + b[1][3] = svec[3] * a[1][3]; \ + b[2][3] = svec[3] * a[2][3]; \ + b[3][3] = svec[3] * a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_2X2(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_3X3(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + b[0][2] += (s) * a[0][2]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ + b[1][2] += (s) * a[1][2]; \ + \ + b[2][0] += (s) * a[2][0]; \ + b[2][1] += (s) * a[2][1]; \ + b[2][2] += (s) * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_4X4(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + b[0][2] += (s) * a[0][2]; \ + b[0][3] += (s) * a[0][3]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ + b[1][2] += (s) * a[1][2]; \ + b[1][3] += (s) * a[1][3]; \ + \ + b[2][0] += (s) * a[2][0]; \ + b[2][1] += (s) * a[2][1]; \ + b[2][2] += (s) * a[2][2]; \ + b[2][3] += (s) * a[2][3]; \ + \ + b[3][0] += (s) * a[3][0]; \ + b[3][1] += (s) * a[3][1]; \ + b[3][2] += (s) * a[3][2]; \ + b[3][3] += (s) * a[3][3]; \ +}\ + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_2X2(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]; \ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]; \ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]; \ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]; \ + \ +}\ + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_3X3(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]; \ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]; \ + c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]; \ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]; \ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]; \ + c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]; \ + \ + c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]; \ + c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]; \ + c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]; \ +}\ + + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_4X4(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\ + c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\ + c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\ + c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\ + c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\ + \ + c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\ + c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\ + c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\ + c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\ + \ + c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\ + c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\ + c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\ + c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\ +}\ + + +/*! matrix times vector */ +#define MAT_DOT_VEC_2X2(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1]; \ +}\ + + +/*! matrix times vector */ +#define MAT_DOT_VEC_3X3(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2]; \ +}\ + + +/*! matrix times vector +v is a vec4f +*/ +#define MAT_DOT_VEC_4X4(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3]; \ + p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3]; \ +}\ + +/*! matrix times vector +v is a vec3f +and m is a mat4f
    +Last column is added as the position +*/ +#define MAT_DOT_VEC_3X4(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]; \ +}\ + + +/*! vector transpose times matrix */ +/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */ +#define VEC_DOT_MAT_3X3(p,v,m) \ +{ \ + p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]; \ + p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]; \ + p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]; \ +}\ + + +/*! affine matrix times vector */ +/** The matrix is assumed to be an affine matrix, with last two + * entries representing a translation */ +#define MAT_DOT_VEC_2X3(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]; \ +}\ + +//! Transform a plane +#define MAT_TRANSFORM_PLANE_4X4(pout,m,plane)\ +{ \ + pout[0] = m[0][0]*plane[0] + m[0][1]*plane[1] + m[0][2]*plane[2];\ + pout[1] = m[1][0]*plane[0] + m[1][1]*plane[1] + m[1][2]*plane[2];\ + pout[2] = m[2][0]*plane[0] + m[2][1]*plane[1] + m[2][2]*plane[2];\ + pout[3] = m[0][3]*pout[0] + m[1][3]*pout[1] + m[2][3]*pout[2] + plane[3];\ +}\ + + + +/** inverse transpose of matrix times vector + * + * This macro computes inverse transpose of matrix m, + * and multiplies vector v into it, to yeild vector p + * + * DANGER !!! Do Not use this on normal vectors!!! + * It will leave normals the wrong length !!! + * See macro below for use on normals. + */ +#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v) \ +{ \ + GREAL det; \ + \ + det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; \ + p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \ + p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \ + \ + /* if matrix not singular, and not orthonormal, then renormalize */ \ + if ((det!=1.0f) && (det != 0.0f)) { \ + det = 1.0f / det; \ + p[0] *= det; \ + p[1] *= det; \ + } \ +}\ + + +/** transform normal vector by inverse transpose of matrix + * and then renormalize the vector + * + * This macro computes inverse transpose of matrix m, + * and multiplies vector v into it, to yeild vector p + * Vector p is then normalized. + */ +#define NORM_XFORM_2X2(p,m,v) \ +{ \ + GREAL len; \ + \ + /* do nothing if off-diagonals are zero and diagonals are \ + * equal */ \ + if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \ + p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \ + p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \ + \ + len = p[0]*p[0] + p[1]*p[1]; \ + GIM_INV_SQRT(len,len); \ + p[0] *= len; \ + p[1] *= len; \ + } else { \ + VEC_COPY_2 (p, v); \ + } \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_2X2(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_3X3(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + m[0][2] = v[0] * t[2]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ + m[1][2] = v[1] * t[2]; \ + \ + m[2][0] = v[2] * t[0]; \ + m[2][1] = v[2] * t[1]; \ + m[2][2] = v[2] * t[2]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_4X4(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + m[0][2] = v[0] * t[2]; \ + m[0][3] = v[0] * t[3]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ + m[1][2] = v[1] * t[2]; \ + m[1][3] = v[1] * t[3]; \ + \ + m[2][0] = v[2] * t[0]; \ + m[2][1] = v[2] * t[1]; \ + m[2][2] = v[2] * t[2]; \ + m[2][3] = v[2] * t[3]; \ + \ + m[3][0] = v[3] * t[0]; \ + m[3][1] = v[3] * t[1]; \ + m[3][2] = v[3] * t[2]; \ + m[3][3] = v[3] * t[3]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_2X2(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_3X3(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + m[0][2] += v[0] * t[2]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ + m[1][2] += v[1] * t[2]; \ + \ + m[2][0] += v[2] * t[0]; \ + m[2][1] += v[2] * t[1]; \ + m[2][2] += v[2] * t[2]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_4X4(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + m[0][2] += v[0] * t[2]; \ + m[0][3] += v[0] * t[3]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ + m[1][2] += v[1] * t[2]; \ + m[1][3] += v[1] * t[3]; \ + \ + m[2][0] += v[2] * t[0]; \ + m[2][1] += v[2] * t[1]; \ + m[2][2] += v[2] * t[2]; \ + m[2][3] += v[2] * t[3]; \ + \ + m[3][0] += v[3] * t[0]; \ + m[3][1] += v[3] * t[1]; \ + m[3][2] += v[3] * t[2]; \ + m[3][3] += v[3] * t[3]; \ +}\ + + +/** determinant of matrix + * + * Computes determinant of matrix m, returning d + */ +#define DETERMINANT_2X2(d,m) \ +{ \ + d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \ +}\ + + +/** determinant of matrix + * + * Computes determinant of matrix m, returning d + */ +#define DETERMINANT_3X3(d,m) \ +{ \ + d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \ + d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \ + d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \ +}\ + + +/** i,j,th cofactor of a 4x4 matrix + * + */ +#define COFACTOR_4X4_IJ(fac,m,i,j) \ +{ \ + GUINT __ii[4], __jj[4], __k; \ + \ + for (__k=0; __k +*/ +#define INV_MAT_DOT_VEC_3X3(p,m,v) \ +{ \ + p[0] = MAT_DOT_COL(m,v,0); \ + p[1] = MAT_DOT_COL(m,v,1); \ + p[2] = MAT_DOT_COL(m,v,2); \ +}\ + + + +#endif // GIM_VECTOR_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_math.h b/Code/Physics/src/BulletCollision/Gimpact/gim_math.h new file mode 100644 index 00000000..939079e1 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_math.h @@ -0,0 +1,157 @@ +#ifndef GIM_MATH_H_INCLUDED +#define GIM_MATH_H_INCLUDED +/*! \file gim_math.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "LinearMath/btScalar.h" + + + +#define GREAL btScalar +#define GREAL2 double +#define GINT int +#define GUINT unsigned int +#define GSHORT short +#define GUSHORT unsigned short +#define GINT64 long long +#define GUINT64 unsigned long long + + + +#define G_PI 3.14159265358979f +#define G_HALF_PI 1.5707963f +//267948966 +#define G_TWO_PI 6.28318530f +//71795864 +#define G_ROOT3 1.73205f +#define G_ROOT2 1.41421f +#define G_UINT_INFINITY 0xffffffff //!< A very very high value +#define G_REAL_INFINITY FLT_MAX +#define G_SIGN_BITMASK 0x80000000 +#define G_EPSILON SIMD_EPSILON + + + +enum GIM_SCALAR_TYPES +{ + G_STYPE_REAL =0, + G_STYPE_REAL2, + G_STYPE_SHORT, + G_STYPE_USHORT, + G_STYPE_INT, + G_STYPE_UINT, + G_STYPE_INT64, + G_STYPE_UINT64 +}; + + + +#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f) +#define G_RADTODEG(X) ((X)*180.0f/3.1415926f) + +//! Integer representation of a floating-point value. +#define GIM_IR(x) ((GUINT&)(x)) + +//! Signed integer representation of a floating-point value. +#define GIM_SIR(x) ((GINT&)(x)) + +//! Absolute integer representation of a floating-point value +#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff) + +//! Floating-point representation of an integer value. +#define GIM_FR(x) ((GREAL&)(x)) + +#define GIM_MAX(a,b) (ab?b:a) + +#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c)) +#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c)) + +#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON) + +#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON) + +#define GIM_IS_POSISITVE(value) (value >= G_EPSILON) + +#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2)) + +///returns a clamped number +#define GIM_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) + +#define GIM_GREATER(x, y) btFabs(x) > (y) + +///Swap numbers +#define GIM_SWAP_NUMBERS(a,b){ \ + a = a+b; \ + b = a-b; \ + a = a-b; \ +}\ + +#define GIM_INV_SQRT(va,isva)\ +{\ + if(va<=0.0000001f)\ + {\ + isva = G_REAL_INFINITY;\ + }\ + else\ + {\ + GREAL _x = va * 0.5f;\ + GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\ + isva = GIM_FR(_y);\ + isva = isva * ( 1.5f - ( _x * isva * isva ) );\ + }\ +}\ + +#define GIM_SQRT(va,sva)\ +{\ + GIM_INV_SQRT(va,sva);\ + sva = 1.0f/sva;\ +}\ + +//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html +inline GREAL gim_inv_sqrt(GREAL f) +{ + GREAL r; + GIM_INV_SQRT(f,r); + return r; +} + +inline GREAL gim_sqrt(GREAL f) +{ + GREAL r; + GIM_SQRT(f,r); + return r; +} + + + +#endif // GIM_MATH_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_memory.cpp b/Code/Physics/src/BulletCollision/Gimpact/gim_memory.cpp new file mode 100644 index 00000000..1636eb78 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_memory.cpp @@ -0,0 +1,135 @@ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_memory.h" +#include "stdlib.h" + +#ifdef GIM_SIMD_MEMORY +#include "LinearMath/btAlignedAllocator.h" +#endif + +static gim_alloc_function *g_allocfn = 0; +static gim_alloca_function *g_allocafn = 0; +static gim_realloc_function *g_reallocfn = 0; +static gim_free_function *g_freefn = 0; + +void gim_set_alloc_handler (gim_alloc_function *fn) +{ + g_allocfn = fn; +} + +void gim_set_alloca_handler (gim_alloca_function *fn) +{ + g_allocafn = fn; +} + +void gim_set_realloc_handler (gim_realloc_function *fn) +{ + g_reallocfn = fn; +} + +void gim_set_free_handler (gim_free_function *fn) +{ + g_freefn = fn; +} + +gim_alloc_function *gim_get_alloc_handler() +{ + return g_allocfn; +} + +gim_alloca_function *gim_get_alloca_handler() +{ + return g_allocafn; +} + + +gim_realloc_function *gim_get_realloc_handler () +{ + return g_reallocfn; +} + + +gim_free_function *gim_get_free_handler () +{ + return g_freefn; +} + + +void * gim_alloc(size_t size) +{ + void * ptr; + if (g_allocfn) + { + ptr = g_allocfn(size); + } + else + { +#ifdef GIM_SIMD_MEMORY + ptr = btAlignedAlloc(size,16); +#else + ptr = malloc(size); +#endif + } + return ptr; +} + +void * gim_alloca(size_t size) +{ + if (g_allocafn) return g_allocafn(size); else return gim_alloc(size); +} + + +void * gim_realloc(void *ptr, size_t oldsize, size_t newsize) +{ + void * newptr = gim_alloc(newsize); + size_t copysize = oldsize + +#ifdef PREFETCH +#include // for prefetch +#define pfval 64 +#define pfval2 128 +//! Prefetch 64 +#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0) +//! Prefetch 128 +#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0) +#else +//! Prefetch 64 +#define pf(_x,_i) +//! Prefetch 128 +#define pf2(_x,_i) +#endif + + +///Functions for manip packed arrays of numbers +#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\ +{\ + for (GUINT _i_=0;_i_=SIMD_T_SIZE) + { + *(ui_dst_ptr++) = *(ui_src_ptr++); + copysize-=SIMD_T_SIZE; + } + if(copysize==0) return; +*/ + + char * c_src_ptr = (char *)src; + char * c_dst_ptr = (char *)dst; + while(copysize>0) + { + *(c_dst_ptr++) = *(c_src_ptr++); + copysize--; + } + return; +#else + memcpy(dst,src,copysize); +#endif +} + + + +template +inline void gim_swap_elements(T* _array,size_t _i,size_t _j) +{ + T _e_tmp_ = _array[_i]; + _array[_i] = _array[_j]; + _array[_j] = _e_tmp_; +} + + +template +inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j) +{ + char _e_tmp_[sizeof(T)]; + gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T)); + gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T)); + gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T)); +} + +template +inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j) +{ + char _e_tmp_[SIZE]; + _i*=SIZE; + _j*=SIZE; + gim_simd_memcpy(_e_tmp_,_array+_i,SIZE); + gim_simd_memcpy(_array+_i,_array+_j,SIZE); + gim_simd_memcpy(_array+_j,_e_tmp_,SIZE); +} + +#endif // GIM_MEMORY_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_radixsort.h b/Code/Physics/src/BulletCollision/Gimpact/gim_radixsort.h new file mode 100644 index 00000000..c246ef12 --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_radixsort.h @@ -0,0 +1,406 @@ +#ifndef GIM_RADIXSORT_H_INCLUDED +#define GIM_RADIXSORT_H_INCLUDED +/*! \file gim_radixsort.h +\author Francisco Leon Najera. +Based on the work of Michael Herf : "fast floating-point radix sort" +Avaliable on http://www.stereopsis.com/radix.html +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_memory.h" + +///Macros for sorting. +//! Prototype for comparators +class less_comparator +{ + public: + + template + inline int operator() ( const T& a, const Z& b ) + { + return ( ab?1:0)); + } +}; + +//! Prototype for comparators +class integer_comparator +{ + public: + + template + inline int operator() ( const T& a, const T& b ) + { + return (int)(a-b); + } +}; + +//!Prototype for getting the integer representation of an object +class uint_key_func +{ +public: + template + inline GUINT operator()( const T& a) + { + return (GUINT)a; + } +}; + + +//!Prototype for copying elements +class copy_elements_func +{ +public: + template + inline void operator()(T& a,T& b) + { + a = b; + } +}; + +//!Prototype for copying elements +class memcopy_elements_func +{ +public: + template + inline void operator()(T& a,T& b) + { + gim_simd_memcpy(&a,&b,sizeof(T)); + } +}; + + +//! @{ +struct GIM_RSORT_TOKEN +{ + GUINT m_key; + GUINT m_value; + GIM_RSORT_TOKEN() + { + } + GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken) + { + m_key = rtoken.m_key; + m_value = rtoken.m_value; + } + + inline bool operator <(const GIM_RSORT_TOKEN& other) const + { + return (m_key < other.m_key); + } + + inline bool operator >(const GIM_RSORT_TOKEN& other) const + { + return (m_key > other.m_key); + } +}; + +//! Prototype for comparators +class GIM_RSORT_TOKEN_COMPARATOR +{ + public: + + inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b ) + { + return (int)((a.m_key) - (b.m_key)); + } +}; + + + +#define kHist 2048 +// ---- utils for accessing 11-bit quantities +#define D11_0(x) (x & 0x7FF) +#define D11_1(x) (x >> 11 & 0x7FF) +#define D11_2(x) (x >> 22 ) + + + +///Radix sort for unsigned integer keys +inline void gim_radix_sort_rtokens( + GIM_RSORT_TOKEN * array, + GIM_RSORT_TOKEN * sorted, GUINT element_count) +{ + GUINT i; + GUINT b0[kHist * 3]; + GUINT *b1 = b0 + kHist; + GUINT *b2 = b1 + kHist; + for (i = 0; i < kHist * 3; ++i) + { + b0[i] = 0; + } + GUINT fi; + GUINT pos; + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + b0[D11_0(fi)] ++; + b1[D11_1(fi)] ++; + b2[D11_2(fi)] ++; + } + { + GUINT sum0 = 0, sum1 = 0, sum2 = 0; + GUINT tsum; + for (i = 0; i < kHist; ++i) + { + tsum = b0[i] + sum0; + b0[i] = sum0 - 1; + sum0 = tsum; + tsum = b1[i] + sum1; + b1[i] = sum1 - 1; + sum1 = tsum; + tsum = b2[i] + sum2; + b2[i] = sum2 - 1; + sum2 = tsum; + } + } + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + pos = D11_0(fi); + pos = ++b0[pos]; + sorted[pos].m_key = array[i].m_key; + sorted[pos].m_value = array[i].m_value; + } + for (i = 0; i < element_count; ++i) + { + fi = sorted[i].m_key; + pos = D11_1(fi); + pos = ++b1[pos]; + array[pos].m_key = sorted[i].m_key; + array[pos].m_value = sorted[i].m_value; + } + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + pos = D11_2(fi); + pos = ++b2[pos]; + sorted[pos].m_key = array[i].m_key; + sorted[pos].m_value = array[i].m_value; + } +} + + + + +/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN +/*! +*\param array Array of elements to sort +*\param sorted_tokens Tokens of sorted elements +*\param element_count element count +*\param uintkey_macro Functor which retrieves the integer representation of an array element +*/ +template +void gim_radix_sort_array_tokens( + T* array , + GIM_RSORT_TOKEN * sorted_tokens, + GUINT element_count,GETKEY_CLASS uintkey_macro) +{ + GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count); + for (GUINT _i=0;_i +void gim_radix_sort( + T * array, GUINT element_count, + GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro) +{ + GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count); + gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro); + T * _original_array = (T *) gim_alloc(sizeof(T)*element_count); + gim_simd_memcpy(_original_array,array,sizeof(T)*element_count); + for (GUINT _i=0;_i +bool gim_binary_search_ex( + const T* _array, GUINT _start_i, + GUINT _end_i,GUINT & _result_index, + const KEYCLASS & _search_key, + COMP_CLASS _comp_macro) +{ + GUINT _k; + int _comp_result; + GUINT _i = _start_i; + GUINT _j = _end_i+1; + while (_i < _j) + { + _k = (_j+_i-1)/2; + _comp_result = _comp_macro(_array[_k], _search_key); + if (_comp_result == 0) + { + _result_index = _k; + return true; + } + else if (_comp_result < 0) + { + _i = _k+1; + } + else + { + _j = _k; + } + } + _result_index = _i; + return false; +} + + + +//! Failsafe Iterative binary search,Template version +/*! +If the element is not found, it returns the nearest upper element position, may be the further position after the last element. +\param _array +\param _start_i the beginning of the array +\param _end_i the ending index of the array +\param _search_key Value to find +\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value +\return true if found, else false +*/ +template +bool gim_binary_search( + const T*_array,GUINT _start_i, + GUINT _end_i,const T & _search_key, + GUINT & _result_index) +{ + GUINT _i = _start_i; + GUINT _j = _end_i+1; + GUINT _k; + while(_i < _j) + { + _k = (_j+_i-1)/2; + if(_array[_k]==_search_key) + { + _result_index = _k; + return true; + } + else if (_array[_k]<_search_key) + { + _i = _k+1; + } + else + { + _j = _k; + } + } + _result_index = _i; + return false; +} + + + +///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ +template +void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc) +{ + /* PRE: a[k+1..N] is a heap */ + /* POST: a[k..N] is a heap */ + + T temp = pArr[k - 1]; + /* k has child(s) */ + while (k <= n/2) + { + int child = 2*k; + + if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0) + { + child++; + } + /* pick larger child */ + if (CompareFunc(temp , pArr[child - 1])<0) + { + /* move child up */ + pArr[k - 1] = pArr[child - 1]; + k = child; + } + else + { + break; + } + } + pArr[k - 1] = temp; +} /*downHeap*/ + + +template +void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc) +{ + /* sort a[0..N-1], N.B. 0 to N-1 */ + GUINT k; + GUINT n = element_count; + for (k = n/2; k > 0; k--) + { + gim_down_heap(pArr, k, n, CompareFunc); + } + + /* a[1..N] is now a heap */ + while ( n>=2 ) + { + gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */ + --n; + /* restore a[1..i-1] heap */ + gim_down_heap(pArr, 1, n, CompareFunc); + } +} + + + + +#endif // GIM_RADIXSORT_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.cpp new file mode 100644 index 00000000..f9727e1d --- /dev/null +++ b/Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.cpp @@ -0,0 +1,640 @@ + +/*! \file gim_tri_collision.h +\author Francisco Leon Najera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_tri_collision.h" + + +#define TRI_LOCAL_EPSILON 0.000001f +#define MIN_EDGE_EDGE_DIS 0.00001f + + +class GIM_TRIANGLE_CALCULATION_CACHE +{ +public: + GREAL margin; + btVector3 tu_vertices[3]; + btVector3 tv_vertices[3]; + btVector4 tu_plane; + btVector4 tv_plane; + btVector3 closest_point_u; + btVector3 closest_point_v; + btVector3 edge_edge_dir; + btVector3 distances; + GREAL du[4]; + GREAL du0du1; + GREAL du0du2; + GREAL dv[4]; + GREAL dv0dv1; + GREAL dv0dv2; + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + btVector3 contact_points[MAX_TRI_CLIPPING]; + + + + //! if returns false, the faces are paralele + SIMD_FORCE_INLINE bool compute_intervals( + const GREAL &D0, + const GREAL &D1, + const GREAL &D2, + const GREAL &D0D1, + const GREAL &D0D2, + GREAL & scale_edge0, + GREAL & scale_edge1, + GUINT &edge_index0, + GUINT &edge_index1) + { + if(D0D1>0.0f) + { + /* here we know that D0D2<=0.0 */ + /* that is D0, D1 are on the same side, D2 on the other or on the plane */ + scale_edge0 = -D2/(D0-D2); + scale_edge1 = -D1/(D2-D1); + edge_index0 = 2;edge_index1 = 1; + } + else if(D0D2>0.0f) + { + /* here we know that d0d1<=0.0 */ + scale_edge0 = -D0/(D1-D0); + scale_edge1 = -D1/(D2-D1); + edge_index0 = 0;edge_index1 = 1; + } + else if(D1*D2>0.0f || D0!=0.0f) + { + /* here we know that d0d1<=0.0 or that D0!=0.0 */ + scale_edge0 = -D0/(D1-D0); + scale_edge1 = -D2/(D0-D2); + edge_index0 = 0 ;edge_index1 = 2; + } + else + { + return false; + } + return true; + } + + + //! clip triangle + /*! + */ + SIMD_FORCE_INLINE GUINT clip_triangle( + const btVector4 & tri_plane, + const btVector3 * tripoints, + const btVector3 * srcpoints, + btVector3 * clip_points) + { + // edge 0 + + btVector4 edgeplane; + + EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); + + GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( + edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); + + if(clipped_count == 0) return 0; + + // edge 1 + + EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points,clipped_count,temp_points1); + + if(clipped_count == 0) return 0; + + // edge 2 + + EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points1,clipped_count,clip_points); + + return clipped_count; + + + /*GUINT i0 = (tri_plane.closestAxis()+1)%3; + GUINT i1 = (i0+1)%3; + // edge 0 + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + + GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC( + 0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points, + DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1)); + + + if(clipped_count == 0) return 0; + + // edge 1 + clipped_count = PLANE_CLIP_POLYGON_GENERIC( + 0,temp_points,clipped_count,temp_points1, + DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1)); + + if(clipped_count == 0) return 0; + + // edge 2 + clipped_count = PLANE_CLIP_POLYGON_GENERIC( + 0,temp_points1,clipped_count,clipped_points, + DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1)); + + return clipped_count;*/ + } + + SIMD_FORCE_INLINE void sort_isect( + GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1) + { + if(isect1=isect_v[1]) // face U casts face V + { + return 1; + } + else if(isect_v[0]<=isect_u[0]) // face V casts face U + { + return 2; + } + // closest points + closest_point_u = up_e1; + closest_point_v = vp_e0; + // calc edges and separation + + if(isect_u[1]+ MIN_EDGE_EDGE_DIS=isect_u[1]) // face V casts face U + { + return 2; + } + else if(isect_u[0]<=isect_v[0]) // face U casts face V + { + return 1; + } + // closest points + closest_point_u = up_e0; + closest_point_v = vp_e1; + // calc edges and separation + + if(isect_v[1]+MIN_EDGE_EDGE_DIS0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? + { + if(du[0]<0) //we need test behind the triangle plane + { + distances[0] = GIM_MAX3(du[0],du[1],du[2]); + distances[0] = -distances[0]; + if(distances[0]>margin) return false; //never intersect + + //reorder triangle v + VEC_SWAP(tv_vertices[0],tv_vertices[1]); + VEC_SCALE_4(tv_plane,-1.0f,tv_plane); + } + else + { + distances[0] = GIM_MIN3(du[0],du[1],du[2]); + if(distances[0]>margin) return false; //never intersect + } + } + else + { + //Look if we need to invert the triangle + distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid + + if(distances[0]<0.0f) + { + //reorder triangle v + VEC_SWAP(tv_vertices[0],tv_vertices[1]); + VEC_SCALE_4(tv_plane,-1.0f,tv_plane); + + distances[0] = GIM_MAX3(du[0],du[1],du[2]); + distances[0] = -distances[0]; + } + else + { + distances[0] = GIM_MIN3(du[0],du[1],du[2]); + } + } + + + // plane U vs V points + + TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane); + + dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]); + dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]); + dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]); + + dv0dv1 = dv[0] * dv[1]; + dv0dv2 = dv[0] * dv[2]; + + + if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? + { + if(dv[0]<0) //we need test behind the triangle plane + { + distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); + distances[1] = -distances[1]; + if(distances[1]>margin) return false; //never intersect + + //reorder triangle u + VEC_SWAP(tu_vertices[0],tu_vertices[1]); + VEC_SCALE_4(tu_plane,-1.0f,tu_plane); + } + else + { + distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); + if(distances[1]>margin) return false; //never intersect + } + } + else + { + //Look if we need to invert the triangle + distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid + + if(distances[1]<0.0f) + { + //reorder triangle v + VEC_SWAP(tu_vertices[0],tu_vertices[1]); + VEC_SCALE_4(tu_plane,-1.0f,tu_plane); + + distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); + distances[1] = -distances[1]; + } + else + { + distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); + } + } + + GUINT bl; + /* bl = cross_line_intersection_test(); + if(bl==3) + { + //take edge direction too + bl = distances.maxAxis(); + } + else + {*/ + bl = 0; + if(distances[0]margin) return false; + + contacts.m_penetration_depth = -distances[2] + margin; + contacts.m_points[0] = closest_point_v; + contacts.m_point_count = 1; + VEC_COPY(contacts.m_separating_normal,edge_edge_dir); + + return true; + } + + //clip face against other + + + GUINT point_count; + //TODO + if(bl == 0) //clip U points against V + { + point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points); + if(point_count == 0) return false; + contacts.merge_points(tv_plane,margin,contact_points,point_count); + } + else //clip V points against U + { + point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points); + if(point_count == 0) return false; + contacts.merge_points(tu_plane,margin,contact_points,point_count); + contacts.m_separating_normal *= -1.f; + } + if(contacts.m_point_count == 0) return false; + return true; + } + +}; + + +/*class GIM_TRIANGLE_CALCULATION_CACHE +{ +public: + GREAL margin; + GUINT clipped_count; + btVector3 tu_vertices[3]; + btVector3 tv_vertices[3]; + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + btVector3 clipped_points[MAX_TRI_CLIPPING]; + GIM_TRIANGLE_CONTACT_DATA contacts1; + GIM_TRIANGLE_CONTACT_DATA contacts2; + + + //! clip triangle + GUINT clip_triangle( + const btVector4 & tri_plane, + const btVector3 * tripoints, + const btVector3 * srcpoints, + btVector3 * clipped_points) + { + // edge 0 + + btVector4 edgeplane; + + EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); + + GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( + edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); + + if(clipped_count == 0) return 0; + + // edge 1 + + EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points,clipped_count,temp_points1); + + if(clipped_count == 0) return 0; + + // edge 2 + + EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points1,clipped_count,clipped_points); + + return clipped_count; + } + + + + + //! collides only on one side + bool triangle_collision( + const btVector3 & u0, + const btVector3 & u1, + const btVector3 & u2, + GREAL margin_u, + const btVector3 & v0, + const btVector3 & v1, + const btVector3 & v2, + GREAL margin_v, + GIM_TRIANGLE_CONTACT_DATA & contacts) + { + + margin = margin_u + margin_v; + + + tu_vertices[0] = u0; + tu_vertices[1] = u1; + tu_vertices[2] = u2; + + tv_vertices[0] = v0; + tv_vertices[1] = v1; + tv_vertices[2] = v2; + + //create planes + // plane v vs U points + + + TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal); + + clipped_count = clip_triangle( + contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points); + + if(clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); + if(contacts1.m_point_count == 0) return false; // too far + + //Normal pointing to triangle1 + //contacts1.m_separating_normal *= -1.f; + + //Clip tri1 by tri2 edges + + TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal); + + clipped_count = clip_triangle( + contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points); + + if(clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); + if(contacts2.m_point_count == 0) return false; // too far + + contacts2.m_separating_normal *= -1.f; + + ////check most dir for contacts + if(contacts2.m_penetration_depth + SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane, + GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func) + { + m_point_count = 0; + m_penetration_depth= -1000.0f; + + GUINT point_indices[MAX_TRI_CLIPPING]; + + GUINT _k; + + for(_k=0;_k=0.0f) + { + if(_dist>m_penetration_depth) + { + m_penetration_depth = _dist; + point_indices[0] = _k; + m_point_count=1; + } + else if((_dist+G_EPSILON)>=m_penetration_depth) + { + point_indices[m_point_count] = _k; + m_point_count++; + } + } + } + + for( _k=0;_k u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1] + + --> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1] + + --> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2] + + --> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2] + + --> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1] + + --> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) + +if 0.0<= u+v <=1.0 then they are inside of triangle + + \return false if the point is outside of triangle.This function doesn't take the margin + */ + SIMD_FORCE_INLINE bool get_uv_parameters( + const btVector3 & point, + const btVector3 & tri_plane, + GREAL & u, GREAL & v) const + { + btVector3 _axe1 = m_vertices[1]-m_vertices[0]; + btVector3 _axe2 = m_vertices[2]-m_vertices[0]; + btVector3 _vecproj = point - m_vertices[0]; + GUINT _i1 = (tri_plane.closestAxis()+1)%3; + GUINT _i2 = (_i1+1)%3; + if(btFabs(_axe2[_i2])G_EPSILON) + { + return false; + } + } + return true; + } + + //! is point in triangle beam? + /*! + Test if point is in triangle, with m_margin tolerance + */ + SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const + { + //Test with edge 0 + btVector4 edge_plane; + this->get_edge_plane(0,tri_normal,edge_plane); + GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + + this->get_edge_plane(1,tri_normal,edge_plane); + dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + + this->get_edge_plane(2,tri_normal,edge_plane); + dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + return true; + } + + + //! Bidireccional ray collision + SIMD_FORCE_INLINE bool ray_collision( + const btVector3 & vPoint, + const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal, + GREAL & tparam, GREAL tmax = G_REAL_INFINITY) + { + btVector4 faceplane; + { + btVector3 dif1 = m_vertices[1] - m_vertices[0]; + btVector3 dif2 = m_vertices[2] - m_vertices[0]; + VEC_CROSS(faceplane,dif1,dif2); + faceplane[3] = m_vertices[0].dot(faceplane); + } + + GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax); + if(res == 0) return false; + if(! is_point_inside(pout,faceplane)) return false; + + if(res==2) //invert normal + { + triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]); + } + else + { + triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]); + } + + VEC_NORMALIZE(triangle_normal); + + return true; + } + + + //! one direccion ray collision + SIMD_FORCE_INLINE bool ray_collision_front_side( + const btVector3 & vPoint, + const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal, + GREAL & tparam, GREAL tmax = G_REAL_INFINITY) + { + btVector4 faceplane; + { + btVector3 dif1 = m_vertices[1] - m_vertices[0]; + btVector3 dif2 = m_vertices[2] - m_vertices[0]; + VEC_CROSS(faceplane,dif1,dif2); + faceplane[3] = m_vertices[0].dot(faceplane); + } + + GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax); + if(res != 1) return false; + + if(!is_point_inside(pout,faceplane)) return false; + + triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]); + + VEC_NORMALIZE(triangle_normal); + + return true; + } + +}; + + + + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp new file mode 100644 index 00000000..940282f5 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -0,0 +1,242 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btContinuousConvexCollision.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "LinearMath/btTransformUtil.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "btGjkPairDetector.h" +#include "btPointCollector.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + + + +btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_simplexSolver(simplexSolver), +m_penetrationDepthSolver(penetrationDepthSolver), +m_convexA(convexA),m_convexB1(convexB),m_planeShape(0) +{ +} + + +btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape* convexA,const btStaticPlaneShape* plane) +:m_simplexSolver(0), +m_penetrationDepthSolver(0), +m_convexA(convexA),m_convexB1(0),m_planeShape(plane) +{ +} + + +/// This maximum should not be necessary. It allows for untested/degenerate cases in production code. +/// You don't want your game ever to lock-up. +#define MAX_ITERATIONS 64 + +void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector) +{ + if (m_convexB1) + { + m_simplexSolver->reset(); + btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = transA; + input.m_transformB = transB; + gjk.getClosestPoints(input,pointCollector,0); + } else + { + //convex versus plane + const btConvexShape* convexShape = m_convexA; + const btStaticPlaneShape* planeShape = m_planeShape; + + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + btTransform convexWorldTransform = transA; + btTransform convexInPlaneTrans; + convexInPlaneTrans= transB.inverse() * convexWorldTransform; + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * transB; + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected; + btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal; + + pointCollector.addContactPoint( + normalOnSurfaceB, + vtxInPlaneWorld, + distance); + } +} + +bool btContinuousConvexCollision::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + + /// compute linear and angular velocity for this interval, to interpolate + btVector3 linVelA,angVelA,linVelB,angVelB; + btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); + btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); + + + btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); + btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f; + + btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + + btScalar relLinVelocLength = (linVelB-linVelA).length(); + + if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) + return false; + + + + btScalar lambda = btScalar(0.); + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + + int numIter = 0; + //first solution, using GJK + + + btScalar radius = 0.001f; +// result.drawCoordSystem(sphereTr); + + btPointCollector pointCollector1; + + { + + computeClosestPoints(fromA,fromB,pointCollector1); + + hasResult = pointCollector1.m_hasResult; + c = pointCollector1.m_pointInWorld; + } + + if (hasResult) + { + btScalar dist; + dist = pointCollector1.m_distance + result.m_allowedPenetration; + n = pointCollector1.m_normalOnBInWorld; + btScalar projectedLinearVelocity = relLinVel.dot(n); + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) + return false; + + //not close enough + while (dist > radius) + { + if (result.m_debugDrawer) + { + result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1)); + } + btScalar dLambda = btScalar(0.); + + projectedLinearVelocity = relLinVel.dot(n); + + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) + return false; + + dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); + + + + lambda = lambda + dLambda; + + if (lambda > btScalar(1.)) + return false; + + if (lambda < btScalar(0.)) + return false; + + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); + break; + } + lastLambda = lambda; + + + + //interpolate to next lambda + btTransform interpolatedTransA,interpolatedTransB,relativeTrans; + + btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA); + btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB); + relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA); + + if (result.m_debugDrawer) + { + result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0)); + } + + result.DebugDraw( lambda ); + + btPointCollector pointCollector; + computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector); + + if (pointCollector.m_hasResult) + { + dist = pointCollector.m_distance+result.m_allowedPenetration; + c = pointCollector.m_pointInWorld; + n = pointCollector.m_normalOnBInWorld; + } else + { + result.reportFailure(-1, numIter); + return false; + } + + numIter++; + if (numIter > maxIter) + { + result.reportFailure(-2, numIter); + return false; + } + } + + result.m_fraction = lambda; + result.m_normal = n; + result.m_hitPoint = c; + return true; + } + + return false; + +} + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h new file mode 100644 index 00000000..bdc0572f --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -0,0 +1,59 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H +#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H + +#include "btConvexCast.h" +#include "btSimplexSolverInterface.h" +class btConvexPenetrationDepthSolver; +class btConvexShape; +class btStaticPlaneShape; + +/// btContinuousConvexCollision implements angular and linear time of impact for convex objects. +/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). +/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent. +/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops +class btContinuousConvexCollision : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_penetrationDepthSolver; + const btConvexShape* m_convexA; + //second object is either a convex or a plane (code sharing) + const btConvexShape* m_convexB1; + const btStaticPlaneShape* m_planeShape; + + void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector); + +public: + + btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + + btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane ); + + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + + +}; + + +#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp new file mode 100644 index 00000000..d2a1310b --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp @@ -0,0 +1,20 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConvexCast.h" + +btConvexCast::~btConvexCast() +{ +} diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h new file mode 100644 index 00000000..bfd79d03 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -0,0 +1,73 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_CONVEX_CAST_H +#define BT_CONVEX_CAST_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" +class btMinkowskiSumShape; +#include "LinearMath/btIDebugDraw.h" + +/// btConvexCast is an interface for Casting +class btConvexCast +{ +public: + + + virtual ~btConvexCast(); + + ///RayResult stores the closest result + /// alternatively, add a callback method to decide about closest/all results + struct CastResult + { + //virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0; + + virtual void DebugDraw(btScalar fraction) {(void)fraction;} + virtual void drawCoordSystem(const btTransform& trans) {(void)trans;} + virtual void reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;} + CastResult() + :m_fraction(btScalar(BT_LARGE_FLOAT)), + m_debugDrawer(0), + m_allowedPenetration(btScalar(0)) + { + } + + + virtual ~CastResult() {}; + + btTransform m_hitTransformA; + btTransform m_hitTransformB; + btVector3 m_normal; + btVector3 m_hitPoint; + btScalar m_fraction; //input and output + btIDebugDraw* m_debugDrawer; + btScalar m_allowedPenetration; + + }; + + + /// cast a convex against another convex object + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) = 0; +}; + +#endif //BT_CONVEX_CAST_H diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h new file mode 100644 index 00000000..29620abf --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_CONVEX_PENETRATION_DEPTH_H +#define BT_CONVEX_PENETRATION_DEPTH_H + +class btVector3; +#include "btSimplexSolverInterface.h" +class btConvexShape; +class btTransform; + +///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. +class btConvexPenetrationDepthSolver +{ +public: + + virtual ~btConvexPenetrationDepthSolver() {}; + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw) = 0; + + +}; +#endif //BT_CONVEX_PENETRATION_DEPTH_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h new file mode 100644 index 00000000..46ce1ab7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -0,0 +1,88 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H +#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" + +/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations +/// This interface allows to query for closest points and penetration depth between two (convex) objects +/// the closest point is on the second object (B), and the normal points from the surface on B towards A. +/// distance is between closest points on B and closest point on A. So you can calculate closest point on A +/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB +struct btDiscreteCollisionDetectorInterface +{ + + struct Result + { + + virtual ~Result(){} + + ///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner + virtual void setShapeIdentifiersA(int partId0,int index0)=0; + virtual void setShapeIdentifiersB(int partId1,int index1)=0; + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0; + }; + + struct ClosestPointInput + { + ClosestPointInput() + :m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT)) + { + } + + btTransform m_transformA; + btTransform m_transformB; + btScalar m_maximumDistanceSquared; + }; + + virtual ~btDiscreteCollisionDetectorInterface() {}; + + // + // give either closest points (distance > 0) or penetration (distance) + // the normal always points from B towards A + // + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0; + +}; + +struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result +{ + btVector3 m_normalOnSurfaceB; + btVector3 m_closestPointInB; + btScalar m_distance; //negative means penetration ! + + btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT)) + { + + } + virtual ~btStorageResult() {}; + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + if (depth < m_distance) + { + m_normalOnSurfaceB = normalOnBInWorld; + m_closestPointInB = pointInWorld; + m_distance = depth; + } + } +}; + +#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp new file mode 100644 index 00000000..bef697a0 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -0,0 +1,176 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "btGjkConvexCast.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "btGjkPairDetector.h" +#include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif + +btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +:m_simplexSolver(simplexSolver), +m_convexA(convexA), +m_convexB(convexB) +{ +} + +bool btGjkConvexCast::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + + m_simplexSolver->reset(); + + /// compute linear velocity for this interval, to interpolate + //assume no rotation/angular velocity, assert here? + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); + + btScalar radius = btScalar(0.001); + btScalar lambda = btScalar(0.); + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + btVector3 r = (linVelA-linVelB); + + btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + + int numIter = 0; + //first solution, using GJK + + + btTransform identityTrans; + identityTrans.setIdentity(); + + +// result.drawCoordSystem(sphereTr); + + btPointCollector pointCollector; + + + btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + + //we don't use margins during CCD + // gjk.setIgnoreMargin(true); + + input.m_transformA = fromA; + input.m_transformB = fromB; + gjk.getClosestPoints(input,pointCollector,0); + + hasResult = pointCollector.m_hasResult; + c = pointCollector.m_pointInWorld; + + if (hasResult) + { + btScalar dist; + dist = pointCollector.m_distance; + n = pointCollector.m_normalOnBInWorld; + + + + //not close enough + while (dist > radius) + { + numIter++; + if (numIter > maxIter) + { + return false; //todo: report a failure + } + btScalar dLambda = btScalar(0.); + + btScalar projectedLinearVelocity = r.dot(n); + + dLambda = dist / (projectedLinearVelocity); + + lambda = lambda - dLambda; + + if (lambda > btScalar(1.)) + return false; + + if (lambda < btScalar(0.)) + return false; + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); + break; + } + lastLambda = lambda; + + //interpolate to next lambda + result.DebugDraw( lambda ); + input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + + gjk.getClosestPoints(input,pointCollector,0); + if (pointCollector.m_hasResult) + { + if (pointCollector.m_distance < btScalar(0.)) + { + result.m_fraction = lastLambda; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n; + result.m_hitPoint = pointCollector.m_pointInWorld; + return true; + } + c = pointCollector.m_pointInWorld; + n = pointCollector.m_normalOnBInWorld; + dist = pointCollector.m_distance; + } else + { + //?? + return false; + } + + } + + //is n normalized? + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (n.dot(r)>=-result.m_allowedPenetration) + return false; + + result.m_fraction = lambda; + result.m_normal = n; + result.m_hitPoint = c; + return true; + } + + return false; + + +} + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h new file mode 100644 index 00000000..6a42ee63 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GJK_CONVEX_CAST_H +#define BT_GJK_CONVEX_CAST_H + +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btVector3.h" +#include "btConvexCast.h" +class btConvexShape; +class btMinkowskiSumShape; +#include "btSimplexSolverInterface.h" + +///GjkConvexCast performs a raycast on a convex object using support mapping. +class btGjkConvexCast : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; + +public: + + btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + + /// cast a convex against another convex object + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + +}; + +#endif //BT_GJK_CONVEX_CAST_H diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp new file mode 100644 index 00000000..3268f06c --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -0,0 +1,1031 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "btGjkEpa2.h" + +#if defined(DEBUG) || defined (_DEBUG) +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +#endif //__SPU__ +#endif + +namespace gjkepa2_impl +{ + + // Config + + /* GJK */ +#define GJK_MAX_ITERATIONS 128 +#define GJK_ACCURARY ((btScalar)0.0001) +#define GJK_MIN_DISTANCE ((btScalar)0.0001) +#define GJK_DUPLICATED_EPS ((btScalar)0.0001) +#define GJK_SIMPLEX2_EPS ((btScalar)0.0) +#define GJK_SIMPLEX3_EPS ((btScalar)0.0) +#define GJK_SIMPLEX4_EPS ((btScalar)0.0) + + /* EPA */ +#define EPA_MAX_VERTICES 64 +#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) +#define EPA_MAX_ITERATIONS 255 +#define EPA_ACCURACY ((btScalar)0.0001) +#define EPA_FALLBACK (10*EPA_ACCURACY) +#define EPA_PLANE_EPS ((btScalar)0.00001) +#define EPA_INSIDE_EPS ((btScalar)0.01) + + + // Shorthands + typedef unsigned int U; + typedef unsigned char U1; + + // MinkowskiDiff + struct MinkowskiDiff + { + const btConvexShape* m_shapes[2]; + btMatrix3x3 m_toshape1; + btTransform m_toshape0; +#ifdef __SPU__ + bool m_enableMargin; +#else + btVector3 (btConvexShape::*Ls)(const btVector3&) const; +#endif//__SPU__ + + + MinkowskiDiff() + { + + } +#ifdef __SPU__ + void EnableMargin(bool enable) + { + m_enableMargin = enable; + } + inline btVector3 Support0(const btVector3& d) const + { + if (m_enableMargin) + { + return m_shapes[0]->localGetSupportVertexNonVirtual(d); + } else + { + return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d); + } + } + inline btVector3 Support1(const btVector3& d) const + { + if (m_enableMargin) + { + return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d)); + } else + { + return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d)); + } + } +#else + void EnableMargin(bool enable) + { + if(enable) + Ls=&btConvexShape::localGetSupportVertexNonVirtual; + else + Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual; + } + inline btVector3 Support0(const btVector3& d) const + { + return(((m_shapes[0])->*(Ls))(d)); + } + inline btVector3 Support1(const btVector3& d) const + { + return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); + } +#endif //__SPU__ + + inline btVector3 Support(const btVector3& d) const + { + return(Support0(d)-Support1(-d)); + } + btVector3 Support(const btVector3& d,U index) const + { + if(index) + return(Support1(d)); + else + return(Support0(d)); + } + }; + + typedef MinkowskiDiff tShape; + + + // GJK + struct GJK + { + /* Types */ + struct sSV + { + btVector3 d,w; + }; + struct sSimplex + { + sSV* c[4]; + btScalar p[4]; + U rank; + }; + struct eStatus { enum _ { + Valid, + Inside, + Failed };}; + /* Fields */ + tShape m_shape; + btVector3 m_ray; + btScalar m_distance; + sSimplex m_simplices[2]; + sSV m_store[4]; + sSV* m_free[4]; + U m_nfree; + U m_current; + sSimplex* m_simplex; + eStatus::_ m_status; + /* Methods */ + GJK() + { + Initialize(); + } + void Initialize() + { + m_ray = btVector3(0,0,0); + m_nfree = 0; + m_status = eStatus::Failed; + m_current = 0; + m_distance = 0; + } + eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess) + { + U iterations=0; + btScalar sqdist=0; + btScalar alpha=0; + btVector3 lastw[4]; + U clastw=0; + /* Initialize solver */ + m_free[0] = &m_store[0]; + m_free[1] = &m_store[1]; + m_free[2] = &m_store[2]; + m_free[3] = &m_store[3]; + m_nfree = 4; + m_current = 0; + m_status = eStatus::Valid; + m_shape = shapearg; + m_distance = 0; + /* Initialize simplex */ + m_simplices[0].rank = 0; + m_ray = guess; + const btScalar sqrl= m_ray.length2(); + appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0)); + m_simplices[0].p[0] = 1; + m_ray = m_simplices[0].c[0]->w; + sqdist = sqrl; + lastw[0] = + lastw[1] = + lastw[2] = + lastw[3] = m_ray; + /* Loop */ + do { + const U next=1-m_current; + sSimplex& cs=m_simplices[m_current]; + sSimplex& ns=m_simplices[next]; + /* Check zero */ + const btScalar rl=m_ray.length(); + if(rlw; + bool found=false; + for(U i=0;i<4;++i) + { + if((w-lastw[i]).length2()w, + cs.c[1]->w, + weights,mask);break; + case 3: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + weights,mask);break; + case 4: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + cs.c[3]->w, + weights,mask);break; + } + if(sqdist>=0) + {/* Valid */ + ns.rank = 0; + m_ray = btVector3(0,0,0); + m_current = next; + for(U i=0,ni=cs.rank;iw*weights[i]; + } + else + { + m_free[m_nfree++] = cs.c[i]; + } + } + if(mask==15) m_status=eStatus::Inside; + } + else + {/* Return old simplex */ + removevertice(m_simplices[m_current]); + break; + } + m_status=((++iterations)rank) + { + case 1: + { + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + appendvertice(*m_simplex, axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 2: + { + const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + const btVector3 p=btCross(d,axis); + if(p.length2()>0) + { + appendvertice(*m_simplex, p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + } + break; + case 3: + { + const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w, + m_simplex->c[2]->w-m_simplex->c[0]->w); + if(n.length2()>0) + { + appendvertice(*m_simplex,n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 4: + { + if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, + m_simplex->c[1]->w-m_simplex->c[3]->w, + m_simplex->c[2]->w-m_simplex->c[3]->w))>0) + return(true); + } + break; + } + return(false); + } + /* Internals */ + void getsupport(const btVector3& d,sSV& sv) const + { + sv.d = d/d.length(); + sv.w = m_shape.Support(sv.d); + } + void removevertice(sSimplex& simplex) + { + m_free[m_nfree++]=simplex.c[--simplex.rank]; + } + void appendvertice(sSimplex& simplex,const btVector3& v) + { + simplex.p[simplex.rank]=0; + simplex.c[simplex.rank]=m_free[--m_nfree]; + getsupport(v,*simplex.c[simplex.rank++]); + } + static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c) + { + return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()- + a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+ + a.x()*b.y()*c.z()-a.z()*b.y()*c.x()); + } + static btScalar projectorigin( const btVector3& a, + const btVector3& b, + btScalar* w,U& m) + { + const btVector3 d=b-a; + const btScalar l=d.length2(); + if(l>GJK_SIMPLEX2_EPS) + { + const btScalar t(l>0?-btDot(a,d)/l:0); + if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); } + else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); } + else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); } + } + return(-1); + } + static btScalar projectorigin( const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar* w,U& m) + { + static const U imd3[]={1,2,0}; + const btVector3* vt[]={&a,&b,&c}; + const btVector3 dl[]={a-b,b-c,c-a}; + const btVector3 n=btCross(dl[0],dl[1]); + const btScalar l=n.length2(); + if(l>GJK_SIMPLEX3_EPS) + { + btScalar mindist=-1; + btScalar subw[2]={0.f,0.f}; + U subm(0); + for(U i=0;i<3;++i) + { + if(btDot(*vt[i],btCross(dl[i],n))>0) + { + const U j=imd3[i]; + const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm)); + if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) + { + btScalar mindist=-1; + btScalar subw[3]={0.f,0.f,0.f}; + U subm(0); + for(U i=0;i<3;++i) + { + const U j=imd3[i]; + const btScalar s=vl*btDot(d,btCross(dl[i],dl[j])); + if(s>0) + { + const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm); + if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; + fb->e[eb]=(U1)ea;fb->f[eb]=fa; + } + static inline void append(sList& list,sFace* face) + { + face->l[0] = 0; + face->l[1] = list.root; + if(list.root) list.root->l[0]=face; + list.root = face; + ++list.count; + } + static inline void remove(sList& list,sFace* face) + { + if(face->l[1]) face->l[1]->l[0]=face->l[0]; + if(face->l[0]) face->l[0]->l[1]=face->l[1]; + if(face==list.root) list.root=face->l[1]; + --list.count; + } + + + void Initialize() + { + m_status = eStatus::Failed; + m_normal = btVector3(0,0,0); + m_depth = 0; + m_nextsv = 0; + for(U i=0;i1)&&gjk.EncloseOrigin()) + { + + /* Clean up */ + while(m_hull.root) + { + sFace* f = m_hull.root; + remove(m_hull,f); + append(m_stock,f); + } + m_status = eStatus::Valid; + m_nextsv = 0; + /* Orient simplex */ + if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, + simplex.c[1]->w-simplex.c[3]->w, + simplex.c[2]->w-simplex.c[3]->w)<0) + { + btSwap(simplex.c[0],simplex.c[1]); + btSwap(simplex.p[0],simplex.p[1]); + } + /* Build initial hull */ + sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), + newface(simplex.c[1],simplex.c[0],simplex.c[3],true), + newface(simplex.c[2],simplex.c[1],simplex.c[3],true), + newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; + if(m_hull.count==4) + { + sFace* best=findbest(); + sFace outer=*best; + U pass=0; + U iterations=0; + bind(tetra[0],0,tetra[1],0); + bind(tetra[0],1,tetra[2],0); + bind(tetra[0],2,tetra[3],0); + bind(tetra[1],1,tetra[3],2); + bind(tetra[1],2,tetra[2],1); + bind(tetra[2],2,tetra[3],1); + m_status=eStatus::Valid; + for(;iterationspass = (U1)(++pass); + gjk.getsupport(best->n,*w); + const btScalar wdist=btDot(best->n,w->w)-best->d; + if(wdist>EPA_ACCURACY) + { + for(U j=0;(j<3)&&valid;++j) + { + valid&=expand( pass,w, + best->f[j],best->e[j], + horizon); + } + if(valid&&(horizon.nf>=3)) + { + bind(horizon.cf,1,horizon.ff,2); + remove(m_hull,best); + append(m_stock,best); + best=findbest(); + outer=*best; + } else { m_status=eStatus::InvalidHull;break; } + } else { m_status=eStatus::AccuraryReached;break; } + } else { m_status=eStatus::OutOfVertices;break; } + } + const btVector3 projection=outer.n*outer.d; + m_normal = outer.n; + m_depth = outer.d; + m_result.rank = 3; + m_result.c[0] = outer.c[0]; + m_result.c[1] = outer.c[1]; + m_result.c[2] = outer.c[2]; + m_result.p[0] = btCross( outer.c[1]->w-projection, + outer.c[2]->w-projection).length(); + m_result.p[1] = btCross( outer.c[2]->w-projection, + outer.c[0]->w-projection).length(); + m_result.p[2] = btCross( outer.c[0]->w-projection, + outer.c[1]->w-projection).length(); + const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; + m_result.p[0] /= sum; + m_result.p[1] /= sum; + m_result.p[2] /= sum; + return(m_status); + } + } + /* Fallback */ + m_status = eStatus::FallBack; + m_normal = -guess; + const btScalar nl=m_normal.length(); + if(nl>0) + m_normal = m_normal/nl; + else + m_normal = btVector3(1,0,0); + m_depth = 0; + m_result.rank=1; + m_result.c[0]=simplex.c[0]; + m_result.p[0]=1; + return(m_status); + } + bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist) + { + const btVector3 ba = b->w - a->w; + const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane + const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required + + if(a_dot_nab < 0) + { + // Outside of edge a->b + + const btScalar ba_l2 = ba.length2(); + const btScalar a_dot_ba = btDot(a->w, ba); + const btScalar b_dot_ba = btDot(b->w, ba); + + if(a_dot_ba > 0) + { + // Pick distance vertex a + dist = a->w.length(); + } + else if(b_dot_ba < 0) + { + // Pick distance vertex b + dist = b->w.length(); + } + else + { + // Pick distance to edge a->b + const btScalar a_dot_b = btDot(a->w, b->w); + dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0)); + } + + return true; + } + + return false; + } + sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) + { + if(m_stock.root) + { + sFace* face=m_stock.root; + remove(m_stock,face); + append(m_hull,face); + face->pass = 0; + face->c[0] = a; + face->c[1] = b; + face->c[2] = c; + face->n = btCross(b->w-a->w,c->w-a->w); + const btScalar l=face->n.length(); + const bool v=l>EPA_ACCURACY; + + if(v) + { + if(!(getedgedist(face, a, b, face->d) || + getedgedist(face, b, c, face->d) || + getedgedist(face, c, a, face->d))) + { + // Origin projects to the interior of the triangle + // Use distance to triangle plane + face->d = btDot(a->w, face->n) / l; + } + + face->n /= l; + if(forced || (face->d >= -EPA_PLANE_EPS)) + { + return face; + } + else + m_status=eStatus::NonConvex; + } + else + m_status=eStatus::Degenerated; + + remove(m_hull, face); + append(m_stock, face); + return 0; + + } + m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces; + return 0; + } + sFace* findbest() + { + sFace* minf=m_hull.root; + btScalar mind=minf->d*minf->d; + for(sFace* f=minf->l[1];f;f=f->l[1]) + { + const btScalar sqd=f->d*f->d; + if(sqdpass!=pass) + { + const U e1=i1m3[e]; + if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) + { + sFace* nf=newface(f->c[e1],f->c[e],w,false); + if(nf) + { + bind(nf,0,f,e); + if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; + horizon.cf=nf; + ++horizon.nf; + return(true); + } + } + else + { + const U e2=i2m3[e]; + f->pass = (U1)pass; + if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& + expand(pass,w,f->f[e2],f->e[e2],horizon)) + { + remove(m_hull,f); + append(m_stock,f); + return(true); + } + } + } + return(false); + } + + }; + + // + static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + btGjkEpaSolver2::sResults& results, + tShape& shape, + bool withmargins) + { + /* Results */ + results.witnesses[0] = + results.witnesses[1] = btVector3(0,0,0); + results.status = btGjkEpaSolver2::sResults::Separated; + /* Shape */ + shape.m_shapes[0] = shape0; + shape.m_shapes[1] = shape1; + shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis()); + shape.m_toshape0 = wtrs0.inverseTimes(wtrs1); + shape.EnableMargin(withmargins); + } + +} + +// +// Api +// + +using namespace gjkepa2_impl; + +// +int btGjkEpaSolver2::StackSizeRequirement() +{ + return(sizeof(GJK)+sizeof(EPA)); +} + +// +bool btGjkEpaSolver2::Distance( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ + tShape shape; + Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); + if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + results.normal = w0-w1; + results.distance = results.normal.length(); + results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; + return(true); + } + else + { + results.status = gjk_status==GJK::eStatus::Inside? + sResults::Penetrating : + sResults::GJK_Failed ; + return(false); + } +} + +// +bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins) +{ + tShape shape; + Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); + switch(gjk_status) + { + case GJK::eStatus::Inside: + { + EPA epa; + EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); + if(epa_status!=EPA::eStatus::Failed) + { + btVector3 w0=btVector3(0,0,0); + for(U i=0;id,0)*epa.m_result.p[i]; + } + results.status = sResults::Penetrating; + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); + results.normal = -epa.m_normal; + results.distance = -epa.m_depth; + return(true); + } else results.status=sResults::EPA_Failed; + } + break; + case GJK::eStatus::Failed: + results.status=sResults::GJK_Failed; + break; + default: + { + } + } + return(false); +} + +#ifndef __SPU__ +// +btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, + btScalar margin, + const btConvexShape* shape0, + const btTransform& wtrs0, + sResults& results) +{ + tShape shape; + btSphereShape shape1(margin); + btTransform wtrs1(btQuaternion(0,0,0,1),position); + Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1)); + if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + const btVector3 delta= results.witnesses[1]- + results.witnesses[0]; + const btScalar margin= shape0->getMarginNonVirtual()+ + shape1.getMarginNonVirtual(); + const btScalar length= delta.length(); + results.normal = delta/length; + results.witnesses[0] += results.normal*margin; + return(length-margin); + } + else + { + if(gjk_status==GJK::eStatus::Inside) + { + if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results)) + { + const btVector3 delta= results.witnesses[0]- + results.witnesses[1]; + const btScalar length= delta.length(); + if (length >= SIMD_EPSILON) + results.normal = delta/length; + return(-length); + } + } + } + return(SIMD_INFINITY); +} + +// +bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ + if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) + return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); + else + return(true); +} +#endif //__SPU__ + +/* Symbols cleanup */ + +#undef GJK_MAX_ITERATIONS +#undef GJK_ACCURARY +#undef GJK_MIN_DISTANCE +#undef GJK_DUPLICATED_EPS +#undef GJK_SIMPLEX2_EPS +#undef GJK_SIMPLEX3_EPS +#undef GJK_SIMPLEX4_EPS + +#undef EPA_MAX_VERTICES +#undef EPA_MAX_FACES +#undef EPA_MAX_ITERATIONS +#undef EPA_ACCURACY +#undef EPA_FALLBACK +#undef EPA_PLANE_EPS +#undef EPA_INSIDE_EPS diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h new file mode 100644 index 00000000..ac501d5e --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#ifndef BT_GJK_EPA2_H +#define BT_GJK_EPA2_H + +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +///btGjkEpaSolver contributed under zlib by Nathanael Presson +struct btGjkEpaSolver2 +{ +struct sResults + { + enum eStatus + { + Separated, /* Shapes doesnt penetrate */ + Penetrating, /* Shapes are penetrating */ + GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ + } status; + btVector3 witnesses[2]; + btVector3 normal; + btScalar distance; + }; + +static int StackSizeRequirement(); + +static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); + +static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins=true); +#ifndef __SPU__ +static btScalar SignedDistance( const btVector3& position, + btScalar margin, + const btConvexShape* shape, + const btTransform& wtrs, + sResults& results); + +static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); +#endif //__SPU__ + +}; + +#endif //BT_GJK_EPA2_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp new file mode 100644 index 00000000..572ec36f --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +EPA Copyright (c) Ricardo Padrela 2006 + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "btGjkEpaPenetrationDepthSolver.h" + + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, + const btTransform& transformA, const btTransform& transformB, + btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB, + class btIDebugDraw* debugDraw) +{ + + (void)debugDraw; + (void)v; + (void)simplexSolver; + +// const btScalar radialmargin(btScalar(0.)); + + btVector3 guessVector(transformB.getOrigin()-transformA.getOrigin()); + btGjkEpaSolver2::sResults results; + + + if(btGjkEpaSolver2::Penetration(pConvexA,transformA, + pConvexB,transformB, + guessVector,results)) + + { + // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); + //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); + wWitnessOnA = results.witnesses[0]; + wWitnessOnB = results.witnesses[1]; + v = results.normal; + return true; + } else + { + if(btGjkEpaSolver2::Distance(pConvexA,transformA,pConvexB,transformB,guessVector,results)) + { + wWitnessOnA = results.witnesses[0]; + wWitnessOnB = results.witnesses[1]; + v = results.normal; + return false; + } + } + + return false; +} + + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h new file mode 100644 index 00000000..1ed6340a --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -0,0 +1,43 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +EPA Copyright (c) Ricardo Padrela 2006 + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H +#define BT_GJP_EPA_PENETRATION_DEPTH_H + +#include "btConvexPenetrationDepthSolver.h" + +///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to +///calculate the penetration depth between two convex shapes. +class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ + public : + + btGjkEpaPenetrationDepthSolver() + { + } + + bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, + const btTransform& transformA, const btTransform& transformB, + btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB, + class btIDebugDraw* debugDraw); + + private : + +}; + +#endif // BT_GJP_EPA_PENETRATION_DEPTH_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp new file mode 100644 index 00000000..88775794 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -0,0 +1,480 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btGjkPairDetector.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + + + +#if defined(DEBUG) || defined (_DEBUG) +//#define TEST_NON_VIRTUAL 1 +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +//#define DEBUG_SPU_COLLISION_DETECTION 1 +#endif //__SPU__ +#endif + +//must be above the machine epsilon +#define REL_ERROR2 btScalar(1.0e-6) + +//temp globals, to improve GJK/EPA/penetration calculations +int gNumDeepPenetrationChecks = 0; +int gNumGjkChecks = 0; + + +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)), +m_penetrationDepthSolver(penetrationDepthSolver), +m_simplexSolver(simplexSolver), +m_minkowskiA(objectA), +m_minkowskiB(objectB), +m_shapeTypeA(objectA->getShapeType()), +m_shapeTypeB(objectB->getShapeType()), +m_marginA(objectA->getMargin()), +m_marginB(objectB->getMargin()), +m_ignoreMargin(false), +m_lastUsedMethod(-1), +m_catchDegeneracies(1), +m_fixContactNormalDirection(1) +{ +} +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)), +m_penetrationDepthSolver(penetrationDepthSolver), +m_simplexSolver(simplexSolver), +m_minkowskiA(objectA), +m_minkowskiB(objectB), +m_shapeTypeA(shapeTypeA), +m_shapeTypeB(shapeTypeB), +m_marginA(marginA), +m_marginB(marginB), +m_ignoreMargin(false), +m_lastUsedMethod(-1), +m_catchDegeneracies(1), +m_fixContactNormalDirection(1) +{ +} + +void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) +{ + (void)swapResults; + + getClosestPointsNonVirtual(input,output,debugDraw); +} + +#ifdef __SPU__ +void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +#else +void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +#endif +{ + m_cachedSeparatingDistance = 0.f; + + btScalar distance=btScalar(0.); + btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 pointOnA,pointOnB; + btTransform localTransA = input.m_transformA; + btTransform localTransB = input.m_transformB; + btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5); + localTransA.getOrigin() -= positionOffset; + localTransB.getOrigin() -= positionOffset; + + bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d(); + + btScalar marginA = m_marginA; + btScalar marginB = m_marginB; + + gNumGjkChecks++; + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("inside gjk\n"); +#endif + //for CCD we don't use margins + if (m_ignoreMargin) + { + marginA = btScalar(0.); + marginB = btScalar(0.); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("ignoring margin\n"); +#endif + } + + m_curIter = 0; + int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN? + m_cachedSeparatingAxis.setValue(0,1,0); + + bool isValid = false; + bool checkSimplex = false; + bool checkPenetration = true; + m_degenerateSimplex = 0; + + m_lastUsedMethod = -1; + + { + btScalar squaredDistance = BT_LARGE_FLOAT; + btScalar delta = btScalar(0.); + + btScalar margin = marginA + marginB; + + + + m_simplexSolver->reset(); + + for ( ; ; ) + //while (true) + { + + btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis(); + btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis(); + +#if 1 + + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); + +// btVector3 pInA = localGetSupportingVertexWithoutMargin(m_shapeTypeA, m_minkowskiA, seperatingAxisInA,input.m_convexVertexData[0]);//, &featureIndexA); +// btVector3 qInB = localGetSupportingVertexWithoutMargin(m_shapeTypeB, m_minkowskiB, seperatingAxisInB,input.m_convexVertexData[1]);//, &featureIndexB); + +#else +#ifdef __SPU__ + btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); +#else + btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); +#ifdef TEST_NON_VIRTUAL + btVector3 pInAv = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + btVector3 qInBv = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + btAssert((pInAv-pInA).length() < 0.0001); + btAssert((qInBv-qInB).length() < 0.0001); +#endif // +#endif //__SPU__ +#endif + + + btVector3 pWorld = localTransA(pInA); + btVector3 qWorld = localTransB(qInB); + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("got local supporting vertices\n"); +#endif + + if (check2d) + { + pWorld[2] = 0.f; + qWorld[2] = 0.f; + } + + btVector3 w = pWorld - qWorld; + delta = m_cachedSeparatingAxis.dot(w); + + // potential exit, they don't overlap + if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) + { + m_degenerateSimplex = 10; + checkSimplex=true; + //checkPenetration = false; + break; + } + + //exit 0: the new point is already in the simplex, or we didn't come any closer + if (m_simplexSolver->inSimplex(w)) + { + m_degenerateSimplex = 1; + checkSimplex = true; + break; + } + // are we getting any closer ? + btScalar f0 = squaredDistance - delta; + btScalar f1 = squaredDistance * REL_ERROR2; + + if (f0 <= f1) + { + if (f0 <= btScalar(0.)) + { + m_degenerateSimplex = 2; + } else + { + m_degenerateSimplex = 11; + } + checkSimplex = true; + break; + } + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("addVertex 1\n"); +#endif + //add current vertex to simplex + m_simplexSolver->addVertex(w, pWorld, qWorld); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("addVertex 2\n"); +#endif + btVector3 newCachedSeparatingAxis; + + //calculate the closest point to the origin (update vector v) + if (!m_simplexSolver->closest(newCachedSeparatingAxis)) + { + m_degenerateSimplex = 3; + checkSimplex = true; + break; + } + + if(newCachedSeparatingAxis.length2()previousSquaredDistance) + { + m_degenerateSimplex = 7; + squaredDistance = previousSquaredDistance; + checkSimplex = false; + break; + } +#endif // + + + //redundant m_simplexSolver->compute_points(pointOnA, pointOnB); + + //are we getting any closer ? + if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) + { +// m_simplexSolver->backup_closest(m_cachedSeparatingAxis); + checkSimplex = true; + m_degenerateSimplex = 12; + + break; + } + + m_cachedSeparatingAxis = newCachedSeparatingAxis; + + //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject + if (m_curIter++ > gGjkMaxIter) + { + #if defined(DEBUG) || defined (_DEBUG) || defined (DEBUG_SPU_COLLISION_DETECTION) + + printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter); + printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n", + m_cachedSeparatingAxis.getX(), + m_cachedSeparatingAxis.getY(), + m_cachedSeparatingAxis.getZ(), + squaredDistance, + m_minkowskiA->getShapeType(), + m_minkowskiB->getShapeType()); + + #endif + break; + + } + + + bool check = (!m_simplexSolver->fullSimplex()); + //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex()); + + if (!check) + { + //do we need this backup_closest here ? +// m_simplexSolver->backup_closest(m_cachedSeparatingAxis); + m_degenerateSimplex = 13; + break; + } + } + + if (checkSimplex) + { + m_simplexSolver->compute_points(pointOnA, pointOnB); + normalInB = m_cachedSeparatingAxis; + btScalar lenSqr =m_cachedSeparatingAxis.length2(); + + //valid normal + if (lenSqr < 0.0001) + { + m_degenerateSimplex = 5; + } + if (lenSqr > SIMD_EPSILON*SIMD_EPSILON) + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + normalInB *= rlen; //normalize + btScalar s = btSqrt(squaredDistance); + + btAssert(s > btScalar(0.0)); + pointOnA -= m_cachedSeparatingAxis * (marginA / s); + pointOnB += m_cachedSeparatingAxis * (marginB / s); + distance = ((btScalar(1.)/rlen) - margin); + isValid = true; + + m_lastUsedMethod = 1; + } else + { + m_lastUsedMethod = 2; + } + } + + bool catchDegeneratePenetrationCase = + (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01)); + + //if (checkPenetration && !isValid) + if (checkPenetration && (!isValid || catchDegeneratePenetrationCase )) + { + //penetration case + + //if there is no way to handle penetrations, bail out + if (m_penetrationDepthSolver) + { + // Penetration depth case. + btVector3 tmpPointOnA,tmpPointOnB; + + gNumDeepPenetrationChecks++; + m_cachedSeparatingAxis.setZero(); + + bool isValid2 = m_penetrationDepthSolver->calcPenDepth( + *m_simplexSolver, + m_minkowskiA,m_minkowskiB, + localTransA,localTransB, + m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB, + debugDraw + ); + + + if (isValid2) + { + btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA; + btScalar lenSqr = tmpNormalInB.length2(); + if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON)) + { + tmpNormalInB = m_cachedSeparatingAxis; + lenSqr = m_cachedSeparatingAxis.length2(); + } + + if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON)) + { + tmpNormalInB /= btSqrt(lenSqr); + btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length(); + //only replace valid penetrations when the result is deeper (check) + if (!isValid || (distance2 < distance)) + { + distance = distance2; + pointOnA = tmpPointOnA; + pointOnB = tmpPointOnB; + normalInB = tmpNormalInB; + isValid = true; + m_lastUsedMethod = 3; + } else + { + m_lastUsedMethod = 8; + } + } else + { + m_lastUsedMethod = 9; + } + } else + + { + ///this is another degenerate case, where the initial GJK calculation reports a degenerate case + ///EPA reports no penetration, and the second GJK (using the supporting vector without margin) + ///reports a valid positive distance. Use the results of the second GJK instead of failing. + ///thanks to Jacob.Langford for the reproduction case + ///http://code.google.com/p/bullet/issues/detail?id=250 + + + if (m_cachedSeparatingAxis.length2() > btScalar(0.)) + { + btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin; + //only replace valid distances when the distance is less + if (!isValid || (distance2 < distance)) + { + distance = distance2; + pointOnA = tmpPointOnA; + pointOnB = tmpPointOnB; + pointOnA -= m_cachedSeparatingAxis * marginA ; + pointOnB += m_cachedSeparatingAxis * marginB ; + normalInB = m_cachedSeparatingAxis; + normalInB.normalize(); + isValid = true; + m_lastUsedMethod = 6; + } else + { + m_lastUsedMethod = 5; + } + } + } + + } + + } + } + + + + if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared))) + { +#if 0 +///some debugging +// if (check2d) + { + printf("n = %2.3f,%2.3f,%2.3f. ",normalInB[0],normalInB[1],normalInB[2]); + printf("distance = %2.3f exit=%d deg=%d\n",distance,m_lastUsedMethod,m_degenerateSimplex); + } +#endif + + if (m_fixContactNormalDirection) + { + ///@workaround for sticky convex collisions + //in some degenerate cases (usually when the use uses very small margins) + //the contact normal is pointing the wrong direction + //so fix it now (until we can deal with all degenerate cases in GJK and EPA) + //contact normals need to point from B to A in all cases, so we can simply check if the contact normal really points from B to A + //We like to use a dot product of the normal against the difference of the centroids, + //once the centroid is available in the API + //until then we use the center of the aabb to approximate the centroid + btVector3 aabbMin,aabbMax; + m_minkowskiA->getAabb(localTransA,aabbMin,aabbMax); + btVector3 posA = (aabbMax+aabbMin)*btScalar(0.5); + + m_minkowskiB->getAabb(localTransB,aabbMin,aabbMax); + btVector3 posB = (aabbMin+aabbMax)*btScalar(0.5); + + btVector3 diff = posA-posB; + if (diff.dot(normalInB) < 0.f) + normalInB *= -1.f; + } + m_cachedSeparatingAxis = normalInB; + m_cachedSeparatingDistance = distance; + + output.addContactPoint( + normalInB, + pointOnB+positionOffset, + distance); + + } + + +} + + + + + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h new file mode 100644 index 00000000..feeae686 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + + +#ifndef BT_GJK_PAIR_DETECTOR_H +#define BT_GJK_PAIR_DETECTOR_H + +#include "btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +class btConvexShape; +#include "btSimplexSolverInterface.h" +class btConvexPenetrationDepthSolver; + +/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface +class btGjkPairDetector : public btDiscreteCollisionDetectorInterface +{ + + + btVector3 m_cachedSeparatingAxis; + btConvexPenetrationDepthSolver* m_penetrationDepthSolver; + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_minkowskiA; + const btConvexShape* m_minkowskiB; + int m_shapeTypeA; + int m_shapeTypeB; + btScalar m_marginA; + btScalar m_marginB; + + bool m_ignoreMargin; + btScalar m_cachedSeparatingDistance; + + +public: + + //some debugging to fix degeneracy problems + int m_lastUsedMethod; + int m_curIter; + int m_degenerateSimplex; + int m_catchDegeneracies; + int m_fixContactNormalDirection; + + btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + virtual ~btGjkPairDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + + void getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); + + + void setMinkowskiA(const btConvexShape* minkA) + { + m_minkowskiA = minkA; + } + + void setMinkowskiB(const btConvexShape* minkB) + { + m_minkowskiB = minkB; + } + void setCachedSeperatingAxis(const btVector3& seperatingAxis) + { + m_cachedSeparatingAxis = seperatingAxis; + } + + const btVector3& getCachedSeparatingAxis() const + { + return m_cachedSeparatingAxis; + } + btScalar getCachedSeparatingDistance() const + { + return m_cachedSeparatingDistance; + } + + void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver) + { + m_penetrationDepthSolver = penetrationDepthSolver; + } + + ///don't use setIgnoreMargin, it's for Bullet's internal use + void setIgnoreMargin(bool ignoreMargin) + { + m_ignoreMargin = ignoreMargin; + } + + +}; + +#endif //BT_GJK_PAIR_DETECTOR_H diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h new file mode 100644 index 00000000..e40fb1d3 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -0,0 +1,156 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MANIFOLD_CONTACT_POINT_H +#define BT_MANIFOLD_CONTACT_POINT_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransformUtil.h" + +#ifdef PFX_USE_FREE_VECTORMATH + #include "physics_effects/base_level/solver/pfx_constraint_row.h" +typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow; +#else + // Don't change following order of parameters + ATTRIBUTE_ALIGNED16(struct) btConstraintRow { + btScalar m_normal[3]; + btScalar m_rhs; + btScalar m_jacDiagInv; + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_accumImpulse; + }; + typedef btConstraintRow PfxConstraintRow; +#endif //PFX_USE_FREE_VECTORMATH + + + +/// ManifoldContactPoint collects and maintains persistent contactpoints. +/// used to improve stability and performance of rigidbody dynamics response. +class btManifoldPoint + { + public: + btManifoldPoint() + :m_userPersistentData(0), + m_lateralFrictionInitialized(false), + m_appliedImpulse(0.f), + m_appliedImpulseLateral1(0.f), + m_appliedImpulseLateral2(0.f), + m_contactMotion1(0.f), + m_contactMotion2(0.f), + m_contactCFM1(0.f), + m_contactCFM2(0.f), + m_lifeTime(0) + { + } + + btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB, + const btVector3 &normal, + btScalar distance ) : + m_localPointA( pointA ), + m_localPointB( pointB ), + m_normalWorldOnB( normal ), + m_distance1( distance ), + m_combinedFriction(btScalar(0.)), + m_combinedRollingFriction(btScalar(0.)), + m_combinedRestitution(btScalar(0.)), + m_userPersistentData(0), + m_lateralFrictionInitialized(false), + m_appliedImpulse(0.f), + m_appliedImpulseLateral1(0.f), + m_appliedImpulseLateral2(0.f), + m_contactMotion1(0.f), + m_contactMotion2(0.f), + m_contactCFM1(0.f), + m_contactCFM2(0.f), + m_lifeTime(0) + { + + } + + + + btVector3 m_localPointA; + btVector3 m_localPointB; + btVector3 m_positionWorldOnB; + ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity + btVector3 m_positionWorldOnA; + btVector3 m_normalWorldOnB; + + btScalar m_distance1; + btScalar m_combinedFriction; + btScalar m_combinedRollingFriction; + btScalar m_combinedRestitution; + + //BP mod, store contact triangles. + int m_partId0; + int m_partId1; + int m_index0; + int m_index1; + + mutable void* m_userPersistentData; + bool m_lateralFrictionInitialized; + + btScalar m_appliedImpulse; + btScalar m_appliedImpulseLateral1; + btScalar m_appliedImpulseLateral2; + btScalar m_contactMotion1; + btScalar m_contactMotion2; + btScalar m_contactCFM1; + btScalar m_contactCFM2; + + int m_lifeTime;//lifetime of the contactpoint in frames + + btVector3 m_lateralFrictionDir1; + btVector3 m_lateralFrictionDir2; + + + + + btScalar getDistance() const + { + return m_distance1; + } + int getLifeTime() const + { + return m_lifeTime; + } + + const btVector3& getPositionWorldOnA() const { + return m_positionWorldOnA; +// return m_positionWorldOnB + m_normalWorldOnB * m_distance1; + } + + const btVector3& getPositionWorldOnB() const + { + return m_positionWorldOnB; + } + + void setDistance(btScalar dist) + { + m_distance1 = dist; + } + + ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver + btScalar getAppliedImpulse() const + { + return m_appliedImpulse; + } + + + + }; + +#endif //BT_MANIFOLD_CONTACT_POINT_H diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp new file mode 100644 index 00000000..fa45f490 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp @@ -0,0 +1,361 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#define NUM_UNITSPHERE_POINTS 42 + + +bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw + ) +{ + + (void)v; + + bool check2d= convexA->isConvex2d() && convexB->isConvex2d(); + + struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result + { + + btIntermediateResult():m_hasResult(false) + { + } + + btVector3 m_normalOnBInWorld; + btVector3 m_pointInWorld; + btScalar m_depth; + bool m_hasResult; + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + (void)partId0; + (void)index0; + } + virtual void setShapeIdentifiersB(int partId1,int index1) + { + (void)partId1; + (void)index1; + } + void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_normalOnBInWorld = normalOnBInWorld; + m_pointInWorld = pointInWorld; + m_depth = depth; + m_hasResult = true; + } + }; + + //just take fixed number of orientation, and sample the penetration depth in that direction + btScalar minProj = btScalar(BT_LARGE_FLOAT); + btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.)); + btVector3 minA,minB; + btVector3 seperatingAxisInA,seperatingAxisInB; + btVector3 pInA,qInB,pWorld,qWorld,w; + +#ifndef __SPU__ +#define USE_BATCHED_SUPPORT 1 +#endif +#ifdef USE_BATCHED_SUPPORT + + btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + + for (i=0;igetNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + + + + convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); + convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); + + for (i=0;i0.01) + { + + seperatingAxisInA = seperatingAxisInABatch[i]; + seperatingAxisInB = seperatingAxisInBBatch[i]; + + pInA = supportVerticesABatch[i]; + qInB = supportVerticesBBatch[i]; + + pWorld = transA(pInA); + qWorld = transB(qInB); + if (check2d) + { + pWorld[2] = 0.f; + qWorld[2] = 0.f; + } + + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } + } +#else + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + +#ifndef __SPU__ + { + int numPDA = convexA->getNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + getPenetrationDirections()[numSampleDirections] = norm; + numSampleDirections++; + } + } + } +#endif // __SPU__ + + for (int i=0;ilocalGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA); + qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB); + pWorld = transA(pInA); + qWorld = transB(qInB); + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } +#endif //USE_BATCHED_SUPPORT + + //add the margins + + minA += minNorm*convexA->getMarginNonVirtual(); + minB -= minNorm*convexB->getMarginNonVirtual(); + //no penetration + if (minProj < btScalar(0.)) + return false; + + btScalar extraSeparation = 0.5f;///scale dependent + minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual()); + + + + + +//#define DEBUG_DRAW 1 +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(0,1,0); + debugDraw->drawLine(minA,minB,color); + color = btVector3 (1,1,1); + btVector3 vec = minB-minA; + btScalar prj2 = minNorm.dot(vec); + debugDraw->drawLine(minA,minA+(minNorm*minProj),color); + + } +#endif //DEBUG_DRAW + + + + btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); + + btScalar offsetDist = minProj; + btVector3 offset = minNorm * offsetDist; + + + + btGjkPairDetector::ClosestPointInput input; + + btVector3 newOrg = transA.getOrigin() + offset; + + btTransform displacedTrans = transA; + displacedTrans.setOrigin(newOrg); + + input.m_transformA = displacedTrans; + input.m_transformB = transB; + input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj; + + btIntermediateResult res; + gjkdet.setCachedSeperatingAxis(-minNorm); + gjkdet.getClosestPoints(input,res,debugDraw); + + btScalar correctedMinNorm = minProj - res.m_depth; + + + //the penetration depth is over-estimated, relax it + btScalar penetration_relaxation= btScalar(1.); + minNorm*=penetration_relaxation; + + + if (res.m_hasResult) + { + + pa = res.m_pointInWorld - minNorm * correctedMinNorm; + pb = res.m_pointInWorld; + v = minNorm; + +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(1,0,0); + debugDraw->drawLine(pa,pb,color); + } +#endif//DEBUG_DRAW + + + } + return res.m_hasResult; +} + +btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections() +{ + static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = + { + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) + }; + + return sPenetrationDirections; +} + + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h new file mode 100644 index 00000000..fd533b4f --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + +#include "btConvexPenetrationDepthSolver.h" + +///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. +///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. +class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +protected: + + static btVector3* getPenetrationDirections(); + +public: + + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw + ); +}; + +#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp new file mode 100644 index 00000000..4d92e853 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp @@ -0,0 +1,305 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btPersistentManifold.h" +#include "LinearMath/btTransform.h" + + +btScalar gContactBreakingThreshold = btScalar(0.02); +ContactDestroyedCallback gContactDestroyedCallback = 0; +ContactProcessedCallback gContactProcessedCallback = 0; +///gContactCalcArea3Points will approximate the convex hull area using 3 points +///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower +bool gContactCalcArea3Points = true; + + +btPersistentManifold::btPersistentManifold() +:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE), +m_body0(0), +m_body1(0), +m_cachedPoints (0), +m_index1a(0) +{ +} + + + + +#ifdef DEBUG_PERSISTENCY +#include +void btPersistentManifold::DebugPersistency() +{ + int i; + printf("DebugPersistency : numPoints %d\n",m_cachedPoints); + for (i=0;i1) + printf("error in clearUserCache\n"); + } + } + btAssert(occurance<=0); +#endif //DEBUG_PERSISTENCY + + if (pt.m_userPersistentData && gContactDestroyedCallback) + { + (*gContactDestroyedCallback)(pt.m_userPersistentData); + pt.m_userPersistentData = 0; + } + +#ifdef DEBUG_PERSISTENCY + DebugPersistency(); +#endif + } + + +} + +static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3) +{ + // It calculates possible 3 area constructed from random 4 points and returns the biggest one. + + btVector3 a[3],b[3]; + a[0] = p0 - p1; + a[1] = p0 - p2; + a[2] = p0 - p3; + b[0] = p2 - p3; + b[1] = p1 - p3; + b[2] = p1 - p2; + + //todo: Following 3 cross production can be easily optimized by SIMD. + btVector3 tmp0 = a[0].cross(b[0]); + btVector3 tmp1 = a[1].cross(b[1]); + btVector3 tmp2 = a[2].cross(b[2]); + + return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2()); +} + +int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) +{ + //calculate 4 possible cases areas, and take biggest area + //also need to keep 'deepest' + + int maxPenetrationIndex = -1; +#define KEEP_DEEPEST_POINT 1 +#ifdef KEEP_DEEPEST_POINT + btScalar maxPenetration = pt.getDistance(); + for (int i=0;i<4;i++) + { + if (m_pointCache[i].getDistance() < maxPenetration) + { + maxPenetrationIndex = i; + maxPenetration = m_pointCache[i].getDistance(); + } + } +#endif //KEEP_DEEPEST_POINT + + btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.)); + + if (gContactCalcArea3Points) + { + if (maxPenetrationIndex != 0) + { + btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA; + btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; + btVector3 cross = a0.cross(b0); + res0 = cross.length2(); + } + if (maxPenetrationIndex != 1) + { + btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; + btVector3 cross = a1.cross(b1); + res1 = cross.length2(); + } + + if (maxPenetrationIndex != 2) + { + btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA; + btVector3 cross = a2.cross(b2); + res2 = cross.length2(); + } + + if (maxPenetrationIndex != 3) + { + btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA; + btVector3 cross = a3.cross(b3); + res3 = cross.length2(); + } + } + else + { + if(maxPenetrationIndex != 0) { + res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 1) { + res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 2) { + res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 3) { + res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA); + } + } + btVector4 maxvec(res0,res1,res2,res3); + int biggestarea = maxvec.closestAxis4(); + return biggestarea; + +} + + +int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const +{ + btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold(); + int size = getNumContacts(); + int nearestPoint = -1; + for( int i = 0; i < size; i++ ) + { + const btManifoldPoint &mp = m_pointCache[i]; + + btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA; + const btScalar distToManiPoint = diffA.dot(diffA); + if( distToManiPoint < shortestDist ) + { + shortestDist = distToManiPoint; + nearestPoint = i; + } + } + return nearestPoint; +} + +int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive) +{ + if (!isPredictive) + { + btAssert(validContactDistance(newPoint)); + } + + int insertIndex = getNumContacts(); + if (insertIndex == MANIFOLD_CACHE_SIZE) + { +#if MANIFOLD_CACHE_SIZE >= 4 + //sort cache so best points come first, based on area + insertIndex = sortCachedPoints(newPoint); +#else + insertIndex = 0; +#endif + clearUserCache(m_pointCache[insertIndex]); + + } else + { + m_cachedPoints++; + + + } + if (insertIndex<0) + insertIndex=0; + + btAssert(m_pointCache[insertIndex].m_userPersistentData==0); + m_pointCache[insertIndex] = newPoint; + return insertIndex; +} + +btScalar btPersistentManifold::getContactBreakingThreshold() const +{ + return m_contactBreakingThreshold; +} + + + +void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) +{ + int i; +#ifdef DEBUG_PERSISTENCY + printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", + trA.getOrigin().getX(), + trA.getOrigin().getY(), + trA.getOrigin().getZ(), + trB.getOrigin().getX(), + trB.getOrigin().getY(), + trB.getOrigin().getZ()); +#endif //DEBUG_PERSISTENCY + /// first refresh worldspace positions and distance + for (i=getNumContacts()-1;i>=0;i--) + { + btManifoldPoint &manifoldPoint = m_pointCache[i]; + manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA ); + manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB ); + manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB); + manifoldPoint.m_lifeTime++; + } + + /// then + btScalar distance2d; + btVector3 projectedDifference,projectedPoint; + for (i=getNumContacts()-1;i>=0;i--) + { + + btManifoldPoint &manifoldPoint = m_pointCache[i]; + //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) + if (!validContactDistance(manifoldPoint)) + { + removeContactPoint(i); + } else + { + //contact also becomes invalid when relative movement orthogonal to normal exceeds margin + projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1; + projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint; + distance2d = projectedDifference.dot(projectedDifference); + if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) + { + removeContactPoint(i); + } else + { + //contact point processed callback + if (gContactProcessedCallback) + (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1); + } + } + } +#ifdef DEBUG_PERSISTENCY + DebugPersistency(); +#endif // +} + + + + + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h new file mode 100644 index 00000000..2ceaab75 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -0,0 +1,240 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_PERSISTENT_MANIFOLD_H +#define BT_PERSISTENT_MANIFOLD_H + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "btManifoldPoint.h" +class btCollisionObject; +#include "LinearMath/btAlignedAllocator.h" + +struct btCollisionResult; + +///maximum contact breaking and merging threshold +extern btScalar gContactBreakingThreshold; + +typedef bool (*ContactDestroyedCallback)(void* userPersistentData); +typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1); +extern ContactDestroyedCallback gContactDestroyedCallback; +extern ContactProcessedCallback gContactProcessedCallback; + +//the enum starts at 1024 to avoid type conflicts with btTypedConstraint +enum btContactManifoldTypes +{ + MIN_CONTACT_MANIFOLD_TYPE = 1024, + BT_PERSISTENT_MANIFOLD_TYPE +}; + +#define MANIFOLD_CACHE_SIZE 4 + +///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. +///Those contact points are created by the collision narrow phase. +///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. +///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) +///reduces the cache to 4 points, when more then 4 points are added, using following rules: +///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points +///note that some pairs of objects might have more then one contact manifold. + + +ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject +//ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject +{ + + btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE]; + + /// this two body pointers can point to the physics rigidbody class. + const btCollisionObject* m_body0; + const btCollisionObject* m_body1; + + int m_cachedPoints; + + btScalar m_contactBreakingThreshold; + btScalar m_contactProcessingThreshold; + + + /// sort cached points so most isolated points come first + int sortCachedPoints(const btManifoldPoint& pt); + + int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_companionIdA; + int m_companionIdB; + + int m_index1a; + + btPersistentManifold(); + + btPersistentManifold(const btCollisionObject* body0,const btCollisionObject* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold) + : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE), + m_body0(body0),m_body1(body1),m_cachedPoints(0), + m_contactBreakingThreshold(contactBreakingThreshold), + m_contactProcessingThreshold(contactProcessingThreshold) + { + } + + SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0;} + SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1;} + + void setBodies(const btCollisionObject* body0,const btCollisionObject* body1) + { + m_body0 = body0; + m_body1 = body1; + } + + void clearUserCache(btManifoldPoint& pt); + +#ifdef DEBUG_PERSISTENCY + void DebugPersistency(); +#endif // + + SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} + /// the setNumContacts API is usually not used, except when you gather/fill all contacts manually + void setNumContacts(int cachedPoints) + { + m_cachedPoints = cachedPoints; + } + + + SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const + { + btAssert(index < m_cachedPoints); + return m_pointCache[index]; + } + + SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) + { + btAssert(index < m_cachedPoints); + return m_pointCache[index]; + } + + ///@todo: get this margin from the current physics / collision environment + btScalar getContactBreakingThreshold() const; + + btScalar getContactProcessingThreshold() const + { + return m_contactProcessingThreshold; + } + + void setContactBreakingThreshold(btScalar contactBreakingThreshold) + { + m_contactBreakingThreshold = contactBreakingThreshold; + } + + void setContactProcessingThreshold(btScalar contactProcessingThreshold) + { + m_contactProcessingThreshold = contactProcessingThreshold; + } + + + + + int getCacheEntry(const btManifoldPoint& newPoint) const; + + int addManifoldPoint( const btManifoldPoint& newPoint, bool isPredictive=false); + + void removeContactPoint (int index) + { + clearUserCache(m_pointCache[index]); + + int lastUsedIndex = getNumContacts() - 1; +// m_pointCache[index] = m_pointCache[lastUsedIndex]; + if(index != lastUsedIndex) + { + m_pointCache[index] = m_pointCache[lastUsedIndex]; + //get rid of duplicated userPersistentData pointer + m_pointCache[lastUsedIndex].m_userPersistentData = 0; + m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f; + m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f; + m_pointCache[lastUsedIndex].m_lifeTime = 0; + } + + btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); + m_cachedPoints--; + } + void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex) + { + btAssert(validContactDistance(newPoint)); + +#define MAINTAIN_PERSISTENCY 1 +#ifdef MAINTAIN_PERSISTENCY + int lifeTime = m_pointCache[insertIndex].getLifeTime(); + btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse; + btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1; + btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2; +// bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized; + + + + btAssert(lifeTime>=0); + void* cache = m_pointCache[insertIndex].m_userPersistentData; + + m_pointCache[insertIndex] = newPoint; + + m_pointCache[insertIndex].m_userPersistentData = cache; + m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; + m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; + m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; + + m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; + m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; + m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; + + + m_pointCache[insertIndex].m_lifeTime = lifeTime; +#else + clearUserCache(m_pointCache[insertIndex]); + m_pointCache[insertIndex] = newPoint; + +#endif + } + + + bool validContactDistance(const btManifoldPoint& pt) const + { + return pt.m_distance1 <= getContactBreakingThreshold(); + } + /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin + void refreshContactPoints( const btTransform& trA,const btTransform& trB); + + + SIMD_FORCE_INLINE void clearManifold() + { + int i; + for (i=0;i //for FLT_MAX + +int gExpectedNbTests=0; +int gActualNbTests = 0; +bool gUseInternalObject = true; + +// Clips a face to the back of a plane +void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS) +{ + + int ve; + btScalar ds, de; + int numVerts = pVtxIn.size(); + if (numVerts < 2) + return; + + btVector3 firstVertex=pVtxIn[pVtxIn.size()-1]; + btVector3 endVertex = pVtxIn[0]; + + ds = planeNormalWS.dot(firstVertex)+planeEqWS; + + for (ve = 0; ve < numVerts; ve++) + { + endVertex=pVtxIn[ve]; + + de = planeNormalWS.dot(endVertex)+planeEqWS; + + if (ds<0) + { + if (de<0) + { + // Start < 0, end < 0, so output endVertex + ppVtxOut.push_back(endVertex); + } + else + { + // Start < 0, end >= 0, so output intersection + ppVtxOut.push_back( firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de)))); + } + } + else + { + if (de<0) + { + // Start >= 0, end < 0 so output intersection and end + ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de)))); + ppVtxOut.push_back(endVertex); + } + } + firstVertex = endVertex; + ds = de; + } +} + + +static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB) +{ + btScalar Min0,Max0; + btScalar Min1,Max1; + btVector3 witnesPtMinA,witnesPtMaxA; + btVector3 witnesPtMinB,witnesPtMaxB; + + hullA.project(transA,sep_axis, Min0, Max0,witnesPtMinA,witnesPtMaxA); + hullB.project(transB, sep_axis, Min1, Max1,witnesPtMinB,witnesPtMaxB); + + if(Max0=0.0f); + btScalar d1 = Max1 - Min0; + btAssert(d1>=0.0f); + if (d01e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +#ifdef TEST_INTERNAL_OBJECTS + +inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3]) +{ + // This version is ~11.000 cycles (4%) faster overall in one of the tests. +// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK); +// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK); +// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK); + p[0] = sv[0] < 0.0f ? -extents[0] : extents[0]; + p[1] = sv[1] < 0.0f ? -extents[1] : extents[1]; + p[2] = sv[2] < 0.0f ? -extents[2] : extents[2]; +} + +void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr) +{ + const btMatrix3x3& rot = tr.getBasis(); + const btVector3& r0 = rot[0]; + const btVector3& r1 = rot[1]; + const btVector3& r2 = rot[2]; + + const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z(); + const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z(); + const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z(); + + out.setValue(x, y, z); +} + + bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin) +{ + const btScalar dp = delta_c.dot(axis); + + btVector3 localAxis0; + InverseTransformPoint3x3(localAxis0, axis,trans0); + btVector3 localAxis1; + InverseTransformPoint3x3(localAxis1, axis,trans1); + + btScalar p0[3]; + BoxSupport(convex0.m_extents, localAxis0, p0); + btScalar p1[3]; + BoxSupport(convex1.m_extents, localAxis1, p1); + + const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z(); + const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z(); + + const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius; + const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius; + + const btScalar MinMaxRadius = MaxRadius + MinRadius; + const btScalar d0 = MinMaxRadius + dp; + const btScalar d1 = MinMaxRadius - dp; + + const btScalar depth = d0dmin) + return false; + return true; +} +#endif //TEST_INTERNAL_OBJECTS + + + + SIMD_FORCE_INLINE void btSegmentsClosestPoints( + btVector3& ptsVector, + btVector3& offsetA, + btVector3& offsetB, + btScalar& tA, btScalar& tB, + const btVector3& translation, + const btVector3& dirA, btScalar hlenA, + const btVector3& dirB, btScalar hlenB ) +{ + // compute the parameters of the closest points on each line segment + + btScalar dirA_dot_dirB = btDot(dirA,dirB); + btScalar dirA_dot_trans = btDot(dirA,translation); + btScalar dirB_dot_trans = btDot(dirB,translation); + + btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB; + + if ( denom == 0.0f ) { + tA = 0.0f; + } else { + tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom; + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + tB = tA * dirA_dot_dirB - dirB_dot_trans; + + if ( tB < -hlenB ) { + tB = -hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } else if ( tB > hlenB ) { + tB = hlenB; + tA = tB * dirA_dot_dirB + dirA_dot_trans; + + if ( tA < -hlenA ) + tA = -hlenA; + else if ( tA > hlenA ) + tA = hlenA; + } + + // compute the closest points relative to segment centers. + + offsetA = dirA * tA; + offsetB = dirB * tB; + + ptsVector = translation - offsetA + offsetB; +} + + + +bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut) +{ + gActualSATPairTests++; + +//#ifdef TEST_INTERNAL_OBJECTS + const btVector3 c0 = transA * hullA.m_localCenter; + const btVector3 c1 = transB * hullB.m_localCenter; + const btVector3 DeltaC2 = c0 - c1; +//#endif + + btScalar dmin = FLT_MAX; + int curPlaneTests=0; + + int numFacesA = hullA.m_faces.size(); + // Test normals from hullA + for(int i=0;i=0&&edgeB>=0) + { +// printf("edge-edge\n"); + //add an edge-edge contact + + btVector3 ptsVector; + btVector3 offsetA; + btVector3 offsetB; + btScalar tA; + btScalar tB; + + btVector3 translation = witnessPointB-witnessPointA; + + btVector3 dirA = worldEdgeA; + btVector3 dirB = worldEdgeB; + + btScalar hlenB = 1e30f; + btScalar hlenA = 1e30f; + + btSegmentsClosestPoints(ptsVector,offsetA,offsetB,tA,tB, + translation, + dirA, hlenA, + dirB,hlenB); + + btScalar nlSqrt = ptsVector.length2(); + if (nlSqrt>SIMD_EPSILON) + { + btScalar nl = btSqrt(nlSqrt); + ptsVector *= 1.f/nl; + if (ptsVector.dot(DeltaC2)<0.f) + { + ptsVector*=-1.f; + } + btVector3 ptOnB = witnessPointB + offsetB; + btScalar distance = nl; + resultOut.addContactPoint(ptsVector, ptOnB,-distance); + } + + } + + + if((DeltaC2.dot(sep))<0.0f) + sep = -sep; + + return true; +} + +void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut) +{ + btVertexArray worldVertsB2; + btVertexArray* pVtxIn = &worldVertsB1; + btVertexArray* pVtxOut = &worldVertsB2; + pVtxOut->reserve(pVtxIn->size()); + + int closestFaceA=-1; + { + btScalar dmin = FLT_MAX; + for(int face=0;faceresize(0); + } + + + +//#define ONLY_REPORT_DEEPEST_POINT + + btVector3 point; + + + // only keep points that are behind the witness face + { + btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]); + btScalar localPlaneEq = polyA.m_plane[3]; + btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal; + btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin()); + for (int i=0;isize();i++) + { + btVector3 vtx = pVtxIn->at(i); + btScalar depth = planeNormalWS.dot(vtx)+planeEqWS; + if (depth <=minDist) + { +// printf("clamped: depth=%f to minDist=%f\n",depth,minDist); + depth = minDist; + } + + if (depth <=maxDist) + { + btVector3 point = pVtxIn->at(i); +#ifdef ONLY_REPORT_DEEPEST_POINT + curMaxDist = depth; +#else +#if 0 + if (depth<-3) + { + printf("error in btPolyhedralContactClipping depth = %f\n", depth); + printf("likely wrong separatingNormal passed in\n"); + } +#endif + resultOut.addContactPoint(separatingNormal,point,depth); +#endif + } + } + } +#ifdef ONLY_REPORT_DEEPEST_POINT + if (curMaxDist dmax) + { + dmax = d; + closestFaceB = face; + } + } + } + btVertexArray worldVertsB1; + { + const btFace& polyB = hullB.m_faces[closestFaceB]; + const int numVertices = polyB.m_indices.size(); + for(int e0=0;e0=0) + clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut); + +} diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h new file mode 100644 index 00000000..b87bd4f3 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + + +///This file was written by Erwin Coumans + + +#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H +#define BT_POLYHEDRAL_CONTACT_CLIPPING_H + + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "btDiscreteCollisionDetectorInterface.h" + +class btConvexPolyhedron; + +typedef btAlignedObjectArray btVertexArray; + +// Clips a face to the back of a plane +struct btPolyhedralContactClipping +{ + static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut); + static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut); + + static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut); + + ///the clipFace method is used internally + static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS); + +}; + +#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp new file mode 100644 index 00000000..786efd18 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp @@ -0,0 +1,178 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +//#include + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "btRaycastCallback.h" + +btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags) + : + m_from(from), + m_to(to), + //@BP Mod + m_flags(flags), + m_hitFraction(btScalar(1.)) +{ + +} + + + +void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + const btVector3 &vert0=triangle[0]; + const btVector3 &vert1=triangle[1]; + const btVector3 &vert2=triangle[2]; + + btVector3 v10; v10 = vert1 - vert0 ; + btVector3 v20; v20 = vert2 - vert0 ; + + btVector3 triangleNormal; triangleNormal = v10.cross( v20 ); + + const btScalar dist = vert0.dot(triangleNormal); + btScalar dist_a = triangleNormal.dot(m_from) ; + dist_a-= dist; + btScalar dist_b = triangleNormal.dot(m_to); + dist_b -= dist; + + if ( dist_a * dist_b >= btScalar(0.0) ) + { + return ; // same sign + } + + if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0))) + { + // Backface, skip check + return; + } + + + const btScalar proj_length=dist_a-dist_b; + const btScalar distance = (dist_a)/(proj_length); + // Now we have the intersection point on the plane, we'll see if it's inside the triangle + // Add an epsilon as a tolerance for the raycast, + // in case the ray hits exacly on the edge of the triangle. + // It must be scaled for the triangle size. + + if(distance < m_hitFraction) + { + + + btScalar edge_tolerance =triangleNormal.length2(); + edge_tolerance *= btScalar(-0.0001); + btVector3 point; point.setInterpolate3( m_from, m_to, distance); + { + btVector3 v0p; v0p = vert0 - point; + btVector3 v1p; v1p = vert1 - point; + btVector3 cp0; cp0 = v0p.cross( v1p ); + + if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) + { + + + btVector3 v2p; v2p = vert2 - point; + btVector3 cp1; + cp1 = v1p.cross( v2p); + if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) + { + btVector3 cp2; + cp2 = v2p.cross(v0p); + + if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) + { + //@BP Mod + // Triangle normal isn't normalized + triangleNormal.normalize(); + + //@BP Mod - Allow for unflipped normal when raycasting against backfaces + if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0))) + { + m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); + } + else + { + m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); + } + } + } + } + } + } +} + + +btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin) +{ + m_convexShape = convexShape; + m_convexShapeFrom = convexShapeFrom; + m_convexShapeTo = convexShapeTo; + m_triangleToWorld = triangleToWorld; + m_hitFraction = 1.0f; + m_triangleCollisionMargin = triangleCollisionMargin; + m_allowedPenetration = 0.f; +} + +void +btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex) +{ + btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]); + triangleShape.setMargin(m_triangleCollisionMargin); + + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + +//#define USE_SUBSIMPLEX_CONVEX_CAST 1 +//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver); +#else + //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver); + btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + btConvexCast::CastResult castResult; + castResult.m_fraction = btScalar(1.); + castResult.m_allowedPenetration = m_allowedPenetration; + if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < m_hitFraction) + { +/* btContinuousConvexCast's normal is already in world space */ +/* +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST +*/ + castResult.m_normal.normalize(); + + reportHit (castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction, + partId, + triangleIndex); + } + } + } +} diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h new file mode 100644 index 00000000..3999d400 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -0,0 +1,72 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_RAYCAST_TRI_CALLBACK_H +#define BT_RAYCAST_TRI_CALLBACK_H + +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "LinearMath/btTransform.h" +struct btBroadphaseProxy; +class btConvexShape; + +class btTriangleRaycastCallback: public btTriangleCallback +{ +public: + + //input + btVector3 m_from; + btVector3 m_to; + + //@BP Mod - allow backface filtering and unflipped normals + enum EFlags + { + kF_None = 0, + kF_FilterBackfaces = 1 << 0, + kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle + kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm + kF_Terminator = 0xFFFFFFFF + }; + unsigned int m_flags; + + btScalar m_hitFraction; + + btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0; + +}; + +class btTriangleConvexcastCallback : public btTriangleCallback +{ +public: + const btConvexShape* m_convexShape; + btTransform m_convexShapeFrom; + btTransform m_convexShapeTo; + btTransform m_triangleToWorld; + btScalar m_hitFraction; + btScalar m_triangleCollisionMargin; + btScalar m_allowedPenetration; + + btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin); + + virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0; +}; + +#endif //BT_RAYCAST_TRI_CALLBACK_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h new file mode 100644 index 00000000..da8a1391 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -0,0 +1,63 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H +#define BT_SIMPLEX_SOLVER_INTERFACE_H + +#include "LinearMath/btVector3.h" + +#define NO_VIRTUAL_INTERFACE 1 +#ifdef NO_VIRTUAL_INTERFACE +#include "btVoronoiSimplexSolver.h" +#define btSimplexSolverInterface btVoronoiSimplexSolver +#else + +/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices +/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on +/// voronoi regions or barycentric coordinates +class btSimplexSolverInterface +{ + public: + virtual ~btSimplexSolverInterface() {}; + + virtual void reset() = 0; + + virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0; + + virtual bool closest(btVector3& v) = 0; + + virtual btScalar maxVertex() = 0; + + virtual bool fullSimplex() const = 0; + + virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0; + + virtual bool inSimplex(const btVector3& w) = 0; + + virtual void backup_closest(btVector3& v) = 0; + + virtual bool emptySimplex() const = 0; + + virtual void compute_points(btVector3& p1, btVector3& p2) = 0; + + virtual int numVertices() const =0; + + +}; +#endif +#endif //BT_SIMPLEX_SOLVER_INTERFACE_H + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp new file mode 100644 index 00000000..18eb662d --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -0,0 +1,160 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSubSimplexConvexCast.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" + +btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +:m_simplexSolver(simplexSolver), +m_convexA(convexA),m_convexB(convexB) +{ +} + +///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases. +///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565 +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif +bool btSubsimplexConvexCast::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + m_simplexSolver->reset(); + + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); + + btScalar lambda = btScalar(0.); + + btTransform interpolatedTransA = fromA; + btTransform interpolatedTransB = fromB; + + ///take relative motion + btVector3 r = (linVelA-linVelB); + btVector3 v; + + btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis())); + btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis())); + v = supVertexA-supVertexB; + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + + + btScalar dist2 = v.length2(); +#ifdef BT_USE_DOUBLE_PRECISION + btScalar epsilon = btScalar(0.0001); +#else + btScalar epsilon = btScalar(0.0001); +#endif //BT_USE_DOUBLE_PRECISION + btVector3 w,p; + btScalar VdotR; + + while ( (dist2 > epsilon) && maxIter--) + { + supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis())); + supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis())); + w = supVertexA-supVertexB; + + btScalar VdotW = v.dot(w); + + if (lambda > btScalar(1.0)) + { + return false; + } + + if ( VdotW > btScalar(0.)) + { + VdotR = v.dot(r); + + if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON)) + return false; + else + { + lambda = lambda - VdotW / VdotR; + //interpolate to next lambda + // x = s + lambda * r; + interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + //m_simplexSolver->reset(); + //check next line + w = supVertexA-supVertexB; + lastLambda = lambda; + n = v; + hasResult = true; + } + } + ///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc. + if (!m_simplexSolver->inSimplex(w)) + m_simplexSolver->addVertex( w, supVertexA , supVertexB); + + if (m_simplexSolver->closest(v)) + { + dist2 = v.length2(); + hasResult = true; + //todo: check this normal for validity + //n=v; + //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); + //printf("DIST2=%f\n",dist2); + //printf("numverts = %i\n",m_simplexSolver->numVertices()); + } else + { + dist2 = btScalar(0.); + } + } + + //int numiter = MAX_ITERATIONS - maxIter; +// printf("number of iterations: %d", numiter); + + //don't report a time of impact when moving 'away' from the hitnormal + + + result.m_fraction = lambda; + if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON)) + result.m_normal = n.normalized(); + else + result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (result.m_normal.dot(r)>=-result.m_allowedPenetration) + return false; + + btVector3 hitA,hitB; + m_simplexSolver->compute_points(hitA,hitB); + result.m_hitPoint=hitB; + return true; +} + + + + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h new file mode 100644 index 00000000..6c812798 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H +#define BT_SUBSIMPLEX_CONVEX_CAST_H + +#include "btConvexCast.h" +#include "btSimplexSolverInterface.h" +class btConvexShape; + +/// btSubsimplexConvexCast implements Gino van den Bergens' paper +///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection" +/// GJK based Ray Cast, optimized version +/// Objects should not start in overlap, otherwise results are not defined. +class btSubsimplexConvexCast : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; + +public: + + btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver); + + //virtual ~btSubsimplexConvexCast(); + ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects. + ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector. + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + +}; + +#endif //BT_SUBSIMPLEX_CONVEX_CAST_H diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp new file mode 100644 index 00000000..a775198a --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -0,0 +1,609 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + Elsevier CDROM license agreements grants nonexclusive license to use the software + for any purpose, commercial or non-commercial as long as the following credit is included + identifying the original source of the software: + + Parts of the source are "from the book Real-Time Collision Detection by + Christer Ericson, published by Morgan Kaufmann Publishers, + (c) 2005 Elsevier Inc." + +*/ + + +#include "btVoronoiSimplexSolver.h" + +#define VERTA 0 +#define VERTB 1 +#define VERTC 2 +#define VERTD 3 + +#define CATCH_DEGENERATE_TETRAHEDRON 1 +void btVoronoiSimplexSolver::removeVertex(int index) +{ + + btAssert(m_numVertices>0); + m_numVertices--; + m_simplexVectorW[index] = m_simplexVectorW[m_numVertices]; + m_simplexPointsP[index] = m_simplexPointsP[m_numVertices]; + m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices]; +} + +void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts) +{ + if ((numVertices() >= 4) && (!usedVerts.usedVertexD)) + removeVertex(3); + + if ((numVertices() >= 3) && (!usedVerts.usedVertexC)) + removeVertex(2); + + if ((numVertices() >= 2) && (!usedVerts.usedVertexB)) + removeVertex(1); + + if ((numVertices() >= 1) && (!usedVerts.usedVertexA)) + removeVertex(0); + +} + + + + + +//clear the simplex, remove all the vertices +void btVoronoiSimplexSolver::reset() +{ + m_cachedValidClosest = false; + m_numVertices = 0; + m_needsUpdate = true; + m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + m_cachedBC.reset(); +} + + + + //add a vertex +void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q) +{ + m_lastW = w; + m_needsUpdate = true; + + m_simplexVectorW[m_numVertices] = w; + m_simplexPointsP[m_numVertices] = p; + m_simplexPointsQ[m_numVertices] = q; + + m_numVertices++; +} + +bool btVoronoiSimplexSolver::updateClosestVectorAndPoints() +{ + + if (m_needsUpdate) + { + m_cachedBC.reset(); + + m_needsUpdate = false; + + switch (numVertices()) + { + case 0: + m_cachedValidClosest = false; + break; + case 1: + { + m_cachedP1 = m_simplexPointsP[0]; + m_cachedP2 = m_simplexPointsQ[0]; + m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0] + m_cachedBC.reset(); + m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.)); + m_cachedValidClosest = m_cachedBC.isValid(); + break; + }; + case 2: + { + //closest point origin from line segment + const btVector3& from = m_simplexVectorW[0]; + const btVector3& to = m_simplexVectorW[1]; + btVector3 nearest; + + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 diff = p - from; + btVector3 v = to - from; + btScalar t = v.dot(diff); + + if (t > 0) { + btScalar dotVV = v.dot(v); + if (t < dotVV) { + t /= dotVV; + diff -= t*v; + m_cachedBC.m_usedVertices.usedVertexA = true; + m_cachedBC.m_usedVertices.usedVertexB = true; + } else { + t = 1; + diff -= v; + //reduce to 1 point + m_cachedBC.m_usedVertices.usedVertexB = true; + } + } else + { + t = 0; + //reduce to 1 point + m_cachedBC.m_usedVertices.usedVertexA = true; + } + m_cachedBC.setBarycentricCoordinates(1-t,t); + nearest = from + t*v; + + m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]); + m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]); + m_cachedV = m_cachedP1 - m_cachedP2; + + reduceVertices(m_cachedBC.m_usedVertices); + + m_cachedValidClosest = m_cachedBC.isValid(); + break; + } + case 3: + { + //closest point origin from triangle + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + + const btVector3& a = m_simplexVectorW[0]; + const btVector3& b = m_simplexVectorW[1]; + const btVector3& c = m_simplexVectorW[2]; + + closestPtPointTriangle(p,a,b,c,m_cachedBC); + m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2]; + + m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2]; + + m_cachedV = m_cachedP1-m_cachedP2; + + reduceVertices (m_cachedBC.m_usedVertices); + m_cachedValidClosest = m_cachedBC.isValid(); + + break; + } + case 4: + { + + + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + + const btVector3& a = m_simplexVectorW[0]; + const btVector3& b = m_simplexVectorW[1]; + const btVector3& c = m_simplexVectorW[2]; + const btVector3& d = m_simplexVectorW[3]; + + bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC); + + if (hasSeperation) + { + + m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] + + m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3]; + + m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] + + m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3]; + + m_cachedV = m_cachedP1-m_cachedP2; + reduceVertices (m_cachedBC.m_usedVertices); + } else + { +// printf("sub distance got penetration\n"); + + if (m_cachedBC.m_degenerate) + { + m_cachedValidClosest = false; + } else + { + m_cachedValidClosest = true; + //degenerate case == false, penetration = true + zero + m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + break; + } + + m_cachedValidClosest = m_cachedBC.isValid(); + + //closest point origin from tetrahedron + break; + } + default: + { + m_cachedValidClosest = false; + } + }; + } + + return m_cachedValidClosest; + +} + +//return/calculate the closest vertex +bool btVoronoiSimplexSolver::closest(btVector3& v) +{ + bool succes = updateClosestVectorAndPoints(); + v = m_cachedV; + return succes; +} + + + +btScalar btVoronoiSimplexSolver::maxVertex() +{ + int i, numverts = numVertices(); + btScalar maxV = btScalar(0.); + for (i=0;i= btScalar(0.0) && d4 <= d3) + { + result.m_closestPointOnSimplex = b; + result.m_usedVertices.usedVertexB = true; + result.setBarycentricCoordinates(0,1,0); + + return true; // b; // barycentric coordinates (0,1,0) + } + // Check if P in edge region of AB, if so return projection of P onto AB + btScalar vc = d1*d4 - d3*d2; + if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) { + btScalar v = d1 / (d1 - d3); + result.m_closestPointOnSimplex = a + v * ab; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexB = true; + result.setBarycentricCoordinates(1-v,v,0); + return true; + //return a + v * ab; // barycentric coordinates (1-v,v,0) + } + + // Check if P in vertex region outside C + btVector3 cp = p - c; + btScalar d5 = ab.dot(cp); + btScalar d6 = ac.dot(cp); + if (d6 >= btScalar(0.0) && d5 <= d6) + { + result.m_closestPointOnSimplex = c; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(0,0,1); + return true;//c; // barycentric coordinates (0,0,1) + } + + // Check if P in edge region of AC, if so return projection of P onto AC + btScalar vb = d5*d2 - d1*d6; + if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) { + btScalar w = d2 / (d2 - d6); + result.m_closestPointOnSimplex = a + w * ac; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(1-w,0,w); + return true; + //return a + w * ac; // barycentric coordinates (1-w,0,w) + } + + // Check if P in edge region of BC, if so return projection of P onto BC + btScalar va = d3*d6 - d5*d4; + if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) { + btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + + result.m_closestPointOnSimplex = b + w * (c - b); + result.m_usedVertices.usedVertexB = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(0,1-w,w); + return true; + // return b + w * (c - b); // barycentric coordinates (0,1-w,w) + } + + // P inside face region. Compute Q through its barycentric coordinates (u,v,w) + btScalar denom = btScalar(1.0) / (va + vb + vc); + btScalar v = vb * denom; + btScalar w = vc * denom; + + result.m_closestPointOnSimplex = a + ab * v + ac * w; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexB = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(1-v-w,v,w); + + return true; +// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w + +} + + + + + +/// Test if point p and d lie on opposite sides of plane through abc +int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d) +{ + btVector3 normal = (b-a).cross(c-a); + + btScalar signp = (p - a).dot(normal); // [AP AB AC] + btScalar signd = (d - a).dot( normal); // [AD AB AC] + +#ifdef CATCH_DEGENERATE_TETRAHEDRON +#ifdef BT_USE_DOUBLE_PRECISION +if (signd * signd < (btScalar(1e-8) * btScalar(1e-8))) + { + return -1; + } +#else + if (signd * signd < (btScalar(1e-4) * btScalar(1e-4))) + { +// printf("affine dependent/degenerate\n");// + return -1; + } +#endif + +#endif + // Points on opposite sides if expression signs are opposite + return signp * signd < btScalar(0.); +} + + +bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult) +{ + btSubSimplexClosestResult tempResult; + + // Start out assuming point inside all halfspaces, so closest to itself + finalResult.m_closestPointOnSimplex = p; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = true; + finalResult.m_usedVertices.usedVertexB = true; + finalResult.m_usedVertices.usedVertexC = true; + finalResult.m_usedVertices.usedVertexD = true; + + int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d); + int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b); + int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c); + int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a); + + if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0) + { + finalResult.m_degenerate = true; + return false; + } + + if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC) + { + return false; + } + + + btScalar bestSqDist = FLT_MAX; + // If point outside face abc then compute closest point on abc + if (pointOutsideABC) + { + closestPtPointTriangle(p, a, b, c,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + + btScalar sqDist = (q - p).dot( q - p); + // Update best closest point if (squared) distance is less than current best + if (sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + //convert result bitmask! + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB; + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTB], + tempResult.m_barycentricCoords[VERTC], + 0 + ); + + } + } + + + // Repeat test for face acd + if (pointOutsideACD) + { + closestPtPointTriangle(p, a, c, d,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB; + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + 0, + tempResult.m_barycentricCoords[VERTB], + tempResult.m_barycentricCoords[VERTC] + ); + + } + } + // Repeat test for face adb + + + if (pointOutsideADB) + { + closestPtPointTriangle(p, a, d, b,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC; + + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTC], + 0, + tempResult.m_barycentricCoords[VERTB] + ); + + } + } + // Repeat test for face bdc + + + if (pointOutsideBDC) + { + closestPtPointTriangle(p, b, d, c,tempResult); + btVector3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + // + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; + + finalResult.setBarycentricCoordinates( + 0, + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTC], + tempResult.m_barycentricCoords[VERTB] + ); + + } + } + + //help! we ended up full ! + + if (finalResult.m_usedVertices.usedVertexA && + finalResult.m_usedVertices.usedVertexB && + finalResult.m_usedVertices.usedVertexC && + finalResult.m_usedVertices.usedVertexD) + { + return true; + } + + return true; +} + diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h new file mode 100644 index 00000000..2f389e27 --- /dev/null +++ b/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h @@ -0,0 +1,181 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_VORONOI_SIMPLEX_SOLVER_H +#define BT_VORONOI_SIMPLEX_SOLVER_H + +#include "btSimplexSolverInterface.h" + + + +#define VORONOI_SIMPLEX_MAX_VERTS 5 + +///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure +#define BT_USE_EQUAL_VERTEX_THRESHOLD +#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f + + +struct btUsageBitfield{ + btUsageBitfield() + { + reset(); + } + + void reset() + { + usedVertexA = false; + usedVertexB = false; + usedVertexC = false; + usedVertexD = false; + } + unsigned short usedVertexA : 1; + unsigned short usedVertexB : 1; + unsigned short usedVertexC : 1; + unsigned short usedVertexD : 1; + unsigned short unused1 : 1; + unsigned short unused2 : 1; + unsigned short unused3 : 1; + unsigned short unused4 : 1; +}; + + +struct btSubSimplexClosestResult +{ + btVector3 m_closestPointOnSimplex; + //MASK for m_usedVertices + //stores the simplex vertex-usage, using the MASK, + // if m_usedVertices & MASK then the related vertex is used + btUsageBitfield m_usedVertices; + btScalar m_barycentricCoords[4]; + bool m_degenerate; + + void reset() + { + m_degenerate = false; + setBarycentricCoordinates(); + m_usedVertices.reset(); + } + bool isValid() + { + bool valid = (m_barycentricCoords[0] >= btScalar(0.)) && + (m_barycentricCoords[1] >= btScalar(0.)) && + (m_barycentricCoords[2] >= btScalar(0.)) && + (m_barycentricCoords[3] >= btScalar(0.)); + + + return valid; + } + void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.)) + { + m_barycentricCoords[0] = a; + m_barycentricCoords[1] = b; + m_barycentricCoords[2] = c; + m_barycentricCoords[3] = d; + } + +}; + +/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin. +/// Can be used with GJK, as an alternative to Johnson distance algorithm. +#ifdef NO_VIRTUAL_INTERFACE +ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver +#else +ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver : public btSimplexSolverInterface +#endif +{ +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_numVertices; + + btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS]; + btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS]; + btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS]; + + + + btVector3 m_cachedP1; + btVector3 m_cachedP2; + btVector3 m_cachedV; + btVector3 m_lastW; + + btScalar m_equalVertexThreshold; + bool m_cachedValidClosest; + + + btSubSimplexClosestResult m_cachedBC; + + bool m_needsUpdate; + + void removeVertex(int index); + void reduceVertices (const btUsageBitfield& usedVerts); + bool updateClosestVectorAndPoints(); + + bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult); + int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d); + bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result); + +public: + + btVoronoiSimplexSolver() + : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD) + { + } + void reset(); + + void addVertex(const btVector3& w, const btVector3& p, const btVector3& q); + + void setEqualVertexThreshold(btScalar threshold) + { + m_equalVertexThreshold = threshold; + } + + btScalar getEqualVertexThreshold() const + { + return m_equalVertexThreshold; + } + + bool closest(btVector3& v); + + btScalar maxVertex(); + + bool fullSimplex() const + { + return (m_numVertices == 4); + } + + int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const; + + bool inSimplex(const btVector3& w); + + void backup_closest(btVector3& v) ; + + bool emptySimplex() const ; + + void compute_points(btVector3& p1, btVector3& p2) ; + + int numVertices() const + { + return m_numVertices; + } + + +}; + +#endif //BT_VORONOI_SIMPLEX_SOLVER_H + diff --git a/Code/Physics/src/BulletCollision/premake4.lua b/Code/Physics/src/BulletCollision/premake4.lua new file mode 100644 index 00000000..9bc0a9e6 --- /dev/null +++ b/Code/Physics/src/BulletCollision/premake4.lua @@ -0,0 +1,11 @@ + project "BulletCollision" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Code/Physics/src/BulletDynamics/CMakeLists.txt b/Code/Physics/src/BulletDynamics/CMakeLists.txt new file mode 100644 index 00000000..cc472763 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/CMakeLists.txt @@ -0,0 +1,153 @@ +INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ) + + + +SET(BulletDynamics_SRCS + Character/btKinematicCharacterController.cpp + ConstraintSolver/btConeTwistConstraint.cpp + ConstraintSolver/btContactConstraint.cpp + ConstraintSolver/btFixedConstraint.cpp + ConstraintSolver/btGearConstraint.cpp + ConstraintSolver/btGeneric6DofConstraint.cpp + ConstraintSolver/btGeneric6DofSpringConstraint.cpp + ConstraintSolver/btHinge2Constraint.cpp + ConstraintSolver/btHingeConstraint.cpp + ConstraintSolver/btPoint2PointConstraint.cpp + ConstraintSolver/btSequentialImpulseConstraintSolver.cpp + ConstraintSolver/btSliderConstraint.cpp + ConstraintSolver/btSolve2LinearConstraint.cpp + ConstraintSolver/btTypedConstraint.cpp + ConstraintSolver/btUniversalConstraint.cpp + Dynamics/btDiscreteDynamicsWorld.cpp + Dynamics/btRigidBody.cpp + Dynamics/btSimpleDynamicsWorld.cpp + Dynamics/Bullet-C-API.cpp + Vehicle/btRaycastVehicle.cpp + Vehicle/btWheelInfo.cpp + Featherstone/btMultiBody.cpp + Featherstone/btMultiBodyConstraintSolver.cpp + Featherstone/btMultiBodyDynamicsWorld.cpp + Featherstone/btMultiBodyJointLimitConstraint.cpp + Featherstone/btMultiBodyConstraint.cpp + Featherstone/btMultiBodyPoint2Point.cpp + Featherstone/btMultiBodyJointMotor.cpp + MLCPSolvers/btDantzigLCP.cpp + MLCPSolvers/btMLCPSolver.cpp +) + +SET(Root_HDRS + ../btBulletDynamicsCommon.h + ../btBulletCollisionCommon.h +) +SET(ConstraintSolver_HDRS + ConstraintSolver/btConeTwistConstraint.h + ConstraintSolver/btConstraintSolver.h + ConstraintSolver/btContactConstraint.h + ConstraintSolver/btContactSolverInfo.h + ConstraintSolver/btFixedConstraint.h + ConstraintSolver/btGearConstraint.h + ConstraintSolver/btGeneric6DofConstraint.h + ConstraintSolver/btGeneric6DofSpringConstraint.h + ConstraintSolver/btHinge2Constraint.h + ConstraintSolver/btHingeConstraint.h + ConstraintSolver/btJacobianEntry.h + ConstraintSolver/btPoint2PointConstraint.h + ConstraintSolver/btSequentialImpulseConstraintSolver.h + ConstraintSolver/btSliderConstraint.h + ConstraintSolver/btSolve2LinearConstraint.h + ConstraintSolver/btSolverBody.h + ConstraintSolver/btSolverConstraint.h + ConstraintSolver/btTypedConstraint.h + ConstraintSolver/btUniversalConstraint.h +) +SET(Dynamics_HDRS + Dynamics/btActionInterface.h + Dynamics/btDiscreteDynamicsWorld.h + Dynamics/btDynamicsWorld.h + Dynamics/btSimpleDynamicsWorld.h + Dynamics/btRigidBody.h +) +SET(Vehicle_HDRS + Vehicle/btRaycastVehicle.h + Vehicle/btVehicleRaycaster.h + Vehicle/btWheelInfo.h +) + +SET(Featherstone_HDRS + Featherstone/btMultiBody.h + Featherstone/btMultiBodyConstraintSolver.h + Featherstone/btMultiBodyDynamicsWorld.h + Featherstone/btMultiBodyLink.h + Featherstone/btMultiBodyLinkCollider.h + Featherstone/btMultiBodySolverConstraint.h + Featherstone/btMultiBodyConstraint.h + Featherstone/btMultiBodyJointLimitConstraint.h + Featherstone/btMultiBodyConstraint.h + Featherstone/btMultiBodyPoint2Point.h + Featherstone/btMultiBodyJointMotor.h +) + +SET(MLCPSolvers_HDRS + MLCPSolvers/btDantzigLCP.h + MLCPSolvers/btDantzigSolver.h + MLCPSolvers/btMLCPSolver.h + MLCPSolvers/btMLCPSolverInterface.h + MLCPSolvers/btPATHSolver.h + MLCPSolvers/btSolveProjectedGaussSeidel.h +) + +SET(Character_HDRS + Character/btCharacterControllerInterface.h + Character/btKinematicCharacterController.h +) + + + +SET(BulletDynamics_HDRS + ${Root_HDRS} + ${ConstraintSolver_HDRS} + ${Dynamics_HDRS} + ${Vehicle_HDRS} + ${Character_HDRS} + ${Featherstone_HDRS} + ${MLCPSolvers_HDRS} +) + + +ADD_LIBRARY(BulletDynamics ${BulletDynamics_SRCS} ${BulletDynamics_HDRS}) +SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletDynamics BulletCollision LinearMath) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletDynamics DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletDynamics RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + INSTALL(FILES ../btBulletDynamicsCommon.h +DESTINATION ${INCLUDE_INSTALL_DIR}/BulletDynamics) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${ConstraintSolver_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/ConstraintSolver) + SET_PROPERTY(SOURCE ${Dynamics_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Dynamics) + SET_PROPERTY(SOURCE ${Vehicle_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Vehicle) + SET_PROPERTY(SOURCE ${Character_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Character) + SET_PROPERTY(SOURCE ${Featherstone_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Featherstone) + SET_PROPERTY(SOURCE ${MLCPSolvers_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MLCPSolvers) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletDynamics/Character/btCharacterControllerInterface.h b/Code/Physics/src/BulletDynamics/Character/btCharacterControllerInterface.h new file mode 100644 index 00000000..dffb06df --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Character/btCharacterControllerInterface.h @@ -0,0 +1,47 @@ +/* +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 BT_CHARACTER_CONTROLLER_INTERFACE_H +#define BT_CHARACTER_CONTROLLER_INTERFACE_H + +#include "LinearMath/btVector3.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" + +class btCollisionShape; +class btRigidBody; +class btCollisionWorld; + +class btCharacterControllerInterface : public btActionInterface +{ +public: + btCharacterControllerInterface () {}; + virtual ~btCharacterControllerInterface () {}; + + virtual void setWalkDirection(const btVector3& walkDirection) = 0; + virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0; + virtual void reset ( btCollisionWorld* collisionWorld ) = 0; + virtual void warp (const btVector3& origin) = 0; + + virtual void preStep ( btCollisionWorld* collisionWorld) = 0; + virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0; + virtual bool canJump () const = 0; + virtual void jump () = 0; + + virtual bool onGround () const = 0; + virtual void setUpInterpolate (bool value) = 0; +}; + +#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H + diff --git a/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.cpp new file mode 100644 index 00000000..8f1cd20b --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.cpp @@ -0,0 +1,770 @@ +/* +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 +#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" + + +// static helper method +static btVector3 +getNormalizedVector(const btVector3& v) +{ + btVector3 n = v.normalized(); + if (n.length() < SIMD_EPSILON) { + n.setValue(0, 0, 0); + } + return n; +} + + +///@todo Interact with dynamic objects, +///Ride kinematicly animated platforms properly +///More realistic (or maybe just a config option) falling +/// -> Should integrate falling velocity manually and use that in stepDown() +///Support jumping +///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 = me; + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + { + if (rayResult.m_collisionObject == m_me) + return 1.0; + + return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace); + } +protected: + btCollisionObject* m_me; +}; + +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.0); + + if (!convexResult.m_hitCollisionObject->hasContactResponse()) + return btScalar(1.0); + + btVector3 hitNormalWorld; + if (normalInWorldSpace) + { + hitNormalWorld = convexResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + + btScalar dotUp = m_up.dot(hitNormalWorld); + if (dotUp < m_minSlopeDot) { + return btScalar(1.0); + } + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } +protected: + btCollisionObject* m_me; + const btVector3 m_up; + btScalar m_minSlopeDot; +}; + +/* + * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal' + * + * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html + */ +btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal) +{ + return direction - (btScalar(2.0) * direction.dot(normal)) * normal; +} + +/* + * Returns the portion of 'direction' that is parallel to 'normal' + */ +btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal) +{ + btScalar magnitude = direction.dot(normal); + return normal * magnitude; +} + +/* + * Returns the portion of 'direction' that is perpindicular to 'normal' + */ +btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal) +{ + return direction - parallelComponent(direction, normal); +} + +btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis) +{ + m_upAxis = upAxis; + m_addedMargin = 0.02; + m_walkDirection.setValue(0,0,0); + m_useGhostObjectSweepTest = true; + m_ghostObject = ghostObject; + m_stepHeight = stepHeight; + m_turnAngle = btScalar(0.0); + m_convexShape=convexShape; + m_useWalkDirection = true; // use walk direction by default, legacy behavior + m_velocityTimeInterval = 0.0; + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + m_gravity = 9.8 * 3 ; // 3G acceleration. + m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s. + m_jumpSpeed = 10.0; // ? + m_wasOnGround = false; + m_wasJumping = false; + m_interpolateUp = true; + setMaxSlope(btRadians(45.0)); + m_currentStepOffset = 0; + full_drop = false; + bounce_fix = false; +} + +btKinematicCharacterController::~btKinematicCharacterController () +{ +} + +btPairCachingGhostObject* btKinematicCharacterController::getGhostObject() +{ + return m_ghostObject; +} + +bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld) +{ + // Here we must refresh the overlapping paircache as the penetrating movement itself or the + // previous recovery iteration might have used setWorldTransform and pushed us into an object + // that is not in the previous cache contents from the last timestep, as will happen if we + // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck. + // + // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase + // paircache and the ghostobject's internal paircache at the same time. /BW + + btVector3 minAabb, maxAabb; + m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb); + collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(), + minAabb, + maxAabb, + collisionWorld->getDispatcher()); + + bool penetration = false; + + collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher()); + + m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); + + btScalar maxPen = btScalar(0.0); + for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++) + { + m_manifoldArray.resize(0); + + btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; + + btCollisionObject* obj0 = static_cast(collisionPair->m_pProxy0->m_clientObject); + btCollisionObject* obj1 = static_cast(collisionPair->m_pProxy1->m_clientObject); + + if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse())) + continue; + + if (collisionPair->m_algorithm) + collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray); + + + for (int j=0;jgetBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0); + for (int p=0;pgetNumContacts();p++) + { + const btManifoldPoint&pt = manifold->getContactPoint(p); + + btScalar dist = pt.getDistance(); + + if (dist < 0.0) + { + if (dist < maxPen) + { + maxPen = dist; + m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? + + } + m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2); + penetration = true; + } else { + //printf("touching %f\n", dist); + } + } + + //manifold->clearManifold(); + } + } + btTransform newTrans = m_ghostObject->getWorldTransform(); + newTrans.setOrigin(m_currentPosition); + m_ghostObject->setWorldTransform(newTrans); +// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]); + return penetration; +} + +void btKinematicCharacterController::stepUp ( btCollisionWorld* world) +{ + // phase 1: up + btTransform start, end; + m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f)); + + start.setIdentity (); + end.setIdentity (); + + /* FIXME: Handle penetration properly */ + start.setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin)); + end.setOrigin (m_targetPosition); + + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071)); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration); + } + else + { + world->convexSweepTest (m_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]) > 0.0) + { + // we moved up only a fraction of the step height + m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction; + if (m_interpolateUp == true) + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + else + m_currentPosition = m_targetPosition; + } + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + } else { + m_currentStepOffset = m_stepHeight; + m_currentPosition = m_targetPosition; + } +} + +void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag) +{ + btVector3 movementDirection = m_targetPosition - m_currentPosition; + btScalar movementLength = movementDirection.length(); + if (movementLength>SIMD_EPSILON) + { + movementDirection.normalize(); + + btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal); + reflectDir.normalize(); + + btVector3 parallelDir, perpindicularDir; + + parallelDir = parallelComponent (reflectDir, hitNormal); + perpindicularDir = perpindicularComponent (reflectDir, hitNormal); + + m_targetPosition = m_currentPosition; + if (0)//tangentMag != 0.0) + { + btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength); +// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]); + m_targetPosition += parComponent; + } + + if (normalMag != 0.0) + { + btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength); +// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]); + m_targetPosition += perpComponent; + } + } else + { +// printf("movementLength don't normalize a zero vector\n"); + } +} + +void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove) +{ + // printf("m_normalizedDirection=%f,%f,%f\n", + // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]); + // phase 2: forward and strafe + btTransform start, end; + m_targetPosition = m_currentPosition + walkMove; + + start.setIdentity (); + end.setIdentity (); + + btScalar fraction = 1.0; + btScalar distance2 = (m_currentPosition-m_targetPosition).length2(); +// printf("distance2=%f\n",distance2); + + if (m_touchingContact) + { + if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0)) + { + //interferes with step movement + //updateTargetPositionBasedOnCollision (m_touchingNormal); + } + } + + int maxIter = 10; + + while (fraction > btScalar(0.01) && maxIter-- > 0) + { + start.setOrigin (m_currentPosition); + end.setOrigin (m_targetPosition); + btVector3 sweepDirNegative(m_currentPosition - m_targetPosition); + + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0)); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + + btScalar margin = m_convexShape->getMargin(); + m_convexShape->setMargin(margin + m_addedMargin); + + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } else + { + collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } + + m_convexShape->setMargin(margin); + + + fraction -= callback.m_closestHitFraction; + + if (callback.hasHit()) + { + // we moved only a fraction + btScalar hitDistance; + hitDistance = (callback.m_hitPointWorld - m_currentPosition).length(); + +// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + + updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld); + btVector3 currentDir = m_targetPosition - m_currentPosition; + distance2 = currentDir.length2(); + if (distance2 > SIMD_EPSILON) + { + currentDir.normalize(); + /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */ + if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0)) + { + break; + } + } else + { +// printf("currentDir: don't normalize a zero vector\n"); + break; + } + + } else { + // we moved whole way + m_currentPosition = m_targetPosition; + } + + // if (callback.m_closestHitFraction == 0.f) + // break; + + } +} + +void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt) +{ + btTransform start, end, end_double; + bool runonce = false; + + // phase 3: down + /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0; + btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep); + btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt; + btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity; + m_targetPosition -= (step_drop + gravity_drop);*/ + + btVector3 orig_position = m_targetPosition; + + btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; + + if(downVelocity > 0.0 && downVelocity > m_fallSpeed + && (m_wasOnGround || !m_wasJumping)) + downVelocity = m_fallSpeed; + + btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + m_targetPosition -= step_drop; + + btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + btKinematicClosestNotMeConvexResultCallback callback2 (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine); + callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + while (1) + { + start.setIdentity (); + end.setIdentity (); + + end_double.setIdentity (); + + start.setOrigin (m_currentPosition); + end.setOrigin (m_targetPosition); + + //set double test for 2x the step drop, to check for a large drop vs small drop + end_double.setOrigin (m_targetPosition - step_drop); + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + + if (!callback.hasHit()) + { + //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial) + m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } + } else + { + collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + + if (!callback.hasHit()) + { + //test a double fall height, to see if the character should interpolate it's fall (large) or not (small) + collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration); + } + } + + btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; + bool has_hit = false; + if (bounce_fix == true) + has_hit = callback.hasHit() || callback2.hasHit(); + else + has_hit = callback2.hasHit(); + + if(downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit == true && runonce == false + && (m_wasOnGround || !m_wasJumping)) + { + //redo the velocity calculation when falling a small amount, for fast stairs motion + //for larger falls, use the smoother/slower interpolated movement by not touching the target position + + m_targetPosition = orig_position; + downVelocity = m_stepHeight; + + btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + m_targetPosition -= step_drop; + runonce = true; + continue; //re-run previous tests + } + break; + } + + if (callback.hasHit() || runonce == true) + { + // we dropped a fraction of the height -> hit floor + + btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2; + + //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY()); + + if (bounce_fix == true) + { + if (full_drop == true) + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + else + //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction); + } + else + m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); + + full_drop = false; + + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + m_wasJumping = false; + } else { + // we dropped the full height + + full_drop = true; + + if (bounce_fix == true) + { + downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt; + if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping)) + { + m_targetPosition += step_drop; //undo previous target change + downVelocity = m_fallSpeed; + step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity); + m_targetPosition -= step_drop; + } + } + //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY()); + + m_currentPosition = m_targetPosition; + } +} + + + +void btKinematicCharacterController::setWalkDirection +( +const btVector3& walkDirection +) +{ + m_useWalkDirection = true; + m_walkDirection = walkDirection; + m_normalizedDirection = getNormalizedVector(m_walkDirection); +} + + + +void btKinematicCharacterController::setVelocityForTimeInterval +( +const btVector3& velocity, +btScalar timeInterval +) +{ +// printf("setVelocity!\n"); +// printf(" interval: %f\n", timeInterval); +// printf(" velocity: (%f, %f, %f)\n", +// velocity.x(), velocity.y(), velocity.z()); + + m_useWalkDirection = false; + m_walkDirection = velocity; + m_normalizedDirection = getNormalizedVector(m_walkDirection); + m_velocityTimeInterval += timeInterval; +} + +void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld ) +{ + m_verticalVelocity = 0.0; + m_verticalOffset = 0.0; + m_wasOnGround = false; + m_wasJumping = false; + m_walkDirection.setValue(0,0,0); + m_velocityTimeInterval = 0.0; + + //clear pair cache + btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache(); + while (cache->getOverlappingPairArray().size() > 0) + { + cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher()); + } +} + +void btKinematicCharacterController::warp (const btVector3& origin) +{ + btTransform xform; + xform.setIdentity(); + xform.setOrigin (origin); + m_ghostObject->setWorldTransform (xform); +} + + +void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld) +{ + + int numPenetrationLoops = 0; + m_touchingContact = false; + while (recoverFromPenetration (collisionWorld)) + { + numPenetrationLoops++; + m_touchingContact = true; + if (numPenetrationLoops > 4) + { + //printf("character could not recover from penetration = %d\n", numPenetrationLoops); + break; + } + } + + m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); + m_targetPosition = m_currentPosition; +// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); + + +} + +#include + +void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt) +{ +// printf("playerStep(): "); +// printf(" dt = %f", dt); + + // quick check... + if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) { +// printf("\n"); + return; // no motion + } + + m_wasOnGround = onGround(); + + // Update fall velocity. + 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; + + + btTransform xform; + xform = m_ghostObject->getWorldTransform (); + +// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]); +// printf("walkSpeed=%f\n",walkSpeed); + + stepUp (collisionWorld); + if (m_useWalkDirection) { + stepForwardAndStrafe (collisionWorld, m_walkDirection); + } else { + //printf(" time: %f", m_velocityTimeInterval); + // still have some time left for moving! + btScalar dtMoving = + (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval; + m_velocityTimeInterval -= dt; + + // how far will we move while we are moving? + btVector3 move = m_walkDirection * dtMoving; + + //printf(" dtMoving: %f", dtMoving); + + // okay, step + stepForwardAndStrafe(collisionWorld, move); + } + stepDown (collisionWorld, dt); + + // printf("\n"); + + xform.setOrigin (m_currentPosition); + m_ghostObject->setWorldTransform (xform); +} + +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; + +#if 0 + currently no jumping. + btTransform xform; + m_rigidBody->getMotionState()->getWorldTransform (xform); + btVector3 up = xform.getBasis()[1]; + up.normalize (); + btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0); + m_rigidBody->applyCentralImpulse (up * magnitude); +#endif +} + +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 m_verticalVelocity == 0.0 && m_verticalOffset == 0.0; +} + + +btVector3* btKinematicCharacterController::getUpAxisDirections() +{ + static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) }; + + return sUpAxisDirection; +} + +void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer) +{ +} + +void btKinematicCharacterController::setUpInterpolate(bool value) +{ + m_interpolateUp = value; +} diff --git a/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.h b/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.h new file mode 100644 index 00000000..add6f30a --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.h @@ -0,0 +1,170 @@ +/* +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 BT_KINEMATIC_CHARACTER_CONTROLLER_H +#define BT_KINEMATIC_CHARACTER_CONTROLLER_H + +#include "LinearMath/btVector3.h" + +#include "btCharacterControllerInterface.h" + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + + +class btCollisionShape; +class btConvexShape; +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. +ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterControllerInterface +{ +protected: + + btScalar m_halfHeight; + + btPairCachingGhostObject* m_ghostObject; + btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast + + 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_turnAngle; + + btScalar m_stepHeight; + + btScalar m_addedMargin;//@todo: remove this and fix the code + + ///this is the desired walk direction, set by the user + btVector3 m_walkDirection; + btVector3 m_normalizedDirection; + + //some internal variables + btVector3 m_currentPosition; + btScalar m_currentStepOffset; + btVector3 m_targetPosition; + + ///keep track of the contact manifolds + btManifoldArray m_manifoldArray; + + bool m_touchingContact; + btVector3 m_touchingNormal; + + bool m_wasOnGround; + bool m_wasJumping; + bool m_useGhostObjectSweepTest; + bool m_useWalkDirection; + btScalar m_velocityTimeInterval; + int m_upAxis; + + static btVector3* getUpAxisDirections(); + bool m_interpolateUp; + bool full_drop; + bool bounce_fix; + + btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal); + btVector3 parallelComponent (const btVector3& direction, const btVector3& normal); + btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal); + + bool recoverFromPenetration ( btCollisionWorld* collisionWorld); + void stepUp (btCollisionWorld* collisionWorld); + void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); + void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove); + void stepDown (btCollisionWorld* collisionWorld, btScalar dt); +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1); + ~btKinematicCharacterController (); + + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime) + { + preStep ( collisionWorld); + playerStep (collisionWorld, deltaTime); + } + + ///btActionInterface interface + void debugDraw(btIDebugDraw* debugDrawer); + + void setUpAxis (int axis) + { + if (axis < 0) + axis = 0; + if (axis > 2) + axis = 2; + 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 ( btCollisionWorld* collisionWorld ); + 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; + + btPairCachingGhostObject* getGhostObject(); + void setUseGhostSweepTest(bool useGhostObjectSweepTest) + { + m_useGhostObjectSweepTest = useGhostObjectSweepTest; + } + + bool onGround () const; + void setUpInterpolate (bool value); +}; + +#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp new file mode 100644 index 00000000..15a4c92d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -0,0 +1,1141 @@ +/* +Bullet Continuous Collision Detection and Physics Library +btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marcus Hennix +*/ + + +#include "btConeTwistConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" +#include + + + +//#define CONETWIST_USE_OBSOLETE_SOLVER true +#define CONETWIST_USE_OBSOLETE_SOLVER false +#define CONETWIST_DEF_FIX_THRESH btScalar(.05f) + + +SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld) +{ + btVector3 vec = axis * invInertiaWorld; + return axis.dot(vec); +} + + + + +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame,const btTransform& rbBFrame) + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + m_angularOnly(false), + m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) +{ + init(); +} + +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), + m_angularOnly(false), + m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) +{ + m_rbBFrame = m_rbAFrame; + m_rbBFrame.setOrigin(btVector3(0., 0., 0.)); + init(); +} + + +void btConeTwistConstraint::init() +{ + m_angularOnly = false; + m_solveTwistLimit = false; + m_solveSwingLimit = false; + m_bMotorEnabled = false; + m_maxMotorImpulse = btScalar(-1); + + setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT)); + m_damping = btScalar(0.01); + m_fixThresh = CONETWIST_DEF_FIX_THRESH; + m_flags = 0; + m_linCFM = btScalar(0.f); + m_linERP = btScalar(0.7f); + m_angCFM = btScalar(0.f); +} + + +void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 3; + info->nub = 3; + calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); + if(m_solveSwingLimit) + { + info->m_numConstraintRows++; + info->nub--; + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + if(m_solveTwistLimit) + { + info->m_numConstraintRows++; + info->nub--; + } + } +} + +void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + //always reserve 6 rows: object transform is not available on SPU + info->m_numConstraintRows = 6; + info->nub = 0; + +} + + +void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) +{ + getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); +} + +void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +{ + calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB); + + btAssert(!m_useSolveConstraintObsolete); + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; + btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[info->rowskip+1] = -1; + info->m_J2linearAxis[2*info->rowskip+2] = -1; + btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + // set right hand side + btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp; + btScalar k = info->fps * linERP; + int j; + for (j=0; j<3; j++) + { + info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]); + info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY; + info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY; + if(m_flags & BT_CONETWIST_FLAGS_LIN_CFM) + { + info->cfm[j*info->rowskip] = m_linCFM; + } + } + int row = 3; + int srow = row * info->rowskip; + btVector3 ax1; + // angular limits + if(m_solveSwingLimit) + { + btScalar *J1 = info->m_J1angularAxis; + btScalar *J2 = info->m_J2angularAxis; + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { + btTransform trA = transA*m_rbAFrame; + btVector3 p = trA.getBasis().getColumn(1); + btVector3 q = trA.getBasis().getColumn(2); + int srow1 = srow + info->rowskip; + J1[srow+0] = p[0]; + J1[srow+1] = p[1]; + J1[srow+2] = p[2]; + J1[srow1+0] = q[0]; + J1[srow1+1] = q[1]; + J1[srow1+2] = q[2]; + J2[srow+0] = -p[0]; + J2[srow+1] = -p[1]; + J2[srow+2] = -p[2]; + J2[srow1+0] = -q[0]; + J2[srow1+1] = -q[1]; + J2[srow1+2] = -q[2]; + btScalar fact = info->fps * m_relaxationFactor; + info->m_constraintError[srow] = fact * m_swingAxis.dot(p); + info->m_constraintError[srow1] = fact * m_swingAxis.dot(q); + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + info->m_lowerLimit[srow1] = -SIMD_INFINITY; + info->m_upperLimit[srow1] = SIMD_INFINITY; + srow = srow1 + info->rowskip; + } + else + { + ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + btScalar k = info->fps * m_biasFactor; + + info->m_constraintError[srow] = k * m_swingCorrection; + if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM) + { + info->cfm[srow] = m_angCFM; + } + // m_swingCorrection is always positive or 0 + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + srow += info->rowskip; + } + } + if(m_solveTwistLimit) + { + ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor; + btScalar *J1 = info->m_J1angularAxis; + btScalar *J2 = info->m_J2angularAxis; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + btScalar k = info->fps * m_biasFactor; + info->m_constraintError[srow] = k * m_twistCorrection; + if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM) + { + info->cfm[srow] = m_angCFM; + } + if(m_twistSpan > 0.0f) + { + + if(m_twistCorrection > 0.0f) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + srow += info->rowskip; + } +} + + + +void btConeTwistConstraint::buildJacobian() +{ + if (m_useSolveConstraintObsolete) + { + m_appliedImpulse = btScalar(0.); + m_accTwistLimitImpulse = btScalar(0.); + m_accSwingLimitImpulse = btScalar(0.); + m_accMotorImpulse = btVector3(0.,0.,0.); + + if (!m_angularOnly) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + + for (int i=0;i<3;i++) + { + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + } + } + + calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); + } +} + + + +void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +{ + #ifndef __SPU__ + if (m_useSolveConstraintObsolete) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + + btScalar tau = btScalar(0.3); + + //linear part + if (!m_angularOnly) + { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1; + bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1); + btVector3 vel2; + bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2); + btVector3 vel = vel1 - vel2; + + for (int i=0;i<3;i++) + { + const btVector3& normal = m_jac[i].m_linearJointAxis; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + btScalar rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; + m_appliedImpulse += impulse; + + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); + btVector3 ftorqueAxis2 = rel_pos2.cross(normal); + bodyA.internalApplyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); + bodyB.internalApplyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); + + } + } + + // apply motor + if (m_bMotorEnabled) + { + // compute current and predicted transforms + btTransform trACur = m_rbA.getCenterOfMassTransform(); + btTransform trBCur = m_rbB.getCenterOfMassTransform(); + btVector3 omegaA; bodyA.internalGetAngularVelocity(omegaA); + btVector3 omegaB; bodyB.internalGetAngularVelocity(omegaB); + btTransform trAPred; trAPred.setIdentity(); + btVector3 zerovec(0,0,0); + btTransformUtil::integrateTransform( + trACur, zerovec, omegaA, timeStep, trAPred); + btTransform trBPred; trBPred.setIdentity(); + btTransformUtil::integrateTransform( + trBCur, zerovec, omegaB, timeStep, trBPred); + + // compute desired transforms in world + btTransform trPose(m_qTarget); + btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse(); + btTransform trADes = trBPred * trABDes; + btTransform trBDes = trAPred * trABDes.inverse(); + + // compute desired omegas in world + btVector3 omegaADes, omegaBDes; + + btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes); + btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes); + + // compute delta omegas + btVector3 dOmegaA = omegaADes - omegaA; + btVector3 dOmegaB = omegaBDes - omegaB; + + // compute weighted avg axis of dOmega (weighting based on inertias) + btVector3 axisA, axisB; + btScalar kAxisAInv = 0, kAxisBInv = 0; + + if (dOmegaA.length2() > SIMD_EPSILON) + { + axisA = dOmegaA.normalized(); + kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA); + } + + if (dOmegaB.length2() > SIMD_EPSILON) + { + axisB = dOmegaB.normalized(); + kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB); + } + + btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB; + + static bool bDoTorque = true; + if (bDoTorque && avgAxis.length2() > SIMD_EPSILON) + { + avgAxis.normalize(); + kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis); + kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis); + btScalar kInvCombined = kAxisAInv + kAxisBInv; + + btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) / + (kInvCombined * kInvCombined); + + if (m_maxMotorImpulse >= 0) + { + btScalar fMaxImpulse = m_maxMotorImpulse; + if (m_bNormalizedMotorStrength) + fMaxImpulse = fMaxImpulse/kAxisAInv; + + btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse; + btScalar newUnclampedMag = newUnclampedAccImpulse.length(); + if (newUnclampedMag > fMaxImpulse) + { + newUnclampedAccImpulse.normalize(); + newUnclampedAccImpulse *= fMaxImpulse; + impulse = newUnclampedAccImpulse - m_accMotorImpulse; + } + m_accMotorImpulse += impulse; + } + + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + + } + } + else if (m_damping > SIMD_EPSILON) // no motor: do a little damping + { + btVector3 angVelA; bodyA.internalGetAngularVelocity(angVelA); + btVector3 angVelB; bodyB.internalGetAngularVelocity(angVelB); + btVector3 relVel = angVelB - angVelA; + if (relVel.length2() > SIMD_EPSILON) + { + btVector3 relVelAxis = relVel.normalized(); + btScalar m_kDamping = btScalar(1.) / + (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) + + getRigidBodyB().computeAngularImpulseDenominator(relVelAxis)); + btVector3 impulse = m_damping * m_kDamping * relVel; + + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + } + } + + // joint limits + { + ///solve angular part + btVector3 angVelA; + bodyA.internalGetAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.internalGetAngularVelocity(angVelB); + + // solve swing limit + if (m_solveSwingLimit) + { + btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep; + btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis); + if (relSwingVel > 0) + amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor; + btScalar impulseMag = amplitude * m_kSwing; + + // Clamp the accumulated impulse + btScalar temp = m_accSwingLimitImpulse; + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); + impulseMag = m_accSwingLimitImpulse - temp; + + btVector3 impulse = m_swingAxis * impulseMag; + + // don't let cone response affect twist + // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit) + { + btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA; + btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple; + impulse = impulseNoTwistCouple; + } + + impulseMag = impulse.length(); + btVector3 noTwistSwingAxis = impulse / impulseMag; + + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag); + } + + + // solve twist limit + if (m_solveTwistLimit) + { + btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep; + btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis ); + if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important) + amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor; + btScalar impulseMag = amplitude * m_kTwist; + + // Clamp the accumulated impulse + btScalar temp = m_accTwistLimitImpulse; + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); + impulseMag = m_accTwistLimitImpulse - temp; + + // btVector3 impulse = m_twistAxis * impulseMag; + + bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag); + bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag); + } + } + } +#else +btAssert(0); +#endif //__SPU__ +} + + + + +void btConeTwistConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + + +#ifndef __SPU__ +void btConeTwistConstraint::calcAngleInfo() +{ + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + + btVector3 b1Axis1,b1Axis2,b1Axis3; + btVector3 b2Axis1,b2Axis2; + + b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0); + b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0); + + btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + + btScalar swx=btScalar(0.),swy = btScalar(0.); + btScalar thresh = btScalar(10.); + btScalar fact; + + // Get Frame into world space + if (m_swingSpan1 >= btScalar(0.05f)) + { + b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis2); + swing1 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing1 *= fact; + } + + if (m_swingSpan2 >= btScalar(0.05f)) + { + b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis3); + swing2 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing2 *= fact; + } + + btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); + btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); + btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq; + + if (EllipseAngle > 1.0f) + { + m_swingCorrection = EllipseAngle-1.0f; + m_solveSwingLimit = true; + // Calculate necessary axis & factors + m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); + m_swingAxis.normalize(); + btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; + m_swingAxis *= swingAxisSign; + } + + // Twist limits + if (m_twistSpan >= btScalar(0.)) + { + btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1); + btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1); + btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); + btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); + m_twistAngle = twist; + +// btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); + btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.); + if (twist <= -m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = -(twist + m_twistSpan); + m_solveTwistLimit = true; + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + m_twistAxis *= -1.0f; + } + else if (twist > m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = (twist - m_twistSpan); + m_solveTwistLimit = true; + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + } + } +} +#endif //__SPU__ + +static btVector3 vTwist(1,0,0); // twist axis in constraint's space + + + +void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +{ + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + // compute rotation of A wrt B (in constraint space) + if (m_bMotorEnabled && (!m_useSolveConstraintObsolete)) + { // it is assumed that setMotorTarget() was alredy called + // and motor target m_qTarget is within constraint limits + // TODO : split rotation to pure swing and pure twist + // compute desired transforms in world + btTransform trPose(m_qTarget); + btTransform trA = transA * m_rbAFrame; + btTransform trB = transB * m_rbBFrame; + btTransform trDeltaAB = trB * trPose * trA.inverse(); + btQuaternion qDeltaAB = trDeltaAB.getRotation(); + btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z()); + float swingAxisLen2 = swingAxis.length2(); + if(btFuzzyZero(swingAxisLen2)) + { + return; + } + m_swingAxis = swingAxis; + m_swingAxis.normalize(); + m_swingCorrection = qDeltaAB.getAngle(); + if(!btFuzzyZero(m_swingCorrection)) + { + m_solveSwingLimit = true; + } + return; + } + + + { + // compute rotation of A wrt B (in constraint space) + btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation(); + btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation(); + btQuaternion qAB = qB.inverse() * qA; + // split rotation into cone and twist + // (all this is done from B's perspective. Maybe I should be averaging axes...) + btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize(); + btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize(); + btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize(); + + if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh) + { + btScalar swingAngle, swingLimit = 0; btVector3 swingAxis; + computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit); + + if (swingAngle > swingLimit * m_limitSoftness) + { + m_solveSwingLimit = true; + + // compute limit ratio: 0->1, where + // 0 == beginning of soft limit + // 1 == hard/real limit + m_swingLimitRatio = 1.f; + if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON) + { + m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/ + (swingLimit - swingLimit * m_limitSoftness); + } + + // swing correction tries to get back to soft limit + m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness); + + // adjustment of swing axis (based on ellipse normal) + adjustSwingAxisToUseEllipseNormal(swingAxis); + + // Calculate necessary axis & factors + m_swingAxis = quatRotate(qB, -swingAxis); + + m_twistAxisA.setValue(0,0,0); + + m_kSwing = btScalar(1.) / + (computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldA) + + computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldB)); + } + } + else + { + // you haven't set any limits; + // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?) + // anyway, we have either hinge or fixed joint + btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0); + btVector3 target; + btScalar x = ivB.dot(ivA); + btScalar y = ivB.dot(jvA); + btScalar z = ivB.dot(kvA); + if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { // fixed. We'll need to add one more row to constraint + if((!btFuzzyZero(y)) || (!(btFuzzyZero(z)))) + { + m_solveSwingLimit = true; + m_swingAxis = -ivB.cross(ivA); + } + } + else + { + if(m_swingSpan1 < m_fixThresh) + { // hinge around Y axis +// if(!(btFuzzyZero(y))) + if((!(btFuzzyZero(x))) || (!(btFuzzyZero(z)))) + { + m_solveSwingLimit = true; + if(m_swingSpan2 >= m_fixThresh) + { + y = btScalar(0.f); + btScalar span2 = btAtan2(z, x); + if(span2 > m_swingSpan2) + { + x = btCos(m_swingSpan2); + z = btSin(m_swingSpan2); + } + else if(span2 < -m_swingSpan2) + { + x = btCos(m_swingSpan2); + z = -btSin(m_swingSpan2); + } + } + } + } + else + { // hinge around Z axis +// if(!btFuzzyZero(z)) + if((!(btFuzzyZero(x))) || (!(btFuzzyZero(y)))) + { + m_solveSwingLimit = true; + if(m_swingSpan1 >= m_fixThresh) + { + z = btScalar(0.f); + btScalar span1 = btAtan2(y, x); + if(span1 > m_swingSpan1) + { + x = btCos(m_swingSpan1); + y = btSin(m_swingSpan1); + } + else if(span1 < -m_swingSpan1) + { + x = btCos(m_swingSpan1); + y = -btSin(m_swingSpan1); + } + } + } + } + target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0]; + target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1]; + target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2]; + target.normalize(); + m_swingAxis = -ivB.cross(target); + m_swingCorrection = m_swingAxis.length(); + m_swingAxis.normalize(); + } + } + + if (m_twistSpan >= btScalar(0.f)) + { + btVector3 twistAxis; + computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis); + + if (m_twistAngle > m_twistSpan*m_limitSoftness) + { + m_solveTwistLimit = true; + + m_twistLimitRatio = 1.f; + if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON) + { + m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/ + (m_twistSpan - m_twistSpan * m_limitSoftness); + } + + // twist correction tries to get back to soft limit + m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness); + + m_twistAxis = quatRotate(qB, -twistAxis); + + m_kTwist = btScalar(1.) / + (computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldA) + + computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldB)); + } + + if (m_solveSwingLimit) + m_twistAxisA = quatRotate(qA, -twistAxis); + } + else + { + m_twistAngle = btScalar(0.f); + } + } +} + + + +// given a cone rotation in constraint space, (pre: twist must already be removed) +// this method computes its corresponding swing angle and axis. +// more interestingly, it computes the cone/swing limit (angle) for this cone "pose". +void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, + btScalar& swingAngle, // out + btVector3& vSwingAxis, // out + btScalar& swingLimit) // out +{ + swingAngle = qCone.getAngle(); + if (swingAngle > SIMD_EPSILON) + { + vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z()); + vSwingAxis.normalize(); +#if 0 + // non-zero twist?! this should never happen. + btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON)); +#endif + + // Compute limit for given swing. tricky: + // Given a swing axis, we're looking for the intersection with the bounding cone ellipse. + // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.) + + // For starters, compute the direction from center to surface of ellipse. + // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis. + // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.) + btScalar xEllipse = vSwingAxis.y(); + btScalar yEllipse = -vSwingAxis.z(); + + // Now, we use the slope of the vector (using x/yEllipse) and find the length + // of the line that intersects the ellipse: + // x^2 y^2 + // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) + // a^2 b^2 + // Do the math and it should be clear. + + swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1 + if (fabs(xEllipse) > SIMD_EPSILON) + { + btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); + norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); + btScalar swingLimit2 = (1 + surfaceSlope2) / norm; + swingLimit = sqrt(swingLimit2); + } + + // test! + /*swingLimit = m_swingSpan2; + if (fabs(vSwingAxis.z()) > SIMD_EPSILON) + { + btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2; + btScalar sinphi = m_swingSpan2 / sqrt(mag_2); + btScalar phi = asin(sinphi); + btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z())); + btScalar alpha = 3.14159f - theta - phi; + btScalar sinalpha = sin(alpha); + swingLimit = m_swingSpan1 * sinphi/sinalpha; + }*/ + } + else if (swingAngle < 0) + { + // this should never happen! +#if 0 + btAssert(0); +#endif + } +} + +btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const +{ + // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone) + btScalar xEllipse = btCos(fAngleInRadians); + btScalar yEllipse = btSin(fAngleInRadians); + + // Use the slope of the vector (using x/yEllipse) and find the length + // of the line that intersects the ellipse: + // x^2 y^2 + // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits) + // a^2 b^2 + // Do the math and it should be clear. + + float swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1) + if (fabs(xEllipse) > SIMD_EPSILON) + { + btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); + norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); + btScalar swingLimit2 = (1 + surfaceSlope2) / norm; + swingLimit = sqrt(swingLimit2); + } + + // convert into point in constraint space: + // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively + btVector3 vSwingAxis(0, xEllipse, -yEllipse); + btQuaternion qSwing(vSwingAxis, swingLimit); + btVector3 vPointInConstraintSpace(fLength,0,0); + return quatRotate(qSwing, vPointInConstraintSpace); +} + +// given a twist rotation in constraint space, (pre: cone must already be removed) +// this method computes its corresponding angle and axis. +void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, + btScalar& twistAngle, // out + btVector3& vTwistAxis) // out +{ + btQuaternion qMinTwist = qTwist; + twistAngle = qTwist.getAngle(); + + if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. + { + qMinTwist = -(qTwist); + twistAngle = qMinTwist.getAngle(); + } + if (twistAngle < 0) + { + // this should never happen +#if 0 + btAssert(0); +#endif + } + + vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z()); + if (twistAngle > SIMD_EPSILON) + vTwistAxis.normalize(); +} + + +void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const +{ + // the swing axis is computed as the "twist-free" cone rotation, + // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2). + // so, if we're outside the limits, the closest way back inside the cone isn't + // along the vector back to the center. better (and more stable) to use the ellipse normal. + + // convert swing axis to direction from center to surface of ellipse + // (ie. rotate 2D vector by PI/2) + btScalar y = -vSwingAxis.z(); + btScalar z = vSwingAxis.y(); + + // do the math... + if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0. + { + // compute gradient/normal of ellipse surface at current "point" + btScalar grad = y/z; + grad *= m_swingSpan2 / m_swingSpan1; + + // adjust y/z to represent normal at point (instead of vector to point) + if (y > 0) + y = fabs(grad * z); + else + y = -fabs(grad * z); + + // convert ellipse direction back to swing axis + vSwingAxis.setZ(-y); + vSwingAxis.setY( z); + vSwingAxis.normalize(); + } +} + + + +void btConeTwistConstraint::setMotorTarget(const btQuaternion &q) +{ + btTransform trACur = m_rbA.getCenterOfMassTransform(); + btTransform trBCur = m_rbB.getCenterOfMassTransform(); +// btTransform trABCur = trBCur.inverse() * trACur; +// btQuaternion qABCur = trABCur.getRotation(); +// btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame); + //btQuaternion qConstraintCur = trConstraintCur.getRotation(); + + btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation(); + setMotorTargetInConstraintSpace(qConstraint); +} + + +void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q) +{ + m_qTarget = q; + + // clamp motor target to within limits + { + btScalar softness = 1.f;//m_limitSoftness; + + // split into twist and cone + btVector3 vTwisted = quatRotate(m_qTarget, vTwist); + btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize(); + btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize(); + + // clamp cone + if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f)) + { + btScalar swingAngle, swingLimit; btVector3 swingAxis; + computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit); + + if (fabs(swingAngle) > SIMD_EPSILON) + { + if (swingAngle > swingLimit*softness) + swingAngle = swingLimit*softness; + else if (swingAngle < -swingLimit*softness) + swingAngle = -swingLimit*softness; + qTargetCone = btQuaternion(swingAxis, swingAngle); + } + } + + // clamp twist + if (m_twistSpan >= btScalar(0.05f)) + { + btScalar twistAngle; btVector3 twistAxis; + computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis); + + if (fabs(twistAngle) > SIMD_EPSILON) + { + // eddy todo: limitSoftness used here??? + if (twistAngle > m_twistSpan*softness) + twistAngle = m_twistSpan*softness; + else if (twistAngle < -m_twistSpan*softness) + twistAngle = -m_twistSpan*softness; + qTargetTwist = btQuaternion(twistAxis, twistAngle); + } + } + + m_qTarget = qTargetCone * qTargetTwist; + } +} + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btConeTwistConstraint::setParam(int num, btScalar value, int axis) +{ + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + if((axis >= 0) && (axis < 3)) + { + m_linERP = value; + m_flags |= BT_CONETWIST_FLAGS_LIN_ERP; + } + else + { + m_biasFactor = value; + } + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + if((axis >= 0) && (axis < 3)) + { + m_linCFM = value; + m_flags |= BT_CONETWIST_FLAGS_LIN_CFM; + } + else + { + m_angCFM = value; + m_flags |= BT_CONETWIST_FLAGS_ANG_CFM; + } + break; + default: + btAssertConstrParams(0); + break; + } +} + +///return the local value of parameter +btScalar btConeTwistConstraint::getParam(int num, int axis) const +{ + btScalar retVal = 0; + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + if((axis >= 0) && (axis < 3)) + { + btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP); + retVal = m_linERP; + } + else if((axis >= 3) && (axis < 6)) + { + retVal = m_biasFactor; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + if((axis >= 0) && (axis < 3)) + { + btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM); + retVal = m_linCFM; + } + else if((axis >= 3) && (axis < 6)) + { + btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM); + retVal = m_angCFM; + } + else + { + btAssertConstrParams(0); + } + break; + default : + btAssertConstrParams(0); + } + return retVal; +} + + +void btConeTwistConstraint::setFrames(const btTransform & frameA, const btTransform & frameB) +{ + m_rbAFrame = frameA; + m_rbBFrame = frameB; + buildJacobian(); + //calculateTransforms(); +} + + + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h new file mode 100644 index 00000000..1735b524 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -0,0 +1,381 @@ +/* +Bullet Continuous Collision Detection and Physics Library +btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marcus Hennix +*/ + + + +/* +Overview: + +btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc). +It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint". +It divides the 3 rotational DOFs into swing (movement within a cone) and twist. +Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape. +(Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.) + +In the contraint's frame of reference: +twist is along the x-axis, +and swing 1 and 2 are along the z and y axes respectively. +*/ + + + +#ifndef BT_CONETWISTCONSTRAINT_H +#define BT_CONETWISTCONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData +#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData" +#else +#define btConeTwistConstraintData2 btConeTwistConstraintData +#define btConeTwistConstraintDataName "btConeTwistConstraintData" +#endif //BT_USE_DOUBLE_PRECISION + + +class btRigidBody; + +enum btConeTwistFlags +{ + BT_CONETWIST_FLAGS_LIN_CFM = 1, + BT_CONETWIST_FLAGS_LIN_ERP = 2, + BT_CONETWIST_FLAGS_ANG_CFM = 4 +}; + +///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) +ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint +{ +#ifdef IN_PARALLELL_SOLVER +public: +#endif + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btTransform m_rbAFrame; + btTransform m_rbBFrame; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + btScalar m_damping; + + btScalar m_swingSpan1; + btScalar m_swingSpan2; + btScalar m_twistSpan; + + btScalar m_fixThresh; + + btVector3 m_swingAxis; + btVector3 m_twistAxis; + + btScalar m_kSwing; + btScalar m_kTwist; + + btScalar m_twistLimitSign; + btScalar m_swingCorrection; + btScalar m_twistCorrection; + + btScalar m_twistAngle; + + btScalar m_accSwingLimitImpulse; + btScalar m_accTwistLimitImpulse; + + bool m_angularOnly; + bool m_solveTwistLimit; + bool m_solveSwingLimit; + + bool m_useSolveConstraintObsolete; + + // not yet used... + btScalar m_swingLimitRatio; + btScalar m_twistLimitRatio; + btVector3 m_twistAxisA; + + // motor + bool m_bMotorEnabled; + bool m_bNormalizedMotorStrength; + btQuaternion m_qTarget; + btScalar m_maxMotorImpulse; + btVector3 m_accMotorImpulse; + + // parameters + int m_flags; + btScalar m_linCFM; + btScalar m_linERP; + btScalar m_angCFM; + +protected: + + void init(); + + void computeConeLimitInfo(const btQuaternion& qCone, // in + btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs + + void computeTwistLimitInfo(const btQuaternion& qTwist, // in + btScalar& twistAngle, btVector3& vTwistAxis); // all outs + + void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const; + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame); + + btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame); + + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); + + virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); + + + void updateRHS(btScalar timeStep); + + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + void setAngularOnly(bool angularOnly) + { + m_angularOnly = angularOnly; + } + + void setLimit(int limitIndex,btScalar limitValue) + { + switch (limitIndex) + { + case 3: + { + m_twistSpan = limitValue; + break; + } + case 4: + { + m_swingSpan2 = limitValue; + break; + } + case 5: + { + m_swingSpan1 = limitValue; + break; + } + default: + { + } + }; + } + + // setLimit(), a few notes: + // _softness: + // 0->1, recommend ~0.8->1. + // describes % of limits where movement is free. + // beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached. + // _biasFactor: + // 0->1?, recommend 0.3 +/-0.3 or so. + // strength with which constraint resists zeroth order (angular, not angular velocity) limit violation. + // __relaxationFactor: + // 0->1, recommend to stay near 1. + // the lower the value, the less the constraint will fight velocities which violate the angular limits. + void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { + m_swingSpan1 = _swingSpan1; + m_swingSpan2 = _swingSpan2; + m_twistSpan = _twistSpan; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + } + + const btTransform& getAFrame() { return m_rbAFrame; }; + const btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveTwistLimit() + { + return m_solveTwistLimit; + } + + inline int getSolveSwingLimit() + { + return m_solveTwistLimit; + } + + inline btScalar getTwistLimitSign() + { + return m_twistLimitSign; + } + + void calcAngleInfo(); + void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); + + inline btScalar getSwingSpan1() + { + return m_swingSpan1; + } + inline btScalar getSwingSpan2() + { + return m_swingSpan2; + } + inline btScalar getTwistSpan() + { + return m_twistSpan; + } + inline btScalar getTwistAngle() + { + return m_twistAngle; + } + bool isPastSwingLimit() { return m_solveSwingLimit; } + + void setDamping(btScalar damping) { m_damping = damping; } + + void enableMotor(bool b) { m_bMotorEnabled = b; } + void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; } + void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; } + + btScalar getFixThresh() { return m_fixThresh; } + void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; } + + // setMotorTarget: + // q: the desired rotation of bodyA wrt bodyB. + // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability) + // note: don't forget to enableMotor() + void setMotorTarget(const btQuaternion &q); + + // same as above, but q is the desired rotation of frameA wrt frameB in constraint space + void setMotorTargetInConstraintSpace(const btQuaternion &q); + + btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const; + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + + virtual void setFrames(const btTransform& frameA, const btTransform& frameB); + + const btTransform& getFrameOffsetA() const + { + return m_rbAFrame; + } + + const btTransform& getFrameOffsetB() const + { + return m_rbBFrame; + } + + + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + + + +struct btConeTwistConstraintDoubleData +{ + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; + btTransformDoubleData m_rbBFrame; + + //limits + double m_swingSpan1; + double m_swingSpan2; + double m_twistSpan; + double m_limitSoftness; + double m_biasFactor; + double m_relaxationFactor; + + double m_damping; + + + +}; + +#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION +///this structure is not used, except for loading pre-2.82 .bullet files +struct btConeTwistConstraintData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; + btTransformFloatData m_rbBFrame; + + //limits + float m_swingSpan1; + float m_swingSpan2; + float m_twistSpan; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + + float m_damping; + + char m_pad[4]; + +}; +#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION +// + +SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btConeTwistConstraintData2); + +} + + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*) dataBuffer; + btTypedConstraint::serialize(&cone->m_typeConstraintData,serializer); + + m_rbAFrame.serialize(cone->m_rbAFrame); + m_rbBFrame.serialize(cone->m_rbBFrame); + + cone->m_swingSpan1 = m_swingSpan1; + cone->m_swingSpan2 = m_swingSpan2; + cone->m_twistSpan = m_twistSpan; + cone->m_limitSoftness = m_limitSoftness; + cone->m_biasFactor = m_biasFactor; + cone->m_relaxationFactor = m_relaxationFactor; + cone->m_damping = m_damping; + + return btConeTwistConstraintDataName; +} + + +#endif //BT_CONETWISTCONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h new file mode 100644 index 00000000..1ba1cd1e --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -0,0 +1,64 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONSTRAINT_SOLVER_H +#define BT_CONSTRAINT_SOLVER_H + +#include "LinearMath/btScalar.h" + +class btPersistentManifold; +class btRigidBody; +class btCollisionObject; +class btTypedConstraint; +struct btContactSolverInfo; +struct btBroadphaseProxy; +class btIDebugDraw; +class btStackAlloc; +class btDispatcher; +/// btConstraintSolver provides solver interface + + +enum btConstraintSolverType +{ + BT_SEQUENTIAL_IMPULSE_SOLVER=1, + BT_MLCP_SOLVER=2 +}; + +class btConstraintSolver +{ + +public: + + virtual ~btConstraintSolver() {} + + virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;} + + ///solve a group of constraints + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer,btDispatcher* dispatcher) = 0; + + virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */) {;} + + ///clear internal cached data and reset random seed + virtual void reset() = 0; + + virtual btConstraintSolverType getSolverType() const=0; + + +}; + + + + +#endif //BT_CONSTRAINT_SOLVER_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp new file mode 100644 index 00000000..9d60d995 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -0,0 +1,178 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btContactConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + + + +btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB) +:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB), + m_contactManifold(*contactManifold) +{ + +} + +btContactConstraint::~btContactConstraint() +{ + +} + +void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold) +{ + m_contactManifold = *contactManifold; +} + +void btContactConstraint::getInfo1 (btConstraintInfo1* info) +{ + +} + +void btContactConstraint::getInfo2 (btConstraintInfo2* info) +{ + +} + +void btContactConstraint::buildJacobian() +{ + +} + + + + + +#include "btContactConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + + + +//response between two dynamic objects without friction and no restitution, assuming 0 penetration depth +btScalar resolveSingleCollision( + btRigidBody* body1, + btCollisionObject* colObj2, + const btVector3& contactPositionWorld, + const btVector3& contactNormalOnB, + const btContactSolverInfo& solverInfo, + btScalar distance) +{ + btRigidBody* body2 = btRigidBody::upcast(colObj2); + + + const btVector3& normal = contactNormalOnB; + + btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin(); + btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin(); + + btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btScalar combinedRestitution = 0.f; + btScalar restitution = combinedRestitution* -rel_vel; + + btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ; + btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping; + btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal); + btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f; + btScalar relaxation = 1.f; + btScalar jacDiagABInv = relaxation/(denom0+denom1); + + btScalar penetrationImpulse = positionalError * jacDiagABInv; + btScalar velocityImpulse = velocityError * jacDiagABInv; + + btScalar normalImpulse = penetrationImpulse+velocityImpulse; + normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse; + + body1->applyImpulse(normal*(normalImpulse), rel_pos1); + if (body2) + body2->applyImpulse(-normal*(normalImpulse), rel_pos2); + + return normalImpulse; +} + + +//bilateral constraint between two dynamic objects +void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep) +{ + (void)timeStep; + (void)distance; + + + btScalar normalLenSqr = normal.length2(); + btAssert(btFabs(normalLenSqr) < btScalar(1.1)); + if (normalLenSqr > btScalar(1.1)) + { + impulse = btScalar(0.); + return; + } + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); + //this jacobian entry could be re-used for all iterations + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + + btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), + body2.getCenterOfMassTransform().getBasis().transpose(), + rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), + body2.getInvInertiaDiagLocal(),body2.getInvMass()); + + btScalar jacDiagAB = jac.getDiagonal(); + btScalar jacDiagABInv = btScalar(1.) / jacDiagAB; + + btScalar rel_vel = jac.getRelativeVelocity( + body1.getLinearVelocity(), + body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(), + body2.getLinearVelocity(), + body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); + btScalar a; + a=jacDiagABInv; + + + rel_vel = normal.dot(vel); + + //todo: move this into proper structure + btScalar contactDamping = btScalar(0.2); + +#ifdef ONLY_USE_LINEAR_MASS + btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass()); + impulse = - contactDamping * rel_vel * massTerm; +#else + btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv; + impulse = velocityImpulse; +#endif +} + + + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.h new file mode 100644 index 00000000..477c79d1 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONTACT_CONSTRAINT_H +#define BT_CONTACT_CONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" + +///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface +ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint +{ +protected: + + btPersistentManifold m_contactManifold; + +public: + + + btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB); + + void setContactManifold(btPersistentManifold* contactManifold); + + btPersistentManifold* getContactManifold() + { + return &m_contactManifold; + } + + const btPersistentManifold* getContactManifold() const + { + return &m_contactManifold; + } + + virtual ~btContactConstraint(); + + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + ///obsolete methods + virtual void buildJacobian(); + + +}; + +///very basic collision resolution without friction +btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance); + + +///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects +void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep); + + + +#endif //BT_CONTACT_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h new file mode 100644 index 00000000..c07e9bbd --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -0,0 +1,159 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONTACT_SOLVER_INFO +#define BT_CONTACT_SOLVER_INFO + +#include "LinearMath/btScalar.h" + +enum btSolverMode +{ + SOLVER_RANDMIZE_ORDER = 1, + SOLVER_FRICTION_SEPARATE = 2, + SOLVER_USE_WARMSTARTING = 4, + SOLVER_USE_2_FRICTION_DIRECTIONS = 16, + SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32, + SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64, + SOLVER_CACHE_FRIENDLY = 128, + SOLVER_SIMD = 256, + SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512, + SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024 +}; + +struct btContactSolverInfoData +{ + + + btScalar m_tau; + btScalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + btScalar m_friction; + btScalar m_timeStep; + btScalar m_restitution; + int m_numIterations; + btScalar m_maxErrorReduction; + btScalar m_sor; + btScalar m_erp;//used as Baumgarte factor + btScalar m_erp2;//used in Split Impulse + btScalar m_globalCfm;//constraint force mixing + int m_splitImpulse; + btScalar m_splitImpulsePenetrationThreshold; + btScalar m_splitImpulseTurnErp; + btScalar m_linearSlop; + btScalar m_warmstartingFactor; + + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + btScalar m_maxGyroscopicForce; + btScalar m_singleAxisRollingFrictionThreshold; + + +}; + +struct btContactSolverInfo : public btContactSolverInfoData +{ + + + + inline btContactSolverInfo() + { + m_tau = btScalar(0.6); + m_damping = btScalar(1.0); + m_friction = btScalar(0.3); + m_timeStep = btScalar(1.f/60.f); + m_restitution = btScalar(0.); + m_maxErrorReduction = btScalar(20.); + m_numIterations = 10; + m_erp = btScalar(0.2); + m_erp2 = btScalar(0.8); + m_globalCfm = btScalar(0.); + m_sor = btScalar(1.); + m_splitImpulse = true; + m_splitImpulsePenetrationThreshold = -.04f; + m_splitImpulseTurnErp = 0.1f; + m_linearSlop = btScalar(0.0); + m_warmstartingFactor=btScalar(0.85); + //m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER; + m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER; + m_restingContactRestitutionThreshold = 2;//unused as of 2.81 + m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit + m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their BT_ENABLE_GYROPSCOPIC_FORCE flag set (using btRigidBody::setFlag) + m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows. + } +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btContactSolverInfoDoubleData +{ + double m_tau; + double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + double m_friction; + double m_timeStep; + double m_restitution; + double m_maxErrorReduction; + double m_sor; + double m_erp;//used as Baumgarte factor + double m_erp2;//used in Split Impulse + double m_globalCfm;//constraint force mixing + double m_splitImpulsePenetrationThreshold; + double m_splitImpulseTurnErp; + double m_linearSlop; + double m_warmstartingFactor; + double m_maxGyroscopicForce; + double m_singleAxisRollingFrictionThreshold; + + int m_numIterations; + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + int m_splitImpulse; + char m_padding[4]; + +}; +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btContactSolverInfoFloatData +{ + float m_tau; + float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + float m_friction; + float m_timeStep; + + float m_restitution; + float m_maxErrorReduction; + float m_sor; + float m_erp;//used as Baumgarte factor + + float m_erp2;//used in Split Impulse + float m_globalCfm;//constraint force mixing + float m_splitImpulsePenetrationThreshold; + float m_splitImpulseTurnErp; + + float m_linearSlop; + float m_warmstartingFactor; + float m_maxGyroscopicForce; + float m_singleAxisRollingFrictionThreshold; + + int m_numIterations; + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + + int m_splitImpulse; + char m_padding[4]; +}; + + + +#endif //BT_CONTACT_SOLVER_INFO diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp new file mode 100644 index 00000000..f93a3280 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp @@ -0,0 +1,129 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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 "btFixedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + + +btFixedConstraint::btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB) +:btTypedConstraint(FIXED_CONSTRAINT_TYPE,rbA,rbB) +{ + m_pivotInA = frameInA.getOrigin(); + m_pivotInB = frameInB.getOrigin(); + m_relTargetAB = frameInA.getRotation()*frameInB.getRotation().inverse(); + +} + +btFixedConstraint::~btFixedConstraint () +{ +} + + +void btFixedConstraint::getInfo1 (btConstraintInfo1* info) +{ + info->m_numConstraintRows = 6; + info->nub = 6; +} + +void btFixedConstraint::getInfo2 (btConstraintInfo2* info) +{ + //fix the 3 linear degrees of freedom + + + const btVector3& worldPosA = m_rbA.getCenterOfMassTransform().getOrigin(); + const btMatrix3x3& worldOrnA = m_rbA.getCenterOfMassTransform().getBasis(); + const btVector3& worldPosB= m_rbB.getCenterOfMassTransform().getOrigin(); + const btMatrix3x3& worldOrnB = m_rbB.getCenterOfMassTransform().getBasis(); + + + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; + + btVector3 a1 = worldOrnA*m_pivotInA; + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + if (info->m_J2linearAxis) + { + info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[info->rowskip+1] = -1; + info->m_J2linearAxis[2*info->rowskip+2] = -1; + } + + btVector3 a2 = worldOrnB*m_pivotInB; + + { + // btVector3 a2n = -a2; + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + // set right hand side for the linear dofs + btScalar k = info->fps * info->erp; + + btVector3 linearError = k*(a2+worldPosB-a1-worldPosA); + int j; + for (j=0; j<3; j++) + { + + + + info->m_constraintError[j*info->rowskip] = linearError[j]; + //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]); + } + + //fix the 3 angular degrees of freedom + + int start_row = 3; + int s = info->rowskip; + int start_index = start_row * s; + + // 3 rows to make body rotations equal + info->m_J1angularAxis[start_index] = 1; + info->m_J1angularAxis[start_index + s + 1] = 1; + info->m_J1angularAxis[start_index + s*2+2] = 1; + if ( info->m_J2angularAxis) + { + info->m_J2angularAxis[start_index] = -1; + info->m_J2angularAxis[start_index + s+1] = -1; + info->m_J2angularAxis[start_index + s*2+2] = -1; + } + + // set right hand side for the angular dofs + + btVector3 diff; + btScalar angle; + btMatrix3x3 mrelCur = worldOrnA *worldOrnB.inverse(); + btQuaternion qrelCur; + mrelCur.getRotation(qrelCur); + btTransformUtil::calculateDiffAxisAngleQuaternion(m_relTargetAB,qrelCur,diff,angle); + diff*=-angle; + for (j=0; j<3; j++) + { + info->m_constraintError[(3+j)*info->rowskip] = k * diff[j]; + } + +} \ No newline at end of file diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h new file mode 100644 index 00000000..697e319e --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h @@ -0,0 +1,49 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_FIXED_CONSTRAINT_H +#define BT_FIXED_CONSTRAINT_H + +#include "btTypedConstraint.h" + +ATTRIBUTE_ALIGNED16(class) btFixedConstraint : public btTypedConstraint +{ + btVector3 m_pivotInA; + btVector3 m_pivotInB; + btQuaternion m_relTargetAB; + +public: + btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB); + + virtual ~btFixedConstraint(); + + + virtual void getInfo1 (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + virtual void setParam(int num, btScalar value, int axis = -1) + { + btAssert(0); + } + virtual btScalar getParam(int num, int axis = -1) const + { + btAssert(0); + return 0.f; + } + +}; + +#endif //BT_FIXED_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp new file mode 100644 index 00000000..bcd457b6 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp @@ -0,0 +1,54 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org + +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. +*/ + +/// Implemented by Erwin Coumans. The idea for the constraint comes from Dimitris Papavasiliou. + +#include "btGearConstraint.h" + +btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio) +:btTypedConstraint(GEAR_CONSTRAINT_TYPE,rbA,rbB), +m_axisInA(axisInA), +m_axisInB(axisInB), +m_ratio(ratio) +{ +} + +btGearConstraint::~btGearConstraint () +{ +} + +void btGearConstraint::getInfo1 (btConstraintInfo1* info) +{ + info->m_numConstraintRows = 1; + info->nub = 1; +} + +void btGearConstraint::getInfo2 (btConstraintInfo2* info) +{ + btVector3 globalAxisA, globalAxisB; + + globalAxisA = m_rbA.getWorldTransform().getBasis()*this->m_axisInA; + globalAxisB = m_rbB.getWorldTransform().getBasis()*this->m_axisInB; + + info->m_J1angularAxis[0] = globalAxisA[0]; + info->m_J1angularAxis[1] = globalAxisA[1]; + info->m_J1angularAxis[2] = globalAxisA[2]; + + info->m_J2angularAxis[0] = m_ratio*globalAxisB[0]; + info->m_J2angularAxis[1] = m_ratio*globalAxisB[1]; + info->m_J2angularAxis[2] = m_ratio*globalAxisB[2]; + +} + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.h new file mode 100644 index 00000000..f9afcb91 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.h @@ -0,0 +1,152 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEAR_CONSTRAINT_H +#define BT_GEAR_CONSTRAINT_H + +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + + +#ifdef BT_USE_DOUBLE_PRECISION +#define btGearConstraintData btGearConstraintDoubleData +#define btGearConstraintDataName "btGearConstraintDoubleData" +#else +#define btGearConstraintData btGearConstraintFloatData +#define btGearConstraintDataName "btGearConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION + + + +///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio. +///See Bullet/Demos/ConstraintDemo for an example use. +class btGearConstraint : public btTypedConstraint +{ +protected: + btVector3 m_axisInA; + btVector3 m_axisInB; + bool m_useFrameA; + btScalar m_ratio; + +public: + btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f); + virtual ~btGearConstraint (); + + ///internal method used by the constraint solver, don't use them directly + virtual void getInfo1 (btConstraintInfo1* info); + + ///internal method used by the constraint solver, don't use them directly + virtual void getInfo2 (btConstraintInfo2* info); + + void setAxisA(btVector3& axisA) + { + m_axisInA = axisA; + } + void setAxisB(btVector3& axisB) + { + m_axisInB = axisB; + } + void setRatio(btScalar ratio) + { + m_ratio = ratio; + } + const btVector3& getAxisA() const + { + return m_axisInA; + } + const btVector3& getAxisB() const + { + return m_axisInB; + } + btScalar getRatio() const + { + return m_ratio; + } + + + virtual void setParam(int num, btScalar value, int axis = -1) + { + (void) num; + (void) value; + (void) axis; + btAssert(0); + } + + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const + { + (void) num; + (void) axis; + btAssert(0); + return 0.f; + } + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; +}; + + + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btGearConstraintFloatData +{ + btTypedConstraintFloatData m_typeConstraintData; + + btVector3FloatData m_axisInA; + btVector3FloatData m_axisInB; + + float m_ratio; + char m_padding[4]; +}; + +struct btGearConstraintDoubleData +{ + btTypedConstraintDoubleData m_typeConstraintData; + + btVector3DoubleData m_axisInA; + btVector3DoubleData m_axisInB; + + double m_ratio; +}; + +SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btGearConstraintData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btGearConstraintData* gear = (btGearConstraintData*)dataBuffer; + btTypedConstraint::serialize(&gear->m_typeConstraintData,serializer); + + m_axisInA.serialize( gear->m_axisInA ); + m_axisInB.serialize( gear->m_axisInB ); + + gear->m_ratio = m_ratio; + + return btGearConstraintDataName; +} + + + + + + +#endif //BT_GEAR_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp new file mode 100644 index 00000000..bc2b5a85 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -0,0 +1,1063 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +/* +2007-09-09 +Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + +#include "btGeneric6DofConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btTransformUtil.h" +#include + + + +#define D6_USE_OBSOLETE_METHOD false +#define D6_USE_FRAME_OFFSET true + + + + + + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) +: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) +, m_frameInA(frameInA) +, m_frameInB(frameInB), +m_useLinearReferenceFrameA(useLinearReferenceFrameA), +m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), +m_flags(0), +m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) +{ + calculateTransforms(); +} + + + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) + : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameB), + m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), + m_flags(0), + m_useSolveConstraintObsolete(false) +{ + ///not providing rigidbody A means implicitly using worldspace for body A + m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; + calculateTransforms(); +} + + + + +#define GENERIC_D6_DISABLE_WARMSTARTING 1 + + + +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) +{ + int i = index%3; + int j = index/3; + return mat[i][j]; +} + + + +///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +{ + // // rot = cy*cz -cy*sz sy + // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx + // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy + // + + btScalar fi = btGetMatrixElem(mat,2); + if (fi < btScalar(1.0f)) + { + if (fi > btScalar(-1.0f)) + { + xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); + xyz[1] = btAsin(btGetMatrixElem(mat,2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + } + return false; +} + +//////////////////////////// btRotationalLimitMotor //////////////////////////////////// + +int btRotationalLimitMotor::testLimitValue(btScalar test_value) +{ + if(m_loLimit>m_hiLimit) + { + m_currentLimit = 0;//Free from violation + return 0; + } + if (test_value < m_loLimit) + { + m_currentLimit = 1;//low limit violation + m_currentLimitError = test_value - m_loLimit; + if(m_currentLimitError>SIMD_PI) + m_currentLimitError-=SIMD_2_PI; + else if(m_currentLimitError<-SIMD_PI) + m_currentLimitError+=SIMD_2_PI; + return 1; + } + else if (test_value> m_hiLimit) + { + m_currentLimit = 2;//High limit violation + m_currentLimitError = test_value - m_hiLimit; + if(m_currentLimitError>SIMD_PI) + m_currentLimitError-=SIMD_2_PI; + else if(m_currentLimitError<-SIMD_PI) + m_currentLimitError+=SIMD_2_PI; + return 2; + }; + + m_currentLimit = 0;//Free from violation + return 0; + +} + + + +btScalar btRotationalLimitMotor::solveAngularLimits( + btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, + btRigidBody * body0, btRigidBody * body1 ) +{ + if (needApplyTorques()==false) return 0.0f; + + btScalar target_velocity = m_targetVelocity; + btScalar maxMotorForce = m_maxMotorForce; + + //current error correction + if (m_currentLimit!=0) + { + target_velocity = -m_stopERP*m_currentLimitError/(timeStep); + maxMotorForce = m_maxLimitForce; + } + + maxMotorForce *= timeStep; + + // current velocity difference + + btVector3 angVelA = body0->getAngularVelocity(); + btVector3 angVelB = body1->getAngularVelocity(); + + btVector3 vel_diff; + vel_diff = angVelA-angVelB; + + + + btScalar rel_vel = axis.dot(vel_diff); + + // correction velocity + btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + + + if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) + { + return 0.0f;//no need for applying force + } + + + // correction impulse + btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; + + // clip correction impulse + btScalar clippedMotorImpulse; + + ///@todo: should clip against accumulated impulse + if (unclippedMotorImpulse>0.0f) + { + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; + } + else + { + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; + } + + + // sort with accumulated impulses + btScalar lo = btScalar(-BT_LARGE_FLOAT); + btScalar hi = btScalar(BT_LARGE_FLOAT); + + btScalar oldaccumImpulse = m_accumulatedImpulse; + btScalar sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + btVector3 motorImp = clippedMotorImpulse * axis; + + body0->applyTorqueImpulse(motorImp); + body1->applyTorqueImpulse(-motorImp); + + return clippedMotorImpulse; + + +} + +//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// + + + + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + + +int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value) +{ + btScalar loLimit = m_lowerLimit[limitIndex]; + btScalar hiLimit = m_upperLimit[limitIndex]; + if(loLimit > hiLimit) + { + m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimitError[limitIndex] = btScalar(0.f); + return 0; + } + + if (test_value < loLimit) + { + m_currentLimit[limitIndex] = 2;//low limit violation + m_currentLimitError[limitIndex] = test_value - loLimit; + return 2; + } + else if (test_value> hiLimit) + { + m_currentLimit[limitIndex] = 1;//High limit violation + m_currentLimitError[limitIndex] = test_value - hiLimit; + return 1; + }; + + m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimitError[limitIndex] = btScalar(0.f); + return 0; +} + + + +btScalar btTranslationalLimitMotor::solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos) +{ + + ///find relative velocity + // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); + // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); + btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel = axis_normal_on_a.dot(vel); + + + + /// apply displacement correction + + //positional error (zeroth order error) + btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); + btScalar lo = btScalar(-BT_LARGE_FLOAT); + btScalar hi = btScalar(BT_LARGE_FLOAT); + + btScalar minLimit = m_lowerLimit[limit_index]; + btScalar maxLimit = m_upperLimit[limit_index]; + + //handle the limits + if (minLimit < maxLimit) + { + { + if (depth > maxLimit) + { + depth -= maxLimit; + lo = btScalar(0.); + + } + else + { + if (depth < minLimit) + { + depth -= minLimit; + hi = btScalar(0.); + } + else + { + return 0.0f; + } + } + } + } + + btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; + + + + + btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; + + btVector3 impulse_vector = axis_normal_on_a * normalImpulse; + body1.applyImpulse( impulse_vector, rel_pos1); + body2.applyImpulse(-impulse_vector, rel_pos2); + + + + return normalImpulse; +} + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + +void btGeneric6DofConstraint::calculateAngleInfo() +{ + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); + matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + // in euler angle mode we do not actually constrain the angular velocity + // along the axes axis[0] and axis[2] (although we do use axis[1]) : + // + // to get constrain w2-w1 along ...not + // ------ --------------------- ------ + // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] + // d(angle[1])/dt = 0 ax[1] + // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] + // + // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. + // to prove the result for angle[0], write the expression for angle[0] from + // GetInfo1 then take the derivative. to prove this for angle[2] it is + // easier to take the euler rate expression for d(angle[2])/dt with respect + // to the components of w and set that to 0. + btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); + btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); + + m_calculatedAxis[1] = axis2.cross(axis0); + m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); + m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); + + m_calculatedAxis[0].normalize(); + m_calculatedAxis[1].normalize(); + m_calculatedAxis[2].normalize(); + +} + +void btGeneric6DofConstraint::calculateTransforms() +{ + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +{ + m_calculatedTransformA = transA * m_frameInA; + m_calculatedTransformB = transB * m_frameInB; + calculateLinearInfo(); + calculateAngleInfo(); + if(m_useOffsetForConstraintFrame) + { // get weight factors depending on masses + btScalar miA = getRigidBodyA().getInvMass(); + btScalar miB = getRigidBodyB().getInvMass(); + m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); + btScalar miS = miA + miB; + if(miS > btScalar(0.f)) + { + m_factA = miB / miS; + } + else + { + m_factA = btScalar(0.5f); + } + m_factB = btScalar(1.0f) - m_factA; + } +} + + + +void btGeneric6DofConstraint::buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW) +{ + new (&jacLinear) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); +} + + + +void btGeneric6DofConstraint::buildAngularJacobian( + btJacobianEntry & jacAngular,const btVector3 & jointAxisW) +{ + new (&jacAngular) btJacobianEntry(jointAxisW, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +} + + + +bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) +{ + btScalar angle = m_calculatedAxisAngleDiff[axis_index]; + angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit); + m_angularLimits[axis_index].m_currentPosition = angle; + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); +} + + + +void btGeneric6DofConstraint::buildJacobian() +{ +#ifndef __SPU__ + if (m_useSolveConstraintObsolete) + { + + // Clear accumulated impulses for the next simulation step + m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + int i; + for(i = 0; i < 3; i++) + { + m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); + } + //calculates transform + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + + // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); + // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); + calcAnchorPos(); + btVector3 pivotAInW = m_AnchorPos; + btVector3 pivotBInW = m_AnchorPos; + + // not used here + // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 normalWorld; + //linear part + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + if (m_useLinearReferenceFrameA) + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + else + normalWorld = m_calculatedTransformB.getBasis().getColumn(i); + + buildLinearJacobian( + m_jacLinear[i],normalWorld , + pivotAInW,pivotBInW); + + } + } + + // angular part + for (i=0;i<3;i++) + { + //calculates error angle + if (testAngularLimitMotor(i)) + { + normalWorld = this->getAxis(i); + // Create angular atom + buildAngularJacobian(m_jacAng[i],normalWorld); + } + } + + } +#endif //__SPU__ + +} + + +void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + //prepare constraint + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + info->m_numConstraintRows = 0; + info->nub = 6; + int i; + //test linear limits + for(i = 0; i < 3; i++) + { + if(m_linearLimits.needApplyForce(i)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + //test angular limits + for (i=0;i<3 ;i++ ) + { + if(testAngularLimitMotor(i)) + { + info->m_numConstraintRows++; + info->nub--; + } + } + } +} + +void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + //pre-allocate all 6 + info->m_numConstraintRows = 6; + info->nub = 0; + } +} + + +void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) +{ + btAssert(!m_useSolveConstraintObsolete); + + const btTransform& transA = m_rbA.getCenterOfMassTransform(); + const btTransform& transB = m_rbB.getCenterOfMassTransform(); + const btVector3& linVelA = m_rbA.getLinearVelocity(); + const btVector3& linVelB = m_rbB.getLinearVelocity(); + const btVector3& angVelA = m_rbA.getAngularVelocity(); + const btVector3& angVelB = m_rbB.getAngularVelocity(); + + if(m_useOffsetForConstraintFrame) + { // for stability better to solve angular limits first + int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); + setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + } + else + { // leave old version for compatibility + int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB); + setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB); + } + +} + + +void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +{ + + btAssert(!m_useSolveConstraintObsolete); + //prepare constraint + calculateTransforms(transA,transB); + + int i; + for (i=0;i<3 ;i++ ) + { + testAngularLimitMotor(i); + } + + if(m_useOffsetForConstraintFrame) + { // for stability better to solve angular limits first + int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); + setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + } + else + { // leave old version for compatibility + int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB); + setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB); + } +} + + + +int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +{ +// int row = 0; + //solve linear limits + btRotationalLimitMotor limot; + for (int i=0;i<3 ;i++ ) + { + if(m_linearLimits.needApplyForce(i)) + { // re-use rotational motor code + limot.m_bounce = btScalar(0.f); + limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; + limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i]; + limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; + limot.m_damping = m_linearLimits.m_damping; + limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; + limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; + limot.m_limitSoftness = m_linearLimits.m_limitSoftness; + limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; + limot.m_maxLimitForce = btScalar(0.f); + limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; + limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; + btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); + int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT); + limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0]; + limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0]; + limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp; + if(m_useOffsetForConstraintFrame) + { + int indx1 = (i + 1) % 3; + int indx2 = (i + 2) % 3; + int rotAllowed = 1; // rotations around orthos to current axis + if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit) + { + rotAllowed = 0; + } + row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed); + } + else + { + row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0); + } + } + } + return row; +} + + + +int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +{ + btGeneric6DofConstraint * d6constraint = this; + int row = row_offset; + //solve angular limits + for (int i=0;i<3 ;i++ ) + { + if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) + { + btVector3 axis = d6constraint->getAxis(i); + int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT); + if(!(flags & BT_6DOF_FLAGS_CFM_NORM)) + { + m_angularLimits[i].m_normalCFM = info->cfm[0]; + } + if(!(flags & BT_6DOF_FLAGS_CFM_STOP)) + { + m_angularLimits[i].m_stopCFM = info->cfm[0]; + } + if(!(flags & BT_6DOF_FLAGS_ERP_STOP)) + { + m_angularLimits[i].m_stopERP = info->erp; + } + row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i), + transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1); + } + } + + return row; +} + + + + +void btGeneric6DofConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + + +void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB) +{ + m_frameInA = frameA; + m_frameInB = frameB; + buildJacobian(); + calculateTransforms(); +} + + + +btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const +{ + return m_calculatedAxis[axis_index]; +} + + +btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const +{ + return m_calculatedLinearDiff[axisIndex]; +} + + +btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const +{ + return m_calculatedAxisAngleDiff[axisIndex]; +} + + + +void btGeneric6DofConstraint::calcAnchorPos(void) +{ + btScalar imA = m_rbA.getInvMass(); + btScalar imB = m_rbB.getInvMass(); + btScalar weight; + if(imB == btScalar(0.0)) + { + weight = btScalar(1.0); + } + else + { + weight = imA / (imA + imB); + } + const btVector3& pA = m_calculatedTransformA.getOrigin(); + const btVector3& pB = m_calculatedTransformB.getOrigin(); + m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight); + return; +} + + + +void btGeneric6DofConstraint::calculateLinearInfo() +{ + m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); + m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; + for(int i = 0; i < 3; i++) + { + m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i]; + m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); + } +} + + + +int btGeneric6DofConstraint::get_limit_motor_info2( + btRotationalLimitMotor * limot, + const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, + btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed) +{ + int srow = row * info->rowskip; + int powered = limot->m_enableMotor; + int limit = limot->m_currentLimit; + if (powered || limit) + { // if the joint is powered, or has joint limits, add in the extra row + btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; + btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis; + J1[srow+0] = ax1[0]; + J1[srow+1] = ax1[1]; + J1[srow+2] = ax1[2]; + + J2[srow+0] = -ax1[0]; + J2[srow+1] = -ax1[1]; + J2[srow+2] = -ax1[2]; + + if((!rotational)) + { + if (m_useOffsetForConstraintFrame) + { + btVector3 tmpA, tmpB, relA, relB; + // get vector from bodyB to frameB in WCS + relB = m_calculatedTransformB.getOrigin() - transB.getOrigin(); + // get its projection to constraint axis + btVector3 projB = ax1 * relB.dot(ax1); + // get vector directed from bodyB to constraint axis (and orthogonal to it) + btVector3 orthoB = relB - projB; + // same for bodyA + relA = m_calculatedTransformA.getOrigin() - transA.getOrigin(); + btVector3 projA = ax1 * relA.dot(ax1); + btVector3 orthoA = relA - projA; + // get desired offset between frames A and B along constraint axis + btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError; + // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis + btVector3 totalDist = projA + ax1 * desiredOffs - projB; + // get offset vectors relA and relB + relA = orthoA + totalDist * m_factA; + relB = orthoB - totalDist * m_factB; + tmpA = relA.cross(ax1); + tmpB = relB.cross(ax1); + if(m_hasStaticBody && (!rotAllowed)) + { + tmpA *= m_factA; + tmpB *= m_factB; + } + int i; + for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i]; + } else + { + btVector3 ltd; // Linear Torque Decoupling vector + btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin(); + ltd = c.cross(ax1); + info->m_J1angularAxis[srow+0] = ltd[0]; + info->m_J1angularAxis[srow+1] = ltd[1]; + info->m_J1angularAxis[srow+2] = ltd[2]; + + c = m_calculatedTransformB.getOrigin() - transB.getOrigin(); + ltd = -c.cross(ax1); + info->m_J2angularAxis[srow+0] = ltd[0]; + info->m_J2angularAxis[srow+1] = ltd[1]; + info->m_J2angularAxis[srow+2] = ltd[2]; + } + } + // if we're limited low and high simultaneously, the joint motor is + // ineffective + if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0; + info->m_constraintError[srow] = btScalar(0.f); + if (powered) + { + info->cfm[srow] = limot->m_normalCFM; + if(!limit) + { + btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity; + + btScalar mot_fact = getMotorFactor( limot->m_currentPosition, + limot->m_loLimit, + limot->m_hiLimit, + tag_vel, + info->fps * limot->m_stopERP); + info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity; + info->m_lowerLimit[srow] = -limot->m_maxMotorForce; + info->m_upperLimit[srow] = limot->m_maxMotorForce; + } + } + if(limit) + { + btScalar k = info->fps * limot->m_stopERP; + if(!rotational) + { + info->m_constraintError[srow] += k * limot->m_currentLimitError; + } + else + { + info->m_constraintError[srow] += -k * limot->m_currentLimitError; + } + info->cfm[srow] = limot->m_stopCFM; + if (limot->m_loLimit == limot->m_hiLimit) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + if (limit == 1) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // deal with bounce + if (limot->m_bounce > 0) + { + // calculate joint velocity + btScalar vel; + if (rotational) + { + vel = angVelA.dot(ax1); +//make sure that if no body -> angVelB == zero vec +// if (body1) + vel -= angVelB.dot(ax1); + } + else + { + vel = linVelA.dot(ax1); +//make sure that if no body -> angVelB == zero vec +// if (body1) + vel -= linVelB.dot(ax1); + } + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if (limit == 1) + { + if (vel < 0) + { + btScalar newc = -limot->m_bounce* vel; + if (newc > info->m_constraintError[srow]) + info->m_constraintError[srow] = newc; + } + } + else + { + if (vel > 0) + { + btScalar newc = -limot->m_bounce * vel; + if (newc < info->m_constraintError[srow]) + info->m_constraintError[srow] = newc; + } + } + } + } + } + return 1; + } + else return 0; +} + + + + + + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. +void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis) +{ + if((axis >= 0) && (axis < 3)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + m_linearLimits.m_stopERP[axis] = value; + m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_STOP_CFM : + m_linearLimits.m_stopCFM[axis] = value; + m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_CFM : + m_linearLimits.m_normalCFM[axis] = value; + m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + default : + btAssertConstrParams(0); + } + } + else if((axis >=3) && (axis < 6)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + m_angularLimits[axis - 3].m_stopERP = value; + m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_STOP_CFM : + m_angularLimits[axis - 3].m_stopCFM = value; + m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + case BT_CONSTRAINT_CFM : + m_angularLimits[axis - 3].m_normalCFM = value; + m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } +} + + ///return the local value of parameter +btScalar btGeneric6DofConstraint::getParam(int num, int axis) const +{ + btScalar retVal = 0; + if((axis >= 0) && (axis < 3)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_linearLimits.m_stopERP[axis]; + break; + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_linearLimits.m_stopCFM[axis]; + break; + case BT_CONSTRAINT_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_linearLimits.m_normalCFM[axis]; + break; + default : + btAssertConstrParams(0); + } + } + else if((axis >=3) && (axis < 6)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_angularLimits[axis - 3].m_stopERP; + break; + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_angularLimits[axis - 3].m_stopCFM; + break; + case BT_CONSTRAINT_CFM : + btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); + retVal = m_angularLimits[axis - 3].m_normalCFM; + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } + return retVal; +} + + + +void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +{ + btVector3 zAxis = axis1.normalized(); + btVector3 yAxis = axis2.normalized(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + + // now get constraint frame in local coordinate systems + m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; + + calculateTransforms(); +} diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h new file mode 100644 index 00000000..431a5241 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -0,0 +1,640 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev +/// Added support for generic constraint solver through getInfo1/getInfo2 methods + +/* +2007-09-09 +btGeneric6DofConstraint Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + + +#ifndef BT_GENERIC_6DOF_CONSTRAINT_H +#define BT_GENERIC_6DOF_CONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + + +#ifdef BT_USE_DOUBLE_PRECISION +#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2 +#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2" +#else +#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData +#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData" +#endif //BT_USE_DOUBLE_PRECISION + + +//! Rotation Limit structure for generic joints +class btRotationalLimitMotor +{ +public: + //! limit_parameters + //!@{ + btScalar m_loLimit;//!< joint limit + btScalar m_hiLimit;//!< joint limit + btScalar m_targetVelocity;//!< target motor velocity + btScalar m_maxMotorForce;//!< max force on motor + btScalar m_maxLimitForce;//!< max force on limit + btScalar m_damping;//!< Damping. + btScalar m_limitSoftness;//! Relaxation factor + btScalar m_normalCFM;//!< Constraint force mixing factor + btScalar m_stopERP;//!< Error tolerance factor when joint is at limit + btScalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit + btScalar m_bounce;//!< restitution factor + bool m_enableMotor; + + //!@} + + //! temp_variables + //!@{ + btScalar m_currentLimitError;//! How much is violated this limit + btScalar m_currentPosition; //! current value of angle + int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit + btScalar m_accumulatedImpulse; + //!@} + + btRotationalLimitMotor() + { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 0.1f; + m_maxLimitForce = 300.0f; + m_loLimit = 1.0f; + m_hiLimit = -1.0f; + m_normalCFM = 0.f; + m_stopERP = 0.2f; + m_stopCFM = 0.f; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + } + + btRotationalLimitMotor(const btRotationalLimitMotor & limot) + { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_normalCFM = limot.m_normalCFM; + m_stopERP = limot.m_stopERP; + m_stopCFM = limot.m_stopCFM; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } + + + + //! Is limited + bool isLimited() + { + if(m_loLimit > m_hiLimit) return false; + return true; + } + + //! Need apply correction + bool needApplyTorques() + { + if(m_currentLimit == 0 && m_enableMotor == false) return false; + return true; + } + + //! calculates error + /*! + calculates m_currentLimit and m_currentLimitError. + */ + int testLimitValue(btScalar test_value); + + //! apply the correction impulses for two bodies + btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); + +}; + + + +class btTranslationalLimitMotor +{ +public: + btVector3 m_lowerLimit;//!< the constraint lower limits + btVector3 m_upperLimit;//!< the constraint upper limits + btVector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + btScalar m_limitSoftness;//!< Softness for linear limit + btScalar m_damping;//!< Damping for linear limit + btScalar m_restitution;//! Bounce parameter for linear limit + btVector3 m_normalCFM;//!< Constraint force mixing factor + btVector3 m_stopERP;//!< Error tolerance factor when joint is at limit + btVector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit + //!@} + bool m_enableMotor[3]; + btVector3 m_targetVelocity;//!< target motor velocity + btVector3 m_maxMotorForce;//!< max force on motor + btVector3 m_currentLimitError;//! How much is violated this limit + btVector3 m_currentLinearDiff;//! Current relative offset of constraint frames + int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit + + btTranslationalLimitMotor() + { + m_lowerLimit.setValue(0.f,0.f,0.f); + m_upperLimit.setValue(0.f,0.f,0.f); + m_accumulatedImpulse.setValue(0.f,0.f,0.f); + m_normalCFM.setValue(0.f, 0.f, 0.f); + m_stopERP.setValue(0.2f, 0.2f, 0.2f); + m_stopCFM.setValue(0.f, 0.f, 0.f); + + m_limitSoftness = 0.7f; + m_damping = btScalar(1.0f); + m_restitution = btScalar(0.5f); + for(int i=0; i < 3; i++) + { + m_enableMotor[i] = false; + m_targetVelocity[i] = btScalar(0.f); + m_maxMotorForce[i] = btScalar(0.f); + } + } + + btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) + { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; + + m_limitSoftness = other.m_limitSoftness ; + m_damping = other.m_damping; + m_restitution = other.m_restitution; + m_normalCFM = other.m_normalCFM; + m_stopERP = other.m_stopERP; + m_stopCFM = other.m_stopCFM; + + for(int i=0; i < 3; i++) + { + m_enableMotor[i] = other.m_enableMotor[i]; + m_targetVelocity[i] = other.m_targetVelocity[i]; + m_maxMotorForce[i] = other.m_maxMotorForce[i]; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + inline bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + inline bool needApplyForce(int limitIndex) + { + if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; + return true; + } + int testLimitValue(int limitIndex, btScalar test_value); + + + btScalar solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos); + + +}; + +enum bt6DofFlags +{ + BT_6DOF_FLAGS_CFM_NORM = 1, + BT_6DOF_FLAGS_CFM_STOP = 2, + BT_6DOF_FLAGS_ERP_STOP = 4 +}; +#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis + + +/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space +/*! +btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. +currently this limit supports rotational motors
    +
      +
    • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. +At this moment translational motors are not supported. May be in the future.
    • + +
    • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. +This is accessible through btGeneric6DofConstraint.getLimitMotor method, +This brings support for limit parameters and motors.
    • + +
    • Angulars limits have these possible ranges: + + + + + + + + + + + + + + + + + + +
      AXISMIN ANGLEMAX ANGLE
      X-PIPI
      Y-PI/2PI/2
      Z-PIPI
      +
    • +
    + +*/ +ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint +{ +protected: + + //! relative_frames + //!@{ + btTransform m_frameInA;//!< the constraint space w.r.t body A + btTransform m_frameInB;//!< the constraint space w.r.t body B + //!@} + + //! Jacobians + //!@{ + btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints + //!@} + + //! Linear_Limit_parameters + //!@{ + btTranslationalLimitMotor m_linearLimits; + //!@} + + + //! hinge_parameters + //!@{ + btRotationalLimitMotor m_angularLimits[3]; + //!@} + + +protected: + //! temporal variables + //!@{ + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + btVector3 m_calculatedLinearDiff; + btScalar m_factA; + btScalar m_factB; + bool m_hasStaticBody; + + btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes + + bool m_useLinearReferenceFrameA; + bool m_useOffsetForConstraintFrame; + + int m_flags; + + //!@} + + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + + + int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + + int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + + void buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW); + + void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + + // tests linear limits + void calculateLinearInfo(); + + //! calcs the euler angles between the two bodies. + void calculateAngleInfo(); + + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + + //! Calcs global transform of the offsets + /*! + Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. + \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo + */ + void calculateTransforms(const btTransform& transA,const btTransform& transB); + + void calculateTransforms(); + + //! Gets the global transform of the offset for body A + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformA() const + { + return m_calculatedTransformA; + } + + //! Gets the global transform of the offset for body B + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformB() const + { + return m_calculatedTransformB; + } + + const btTransform & getFrameOffsetA() const + { + return m_frameInA; + } + + const btTransform & getFrameOffsetB() const + { + return m_frameInB; + } + + + btTransform & getFrameOffsetA() + { + return m_frameInA; + } + + btTransform & getFrameOffsetB() + { + return m_frameInB; + } + + + //! performs Jacobian calculation, and also calculates angle differences and axis + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + + + void updateRHS(btScalar timeStep); + + //! Get the rotation axis in global coordinates + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btVector3 getAxis(int axis_index) const; + + //! Get the relative Euler angle + /*! + \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. + */ + btScalar getAngle(int axis_index) const; + + //! Get the relative position of the constraint pivot + /*! + \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. + */ + btScalar getRelativePivotPosition(int axis_index) const; + + void setFrames(const btTransform & frameA, const btTransform & frameB); + + //! Test angular limit. + /*! + Calculates angular correction and returns true if limit needs to be corrected. + \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. + */ + bool testAngularLimitMotor(int axis_index); + + void setLinearLowerLimit(const btVector3& linearLower) + { + m_linearLimits.m_lowerLimit = linearLower; + } + + void getLinearLowerLimit(btVector3& linearLower) + { + linearLower = m_linearLimits.m_lowerLimit; + } + + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_linearLimits.m_upperLimit = linearUpper; + } + + void getLinearUpperLimit(btVector3& linearUpper) + { + linearUpper = m_linearLimits.m_upperLimit; + } + + void setAngularLowerLimit(const btVector3& angularLower) + { + for(int i = 0; i < 3; i++) + m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]); + } + + void getAngularLowerLimit(btVector3& angularLower) + { + for(int i = 0; i < 3; i++) + angularLower[i] = m_angularLimits[i].m_loLimit; + } + + void setAngularUpperLimit(const btVector3& angularUpper) + { + for(int i = 0; i < 3; i++) + m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]); + } + + void getAngularUpperLimit(btVector3& angularUpper) + { + for(int i = 0; i < 3; i++) + angularUpper[i] = m_angularLimits[i].m_hiLimit; + } + + //! Retrieves the angular limit informacion + btRotationalLimitMotor * getRotationalLimitMotor(int index) + { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + btTranslationalLimitMotor * getTranslationalLimitMotor() + { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, btScalar lo, btScalar hi) + { + if(axis<3) + { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } + else + { + lo = btNormalizeAngle(lo); + hi = btNormalizeAngle(hi); + m_angularLimits[axis-3].m_loLimit = lo; + m_angularLimits[axis-3].m_hiLimit = hi; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + bool isLimited(int limitIndex) + { + if(limitIndex<3) + { + return m_linearLimits.isLimited(limitIndex); + + } + return m_angularLimits[limitIndex-3].isLimited(); + } + + virtual void calcAnchorPos(void); // overridable + + int get_limit_motor_info2( btRotationalLimitMotor * limot, + const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, + btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false); + + // access for UseFrameOffset + bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + void setAxis( const btVector3& axis1, const btVector3& axis2); + + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + + +struct btGeneric6DofConstraintData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformFloatData m_rbBFrame; + + btVector3FloatData m_linearUpperLimit; + btVector3FloatData m_linearLowerLimit; + + btVector3FloatData m_angularUpperLimit; + btVector3FloatData m_angularLowerLimit; + + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; +}; + +struct btGeneric6DofConstraintDoubleData2 +{ + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformDoubleData m_rbBFrame; + + btVector3DoubleData m_linearUpperLimit; + btVector3DoubleData m_linearLowerLimit; + + btVector3DoubleData m_angularUpperLimit; + btVector3DoubleData m_angularLowerLimit; + + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; +}; + +SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btGeneric6DofConstraintData2); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btGeneric6DofConstraintData2* dof = (btGeneric6DofConstraintData2*)dataBuffer; + btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer); + + m_frameInA.serialize(dof->m_rbAFrame); + m_frameInB.serialize(dof->m_rbBFrame); + + + int i; + for (i=0;i<3;i++) + { + dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit; + dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit; + dof->m_linearLowerLimit.m_floats[i] = m_linearLimits.m_lowerLimit[i]; + dof->m_linearUpperLimit.m_floats[i] = m_linearLimits.m_upperLimit[i]; + } + + dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA? 1 : 0; + dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0; + + return btGeneric6DofConstraintDataName; +} + + + + + +#endif //BT_GENERIC_6DOF_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp new file mode 100644 index 00000000..6f765884 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp @@ -0,0 +1,185 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btGeneric6DofSpringConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" + + +btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) + : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA) +{ + init(); +} + + +btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) + : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB) +{ + init(); +} + + +void btGeneric6DofSpringConstraint::init() +{ + m_objectType = D6_SPRING_CONSTRAINT_TYPE; + + for(int i = 0; i < 6; i++) + { + m_springEnabled[i] = false; + m_equilibriumPoint[i] = btScalar(0.f); + m_springStiffness[i] = btScalar(0.f); + m_springDamping[i] = btScalar(1.f); + } +} + + +void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff) +{ + btAssert((index >= 0) && (index < 6)); + m_springEnabled[index] = onOff; + if(index < 3) + { + m_linearLimits.m_enableMotor[index] = onOff; + } + else + { + m_angularLimits[index - 3].m_enableMotor = onOff; + } +} + + + +void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness) +{ + btAssert((index >= 0) && (index < 6)); + m_springStiffness[index] = stiffness; +} + + +void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping) +{ + btAssert((index >= 0) && (index < 6)); + m_springDamping[index] = damping; +} + + +void btGeneric6DofSpringConstraint::setEquilibriumPoint() +{ + calculateTransforms(); + int i; + + for( i = 0; i < 3; i++) + { + m_equilibriumPoint[i] = m_calculatedLinearDiff[i]; + } + for(i = 0; i < 3; i++) + { + m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i]; + } +} + + + +void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index) +{ + btAssert((index >= 0) && (index < 6)); + calculateTransforms(); + if(index < 3) + { + m_equilibriumPoint[index] = m_calculatedLinearDiff[index]; + } + else + { + m_equilibriumPoint[index] = m_calculatedAxisAngleDiff[index - 3]; + } +} + +void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val) +{ + btAssert((index >= 0) && (index < 6)); + m_equilibriumPoint[index] = val; +} + + +void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info) +{ + // it is assumed that calculateTransforms() have been called before this call + int i; + //btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity(); + for(i = 0; i < 3; i++) + { + if(m_springEnabled[i]) + { + // get current position of constraint + btScalar currPos = m_calculatedLinearDiff[i]; + // calculate difference + btScalar delta = currPos - m_equilibriumPoint[i]; + // spring force is (delta * m_stiffness) according to Hooke's Law + btScalar force = delta * m_springStiffness[i]; + btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations); + m_linearLimits.m_targetVelocity[i] = velFactor * force; + m_linearLimits.m_maxMotorForce[i] = btFabs(force) / info->fps; + } + } + for(i = 0; i < 3; i++) + { + if(m_springEnabled[i + 3]) + { + // get current position of constraint + btScalar currPos = m_calculatedAxisAngleDiff[i]; + // calculate difference + btScalar delta = currPos - m_equilibriumPoint[i+3]; + // spring force is (-delta * m_stiffness) according to Hooke's Law + btScalar force = -delta * m_springStiffness[i+3]; + btScalar velFactor = info->fps * m_springDamping[i+3] / btScalar(info->m_numIterations); + m_angularLimits[i].m_targetVelocity = velFactor * force; + m_angularLimits[i].m_maxMotorForce = btFabs(force) / info->fps; + } + } +} + + +void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info) +{ + // this will be called by constraint solver at the constraint setup stage + // set current motor parameters + internalUpdateSprings(info); + // do the rest of job for constraint setup + btGeneric6DofConstraint::getInfo2(info); +} + + +void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +{ + btVector3 zAxis = axis1.normalized(); + btVector3 yAxis = axis2.normalized(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + + // now get constraint frame in local coordinate systems + m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; + + calculateTransforms(); +} + + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h new file mode 100644 index 00000000..1b2e0f62 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h @@ -0,0 +1,121 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H +#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H + + +#include "LinearMath/btVector3.h" +#include "btTypedConstraint.h" +#include "btGeneric6DofConstraint.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2 +#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2" +#else +#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData +#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData" +#endif //BT_USE_DOUBLE_PRECISION + + + +/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF + +/// DOF index used in enableSpring() and setStiffness() means: +/// 0 : translation X +/// 1 : translation Y +/// 2 : translation Z +/// 3 : rotation X (3rd Euler rotational around new position of X axis, range [-PI+epsilon, PI-epsilon] ) +/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] ) +/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] ) + +ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpringConstraint : public btGeneric6DofConstraint +{ +protected: + bool m_springEnabled[6]; + btScalar m_equilibriumPoint[6]; + btScalar m_springStiffness[6]; + btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping) + void init(); + void internalUpdateSprings(btConstraintInfo2* info); +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + void enableSpring(int index, bool onOff); + void setStiffness(int index, btScalar stiffness); + void setDamping(int index, btScalar damping); + void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF + void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF + void setEquilibriumPoint(int index, btScalar val); + + virtual void setAxis( const btVector3& axis1, const btVector3& axis2); + + virtual void getInfo2 (btConstraintInfo2* info); + + virtual int calculateSerializeBufferSize() const; + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + + +struct btGeneric6DofSpringConstraintData +{ + btGeneric6DofConstraintData m_6dofData; + + int m_springEnabled[6]; + float m_equilibriumPoint[6]; + float m_springStiffness[6]; + float m_springDamping[6]; +}; + +struct btGeneric6DofSpringConstraintDoubleData2 +{ + btGeneric6DofConstraintDoubleData2 m_6dofData; + + int m_springEnabled[6]; + double m_equilibriumPoint[6]; + double m_springStiffness[6]; + double m_springDamping[6]; +}; + + +SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btGeneric6DofSpringConstraintData2); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btGeneric6DofSpringConstraintData2* dof = (btGeneric6DofSpringConstraintData2*)dataBuffer; + btGeneric6DofConstraint::serialize(&dof->m_6dofData,serializer); + + int i; + for (i=0;i<6;i++) + { + dof->m_equilibriumPoint[i] = m_equilibriumPoint[i]; + dof->m_springDamping[i] = m_springDamping[i]; + dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0; + dof->m_springStiffness[i] = m_springStiffness[i]; + } + return btGeneric6DofSpringConstraintDataName; +} + +#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp new file mode 100644 index 00000000..29123d52 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btHinge2Constraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" + + + +// constructor +// anchor, axis1 and axis2 are in world coordinate system +// axis1 must be orthogonal to axis2 +btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2) +: btGeneric6DofSpringConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), + m_anchor(anchor), + m_axis1(axis1), + m_axis2(axis2) +{ + // build frame basis + // 6DOF constraint uses Euler angles and to define limits + // it is assumed that rotational order is : + // Z - first, allowed limits are (-PI,PI); + // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number + // used to prevent constraint from instability on poles; + // new position of X, allowed limits are (-PI,PI); + // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs + // Build the frame in world coordinate system first + btVector3 zAxis = axis1.normalize(); + btVector3 xAxis = axis2.normalize(); + btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + frameInW.setOrigin(anchor); + // now get constraint frame in local coordinate systems + m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW; + // sei limits + setLinearLowerLimit(btVector3(0.f, 0.f, -1.f)); + setLinearUpperLimit(btVector3(0.f, 0.f, 1.f)); + // like front wheels of a car + setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f)); + setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f)); + // enable suspension + enableSpring(2, true); + setStiffness(2, SIMD_PI * SIMD_PI * 4.f); // period 1 sec for 1 kilogramm weel :-) + setDamping(2, 0.01f); + setEquilibriumPoint(); +} + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h new file mode 100644 index 00000000..9a004986 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h @@ -0,0 +1,60 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_HINGE2_CONSTRAINT_H +#define BT_HINGE2_CONSTRAINT_H + + + +#include "LinearMath/btVector3.h" +#include "btTypedConstraint.h" +#include "btGeneric6DofSpringConstraint.h" + + + +// Constraint similar to ODE Hinge2 Joint +// has 3 degrees of frredom: +// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2) +// 1 translational (along axis Z) with suspension spring + +ATTRIBUTE_ALIGNED16(class) btHinge2Constraint : public btGeneric6DofSpringConstraint +{ +protected: + btVector3 m_anchor; + btVector3 m_axis1; + btVector3 m_axis2; +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + // constructor + // anchor, axis1 and axis2 are in world coordinate system + // axis1 must be orthogonal to axis2 + btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2); + // access + const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } + const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } + const btVector3& getAxis1() { return m_axis1; } + const btVector3& getAxis2() { return m_axis2; } + btScalar getAngle1() { return getAngle(2); } + btScalar getAngle2() { return getAngle(0); } + // limits + void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); } + void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3( 1.f, 0.f, ang1min)); } +}; + + + +#endif // BT_HINGE2_CONSTRAINT_H + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp new file mode 100644 index 00000000..c1897413 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -0,0 +1,1046 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btHingeConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" +#include +#include "btSolverBody.h" + + + +//#define HINGE_USE_OBSOLETE_SOLVER false +#define HINGE_USE_OBSOLETE_SOLVER false + +#define HINGE_USE_FRAME_OFFSET true + +#ifndef __SPU__ + + + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, + const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA) + :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit(), +#endif + m_angularOnly(false), + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), + m_useReferenceFrameA(useReferenceFrameA), + m_flags(0) +{ + m_rbAFrame.getOrigin() = pivotInA; + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + + btVector3 rbAxisA2; + btScalar projection = axisInA.dot(rbAxisA1); + if (projection >= 1.0f - SIMD_EPSILON) { + rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else if (projection <= -1.0f + SIMD_EPSILON) { + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else { + rbAxisA2 = axisInA.cross(rbAxisA1); + rbAxisA1 = rbAxisA2.cross(axisInA); + } + + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.getOrigin() = pivotInB; + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), +m_useReferenceFrameA(useReferenceFrameA), +m_flags(0) +{ + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + // fixed axis in worldspace + btVector3 rbAxisA1, rbAxisA2; + btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); + + m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + + m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), +m_useReferenceFrameA(useReferenceFrameA), +m_flags(0) +{ +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), +m_enableAngularMotor(false), +m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), +m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), +m_useReferenceFrameA(useReferenceFrameA), +m_flags(0) +{ + ///not providing rigidbody B means implicitly using worldspace for body B + + m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); +#ifndef _BT_USE_CENTER_LIMIT_ + //start with free + m_lowerLimit = btScalar(1.0f); + m_upperLimit = btScalar(-1.0f); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +#endif + m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); +} + + + +void btHingeConstraint::buildJacobian() +{ + if (m_useSolveConstraintObsolete) + { + m_appliedImpulse = btScalar(0.); + m_accMotorImpulse = btScalar(0.); + + if (!m_angularOnly) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + + for (int i=0;i<3;i++) + { + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + } + } + + //calculate two perpendicular jointAxis, orthogonal to hingeAxis + //these two jointAxis require equal angular velocities for both bodies + + //this is unused for now, it's a todo + btVector3 jointAxis0local; + btVector3 jointAxis1local; + + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); + + btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; + btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + + new (&m_jacAng[0]) btJacobianEntry(jointAxis0, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + new (&m_jacAng[1]) btJacobianEntry(jointAxis1, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + // clear accumulator + m_accLimitImpulse = btScalar(0.); + + // test angular limit + testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + + //Compute K = J*W*J' for hinge axis + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA)); + + } +} + + +#endif //__SPU__ + + +void btHingeConstraint::getInfo1(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular + info->nub = 1; + //always add the row, to avoid computation (data is not available yet) + //prepare constraint + testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + if(getSolveLimit() || getEnableAngularMotor()) + { + info->m_numConstraintRows++; // limit 3rd anguar as well + info->nub--; + } + + } +} + +void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + //always add the 'limit' row, to avoid computation (data is not available yet) + info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular + info->nub = 0; + } +} + +void btHingeConstraint::getInfo2 (btConstraintInfo2* info) +{ + if(m_useOffsetForConstraintFrame) + { + getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); + } + else + { + getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); + } +} + + +void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +{ + ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now + testLimit(transA,transB); + + getInfo2Internal(info,transA,transB,angVelA,angVelB); +} + + +void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +{ + + btAssert(!m_useSolveConstraintObsolete); + int i, skip = info->rowskip; + // transforms in world space + btTransform trA = transA*m_rbAFrame; + btTransform trB = transB*m_rbBFrame; + // pivot point + btVector3 pivotAInW = trA.getOrigin(); + btVector3 pivotBInW = trB.getOrigin(); +#if 0 + if (0) + { + for (i=0;i<6;i++) + { + info->m_J1linearAxis[i*skip]=0; + info->m_J1linearAxis[i*skip+1]=0; + info->m_J1linearAxis[i*skip+2]=0; + + info->m_J1angularAxis[i*skip]=0; + info->m_J1angularAxis[i*skip+1]=0; + info->m_J1angularAxis[i*skip+2]=0; + + info->m_J2linearAxis[i*skip]=0; + info->m_J2linearAxis[i*skip+1]=0; + info->m_J2linearAxis[i*skip+2]=0; + + info->m_J2angularAxis[i*skip]=0; + info->m_J2angularAxis[i*skip+1]=0; + info->m_J2angularAxis[i*skip+2]=0; + + info->m_constraintError[i*skip]=0.f; + } + } +#endif //#if 0 + // linear (all fixed) + + if (!m_angularOnly) + { + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[skip + 1] = 1; + info->m_J1linearAxis[2 * skip + 2] = 1; + + info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[skip + 1] = -1; + info->m_J2linearAxis[2 * skip + 2] = -1; + } + + + + + btVector3 a1 = pivotAInW - transA.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + btVector3 a2 = pivotBInW - transB.getOrigin(); + { + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + // linear RHS + btScalar k = info->fps * info->erp; + if (!m_angularOnly) + { + for(i = 0; i < 3; i++) + { + info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]); + } + } + // make rotations around X and Y equal + // the hinge axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the hinge axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the hinge axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + // get hinge axis (Z) + btVector3 ax1 = trA.getBasis().getColumn(2); + // get 2 orthos to hinge axis (X, Y) + btVector3 p = trA.getBasis().getColumn(0); + btVector3 q = trA.getBasis().getColumn(1); + // set the two hinge angular rows + int s3 = 3 * info->rowskip; + int s4 = 4 * info->rowskip; + + info->m_J1angularAxis[s3 + 0] = p[0]; + info->m_J1angularAxis[s3 + 1] = p[1]; + info->m_J1angularAxis[s3 + 2] = p[2]; + info->m_J1angularAxis[s4 + 0] = q[0]; + info->m_J1angularAxis[s4 + 1] = q[1]; + info->m_J1angularAxis[s4 + 2] = q[2]; + + info->m_J2angularAxis[s3 + 0] = -p[0]; + info->m_J2angularAxis[s3 + 1] = -p[1]; + info->m_J2angularAxis[s3 + 2] = -p[2]; + info->m_J2angularAxis[s4 + 0] = -q[0]; + info->m_J2angularAxis[s4 + 1] = -q[1]; + info->m_J2angularAxis[s4 + 2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the hinge back into alignment. + // if ax1,ax2 are the unit length hinge axes as computed from body1 and + // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if `theta' is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + btVector3 ax2 = trB.getBasis().getColumn(2); + btVector3 u = ax1.cross(ax2); + info->m_constraintError[s3] = k * u.dot(p); + info->m_constraintError[s4] = k * u.dot(q); + // check angular limits + int nrow = 4; // last filled row + int srow; + btScalar limit_err = btScalar(0.0); + int limit = 0; + if(getSolveLimit()) + { +#ifdef _BT_USE_CENTER_LIMIT_ + limit_err = m_limit.getCorrection() * m_referenceSign; +#else + limit_err = m_correction * m_referenceSign; +#endif + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + + } + // if the hinge has joint limits or motor, add in the extra row + int powered = 0; + if(getEnableAngularMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerLimit(); + btScalar histop = getUpperLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = btScalar(0.0f); + btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp; + if(powered) + { + if(m_flags & BT_HINGE_FLAGS_CFM_NORM) + { + info->cfm[srow] = m_normalCFM; + } + btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP); + info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; + info->m_lowerLimit[srow] = - m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_HINGE_FLAGS_CFM_STOP) + { + info->cfm[srow] = m_stopCFM; + } + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) +#ifdef _BT_USE_CENTER_LIMIT_ + btScalar bounce = m_limit.getRelaxationFactor(); +#else + btScalar bounce = m_relaxationFactor; +#endif + if(bounce > btScalar(0.0)) + { + btScalar vel = angVelA.dot(ax1); + vel -= angVelB.dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } +#ifdef _BT_USE_CENTER_LIMIT_ + info->m_constraintError[srow] *= m_limit.getBiasFactor(); +#else + info->m_constraintError[srow] *= m_biasFactor; +#endif + } // if(limit) + } // if angular limit or powered +} + + +void btHingeConstraint::setFrames(const btTransform & frameA, const btTransform & frameB) +{ + m_rbAFrame = frameA; + m_rbBFrame = frameB; + buildJacobian(); +} + + +void btHingeConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + + +btScalar btHingeConstraint::getHingeAngle() +{ + return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB) +{ + const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1); +// btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + return m_referenceSign * angle; +} + + + +void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB) +{ + // Compute limit information + m_hingeAngle = getHingeAngle(transA,transB); +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit.test(m_hingeAngle); +#else + m_correction = btScalar(0.); + m_limitSign = btScalar(0.); + m_solveLimit = false; + if (m_lowerLimit <= m_upperLimit) + { + m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit); + if (m_hingeAngle <= m_lowerLimit) + { + m_correction = (m_lowerLimit - m_hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } + else if (m_hingeAngle >= m_upperLimit) + { + m_correction = m_upperLimit - m_hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } +#endif + return; +} + + +static btVector3 vHinge(0, 0, btScalar(1)); + +void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt) +{ + // convert target from body to constraint space + btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation(); + qConstraint.normalize(); + + // extract "pure" hinge component + btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize(); + btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge); + btQuaternion qHinge = qNoHinge.inverse() * qConstraint; + qHinge.normalize(); + + // compute angular target, clamped to limits + btScalar targetAngle = qHinge.getAngle(); + if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate. + { + qHinge = -(qHinge); + targetAngle = qHinge.getAngle(); + } + if (qHinge.getZ() < 0) + targetAngle = -targetAngle; + + setMotorTarget(targetAngle, dt); +} + +void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt) +{ +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit.fit(targetAngle); +#else + if (m_lowerLimit < m_upperLimit) + { + if (targetAngle < m_lowerLimit) + targetAngle = m_lowerLimit; + else if (targetAngle > m_upperLimit) + targetAngle = m_upperLimit; + } +#endif + // compute angular velocity + btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + btScalar dAngle = targetAngle - curAngle; + m_motorTargetVelocity = dAngle / dt; +} + + + +void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +{ + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + // transforms in world space + btTransform trA = transA*m_rbAFrame; + btTransform trB = transB*m_rbBFrame; + // pivot point +// btVector3 pivotAInW = trA.getOrigin(); +// btVector3 pivotBInW = trB.getOrigin(); +#if 1 + // difference between frames in WCS + btVector3 ofs = trB.getOrigin() - trA.getOrigin(); + // now get weight factors depending on masses + btScalar miA = getRigidBodyA().getInvMass(); + btScalar miB = getRigidBodyB().getInvMass(); + bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); + btScalar miS = miA + miB; + btScalar factA, factB; + if(miS > btScalar(0.f)) + { + factA = miB / miS; + } + else + { + factA = btScalar(0.5f); + } + factB = btScalar(1.0f) - factA; + // get the desired direction of hinge axis + // as weighted sum of Z-orthos of frameA and frameB in WCS + btVector3 ax1A = trA.getBasis().getColumn(2); + btVector3 ax1B = trB.getBasis().getColumn(2); + btVector3 ax1 = ax1A * factA + ax1B * factB; + ax1.normalize(); + // fill first 3 rows + // we want: velA + wA x relA == velB + wB x relB + btTransform bodyA_trans = transA; + btTransform bodyB_trans = transB; + int s0 = 0; + int s1 = s; + int s2 = s * 2; + int nrow = 2; // last filled row + btVector3 tmpA, tmpB, relA, relB, p, q; + // get vector from bodyB to frameB in WCS + relB = trB.getOrigin() - bodyB_trans.getOrigin(); + // get its projection to hinge axis + btVector3 projB = ax1 * relB.dot(ax1); + // get vector directed from bodyB to hinge axis (and orthogonal to it) + btVector3 orthoB = relB - projB; + // same for bodyA + relA = trA.getOrigin() - bodyA_trans.getOrigin(); + btVector3 projA = ax1 * relA.dot(ax1); + btVector3 orthoA = relA - projA; + btVector3 totalDist = projA - projB; + // get offset vectors relA and relB + relA = orthoA + totalDist * factA; + relB = orthoB - totalDist * factB; + // now choose average ortho to hinge axis + p = orthoB * factA + orthoA * factB; + btScalar len2 = p.length2(); + if(len2 > SIMD_EPSILON) + { + p /= btSqrt(len2); + } + else + { + p = trA.getBasis().getColumn(1); + } + // make one more ortho + q = ax1.cross(p); + // fill three rows + tmpA = relA.cross(p); + tmpB = relB.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i]; + tmpA = relA.cross(q); + tmpB = relB.cross(q); + if(hasStaticBody && getSolveLimit()) + { // to make constraint between static and dynamic objects more rigid + // remove wA (or wB) from equation if angular limit is hit + tmpB *= factB; + tmpA *= factA; + } + for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i]; + tmpA = relA.cross(ax1); + tmpB = relB.cross(ax1); + if(hasStaticBody) + { // to make constraint between static and dynamic objects more rigid + // remove wA (or wB) from equation + tmpB *= factB; + tmpA *= factA; + } + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; + + btScalar k = info->fps * info->erp; + + if (!m_angularOnly) + { + for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i]; + + for (i=0; i<3; i++) info->m_J2linearAxis[s0+i] = -p[i]; + for (i=0; i<3; i++) info->m_J2linearAxis[s1+i] = -q[i]; + for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -ax1[i]; + + // compute three elements of right hand side + + btScalar rhs = k * p.dot(ofs); + info->m_constraintError[s0] = rhs; + rhs = k * q.dot(ofs); + info->m_constraintError[s1] = rhs; + rhs = k * ax1.dot(ofs); + info->m_constraintError[s2] = rhs; + } + // the hinge axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the hinge axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the hinge axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + int s3 = 3 * s; + int s4 = 4 * s; + info->m_J1angularAxis[s3 + 0] = p[0]; + info->m_J1angularAxis[s3 + 1] = p[1]; + info->m_J1angularAxis[s3 + 2] = p[2]; + info->m_J1angularAxis[s4 + 0] = q[0]; + info->m_J1angularAxis[s4 + 1] = q[1]; + info->m_J1angularAxis[s4 + 2] = q[2]; + + info->m_J2angularAxis[s3 + 0] = -p[0]; + info->m_J2angularAxis[s3 + 1] = -p[1]; + info->m_J2angularAxis[s3 + 2] = -p[2]; + info->m_J2angularAxis[s4 + 0] = -q[0]; + info->m_J2angularAxis[s4 + 1] = -q[1]; + info->m_J2angularAxis[s4 + 2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the hinge back into alignment. + // if ax1A,ax1B are the unit length hinge axes as computed from bodyA and + // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if "theta" is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + k = info->fps * info->erp; + btVector3 u = ax1A.cross(ax1B); + info->m_constraintError[s3] = k * u.dot(p); + info->m_constraintError[s4] = k * u.dot(q); +#endif + // check angular limits + nrow = 4; // last filled row + int srow; + btScalar limit_err = btScalar(0.0); + int limit = 0; + if(getSolveLimit()) + { +#ifdef _BT_USE_CENTER_LIMIT_ + limit_err = m_limit.getCorrection() * m_referenceSign; +#else + limit_err = m_correction * m_referenceSign; +#endif + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + + } + // if the hinge has joint limits or motor, add in the extra row + int powered = 0; + if(getEnableAngularMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerLimit(); + btScalar histop = getUpperLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = btScalar(0.0f); + btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp; + if(powered) + { + if(m_flags & BT_HINGE_FLAGS_CFM_NORM) + { + info->cfm[srow] = m_normalCFM; + } + btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP); + info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; + info->m_lowerLimit[srow] = - m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_HINGE_FLAGS_CFM_STOP) + { + info->cfm[srow] = m_stopCFM; + } + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) +#ifdef _BT_USE_CENTER_LIMIT_ + btScalar bounce = m_limit.getRelaxationFactor(); +#else + btScalar bounce = m_relaxationFactor; +#endif + if(bounce > btScalar(0.0)) + { + btScalar vel = angVelA.dot(ax1); + vel -= angVelB.dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } +#ifdef _BT_USE_CENTER_LIMIT_ + info->m_constraintError[srow] *= m_limit.getBiasFactor(); +#else + info->m_constraintError[srow] *= m_biasFactor; +#endif + } // if(limit) + } // if angular limit or powered +} + + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btHingeConstraint::setParam(int num, btScalar value, int axis) +{ + if((axis == -1) || (axis == 5)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + m_stopERP = value; + m_flags |= BT_HINGE_FLAGS_ERP_STOP; + break; + case BT_CONSTRAINT_STOP_CFM : + m_stopCFM = value; + m_flags |= BT_HINGE_FLAGS_CFM_STOP; + break; + case BT_CONSTRAINT_CFM : + m_normalCFM = value; + m_flags |= BT_HINGE_FLAGS_CFM_NORM; + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } +} + +///return the local value of parameter +btScalar btHingeConstraint::getParam(int num, int axis) const +{ + btScalar retVal = 0; + if((axis == -1) || (axis == 5)) + { + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP); + retVal = m_stopERP; + break; + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP); + retVal = m_stopCFM; + break; + case BT_CONSTRAINT_CFM : + btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM); + retVal = m_normalCFM; + break; + default : + btAssertConstrParams(0); + } + } + else + { + btAssertConstrParams(0); + } + return retVal; +} + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h new file mode 100644 index 00000000..7c33ac24 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -0,0 +1,412 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ + +#ifndef BT_HINGECONSTRAINT_H +#define BT_HINGECONSTRAINT_H + +#define _BT_USE_CENTER_LIMIT_ 1 + + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version +#define btHingeConstraintDataName "btHingeConstraintDoubleData2" +#else +#define btHingeConstraintData btHingeConstraintFloatData +#define btHingeConstraintDataName "btHingeConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION + + + +enum btHingeFlags +{ + BT_HINGE_FLAGS_CFM_STOP = 1, + BT_HINGE_FLAGS_ERP_STOP = 2, + BT_HINGE_FLAGS_CFM_NORM = 4 +}; + + +/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space +/// axis defines the orientation of the hinge axis +ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint +{ +#ifdef IN_PARALLELL_SOLVER +public: +#endif + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor + + btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransform m_rbBFrame; + + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + + +#ifdef _BT_USE_CENTER_LIMIT_ + btAngularLimit m_limit; +#else + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_limitSign; + btScalar m_correction; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + bool m_solveLimit; +#endif + + btScalar m_kHinge; + + + btScalar m_accLimitImpulse; + btScalar m_hingeAngle; + btScalar m_referenceSign; + + bool m_angularOnly; + bool m_enableAngularMotor; + bool m_useSolveConstraintObsolete; + bool m_useOffsetForConstraintFrame; + bool m_useReferenceFrameA; + + btScalar m_accMotorImpulse; + + int m_flags; + btScalar m_normalCFM; + btScalar m_stopCFM; + btScalar m_stopERP; + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false); + + + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + + void getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + void getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + + + void updateRHS(btScalar timeStep); + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + btRigidBody& getRigidBodyA() + { + return m_rbA; + } + + btRigidBody& getRigidBodyB() + { + return m_rbB; + } + + btTransform& getFrameOffsetA() + { + return m_rbAFrame; + } + + btTransform& getFrameOffsetB() + { + return m_rbBFrame; + } + + void setFrames(const btTransform& frameA, const btTransform& frameB); + + void setAngularOnly(bool angularOnly) + { + m_angularOnly = angularOnly; + } + + void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse) + { + m_enableAngularMotor = enableMotor; + m_motorTargetVelocity = targetVelocity; + m_maxMotorImpulse = maxMotorImpulse; + } + + // extra motor API, including ability to set a target rotation (as opposed to angular velocity) + // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to + // maintain a given angular target. + void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; } + void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; } + void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B. + void setMotorTarget(btScalar targetAngle, btScalar dt); + + + void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor); +#else + m_lowerLimit = btNormalizeAngle(low); + m_upperLimit = btNormalizeAngle(high); + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; +#endif + } + + void setAxis(btVector3& axisInA) + { + btVector3 rbAxisA1, rbAxisA2; + btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); + btVector3 pivotInA = m_rbAFrame.getOrigin(); +// m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA)); + + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis(); + + } + + btScalar getLowerLimit() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getLow(); +#else + return m_lowerLimit; +#endif + } + + btScalar getUpperLimit() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getHigh(); +#else + return m_upperLimit; +#endif + } + + + btScalar getHingeAngle(); + + btScalar getHingeAngle(const btTransform& transA,const btTransform& transB); + + void testLimit(const btTransform& transA,const btTransform& transB); + + + const btTransform& getAFrame() const { return m_rbAFrame; }; + const btTransform& getBFrame() const { return m_rbBFrame; }; + + btTransform& getAFrame() { return m_rbAFrame; }; + btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveLimit() + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.isLimit(); +#else + return m_solveLimit; +#endif + } + + inline btScalar getLimitSign() + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getSign(); +#else + return m_limitSign; +#endif + } + + inline bool getAngularOnly() + { + return m_angularOnly; + } + inline bool getEnableAngularMotor() + { + return m_enableAngularMotor; + } + inline btScalar getMotorTargetVelosity() + { + return m_motorTargetVelocity; + } + inline btScalar getMaxMotorImpulse() + { + return m_maxMotorImpulse; + } + // access for UseFrameOffset + bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + + +//only for backward compatibility +#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION +///this structure is not used, except for loading pre-2.82 .bullet files +struct btHingeConstraintDoubleData +{ + btTypedConstraintData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformDoubleData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + +}; +#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION + + +struct btHingeConstraintFloatData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformFloatData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + +}; + + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btHingeConstraintDoubleData2 +{ + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformDoubleData m_rbBFrame; + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + double m_motorTargetVelocity; + double m_maxMotorImpulse; + + double m_lowerLimit; + double m_upperLimit; + double m_limitSoftness; + double m_biasFactor; + double m_relaxationFactor; + char m_padding1[4]; + +}; + + + + +SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btHingeConstraintData); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer; + btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer); + + m_rbAFrame.serialize(hingeData->m_rbAFrame); + m_rbBFrame.serialize(hingeData->m_rbBFrame); + + hingeData->m_angularOnly = m_angularOnly; + hingeData->m_enableAngularMotor = m_enableAngularMotor; + hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse); + hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity); + hingeData->m_useReferenceFrameA = m_useReferenceFrameA; +#ifdef _BT_USE_CENTER_LIMIT_ + hingeData->m_lowerLimit = float(m_limit.getLow()); + hingeData->m_upperLimit = float(m_limit.getHigh()); + hingeData->m_limitSoftness = float(m_limit.getSoftness()); + hingeData->m_biasFactor = float(m_limit.getBiasFactor()); + hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor()); +#else + hingeData->m_lowerLimit = float(m_lowerLimit); + hingeData->m_upperLimit = float(m_upperLimit); + hingeData->m_limitSoftness = float(m_limitSoftness); + hingeData->m_biasFactor = float(m_biasFactor); + hingeData->m_relaxationFactor = float(m_relaxationFactor); +#endif + + return btHingeConstraintDataName; +} + +#endif //BT_HINGECONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h new file mode 100644 index 00000000..125580d1 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -0,0 +1,155 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_JACOBIAN_ENTRY_H +#define BT_JACOBIAN_ENTRY_H + +#include "LinearMath/btMatrix3x3.h" + + +//notes: +// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components +// which makes the btJacobianEntry memory layout 16 bytes +// if you only are interested in angular part, just feed massInvA and massInvB zero + +/// Jacobian entry is an abstraction that allows to describe constraints +/// it can be used in combination with a constraint solver +/// Can be used to relate the effect of an impulse to the constraint error +ATTRIBUTE_ALIGNED16(class) btJacobianEntry +{ +public: + btJacobianEntry() {}; + //constraint between two different rigidbodies + btJacobianEntry( + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& jointAxis, + const btVector3& inertiaInvA, + const btScalar massInvA, + const btVector3& inertiaInvB, + const btScalar massInvB) + :m_linearJointAxis(jointAxis) + { + m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis)); + m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //angular constraint between two different rigidbodies + btJacobianEntry(const btVector3& jointAxis, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + { + m_aJ= world2A*jointAxis; + m_bJ = world2B*-jointAxis; + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //angular constraint between two different rigidbodies + btJacobianEntry(const btVector3& axisInA, + const btVector3& axisInB, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + , m_aJ(axisInA) + , m_bJ(-axisInB) + { + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //constraint on one rigidbody + btJacobianEntry( + const btMatrix3x3& world2A, + const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& jointAxis, + const btVector3& inertiaInvA, + const btScalar massInvA) + :m_linearJointAxis(jointAxis) + { + m_aJ= world2A*(rel_pos1.cross(jointAxis)); + m_bJ = world2A*(rel_pos2.cross(-jointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + btScalar getDiagonal() const { return m_Adiag; } + + // for two constraints on the same rigidbody (for example vehicle friction) + btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const + { + const btJacobianEntry& jacA = *this; + btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); + btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ); + return lin + ang; + } + + + + // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) + btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const + { + const btJacobianEntry& jacA = *this; + btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; + btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; + btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; + btVector3 lin0 = massInvA * lin ; + btVector3 lin1 = massInvB * lin; + btVector3 sum = ang0+ang1+lin0+lin1; + return sum[0]+sum[1]+sum[2]; + } + + btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB) + { + btVector3 linrel = linvelA - linvelB; + btVector3 angvela = angvelA * m_aJ; + btVector3 angvelb = angvelB * m_bJ; + linrel *= m_linearJointAxis; + angvela += angvelb; + angvela += linrel; + btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2]; + return rel_vel2 + SIMD_EPSILON; + } +//private: + + btVector3 m_linearJointAxis; + btVector3 m_aJ; + btVector3 m_bJ; + btVector3 m_0MinvJt; + btVector3 m_1MinvJt; + //Optimization: can be stored in the w/last component of one of the vectors + btScalar m_Adiag; + +}; + +#endif //BT_JACOBIAN_ENTRY_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp new file mode 100644 index 00000000..3c0430b9 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -0,0 +1,229 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btPoint2PointConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include + + + + + +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), +m_flags(0), +m_useSolveConstraintObsolete(false) +{ + +} + + +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), +m_flags(0), +m_useSolveConstraintObsolete(false) +{ + +} + +void btPoint2PointConstraint::buildJacobian() +{ + + ///we need it for both methods + { + m_appliedImpulse = btScalar(0.); + + btVector3 normal(0,0,0); + + for (int i=0;i<3;i++) + { + normal[i] = 1; + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), + normal, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + normal[i] = 0; + } + } + + +} + +void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) +{ + getInfo1NonVirtual(info); +} + +void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } else + { + info->m_numConstraintRows = 3; + info->nub = 3; + } +} + + + + +void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) +{ + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + +void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans) +{ + btAssert(!m_useSolveConstraintObsolete); + + //retrieve matrices + + // anchor points in global coordinates with respect to body PORs. + + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip+1] = 1; + info->m_J1linearAxis[2*info->rowskip+2] = 1; + + btVector3 a1 = body0_trans.getBasis()*getPivotInA(); + { + btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3 a1neg = -a1; + a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[info->rowskip+1] = -1; + info->m_J2linearAxis[2*info->rowskip+2] = -1; + + btVector3 a2 = body1_trans.getBasis()*getPivotInB(); + + { + // btVector3 a2n = -a2; + btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); + a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + } + + + + // set right hand side + btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp; + btScalar k = info->fps * currERP; + int j; + for (j=0; j<3; j++) + { + info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); + //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]); + } + if(m_flags & BT_P2P_FLAGS_CFM) + { + for (j=0; j<3; j++) + { + info->cfm[j*info->rowskip] = m_cfm; + } + } + + btScalar impulseClamp = m_setting.m_impulseClamp;// + for (j=0; j<3; j++) + { + if (m_setting.m_impulseClamp > 0) + { + info->m_lowerLimit[j*info->rowskip] = -impulseClamp; + info->m_upperLimit[j*info->rowskip] = impulseClamp; + } + } + info->m_damping = m_setting.m_damping; + +} + + + +void btPoint2PointConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btPoint2PointConstraint::setParam(int num, btScalar value, int axis) +{ + if(axis != -1) + { + btAssertConstrParams(0); + } + else + { + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + m_erp = value; + m_flags |= BT_P2P_FLAGS_ERP; + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + m_cfm = value; + m_flags |= BT_P2P_FLAGS_CFM; + break; + default: + btAssertConstrParams(0); + } + } +} + +///return the local value of parameter +btScalar btPoint2PointConstraint::getParam(int num, int axis) const +{ + btScalar retVal(SIMD_INFINITY); + if(axis != -1) + { + btAssertConstrParams(0); + } + else + { + switch(num) + { + case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_STOP_ERP : + btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP); + retVal = m_erp; + break; + case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_STOP_CFM : + btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM); + retVal = m_cfm; + break; + default: + btAssertConstrParams(0); + } + } + return retVal; +} + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h new file mode 100644 index 00000000..91218949 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -0,0 +1,175 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_POINT2POINTCONSTRAINT_H +#define BT_POINT2POINTCONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + +#ifdef BT_USE_DOUBLE_PRECISION +#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2 +#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2" +#else +#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData +#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION + +struct btConstraintSetting +{ + btConstraintSetting() : + m_tau(btScalar(0.3)), + m_damping(btScalar(1.)), + m_impulseClamp(btScalar(0.)) + { + } + btScalar m_tau; + btScalar m_damping; + btScalar m_impulseClamp; +}; + +enum btPoint2PointFlags +{ + BT_P2P_FLAGS_ERP = 1, + BT_P2P_FLAGS_CFM = 2 +}; + +/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space +ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint +{ +#ifdef IN_PARALLELL_SOLVER +public: +#endif + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btVector3 m_pivotInA; + btVector3 m_pivotInB; + + int m_flags; + btScalar m_erp; + btScalar m_cfm; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + + btConstraintSetting m_setting; + + btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); + + btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA); + + + virtual void buildJacobian(); + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual (btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans); + + void updateRHS(btScalar timeStep); + + void setPivotA(const btVector3& pivotA) + { + m_pivotInA = pivotA; + } + + void setPivotB(const btVector3& pivotB) + { + m_pivotInB = pivotB; + } + + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btPoint2PointConstraintFloatData +{ + btTypedConstraintData m_typeConstraintData; + btVector3FloatData m_pivotInA; + btVector3FloatData m_pivotInB; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btPoint2PointConstraintDoubleData2 +{ + btTypedConstraintDoubleData m_typeConstraintData; + btVector3DoubleData m_pivotInA; + btVector3DoubleData m_pivotInB; +}; + +#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +///this structure is not used, except for loading pre-2.82 .bullet files +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btPoint2PointConstraintDoubleData +{ + btTypedConstraintData m_typeConstraintData; + btVector3DoubleData m_pivotInA; + btVector3DoubleData m_pivotInB; +}; +#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION + + +SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btPoint2PointConstraintData2); + +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btPoint2PointConstraintData2* p2pData = (btPoint2PointConstraintData2*)dataBuffer; + + btTypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer); + m_pivotInA.serialize(p2pData->m_pivotInA); + m_pivotInB.serialize(p2pData->m_pivotInB); + + return btPoint2PointConstraintDataName; +} + +#endif //BT_POINT2POINTCONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp new file mode 100644 index 00000000..be93e354 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -0,0 +1,1739 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +//#define COMPUTE_IMPULSE_DENOM 1 +//#define BT_ADDITIONAL_DEBUG + +//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. + +#include "btSequentialImpulseConstraintSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" + +#include "LinearMath/btIDebugDraw.h" +//#include "btJacobianEntry.h" +#include "LinearMath/btMinMax.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btQuickprof.h" +//#include "btSolverBody.h" +//#include "btSolverConstraint.h" +#include "LinearMath/btAlignedObjectArray.h" +#include //for memset + +int gNumSplitImpulseRecoveries = 0; + +#include "BulletDynamics/Dynamics/btRigidBody.h" + +btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() +:m_btSeed2(0) +{ + +} + +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() +{ +} + +#ifdef USE_SIMD +#include +#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) +static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) ); +} +#endif//USE_SIMD + +// Project Gauss Seidel or the equivalent Sequential Impulse +void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128,body2.internalGetInvMass().mVec128); + __m128 impulseMagnitude = deltaImpulse; + body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSingleConstraintRowGeneric(body1,body2,c); +#endif +} + +// Project Gauss Seidel or the equivalent Sequential Impulse + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity()); + const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity()); + +// const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn; + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else if (sum > c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + + body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); +} + + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,body2.internalGetInvMass().mVec128); + __m128 impulseMagnitude = deltaImpulse; + body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSingleConstraintRowLowerLimit(body1,body2,c); +#endif +} + +// Projected Gauss Seidel or the equivalent Sequential Impulse + void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity()); + const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity()); + + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else + { + c.m_appliedImpulse = sum; + } + body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); +} + + +void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& c) +{ + if (c.m_rhsPenetration) + { + gNumSplitImpulseRecoveries++; + btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity()); + const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity()); + + deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse; + c.m_appliedPushImpulse = c.m_lowerLimit; + } + else + { + c.m_appliedPushImpulse = sum; + } + body1.internalApplyPushImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + body2.internalApplyPushImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); + } +} + + void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c) +{ +#ifdef USE_SIMD + if (!c.m_rhsPenetration) + return; + + gNumSplitImpulseRecoveries++; + + __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); + btSimdScalar resultLowerLess,resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); + deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); + c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,body2.internalGetInvMass().mVec128); + __m128 impulseMagnitude = deltaImpulse; + body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); + body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); + body2.internalGetPushVelocity().mVec128 = _mm_add_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); + body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); +#else + resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c); +#endif +} + + + +unsigned long btSequentialImpulseConstraintSolver::btRand2() +{ + m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; + return m_btSeed2; +} + + + +//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1) +int btSequentialImpulseConstraintSolver::btRandInt2 (int n) +{ + // seems good; xor-fold and modulus + const unsigned long un = static_cast(n); + unsigned long r = btRand2(); + + // note: probably more aggressive than it needs to be -- might be + // able to get away without one or two of the innermost branches. + if (un <= 0x00010000UL) { + r ^= (r >> 16); + if (un <= 0x00000100UL) { + r ^= (r >> 8); + if (un <= 0x00000010UL) { + r ^= (r >> 4); + if (un <= 0x00000004UL) { + r ^= (r >> 2); + if (un <= 0x00000002UL) { + r ^= (r >> 1); + } + } + } + } + } + + return (int) (r % un); +} + + + +void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep) +{ + + btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0; + + solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f); + + if (rb) + { + solverBody->m_worldTransform = rb->getWorldTransform(); + solverBody->internalSetInvMass(btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor()); + solverBody->m_originalBody = rb; + solverBody->m_angularFactor = rb->getAngularFactor(); + solverBody->m_linearFactor = rb->getLinearFactor(); + solverBody->m_linearVelocity = rb->getLinearVelocity(); + solverBody->m_angularVelocity = rb->getAngularVelocity(); + solverBody->m_externalForceImpulse = rb->getTotalForce()*rb->getInvMass()*timeStep; + solverBody->m_externalTorqueImpulse = rb->getTotalTorque()*rb->getInvInertiaTensorWorld()*timeStep ; + + } else + { + solverBody->m_worldTransform.setIdentity(); + solverBody->internalSetInvMass(btVector3(0,0,0)); + solverBody->m_originalBody = 0; + solverBody->m_angularFactor.setValue(1,1,1); + solverBody->m_linearFactor.setValue(1,1,1); + solverBody->m_linearVelocity.setValue(0,0,0); + solverBody->m_angularVelocity.setValue(0,0,0); + solverBody->m_externalForceImpulse.setValue(0,0,0); + solverBody->m_externalTorqueImpulse.setValue(0,0,0); + } + + +} + + + + + + +btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution) +{ + btScalar rest = restitution * -rel_vel; + return rest; +} + + + +void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode) +{ + + + if (colObj && colObj->hasAnisotropicFriction(frictionMode)) + { + // transform to local coordinates + btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis(); + const btVector3& friction_scaling = colObj->getAnisotropicFriction(); + //apply anisotropic friction + loc_lateral *= friction_scaling; + // ... and transform it back to global coordinates + frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral; + } + +} + + + + +void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +{ + + + btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB]; + + btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody; + btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + + solverConstraint.m_friction = cp.m_combinedFriction; + solverConstraint.m_originalContactPoint = 0; + + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedPushImpulse = 0.f; + + if (body0) + { + solverConstraint.m_contactNormal1 = normalAxis; + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor(); + }else + { + solverConstraint.m_contactNormal1.setZero(); + solverConstraint.m_relpos1CrossNormal.setZero(); + solverConstraint.m_angularComponentA .setZero(); + } + + if (body1) + { + solverConstraint.m_contactNormal2 = -normalAxis; + btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor(); + } else + { + solverConstraint.m_contactNormal2.setZero(); + solverConstraint.m_relpos2CrossNormal.setZero(); + solverConstraint.m_angularComponentB.setZero(); + } + + { + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (body0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = body0->getInvMass() + normalAxis.dot(vec); + } + if (body1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = body1->getInvMass() + normalAxis.dot(vec); + } + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + } + + { + + + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0)) + + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0)); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0)) + + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0)); + + rel_vel = vel1Dotn+vel2Dotn; + +// btScalar positionalError = 0.f; + + btSimdScalar velocityError = desiredVelocity - rel_vel; + btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_cfm = cfmSlip; + solverConstraint.m_lowerLimit = -solverConstraint.m_friction; + solverConstraint.m_upperLimit = solverConstraint.m_friction; + + } +} + +btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +{ + btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing(); + solverConstraint.m_frictionIndex = frictionIndex; + setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, + colObj0, colObj1, relaxation, desiredVelocity, cfmSlip); + return solverConstraint; +} + + +void btSequentialImpulseConstraintSolver::setupRollingFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB, + btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, + btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, + btScalar desiredVelocity, btScalar cfmSlip) + +{ + btVector3 normalAxis(0,0,0); + + + solverConstraint.m_contactNormal1 = normalAxis; + solverConstraint.m_contactNormal2 = -normalAxis; + btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB]; + + btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody; + btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + + solverConstraint.m_friction = cp.m_combinedRollingFriction; + solverConstraint.m_originalContactPoint = 0; + + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedPushImpulse = 0.f; + + { + btVector3 ftorqueAxis1 = -normalAxis1; + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0); + } + { + btVector3 ftorqueAxis1 = normalAxis1; + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0); + } + + + { + btVector3 iMJaA = body0?body0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0); + btVector3 iMJaB = body1?body1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0); + btScalar sum = 0; + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + } + + { + + + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0)) + + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0)); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0)) + + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0)); + + rel_vel = vel1Dotn+vel2Dotn; + +// btScalar positionalError = 0.f; + + btSimdScalar velocityError = desiredVelocity - rel_vel; + btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_cfm = cfmSlip; + solverConstraint.m_lowerLimit = -solverConstraint.m_friction; + solverConstraint.m_upperLimit = solverConstraint.m_friction; + + } +} + + + + + + + + +btSolverConstraint& btSequentialImpulseConstraintSolver::addRollingFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +{ + btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing(); + solverConstraint.m_frictionIndex = frictionIndex; + setupRollingFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, + colObj0, colObj1, relaxation, desiredVelocity, cfmSlip); + return solverConstraint; +} + + +int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep) +{ + + int solverBodyIdA = -1; + + if (body.getCompanionId() >= 0) + { + //body has already been converted + solverBodyIdA = body.getCompanionId(); + btAssert(solverBodyIdA < m_tmpSolverBodyPool.size()); + } else + { + btRigidBody* rb = btRigidBody::upcast(&body); + //convert both active and kinematic objects (for their velocity) + if (rb && (rb->getInvMass() || rb->isKinematicObject())) + { + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,&body,timeStep); + body.setCompanionId(solverBodyIdA); + } else + { + + if (m_fixedBodyId<0) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody,0,timeStep); + } + return m_fixedBodyId; +// return 0;//assume first one is a fixed solver body + } + } + + return solverBodyIdA; + +} +#include + + +void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint, + int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + const btVector3& rel_pos1, const btVector3& rel_pos2) +{ + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + + btRigidBody* rb0 = bodyA->m_originalBody; + btRigidBody* rb1 = bodyB->m_originalBody; + +// btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); +// btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); + //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); + + relaxation = 1.f; + + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + + { +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } + if (rb1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } +#endif //COMPUTE_IMPULSE_DENOM + + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + } + + if (rb0) + { + solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB; + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + } else + { + solverConstraint.m_contactNormal1.setZero(); + solverConstraint.m_relpos1CrossNormal.setZero(); + } + if (rb1) + { + solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB; + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + }else + { + solverConstraint.m_contactNormal2.setZero(); + solverConstraint.m_relpos2CrossNormal.setZero(); + } + + btScalar restitution = 0.f; + btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop; + + { + btVector3 vel1,vel2; + + vel1 = rb0? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); + vel2 = rb1? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + + // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btVector3 vel = vel1 - vel2; + btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); + + + + solverConstraint.m_friction = cp.m_combinedFriction; + + + restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (restitution <= btScalar(0.)) + { + restitution = 0.f; + }; + } + + + ///warm starting (or zero if disabled) + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + if (rb0) + bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + if (rb1) + bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse); + } else + { + solverConstraint.m_appliedImpulse = 0.f; + } + + solverConstraint.m_appliedPushImpulse = 0.f; + + { + + btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse: btVector3(0,0,0); + btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse: btVector3(0,0,0); + btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse: btVector3(0,0,0); + btVector3 externalTorqueImpulseB = bodyB->m_originalBody ?bodyB->m_externalTorqueImpulse : btVector3(0,0,0); + + + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity+externalForceImpulseA) + + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity+externalTorqueImpulseA); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity+externalForceImpulseB) + + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity+externalTorqueImpulseB); + btScalar rel_vel = vel1Dotn+vel2Dotn; + + btScalar positionalError = 0.f; + btScalar velocityError = restitution - rel_vel;// * damping; + + + btScalar erp = infoGlobal.m_erp2; + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + erp = infoGlobal.m_erp; + } + + if (penetration>0) + { + positionalError = 0; + + velocityError -= penetration / infoGlobal.m_timeStep; + } else + { + positionalError = -penetration * erp/infoGlobal.m_timeStep; + } + + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;//-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhsPenetration = 0.f; + + } else + { + //split position and velocity into rhs and m_rhsPenetration + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = penetrationImpulse; + } + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } + + + + +} + + + +void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, + int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal) +{ + + btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + + btRigidBody* rb0 = bodyA->m_originalBody; + btRigidBody* rb1 = bodyB->m_originalBody; + + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; + if (rb0) + bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + if (rb1) + bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse); + } else + { + frictionConstraint1.m_appliedImpulse = 0.f; + } + } + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; + if (rb0) + bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); + if (rb1) + bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse); + } else + { + frictionConstraint2.m_appliedImpulse = 0.f; + } + } +} + + + + +void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) +{ + btCollisionObject* colObj0=0,*colObj1=0; + + colObj0 = (btCollisionObject*)manifold->getBody0(); + colObj1 = (btCollisionObject*)manifold->getBody1(); + + int solverBodyIdA = getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep); + int solverBodyIdB = getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep); + +// btRigidBody* bodyA = btRigidBody::upcast(colObj0); +// btRigidBody* bodyB = btRigidBody::upcast(colObj1); + + btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + + + + ///avoid collision response between two static objects + if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero()))) + return; + + int rollingFriction=1; + for (int j=0;jgetNumContacts();j++) + { + + btManifoldPoint& cp = manifold->getContactPoint(j); + + if (cp.getDistance() <= manifold->getContactProcessingThreshold()) + { + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + + + int frictionIndex = m_tmpSolverContactConstraintPool.size(); + btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing(); + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + + solverConstraint.m_originalContactPoint = &cp; + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + + btVector3 vel1;// = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); + btVector3 vel2;// = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + + solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1); + solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 ); + + btVector3 vel = vel1 - vel2; + btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); + + setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2); + + + +// const btVector3& pos1 = cp.getPositionWorldOnA(); +// const btVector3& pos2 = cp.getPositionWorldOnB(); + + /////setup the friction constraints + + solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size(); + + btVector3 angVelA(0,0,0),angVelB(0,0,0); + if (rb0) + angVelA = rb0->getAngularVelocity(); + if (rb1) + angVelB = rb1->getAngularVelocity(); + btVector3 relAngVel = angVelB-angVelA; + + if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0)) + { + //only a single rollingFriction per manifold + rollingFriction--; + if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold) + { + relAngVel.normalize(); + applyAnisotropicFriction(colObj0,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + if (relAngVel.length()>0.001) + addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + } else + { + addRollingFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + btVector3 axis0,axis1; + btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1); + applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + if (axis0.length()>0.001) + addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + if (axis1.length()>0.001) + addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + } + } + + ///Bullet has several options to set the friction directions + ///By default, each contact has only a single friction direction that is recomputed automatically very frame + ///based on the relative linear velocity. + ///If the relative velocity it zero, it will automatically compute a friction direction. + + ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. + ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. + /// + ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. + /// + ///The user can manually override the friction directions for certain contacts using a contact callback, + ///and set the cp.m_lateralFrictionInitialized to true + ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) + ///this will give a conveyor belt effect + /// + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) + { + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) + { + cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel); + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize();//?? + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + } else + { + btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) + { + cp.m_lateralFrictionInitialized = true; + } + } + + } else + { + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1); + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2); + + } + setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); + + + + + } + } +} + +void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal) +{ + int i; + btPersistentManifold* manifold = 0; +// btCollisionObject* colObj0=0,*colObj1=0; + + + for (i=0;iisEnabled()) + { + if (!constraint->getRigidBodyA().isStaticOrKinematicObject()) + { + bool found=false; + for (int b=0;bgetRigidBodyA()==bodies[b]) + { + found = true; + break; + } + } + btAssert(found); + } + if (!constraint->getRigidBodyB().isStaticOrKinematicObject()) + { + bool found=false; + for (int b=0;bgetRigidBodyB()==bodies[b]) + { + found = true; + break; + } + } + btAssert(found); + } + } + } + //make sure that dynamic bodies exist for all contact manifolds + for (int i=0;igetBody0()->isStaticOrKinematicObject()) + { + bool found=false; + for (int b=0;bgetBody0()==bodies[b]) + { + found = true; + break; + } + } + btAssert(found); + } + if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject()) + { + bool found=false; + for (int b=0;bgetBody1()==bodies[b]) + { + found = true; + break; + } + } + btAssert(found); + } + } +#endif //BT_ADDITIONAL_DEBUG + + + for (int i = 0; i < numBodies; i++) + { + bodies[i]->setCompanionId(-1); + } + + + m_tmpSolverBodyPool.reserve(numBodies+1); + m_tmpSolverBodyPool.resize(0); + + //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + //initSolverBody(&fixedBody,0); + + //convert all bodies + + for (int i=0;igetInvMass()) + { + btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId]; + btVector3 gyroForce (0,0,0); + if (body->getFlags()&BT_ENABLE_GYROPSCOPIC_FORCE) + { + gyroForce = body->computeGyroscopicForce(infoGlobal.m_maxGyroscopicForce); + solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; + } + } + } + + if (1) + { + int j; + for (j=0;jbuildJacobian(); + constraint->internalSetAppliedImpulse(0.0f); + } + } + + //btRigidBody* rb0=0,*rb1=0; + + //if (1) + { + { + + int totalNumRows = 0; + int i; + + m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints); + //calculate the total number of contraint rows + for (i=0;igetJointFeedback(); + if (fb) + { + fb->m_appliedForceBodyA.setZero(); + fb->m_appliedTorqueBodyA.setZero(); + fb->m_appliedForceBodyB.setZero(); + fb->m_appliedTorqueBodyB.setZero(); + } + + if (constraints[i]->isEnabled()) + { + } + if (constraints[i]->isEnabled()) + { + constraints[i]->getInfo1(&info1); + } else + { + info1.m_numConstraintRows = 0; + info1.nub = 0; + } + totalNumRows += info1.m_numConstraintRows; + } + m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows); + + + ///setup the btSolverConstraints + int currentRow = 0; + + for (i=0;igetRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + + int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep); + int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep); + + btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB]; + + + + + int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations; + if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations) + m_maxOverrideNumSolverIterations = overrideNumSolverIterations; + + + int j; + for ( j=0;jinternalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f); + bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f); + bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f); + bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f); + bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f); + bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f); + bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f); + bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f); + + + btTypedConstraint::btConstraintInfo2 info2; + info2.fps = 1.f/infoGlobal.m_timeStep; + info2.erp = infoGlobal.m_erp; + info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1; + info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; + info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2; + info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; + info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + ///the size of btSolverConstraint needs be a multiple of btScalar + btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + info2.m_constraintError = ¤tConstraintRow->m_rhs; + currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; + info2.m_damping = infoGlobal.m_damping; + info2.cfm = ¤tConstraintRow->m_cfm; + info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; + info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; + info2.m_numIterations = infoGlobal.m_numIterations; + constraints[i]->getInfo2(&info2); + + ///finalize the constraint setup + for ( j=0;j=constraints[i]->getBreakingImpulseThreshold()) + { + solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold(); + } + + if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold()) + { + solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold(); + } + + solverConstraint.m_originalContactPoint = constraint; + + { + const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal; + solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + } + { + const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + } + + { + btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + + btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1); + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJlB.dot(solverConstraint.m_contactNormal2); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + btScalar fsum = btFabs(sum); + btAssert(fsum > SIMD_EPSILON); + solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?btScalar(1.)/sum : 0.f; + } + + + + { + btScalar rel_vel; + btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0); + btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0); + + btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0); + btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0); + + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA) + + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA); + + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB) + + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB); + + rel_vel = vel1Dotn+vel2Dotn; + btScalar restitution = 0.f; + btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel * info2.m_damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_appliedImpulse = 0.f; + + + } + } + } + currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows; + } + } + + convertContacts(manifoldPtr,numManifolds,infoGlobal); + + } + +// btContactSolverInfo info = infoGlobal; + + + int numNonContactPool = m_tmpSolverNonContactConstraintPool.size(); + int numConstraintPool = m_tmpSolverContactConstraintPool.size(); + int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size(); + + ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints + m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2); + else + m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool); + + m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool); + { + int i; + for (i=0;iisEnabled()) + { + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); + } + } + + ///solve all contact constraints using SIMD, if available + if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) + { + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1; + + for (int c=0;cbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + } + } + + if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) + { + + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]]; + + if (totalImpulse>btScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + } + } + } + } + + } + else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS + { + //solve the friction constraints after all contact constraints, don't interleave them + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + int j; + + for (j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + //resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + } + } + + + int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); + for (j=0;jbtScalar(0)) + { + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; + if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction) + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint); + } + } + + + } + } + } else + { + //non-SIMD version + ///solve all joint constraints + for (int j=0;jisEnabled()) + { + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); + } + } + ///solve all contact constraints + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + for (int j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + } + } + + int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); + for (int j=0;jbtScalar(0)) + { + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; + if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction) + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint); + } + } + } + } + return 0.f; +} + + +void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +{ + int iteration; + if (infoGlobal.m_splitImpulse) + { + if (infoGlobal.m_solverMode & SOLVER_SIMD) + { + for ( iteration = 0;iteration infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations; + + for ( int iteration = 0 ; iteration< maxIterations ; iteration++) + //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--) + { + solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + } + + } + return 0.f; +} + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal) +{ + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + int i,j; + + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + for (j=0;jm_appliedImpulse = solveManifold.m_appliedImpulse; + // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + // printf("pt->m_appliedImpulseLateral1 = %f\n", f); + pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; + } + //do a callback here? + } + } + + numPoolConstraints = m_tmpSolverNonContactConstraintPool.size(); + for (j=0;jgetJointFeedback(); + if (fb) + { + fb->m_appliedForceBodyA += solverConstr.m_contactNormal1*solverConstr.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep; + fb->m_appliedForceBodyB += solverConstr.m_contactNormal2*solverConstr.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep; + fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; + fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */ + + } + + constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse); + if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold()) + { + constr->setEnabled(false); + } + } + + + + for ( i=0;isetLinearVelocity( + m_tmpSolverBodyPool[i].m_linearVelocity+ + m_tmpSolverBodyPool[i].m_externalForceImpulse); + + m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity( + m_tmpSolverBodyPool[i].m_angularVelocity+ + m_tmpSolverBodyPool[i].m_externalTorqueImpulse); + + if (infoGlobal.m_splitImpulse) + m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform); + + m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1); + } + } + + m_tmpSolverContactConstraintPool.resizeNoInitialize(0); + m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0); + m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0); + m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0); + + m_tmpSolverBodyPool.resizeNoInitialize(0); + return 0.f; +} + + + +/// btSequentialImpulseConstraintSolver Sequentially applies impulses +btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btDispatcher* /*dispatcher*/) +{ + + BT_PROFILE("solveGroup"); + //you need to provide at least some bodies + + solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer); + + solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer); + + solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal); + + return 0.f; +} + +void btSequentialImpulseConstraintSolver::reset() +{ + m_btSeed2 = 0; +} + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h new file mode 100644 index 00000000..180d2a38 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -0,0 +1,148 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H +#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H + +class btIDebugDraw; +class btPersistentManifold; +class btDispatcher; +class btCollisionObject; +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btSolverBody.h" +#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" +#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" + +///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method. +ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstraintSolver +{ +protected: + btAlignedObjectArray m_tmpSolverBodyPool; + btConstraintArray m_tmpSolverContactConstraintPool; + btConstraintArray m_tmpSolverNonContactConstraintPool; + btConstraintArray m_tmpSolverContactFrictionConstraintPool; + btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool; + + btAlignedObjectArray m_orderTmpConstraintPool; + btAlignedObjectArray m_orderNonContactConstraintPool; + btAlignedObjectArray m_orderFrictionConstraintPool; + btAlignedObjectArray m_tmpConstraintSizesPool; + int m_maxOverrideNumSolverIterations; + int m_fixedBodyId; + void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, + btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, + btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, + btScalar desiredVelocity=0., btScalar cfmSlip=0.); + + void setupRollingFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, + btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, + btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, + btScalar desiredVelocity=0., btScalar cfmSlip=0.); + + btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.); + btSolverConstraint& addRollingFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f); + + + void setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, + const btContactSolverInfo& infoGlobal,btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2); + + static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode); + + void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal); + + ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction + unsigned long m_btSeed2; + + + btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); + + virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); + + void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); + + + void resolveSplitPenetrationSIMD( + btSolverBody& bodyA,btSolverBody& bodyB, + const btSolverConstraint& contactConstraint); + + void resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& bodyA,btSolverBody& bodyB, + const btSolverConstraint& contactConstraint); + + //internal method + int getOrInitSolverBody(btCollisionObject& body,btScalar timeStep); + void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep); + + void resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); + + void resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); + +protected: + + + virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal); + virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btSequentialImpulseConstraintSolver(); + virtual ~btSequentialImpulseConstraintSolver(); + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher); + + + + ///clear internal cached data and reset random seed + virtual void reset(); + + unsigned long btRand2(); + + int btRandInt2 (int n); + + void setRandSeed(unsigned long seed) + { + m_btSeed2 = seed; + } + unsigned long getRandSeed() const + { + return m_btSeed2; + } + + + virtual btConstraintSolverType getSolverType() const + { + return BT_SEQUENTIAL_IMPULSE_SOLVER; + } +}; + + + + +#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp new file mode 100644 index 00000000..aff9f27f --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -0,0 +1,864 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 +*/ + + + +#include "btSliderConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + +#define USE_OFFSET_FOR_CONSTANT_FRAME true + +void btSliderConstraint::initParams() +{ + m_lowerLinLimit = btScalar(1.0); + m_upperLinLimit = btScalar(-1.0); + m_lowerAngLimit = btScalar(0.); + m_upperAngLimit = btScalar(0.); + m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirLin = btScalar(0.); + m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirAng = btScalar(0.); + m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM; + m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM; + + m_poweredLinMotor = false; + m_targetLinMotorVelocity = btScalar(0.); + m_maxLinMotorForce = btScalar(0.); + m_accumulatedLinMotorImpulse = btScalar(0.0); + + m_poweredAngMotor = false; + m_targetAngMotorVelocity = btScalar(0.); + m_maxAngMotorForce = btScalar(0.); + m_accumulatedAngMotorImpulse = btScalar(0.0); + + m_flags = 0; + m_flags = 0; + + m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME; + + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); +} + + + + + +btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB), + m_useSolveConstraintObsolete(false), + m_frameInA(frameInA), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + initParams(); +} + + + +btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB), + m_useSolveConstraintObsolete(false), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + ///not providing rigidbody A means implicitly using worldspace for body A + m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; +// m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin()); + + initParams(); +} + + + + + + +void btSliderConstraint::getInfo1(btConstraintInfo1* info) +{ + if (m_useSolveConstraintObsolete) + { + info->m_numConstraintRows = 0; + info->nub = 0; + } + else + { + info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular + info->nub = 2; + //prepare constraint + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + testAngLimits(); + testLinLimits(); + if(getSolveLinLimit() || getPoweredLinMotor()) + { + info->m_numConstraintRows++; // limit 3rd linear as well + info->nub--; + } + if(getSolveAngLimit() || getPoweredAngMotor()) + { + info->m_numConstraintRows++; // limit 3rd angular as well + info->nub--; + } + } +} + +void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info) +{ + + info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used) + info->nub = 0; +} + +void btSliderConstraint::getInfo2(btConstraintInfo2* info) +{ + getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass()); +} + + + + + + + +void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +{ + if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) + { + m_calculatedTransformA = transA * m_frameInA; + m_calculatedTransformB = transB * m_frameInB; + } + else + { + m_calculatedTransformA = transB * m_frameInB; + m_calculatedTransformB = transA * m_frameInA; + } + m_realPivotAInW = m_calculatedTransformA.getOrigin(); + m_realPivotBInW = m_calculatedTransformB.getOrigin(); + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) + { + m_delta = m_realPivotBInW - m_realPivotAInW; + } + else + { + m_delta = m_realPivotAInW - m_realPivotBInW; + } + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + btVector3 normalWorld; + int i; + //linear part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + m_depth[i] = m_delta.dot(normalWorld); + } +} + + + +void btSliderConstraint::testLinLimits(void) +{ + m_solveLinLim = false; + m_linPos = m_depth[0]; + if(m_lowerLinLimit <= m_upperLinLimit) + { + if(m_depth[0] > m_upperLinLimit) + { + m_depth[0] -= m_upperLinLimit; + m_solveLinLim = true; + } + else if(m_depth[0] < m_lowerLinLimit) + { + m_depth[0] -= m_lowerLinLimit; + m_solveLinLim = true; + } + else + { + m_depth[0] = btScalar(0.); + } + } + else + { + m_depth[0] = btScalar(0.); + } +} + + + +void btSliderConstraint::testAngLimits(void) +{ + m_angDepth = btScalar(0.); + m_solveAngLim = false; + if(m_lowerAngLimit <= m_upperAngLimit) + { + const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); + const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); + const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); +// btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); + btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0)); + rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit); + m_angPos = rot; + if(rot < m_lowerAngLimit) + { + m_angDepth = rot - m_lowerAngLimit; + m_solveAngLim = true; + } + else if(rot > m_upperAngLimit) + { + m_angDepth = rot - m_upperAngLimit; + m_solveAngLim = true; + } + } +} + +btVector3 btSliderConstraint::getAncorInA(void) +{ + btVector3 ancorInA; + ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis; + ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA; + return ancorInA; +} + + + +btVector3 btSliderConstraint::getAncorInB(void) +{ + btVector3 ancorInB; + ancorInB = m_frameInB.getOrigin(); + return ancorInB; +} + + +void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass ) +{ + const btTransform& trA = getCalculatedTransformA(); + const btTransform& trB = getCalculatedTransformB(); + + btAssert(!m_useSolveConstraintObsolete); + int i, s = info->rowskip; + + btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); + + // difference between frames in WCS + btVector3 ofs = trB.getOrigin() - trA.getOrigin(); + // now get weight factors depending on masses + btScalar miA = rbAinvMass; + btScalar miB = rbBinvMass; + bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); + btScalar miS = miA + miB; + btScalar factA, factB; + if(miS > btScalar(0.f)) + { + factA = miB / miS; + } + else + { + factA = btScalar(0.5f); + } + factB = btScalar(1.0f) - factA; + btVector3 ax1, p, q; + btVector3 ax1A = trA.getBasis().getColumn(0); + btVector3 ax1B = trB.getBasis().getColumn(0); + if(m_useOffsetForConstraintFrame) + { + // get the desired direction of slider axis + // as weighted sum of X-orthos of frameA and frameB in WCS + ax1 = ax1A * factA + ax1B * factB; + ax1.normalize(); + // construct two orthos to slider axis + btPlaneSpace1 (ax1, p, q); + } + else + { // old way - use frameA + ax1 = trA.getBasis().getColumn(0); + // get 2 orthos to slider axis (Y, Z) + p = trA.getBasis().getColumn(1); + q = trA.getBasis().getColumn(2); + } + // make rotations around these orthos equal + // the slider axis should be the only unconstrained + // rotational axis, the angular velocity of the two bodies perpendicular to + // the slider axis should be equal. thus the constraint equations are + // p*w1 - p*w2 = 0 + // q*w1 - q*w2 = 0 + // where p and q are unit vectors normal to the slider axis, and w1 and w2 + // are the angular velocity vectors of the two bodies. + info->m_J1angularAxis[0] = p[0]; + info->m_J1angularAxis[1] = p[1]; + info->m_J1angularAxis[2] = p[2]; + info->m_J1angularAxis[s+0] = q[0]; + info->m_J1angularAxis[s+1] = q[1]; + info->m_J1angularAxis[s+2] = q[2]; + + info->m_J2angularAxis[0] = -p[0]; + info->m_J2angularAxis[1] = -p[1]; + info->m_J2angularAxis[2] = -p[2]; + info->m_J2angularAxis[s+0] = -q[0]; + info->m_J2angularAxis[s+1] = -q[1]; + info->m_J2angularAxis[s+2] = -q[2]; + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the slider back into alignment. + // if ax1A,ax1B are the unit length slider axes as computed from bodyA and + // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if "theta" is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. +// btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); + btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp; + btScalar k = info->fps * currERP; + + btVector3 u = ax1A.cross(ax1B); + info->m_constraintError[0] = k * u.dot(p); + info->m_constraintError[s] = k * u.dot(q); + if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG) + { + info->cfm[0] = m_cfmOrthoAng; + info->cfm[s] = m_cfmOrthoAng; + } + + int nrow = 1; // last filled row + int srow; + btScalar limit_err; + int limit; + int powered; + + // next two rows. + // we want: velA + wA x relA == velB + wB x relB ... but this would + // result in three equations, so we project along two orthos to the slider axis + + btTransform bodyA_trans = transA; + btTransform bodyB_trans = transB; + nrow++; + int s2 = nrow * s; + nrow++; + int s3 = nrow * s; + btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0); + if(m_useOffsetForConstraintFrame) + { + // get vector from bodyB to frameB in WCS + relB = trB.getOrigin() - bodyB_trans.getOrigin(); + // get its projection to slider axis + btVector3 projB = ax1 * relB.dot(ax1); + // get vector directed from bodyB to slider axis (and orthogonal to it) + btVector3 orthoB = relB - projB; + // same for bodyA + relA = trA.getOrigin() - bodyA_trans.getOrigin(); + btVector3 projA = ax1 * relA.dot(ax1); + btVector3 orthoA = relA - projA; + // get desired offset between frames A and B along slider axis + btScalar sliderOffs = m_linPos - m_depth[0]; + // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis + btVector3 totalDist = projA + ax1 * sliderOffs - projB; + // get offset vectors relA and relB + relA = orthoA + totalDist * factA; + relB = orthoB - totalDist * factB; + // now choose average ortho to slider axis + p = orthoB * factA + orthoA * factB; + btScalar len2 = p.length2(); + if(len2 > SIMD_EPSILON) + { + p /= btSqrt(len2); + } + else + { + p = trA.getBasis().getColumn(1); + } + // make one more ortho + q = ax1.cross(p); + // fill two rows + tmpA = relA.cross(p); + tmpB = relB.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; + tmpA = relA.cross(q); + tmpB = relB.cross(q); + if(hasStaticBody && getSolveAngLimit()) + { // to make constraint between static and dynamic objects more rigid + // remove wA (or wB) from equation if angular limit is hit + tmpB *= factB; + tmpA *= factA; + } + for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; + for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i]; + for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i]; + } + else + { // old way - maybe incorrect if bodies are not on the slider axis + // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0 + c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); + btVector3 tmp = c.cross(p); + for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i]; + tmp = c.cross(q); + for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i]; + for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i]; + + for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; + for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; + for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i]; + for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i]; + } + // compute two elements of right hand side + + // k = info->fps * info->erp * getSoftnessOrthoLin(); + currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp; + k = info->fps * currERP; + + btScalar rhs = k * p.dot(ofs); + info->m_constraintError[s2] = rhs; + rhs = k * q.dot(ofs); + info->m_constraintError[s3] = rhs; + if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN) + { + info->cfm[s2] = m_cfmOrthoLin; + info->cfm[s3] = m_cfmOrthoLin; + } + + + // check linear limits + limit_err = btScalar(0.0); + limit = 0; + if(getSolveLinLimit()) + { + limit_err = getLinDepth() * signFact; + limit = (limit_err > btScalar(0.0)) ? 2 : 1; + } + powered = 0; + if(getPoweredLinMotor()) + { + powered = 1; + } + // if the slider has joint limits or motor, add in the extra row + if (limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1linearAxis[srow+0] = ax1[0]; + info->m_J1linearAxis[srow+1] = ax1[1]; + info->m_J1linearAxis[srow+2] = ax1[2]; + info->m_J2linearAxis[srow+0] = -ax1[0]; + info->m_J2linearAxis[srow+1] = -ax1[1]; + info->m_J2linearAxis[srow+2] = -ax1[2]; + // linear torque decoupling step: + // + // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies + // do not create a torque couple. in other words, the points that the + // constraint force is applied at must lie along the same ax1 axis. + // a torque couple will result in limited slider-jointed free + // bodies from gaining angular momentum. + if(m_useOffsetForConstraintFrame) + { + // this is needed only when bodyA and bodyB are both dynamic. + if(!hasStaticBody) + { + tmpA = relA.cross(ax1); + tmpB = relB.cross(ax1); + info->m_J1angularAxis[srow+0] = tmpA[0]; + info->m_J1angularAxis[srow+1] = tmpA[1]; + info->m_J1angularAxis[srow+2] = tmpA[2]; + info->m_J2angularAxis[srow+0] = -tmpB[0]; + info->m_J2angularAxis[srow+1] = -tmpB[1]; + info->m_J2angularAxis[srow+2] = -tmpB[2]; + } + } + else + { // The old way. May be incorrect if bodies are not on the slider axis + btVector3 ltd; // Linear Torque Decoupling vector (a torque) + ltd = c.cross(ax1); + info->m_J1angularAxis[srow+0] = factA*ltd[0]; + info->m_J1angularAxis[srow+1] = factA*ltd[1]; + info->m_J1angularAxis[srow+2] = factA*ltd[2]; + info->m_J2angularAxis[srow+0] = factB*ltd[0]; + info->m_J2angularAxis[srow+1] = factB*ltd[1]; + info->m_J2angularAxis[srow+2] = factB*ltd[2]; + } + // right-hand part + btScalar lostop = getLowerLinLimit(); + btScalar histop = getUpperLinLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + info->m_constraintError[srow] = 0.; + info->m_lowerLimit[srow] = 0.; + info->m_upperLimit[srow] = 0.; + currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp; + if(powered) + { + if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN) + { + info->cfm[srow] = m_cfmDirLin; + } + btScalar tag_vel = getTargetLinMotorVelocity(); + btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP); + info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity(); + info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps; + info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN) + { + info->cfm[srow] = m_cfmLimLin; + } + if(lostop == histop) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + else + { // high limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) + btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); + if(bounce > btScalar(0.0)) + { + btScalar vel = linVelA.dot(ax1); + vel -= linVelB.dot(ax1); + vel *= signFact; + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if (newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= getSoftnessLimLin(); + } // if(limit) + } // if linear limit + // check angular limits + limit_err = btScalar(0.0); + limit = 0; + if(getSolveAngLimit()) + { + limit_err = getAngDepth(); + limit = (limit_err > btScalar(0.0)) ? 1 : 2; + } + // if the slider has joint limits, add in the extra row + powered = 0; + if(getPoweredAngMotor()) + { + powered = 1; + } + if(limit || powered) + { + nrow++; + srow = nrow * info->rowskip; + info->m_J1angularAxis[srow+0] = ax1[0]; + info->m_J1angularAxis[srow+1] = ax1[1]; + info->m_J1angularAxis[srow+2] = ax1[2]; + + info->m_J2angularAxis[srow+0] = -ax1[0]; + info->m_J2angularAxis[srow+1] = -ax1[1]; + info->m_J2angularAxis[srow+2] = -ax1[2]; + + btScalar lostop = getLowerAngLimit(); + btScalar histop = getUpperAngLimit(); + if(limit && (lostop == histop)) + { // the joint motor is ineffective + powered = 0; + } + currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp; + if(powered) + { + if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG) + { + info->cfm[srow] = m_cfmDirAng; + } + btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP); + info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity(); + info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps; + info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps; + } + if(limit) + { + k = info->fps * currERP; + info->m_constraintError[srow] += k * limit_err; + if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG) + { + info->cfm[srow] = m_cfmLimAng; + } + if(lostop == histop) + { + // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else if(limit == 1) + { // low limit + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { // high limit + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) + btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng()); + if(bounce > btScalar(0.0)) + { + btScalar vel = m_rbA.getAngularVelocity().dot(ax1); + vel -= m_rbB.getAngularVelocity().dot(ax1); + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if(limit == 1) + { // low limit + if(vel < 0) + { + btScalar newc = -bounce * vel; + if(newc > info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + else + { // high limit - all those computations are reversed + if(vel > 0) + { + btScalar newc = -bounce * vel; + if(newc < info->m_constraintError[srow]) + { + info->m_constraintError[srow] = newc; + } + } + } + } + info->m_constraintError[srow] *= getSoftnessLimAng(); + } // if(limit) + } // if angular limit or powered +} + + +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. +void btSliderConstraint::setParam(int num, btScalar value, int axis) +{ + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + if(axis < 1) + { + m_softnessLimLin = value; + m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN; + } + else if(axis < 3) + { + m_softnessOrthoLin = value; + m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN; + } + else if(axis == 3) + { + m_softnessLimAng = value; + m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG; + } + else if(axis < 6) + { + m_softnessOrthoAng = value; + m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM : + if(axis < 1) + { + m_cfmDirLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN; + } + else if(axis == 3) + { + m_cfmDirAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_STOP_CFM : + if(axis < 1) + { + m_cfmLimLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN; + } + else if(axis < 3) + { + m_cfmOrthoLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN; + } + else if(axis == 3) + { + m_cfmLimAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG; + } + else if(axis < 6) + { + m_cfmOrthoAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG; + } + else + { + btAssertConstrParams(0); + } + break; + } +} + +///return the local value of parameter +btScalar btSliderConstraint::getParam(int num, int axis) const +{ + btScalar retVal(SIMD_INFINITY); + switch(num) + { + case BT_CONSTRAINT_STOP_ERP : + if(axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN); + retVal = m_softnessLimLin; + } + else if(axis < 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN); + retVal = m_softnessOrthoLin; + } + else if(axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG); + retVal = m_softnessLimAng; + } + else if(axis < 6) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG); + retVal = m_softnessOrthoAng; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM : + if(axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN); + retVal = m_cfmDirLin; + } + else if(axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG); + retVal = m_cfmDirAng; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_STOP_CFM : + if(axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN); + retVal = m_cfmLimLin; + } + else if(axis < 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN); + retVal = m_cfmOrthoLin; + } + else if(axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG); + retVal = m_cfmLimAng; + } + else if(axis < 6) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG); + retVal = m_cfmOrthoAng; + } + else + { + btAssertConstrParams(0); + } + break; + } + return retVal; +} + + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h new file mode 100644 index 00000000..57ebb47d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -0,0 +1,361 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +TODO: + - add clamping od accumulated impulse to improve stability + - add conversion for ODE constraint solver +*/ + +#ifndef BT_SLIDER_CONSTRAINT_H +#define BT_SLIDER_CONSTRAINT_H + +#ifdef BT_USE_DOUBLE_PRECISION +#define btSliderConstraintData2 btSliderConstraintDoubleData +#define btSliderConstraintDataName "btSliderConstraintDoubleData" +#else +#define btSliderConstraintData2 btSliderConstraintData +#define btSliderConstraintDataName "btSliderConstraintData" +#endif //BT_USE_DOUBLE_PRECISION + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + + + +class btRigidBody; + + + +#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) +#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f)) + + +enum btSliderFlags +{ + BT_SLIDER_FLAGS_CFM_DIRLIN = (1 << 0), + BT_SLIDER_FLAGS_ERP_DIRLIN = (1 << 1), + BT_SLIDER_FLAGS_CFM_DIRANG = (1 << 2), + BT_SLIDER_FLAGS_ERP_DIRANG = (1 << 3), + BT_SLIDER_FLAGS_CFM_ORTLIN = (1 << 4), + BT_SLIDER_FLAGS_ERP_ORTLIN = (1 << 5), + BT_SLIDER_FLAGS_CFM_ORTANG = (1 << 6), + BT_SLIDER_FLAGS_ERP_ORTANG = (1 << 7), + BT_SLIDER_FLAGS_CFM_LIMLIN = (1 << 8), + BT_SLIDER_FLAGS_ERP_LIMLIN = (1 << 9), + BT_SLIDER_FLAGS_CFM_LIMANG = (1 << 10), + BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11) +}; + + +ATTRIBUTE_ALIGNED16(class) btSliderConstraint : public btTypedConstraint +{ +protected: + ///for backwards compatibility during the transition to 'getInfo/getInfo2' + bool m_useSolveConstraintObsolete; + bool m_useOffsetForConstraintFrame; + btTransform m_frameInA; + btTransform m_frameInB; + // use frameA fo define limits, if true + bool m_useLinearReferenceFrameA; + // linear limits + btScalar m_lowerLinLimit; + btScalar m_upperLinLimit; + // angular limits + btScalar m_lowerAngLimit; + btScalar m_upperAngLimit; + // softness, restitution and damping for different cases + // DirLin - moving inside linear limits + // LimLin - hitting linear limit + // DirAng - moving inside angular limits + // LimAng - hitting angular limit + // OrthoLin, OrthoAng - against constraint axis + btScalar m_softnessDirLin; + btScalar m_restitutionDirLin; + btScalar m_dampingDirLin; + btScalar m_cfmDirLin; + + btScalar m_softnessDirAng; + btScalar m_restitutionDirAng; + btScalar m_dampingDirAng; + btScalar m_cfmDirAng; + + btScalar m_softnessLimLin; + btScalar m_restitutionLimLin; + btScalar m_dampingLimLin; + btScalar m_cfmLimLin; + + btScalar m_softnessLimAng; + btScalar m_restitutionLimAng; + btScalar m_dampingLimAng; + btScalar m_cfmLimAng; + + btScalar m_softnessOrthoLin; + btScalar m_restitutionOrthoLin; + btScalar m_dampingOrthoLin; + btScalar m_cfmOrthoLin; + + btScalar m_softnessOrthoAng; + btScalar m_restitutionOrthoAng; + btScalar m_dampingOrthoAng; + btScalar m_cfmOrthoAng; + + // for interlal use + bool m_solveLinLim; + bool m_solveAngLim; + + int m_flags; + + btJacobianEntry m_jacLin[3]; + btScalar m_jacLinDiagABInv[3]; + + btJacobianEntry m_jacAng[3]; + + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + + btVector3 m_sliderAxis; + btVector3 m_realPivotAInW; + btVector3 m_realPivotBInW; + btVector3 m_projPivotInW; + btVector3 m_delta; + btVector3 m_depth; + btVector3 m_relPosA; + btVector3 m_relPosB; + + btScalar m_linPos; + btScalar m_angPos; + + btScalar m_angDepth; + btScalar m_kAngle; + + bool m_poweredLinMotor; + btScalar m_targetLinMotorVelocity; + btScalar m_maxLinMotorForce; + btScalar m_accumulatedLinMotorImpulse; + + bool m_poweredAngMotor; + btScalar m_targetAngMotorVelocity; + btScalar m_maxAngMotorForce; + btScalar m_accumulatedAngMotorImpulse; + + //------------------------ + void initParams(); +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + // constructors + btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA); + + // overrides + + virtual void getInfo1 (btConstraintInfo1* info); + + void getInfo1NonVirtual(btConstraintInfo1* info); + + virtual void getInfo2 (btConstraintInfo2* info); + + void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass); + + + // access + const btRigidBody& getRigidBodyA() const { return m_rbA; } + const btRigidBody& getRigidBodyB() const { return m_rbB; } + const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } + const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } + const btTransform & getFrameOffsetA() const { return m_frameInA; } + const btTransform & getFrameOffsetB() const { return m_frameInB; } + btTransform & getFrameOffsetA() { return m_frameInA; } + btTransform & getFrameOffsetB() { return m_frameInB; } + btScalar getLowerLinLimit() { return m_lowerLinLimit; } + void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } + btScalar getUpperLinLimit() { return m_upperLinLimit; } + void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } + btScalar getLowerAngLimit() { return m_lowerAngLimit; } + void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); } + btScalar getUpperAngLimit() { return m_upperAngLimit; } + void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); } + bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; } + btScalar getSoftnessDirLin() { return m_softnessDirLin; } + btScalar getRestitutionDirLin() { return m_restitutionDirLin; } + btScalar getDampingDirLin() { return m_dampingDirLin ; } + btScalar getSoftnessDirAng() { return m_softnessDirAng; } + btScalar getRestitutionDirAng() { return m_restitutionDirAng; } + btScalar getDampingDirAng() { return m_dampingDirAng; } + btScalar getSoftnessLimLin() { return m_softnessLimLin; } + btScalar getRestitutionLimLin() { return m_restitutionLimLin; } + btScalar getDampingLimLin() { return m_dampingLimLin; } + btScalar getSoftnessLimAng() { return m_softnessLimAng; } + btScalar getRestitutionLimAng() { return m_restitutionLimAng; } + btScalar getDampingLimAng() { return m_dampingLimAng; } + btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; } + btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; } + btScalar getDampingOrthoLin() { return m_dampingOrthoLin; } + btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; } + btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; } + btScalar getDampingOrthoAng() { return m_dampingOrthoAng; } + void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; } + void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } + void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; } + void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; } + void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } + void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; } + void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; } + void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } + void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; } + void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; } + void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } + void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; } + void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } + void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } + void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } + void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } + void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } + void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } + void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } + bool getPoweredLinMotor() { return m_poweredLinMotor; } + void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } + btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } + void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } + btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; } + void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } + bool getPoweredAngMotor() { return m_poweredAngMotor; } + void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } + btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } + void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } + btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } + + btScalar getLinearPos() const { return m_linPos; } + btScalar getAngularPos() const { return m_angPos; } + + + + // access for ODE solver + bool getSolveLinLimit() { return m_solveLinLim; } + btScalar getLinDepth() { return m_depth[0]; } + bool getSolveAngLimit() { return m_solveAngLim; } + btScalar getAngDepth() { return m_angDepth; } + // shared code used by ODE solver + void calculateTransforms(const btTransform& transA,const btTransform& transB); + void testLinLimits(); + void testAngLimits(); + // access for PE Solver + btVector3 getAncorInA(); + btVector3 getAncorInB(); + // access for UseFrameOffset + bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } + void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } + + void setFrames(const btTransform& frameA, const btTransform& frameB) + { + m_frameInA=frameA; + m_frameInB=frameB; + calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + buildJacobian(); + } + + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1); + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + + +}; + + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 + + +struct btSliderConstraintData +{ + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformFloatData m_rbBFrame; + + float m_linearUpperLimit; + float m_linearLowerLimit; + + float m_angularUpperLimit; + float m_angularLowerLimit; + + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; + +}; + + +struct btSliderConstraintDoubleData +{ + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransformDoubleData m_rbBFrame; + + double m_linearUpperLimit; + double m_linearLowerLimit; + + double m_angularUpperLimit; + double m_angularLowerLimit; + + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; + +}; + +SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btSliderConstraintData2); +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + + btSliderConstraintData2* sliderData = (btSliderConstraintData2*) dataBuffer; + btTypedConstraint::serialize(&sliderData->m_typeConstraintData,serializer); + + m_frameInA.serialize(sliderData->m_rbAFrame); + m_frameInB.serialize(sliderData->m_rbBFrame); + + sliderData->m_linearUpperLimit = m_upperLinLimit; + sliderData->m_linearLowerLimit = m_lowerLinLimit; + + sliderData->m_angularUpperLimit = m_upperAngLimit; + sliderData->m_angularLowerLimit = m_lowerAngLimit; + + sliderData->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA; + sliderData->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame; + + return btSliderConstraintDataName; +} + + + +#endif //BT_SLIDER_CONSTRAINT_H + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp new file mode 100644 index 00000000..0c7dbd66 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp @@ -0,0 +1,255 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "btSolve2LinearConstraint.h" + +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" + + +void btSolve2LinearConstraint::resolveUnilateralPairConstraint( + btRigidBody* body1, + btRigidBody* body2, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + (void)linvelA; + (void)linvelB; + (void)angvelB; + (void)angvelA; + + + + imp0 = btScalar(0.); + imp1 = btScalar(0.); + + btScalar len = btFabs(normalA.length()) - btScalar(1.); + if (btFabs(len) >= SIMD_EPSILON) + return; + + btAssert(len < SIMD_EPSILON); + + + //this jacobian entry could be re-used for all iterations + btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + +// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv + btScalar massTerm = btScalar(1.) / (invMassA + invMassB); + + + // calculate rhs (or error) terms + const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping; + + + // dC/dv * dv = -C + + // jacobian * impulse = -error + // + + //impulse = jacobianInverse * -error + + // inverting 2x2 symmetric system (offdiagonal are equal!) + // + + + btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); + + //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + //[a b] [d -c] + //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) + + //[jA nD] * [imp0] = [dv0] + //[nD jB] [imp1] [dv1] + +} + + + +void btSolve2LinearConstraint::resolveBilateralPairConstraint( + btRigidBody* body1, + btRigidBody* body2, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + + (void)linvelA; + (void)linvelB; + (void)angvelA; + (void)angvelB; + + + + imp0 = btScalar(0.); + imp1 = btScalar(0.); + + btScalar len = btFabs(normalA.length()) - btScalar(1.); + if (btFabs(len) >= SIMD_EPSILON) + return; + + btAssert(len < SIMD_EPSILON); + + + //this jacobian entry could be re-used for all iterations + btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + + // calculate rhs (or error) terms + const btScalar dv0 = depthA * m_tau - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau - vel1 * m_damping; + + // dC/dv * dv = -C + + // jacobian * impulse = -error + // + + //impulse = jacobianInverse * -error + + // inverting 2x2 symmetric system (offdiagonal are equal!) + // + + + btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); + + //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + //[a b] [d -c] + //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) + + //[jA nD] * [imp0] = [dv0] + //[nD jB] [imp1] [dv1] + + if ( imp0 > btScalar(0.0)) + { + if ( imp1 > btScalar(0.0) ) + { + //both positive + } + else + { + imp1 = btScalar(0.); + + // now imp0>0 imp1<0 + imp0 = dv0 / jacA.getDiagonal(); + if ( imp0 > btScalar(0.0) ) + { + } else + { + imp0 = btScalar(0.); + } + } + } + else + { + imp0 = btScalar(0.); + + imp1 = dv1 / jacB.getDiagonal(); + if ( imp1 <= btScalar(0.0) ) + { + imp1 = btScalar(0.); + // now imp0>0 imp1<0 + imp0 = dv0 / jacA.getDiagonal(); + if ( imp0 > btScalar(0.0) ) + { + } else + { + imp0 = btScalar(0.); + } + } else + { + } + } +} + + +/* +void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btMatrix3x3& invInertiaBWS, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + +} +*/ + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h new file mode 100644 index 00000000..e8bfabf8 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOLVE_2LINEAR_CONSTRAINT_H +#define BT_SOLVE_2LINEAR_CONSTRAINT_H + +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" + + +class btRigidBody; + + + +/// constraint class used for lateral tyre friction. +class btSolve2LinearConstraint +{ + btScalar m_tau; + btScalar m_damping; + +public: + + btSolve2LinearConstraint(btScalar tau,btScalar damping) + { + m_tau = tau; + m_damping = damping; + } + // + // solve unilateral constraint (equality, direct method) + // + void resolveUnilateralPairConstraint( + btRigidBody* body0, + btRigidBody* body1, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + + + // + // solving 2x2 lcp problem (inequality, direct solution ) + // + void resolveBilateralPairConstraint( + btRigidBody* body0, + btRigidBody* body1, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + +/* + void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btMatrix3x3& invInertiaBWS, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + +*/ + +}; + +#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverBody.h new file mode 100644 index 00000000..27ccefe4 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -0,0 +1,306 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOLVER_BODY_H +#define BT_SOLVER_BODY_H + +class btRigidBody; +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btTransformUtil.h" + +///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision +#ifdef BT_USE_SSE +#define USE_SIMD 1 +#endif // + + +#ifdef USE_SIMD + +struct btSimdScalar +{ + SIMD_FORCE_INLINE btSimdScalar() + { + + } + + SIMD_FORCE_INLINE btSimdScalar(float fl) + :m_vec128 (_mm_set1_ps(fl)) + { + } + + SIMD_FORCE_INLINE btSimdScalar(__m128 v128) + :m_vec128(v128) + { + } + union + { + __m128 m_vec128; + float m_floats[4]; + int m_ints[4]; + btScalar m_unusedPadding; + }; + SIMD_FORCE_INLINE __m128 get128() + { + return m_vec128; + } + + SIMD_FORCE_INLINE const __m128 get128() const + { + return m_vec128; + } + + SIMD_FORCE_INLINE void set128(__m128 v128) + { + m_vec128 = v128; + } + + SIMD_FORCE_INLINE operator __m128() + { + return m_vec128; + } + SIMD_FORCE_INLINE operator const __m128() const + { + return m_vec128; + } + + SIMD_FORCE_INLINE operator float() const + { + return m_floats[0]; + } + +}; + +///@brief Return the elementwise product of two btSimdScalar +SIMD_FORCE_INLINE btSimdScalar +operator*(const btSimdScalar& v1, const btSimdScalar& v2) +{ + return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128())); +} + +///@brief Return the elementwise product of two btSimdScalar +SIMD_FORCE_INLINE btSimdScalar +operator+(const btSimdScalar& v1, const btSimdScalar& v2) +{ + return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128())); +} + + +#else +#define btSimdScalar btScalar +#endif + +///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. +ATTRIBUTE_ALIGNED16 (struct) btSolverBody +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + btTransform m_worldTransform; + btVector3 m_deltaLinearVelocity; + btVector3 m_deltaAngularVelocity; + btVector3 m_angularFactor; + btVector3 m_linearFactor; + btVector3 m_invMass; + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + btVector3 m_linearVelocity; + btVector3 m_angularVelocity; + btVector3 m_externalForceImpulse; + btVector3 m_externalTorqueImpulse; + + btRigidBody* m_originalBody; + void setWorldTransform(const btTransform& worldTransform) + { + m_worldTransform = worldTransform; + } + + const btTransform& getWorldTransform() const + { + return m_worldTransform; + } + + + + SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity ) const + { + if (m_originalBody) + velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity+m_externalTorqueImpulse).cross(rel_pos); + else + velocity.setValue(0,0,0); + } + + + SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const + { + if (m_originalBody) + velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos); + else + velocity.setValue(0,0,0); + } + + SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const + { + if (m_originalBody) + angVel =m_angularVelocity+m_deltaAngularVelocity; + else + angVel.setValue(0,0,0); + } + + + //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position + SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) + { + if (m_originalBody) + { + m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor; + m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + if (m_originalBody) + { + m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor; + m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + + + const btVector3& getDeltaLinearVelocity() const + { + return m_deltaLinearVelocity; + } + + const btVector3& getDeltaAngularVelocity() const + { + return m_deltaAngularVelocity; + } + + const btVector3& getPushVelocity() const + { + return m_pushVelocity; + } + + const btVector3& getTurnVelocity() const + { + return m_turnVelocity; + } + + + //////////////////////////////////////////////// + ///some internal methods, don't use them + + btVector3& internalGetDeltaLinearVelocity() + { + return m_deltaLinearVelocity; + } + + btVector3& internalGetDeltaAngularVelocity() + { + return m_deltaAngularVelocity; + } + + const btVector3& internalGetAngularFactor() const + { + return m_angularFactor; + } + + const btVector3& internalGetInvMass() const + { + return m_invMass; + } + + void internalSetInvMass(const btVector3& invMass) + { + m_invMass = invMass; + } + + btVector3& internalGetPushVelocity() + { + return m_pushVelocity; + } + + btVector3& internalGetTurnVelocity() + { + return m_turnVelocity; + } + + SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const + { + velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos); + } + + SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const + { + angVel = m_angularVelocity+m_deltaAngularVelocity; + } + + + //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) + { + if (m_originalBody) + { + m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor; + m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + + + + void writebackVelocity() + { + if (m_originalBody) + { + m_linearVelocity +=m_deltaLinearVelocity; + m_angularVelocity += m_deltaAngularVelocity; + + //m_originalBody->setCompanionId(-1); + } + } + + + void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp) + { + (void) timeStep; + if (m_originalBody) + { + m_linearVelocity += m_deltaLinearVelocity; + m_angularVelocity += m_deltaAngularVelocity; + + //correct the position/orientation based on push/turn recovery + btTransform newTransform; + if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0) + { + // btQuaternion orn = m_worldTransform.getRotation(); + btTransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform); + m_worldTransform = newTransform; + } + //m_worldTransform.setRotation(orn); + //m_originalBody->setCompanionId(-1); + } + } + + + +}; + +#endif //BT_SOLVER_BODY_H + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h new file mode 100644 index 00000000..5515e6b3 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -0,0 +1,80 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOLVER_CONSTRAINT_H +#define BT_SOLVER_CONSTRAINT_H + +class btRigidBody; +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "btJacobianEntry.h" +#include "LinearMath/btAlignedObjectArray.h" + +//#define NO_FRICTION_TANGENTIALS 1 +#include "btSolverBody.h" + + +///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. +ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btVector3 m_relpos1CrossNormal; + btVector3 m_contactNormal1; + + btVector3 m_relpos2CrossNormal; + btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always + + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + mutable btSimdScalar m_appliedPushImpulse; + mutable btSimdScalar m_appliedImpulse; + + btScalar m_friction; + btScalar m_jacDiagABInv; + btScalar m_rhs; + btScalar m_cfm; + + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_rhsPenetration; + union + { + void* m_originalContactPoint; + btScalar m_unusedPadding4; + int m_numRowsForNonContactConstraint; + }; + + int m_overrideNumSolverIterations; + int m_frictionIndex; + int m_solverBodyIdA; + int m_solverBodyIdB; + + + enum btSolverConstraintType + { + BT_SOLVER_CONTACT_1D = 0, + BT_SOLVER_FRICTION_1D + }; +}; + +typedef btAlignedObjectArray btConstraintArray; + + +#endif //BT_SOLVER_CONSTRAINT_H + + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp new file mode 100644 index 00000000..27fdd9d3 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -0,0 +1,222 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btTypedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btSerializer.h" + + +#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f) + +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) +:btTypedObject(type), +m_userConstraintType(-1), +m_userConstraintId(-1), +m_breakingImpulseThreshold(SIMD_INFINITY), +m_isEnabled(true), +m_needsFeedback(false), +m_overrideNumSolverIterations(-1), +m_rbA(rbA), +m_rbB(getFixedBody()), +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE), +m_jointFeedback(0) +{ +} + + +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) +:btTypedObject(type), +m_userConstraintType(-1), +m_userConstraintId(-1), +m_breakingImpulseThreshold(SIMD_INFINITY), +m_isEnabled(true), +m_needsFeedback(false), +m_overrideNumSolverIterations(-1), +m_rbA(rbA), +m_rbB(rbB), +m_appliedImpulse(btScalar(0.)), +m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE), +m_jointFeedback(0) +{ +} + + + + +btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact) +{ + if(lowLim > uppLim) + { + return btScalar(1.0f); + } + else if(lowLim == uppLim) + { + return btScalar(0.0f); + } + btScalar lim_fact = btScalar(1.0f); + btScalar delta_max = vel / timeFact; + if(delta_max < btScalar(0.0f)) + { + if((pos >= lowLim) && (pos < (lowLim - delta_max))) + { + lim_fact = (lowLim - pos) / delta_max; + } + else if(pos < lowLim) + { + lim_fact = btScalar(0.0f); + } + else + { + lim_fact = btScalar(1.0f); + } + } + else if(delta_max > btScalar(0.0f)) + { + if((pos <= uppLim) && (pos > (uppLim - delta_max))) + { + lim_fact = (uppLim - pos) / delta_max; + } + else if(pos > uppLim) + { + lim_fact = btScalar(0.0f); + } + else + { + lim_fact = btScalar(1.0f); + } + } + else + { + lim_fact = btScalar(0.0f); + } + return lim_fact; +} + +///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +{ + btTypedConstraintData2* tcd = (btTypedConstraintData2*) dataBuffer; + + tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA); + tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB); + char* name = (char*) serializer->findNameForPointer(this); + tcd->m_name = (char*)serializer->getUniquePointer(name); + if (tcd->m_name) + { + serializer->serializeName(name); + } + + tcd->m_objectType = m_objectType; + tcd->m_needsFeedback = m_needsFeedback; + tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations; + tcd->m_breakingImpulseThreshold = m_breakingImpulseThreshold; + tcd->m_isEnabled = m_isEnabled? 1: 0; + + tcd->m_userConstraintId =m_userConstraintId; + tcd->m_userConstraintType =m_userConstraintType; + + tcd->m_appliedImpulse = m_appliedImpulse; + tcd->m_dbgDrawSize = m_dbgDrawSize; + + tcd->m_disableCollisionsBetweenLinkedBodies = false; + + int i; + for (i=0;im_disableCollisionsBetweenLinkedBodies = true; + for (i=0;im_disableCollisionsBetweenLinkedBodies = true; + + return btTypedConstraintDataName; +} + +btRigidBody& btTypedConstraint::getFixedBody() +{ + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; +} + + +void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor) +{ + m_halfRange = (high - low) / 2.0f; + m_center = btNormalizeAngle(low + m_halfRange); + m_softness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; +} + +void btAngularLimit::test(const btScalar angle) +{ + m_correction = 0.0f; + m_sign = 0.0f; + m_solveLimit = false; + + if (m_halfRange >= 0.0f) + { + btScalar deviation = btNormalizeAngle(angle - m_center); + if (deviation < -m_halfRange) + { + m_solveLimit = true; + m_correction = - (deviation + m_halfRange); + m_sign = +1.0f; + } + else if (deviation > m_halfRange) + { + m_solveLimit = true; + m_correction = m_halfRange - deviation; + m_sign = -1.0f; + } + } +} + + +btScalar btAngularLimit::getError() const +{ + return m_correction * m_sign; +} + +void btAngularLimit::fit(btScalar& angle) const +{ + if (m_halfRange > 0.0f) + { + btScalar relativeAngle = btNormalizeAngle(angle - m_center); + if (!btEqual(relativeAngle, m_halfRange)) + { + if (relativeAngle > 0.0f) + { + angle = getHigh(); + } + else + { + angle = getLow(); + } + } + } +} + +btScalar btAngularLimit::getLow() const +{ + return btNormalizeAngle(m_center - m_halfRange); +} + +btScalar btAngularLimit::getHigh() const +{ + return btNormalizeAngle(m_center + m_halfRange); +} diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h new file mode 100644 index 00000000..b58f984d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -0,0 +1,544 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_TYPED_CONSTRAINT_H +#define BT_TYPED_CONSTRAINT_H + + +#include "LinearMath/btScalar.h" +#include "btSolverConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btTypedConstraintData2 btTypedConstraintDoubleData +#define btTypedConstraintDataName "btTypedConstraintDoubleData" +#else +#define btTypedConstraintData2 btTypedConstraintFloatData +#define btTypedConstraintDataName "btTypedConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION + + +class btSerializer; + +//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility +enum btTypedConstraintType +{ + POINT2POINT_CONSTRAINT_TYPE=3, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + SLIDER_CONSTRAINT_TYPE, + CONTACT_CONSTRAINT_TYPE, + D6_SPRING_CONSTRAINT_TYPE, + GEAR_CONSTRAINT_TYPE, + FIXED_CONSTRAINT_TYPE, + MAX_CONSTRAINT_TYPE +}; + + +enum btConstraintParams +{ + BT_CONSTRAINT_ERP=1, + BT_CONSTRAINT_STOP_ERP, + BT_CONSTRAINT_CFM, + BT_CONSTRAINT_STOP_CFM +}; + +#if 1 + #define btAssertConstrParams(_par) btAssert(_par) +#else + #define btAssertConstrParams(_par) +#endif + + +ATTRIBUTE_ALIGNED16(struct) btJointFeedback +{ + btVector3 m_appliedForceBodyA; + btVector3 m_appliedTorqueBodyA; + btVector3 m_appliedForceBodyB; + btVector3 m_appliedTorqueBodyB; +}; + + +///TypedConstraint is the baseclass for Bullet constraints and vehicles +ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject +{ + int m_userConstraintType; + + union + { + int m_userConstraintId; + void* m_userConstraintPtr; + }; + + btScalar m_breakingImpulseThreshold; + bool m_isEnabled; + bool m_needsFeedback; + int m_overrideNumSolverIterations; + + + btTypedConstraint& operator=(btTypedConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + +protected: + btRigidBody& m_rbA; + btRigidBody& m_rbB; + btScalar m_appliedImpulse; + btScalar m_dbgDrawSize; + btJointFeedback* m_jointFeedback; + + ///internal method used by the constraint solver, don't use them directly + btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); + + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + virtual ~btTypedConstraint() {}; + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); + + struct btConstraintInfo1 { + int m_numConstraintRows,nub; + }; + + static btRigidBody& getFixedBody(); + + struct btConstraintInfo2 { + // integrator parameters: frames per second (1/stepsize), default error + // reduction parameter (0..1). + btScalar fps,erp; + + // for the first and second body, pointers to two (linear and angular) + // n*3 jacobian sub matrices, stored by rows. these matrices will have + // been initialized to 0 on entry. if the second body is zero then the + // J2xx pointers may be 0. + btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis; + + // elements to jump from one row to the next in J's + int rowskip; + + // right hand sides of the equation J*v = c + cfm * lambda. cfm is the + // "constraint force mixing" vector. c is set to zero on entry, cfm is + // set to a constant value (typically very small or zero) value on entry. + btScalar *m_constraintError,*cfm; + + // lo and hi limits for variables (set to -/+ infinity on entry). + btScalar *m_lowerLimit,*m_upperLimit; + + // findex vector for variables. see the LCP solver interface for a + // description of what this does. this is set to -1 on entry. + // note that the returned indexes are relative to the first index of + // the constraint. + int *findex; + // number of solver iterations + int m_numIterations; + + //damping of the velocity + btScalar m_damping; + }; + + int getOverrideNumSolverIterations() const + { + return m_overrideNumSolverIterations; + } + + ///override the number of constraint solver iterations used to solve this constraint + ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations + void setOverrideNumSolverIterations(int overideNumIterations) + { + m_overrideNumSolverIterations = overideNumIterations; + } + + ///internal method used by the constraint solver, don't use them directly + virtual void buildJacobian() {}; + + ///internal method used by the constraint solver, don't use them directly + virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep) + { + (void)ca; + (void)solverBodyA; + (void)solverBodyB; + (void)timeStep; + } + + ///internal method used by the constraint solver, don't use them directly + virtual void getInfo1 (btConstraintInfo1* info)=0; + + ///internal method used by the constraint solver, don't use them directly + virtual void getInfo2 (btConstraintInfo2* info)=0; + + ///internal method used by the constraint solver, don't use them directly + void internalSetAppliedImpulse(btScalar appliedImpulse) + { + m_appliedImpulse = appliedImpulse; + } + ///internal method used by the constraint solver, don't use them directly + btScalar internalGetAppliedImpulse() + { + return m_appliedImpulse; + } + + + btScalar getBreakingImpulseThreshold() const + { + return m_breakingImpulseThreshold; + } + + void setBreakingImpulseThreshold(btScalar threshold) + { + m_breakingImpulseThreshold = threshold; + } + + bool isEnabled() const + { + return m_isEnabled; + } + + void setEnabled(bool enabled) + { + m_isEnabled=enabled; + } + + + ///internal method used by the constraint solver, don't use them directly + virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar /*timeStep*/) {}; + + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + btRigidBody& getRigidBodyA() + { + return m_rbA; + } + btRigidBody& getRigidBodyB() + { + return m_rbB; + } + + int getUserConstraintType() const + { + return m_userConstraintType ; + } + + void setUserConstraintType(int userConstraintType) + { + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; + } + + int getUserConstraintId() const + { + return m_userConstraintId; + } + + void setUserConstraintPtr(void* ptr) + { + m_userConstraintPtr = ptr; + } + + void* getUserConstraintPtr() + { + return m_userConstraintPtr; + } + + void setJointFeedback(btJointFeedback* jointFeedback) + { + m_jointFeedback = jointFeedback; + } + + const btJointFeedback* getJointFeedback() const + { + return m_jointFeedback; + } + + btJointFeedback* getJointFeedback() + { + return m_jointFeedback; + } + + + int getUid() const + { + return m_userConstraintId; + } + + bool needsFeedback() const + { + return m_needsFeedback; + } + + ///enableFeedback will allow to read the applied linear and angular impulse + ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information + void enableFeedback(bool needsFeedback) + { + m_needsFeedback = needsFeedback; + } + + ///getAppliedImpulse is an estimated total applied impulse. + ///This feedback could be used to determine breaking constraints or playing sounds. + btScalar getAppliedImpulse() const + { + btAssert(m_needsFeedback); + return m_appliedImpulse; + } + + btTypedConstraintType getConstraintType () const + { + return btTypedConstraintType(m_objectType); + } + + void setDbgDrawSize(btScalar dbgDrawSize) + { + m_dbgDrawSize = dbgDrawSize; + } + btScalar getDbgDrawSize() + { + return m_dbgDrawSize; + } + + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///If no axis is provided, it uses the default axis for this constraint. + virtual void setParam(int num, btScalar value, int axis = -1) = 0; + + ///return the local value of parameter + virtual btScalar getParam(int num, int axis = -1) const = 0; + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + +}; + +// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits +// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI]) +SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians) +{ + if(angleLowerLimitInRadians >= angleUpperLimitInRadians) + { + return angleInRadians; + } + else if(angleInRadians < angleLowerLimitInRadians) + { + btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians)); + btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians)); + return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI); + } + else if(angleInRadians > angleUpperLimitInRadians) + { + btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians)); + btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians)); + return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians; + } + else + { + return angleInRadians; + } +} + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btTypedConstraintFloatData +{ + btRigidBodyFloatData *m_rbA; + btRigidBodyFloatData *m_rbB; + char *m_name; + + int m_objectType; + int m_userConstraintType; + int m_userConstraintId; + int m_needsFeedback; + + float m_appliedImpulse; + float m_dbgDrawSize; + + int m_disableCollisionsBetweenLinkedBodies; + int m_overrideNumSolverIterations; + + float m_breakingImpulseThreshold; + int m_isEnabled; + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 + +#define BT_BACKWARDS_COMPATIBLE_SERIALIZATION +#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION +///this structure is not used, except for loading pre-2.82 .bullet files +struct btTypedConstraintData +{ + btRigidBodyData *m_rbA; + btRigidBodyData *m_rbB; + char *m_name; + + int m_objectType; + int m_userConstraintType; + int m_userConstraintId; + int m_needsFeedback; + + float m_appliedImpulse; + float m_dbgDrawSize; + + int m_disableCollisionsBetweenLinkedBodies; + int m_overrideNumSolverIterations; + + float m_breakingImpulseThreshold; + int m_isEnabled; + +}; +#endif //BACKWARDS_COMPATIBLE + +struct btTypedConstraintDoubleData +{ + btRigidBodyDoubleData *m_rbA; + btRigidBodyDoubleData *m_rbB; + char *m_name; + + int m_objectType; + int m_userConstraintType; + int m_userConstraintId; + int m_needsFeedback; + + double m_appliedImpulse; + double m_dbgDrawSize; + + int m_disableCollisionsBetweenLinkedBodies; + int m_overrideNumSolverIterations; + + double m_breakingImpulseThreshold; + int m_isEnabled; + char padding[4]; + +}; + + +SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const +{ + return sizeof(btTypedConstraintData2); +} + + + +class btAngularLimit +{ +private: + btScalar + m_center, + m_halfRange, + m_softness, + m_biasFactor, + m_relaxationFactor, + m_correction, + m_sign; + + bool + m_solveLimit; + +public: + /// Default constructor initializes limit as inactive, allowing free constraint movement + btAngularLimit() + :m_center(0.0f), + m_halfRange(-1.0f), + m_softness(0.9f), + m_biasFactor(0.3f), + m_relaxationFactor(1.0f), + m_correction(0.0f), + m_sign(0.0f), + m_solveLimit(false) + {} + + /// Sets all limit's parameters. + /// When low > high limit becomes inactive. + /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit + void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f); + + /// Checks conastaint angle against limit. If limit is active and the angle violates the limit + /// correction is calculated. + void test(const btScalar angle); + + /// Returns limit's softness + inline btScalar getSoftness() const + { + return m_softness; + } + + /// Returns limit's bias factor + inline btScalar getBiasFactor() const + { + return m_biasFactor; + } + + /// Returns limit's relaxation factor + inline btScalar getRelaxationFactor() const + { + return m_relaxationFactor; + } + + /// Returns correction value evaluated when test() was invoked + inline btScalar getCorrection() const + { + return m_correction; + } + + /// Returns sign value evaluated when test() was invoked + inline btScalar getSign() const + { + return m_sign; + } + + /// Gives half of the distance between min and max limit angle + inline btScalar getHalfRange() const + { + return m_halfRange; + } + + /// Returns true when the last test() invocation recognized limit violation + inline bool isLimit() const + { + return m_solveLimit; + } + + /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle + /// returned is modified so it equals to the limit closest to given angle. + void fit(btScalar& angle) const; + + /// Returns correction value multiplied by sign value + btScalar getError() const; + + btScalar getLow() const; + + btScalar getHigh() const; + +}; + + + +#endif //BT_TYPED_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp new file mode 100644 index 00000000..b009f41a --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp @@ -0,0 +1,87 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +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 "btUniversalConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" + + + +#define UNIV_EPS btScalar(0.01f) + + +// constructor +// anchor, axis1 and axis2 are in world coordinate system +// axis1 must be orthogonal to axis2 +btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2) +: btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), + m_anchor(anchor), + m_axis1(axis1), + m_axis2(axis2) +{ + // build frame basis + // 6DOF constraint uses Euler angles and to define limits + // it is assumed that rotational order is : + // Z - first, allowed limits are (-PI,PI); + // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number + // used to prevent constraint from instability on poles; + // new position of X, allowed limits are (-PI,PI); + // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs + // Build the frame in world coordinate system first + btVector3 zAxis = m_axis1.normalize(); + btVector3 yAxis = m_axis2.normalize(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + frameInW.setOrigin(anchor); + // now get constraint frame in local coordinate systems + m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW; + // sei limits + setLinearLowerLimit(btVector3(0., 0., 0.)); + setLinearUpperLimit(btVector3(0., 0., 0.)); + setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS)); + setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS)); +} + +void btUniversalConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +{ + m_axis1 = axis1; + m_axis2 = axis2; + + btVector3 zAxis = axis1.normalized(); + btVector3 yAxis = axis2.normalized(); + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + + btTransform frameInW; + frameInW.setIdentity(); + frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + frameInW.setOrigin(m_anchor); + + // now get constraint frame in local coordinate systems + m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; + m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; + + calculateTransforms(); +} + + diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h new file mode 100644 index 00000000..9e708410 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h @@ -0,0 +1,65 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_UNIVERSAL_CONSTRAINT_H +#define BT_UNIVERSAL_CONSTRAINT_H + + + +#include "LinearMath/btVector3.h" +#include "btTypedConstraint.h" +#include "btGeneric6DofConstraint.h" + + + +/// Constraint similar to ODE Universal Joint +/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1) +/// and Y (axis 2) +/// Description from ODE manual : +/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular. +/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal." + +ATTRIBUTE_ALIGNED16(class) btUniversalConstraint : public btGeneric6DofConstraint +{ +protected: + btVector3 m_anchor; + btVector3 m_axis1; + btVector3 m_axis2; +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + // constructor + // anchor, axis1 and axis2 are in world coordinate system + // axis1 must be orthogonal to axis2 + btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2); + // access + const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } + const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } + const btVector3& getAxis1() { return m_axis1; } + const btVector3& getAxis2() { return m_axis2; } + btScalar getAngle1() { return getAngle(2); } + btScalar getAngle2() { return getAngle(1); } + // limits + void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); } + void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); } + + void setAxis( const btVector3& axis1, const btVector3& axis2); +}; + + + +#endif // BT_UNIVERSAL_CONSTRAINT_H + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/Code/Physics/src/BulletDynamics/Dynamics/Bullet-C-API.cpp new file mode 100644 index 00000000..bd8e2748 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -0,0 +1,405 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* + Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's. + Work in progress, functionality will be added on demand. + + If possible, use the richer Bullet C++ API, by including +*/ + +#include "Bullet-C-Api.h" +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btAlignedAllocator.h" + + + +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + + +/* + Create and Delete a Physics SDK +*/ + +struct btPhysicsSdk +{ + +// btDispatcher* m_dispatcher; +// btOverlappingPairCache* m_pairCache; +// btConstraintSolver* m_constraintSolver + + btVector3 m_worldAabbMin; + btVector3 m_worldAabbMax; + + + //todo: version, hardware/optimization settings etc? + btPhysicsSdk() + :m_worldAabbMin(-1000,-1000,-1000), + m_worldAabbMax(1000,1000,1000) + { + + } + + +}; + +plPhysicsSdkHandle plNewBulletSdk() +{ + void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); + return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; +} + +void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) +{ + btPhysicsSdk* phys = reinterpret_cast(physicsSdk); + btAlignedFree(phys); +} + + +/* Dynamics World */ +plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle) +{ + btPhysicsSdk* physicsSdk = reinterpret_cast(physicsSdkHandle); + void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16); + btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration(); + mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16); + btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration); + mem = btAlignedAlloc(sizeof(btAxisSweep3),16); + btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); + mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver(); + + mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16); + return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration); +} +void plDeleteDynamicsWorld(plDynamicsWorldHandle world) +{ + //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAlignedFree(dynamicsWorld); +} + +void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + dynamicsWorld->stepSimulation(timeStep); +} + +void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + + dynamicsWorld->addRigidBody(body); +} + +void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + + dynamicsWorld->removeRigidBody(body); +} + +/* Rigid Body */ + +plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) +{ + btTransform trans; + trans.setIdentity(); + btVector3 localInertia(0,0,0); + btCollisionShape* shape = reinterpret_cast( cshape); + btAssert(shape); + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + void* mem = btAlignedAlloc(sizeof(btRigidBody),16); + btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia); + btRigidBody* body = new (mem)btRigidBody(rbci); + body->setWorldTransform(trans); + body->setUserPointer(user_data); + return (plRigidBodyHandle) body; +} + +void plDeleteRigidBody(plRigidBodyHandle cbody) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); + btAssert(body); + btAlignedFree( body); +} + + +/* Collision Shape definition */ + +plCollisionShapeHandle plNewSphereShape(plReal radius) +{ + void* mem = btAlignedAlloc(sizeof(btSphereShape),16); + return (plCollisionShapeHandle) new (mem)btSphereShape(radius); + +} + +plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) +{ + void* mem = btAlignedAlloc(sizeof(btBoxShape),16); + return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); +} + +plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) +{ + //capsule is convex hull of 2 spheres, so use btMultiSphereShape + + const int numSpheres = 2; + btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; + btScalar radi[numSpheres] = {radius,radius}; + void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16); + return (plCollisionShapeHandle) new (mem)btMultiSphereShape(positions,radi,numSpheres); +} +plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btConeShape),16); + return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); +} + +plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); + return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); +} + +/* Convex Meshes */ +plCollisionShapeHandle plNewConvexHullShape() +{ + void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); + return (plCollisionShapeHandle) new (mem)btConvexHullShape(); +} + + +/* Concave static triangle meshes */ +plMeshInterfaceHandle plNewMeshInterface() +{ + return 0; +} + +plCollisionShapeHandle plNewCompoundShape() +{ + void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); + return (plCollisionShapeHandle) new (mem)btCompoundShape(); +} + +void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn) +{ + btCollisionShape* colShape = reinterpret_cast(compoundShapeHandle); + btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE); + btCompoundShape* compoundShape = reinterpret_cast(colShape); + btCollisionShape* childShape = reinterpret_cast(childShapeHandle); + btTransform localTrans; + localTrans.setIdentity(); + localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2])); + localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3])); + compoundShape->addChildShape(localTrans,childShape); +} + +void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient) +{ + btQuaternion orn; + orn.setEuler(yaw,pitch,roll); + orient[0] = orn.getX(); + orient[1] = orn.getY(); + orient[2] = orn.getZ(); + orient[3] = orn.getW(); + +} + + +// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); +// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + +void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) +{ + btCollisionShape* colShape = reinterpret_cast( cshape); + (void)colShape; + btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); + btConvexHullShape* convexHullShape = reinterpret_cast( cshape); + convexHullShape->addPoint(btVector3(x,y,z)); + +} + +void plDeleteShape(plCollisionShapeHandle cshape) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + btAssert(shape); + btAlignedFree(shape); +} +void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + btAssert(shape); + btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); + shape->setLocalScaling(scaling); +} + + + +void plSetPosition(plRigidBodyHandle object, const plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btVector3 pos(position[0],position[1],position[2]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setOrigin(pos); + body->setWorldTransform(worldTrans); +} + +void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setRotation(orn); + body->setWorldTransform(worldTrans); +} + +void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btTransform& worldTrans = body->getWorldTransform(); + worldTrans.setFromOpenGLMatrix(matrix); +} + +void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + body->getWorldTransform().getOpenGLMatrix(matrix); + +} + +void plGetPosition(plRigidBodyHandle object,plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btVector3& pos = body->getWorldTransform().getOrigin(); + position[0] = pos.getX(); + position[1] = pos.getY(); + position[2] = pos.getZ(); +} + +void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btQuaternion& orn = body->getWorldTransform().getRotation(); + orientation[0] = orn.getX(); + orientation[1] = orn.getY(); + orientation[2] = orn.getZ(); + orientation[3] = orn.getW(); +} + + + +//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]) +{ + btVector3 vp(p1[0], p1[1], p1[2]); + btTriangleShape trishapeA(vp, + btVector3(p2[0], p2[1], p2[2]), + btVector3(p3[0], p3[1], p3[2])); + trishapeA.setMargin(0.000001f); + btVector3 vq(q1[0], q1[1], q1[2]); + btTriangleShape trishapeB(vq, + btVector3(q2[0], q2[1], q2[2]), + btVector3(q3[0], q3[1], q3[2])); + trishapeB.setMargin(0.000001f); + + // btVoronoiSimplexSolver sGjkSimplexSolver; + // btGjkEpaPenetrationDepthSolver penSolverPtr; + + static btSimplexSolverInterface sGjkSimplexSolver; + sGjkSimplexSolver.reset(); + + static btGjkEpaPenetrationDepthSolver Solver0; + static btMinkowskiPenetrationDepthSolver Solver1; + + btConvexPenetrationDepthSolver* Solver = NULL; + + Solver = &Solver1; + + btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver); + + convexConvex.m_catchDegeneracies = 1; + + // btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,0); + + btPointCollector gjkOutput; + btGjkPairDetector::ClosestPointInput input; + + + btTransform tr; + tr.setIdentity(); + + input.m_transformA = tr; + input.m_transformB = tr; + + convexConvex.getClosestPoints(input, gjkOutput, 0); + + + if (gjkOutput.m_hasResult) + { + + pb[0] = pa[0] = gjkOutput.m_pointInWorld[0]; + pb[1] = pa[1] = gjkOutput.m_pointInWorld[1]; + pb[2] = pa[2] = gjkOutput.m_pointInWorld[2]; + + pb[0]+= gjkOutput.m_normalOnBInWorld[0] * gjkOutput.m_distance; + pb[1]+= gjkOutput.m_normalOnBInWorld[1] * gjkOutput.m_distance; + pb[2]+= gjkOutput.m_normalOnBInWorld[2] * gjkOutput.m_distance; + + normal[0] = gjkOutput.m_normalOnBInWorld[0]; + normal[1] = gjkOutput.m_normalOnBInWorld[1]; + normal[2] = gjkOutput.m_normalOnBInWorld[2]; + + return gjkOutput.m_distance; + } + return -1.0f; +} + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btActionInterface.h b/Code/Physics/src/BulletDynamics/Dynamics/btActionInterface.h new file mode 100644 index 00000000..e1fea3a4 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btActionInterface.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _BT_ACTION_INTERFACE_H +#define _BT_ACTION_INTERFACE_H + +class btIDebugDraw; +class btCollisionWorld; + +#include "LinearMath/btScalar.h" +#include "btRigidBody.h" + +///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld +class btActionInterface +{ +protected: + + static btRigidBody& getFixedBody(); + + +public: + + virtual ~btActionInterface() + { + } + + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0; + + virtual void debugDraw(btIDebugDraw* debugDrawer) = 0; + +}; + +#endif //_BT_ACTION_INTERFACE_H + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp new file mode 100644 index 00000000..610db477 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -0,0 +1,1463 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +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 "btDiscreteDynamicsWorld.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btQuickprof.h" + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + + +#include "BulletDynamics/Dynamics/btActionInterface.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btMotionState.h" + +#include "LinearMath/btSerializer.h" + +#if 0 +btAlignedObjectArray debugContacts; +btAlignedObjectArray debugNormals; +int startHit=2; +int firstHit=startHit; +#endif + +SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) +{ + int islandId; + + const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); + const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); + islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); + return islandId; + +} + + +class btSortConstraintOnIslandPredicate +{ + public: + + bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const + { + int rIslandId0,lIslandId0; + rIslandId0 = btGetConstraintIslandId(rhs); + lIslandId0 = btGetConstraintIslandId(lhs); + return lIslandId0 < rIslandId0; + } +}; + +struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback +{ + btContactSolverInfo* m_solverInfo; + btConstraintSolver* m_solver; + btTypedConstraint** m_sortedConstraints; + int m_numConstraints; + btIDebugDraw* m_debugDrawer; + btDispatcher* m_dispatcher; + + btAlignedObjectArray m_bodies; + btAlignedObjectArray m_manifolds; + btAlignedObjectArray m_constraints; + + + InplaceSolverIslandCallback( + btConstraintSolver* solver, + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) + :m_solverInfo(NULL), + m_solver(solver), + m_sortedConstraints(NULL), + m_numConstraints(0), + m_debugDrawer(NULL), + m_dispatcher(dispatcher) + { + + } + + InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other) + { + btAssert(0); + (void)other; + return *this; + } + + SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer) + { + btAssert(solverInfo); + m_solverInfo = solverInfo; + m_sortedConstraints = sortedConstraints; + m_numConstraints = numConstraints; + m_debugDrawer = debugDrawer; + m_bodies.resize (0); + m_manifolds.resize (0); + m_constraints.resize (0); + } + + + virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) + { + if (islandId<0) + { + ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher); + } else + { + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;im_minimumSolverBatchSize<=1) + { + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher); + } else + { + + for (i=0;im_solverInfo->m_minimumSolverBatchSize) + { + processConstraints(); + } else + { + //printf("deferred\n"); + } + } + } + } + void processConstraints() + { + + btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0; + btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0; + btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0; + + m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_dispatcher); + m_bodies.resize(0); + m_manifolds.resize(0); + m_constraints.resize(0); + + } + +}; + + + +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_sortedConstraints (), +m_solverIslandCallback ( NULL ), +m_constraintSolver(constraintSolver), +m_gravity(0,-10,0), +m_localTime(0), +m_synchronizeAllMotionStates(false), +m_applySpeculativeContactRestitution(false), +m_profileTimings(0), +m_fixedTimeStep(0), +m_latencyMotionStateInterpolation(true) + +{ + if (!m_constraintSolver) + { + void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; + m_ownsConstraintSolver = true; + } else + { + m_ownsConstraintSolver = false; + } + + { + void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); + m_islandManager = new (mem) btSimulationIslandManager(); + } + + m_ownsIslandManager = true; + + { + void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16); + m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (m_constraintSolver, 0, dispatcher); + } +} + + +btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() +{ + //only delete it when we created it + if (m_ownsIslandManager) + { + m_islandManager->~btSimulationIslandManager(); + btAlignedFree( m_islandManager); + } + if (m_solverIslandCallback) + { + m_solverIslandCallback->~InplaceSolverIslandCallback(); + btAlignedFree(m_solverIslandCallback); + } + if (m_ownsConstraintSolver) + { + + m_constraintSolver->~btConstraintSolver(); + btAlignedFree(m_constraintSolver); + } +} + +void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) +{ +///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows +///to switch status _after_ adding kinematic objects to the world +///fix it for Bullet 3.x release + for (int i=0;igetActivationState() != ISLAND_SLEEPING) + { + if (body->isKinematicObject()) + { + //to calculate velocities next frame + body->saveKinematicState(timeStep); + } + } + } + +} + +void btDiscreteDynamicsWorld::debugDrawWorld() +{ + BT_PROFILE("debugDrawWorld"); + + btCollisionWorld::debugDrawWorld(); + + bool drawConstraints = false; + if (getDebugDrawer()) + { + int mode = getDebugDrawer()->getDebugMode(); + if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits)) + { + drawConstraints = true; + } + } + if(drawConstraints) + { + for(int i = getNumConstraints()-1; i>=0 ;i--) + { + btTypedConstraint* constraint = getConstraint(i); + debugDrawConstraint(constraint); + } + } + + + + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals))) + { + int i; + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode()) + { + for (i=0;idebugDraw(m_debugDrawer); + } + } + } +} + +void btDiscreteDynamicsWorld::clearForces() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } +} + +///apply gravity, call this once per timestep +void btDiscreteDynamicsWorld::applyGravity() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;iisActive()) + { + // MOD: Changing gravity for every body so they are pulled towards 0, 0, 0 + btTransform trans; + body->getMotionState()->getWorldTransform(trans); + body->setGravity(-trans.getOrigin().normalized()*10); + body->applyGravity(); + } + } +} + + +void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body) +{ + btAssert(body); + + if (body->getMotionState() && !body->isStaticOrKinematicObject()) + { + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + ///@todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(), + (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(), + interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } + } +} + + +void btDiscreteDynamicsWorld::synchronizeMotionStates() +{ + BT_PROFILE("synchronizeMotionStates"); + if (m_synchronizeAllMotionStates) + { + //iterate over all collision objects + for ( int i=0;iisActive()) + synchronizeSingleMotionState(body); + } + } +} + + +int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) +{ + startProfiling(timeStep); + + BT_PROFILE("stepSimulation"); + + int numSimulationSubSteps = 0; + + if (maxSubSteps) + { + //fixed timestep with interpolation + m_fixedTimeStep = fixedTimeStep; + m_localTime += timeStep; + if (m_localTime >= fixedTimeStep) + { + numSimulationSubSteps = int( m_localTime / fixedTimeStep); + m_localTime -= numSimulationSubSteps * fixedTimeStep; + } + } else + { + //variable timestep + fixedTimeStep = timeStep; + m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep; + m_fixedTimeStep = 0; + if (btFuzzyZero(timeStep)) + { + numSimulationSubSteps = 0; + maxSubSteps = 0; + } else + { + numSimulationSubSteps = 1; + maxSubSteps = 1; + } + } + + //process some debugging flags + if (getDebugDrawer()) + { + btIDebugDraw* debugDrawer = getDebugDrawer (); + gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; + } + if (numSimulationSubSteps) + { + + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt + int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; + + saveKinematicState(fixedTimeStep*clampedSimulationSteps); + + applyGravity(); + + + + for (int i=0;iisActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) + { + body->setGravity(gravity); + } + } +} + +btVector3 btDiscreteDynamicsWorld::getGravity () const +{ + return m_gravity; +} + +void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +{ + btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask); +} + +void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btRigidBody* body = btRigidBody::upcast(collisionObject); + if (body) + removeRigidBody(body); + else + btCollisionWorld::removeCollisionObject(collisionObject); +} + +void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + m_nonStaticRigidBodies.remove(body); + btCollisionWorld::removeCollisionObject(body); +} + + +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body) +{ + if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) + { + body->setGravity(m_gravity); + } + + if (body->getCollisionShape()) + { + if (!body->isStaticObject()) + { + m_nonStaticRigidBodies.push_back(body); + } else + { + body->setActivationState(ISLAND_SLEEPING); + } + + bool isDynamic = !(body->isStaticObject() || body->isKinematicObject()); + short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter); + short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + + addCollisionObject(body,collisionFilterGroup,collisionFilterMask); + } +} + +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +{ + if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY)) + { + body->setGravity(m_gravity); + } + + if (body->getCollisionShape()) + { + if (!body->isStaticObject()) + { + m_nonStaticRigidBodies.push_back(body); + } + else + { + body->setActivationState(ISLAND_SLEEPING); + } + addCollisionObject(body,group,mask); + } +} + + +void btDiscreteDynamicsWorld::updateActions(btScalar timeStep) +{ + BT_PROFILE("updateActions"); + + for ( int i=0;iupdateAction( this, timeStep); + } +} + + +void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) +{ + BT_PROFILE("updateActivationState"); + + for ( int i=0;iupdateDeactivation(timeStep); + + if (body->wantsSleeping()) + { + if (body->isStaticOrKinematicObject()) + { + body->setActivationState(ISLAND_SLEEPING); + } else + { + if (body->getActivationState() == ACTIVE_TAG) + body->setActivationState( WANTS_DEACTIVATION ); + if (body->getActivationState() == ISLAND_SLEEPING) + { + body->setAngularVelocity(btVector3(0,0,0)); + body->setLinearVelocity(btVector3(0,0,0)); + } + + } + } else + { + if (body->getActivationState() != DISABLE_DEACTIVATION) + body->setActivationState( ACTIVE_TAG ); + } + } + } +} + +void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) +{ + m_constraints.push_back(constraint); + if (disableCollisionsBetweenLinkedBodies) + { + constraint->getRigidBodyA().addConstraintRef(constraint); + constraint->getRigidBodyB().addConstraintRef(constraint); + } +} + +void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint) +{ + m_constraints.remove(constraint); + constraint->getRigidBodyA().removeConstraintRef(constraint); + constraint->getRigidBodyB().removeConstraintRef(constraint); +} + +void btDiscreteDynamicsWorld::addAction(btActionInterface* action) +{ + m_actions.push_back(action); +} + +void btDiscreteDynamicsWorld::removeAction(btActionInterface* action) +{ + m_actions.remove(action); +} + + +void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle) +{ + addAction(vehicle); +} + +void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle) +{ + removeAction(vehicle); +} + +void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character) +{ + addAction(character); +} + +void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character) +{ + removeAction(character); +} + + + + +void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + BT_PROFILE("solveConstraints"); + + m_sortedConstraints.resize( m_constraints.size()); + int i; + for (i=0;isetup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer()); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); + + /// solve all the constraints for this island + m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback); + + m_solverIslandCallback->processConstraints(); + + m_constraintSolver->allSolved(solverInfo, m_debugDrawer); +} + + +void btDiscreteDynamicsWorld::calculateSimulationIslands() +{ + BT_PROFILE("calculateSimulationIslands"); + + getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); + + { + //merge islands based on speculative contact manifolds too + for (int i=0;im_predictiveManifolds.size();i++) + { + btPersistentManifold* manifold = m_predictiveManifolds[i]; + + const btCollisionObject* colObj0 = manifold->getBody0(); + const btCollisionObject* colObj1 = manifold->getBody1(); + + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) + { + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag()); + } + } + } + + { + int i; + int numConstraints = int(m_constraints.size()); + for (i=0;i< numConstraints ; i++ ) + { + btTypedConstraint* constraint = m_constraints[i]; + if (constraint->isEnabled()) + { + const btRigidBody* colObj0 = &constraint->getRigidBodyA(); + const btRigidBody* colObj1 = &constraint->getRigidBodyB(); + + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) + { + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag()); + } + } + } + } + + //Store the island id in each body + getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); + + +} + + + + +class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +{ +public: + + btCollisionObject* m_me; + btScalar m_allowedPenetration; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + +public: + btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : + btCollisionWorld::ClosestConvexResultCallback(fromA,toA), + m_me(me), + m_allowedPenetration(0.0f), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if (convexResult.m_hitCollisionObject == m_me) + return 1.0f; + + //ignore result if there is no contact response + if(!convexResult.m_hitCollisionObject->hasContactResponse()) + return 1.0f; + + btVector3 linVelA,linVelB; + linVelA = m_convexToWorld-m_convexFromWorld; + linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin(); + + btVector3 relativeVelocity = (linVelA-linVelB); + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration) + return 1.f; + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + //don't collide with itself + if (proxy0->m_clientObject == m_me) + return false; + + ///don't do CCD when the collision filters are not matching + if (!ClosestConvexResultCallback::needsCollision(proxy0)) + return false; + + btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; + + //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179 + if (m_dispatcher->needsResponse(m_me,otherObj)) + { +#if 0 + ///don't do CCD when there are already contact points (touching contact/penetration) + btAlignedObjectArray manifoldArray; + btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); + if (collisionPair) + { + if (collisionPair->m_algorithm) + { + manifoldArray.resize(0); + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + for (int j=0;jgetNumContacts()>0) + return false; + } + } + } +#endif + return true; + } + + return false; + } + + +}; + +///internal debugging variable. this value shouldn't be too high +int gNumClampedCcdMotions=0; + + +void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep) +{ + BT_PROFILE("createPredictiveContacts"); + + { + BT_PROFILE("release predictive contact manifolds"); + + for (int i=0;im_dispatcher1->releaseManifold(manifold); + } + m_predictiveManifolds.clear(); + } + + btTransform predictedTrans; + for ( int i=0;isetHitFraction(1.f); + + if (body->isActive() && (!body->isStaticOrKinematicObject())) + { + + body->predictIntegratedTransform(timeStep, predictedTrans); + + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + + if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + { + BT_PROFILE("predictive convexSweepTest"); + if (body->getCollisionShape()->isConvex()) + { + gNumClampedCcdMotions++; +#ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY + class StaticOnlyCallback : public btClosestNotMeConvexResultCallback + { + public: + + StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : + btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher) + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; + if (!otherObj->isStaticOrKinematicObject()) + return false; + return btClosestNotMeConvexResultCallback::needsCollision(proxy0); + } + }; + + StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#else + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#endif + //btConvexShape* convexShape = static_cast(body->getCollisionShape()); + btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration; + + sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup; + sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask; + btTransform modifiedPredictedTrans = predictedTrans; + modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis()); + + convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults); + if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) + { + + btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction; + btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld); + + + btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject); + m_predictiveManifolds.push_back(manifold); + + btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec; + btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB; + + btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance); + + bool isPredictive = true; + int index = manifold->addManifoldPoint(newPoint, isPredictive); + btManifoldPoint& pt = manifold->getContactPoint(index); + pt.m_combinedRestitution = 0; + pt.m_combinedFriction = btManifoldResult::calculateCombinedFriction(body,sweepResults.m_hitCollisionObject); + pt.m_positionWorldOnA = body->getWorldTransform().getOrigin(); + pt.m_positionWorldOnB = worldPointB; + + } + } + } + } + } +} +void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + BT_PROFILE("integrateTransforms"); + btTransform predictedTrans; + for ( int i=0;isetHitFraction(1.f); + + if (body->isActive() && (!body->isStaticOrKinematicObject())) + { + + body->predictIntegratedTransform(timeStep, predictedTrans); + + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + + + + if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + { + BT_PROFILE("CCD motion clamping"); + if (body->getCollisionShape()->isConvex()) + { + gNumClampedCcdMotions++; +#ifdef USE_STATIC_ONLY + class StaticOnlyCallback : public btClosestNotMeConvexResultCallback + { + public: + + StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : + btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher) + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; + if (!otherObj->isStaticOrKinematicObject()) + return false; + return btClosestNotMeConvexResultCallback::needsCollision(proxy0); + } + }; + + StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#else + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#endif + //btConvexShape* convexShape = static_cast(body->getCollisionShape()); + btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration; + + sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup; + sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask; + btTransform modifiedPredictedTrans = predictedTrans; + modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis()); + + convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults); + if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) + { + + //printf("clamped integration to hit fraction = %f\n",fraction); + body->setHitFraction(sweepResults.m_closestHitFraction); + body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); + body->setHitFraction(0.f); + body->proceedToTransform( predictedTrans); + +#if 0 + btVector3 linVel = body->getLinearVelocity(); + + btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep; + btScalar maxSpeedSqr = maxSpeed*maxSpeed; + if (linVel.length2()>maxSpeedSqr) + { + linVel.normalize(); + linVel*= maxSpeed; + body->setLinearVelocity(linVel); + btScalar ms2 = body->getLinearVelocity().length2(); + body->predictIntegratedTransform(timeStep, predictedTrans); + + btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + btScalar smt = body->getCcdSquareMotionThreshold(); + printf("sm2=%f\n",sm2); + } +#else + + //don't apply the collision response right now, it will happen next frame + //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution. + //btScalar appliedImpulse = 0.f; + //btScalar depth = 0.f; + //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth); + + +#endif + + continue; + } + } + } + + + body->proceedToTransform( predictedTrans); + + } + + } + + ///this should probably be switched on by default, but it is not well tested yet + if (m_applySpeculativeContactRestitution) + { + BT_PROFILE("apply speculative contact restitution"); + for (int i=0;igetBody0()); + btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1()); + + for (int p=0;pgetNumContacts();p++) + { + const btManifoldPoint& pt = manifold->getContactPoint(p); + btScalar combinedRestitution = btManifoldResult::calculateCombinedRestitution(body0, body1); + + if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f) + //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f) + { + btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution; + + const btVector3& pos1 = pt.getPositionWorldOnA(); + const btVector3& pos2 = pt.getPositionWorldOnB(); + + btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin(); + btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin(); + + if (body0) + body0->applyImpulse(imp,rel_pos0); + if (body1) + body1->applyImpulse(-imp,rel_pos1); + } + } + } + } + +} + + + + + + +void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + BT_PROFILE("predictUnconstraintMotion"); + for ( int i=0;iisStaticOrKinematicObject()) + { + //don't integrate/update velocities here, it happens in the constraint solver + + body->applyDamping(timeStep); + + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + } + } +} + + +void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) +{ + (void)timeStep; + +#ifndef BT_NO_PROFILE + CProfileManager::Reset(); +#endif //BT_NO_PROFILE + +} + + + + + + +void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint) +{ + bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0; + bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0; + btScalar dbgDrawSize = constraint->getDbgDrawSize(); + if(dbgDrawSize <= btScalar(0.f)) + { + return; + } + + switch(constraint->getConstraintType()) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint; + btTransform tr; + tr.setIdentity(); + btVector3 pivot = p2pC->getPivotInA(); + pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot; + tr.setOrigin(pivot); + getDebugDrawer()->drawTransform(tr, dbgDrawSize); + // that ideally should draw the same frame + pivot = p2pC->getPivotInB(); + pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot; + tr.setOrigin(pivot); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + } + break; + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* pHinge = (btHingeConstraint*)constraint; + btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + btScalar minAng = pHinge->getLowerLimit(); + btScalar maxAng = pHinge->getUpperLimit(); + if(minAng == maxAng) + { + break; + } + bool drawSect = true; + if(minAng > maxAng) + { + minAng = btScalar(0.f); + maxAng = SIMD_2_PI; + drawSect = false; + } + if(drawLimits) + { + btVector3& center = tr.getOrigin(); + btVector3 normal = tr.getBasis().getColumn(2); + btVector3 axis = tr.getBasis().getColumn(0); + getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect); + } + } + break; + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint; + btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + //const btScalar length = btScalar(5); + const btScalar length = dbgDrawSize; + static int nSegments = 8*4; + btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments); + btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length); + pPrev = tr * pPrev; + for (int i=0; iGetPointForAngle(fAngleInRadians, length); + pCur = tr * pCur; + getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0)); + + if (i%(nSegments/8) == 0) + getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0)); + + pPrev = pCur; + } + btScalar tws = pCT->getTwistSpan(); + btScalar twa = pCT->getTwistAngle(); + bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f)); + if(useFrameB) + { + tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame(); + } + else + { + tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame(); + } + btVector3 pivot = tr.getOrigin(); + btVector3 normal = tr.getBasis().getColumn(0); + btVector3 axis1 = tr.getBasis().getColumn(1); + getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true); + + } + } + break; + case D6_SPRING_CONSTRAINT_TYPE: + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint; + btTransform tr = p6DOF->getCalculatedTransformA(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = p6DOF->getCalculatedTransformB(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + tr = p6DOF->getCalculatedTransformA(); + const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin(); + btVector3 up = tr.getBasis().getColumn(2); + btVector3 axis = tr.getBasis().getColumn(0); + btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit; + btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit; + btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit; + btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit; + getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0)); + axis = tr.getBasis().getColumn(1); + btScalar ay = p6DOF->getAngle(1); + btScalar az = p6DOF->getAngle(2); + btScalar cy = btCos(ay); + btScalar sy = btSin(ay); + btScalar cz = btCos(az); + btScalar sz = btSin(az); + btVector3 ref; + ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2]; + ref[1] = -sz*axis[0] + cz*axis[1]; + ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2]; + tr = p6DOF->getCalculatedTransformB(); + btVector3 normal = -tr.getBasis().getColumn(0); + btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit; + btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit; + if(minFi > maxFi) + { + getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false); + } + else if(minFi < maxFi) + { + getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true); + } + tr = p6DOF->getCalculatedTransformA(); + btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit; + btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit; + getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0)); + } + } + break; + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraint* pSlider = (btSliderConstraint*)constraint; + btTransform tr = pSlider->getCalculatedTransformA(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + tr = pSlider->getCalculatedTransformB(); + if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize); + if(drawLimits) + { + btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB(); + btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f); + btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f); + getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0)); + btVector3 normal = tr.getBasis().getColumn(0); + btVector3 axis = tr.getBasis().getColumn(1); + btScalar a_min = pSlider->getLowerAngLimit(); + btScalar a_max = pSlider->getUpperAngLimit(); + const btVector3& center = pSlider->getCalculatedTransformB().getOrigin(); + getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true); + } + } + break; + default : + break; + } + return; +} + + + + + +void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) +{ + if (m_ownsConstraintSolver) + { + btAlignedFree( m_constraintSolver); + } + m_ownsConstraintSolver = false; + m_constraintSolver = solver; + m_solverIslandCallback->m_solver = solver; +} + +btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} + + +int btDiscreteDynamicsWorld::getNumConstraints() const +{ + return int(m_constraints.size()); +} +btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) +{ + return m_constraints[index]; +} +const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const +{ + return m_constraints[index]; +} + + + +void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() & btCollisionObject::CO_RIGID_BODY) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj); + } + } + + for (i=0;icalculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(size,1); + const char* structType = constraint->serialize(chunk->m_oldPtr,serializer); + serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint); + } +} + + + + +void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer) +{ +#ifdef BT_USE_DOUBLE_PRECISION + int len = sizeof(btDynamicsWorldDoubleData); + btChunk* chunk = serializer->allocate(len,1); + btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr; +#else//BT_USE_DOUBLE_PRECISION + int len = sizeof(btDynamicsWorldFloatData); + btChunk* chunk = serializer->allocate(len,1); + btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr; +#endif//BT_USE_DOUBLE_PRECISION + + memset(worldInfo ,0x00,len); + + m_gravity.serialize(worldInfo->m_gravity); + worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau; + worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping; + worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction; + worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep; + + worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution; + worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction; + worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor; + worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp; + + worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2; + worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm; + worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold; + worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp; + + worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop; + worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor; + worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce; + worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold; + + worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations; + worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode; + worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold; + worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize; + + worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse; + +#ifdef BT_USE_DOUBLE_PRECISION + const char* structType = "btDynamicsWorldDoubleData"; +#else//BT_USE_DOUBLE_PRECISION + const char* structType = "btDynamicsWorldFloatData"; +#endif//BT_USE_DOUBLE_PRECISION + serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo); +} + +void btDiscreteDynamicsWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeDynamicsWorldInfo(serializer); + + serializeRigidBodies(serializer); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h new file mode 100644 index 00000000..d8a34b7d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -0,0 +1,234 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_DISCRETE_DYNAMICS_WORLD_H +#define BT_DISCRETE_DYNAMICS_WORLD_H + +#include "btDynamicsWorld.h" + +class btDispatcher; +class btOverlappingPairCache; +class btConstraintSolver; +class btSimulationIslandManager; +class btTypedConstraint; +class btActionInterface; +class btPersistentManifold; +class btIDebugDraw; +struct InplaceSolverIslandCallback; + +#include "LinearMath/btAlignedObjectArray.h" + + +///btDiscreteDynamicsWorld provides discrete rigid body simulation +///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld +{ +protected: + + btAlignedObjectArray m_sortedConstraints; + InplaceSolverIslandCallback* m_solverIslandCallback; + + btConstraintSolver* m_constraintSolver; + + btSimulationIslandManager* m_islandManager; + + btAlignedObjectArray m_constraints; + + btAlignedObjectArray m_nonStaticRigidBodies; + + btVector3 m_gravity; + + //for variable timesteps + btScalar m_localTime; + btScalar m_fixedTimeStep; + //for variable timesteps + + bool m_ownsIslandManager; + bool m_ownsConstraintSolver; + bool m_synchronizeAllMotionStates; + bool m_applySpeculativeContactRestitution; + + btAlignedObjectArray m_actions; + + int m_profileTimings; + + bool m_latencyMotionStateInterpolation; + + btAlignedObjectArray m_predictiveManifolds; + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void integrateTransforms(btScalar timeStep); + + virtual void calculateSimulationIslands(); + + virtual void solveConstraints(btContactSolverInfo& solverInfo); + + virtual void updateActivationState(btScalar timeStep); + + void updateActions(btScalar timeStep); + + void startProfiling(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void createPredictiveContacts(btScalar timeStep); + + virtual void saveKinematicState(btScalar timeStep); + + void serializeRigidBodies(btSerializer* serializer); + + void serializeDynamicsWorldInfo(btSerializer* serializer); + +public: + + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btDiscreteDynamicsWorld(); + + ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + + virtual void synchronizeMotionStates(); + + ///this can be useful to synchronize a single rigid body -> graphics object + void synchronizeSingleMotionState(btRigidBody* body); + + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); + + virtual void removeConstraint(btTypedConstraint* constraint); + + virtual void addAction(btActionInterface*); + + virtual void removeAction(btActionInterface*); + + btSimulationIslandManager* getSimulationIslandManager() + { + return m_islandManager; + } + + const btSimulationIslandManager* getSimulationIslandManager() const + { + return m_islandManager; + } + + btCollisionWorld* getCollisionWorld() + { + return this; + } + + virtual void setGravity(const btVector3& gravity); + + virtual btVector3 getGravity () const; + + virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + + virtual void addRigidBody(btRigidBody* body); + + virtual void addRigidBody(btRigidBody* body, short group, short mask); + + virtual void removeRigidBody(btRigidBody* body); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + + void debugDrawConstraint(btTypedConstraint* constraint); + + virtual void debugDrawWorld(); + + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); + + virtual int getNumConstraints() const; + + virtual btTypedConstraint* getConstraint(int index) ; + + virtual const btTypedConstraint* getConstraint(int index) const; + + + virtual btDynamicsWorldType getWorldType() const + { + return BT_DISCRETE_DYNAMICS_WORLD; + } + + ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep. + virtual void clearForces(); + + ///apply gravity, call this once per timestep + virtual void applyGravity(); + + virtual void setNumTasks(int numTasks) + { + (void) numTasks; + } + + ///obsolete, use updateActions instead + virtual void updateVehicles(btScalar timeStep) + { + updateActions(timeStep); + } + + ///obsolete, use addAction instead + virtual void addVehicle(btActionInterface* vehicle); + ///obsolete, use removeAction instead + virtual void removeVehicle(btActionInterface* vehicle); + ///obsolete, use addAction instead + virtual void addCharacter(btActionInterface* character); + ///obsolete, use removeAction instead + virtual void removeCharacter(btActionInterface* character); + + void setSynchronizeAllMotionStates(bool synchronizeAll) + { + m_synchronizeAllMotionStates = synchronizeAll; + } + bool getSynchronizeAllMotionStates() const + { + return m_synchronizeAllMotionStates; + } + + void setApplySpeculativeContactRestitution(bool enable) + { + m_applySpeculativeContactRestitution = enable; + } + + bool getApplySpeculativeContactRestitution() const + { + return m_applySpeculativeContactRestitution; + } + + ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo) + virtual void serialize(btSerializer* serializer); + + ///Interpolate motion state between previous and current transform, instead of current and next transform. + ///This can relieve discontinuities in the rendering, due to penetrations + void setLatencyMotionStateInterpolation(bool latencyInterpolation ) + { + m_latencyMotionStateInterpolation = latencyInterpolation; + } + bool getLatencyMotionStateInterpolation() const + { + return m_latencyMotionStateInterpolation; + } +}; + +#endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/Code/Physics/src/BulletDynamics/Dynamics/btDynamicsWorld.h new file mode 100644 index 00000000..35dd1400 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -0,0 +1,167 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DYNAMICS_WORLD_H +#define BT_DYNAMICS_WORLD_H + +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +class btTypedConstraint; +class btActionInterface; +class btConstraintSolver; +class btDynamicsWorld; + + +/// Type for the callback for each tick +typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); + +enum btDynamicsWorldType +{ + BT_SIMPLE_DYNAMICS_WORLD=1, + BT_DISCRETE_DYNAMICS_WORLD=2, + BT_CONTINUOUS_DYNAMICS_WORLD=3, + BT_SOFT_RIGID_DYNAMICS_WORLD=4, + BT_GPU_DYNAMICS_WORLD=5 +}; + +///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. +class btDynamicsWorld : public btCollisionWorld +{ + +protected: + btInternalTickCallback m_internalTickCallback; + btInternalTickCallback m_internalPreTickCallback; + void* m_worldUserInfo; + + btContactSolverInfo m_solverInfo; + +public: + + + btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) + :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0) + { + } + + virtual ~btDynamicsWorld() + { + } + + ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds. + ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'. + ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'. + ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant. + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; + + virtual void debugDrawWorld() = 0; + + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) + { + (void)constraint; (void)disableCollisionsBetweenLinkedBodies; + } + + virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} + + virtual void addAction(btActionInterface* action) = 0; + + virtual void removeAction(btActionInterface* action) = 0; + + //once a rigidbody is added to the dynamics world, it will get this gravity assigned + //existing rigidbodies in the world get gravity assigned too, during this method + virtual void setGravity(const btVector3& gravity) = 0; + virtual btVector3 getGravity () const = 0; + + virtual void synchronizeMotionStates() = 0; + + virtual void addRigidBody(btRigidBody* body) = 0; + + virtual void addRigidBody(btRigidBody* body, short group, short mask) = 0; + + virtual void removeRigidBody(btRigidBody* body) = 0; + + virtual void setConstraintSolver(btConstraintSolver* solver) = 0; + + virtual btConstraintSolver* getConstraintSolver() = 0; + + virtual int getNumConstraints() const { return 0; } + + virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; } + + virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } + + virtual btDynamicsWorldType getWorldType() const=0; + + virtual void clearForces() = 0; + + /// Set the callback for when an internal tick (simulation substep) happens, optional user info + void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0,bool isPreTick=false) + { + if (isPreTick) + { + m_internalPreTickCallback = cb; + } else + { + m_internalTickCallback = cb; + } + m_worldUserInfo = worldUserInfo; + } + + void setWorldUserInfo(void* worldUserInfo) + { + m_worldUserInfo = worldUserInfo; + } + + void* getWorldUserInfo() const + { + return m_worldUserInfo; + } + + btContactSolverInfo& getSolverInfo() + { + return m_solverInfo; + } + + + ///obsolete, use addAction instead. + virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;} + ///obsolete, use removeAction instead + virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;} + ///obsolete, use addAction instead. + virtual void addCharacter(btActionInterface* character) {(void)character;} + ///obsolete, use removeAction instead + virtual void removeCharacter(btActionInterface* character) {(void)character;} + + +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btDynamicsWorldDoubleData +{ + btContactSolverInfoDoubleData m_solverInfo; + btVector3DoubleData m_gravity; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btDynamicsWorldFloatData +{ + btContactSolverInfoFloatData m_solverInfo; + btVector3FloatData m_gravity; +}; + + +#endif //BT_DYNAMICS_WORLD_H + + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.cpp b/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.cpp new file mode 100644 index 00000000..222f9006 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -0,0 +1,400 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btRigidBody.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMotionState.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "LinearMath/btSerializer.h" + +//'temporarily' global variables +btScalar gDeactivationTime = btScalar(2.); +bool gDisableDeactivation = false; +static int uniqueId = 0; + + +btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + setupRigidBody(constructionInfo); +} + +btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) +{ + btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); + setupRigidBody(cinfo); +} + +void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + + m_internalType=CO_RIGID_BODY; + + m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + m_angularFactor.setValue(1,1,1); + m_linearFactor.setValue(1,1,1); + m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); + + m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; + m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; + m_optionalMotionState = constructionInfo.m_motionState; + m_contactSolverType = 0; + m_frictionSolverType = 0; + m_additionalDamping = constructionInfo.m_additionalDamping; + m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor; + m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; + m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; + m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; + + if (m_optionalMotionState) + { + m_optionalMotionState->getWorldTransform(m_worldTransform); + } else + { + m_worldTransform = constructionInfo.m_startWorldTransform; + } + + m_interpolationWorldTransform = m_worldTransform; + m_interpolationLinearVelocity.setValue(0,0,0); + m_interpolationAngularVelocity.setValue(0,0,0); + + //moved to btCollisionObject + m_friction = constructionInfo.m_friction; + m_rollingFriction = constructionInfo.m_rollingFriction; + m_restitution = constructionInfo.m_restitution; + + setCollisionShape( constructionInfo.m_collisionShape ); + m_debugBodyId = uniqueId++; + + setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); + updateInertiaTensor(); + + m_rigidbodyFlags = 0; + + + m_deltaLinearVelocity.setZero(); + m_deltaAngularVelocity.setZero(); + m_invMass = m_inverseMass*m_linearFactor; + m_pushVelocity.setZero(); + m_turnVelocity.setZero(); + + + +} + + +void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) +{ + btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); +} + +void btRigidBody::saveKinematicState(btScalar timeStep) +{ + //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities + if (timeStep != btScalar(0.)) + { + //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform + if (getMotionState()) + getMotionState()->getWorldTransform(m_worldTransform); + btVector3 linVel,angVel; + + btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity); + m_interpolationLinearVelocity = m_linearVelocity; + m_interpolationAngularVelocity = m_angularVelocity; + m_interpolationWorldTransform = m_worldTransform; + //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ()); + } +} + +void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax); +} + + + + +void btRigidBody::setGravity(const btVector3& acceleration) +{ + if (m_inverseMass != btScalar(0.0)) + { + m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); + } + m_gravity_acceleration = acceleration; +} + + + + + + +void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) +{ + m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); +} + + + + +///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping +void btRigidBody::applyDamping(btScalar timeStep) +{ + //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74 + //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway + +//#define USE_OLD_DAMPING_METHOD 1 +#ifdef USE_OLD_DAMPING_METHOD + m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); +#else + m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep); + m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep); +#endif + + if (m_additionalDamping) + { + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && + (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) + { + m_angularVelocity *= m_additionalDampingFactor; + m_linearVelocity *= m_additionalDampingFactor; + } + + + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + } +} + + +void btRigidBody::applyGravity() +{ + if (isStaticOrKinematicObject()) + return; + + applyCentralForce(m_gravity); + +} + +void btRigidBody::proceedToTransform(const btTransform& newTrans) +{ + setCenterOfMassTransform( newTrans ); +} + + +void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia) +{ + if (mass == btScalar(0.)) + { + m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; + m_inverseMass = btScalar(0.); + } else + { + m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT); + m_inverseMass = btScalar(1.0) / mass; + } + + //Fg = m * a + m_gravity = mass * m_gravity_acceleration; + + m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0), + inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0), + inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0)); + + m_invMass = m_linearFactor*m_inverseMass; +} + + +void btRigidBody::updateInertiaTensor() +{ + m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose(); +} + + +btVector3 btRigidBody::computeGyroscopicForce(btScalar maxGyroscopicForce) const +{ + btVector3 inertiaLocal; + inertiaLocal[0] = 1.f/getInvInertiaDiagLocal()[0]; + inertiaLocal[1] = 1.f/getInvInertiaDiagLocal()[1]; + inertiaLocal[2] = 1.f/getInvInertiaDiagLocal()[2]; + btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose(); + btVector3 tmp = inertiaTensorWorld*getAngularVelocity(); + btVector3 gf = getAngularVelocity().cross(tmp); + btScalar l2 = gf.length2(); + if (l2>maxGyroscopicForce*maxGyroscopicForce) + { + gf *= btScalar(1.)/btSqrt(l2)*maxGyroscopicForce; + } + return gf; +} + +void btRigidBody::integrateVelocities(btScalar step) +{ + if (isStaticOrKinematicObject()) + return; + + m_linearVelocity += m_totalForce * (m_inverseMass * step); + m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step; + +#define MAX_ANGVEL SIMD_HALF_PI + /// clamp angular velocity. collision calculations will fail on higher angular velocities + btScalar angvel = m_angularVelocity.length(); + if (angvel*step > MAX_ANGVEL) + { + m_angularVelocity *= (MAX_ANGVEL/step) /angvel; + } + +} + +btQuaternion btRigidBody::getOrientation() const +{ + btQuaternion orn; + m_worldTransform.getBasis().getRotation(orn); + return orn; +} + + +void btRigidBody::setCenterOfMassTransform(const btTransform& xform) +{ + + if (isKinematicObject()) + { + m_interpolationWorldTransform = m_worldTransform; + } else + { + m_interpolationWorldTransform = xform; + } + m_interpolationLinearVelocity = getLinearVelocity(); + m_interpolationAngularVelocity = getAngularVelocity(); + m_worldTransform = xform; + updateInertiaTensor(); +} + + +bool btRigidBody::checkCollideWithOverride(const btCollisionObject* co) const +{ + const btRigidBody* otherRb = btRigidBody::upcast(co); + if (!otherRb) + return true; + + for (int i = 0; i < m_constraintRefs.size(); ++i) + { + const btTypedConstraint* c = m_constraintRefs[i]; + if (c->isEnabled()) + if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb) + return false; + } + + return true; +} + + + +void btRigidBody::addConstraintRef(btTypedConstraint* c) +{ + int index = m_constraintRefs.findLinearSearch(c); + if (index == m_constraintRefs.size()) + m_constraintRefs.push_back(c); + + m_checkCollideWith = true; +} + +void btRigidBody::removeConstraintRef(btTypedConstraint* c) +{ + m_constraintRefs.remove(c); + m_checkCollideWith = m_constraintRefs.size() > 0; +} + +int btRigidBody::calculateSerializeBufferSize() const +{ + int sz = sizeof(btRigidBodyData); + return sz; +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const +{ + btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer; + + btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer); + + m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld); + m_linearVelocity.serialize(rbd->m_linearVelocity); + m_angularVelocity.serialize(rbd->m_angularVelocity); + rbd->m_inverseMass = m_inverseMass; + m_angularFactor.serialize(rbd->m_angularFactor); + m_linearFactor.serialize(rbd->m_linearFactor); + m_gravity.serialize(rbd->m_gravity); + m_gravity_acceleration.serialize(rbd->m_gravity_acceleration); + m_invInertiaLocal.serialize(rbd->m_invInertiaLocal); + m_totalForce.serialize(rbd->m_totalForce); + m_totalTorque.serialize(rbd->m_totalTorque); + rbd->m_linearDamping = m_linearDamping; + rbd->m_angularDamping = m_angularDamping; + rbd->m_additionalDamping = m_additionalDamping; + rbd->m_additionalDampingFactor = m_additionalDampingFactor; + rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr; + rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr; + rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor; + rbd->m_linearSleepingThreshold=m_linearSleepingThreshold; + rbd->m_angularSleepingThreshold = m_angularSleepingThreshold; + + return btRigidBodyDataName; +} + + + +void btRigidBody::serializeSingleObject(class btSerializer* serializer) const +{ + btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1); + const char* structType = serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this); +} + + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.h b/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.h new file mode 100644 index 00000000..ed90fb44 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.h @@ -0,0 +1,604 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_RIGIDBODY_H +#define BT_RIGIDBODY_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +class btCollisionShape; +class btMotionState; +class btTypedConstraint; + + +extern btScalar gDeactivationTime; +extern bool gDisableDeactivation; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btRigidBodyData btRigidBodyDoubleData +#define btRigidBodyDataName "btRigidBodyDoubleData" +#else +#define btRigidBodyData btRigidBodyFloatData +#define btRigidBodyDataName "btRigidBodyFloatData" +#endif //BT_USE_DOUBLE_PRECISION + + +enum btRigidBodyFlags +{ + BT_DISABLE_WORLD_GRAVITY = 1, + ///The BT_ENABLE_GYROPSCOPIC_FORCE can easily introduce instability + ///So generally it is best to not enable it. + ///If really needed, run at a high frequency like 1000 Hertz: ///See Demos/GyroscopicDemo for an example use + BT_ENABLE_GYROPSCOPIC_FORCE = 2 +}; + + +///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. +///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. +///There are 3 types of rigid bodies: +///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. +///- B) Fixed objects with zero mass. They are not moving (basically collision objects) +///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. +///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. +///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) +class btRigidBody : public btCollisionObject +{ + + btMatrix3x3 m_invInertiaTensorWorld; + btVector3 m_linearVelocity; + btVector3 m_angularVelocity; + btScalar m_inverseMass; + btVector3 m_linearFactor; + + btVector3 m_gravity; + btVector3 m_gravity_acceleration; + btVector3 m_invInertiaLocal; + btVector3 m_totalForce; + btVector3 m_totalTorque; + + btScalar m_linearDamping; + btScalar m_angularDamping; + + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //m_optionalMotionState allows to automatic synchronize the world transform for active objects + btMotionState* m_optionalMotionState; + + //keep track of typed constraints referencing this rigid body + btAlignedObjectArray m_constraintRefs; + + int m_rigidbodyFlags; + + int m_debugBodyId; + + +protected: + + ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity); + btVector3 m_deltaAngularVelocity; + btVector3 m_angularFactor; + btVector3 m_invMass; + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + + +public: + + + ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. + ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) + ///You can use the motion state to synchronize the world transform between physics and graphics objects. + ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, + ///m_startWorldTransform is only used when you don't provide a motion state. + struct btRigidBodyConstructionInfo + { + btScalar m_mass; + + ///When a motionState is provided, the rigid body will initialize its world transform from the motion state + ///In this case, m_startWorldTransform is ignored. + btMotionState* m_motionState; + btTransform m_startWorldTransform; + + btCollisionShape* m_collisionShape; + btVector3 m_localInertia; + btScalar m_linearDamping; + btScalar m_angularDamping; + + ///best simulation results when friction is non-zero + btScalar m_friction; + ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever. + ///See Bullet/Demos/RollingFrictionDemo for usage + btScalar m_rollingFriction; + ///best simulation results using zero restitution. + btScalar m_restitution; + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): + m_mass(mass), + m_motionState(motionState), + m_collisionShape(collisionShape), + m_localInertia(localInertia), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.)), + m_friction(btScalar(0.5)), + m_rollingFriction(btScalar(0)), + m_restitution(btScalar(0.)), + m_linearSleepingThreshold(btScalar(0.8)), + m_angularSleepingThreshold(btScalar(1.f)), + m_additionalDamping(false), + m_additionalDampingFactor(btScalar(0.005)), + m_additionalLinearDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingFactor(btScalar(0.01)) + { + m_startWorldTransform.setIdentity(); + } + }; + + ///btRigidBody constructor using construction info + btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); + + ///btRigidBody constructor for backwards compatibility. + ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) + btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); + + + virtual ~btRigidBody() + { + //No constraints should point to this rigidbody + //Remove constraints from the dynamics world before you delete the related rigidbodies. + btAssert(m_constraintRefs.size()==0); + } + +protected: + + ///setupRigidBody is only used internally by the constructor + void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); + +public: + + void proceedToTransform(const btTransform& newTrans); + + ///to keep collision detection and dynamics separate we don't store a rigidbody pointer + ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast + static const btRigidBody* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY) + return (const btRigidBody*)colObj; + return 0; + } + static btRigidBody* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY) + return (btRigidBody*)colObj; + return 0; + } + + /// continuous collision detection needs prediction + void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ; + + void saveKinematicState(btScalar step); + + void applyGravity(); + + void setGravity(const btVector3& acceleration); + + const btVector3& getGravity() const + { + return m_gravity_acceleration; + } + + void setDamping(btScalar lin_damping, btScalar ang_damping); + + btScalar getLinearDamping() const + { + return m_linearDamping; + } + + btScalar getAngularDamping() const + { + return m_angularDamping; + } + + btScalar getLinearSleepingThreshold() const + { + return m_linearSleepingThreshold; + } + + btScalar getAngularSleepingThreshold() const + { + return m_angularSleepingThreshold; + } + + void applyDamping(btScalar timeStep); + + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { + return m_collisionShape; + } + + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { + return m_collisionShape; + } + + void setMassProps(btScalar mass, const btVector3& inertia); + + const btVector3& getLinearFactor() const + { + return m_linearFactor; + } + void setLinearFactor(const btVector3& linearFactor) + { + m_linearFactor = linearFactor; + m_invMass = m_linearFactor*m_inverseMass; + } + btScalar getInvMass() const { return m_inverseMass; } + const btMatrix3x3& getInvInertiaTensorWorld() const { + return m_invInertiaTensorWorld; + } + + void integrateVelocities(btScalar step); + + void setCenterOfMassTransform(const btTransform& xform); + + void applyCentralForce(const btVector3& force) + { + m_totalForce += force*m_linearFactor; + } + + const btVector3& getTotalForce() const + { + return m_totalForce; + }; + + const btVector3& getTotalTorque() const + { + return m_totalTorque; + }; + + const btVector3& getInvInertiaDiagLocal() const + { + return m_invInertiaLocal; + }; + + void setInvInertiaDiagLocal(const btVector3& diagInvInertia) + { + m_invInertiaLocal = diagInvInertia; + } + + void setSleepingThresholds(btScalar linear,btScalar angular) + { + m_linearSleepingThreshold = linear; + m_angularSleepingThreshold = angular; + } + + void applyTorque(const btVector3& torque) + { + m_totalTorque += torque*m_angularFactor; + } + + void applyForce(const btVector3& force, const btVector3& rel_pos) + { + applyCentralForce(force); + applyTorque(rel_pos.cross(force*m_linearFactor)); + } + + void applyCentralImpulse(const btVector3& impulse) + { + m_linearVelocity += impulse *m_linearFactor * m_inverseMass; + } + + void applyTorqueImpulse(const btVector3& torque) + { + m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor; + } + + void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) + { + if (m_inverseMass != btScalar(0.)) + { + applyCentralImpulse(impulse); + if (m_angularFactor) + { + applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor)); + } + } + } + + void clearForces() + { + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + } + + void updateInertiaTensor(); + + const btVector3& getCenterOfMassPosition() const { + return m_worldTransform.getOrigin(); + } + btQuaternion getOrientation() const; + + const btTransform& getCenterOfMassTransform() const { + return m_worldTransform; + } + const btVector3& getLinearVelocity() const { + return m_linearVelocity; + } + const btVector3& getAngularVelocity() const { + return m_angularVelocity; + } + + + inline void setLinearVelocity(const btVector3& lin_vel) + { + m_updateRevision++; + m_linearVelocity = lin_vel; + } + + inline void setAngularVelocity(const btVector3& ang_vel) + { + m_updateRevision++; + m_angularVelocity = ang_vel; + } + + btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const + { + //we also calculate lin/ang velocity for kinematic objects + return m_linearVelocity + m_angularVelocity.cross(rel_pos); + + //for kinematic objects, we could also use use: + // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep; + } + + void translate(const btVector3& v) + { + m_worldTransform.getOrigin() += v; + } + + + void getAabb(btVector3& aabbMin,btVector3& aabbMax) const; + + + + + + SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const + { + btVector3 r0 = pos - getCenterOfMassPosition(); + + btVector3 c0 = (r0).cross(normal); + + btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0); + + return m_inverseMass + normal.dot(vec); + + } + + SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const + { + btVector3 vec = axis * getInvInertiaTensorWorld(); + return axis.dot(vec); + } + + SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) + { + if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) + return; + + if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && + (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) + { + m_deactivationTime += timeStep; + } else + { + m_deactivationTime=btScalar(0.); + setActivationState(0); + } + + } + + SIMD_FORCE_INLINE bool wantsSleeping() + { + + if (getActivationState() == DISABLE_DEACTIVATION) + return false; + + //disable deactivation + if (gDisableDeactivation || (gDeactivationTime == btScalar(0.))) + return false; + + if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION)) + return true; + + if (m_deactivationTime> gDeactivationTime) + { + return true; + } + return false; + } + + + + const btBroadphaseProxy* getBroadphaseProxy() const + { + return m_broadphaseHandle; + } + btBroadphaseProxy* getBroadphaseProxy() + { + return m_broadphaseHandle; + } + void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy) + { + m_broadphaseHandle = broadphaseProxy; + } + + //btMotionState allows to automatic synchronize the world transform for active objects + btMotionState* getMotionState() + { + return m_optionalMotionState; + } + const btMotionState* getMotionState() const + { + return m_optionalMotionState; + } + void setMotionState(btMotionState* motionState) + { + m_optionalMotionState = motionState; + if (m_optionalMotionState) + motionState->getWorldTransform(m_worldTransform); + } + + //for experimental overriding of friction/contact solver func + int m_contactSolverType; + int m_frictionSolverType; + + void setAngularFactor(const btVector3& angFac) + { + m_updateRevision++; + m_angularFactor = angFac; + } + + void setAngularFactor(btScalar angFac) + { + m_updateRevision++; + m_angularFactor.setValue(angFac,angFac,angFac); + } + const btVector3& getAngularFactor() const + { + return m_angularFactor; + } + + //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase? + bool isInWorld() const + { + return (getBroadphaseProxy() != 0); + } + + virtual bool checkCollideWithOverride(const btCollisionObject* co) const; + + void addConstraintRef(btTypedConstraint* c); + void removeConstraintRef(btTypedConstraint* c); + + btTypedConstraint* getConstraintRef(int index) + { + return m_constraintRefs[index]; + } + + int getNumConstraintRefs() const + { + return m_constraintRefs.size(); + } + + void setFlags(int flags) + { + m_rigidbodyFlags = flags; + } + + int getFlags() const + { + return m_rigidbodyFlags; + } + + btVector3 computeGyroscopicForce(btScalar maxGyroscopicForce) const; + + /////////////////////////////////////////////// + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; + + virtual void serializeSingleObject(class btSerializer* serializer) const; + +}; + +//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btRigidBodyFloatData +{ + btCollisionObjectFloatData m_collisionObjectData; + btMatrix3x3FloatData m_invInertiaTensorWorld; + btVector3FloatData m_linearVelocity; + btVector3FloatData m_angularVelocity; + btVector3FloatData m_angularFactor; + btVector3FloatData m_linearFactor; + btVector3FloatData m_gravity; + btVector3FloatData m_gravity_acceleration; + btVector3FloatData m_invInertiaLocal; + btVector3FloatData m_totalForce; + btVector3FloatData m_totalTorque; + float m_inverseMass; + float m_linearDamping; + float m_angularDamping; + float m_additionalDampingFactor; + float m_additionalLinearDampingThresholdSqr; + float m_additionalAngularDampingThresholdSqr; + float m_additionalAngularDampingFactor; + float m_linearSleepingThreshold; + float m_angularSleepingThreshold; + int m_additionalDamping; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btRigidBodyDoubleData +{ + btCollisionObjectDoubleData m_collisionObjectData; + btMatrix3x3DoubleData m_invInertiaTensorWorld; + btVector3DoubleData m_linearVelocity; + btVector3DoubleData m_angularVelocity; + btVector3DoubleData m_angularFactor; + btVector3DoubleData m_linearFactor; + btVector3DoubleData m_gravity; + btVector3DoubleData m_gravity_acceleration; + btVector3DoubleData m_invInertiaLocal; + btVector3DoubleData m_totalForce; + btVector3DoubleData m_totalTorque; + double m_inverseMass; + double m_linearDamping; + double m_angularDamping; + double m_additionalDampingFactor; + double m_additionalLinearDampingThresholdSqr; + double m_additionalAngularDampingThresholdSqr; + double m_additionalAngularDampingFactor; + double m_linearSleepingThreshold; + double m_angularSleepingThreshold; + int m_additionalDamping; + char m_padding[4]; +}; + + + +#endif //BT_RIGIDBODY_H + diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp new file mode 100644 index 00000000..35dd3884 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -0,0 +1,280 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSimpleDynamicsWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" +{ + void btBulletDynamicsProbe (); + void btBulletDynamicsProbe () {} +} + + + + +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_constraintSolver(constraintSolver), +m_ownsConstraintSolver(false), +m_gravity(0,0,-10) +{ + +} + + +btSimpleDynamicsWorld::~btSimpleDynamicsWorld() +{ + if (m_ownsConstraintSolver) + btAlignedFree( m_constraintSolver); +} + +int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) +{ + (void)fixedTimeStep; + (void)maxSubSteps; + + + ///apply gravity, predict motion + predictUnconstraintMotion(timeStep); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_debugDraw = getDebugDrawer(); + + ///perform collision detection + performDiscreteCollisionDetection(); + + ///solve contact constraints + int numManifolds = m_dispatcher1->getNumManifolds(); + if (numManifolds) + { + btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer(); + + btContactSolverInfo infoGlobal; + infoGlobal.m_timeStep = timeStep; + m_constraintSolver->prepareSolve(0,numManifolds); + m_constraintSolver->solveGroup(&getCollisionObjectArray()[0],getNumCollisionObjects(),manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_dispatcher1); + m_constraintSolver->allSolved(infoGlobal,m_debugDrawer); + } + + ///integrate transforms + integrateTransforms(timeStep); + + updateAabbs(); + + synchronizeMotionStates(); + + clearForces(); + + return 1; + +} + +void btSimpleDynamicsWorld::clearForces() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } + } +} + + +void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) +{ + m_gravity = gravity; + for ( int i=0;isetGravity(gravity); + } + } +} + +btVector3 btSimpleDynamicsWorld::getGravity () const +{ + return m_gravity; +} + +void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + btCollisionWorld::removeCollisionObject(body); +} + +void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btRigidBody* body = btRigidBody::upcast(collisionObject); + if (body) + removeRigidBody(body); + else + btCollisionWorld::removeCollisionObject(collisionObject); +} + + +void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body) +{ + body->setGravity(m_gravity); + + if (body->getCollisionShape()) + { + addCollisionObject(body); + } +} + +void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +{ + body->setGravity(m_gravity); + + if (body->getCollisionShape()) + { + addCollisionObject(body,group,mask); + } +} + + +void btSimpleDynamicsWorld::debugDrawWorld() +{ + +} + +void btSimpleDynamicsWorld::addAction(btActionInterface* action) +{ + +} + +void btSimpleDynamicsWorld::removeAction(btActionInterface* action) +{ + +} + + +void btSimpleDynamicsWorld::updateAabbs() +{ + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticObject())) + { + btVector3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btBroadphaseInterface* bp = getBroadphase(); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + } + } + } +} + +void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticObject())) + { + body->predictIntegratedTransform(timeStep, predictedTrans); + body->proceedToTransform( predictedTrans); + } + } + } +} + + + +void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + for ( int i=0;iisStaticObject()) + { + if (body->isActive()) + { + body->applyGravity(); + body->integrateVelocities( timeStep); + body->applyDamping(timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + } + } + } + } +} + + +void btSimpleDynamicsWorld::synchronizeMotionStates() +{ + ///@todo: iterate over awake simulation islands! + for ( int i=0;igetMotionState()) + { + if (body->getActivationState() != ISLAND_SLEEPING) + { + body->getMotionState()->setWorldTransform(body->getWorldTransform()); + } + } + } + +} + + +void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) +{ + if (m_ownsConstraintSolver) + { + btAlignedFree(m_constraintSolver); + } + m_ownsConstraintSolver = false; + m_constraintSolver = solver; +} + +btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h new file mode 100644 index 00000000..d48d2e39 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -0,0 +1,89 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SIMPLE_DYNAMICS_WORLD_H +#define BT_SIMPLE_DYNAMICS_WORLD_H + +#include "btDynamicsWorld.h" + +class btDispatcher; +class btOverlappingPairCache; +class btConstraintSolver; + +///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. +///Please use btDiscreteDynamicsWorld instead +class btSimpleDynamicsWorld : public btDynamicsWorld +{ +protected: + + btConstraintSolver* m_constraintSolver; + + bool m_ownsConstraintSolver; + + void predictUnconstraintMotion(btScalar timeStep); + + void integrateTransforms(btScalar timeStep); + + btVector3 m_gravity; + +public: + + + + ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver + btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btSimpleDynamicsWorld(); + + ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + virtual void setGravity(const btVector3& gravity); + + virtual btVector3 getGravity () const; + + virtual void addRigidBody(btRigidBody* body); + + virtual void addRigidBody(btRigidBody* body, short group, short mask); + + virtual void removeRigidBody(btRigidBody* body); + + virtual void debugDrawWorld(); + + virtual void addAction(btActionInterface* action); + + virtual void removeAction(btActionInterface* action); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + virtual void updateAabbs(); + + virtual void synchronizeMotionStates(); + + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SIMPLE_DYNAMICS_WORLD; + } + + virtual void clearForces(); + +}; + +#endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.cpp new file mode 100644 index 00000000..56a1c55d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.cpp @@ -0,0 +1,1009 @@ +/* + * PURPOSE: + * Class representing an articulated rigid body. Stores the body's + * current state, allows forces and torques to be set, handles + * timestepping and implements Featherstone's algorithm. + * + * COPYRIGHT: + * Copyright (C) Stephen Thompson, , 2011-2013 + * Portions written By Erwin Coumans: replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix) + + 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 "btMultiBody.h" +#include "btMultiBodyLink.h" +#include "btMultiBodyLinkCollider.h" + +// #define INCLUDE_GYRO_TERM + +namespace { + const btScalar SLEEP_EPSILON = btScalar(0.05); // this is a squared velocity (m^2 s^-2) + const btScalar SLEEP_TIMEOUT = btScalar(2); // in seconds +} + + + + +// +// Various spatial helper functions +// + +namespace { + void SpatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame + const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates + const btVector3 &top_in, // top part of input vector + const btVector3 &bottom_in, // bottom part of input vector + btVector3 &top_out, // top part of output vector + btVector3 &bottom_out) // bottom part of output vector + { + top_out = rotation_matrix * top_in; + bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in; + } + + void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix, + const btVector3 &displacement, + const btVector3 &top_in, + const btVector3 &bottom_in, + btVector3 &top_out, + btVector3 &bottom_out) + { + top_out = rotation_matrix.transpose() * top_in; + bottom_out = rotation_matrix.transpose() * (bottom_in + displacement.cross(top_in)); + } + + btScalar SpatialDotProduct(const btVector3 &a_top, + const btVector3 &a_bottom, + const btVector3 &b_top, + const btVector3 &b_bottom) + { + return a_bottom.dot(b_top) + a_top.dot(b_bottom); + } +} + + +// +// Implementation of class btMultiBody +// + +btMultiBody::btMultiBody(int n_links, + btScalar mass, + const btVector3 &inertia, + bool fixed_base_, + bool can_sleep_) + : base_quat(0, 0, 0, 1), + base_mass(mass), + base_inertia(inertia), + + fixed_base(fixed_base_), + awake(true), + can_sleep(can_sleep_), + sleep_timer(0), + m_baseCollider(0), + m_linearDamping(0.04f), + m_angularDamping(0.04f), + m_useGyroTerm(true), + m_maxAppliedImpulse(1000.f), + m_hasSelfCollision(true) +{ + links.resize(n_links); + + vector_buf.resize(2*n_links); + matrix_buf.resize(n_links + 1); + m_real_buf.resize(6 + 2*n_links); + base_pos.setValue(0, 0, 0); + base_force.setValue(0, 0, 0); + base_torque.setValue(0, 0, 0); +} + +btMultiBody::~btMultiBody() +{ +} + +void btMultiBody::setupPrismatic(int i, + btScalar mass, + const btVector3 &inertia, + int parent, + const btQuaternion &rot_parent_to_this, + const btVector3 &joint_axis, + const btVector3 &r_vector_when_q_zero, + bool disableParentCollision) +{ + links[i].mass = mass; + links[i].inertia = inertia; + links[i].parent = parent; + links[i].zero_rot_parent_to_this = rot_parent_to_this; + links[i].axis_top.setValue(0,0,0); + links[i].axis_bottom = joint_axis; + links[i].e_vector = r_vector_when_q_zero; + links[i].is_revolute = false; + links[i].cached_rot_parent_to_this = rot_parent_to_this; + if (disableParentCollision) + links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; + + links[i].updateCache(); +} + +void btMultiBody::setupRevolute(int i, + btScalar mass, + const btVector3 &inertia, + int parent, + const btQuaternion &zero_rot_parent_to_this, + const btVector3 &joint_axis, + const btVector3 &parent_axis_position, + const btVector3 &my_axis_position, + bool disableParentCollision) +{ + links[i].mass = mass; + links[i].inertia = inertia; + links[i].parent = parent; + links[i].zero_rot_parent_to_this = zero_rot_parent_to_this; + links[i].axis_top = joint_axis; + links[i].axis_bottom = joint_axis.cross(my_axis_position); + links[i].d_vector = my_axis_position; + links[i].e_vector = parent_axis_position; + links[i].is_revolute = true; + if (disableParentCollision) + links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION; + links[i].updateCache(); +} + + + + + +int btMultiBody::getParent(int i) const +{ + return links[i].parent; +} + +btScalar btMultiBody::getLinkMass(int i) const +{ + return links[i].mass; +} + +const btVector3 & btMultiBody::getLinkInertia(int i) const +{ + return links[i].inertia; +} + +btScalar btMultiBody::getJointPos(int i) const +{ + return links[i].joint_pos; +} + +btScalar btMultiBody::getJointVel(int i) const +{ + return m_real_buf[6 + i]; +} + +void btMultiBody::setJointPos(int i, btScalar q) +{ + links[i].joint_pos = q; + links[i].updateCache(); +} + +void btMultiBody::setJointVel(int i, btScalar qdot) +{ + m_real_buf[6 + i] = qdot; +} + +const btVector3 & btMultiBody::getRVector(int i) const +{ + return links[i].cached_r_vector; +} + +const btQuaternion & btMultiBody::getParentToLocalRot(int i) const +{ + return links[i].cached_rot_parent_to_this; +} + +btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const +{ + btVector3 result = local_pos; + while (i != -1) { + // 'result' is in frame i. transform it to frame parent(i) + result += getRVector(i); + result = quatRotate(getParentToLocalRot(i).inverse(),result); + i = getParent(i); + } + + // 'result' is now in the base frame. transform it to world frame + result = quatRotate(getWorldToBaseRot().inverse() ,result); + result += getBasePos(); + + return result; +} + +btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const +{ + if (i == -1) { + // world to base + return quatRotate(getWorldToBaseRot(),(world_pos - getBasePos())); + } else { + // find position in parent frame, then transform to current frame + return quatRotate(getParentToLocalRot(i),worldPosToLocal(getParent(i), world_pos)) - getRVector(i); + } +} + +btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const +{ + btVector3 result = local_dir; + while (i != -1) { + result = quatRotate(getParentToLocalRot(i).inverse() , result); + i = getParent(i); + } + result = quatRotate(getWorldToBaseRot().inverse() , result); + return result; +} + +btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const +{ + if (i == -1) { + return quatRotate(getWorldToBaseRot(), world_dir); + } else { + return quatRotate(getParentToLocalRot(i) ,worldDirToLocal(getParent(i), world_dir)); + } +} + +void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const +{ + int num_links = getNumLinks(); + // Calculates the velocities of each link (and the base) in its local frame + omega[0] = quatRotate(base_quat ,getBaseOmega()); + vel[0] = quatRotate(base_quat ,getBaseVel()); + + for (int i = 0; i < num_links; ++i) { + const int parent = links[i].parent; + + // transform parent vel into this frame, store in omega[i+1], vel[i+1] + SpatialTransform(btMatrix3x3(links[i].cached_rot_parent_to_this), links[i].cached_r_vector, + omega[parent+1], vel[parent+1], + omega[i+1], vel[i+1]); + + // now add qidot * shat_i + omega[i+1] += getJointVel(i) * links[i].axis_top; + vel[i+1] += getJointVel(i) * links[i].axis_bottom; + } +} + +btScalar btMultiBody::getKineticEnergy() const +{ + int num_links = getNumLinks(); + // TODO: would be better not to allocate memory here + btAlignedObjectArray omega;omega.resize(num_links+1); + btAlignedObjectArray vel;vel.resize(num_links+1); + compTreeLinkVelocities(&omega[0], &vel[0]); + + // we will do the factor of 0.5 at the end + btScalar result = base_mass * vel[0].dot(vel[0]); + result += omega[0].dot(base_inertia * omega[0]); + + for (int i = 0; i < num_links; ++i) { + result += links[i].mass * vel[i+1].dot(vel[i+1]); + result += omega[i+1].dot(links[i].inertia * omega[i+1]); + } + + return 0.5f * result; +} + +btVector3 btMultiBody::getAngularMomentum() const +{ + int num_links = getNumLinks(); + // TODO: would be better not to allocate memory here + btAlignedObjectArray omega;omega.resize(num_links+1); + btAlignedObjectArray vel;vel.resize(num_links+1); + btAlignedObjectArray rot_from_world;rot_from_world.resize(num_links+1); + compTreeLinkVelocities(&omega[0], &vel[0]); + + rot_from_world[0] = base_quat; + btVector3 result = quatRotate(rot_from_world[0].inverse() , (base_inertia * omega[0])); + + for (int i = 0; i < num_links; ++i) { + rot_from_world[i+1] = links[i].cached_rot_parent_to_this * rot_from_world[links[i].parent+1]; + result += (quatRotate(rot_from_world[i+1].inverse() , (links[i].inertia * omega[i+1]))); + } + + return result; +} + + +void btMultiBody::clearForcesAndTorques() +{ + base_force.setValue(0, 0, 0); + base_torque.setValue(0, 0, 0); + + for (int i = 0; i < getNumLinks(); ++i) { + links[i].applied_force.setValue(0, 0, 0); + links[i].applied_torque.setValue(0, 0, 0); + links[i].joint_torque = 0; + } +} + +void btMultiBody::clearVelocities() +{ + for (int i = 0; i < 6 + getNumLinks(); ++i) + { + m_real_buf[i] = 0.f; + } +} +void btMultiBody::addLinkForce(int i, const btVector3 &f) +{ + links[i].applied_force += f; +} + +void btMultiBody::addLinkTorque(int i, const btVector3 &t) +{ + links[i].applied_torque += t; +} + +void btMultiBody::addJointTorque(int i, btScalar Q) +{ + links[i].joint_torque += Q; +} + +const btVector3 & btMultiBody::getLinkForce(int i) const +{ + return links[i].applied_force; +} + +const btVector3 & btMultiBody::getLinkTorque(int i) const +{ + return links[i].applied_torque; +} + +btScalar btMultiBody::getJointTorque(int i) const +{ + return links[i].joint_torque; +} + + +inline btMatrix3x3 vecMulVecTranspose(const btVector3& v0, const btVector3& v1Transposed) +{ + btVector3 row0 = btVector3( + v0.x() * v1Transposed.x(), + v0.x() * v1Transposed.y(), + v0.x() * v1Transposed.z()); + btVector3 row1 = btVector3( + v0.y() * v1Transposed.x(), + v0.y() * v1Transposed.y(), + v0.y() * v1Transposed.z()); + btVector3 row2 = btVector3( + v0.z() * v1Transposed.x(), + v0.z() * v1Transposed.y(), + v0.z() * v1Transposed.z()); + + btMatrix3x3 m(row0[0],row0[1],row0[2], + row1[0],row1[1],row1[2], + row2[0],row2[1],row2[2]); + return m; +} + + +void btMultiBody::stepVelocities(btScalar dt, + btAlignedObjectArray &scratch_r, + btAlignedObjectArray &scratch_v, + btAlignedObjectArray &scratch_m) +{ + // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot) + // and the base linear & angular accelerations. + + // We apply damping forces in this routine as well as any external forces specified by the + // caller (via addBaseForce etc). + + // output should point to an array of 6 + num_links reals. + // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame), + // num_links joint acceleration values. + + int num_links = getNumLinks(); + + const btScalar DAMPING_K1_LINEAR = m_linearDamping; + const btScalar DAMPING_K2_LINEAR = m_linearDamping; + + const btScalar DAMPING_K1_ANGULAR = m_angularDamping; + const btScalar DAMPING_K2_ANGULAR= m_angularDamping; + + btVector3 base_vel = getBaseVel(); + btVector3 base_omega = getBaseOmega(); + + // Temporary matrices/vectors -- use scratch space from caller + // so that we don't have to keep reallocating every frame + + scratch_r.resize(2*num_links + 6); + scratch_v.resize(8*num_links + 6); + scratch_m.resize(4*num_links + 4); + + btScalar * r_ptr = &scratch_r[0]; + btScalar * output = &scratch_r[num_links]; // "output" holds the q_double_dot results + btVector3 * v_ptr = &scratch_v[0]; + + // vhat_i (top = angular, bottom = linear part) + btVector3 * vel_top_angular = v_ptr; v_ptr += num_links + 1; + btVector3 * vel_bottom_linear = v_ptr; v_ptr += num_links + 1; + + // zhat_i^A + btVector3 * zero_acc_top_angular = v_ptr; v_ptr += num_links + 1; + btVector3 * zero_acc_bottom_linear = v_ptr; v_ptr += num_links + 1; + + // chat_i (note NOT defined for the base) + btVector3 * coriolis_top_angular = v_ptr; v_ptr += num_links; + btVector3 * coriolis_bottom_linear = v_ptr; v_ptr += num_links; + + // top left, top right and bottom left blocks of Ihat_i^A. + // bottom right block = transpose of top left block and is not stored. + // Note: the top right and bottom left blocks are always symmetric matrices, but we don't make use of this fact currently. + btMatrix3x3 * inertia_top_left = &scratch_m[num_links + 1]; + btMatrix3x3 * inertia_top_right = &scratch_m[2*num_links + 2]; + btMatrix3x3 * inertia_bottom_left = &scratch_m[3*num_links + 3]; + + // Cached 3x3 rotation matrices from parent frame to this frame. + btMatrix3x3 * rot_from_parent = &matrix_buf[0]; + btMatrix3x3 * rot_from_world = &scratch_m[0]; + + // hhat_i, ahat_i + // hhat is NOT stored for the base (but ahat is) + btVector3 * h_top = num_links > 0 ? &vector_buf[0] : 0; + btVector3 * h_bottom = num_links > 0 ? &vector_buf[num_links] : 0; + btVector3 * accel_top = v_ptr; v_ptr += num_links + 1; + btVector3 * accel_bottom = v_ptr; v_ptr += num_links + 1; + + // Y_i, D_i + btScalar * Y = r_ptr; r_ptr += num_links; + btScalar * D = num_links > 0 ? &m_real_buf[6 + num_links] : 0; + + // ptr to the joint accel part of the output + btScalar * joint_accel = output + 6; + + + // Start of the algorithm proper. + + // First 'upward' loop. + // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich. + + rot_from_parent[0] = btMatrix3x3(base_quat); + + vel_top_angular[0] = rot_from_parent[0] * base_omega; + vel_bottom_linear[0] = rot_from_parent[0] * base_vel; + + if (fixed_base) { + zero_acc_top_angular[0] = zero_acc_bottom_linear[0] = btVector3(0,0,0); + } else { + zero_acc_top_angular[0] = - (rot_from_parent[0] * (base_force + - base_mass*(DAMPING_K1_LINEAR+DAMPING_K2_LINEAR*base_vel.norm())*base_vel)); + + zero_acc_bottom_linear[0] = + - (rot_from_parent[0] * base_torque); + + if (m_useGyroTerm) + zero_acc_bottom_linear[0]+=vel_top_angular[0].cross( base_inertia * vel_top_angular[0] ); + + zero_acc_bottom_linear[0] += base_inertia * vel_top_angular[0] * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR*vel_top_angular[0].norm()); + + } + + + + inertia_top_left[0] = btMatrix3x3(0,0,0,0,0,0,0,0,0);//::Zero(); + + + inertia_top_right[0].setValue(base_mass, 0, 0, + 0, base_mass, 0, + 0, 0, base_mass); + inertia_bottom_left[0].setValue(base_inertia[0], 0, 0, + 0, base_inertia[1], 0, + 0, 0, base_inertia[2]); + + rot_from_world[0] = rot_from_parent[0]; + + for (int i = 0; i < num_links; ++i) { + const int parent = links[i].parent; + rot_from_parent[i+1] = btMatrix3x3(links[i].cached_rot_parent_to_this); + + + rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1]; + + // vhat_i = i_xhat_p(i) * vhat_p(i) + SpatialTransform(rot_from_parent[i+1], links[i].cached_r_vector, + vel_top_angular[parent+1], vel_bottom_linear[parent+1], + vel_top_angular[i+1], vel_bottom_linear[i+1]); + + // we can now calculate chat_i + // remember vhat_i is really vhat_p(i) (but in current frame) at this point + coriolis_bottom_linear[i] = vel_top_angular[i+1].cross(vel_top_angular[i+1].cross(links[i].cached_r_vector)) + + 2 * vel_top_angular[i+1].cross(links[i].axis_bottom) * getJointVel(i); + if (links[i].is_revolute) { + coriolis_top_angular[i] = vel_top_angular[i+1].cross(links[i].axis_top) * getJointVel(i); + coriolis_bottom_linear[i] += (getJointVel(i) * getJointVel(i)) * links[i].axis_top.cross(links[i].axis_bottom); + } else { + coriolis_top_angular[i] = btVector3(0,0,0); + } + + // now set vhat_i to its true value by doing + // vhat_i += qidot * shat_i + vel_top_angular[i+1] += getJointVel(i) * links[i].axis_top; + vel_bottom_linear[i+1] += getJointVel(i) * links[i].axis_bottom; + + // calculate zhat_i^A + zero_acc_top_angular[i+1] = - (rot_from_world[i+1] * (links[i].applied_force)); + zero_acc_top_angular[i+1] += links[i].mass * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR*vel_bottom_linear[i+1].norm()) * vel_bottom_linear[i+1]; + + zero_acc_bottom_linear[i+1] = + - (rot_from_world[i+1] * links[i].applied_torque); + if (m_useGyroTerm) + { + zero_acc_bottom_linear[i+1] += vel_top_angular[i+1].cross( links[i].inertia * vel_top_angular[i+1] ); + } + + zero_acc_bottom_linear[i+1] += links[i].inertia * vel_top_angular[i+1] * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR*vel_top_angular[i+1].norm()); + + // calculate Ihat_i^A + inertia_top_left[i+1] = btMatrix3x3(0,0,0,0,0,0,0,0,0);//::Zero(); + inertia_top_right[i+1].setValue(links[i].mass, 0, 0, + 0, links[i].mass, 0, + 0, 0, links[i].mass); + inertia_bottom_left[i+1].setValue(links[i].inertia[0], 0, 0, + 0, links[i].inertia[1], 0, + 0, 0, links[i].inertia[2]); + } + + + // 'Downward' loop. + // (part of TreeForwardDynamics in Mirtich.) + for (int i = num_links - 1; i >= 0; --i) { + + h_top[i] = inertia_top_left[i+1] * links[i].axis_top + inertia_top_right[i+1] * links[i].axis_bottom; + h_bottom[i] = inertia_bottom_left[i+1] * links[i].axis_top + inertia_top_left[i+1].transpose() * links[i].axis_bottom; + btScalar val = SpatialDotProduct(links[i].axis_top, links[i].axis_bottom, h_top[i], h_bottom[i]); + D[i] = val; + Y[i] = links[i].joint_torque + - SpatialDotProduct(links[i].axis_top, links[i].axis_bottom, zero_acc_top_angular[i+1], zero_acc_bottom_linear[i+1]) + - SpatialDotProduct(h_top[i], h_bottom[i], coriolis_top_angular[i], coriolis_bottom_linear[i]); + + const int parent = links[i].parent; + + + // Ip += pXi * (Ii - hi hi' / Di) * iXp + const btScalar one_over_di = 1.0f / D[i]; + + + + + const btMatrix3x3 TL = inertia_top_left[i+1] - vecMulVecTranspose(one_over_di * h_top[i] , h_bottom[i]); + const btMatrix3x3 TR = inertia_top_right[i+1] - vecMulVecTranspose(one_over_di * h_top[i] , h_top[i]); + const btMatrix3x3 BL = inertia_bottom_left[i+1]- vecMulVecTranspose(one_over_di * h_bottom[i] , h_bottom[i]); + + + btMatrix3x3 r_cross; + r_cross.setValue( + 0, -links[i].cached_r_vector[2], links[i].cached_r_vector[1], + links[i].cached_r_vector[2], 0, -links[i].cached_r_vector[0], + -links[i].cached_r_vector[1], links[i].cached_r_vector[0], 0); + + inertia_top_left[parent+1] += rot_from_parent[i+1].transpose() * ( TL - TR * r_cross ) * rot_from_parent[i+1]; + inertia_top_right[parent+1] += rot_from_parent[i+1].transpose() * TR * rot_from_parent[i+1]; + inertia_bottom_left[parent+1] += rot_from_parent[i+1].transpose() * + (r_cross * (TL - TR * r_cross) + BL - TL.transpose() * r_cross) * rot_from_parent[i+1]; + + + // Zp += pXi * (Zi + Ii*ci + hi*Yi/Di) + btVector3 in_top, in_bottom, out_top, out_bottom; + const btScalar Y_over_D = Y[i] * one_over_di; + in_top = zero_acc_top_angular[i+1] + + inertia_top_left[i+1] * coriolis_top_angular[i] + + inertia_top_right[i+1] * coriolis_bottom_linear[i] + + Y_over_D * h_top[i]; + in_bottom = zero_acc_bottom_linear[i+1] + + inertia_bottom_left[i+1] * coriolis_top_angular[i] + + inertia_top_left[i+1].transpose() * coriolis_bottom_linear[i] + + Y_over_D * h_bottom[i]; + InverseSpatialTransform(rot_from_parent[i+1], links[i].cached_r_vector, + in_top, in_bottom, out_top, out_bottom); + zero_acc_top_angular[parent+1] += out_top; + zero_acc_bottom_linear[parent+1] += out_bottom; + } + + + // Second 'upward' loop + // (part of TreeForwardDynamics in Mirtich) + + if (fixed_base) + { + accel_top[0] = accel_bottom[0] = btVector3(0,0,0); + } + else + { + if (num_links > 0) + { + //Matrix Imatrix; + //Imatrix.block<3,3>(0,0) = inertia_top_left[0]; + //Imatrix.block<3,3>(3,0) = inertia_bottom_left[0]; + //Imatrix.block<3,3>(0,3) = inertia_top_right[0]; + //Imatrix.block<3,3>(3,3) = inertia_top_left[0].transpose(); + //cached_imatrix_lu.reset(new Eigen::LU >(Imatrix)); // TODO: Avoid memory allocation here? + + cached_inertia_top_left = inertia_top_left[0]; + cached_inertia_top_right = inertia_top_right[0]; + cached_inertia_lower_left = inertia_bottom_left[0]; + cached_inertia_lower_right= inertia_top_left[0].transpose(); + + } + btVector3 rhs_top (zero_acc_top_angular[0][0], zero_acc_top_angular[0][1], zero_acc_top_angular[0][2]); + btVector3 rhs_bot (zero_acc_bottom_linear[0][0], zero_acc_bottom_linear[0][1], zero_acc_bottom_linear[0][2]); + float result[6]; + + solveImatrix(rhs_top, rhs_bot, result); +// printf("result=%f,%f,%f,%f,%f,%f\n",result[0],result[0],result[0],result[0],result[0],result[0]); + for (int i = 0; i < 3; ++i) { + accel_top[0][i] = -result[i]; + accel_bottom[0][i] = -result[i+3]; + } + + } + + // now do the loop over the links + for (int i = 0; i < num_links; ++i) { + const int parent = links[i].parent; + SpatialTransform(rot_from_parent[i+1], links[i].cached_r_vector, + accel_top[parent+1], accel_bottom[parent+1], + accel_top[i+1], accel_bottom[i+1]); + joint_accel[i] = (Y[i] - SpatialDotProduct(h_top[i], h_bottom[i], accel_top[i+1], accel_bottom[i+1])) / D[i]; + accel_top[i+1] += coriolis_top_angular[i] + joint_accel[i] * links[i].axis_top; + accel_bottom[i+1] += coriolis_bottom_linear[i] + joint_accel[i] * links[i].axis_bottom; + } + + // transform base accelerations back to the world frame. + btVector3 omegadot_out = rot_from_parent[0].transpose() * accel_top[0]; + output[0] = omegadot_out[0]; + output[1] = omegadot_out[1]; + output[2] = omegadot_out[2]; + + btVector3 vdot_out = rot_from_parent[0].transpose() * accel_bottom[0]; + output[3] = vdot_out[0]; + output[4] = vdot_out[1]; + output[5] = vdot_out[2]; + // Final step: add the accelerations (times dt) to the velocities. + applyDeltaVee(output, dt); + + +} + + + +void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const +{ + int num_links = getNumLinks(); + ///solve I * x = rhs, so the result = invI * rhs + if (num_links == 0) + { + // in the case of 0 links (i.e. a plain rigid body, not a multibody) rhs * invI is easier + result[0] = rhs_bot[0] / base_inertia[0]; + result[1] = rhs_bot[1] / base_inertia[1]; + result[2] = rhs_bot[2] / base_inertia[2]; + result[3] = rhs_top[0] / base_mass; + result[4] = rhs_top[1] / base_mass; + result[5] = rhs_top[2] / base_mass; + } else + { + /// Special routine for calculating the inverse of a spatial inertia matrix + ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices + btMatrix3x3 Binv = cached_inertia_top_right.inverse()*-1.f; + btMatrix3x3 tmp = cached_inertia_lower_right * Binv; + btMatrix3x3 invIupper_right = (tmp * cached_inertia_top_left + cached_inertia_lower_left).inverse(); + tmp = invIupper_right * cached_inertia_lower_right; + btMatrix3x3 invI_upper_left = (tmp * Binv); + btMatrix3x3 invI_lower_right = (invI_upper_left).transpose(); + tmp = cached_inertia_top_left * invI_upper_left; + tmp[0][0]-= 1.0; + tmp[1][1]-= 1.0; + tmp[2][2]-= 1.0; + btMatrix3x3 invI_lower_left = (Binv * tmp); + + //multiply result = invI * rhs + { + btVector3 vtop = invI_upper_left*rhs_top; + btVector3 tmp; + tmp = invIupper_right * rhs_bot; + vtop += tmp; + btVector3 vbot = invI_lower_left*rhs_top; + tmp = invI_lower_right * rhs_bot; + vbot += tmp; + result[0] = vtop[0]; + result[1] = vtop[1]; + result[2] = vtop[2]; + result[3] = vbot[0]; + result[4] = vbot[1]; + result[5] = vbot[2]; + } + + } +} + + +void btMultiBody::calcAccelerationDeltas(const btScalar *force, btScalar *output, + btAlignedObjectArray &scratch_r, btAlignedObjectArray &scratch_v) const +{ + // Temporary matrices/vectors -- use scratch space from caller + // so that we don't have to keep reallocating every frame + int num_links = getNumLinks(); + scratch_r.resize(num_links); + scratch_v.resize(4*num_links + 4); + + btScalar * r_ptr = num_links == 0 ? 0 : &scratch_r[0]; + btVector3 * v_ptr = &scratch_v[0]; + + // zhat_i^A (scratch space) + btVector3 * zero_acc_top_angular = v_ptr; v_ptr += num_links + 1; + btVector3 * zero_acc_bottom_linear = v_ptr; v_ptr += num_links + 1; + + // rot_from_parent (cached from calcAccelerations) + const btMatrix3x3 * rot_from_parent = &matrix_buf[0]; + + // hhat (cached), accel (scratch) + const btVector3 * h_top = num_links > 0 ? &vector_buf[0] : 0; + const btVector3 * h_bottom = num_links > 0 ? &vector_buf[num_links] : 0; + btVector3 * accel_top = v_ptr; v_ptr += num_links + 1; + btVector3 * accel_bottom = v_ptr; v_ptr += num_links + 1; + + // Y_i (scratch), D_i (cached) + btScalar * Y = r_ptr; r_ptr += num_links; + const btScalar * D = num_links > 0 ? &m_real_buf[6 + num_links] : 0; + + btAssert(num_links == 0 || r_ptr - &scratch_r[0] == scratch_r.size()); + btAssert(v_ptr - &scratch_v[0] == scratch_v.size()); + + + + // First 'upward' loop. + // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich. + + btVector3 input_force(force[3],force[4],force[5]); + btVector3 input_torque(force[0],force[1],force[2]); + + // Fill in zero_acc + // -- set to force/torque on the base, zero otherwise + if (fixed_base) + { + zero_acc_top_angular[0] = zero_acc_bottom_linear[0] = btVector3(0,0,0); + } else + { + zero_acc_top_angular[0] = - (rot_from_parent[0] * input_force); + zero_acc_bottom_linear[0] = - (rot_from_parent[0] * input_torque); + } + for (int i = 0; i < num_links; ++i) + { + zero_acc_top_angular[i+1] = zero_acc_bottom_linear[i+1] = btVector3(0,0,0); + } + + // 'Downward' loop. + for (int i = num_links - 1; i >= 0; --i) + { + + Y[i] = - SpatialDotProduct(links[i].axis_top, links[i].axis_bottom, zero_acc_top_angular[i+1], zero_acc_bottom_linear[i+1]); + Y[i] += force[6 + i]; // add joint torque + + const int parent = links[i].parent; + + // Zp += pXi * (Zi + hi*Yi/Di) + btVector3 in_top, in_bottom, out_top, out_bottom; + const btScalar Y_over_D = Y[i] / D[i]; + in_top = zero_acc_top_angular[i+1] + Y_over_D * h_top[i]; + in_bottom = zero_acc_bottom_linear[i+1] + Y_over_D * h_bottom[i]; + InverseSpatialTransform(rot_from_parent[i+1], links[i].cached_r_vector, + in_top, in_bottom, out_top, out_bottom); + zero_acc_top_angular[parent+1] += out_top; + zero_acc_bottom_linear[parent+1] += out_bottom; + } + + // ptr to the joint accel part of the output + btScalar * joint_accel = output + 6; + + // Second 'upward' loop + if (fixed_base) + { + accel_top[0] = accel_bottom[0] = btVector3(0,0,0); + } else + { + btVector3 rhs_top (zero_acc_top_angular[0][0], zero_acc_top_angular[0][1], zero_acc_top_angular[0][2]); + btVector3 rhs_bot (zero_acc_bottom_linear[0][0], zero_acc_bottom_linear[0][1], zero_acc_bottom_linear[0][2]); + + float result[6]; + solveImatrix(rhs_top,rhs_bot, result); + // printf("result=%f,%f,%f,%f,%f,%f\n",result[0],result[0],result[0],result[0],result[0],result[0]); + + for (int i = 0; i < 3; ++i) { + accel_top[0][i] = -result[i]; + accel_bottom[0][i] = -result[i+3]; + } + + } + + // now do the loop over the links + for (int i = 0; i < num_links; ++i) { + const int parent = links[i].parent; + SpatialTransform(rot_from_parent[i+1], links[i].cached_r_vector, + accel_top[parent+1], accel_bottom[parent+1], + accel_top[i+1], accel_bottom[i+1]); + joint_accel[i] = (Y[i] - SpatialDotProduct(h_top[i], h_bottom[i], accel_top[i+1], accel_bottom[i+1])) / D[i]; + accel_top[i+1] += joint_accel[i] * links[i].axis_top; + accel_bottom[i+1] += joint_accel[i] * links[i].axis_bottom; + } + + // transform base accelerations back to the world frame. + btVector3 omegadot_out; + omegadot_out = rot_from_parent[0].transpose() * accel_top[0]; + output[0] = omegadot_out[0]; + output[1] = omegadot_out[1]; + output[2] = omegadot_out[2]; + + btVector3 vdot_out; + vdot_out = rot_from_parent[0].transpose() * accel_bottom[0]; + + output[3] = vdot_out[0]; + output[4] = vdot_out[1]; + output[5] = vdot_out[2]; +} + +void btMultiBody::stepPositions(btScalar dt) +{ + int num_links = getNumLinks(); + // step position by adding dt * velocity + btVector3 v = getBaseVel(); + base_pos += dt * v; + + // "exponential map" method for the rotation + btVector3 base_omega = getBaseOmega(); + const btScalar omega_norm = base_omega.norm(); + const btScalar omega_times_dt = omega_norm * dt; + const btScalar SMALL_ROTATION_ANGLE = 0.02f; // Theoretically this should be ~ pow(FLT_EPSILON,0.25) which is ~ 0.0156 + if (fabs(omega_times_dt) < SMALL_ROTATION_ANGLE) + { + const btScalar xsq = omega_times_dt * omega_times_dt; // |omega|^2 * dt^2 + const btScalar sin_term = dt * (xsq / 48.0f - 0.5f); // -sin(0.5*dt*|omega|) / |omega| + const btScalar cos_term = 1.0f - xsq / 8.0f; // cos(0.5*dt*|omega|) + base_quat = base_quat * btQuaternion(sin_term * base_omega[0],sin_term * base_omega[1],sin_term * base_omega[2],cos_term); + } else + { + base_quat = base_quat * btQuaternion(base_omega / omega_norm,-omega_times_dt); + } + + // Make sure the quaternion represents a valid rotation. + // (Not strictly necessary, but helps prevent any round-off errors from building up.) + base_quat.normalize(); + + // Finally we can update joint_pos for each of the links + for (int i = 0; i < num_links; ++i) + { + float jointVel = getJointVel(i); + links[i].joint_pos += dt * jointVel; + links[i].updateCache(); + } +} + +void btMultiBody::fillContactJacobian(int link, + const btVector3 &contact_point, + const btVector3 &normal, + btScalar *jac, + btAlignedObjectArray &scratch_r, + btAlignedObjectArray &scratch_v, + btAlignedObjectArray &scratch_m) const +{ + // temporary space + int num_links = getNumLinks(); + scratch_v.resize(2*num_links + 2); + scratch_m.resize(num_links + 1); + + btVector3 * v_ptr = &scratch_v[0]; + btVector3 * p_minus_com = v_ptr; v_ptr += num_links + 1; + btVector3 * n_local = v_ptr; v_ptr += num_links + 1; + btAssert(v_ptr - &scratch_v[0] == scratch_v.size()); + + scratch_r.resize(num_links); + btScalar * results = num_links > 0 ? &scratch_r[0] : 0; + + btMatrix3x3 * rot_from_world = &scratch_m[0]; + + const btVector3 p_minus_com_world = contact_point - base_pos; + + rot_from_world[0] = btMatrix3x3(base_quat); + + p_minus_com[0] = rot_from_world[0] * p_minus_com_world; + n_local[0] = rot_from_world[0] * normal; + + // omega coeffients first. + btVector3 omega_coeffs; + omega_coeffs = p_minus_com_world.cross(normal); + jac[0] = omega_coeffs[0]; + jac[1] = omega_coeffs[1]; + jac[2] = omega_coeffs[2]; + // then v coefficients + jac[3] = normal[0]; + jac[4] = normal[1]; + jac[5] = normal[2]; + + // Set remaining jac values to zero for now. + for (int i = 6; i < 6 + num_links; ++i) { + jac[i] = 0; + } + + // Qdot coefficients, if necessary. + if (num_links > 0 && link > -1) { + + // TODO: speed this up -- don't calculate for links we don't need. + // (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions, + // which is resulting in repeated work being done...) + + // calculate required normals & positions in the local frames. + for (int i = 0; i < num_links; ++i) { + + // transform to local frame + const int parent = links[i].parent; + const btMatrix3x3 mtx(links[i].cached_rot_parent_to_this); + rot_from_world[i+1] = mtx * rot_from_world[parent+1]; + + n_local[i+1] = mtx * n_local[parent+1]; + p_minus_com[i+1] = mtx * p_minus_com[parent+1] - links[i].cached_r_vector; + + // calculate the jacobian entry + if (links[i].is_revolute) { + results[i] = n_local[i+1].dot( links[i].axis_top.cross(p_minus_com[i+1]) + links[i].axis_bottom ); + } else { + results[i] = n_local[i+1].dot( links[i].axis_bottom ); + } + } + + // Now copy through to output. + while (link != -1) { + jac[6 + link] = results[link]; + link = links[link].parent; + } + } +} + +void btMultiBody::wakeUp() +{ + awake = true; +} + +void btMultiBody::goToSleep() +{ + awake = false; +} + +void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep) +{ + int num_links = getNumLinks(); + extern bool gDisableDeactivation; + if (!can_sleep || gDisableDeactivation) + { + awake = true; + sleep_timer = 0; + return; + } + + // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities) + btScalar motion = 0; + for (int i = 0; i < 6 + num_links; ++i) { + motion += m_real_buf[i] * m_real_buf[i]; + } + + if (motion < SLEEP_EPSILON) { + sleep_timer += timestep; + if (sleep_timer > SLEEP_TIMEOUT) { + goToSleep(); + } + } else { + sleep_timer = 0; + if (!awake) + wakeUp(); + } +} diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.h new file mode 100644 index 00000000..7177bebb --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.h @@ -0,0 +1,466 @@ +/* + * PURPOSE: + * Class representing an articulated rigid body. Stores the body's + * current state, allows forces and torques to be set, handles + * timestepping and implements Featherstone's algorithm. + * + * COPYRIGHT: + * Copyright (C) Stephen Thompson, , 2011-2013 + * Portions written By Erwin Coumans: replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix) + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it freely, + subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + */ + + +#ifndef BT_MULTIBODY_H +#define BT_MULTIBODY_H + +#include "LinearMath/btScalar.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAlignedObjectArray.h" + + +#include "btMultiBodyLink.h" +class btMultiBodyLinkCollider; + +class btMultiBody +{ +public: + + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + // + // initialization + // + + btMultiBody(int n_links, // NOT including the base + btScalar mass, // mass of base + const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal + bool fixed_base_, // whether the base is fixed (true) or can move (false) + bool can_sleep_); + + ~btMultiBody(); + + void setupPrismatic(int i, // 0 to num_links-1 + btScalar mass, + const btVector3 &inertia, // in my frame; assumed diagonal + int parent, + const btQuaternion &rot_parent_to_this, // rotate points in parent frame to my frame. + const btVector3 &joint_axis, // in my frame + const btVector3 &r_vector_when_q_zero, // vector from parent COM to my COM, in my frame, when q = 0. + bool disableParentCollision=false + ); + + void setupRevolute(int i, // 0 to num_links-1 + btScalar mass, + const btVector3 &inertia, + int parent, + const btQuaternion &zero_rot_parent_to_this, // rotate points in parent frame to this frame, when q = 0 + const btVector3 &joint_axis, // in my frame + const btVector3 &parent_axis_position, // vector from parent COM to joint axis, in PARENT frame + const btVector3 &my_axis_position, // vector from joint axis to my COM, in MY frame + bool disableParentCollision=false); + + const btMultibodyLink& getLink(int index) const + { + return links[index]; + } + + btMultibodyLink& getLink(int index) + { + return links[index]; + } + + + void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base + { + m_baseCollider = collider; + } + const btMultiBodyLinkCollider* getBaseCollider() const + { + return m_baseCollider; + } + btMultiBodyLinkCollider* getBaseCollider() + { + return m_baseCollider; + } + + // + // get parent + // input: link num from 0 to num_links-1 + // output: link num from 0 to num_links-1, OR -1 to mean the base. + // + int getParent(int link_num) const; + + + // + // get number of links, masses, moments of inertia + // + + int getNumLinks() const { return links.size(); } + btScalar getBaseMass() const { return base_mass; } + const btVector3 & getBaseInertia() const { return base_inertia; } + btScalar getLinkMass(int i) const; + const btVector3 & getLinkInertia(int i) const; + + + // + // change mass (incomplete: can only change base mass and inertia at present) + // + + void setBaseMass(btScalar mass) { base_mass = mass; } + void setBaseInertia(const btVector3 &inertia) { base_inertia = inertia; } + + + // + // get/set pos/vel/rot/omega for the base link + // + + const btVector3 & getBasePos() const { return base_pos; } // in world frame + const btVector3 getBaseVel() const + { + return btVector3(m_real_buf[3],m_real_buf[4],m_real_buf[5]); + } // in world frame + const btQuaternion & getWorldToBaseRot() const + { + return base_quat; + } // rotates world vectors into base frame + btVector3 getBaseOmega() const { return btVector3(m_real_buf[0],m_real_buf[1],m_real_buf[2]); } // in world frame + + void setBasePos(const btVector3 &pos) + { + base_pos = pos; + } + void setBaseVel(const btVector3 &vel) + { + + m_real_buf[3]=vel[0]; m_real_buf[4]=vel[1]; m_real_buf[5]=vel[2]; + } + void setWorldToBaseRot(const btQuaternion &rot) + { + base_quat = rot; + } + void setBaseOmega(const btVector3 &omega) + { + m_real_buf[0]=omega[0]; + m_real_buf[1]=omega[1]; + m_real_buf[2]=omega[2]; + } + + + // + // get/set pos/vel for child links (i = 0 to num_links-1) + // + + btScalar getJointPos(int i) const; + btScalar getJointVel(int i) const; + + void setJointPos(int i, btScalar q); + void setJointVel(int i, btScalar qdot); + + // + // direct access to velocities as a vector of 6 + num_links elements. + // (omega first, then v, then joint velocities.) + // + const btScalar * getVelocityVector() const + { + return &m_real_buf[0]; + } +/* btScalar * getVelocityVector() + { + return &real_buf[0]; + } + */ + + // + // get the frames of reference (positions and orientations) of the child links + // (i = 0 to num_links-1) + // + + const btVector3 & getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords + const btQuaternion & getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i. + + + // + // transform vectors in local frame of link i to world frame (or vice versa) + // + btVector3 localPosToWorld(int i, const btVector3 &vec) const; + btVector3 localDirToWorld(int i, const btVector3 &vec) const; + btVector3 worldPosToLocal(int i, const btVector3 &vec) const; + btVector3 worldDirToLocal(int i, const btVector3 &vec) const; + + + // + // calculate kinetic energy and angular momentum + // useful for debugging. + // + + btScalar getKineticEnergy() const; + btVector3 getAngularMomentum() const; + + + // + // set external forces and torques. Note all external forces/torques are given in the WORLD frame. + // + + void clearForcesAndTorques(); + void clearVelocities(); + + void addBaseForce(const btVector3 &f) + { + base_force += f; + } + void addBaseTorque(const btVector3 &t) { base_torque += t; } + void addLinkForce(int i, const btVector3 &f); + void addLinkTorque(int i, const btVector3 &t); + void addJointTorque(int i, btScalar Q); + + const btVector3 & getBaseForce() const { return base_force; } + const btVector3 & getBaseTorque() const { return base_torque; } + const btVector3 & getLinkForce(int i) const; + const btVector3 & getLinkTorque(int i) const; + btScalar getJointTorque(int i) const; + + + // + // dynamics routines. + // + + // timestep the velocities (given the external forces/torques set using addBaseForce etc). + // also sets up caches for calcAccelerationDeltas. + // + // Note: the caller must provide three vectors which are used as + // temporary scratch space. The idea here is to reduce dynamic + // memory allocation: the same scratch vectors can be re-used + // again and again for different Multibodies, instead of each + // btMultiBody allocating (and then deallocating) their own + // individual scratch buffers. This gives a considerable speed + // improvement, at least on Windows (where dynamic memory + // allocation appears to be fairly slow). + // + void stepVelocities(btScalar dt, + btAlignedObjectArray &scratch_r, + btAlignedObjectArray &scratch_v, + btAlignedObjectArray &scratch_m); + + // calcAccelerationDeltas + // input: force vector (in same format as jacobian, i.e.: + // 3 torque values, 3 force values, num_links joint torque values) + // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values + // (existing contents of output array are replaced) + // stepVelocities must have been called first. + void calcAccelerationDeltas(const btScalar *force, btScalar *output, + btAlignedObjectArray &scratch_r, + btAlignedObjectArray &scratch_v) const; + + // apply a delta-vee directly. used in sequential impulses code. + void applyDeltaVee(const btScalar * delta_vee) + { + + for (int i = 0; i < 6 + getNumLinks(); ++i) + { + m_real_buf[i] += delta_vee[i]; + } + + } + void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier) + { + btScalar sum = 0; + for (int i = 0; i < 6 + getNumLinks(); ++i) + { + sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier; + } + btScalar l = btSqrt(sum); + /* + static btScalar maxl = -1e30f; + if (l>maxl) + { + maxl=l; + // printf("maxl=%f\n",maxl); + } + */ + if (l>m_maxAppliedImpulse) + { +// printf("exceeds 100: l=%f\n",maxl); + multiplier *= m_maxAppliedImpulse/l; + } + + for (int i = 0; i < 6 + getNumLinks(); ++i) + { + sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier; + m_real_buf[i] += delta_vee[i] * multiplier; + } + } + + // timestep the positions (given current velocities). + void stepPositions(btScalar dt); + + + // + // contacts + // + + // This routine fills out a contact constraint jacobian for this body. + // the 'normal' supplied must be -n for body1 or +n for body2 of the contact. + // 'normal' & 'contact_point' are both given in world coordinates. + void fillContactJacobian(int link, + const btVector3 &contact_point, + const btVector3 &normal, + btScalar *jac, + btAlignedObjectArray &scratch_r, + btAlignedObjectArray &scratch_v, + btAlignedObjectArray &scratch_m) const; + + + // + // sleeping + // + void setCanSleep(bool canSleep) + { + can_sleep = canSleep; + } + + bool isAwake() const { return awake; } + void wakeUp(); + void goToSleep(); + void checkMotionAndSleepIfRequired(btScalar timestep); + + bool hasFixedBase() const + { + return fixed_base; + } + + int getCompanionId() const + { + return m_companionId; + } + void setCompanionId(int id) + { + //printf("for %p setCompanionId(%d)\n",this, id); + m_companionId = id; + } + + void setNumLinks(int numLinks)//careful: when changing the number of links, make sure to re-initialize or update existing links + { + links.resize(numLinks); + } + + btScalar getLinearDamping() const + { + return m_linearDamping; + } + void setLinearDamping( btScalar damp) + { + m_linearDamping = damp; + } + btScalar getAngularDamping() const + { + return m_angularDamping; + } + + bool getUseGyroTerm() const + { + return m_useGyroTerm; + } + void setUseGyroTerm(bool useGyro) + { + m_useGyroTerm = useGyro; + } + btScalar getMaxAppliedImpulse() const + { + return m_maxAppliedImpulse; + } + void setMaxAppliedImpulse(btScalar maxImp) + { + m_maxAppliedImpulse = maxImp; + } + + void setHasSelfCollision(bool hasSelfCollision) + { + m_hasSelfCollision = hasSelfCollision; + } + bool hasSelfCollision() const + { + return m_hasSelfCollision; + } + +private: + btMultiBody(const btMultiBody &); // not implemented + void operator=(const btMultiBody &); // not implemented + + void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const; + + void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const; + + +private: + + btMultiBodyLinkCollider* m_baseCollider;//can be NULL + + btVector3 base_pos; // position of COM of base (world frame) + btQuaternion base_quat; // rotates world points into base frame + + btScalar base_mass; // mass of the base + btVector3 base_inertia; // inertia of the base (in local frame; diagonal) + + btVector3 base_force; // external force applied to base. World frame. + btVector3 base_torque; // external torque applied to base. World frame. + + btAlignedObjectArray links; // array of links, excluding the base. index from 0 to num_links-1. + btAlignedObjectArray m_colliders; + + // + // real_buf: + // offset size array + // 0 6 + num_links v (base_omega; base_vel; joint_vels) + // 6+num_links num_links D + // + // vector_buf: + // offset size array + // 0 num_links h_top + // num_links num_links h_bottom + // + // matrix_buf: + // offset size array + // 0 num_links+1 rot_from_parent + // + + btAlignedObjectArray m_real_buf; + btAlignedObjectArray vector_buf; + btAlignedObjectArray matrix_buf; + + //std::auto_ptr > > cached_imatrix_lu; + + btMatrix3x3 cached_inertia_top_left; + btMatrix3x3 cached_inertia_top_right; + btMatrix3x3 cached_inertia_lower_left; + btMatrix3x3 cached_inertia_lower_right; + + bool fixed_base; + + // Sleep parameters. + bool awake; + bool can_sleep; + btScalar sleep_timer; + + int m_companionId; + btScalar m_linearDamping; + btScalar m_angularDamping; + bool m_useGyroTerm; + btScalar m_maxAppliedImpulse; + bool m_hasSelfCollision; +}; + +#endif diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp new file mode 100644 index 00000000..44e04c3a --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp @@ -0,0 +1,527 @@ +#include "btMultiBodyConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +btMultiBodyConstraint::btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral) + :m_bodyA(bodyA), + m_bodyB(bodyB), + m_linkA(linkA), + m_linkB(linkB), + m_num_rows(numRows), + m_isUnilateral(isUnilateral), + m_maxAppliedImpulse(100) +{ + m_jac_size_A = (6 + bodyA->getNumLinks()); + m_jac_size_both = (m_jac_size_A + (bodyB ? 6 + bodyB->getNumLinks() : 0)); + m_pos_offset = ((1 + m_jac_size_both)*m_num_rows); + m_data.resize((2 + m_jac_size_both) * m_num_rows); +} + +btMultiBodyConstraint::~btMultiBodyConstraint() +{ +} + + + +btScalar btMultiBodyConstraint::fillConstraintRowMultiBodyMultiBody(btMultiBodySolverConstraint& constraintRow, + btMultiBodyJacobianData& data, + btScalar* jacOrgA,btScalar* jacOrgB, + const btContactSolverInfo& infoGlobal, + btScalar desiredVelocity, + btScalar lowerLimit, + btScalar upperLimit) +{ + + + + constraintRow.m_multiBodyA = m_bodyA; + constraintRow.m_multiBodyB = m_bodyB; + + btMultiBody* multiBodyA = constraintRow.m_multiBodyA; + btMultiBody* multiBodyB = constraintRow.m_multiBodyB; + + if (multiBodyA) + { + + const int ndofA = multiBodyA->getNumLinks() + 6; + + constraintRow.m_deltaVelAindex = multiBodyA->getCompanionId(); + + if (constraintRow.m_deltaVelAindex <0) + { + constraintRow.m_deltaVelAindex = data.m_deltaVelocities.size(); + multiBodyA->setCompanionId(constraintRow.m_deltaVelAindex); + data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofA); + } else + { + btAssert(data.m_deltaVelocities.size() >= constraintRow.m_deltaVelAindex+ndofA); + } + + constraintRow.m_jacAindex = data.m_jacobians.size(); + data.m_jacobians.resize(data.m_jacobians.size()+ndofA); + data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofA); + btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); + for (int i=0;icalcAccelerationDeltas(&data.m_jacobians[constraintRow.m_jacAindex],delta,data.scratch_r, data.scratch_v); + } + + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumLinks() + 6; + + constraintRow.m_deltaVelBindex = multiBodyB->getCompanionId(); + if (constraintRow.m_deltaVelBindex <0) + { + constraintRow.m_deltaVelBindex = data.m_deltaVelocities.size(); + multiBodyB->setCompanionId(constraintRow.m_deltaVelBindex); + data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofB); + } + + constraintRow.m_jacBindex = data.m_jacobians.size(); + data.m_jacobians.resize(data.m_jacobians.size()+ndofB); + + for (int i=0;icalcAccelerationDeltas(&data.m_jacobians[constraintRow.m_jacBindex],&data.m_deltaVelocitiesUnitImpulse[constraintRow.m_jacBindex],data.scratch_r, data.scratch_v); + } + { + + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + btScalar* jacB = 0; + btScalar* jacA = 0; + btScalar* lambdaA =0; + btScalar* lambdaB =0; + int ndofA = 0; + if (multiBodyA) + { + ndofA = multiBodyA->getNumLinks() + 6; + jacA = &data.m_jacobians[constraintRow.m_jacAindex]; + lambdaA = &data.m_deltaVelocitiesUnitImpulse[constraintRow.m_jacAindex]; + for (int i = 0; i < ndofA; ++i) + { + btScalar j = jacA[i] ; + btScalar l =lambdaA[i]; + denom0 += j*l; + } + } + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumLinks() + 6; + jacB = &data.m_jacobians[constraintRow.m_jacBindex]; + lambdaB = &data.m_deltaVelocitiesUnitImpulse[constraintRow.m_jacBindex]; + for (int i = 0; i < ndofB; ++i) + { + btScalar j = jacB[i] ; + btScalar l =lambdaB[i]; + denom1 += j*l; + } + + } + + if (multiBodyA && (multiBodyA==multiBodyB)) + { + // ndof1 == ndof2 in this case + for (int i = 0; i < ndofA; ++i) + { + denom1 += jacB[i] * lambdaA[i]; + denom1 += jacA[i] * lambdaB[i]; + } + } + + btScalar d = denom0+denom1; + if (btFabs(d)>SIMD_EPSILON) + { + + constraintRow.m_jacDiagABInv = 1.f/(d); + } else + { + constraintRow.m_jacDiagABInv = 1.f; + } + + } + + + //compute rhs and remaining constraintRow fields + + + + + btScalar rel_vel = 0.f; + int ndofA = 0; + int ndofB = 0; + { + + btVector3 vel1,vel2; + if (multiBodyA) + { + ndofA = multiBodyA->getNumLinks() + 6; + btScalar* jacA = &data.m_jacobians[constraintRow.m_jacAindex]; + for (int i = 0; i < ndofA ; ++i) + rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; + } + if (multiBodyB) + { + ndofB = multiBodyB->getNumLinks() + 6; + btScalar* jacB = &data.m_jacobians[constraintRow.m_jacBindex]; + for (int i = 0; i < ndofB ; ++i) + rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; + + } + + constraintRow.m_friction = 0.f; + + constraintRow.m_appliedImpulse = 0.f; + constraintRow.m_appliedPushImpulse = 0.f; + + btScalar velocityError = desiredVelocity - rel_vel;// * damping; + + btScalar erp = infoGlobal.m_erp2; + + btScalar velocityImpulse = velocityError *constraintRow.m_jacDiagABInv; + + if (!infoGlobal.m_splitImpulse) + { + //combine position and velocity into rhs + constraintRow.m_rhs = velocityImpulse; + constraintRow.m_rhsPenetration = 0.f; + + } else + { + //split position and velocity into rhs and m_rhsPenetration + constraintRow.m_rhs = velocityImpulse; + constraintRow.m_rhsPenetration = 0.f; + } + + + constraintRow.m_cfm = 0.f; + constraintRow.m_lowerLimit = lowerLimit; + constraintRow.m_upperLimit = upperLimit; + + } + return rel_vel; +} + + +void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof) +{ + for (int i = 0; i < ndof; ++i) + data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse; +} + + +void btMultiBodyConstraint::fillMultiBodyConstraintMixed(btMultiBodySolverConstraint& solverConstraint, + btMultiBodyJacobianData& data, + const btVector3& contactNormalOnB, + const btVector3& posAworld, const btVector3& posBworld, + btScalar position, + const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + bool isFriction, btScalar desiredVelocity, btScalar cfmSlip) +{ + + + btVector3 rel_pos1 = posAworld; + btVector3 rel_pos2 = posBworld; + + solverConstraint.m_multiBodyA = m_bodyA; + solverConstraint.m_multiBodyB = m_bodyB; + solverConstraint.m_linkA = m_linkA; + solverConstraint.m_linkB = m_linkB; + + + btMultiBody* multiBodyA = solverConstraint.m_multiBodyA; + btMultiBody* multiBodyB = solverConstraint.m_multiBodyB; + + const btVector3& pos1 = posAworld; + const btVector3& pos2 = posBworld; + + btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA); + btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB); + + btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody; + btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody; + + if (bodyA) + rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); + if (bodyB) + rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); + + relaxation = 1.f; + + if (multiBodyA) + { + const int ndofA = multiBodyA->getNumLinks() + 6; + + solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId(); + + if (solverConstraint.m_deltaVelAindex <0) + { + solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size(); + multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex); + data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofA); + } else + { + btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA); + } + + solverConstraint.m_jacAindex = data.m_jacobians.size(); + data.m_jacobians.resize(data.m_jacobians.size()+ndofA); + data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofA); + btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); + + btScalar* jac1=&data.m_jacobians[solverConstraint.m_jacAindex]; + multiBodyA->fillContactJacobian(solverConstraint.m_linkA, posAworld, contactNormalOnB, jac1, data.scratch_r, data.scratch_v, data.scratch_m); + btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + multiBodyA->calcAccelerationDeltas(&data.m_jacobians[solverConstraint.m_jacAindex],delta,data.scratch_r, data.scratch_v); + } else + { + btVector3 torqueAxis0 = rel_pos1.cross(contactNormalOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + solverConstraint.m_contactNormal1 = contactNormalOnB; + } + + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumLinks() + 6; + + solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId(); + if (solverConstraint.m_deltaVelBindex <0) + { + solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size(); + multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex); + data.m_deltaVelocities.resize(data.m_deltaVelocities.size()+ndofB); + } + + solverConstraint.m_jacBindex = data.m_jacobians.size(); + + data.m_jacobians.resize(data.m_jacobians.size()+ndofB); + data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size()+ndofB); + btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size()); + + multiBodyB->fillContactJacobian(solverConstraint.m_linkB, posBworld, -contactNormalOnB, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m); + multiBodyB->calcAccelerationDeltas(&data.m_jacobians[solverConstraint.m_jacBindex],&data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],data.scratch_r, data.scratch_v); + } else + { + btVector3 torqueAxis1 = rel_pos2.cross(contactNormalOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + solverConstraint.m_contactNormal2 = -contactNormalOnB; + } + + { + + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + btScalar* jacB = 0; + btScalar* jacA = 0; + btScalar* lambdaA =0; + btScalar* lambdaB =0; + int ndofA = 0; + if (multiBodyA) + { + ndofA = multiBodyA->getNumLinks() + 6; + jacA = &data.m_jacobians[solverConstraint.m_jacAindex]; + lambdaA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA; ++i) + { + btScalar j = jacA[i] ; + btScalar l =lambdaA[i]; + denom0 += j*l; + } + } else + { + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + contactNormalOnB.dot(vec); + } + } + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumLinks() + 6; + jacB = &data.m_jacobians[solverConstraint.m_jacBindex]; + lambdaB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB; ++i) + { + btScalar j = jacB[i] ; + btScalar l =lambdaB[i]; + denom1 += j*l; + } + + } else + { + if (rb1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + contactNormalOnB.dot(vec); + } + } + + if (multiBodyA && (multiBodyA==multiBodyB)) + { + // ndof1 == ndof2 in this case + for (int i = 0; i < ndofA; ++i) + { + denom1 += jacB[i] * lambdaA[i]; + denom1 += jacA[i] * lambdaB[i]; + } + } + + btScalar d = denom0+denom1; + if (btFabs(d)>SIMD_EPSILON) + { + + solverConstraint.m_jacDiagABInv = relaxation/(d); + } else + { + solverConstraint.m_jacDiagABInv = 1.f; + } + + } + + + //compute rhs and remaining solverConstraint fields + + + + btScalar restitution = 0.f; + btScalar penetration = isFriction? 0 : position+infoGlobal.m_linearSlop; + + btScalar rel_vel = 0.f; + int ndofA = 0; + int ndofB = 0; + { + + btVector3 vel1,vel2; + if (multiBodyA) + { + ndofA = multiBodyA->getNumLinks() + 6; + btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA ; ++i) + rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; + } else + { + if (rb0) + { + rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1); + } + } + if (multiBodyB) + { + ndofB = multiBodyB->getNumLinks() + 6; + btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB ; ++i) + rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; + + } else + { + if (rb1) + { + rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2); + } + } + + solverConstraint.m_friction = 0.f;//cp.m_combinedFriction; + + + restitution = restitution * -rel_vel;//restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (restitution <= btScalar(0.)) + { + restitution = 0.f; + }; + } + + + ///warm starting (or zero if disabled) + /* + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + + if (solverConstraint.m_appliedImpulse) + { + if (multiBodyA) + { + btScalar impulse = solverConstraint.m_appliedImpulse; + btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + multiBodyA->applyDeltaVee(deltaV,impulse); + applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA); + } else + { + if (rb0) + bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + } + if (multiBodyB) + { + btScalar impulse = solverConstraint.m_appliedImpulse; + btScalar* deltaV = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + multiBodyB->applyDeltaVee(deltaV,impulse); + applyDeltaVee(data,deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB); + } else + { + if (rb1) + bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse); + } + } + } else + */ + { + solverConstraint.m_appliedImpulse = 0.f; + } + + solverConstraint.m_appliedPushImpulse = 0.f; + + { + + + btScalar positionalError = 0.f; + btScalar velocityError = restitution - rel_vel;// * damping; + + + btScalar erp = infoGlobal.m_erp2; + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + erp = infoGlobal.m_erp; + } + + if (penetration>0) + { + positionalError = 0; + velocityError = -penetration / infoGlobal.m_timeStep; + + } else + { + positionalError = -penetration * erp/infoGlobal.m_timeStep; + } + + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_rhsPenetration = 0.f; + + } else + { + //split position and velocity into rhs and m_rhsPenetration + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = penetrationImpulse; + } + + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = -m_maxAppliedImpulse; + solverConstraint.m_upperLimit = m_maxAppliedImpulse; + } + +} diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h new file mode 100644 index 00000000..9fa31733 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h @@ -0,0 +1,166 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTIBODY_CONSTRAINT_H +#define BT_MULTIBODY_CONSTRAINT_H + +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btMultiBody.h" + +class btMultiBody; +struct btSolverInfo; + +#include "btMultiBodySolverConstraint.h" + +struct btMultiBodyJacobianData +{ + btAlignedObjectArray m_jacobians; + btAlignedObjectArray m_deltaVelocitiesUnitImpulse; + btAlignedObjectArray m_deltaVelocities; + btAlignedObjectArray scratch_r; + btAlignedObjectArray scratch_v; + btAlignedObjectArray scratch_m; + btAlignedObjectArray* m_solverBodyPool; + int m_fixedBodyId; + +}; + + +class btMultiBodyConstraint +{ +protected: + + btMultiBody* m_bodyA; + btMultiBody* m_bodyB; + int m_linkA; + int m_linkB; + + int m_num_rows; + int m_jac_size_A; + int m_jac_size_both; + int m_pos_offset; + + bool m_isUnilateral; + + btScalar m_maxAppliedImpulse; + + + // data block laid out as follows: + // cached impulses. (one per row.) + // jacobians. (interleaved, row1 body1 then row1 body2 then row2 body 1 etc) + // positions. (one per row.) + btAlignedObjectArray m_data; + + void applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof); + + void fillMultiBodyConstraintMixed(btMultiBodySolverConstraint& solverConstraint, + btMultiBodyJacobianData& data, + const btVector3& contactNormalOnB, + const btVector3& posAworld, const btVector3& posBworld, + btScalar position, + const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0); + + btScalar fillConstraintRowMultiBodyMultiBody(btMultiBodySolverConstraint& constraintRow, + btMultiBodyJacobianData& data, + btScalar* jacOrgA,btScalar* jacOrgB, + const btContactSolverInfo& infoGlobal, + btScalar desiredVelocity, + btScalar lowerLimit, + btScalar upperLimit); + +public: + + btMultiBodyConstraint(btMultiBody* bodyA,btMultiBody* bodyB,int linkA, int linkB, int numRows, bool isUnilateral); + virtual ~btMultiBodyConstraint(); + + + + virtual int getIslandIdA() const =0; + virtual int getIslandIdB() const =0; + + virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal)=0; + + int getNumRows() const + { + return m_num_rows; + } + + btMultiBody* getMultiBodyA() + { + return m_bodyA; + } + btMultiBody* getMultiBodyB() + { + return m_bodyB; + } + + // current constraint position + // constraint is pos >= 0 for unilateral, or pos = 0 for bilateral + // NOTE: ignored position for friction rows. + btScalar getPosition(int row) const + { + return m_data[m_pos_offset + row]; + } + + void setPosition(int row, btScalar pos) + { + m_data[m_pos_offset + row] = pos; + } + + + bool isUnilateral() const + { + return m_isUnilateral; + } + + // jacobian blocks. + // each of size 6 + num_links. (jacobian2 is null if no body2.) + // format: 3 'omega' coefficients, 3 'v' coefficients, then the 'qdot' coefficients. + btScalar* jacobianA(int row) + { + return &m_data[m_num_rows + row * m_jac_size_both]; + } + const btScalar* jacobianA(int row) const + { + return &m_data[m_num_rows + (row * m_jac_size_both)]; + } + btScalar* jacobianB(int row) + { + return &m_data[m_num_rows + (row * m_jac_size_both) + m_jac_size_A]; + } + const btScalar* jacobianB(int row) const + { + return &m_data[m_num_rows + (row * m_jac_size_both) + m_jac_size_A]; + } + + btScalar getMaxAppliedImpulse() const + { + return m_maxAppliedImpulse; + } + void setMaxAppliedImpulse(btScalar maxImp) + { + m_maxAppliedImpulse = maxImp; + } + + +}; + +#endif //BT_MULTIBODY_CONSTRAINT_H + diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp new file mode 100644 index 00000000..577f8462 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp @@ -0,0 +1,795 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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 "btMultiBodyConstraintSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "btMultiBodyLinkCollider.h" + +#include "BulletDynamics/ConstraintSolver/btSolverBody.h" +#include "btMultiBodyConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +#include "LinearMath/btQuickprof.h" + +btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +{ + btScalar val = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + + //solve featherstone non-contact constraints + + //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size()); + for (int j=0;jm_multiBodyFrictionContactConstraints.size();j++) + { + if (iteration < infoGlobal.m_numIterations) + { + btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[j]; + btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse; + //adjust friction limits here + if (totalImpulse>btScalar(0)) + { + frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse); + frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse; + resolveSingleConstraintRowGeneric(frictionConstraint); + } + } + } + return val; +} + +btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +{ + m_multiBodyNonContactConstraints.resize(0); + m_multiBodyNormalContactConstraints.resize(0); + m_multiBodyFrictionContactConstraints.resize(0); + m_data.m_jacobians.resize(0); + m_data.m_deltaVelocitiesUnitImpulse.resize(0); + m_data.m_deltaVelocities.resize(0); + + for (int i=0;im_multiBody->setCompanionId(-1); + } + } + + btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer); + + return val; +} + +void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof) +{ + for (int i = 0; i < ndof; ++i) + m_data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse; +} + +void btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c) +{ + + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + btScalar deltaVelADotn=0; + btScalar deltaVelBDotn=0; + btSolverBody* bodyA = 0; + btSolverBody* bodyB = 0; + int ndofA=0; + int ndofB=0; + + if (c.m_multiBodyA) + { + ndofA = c.m_multiBodyA->getNumLinks() + 6; + for (int i = 0; i < ndofA; ++i) + deltaVelADotn += m_data.m_jacobians[c.m_jacAindex+i] * m_data.m_deltaVelocities[c.m_deltaVelAindex+i]; + } else + { + bodyA = &m_tmpSolverBodyPool[c.m_solverBodyIdA]; + deltaVelADotn += c.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity()); + } + + if (c.m_multiBodyB) + { + ndofB = c.m_multiBodyB->getNumLinks() + 6; + for (int i = 0; i < ndofB; ++i) + deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex+i] * m_data.m_deltaVelocities[c.m_deltaVelBindex+i]; + } else + { + bodyB = &m_tmpSolverBodyPool[c.m_solverBodyIdB]; + deltaVelBDotn += c.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity()); + } + + + deltaImpulse -= deltaVelADotn*c.m_jacDiagABInv;//m_jacDiagABInv = 1./denom + deltaImpulse -= deltaVelBDotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else if (sum > c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + + if (c.m_multiBodyA) + { + applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse,c.m_deltaVelAindex,ndofA); + c.m_multiBodyA->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse); + } else + { + bodyA->internalApplyImpulse(c.m_contactNormal1*bodyA->internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + + } + if (c.m_multiBodyB) + { + applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse,c.m_deltaVelBindex,ndofB); + c.m_multiBodyB->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse); + } else + { + bodyB->internalApplyImpulse(c.m_contactNormal2*bodyB->internalGetInvMass(),c.m_angularComponentB,deltaImpulse); + } + +} + + +void btMultiBodyConstraintSolver::resolveSingleConstraintRowGenericMultiBody(const btMultiBodySolverConstraint& c) +{ + + btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm; + btScalar deltaVelADotn=0; + btScalar deltaVelBDotn=0; + int ndofA=0; + int ndofB=0; + + if (c.m_multiBodyA) + { + ndofA = c.m_multiBodyA->getNumLinks() + 6; + for (int i = 0; i < ndofA; ++i) + deltaVelADotn += m_data.m_jacobians[c.m_jacAindex+i] * m_data.m_deltaVelocities[c.m_deltaVelAindex+i]; + } + + if (c.m_multiBodyB) + { + ndofB = c.m_multiBodyB->getNumLinks() + 6; + for (int i = 0; i < ndofB; ++i) + deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex+i] * m_data.m_deltaVelocities[c.m_deltaVelBindex+i]; + } + + + deltaImpulse -= deltaVelADotn*c.m_jacDiagABInv;//m_jacDiagABInv = 1./denom + deltaImpulse -= deltaVelBDotn*c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; + + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_lowerLimit; + } + else if (sum > c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + + if (c.m_multiBodyA) + { + applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse,c.m_deltaVelAindex,ndofA); + c.m_multiBodyA->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex],deltaImpulse); + } + if (c.m_multiBodyB) + { + applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse,c.m_deltaVelBindex,ndofB); + c.m_multiBodyB->applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex],deltaImpulse); + } +} + + +void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, + const btVector3& contactNormal, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + bool isFriction, btScalar desiredVelocity, btScalar cfmSlip) +{ + + BT_PROFILE("setupMultiBodyContactConstraint"); + btVector3 rel_pos1; + btVector3 rel_pos2; + + btMultiBody* multiBodyA = solverConstraint.m_multiBodyA; + btMultiBody* multiBodyB = solverConstraint.m_multiBodyB; + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA]; + btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB]; + + btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody; + btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody; + + if (bodyA) + rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); + if (bodyB) + rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); + + relaxation = 1.f; + + if (multiBodyA) + { + const int ndofA = multiBodyA->getNumLinks() + 6; + + solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId(); + + if (solverConstraint.m_deltaVelAindex <0) + { + solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size(); + multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex); + m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofA); + } else + { + btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA); + } + + solverConstraint.m_jacAindex = m_data.m_jacobians.size(); + m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofA); + m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofA); + btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size()); + + btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex]; + multiBodyA->fillContactJacobian(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); + btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + multiBodyA->calcAccelerationDeltas(&m_data.m_jacobians[solverConstraint.m_jacAindex],delta,m_data.scratch_r, m_data.scratch_v); + } else + { + btVector3 torqueAxis0 = rel_pos1.cross(contactNormal); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + solverConstraint.m_contactNormal1 = contactNormal; + } + + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumLinks() + 6; + + solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId(); + if (solverConstraint.m_deltaVelBindex <0) + { + solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size(); + multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex); + m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size()+ndofB); + } + + solverConstraint.m_jacBindex = m_data.m_jacobians.size(); + + m_data.m_jacobians.resize(m_data.m_jacobians.size()+ndofB); + m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size()+ndofB); + btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size()); + + multiBodyB->fillContactJacobian(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m); + multiBodyB->calcAccelerationDeltas(&m_data.m_jacobians[solverConstraint.m_jacBindex],&m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex],m_data.scratch_r, m_data.scratch_v); + } else + { + btVector3 torqueAxis1 = rel_pos2.cross(contactNormal); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + solverConstraint.m_contactNormal2 = -contactNormal; + } + + { + + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + btScalar* jacB = 0; + btScalar* jacA = 0; + btScalar* lambdaA =0; + btScalar* lambdaB =0; + int ndofA = 0; + if (multiBodyA) + { + ndofA = multiBodyA->getNumLinks() + 6; + jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex]; + lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA; ++i) + { + btScalar j = jacA[i] ; + btScalar l =lambdaA[i]; + denom0 += j*l; + } + } else + { + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + contactNormal.dot(vec); + } + } + if (multiBodyB) + { + const int ndofB = multiBodyB->getNumLinks() + 6; + jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex]; + lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB; ++i) + { + btScalar j = jacB[i] ; + btScalar l =lambdaB[i]; + denom1 += j*l; + } + + } else + { + if (rb1) + { + vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + contactNormal.dot(vec); + } + } + + if (multiBodyA && (multiBodyA==multiBodyB)) + { + // ndof1 == ndof2 in this case + for (int i = 0; i < ndofA; ++i) + { + denom1 += jacB[i] * lambdaA[i]; + denom1 += jacA[i] * lambdaB[i]; + } + } + + btScalar d = denom0+denom1; + if (btFabs(d)>SIMD_EPSILON) + { + + solverConstraint.m_jacDiagABInv = relaxation/(d); + } else + { + solverConstraint.m_jacDiagABInv = 1.f; + } + + } + + + //compute rhs and remaining solverConstraint fields + + + + btScalar restitution = 0.f; + btScalar penetration = isFriction? 0 : cp.getDistance()+infoGlobal.m_linearSlop; + + btScalar rel_vel = 0.f; + int ndofA = 0; + int ndofB = 0; + { + + btVector3 vel1,vel2; + if (multiBodyA) + { + ndofA = multiBodyA->getNumLinks() + 6; + btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex]; + for (int i = 0; i < ndofA ; ++i) + rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i]; + } else + { + if (rb0) + { + rel_vel += rb0->getVelocityInLocalPoint(rel_pos1).dot(solverConstraint.m_contactNormal1); + } + } + if (multiBodyB) + { + ndofB = multiBodyB->getNumLinks() + 6; + btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex]; + for (int i = 0; i < ndofB ; ++i) + rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i]; + + } else + { + if (rb1) + { + rel_vel += rb1->getVelocityInLocalPoint(rel_pos2).dot(solverConstraint.m_contactNormal2); + } + } + + solverConstraint.m_friction = cp.m_combinedFriction; + + + restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (restitution <= btScalar(0.)) + { + restitution = 0.f; + }; + } + + + ///warm starting (or zero if disabled) + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + + if (solverConstraint.m_appliedImpulse) + { + if (multiBodyA) + { + btScalar impulse = solverConstraint.m_appliedImpulse; + btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex]; + multiBodyA->applyDeltaVee(deltaV,impulse); + applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA); + } else + { + if (rb0) + bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + } + if (multiBodyB) + { + btScalar impulse = solverConstraint.m_appliedImpulse; + btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex]; + multiBodyB->applyDeltaVee(deltaV,impulse); + applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB); + } else + { + if (rb1) + bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse); + } + } + } else + { + solverConstraint.m_appliedImpulse = 0.f; + } + + solverConstraint.m_appliedPushImpulse = 0.f; + + { + + + btScalar positionalError = 0.f; + btScalar velocityError = restitution - rel_vel;// * damping; + + + btScalar erp = infoGlobal.m_erp2; + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + erp = infoGlobal.m_erp; + } + + if (penetration>0) + { + positionalError = 0; + velocityError = -penetration / infoGlobal.m_timeStep; + + } else + { + positionalError = -penetration * erp/infoGlobal.m_timeStep; + } + + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_rhsPenetration = 0.f; + + } else + { + //split position and velocity into rhs and m_rhsPenetration + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = penetrationImpulse; + } + + solverConstraint.m_cfm = 0.f; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } + +} + + + + +btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) +{ + BT_PROFILE("addMultiBodyFrictionConstraint"); + btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing(); + solverConstraint.m_frictionIndex = frictionIndex; + bool isFriction = true; + + const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0()); + const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1()); + + btMultiBody* mbA = fcA? fcA->m_multiBody : 0; + btMultiBody* mbB = fcB? fcB->m_multiBody : 0; + + int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep); + int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep); + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_multiBodyA = mbA; + if (mbA) + solverConstraint.m_linkA = fcA->m_link; + + solverConstraint.m_multiBodyB = mbB; + if (mbB) + solverConstraint.m_linkB = fcB->m_link; + + solverConstraint.m_originalContactPoint = &cp; + + setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip); + return solverConstraint; +} + +void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) +{ + const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0()); + const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1()); + + btMultiBody* mbA = fcA? fcA->m_multiBody : 0; + btMultiBody* mbB = fcB? fcB->m_multiBody : 0; + + btCollisionObject* colObj0=0,*colObj1=0; + + colObj0 = (btCollisionObject*)manifold->getBody0(); + colObj1 = (btCollisionObject*)manifold->getBody1(); + + int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep); + int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep); + + btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB]; + + + ///avoid collision response between two static objects +// if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero()))) + // return; + + int rollingFriction=1; + + for (int j=0;jgetNumContacts();j++) + { + + btManifoldPoint& cp = manifold->getContactPoint(j); + + if (cp.getDistance() <= manifold->getContactProcessingThreshold()) + { + + btScalar relaxation; + + int frictionIndex = m_multiBodyNormalContactConstraints.size(); + + btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints.expandNonInitializing(); + + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_multiBodyA = mbA; + if (mbA) + solverConstraint.m_linkA = fcA->m_link; + + solverConstraint.m_multiBodyB = mbB; + if (mbB) + solverConstraint.m_linkB = fcB->m_link; + + solverConstraint.m_originalContactPoint = &cp; + + bool isFriction = false; + setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB,cp, infoGlobal, relaxation, isFriction); + +// const btVector3& pos1 = cp.getPositionWorldOnA(); +// const btVector3& pos2 = cp.getPositionWorldOnB(); + + /////setup the friction constraints +#define ENABLE_FRICTION +#ifdef ENABLE_FRICTION + solverConstraint.m_frictionIndex = frictionIndex; +#if ROLLING_FRICTION + btVector3 angVelA(0,0,0),angVelB(0,0,0); + if (rb0) + angVelA = rb0->getAngularVelocity(); + if (rb1) + angVelB = rb1->getAngularVelocity(); + btVector3 relAngVel = angVelB-angVelA; + + if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0)) + { + //only a single rollingFriction per manifold + rollingFriction--; + if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold) + { + relAngVel.normalize(); + applyAnisotropicFriction(colObj0,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + if (relAngVel.length()>0.001) + addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + } else + { + addRollingFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + btVector3 axis0,axis1; + btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1); + applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + if (axis0.length()>0.001) + addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + if (axis1.length()>0.001) + addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + } + } +#endif //ROLLING_FRICTION + + ///Bullet has several options to set the friction directions + ///By default, each contact has only a single friction direction that is recomputed automatically very frame + ///based on the relative linear velocity. + ///If the relative velocity it zero, it will automatically compute a friction direction. + + ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. + ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. + /// + ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. + /// + ///The user can manually override the friction directions for certain contacts using a contact callback, + ///and set the cp.m_lateralFrictionInitialized to true + ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) + ///this will give a conveyor belt effect + /// + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized) + {/* + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) + { + cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel); + if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize();//?? + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + } + + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + + } else + */ + { + btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal); + } + + applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal); + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) + { + cp.m_lateralFrictionInitialized = true; + } + } + + } else + { + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal,cp.m_contactMotion1, cp.m_contactCFM1); + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation, infoGlobal,cp.m_contactMotion2, cp.m_contactCFM2); + + //setMultiBodyFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); + //todo: + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedPushImpulse = 0.f; + } + + +#endif //ENABLE_FRICTION + + } + } +} + +void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal) +{ + btPersistentManifold* manifold = 0; + + for (int i=0;igetBody0()); + const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1()); + if (!fcA && !fcB) + { + //the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case + convertContact(manifold,infoGlobal); + } else + { + convertMultiBodyContact(manifold,infoGlobal); + } + } + + //also convert the multibody constraints, if any + + + for (int i=0;icreateConstraintRows(m_multiBodyNonContactConstraints,m_data, infoGlobal); + } + +} + + + +btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher) +{ + return btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher); +} + + +void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher) +{ + //printf("solveMultiBodyGroup start\n"); + m_tmpMultiBodyConstraints = multiBodyConstraints; + m_tmpNumMultiBodyConstraints = numMultiBodyConstraints; + + btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher); + + m_tmpMultiBodyConstraints = 0; + m_tmpNumMultiBodyConstraints = 0; + + +} diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h new file mode 100644 index 00000000..0f4cd69c --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h @@ -0,0 +1,85 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTIBODY_CONSTRAINT_SOLVER_H +#define BT_MULTIBODY_CONSTRAINT_SOLVER_H + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "btMultiBodySolverConstraint.h" + + +class btMultiBody; + +#include "btMultiBodyConstraint.h" + + + +ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver +{ + +protected: + + btMultiBodyConstraintArray m_multiBodyNonContactConstraints; + + btMultiBodyConstraintArray m_multiBodyNormalContactConstraints; + btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints; + + btMultiBodyJacobianData m_data; + + //temp storage for multi body constraints for a specific island/group called by 'solveGroup' + btMultiBodyConstraint** m_tmpMultiBodyConstraints; + int m_tmpNumMultiBodyConstraints; + + void resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c); + void resolveSingleConstraintRowGenericMultiBody(const btMultiBodySolverConstraint& c); + + void convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal); + btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis,btPersistentManifold* manifold,int frictionIndex,btManifoldPoint& cp,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0); + + + void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint& constraintRow, + btScalar* jacA,btScalar* jacB, + btScalar penetration,btScalar combinedFrictionCoeff, btScalar combinedRestitutionCoeff, + const btContactSolverInfo& infoGlobal); + + void setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, + const btVector3& contactNormal, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, + btScalar& relaxation, + bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0); + + void convertMultiBodyContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); +// virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + + virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + void applyDeltaVee(btScalar* deltaV, btScalar impulse, int velocityIndex, int ndof); + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + ///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints) + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher); + + virtual void solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher); +}; + + + + + +#endif //BT_MULTIBODY_CONSTRAINT_SOLVER_H + diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp new file mode 100644 index 00000000..0910f8f6 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp @@ -0,0 +1,578 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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 "btMultiBodyDynamicsWorld.h" +#include "btMultiBodyConstraintSolver.h" +#include "btMultiBody.h" +#include "btMultiBodyLinkCollider.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include "LinearMath/btQuickprof.h" +#include "btMultiBodyConstraint.h" + + + + +void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, short group, short mask) +{ + m_multiBodies.push_back(body); + +} + +void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body) +{ + m_multiBodies.remove(body); +} + +void btMultiBodyDynamicsWorld::calculateSimulationIslands() +{ + BT_PROFILE("calculateSimulationIslands"); + + getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); + + { + //merge islands based on speculative contact manifolds too + for (int i=0;im_predictiveManifolds.size();i++) + { + btPersistentManifold* manifold = m_predictiveManifolds[i]; + + const btCollisionObject* colObj0 = manifold->getBody0(); + const btCollisionObject* colObj1 = manifold->getBody1(); + + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) + { + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag()); + } + } + } + + { + int i; + int numConstraints = int(m_constraints.size()); + for (i=0;i< numConstraints ; i++ ) + { + btTypedConstraint* constraint = m_constraints[i]; + if (constraint->isEnabled()) + { + const btRigidBody* colObj0 = &constraint->getRigidBodyA(); + const btRigidBody* colObj1 = &constraint->getRigidBodyB(); + + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) + { + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag()); + } + } + } + } + + //merge islands linked by Featherstone link colliders + for (int i=0;igetBaseCollider(); + + for (int b=0;bgetNumLinks();b++) + { + btMultiBodyLinkCollider* cur = body->getLink(b).m_collider; + + if (((cur) && (!(cur)->isStaticOrKinematicObject())) && + ((prev) && (!(prev)->isStaticOrKinematicObject()))) + { + int tagPrev = prev->getIslandTag(); + int tagCur = cur->getIslandTag(); + getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur); + } + if (cur && !cur->isStaticOrKinematicObject()) + prev = cur; + + } + } + } + + //merge islands linked by multibody constraints + { + for (int i=0;im_multiBodyConstraints.size();i++) + { + btMultiBodyConstraint* c = m_multiBodyConstraints[i]; + int tagA = c->getIslandIdA(); + int tagB = c->getIslandIdB(); + if (tagA>=0 && tagB>=0) + getSimulationIslandManager()->getUnionFind().unite(tagA, tagB); + } + } + + //Store the island id in each body + getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); + +} + + +void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep) +{ + BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState"); + + + + for ( int i=0;icheckMotionAndSleepIfRequired(timeStep); + if (!body->isAwake()) + { + btMultiBodyLinkCollider* col = body->getBaseCollider(); + if (col && col->getActivationState() == ACTIVE_TAG) + { + col->setActivationState( WANTS_DEACTIVATION); + col->setDeactivationTime(0.f); + } + for (int b=0;bgetNumLinks();b++) + { + btMultiBodyLinkCollider* col = body->getLink(b).m_collider; + if (col && col->getActivationState() == ACTIVE_TAG) + { + col->setActivationState( WANTS_DEACTIVATION); + col->setDeactivationTime(0.f); + } + } + } else + { + btMultiBodyLinkCollider* col = body->getBaseCollider(); + if (col && col->getActivationState() != DISABLE_DEACTIVATION) + col->setActivationState( ACTIVE_TAG ); + + for (int b=0;bgetNumLinks();b++) + { + btMultiBodyLinkCollider* col = body->getLink(b).m_collider; + if (col && col->getActivationState() != DISABLE_DEACTIVATION) + col->setActivationState( ACTIVE_TAG ); + } + } + + } + } + + btDiscreteDynamicsWorld::updateActivationState(timeStep); +} + + +SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs) +{ + int islandId; + + const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); + const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); + islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); + return islandId; + +} + + +class btSortConstraintOnIslandPredicate2 +{ + public: + + bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const + { + int rIslandId0,lIslandId0; + rIslandId0 = btGetConstraintIslandId2(rhs); + lIslandId0 = btGetConstraintIslandId2(lhs); + return lIslandId0 < rIslandId0; + } +}; + + + +SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs) +{ + int islandId; + + int islandTagA = lhs->getIslandIdA(); + int islandTagB = lhs->getIslandIdB(); + islandId= islandTagA>=0?islandTagA:islandTagB; + return islandId; + +} + + +class btSortMultiBodyConstraintOnIslandPredicate +{ + public: + + bool operator() ( const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs ) const + { + int rIslandId0,lIslandId0; + rIslandId0 = btGetMultiBodyConstraintIslandId(rhs); + lIslandId0 = btGetMultiBodyConstraintIslandId(lhs); + return lIslandId0 < rIslandId0; + } +}; + +struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback +{ + btContactSolverInfo* m_solverInfo; + btMultiBodyConstraintSolver* m_solver; + btMultiBodyConstraint** m_multiBodySortedConstraints; + int m_numMultiBodyConstraints; + + btTypedConstraint** m_sortedConstraints; + int m_numConstraints; + btIDebugDraw* m_debugDrawer; + btDispatcher* m_dispatcher; + + btAlignedObjectArray m_bodies; + btAlignedObjectArray m_manifolds; + btAlignedObjectArray m_constraints; + btAlignedObjectArray m_multiBodyConstraints; + + + MultiBodyInplaceSolverIslandCallback( btMultiBodyConstraintSolver* solver, + btDispatcher* dispatcher) + :m_solverInfo(NULL), + m_solver(solver), + m_multiBodySortedConstraints(NULL), + m_numConstraints(0), + m_debugDrawer(NULL), + m_dispatcher(dispatcher) + { + + } + + MultiBodyInplaceSolverIslandCallback& operator=(MultiBodyInplaceSolverIslandCallback& other) + { + btAssert(0); + (void)other; + return *this; + } + + SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer) + { + btAssert(solverInfo); + m_solverInfo = solverInfo; + + m_multiBodySortedConstraints = sortedMultiBodyConstraints; + m_numMultiBodyConstraints = numMultiBodyConstraints; + m_sortedConstraints = sortedConstraints; + m_numConstraints = numConstraints; + + m_debugDrawer = debugDrawer; + m_bodies.resize (0); + m_manifolds.resize (0); + m_constraints.resize (0); + m_multiBodyConstraints.resize(0); + } + + + virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) + { + if (islandId<0) + { + ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id + m_solver->solveMultiBodyGroup( bodies,numBodies,manifolds, numManifolds,m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher); + } else + { + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + btMultiBodyConstraint** startMultiBodyConstraint = 0; + + int numCurConstraints = 0; + int numCurMultiBodyConstraints = 0; + + int i; + + //find the first constraint for this island + + for (i=0;im_minimumSolverBatchSize<=1) + { + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher); + } else + { + + for (i=0;im_solverInfo->m_minimumSolverBatchSize) + { + processConstraints(); + } else + { + //printf("deferred\n"); + } + } + } + } + void processConstraints() + { + + btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0; + btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0; + btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0; + btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0; + + m_solver->solveMultiBodyGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo,m_debugDrawer,m_dispatcher); + m_bodies.resize(0); + m_manifolds.resize(0); + m_constraints.resize(0); + m_multiBodyConstraints.resize(0); + } + +}; + + + +btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) + :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration), + m_multiBodyConstraintSolver(constraintSolver) +{ + //split impulse is not yet supported for Featherstone hierarchies + getSolverInfo().m_splitImpulse = false; + getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS; + m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver,dispatcher); +} + +btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld () +{ + delete m_solverMultiBodyIslandCallback; +} + + + + +void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + + btAlignedObjectArray scratch_r; + btAlignedObjectArray scratch_v; + btAlignedObjectArray scratch_m; + + + BT_PROFILE("solveConstraints"); + + m_sortedConstraints.resize( m_constraints.size()); + int i; + for (i=0;isetup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),sortedMultiBodyConstraints,m_sortedMultiBodyConstraints.size(), getDebugDrawer()); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); + + /// solve all the constraints for this island + m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverMultiBodyIslandCallback); + + + { + BT_PROFILE("btMultiBody addForce and stepVelocities"); + for (int i=0;im_multiBodies.size();i++) + { + btMultiBody* bod = m_multiBodies[i]; + + bool isSleeping = false; + + if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING) + { + isSleeping = true; + } + for (int b=0;bgetNumLinks();b++) + { + if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING) + isSleeping = true; + } + + if (!isSleeping) + { + scratch_r.resize(bod->getNumLinks()+1); + scratch_v.resize(bod->getNumLinks()+1); + scratch_m.resize(bod->getNumLinks()+1); + + bod->clearForcesAndTorques(); + bod->addBaseForce(m_gravity * bod->getBaseMass()); + + for (int j = 0; j < bod->getNumLinks(); ++j) + { + bod->addLinkForce(j, m_gravity * bod->getLinkMass(j)); + } + + bod->stepVelocities(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m); + } + } + } + + m_solverMultiBodyIslandCallback->processConstraints(); + + m_constraintSolver->allSolved(solverInfo, m_debugDrawer); + +} + +void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + btDiscreteDynamicsWorld::integrateTransforms(timeStep); + + { + BT_PROFILE("btMultiBody stepPositions"); + //integrate and update the Featherstone hierarchies + btAlignedObjectArray world_to_local; + btAlignedObjectArray local_origin; + + for (int b=0;bgetBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING) + { + isSleeping = true; + } + for (int b=0;bgetNumLinks();b++) + { + if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING) + isSleeping = true; + } + + + if (!isSleeping) + { + int nLinks = bod->getNumLinks(); + + ///base + num links + world_to_local.resize(nLinks+1); + local_origin.resize(nLinks+1); + + bod->stepPositions(timeStep); + + + + world_to_local[0] = bod->getWorldToBaseRot(); + local_origin[0] = bod->getBasePos(); + + if (bod->getBaseCollider()) + { + btVector3 posr = local_origin[0]; + float pos[4]={posr.x(),posr.y(),posr.z(),1}; + float quat[4]={-world_to_local[0].x(),-world_to_local[0].y(),-world_to_local[0].z(),world_to_local[0].w()}; + btTransform tr; + tr.setIdentity(); + tr.setOrigin(posr); + tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3])); + + bod->getBaseCollider()->setWorldTransform(tr); + + } + + for (int k=0;kgetNumLinks();k++) + { + const int parent = bod->getParent(k); + world_to_local[k+1] = bod->getParentToLocalRot(k) * world_to_local[parent+1]; + local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , bod->getRVector(k))); + } + + + for (int m=0;mgetNumLinks();m++) + { + btMultiBodyLinkCollider* col = bod->getLink(m).m_collider; + if (col) + { + int link = col->m_link; + btAssert(link == m); + + int index = link+1; + + btVector3 posr = local_origin[index]; + float pos[4]={posr.x(),posr.y(),posr.z(),1}; + float quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()}; + btTransform tr; + tr.setIdentity(); + tr.setOrigin(posr); + tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3])); + + col->setWorldTransform(tr); + } + } + } else + { + bod->clearVelocities(); + } + } + } +} + + + +void btMultiBodyDynamicsWorld::addMultiBodyConstraint( btMultiBodyConstraint* constraint) +{ + m_multiBodyConstraints.push_back(constraint); +} + +void btMultiBodyDynamicsWorld::removeMultiBodyConstraint( btMultiBodyConstraint* constraint) +{ + m_multiBodyConstraints.remove(constraint); +} diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h new file mode 100644 index 00000000..ad57a346 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h @@ -0,0 +1,56 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTIBODY_DYNAMICS_WORLD_H +#define BT_MULTIBODY_DYNAMICS_WORLD_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + + +class btMultiBody; +class btMultiBodyConstraint; +class btMultiBodyConstraintSolver; +struct MultiBodyInplaceSolverIslandCallback; + +///The btMultiBodyDynamicsWorld adds Featherstone multi body dynamics to Bullet +///This implementation is still preliminary/experimental. +class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld +{ +protected: + btAlignedObjectArray m_multiBodies; + btAlignedObjectArray m_multiBodyConstraints; + btAlignedObjectArray m_sortedMultiBodyConstraints; + btMultiBodyConstraintSolver* m_multiBodyConstraintSolver; + MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback; + + virtual void calculateSimulationIslands(); + virtual void updateActivationState(btScalar timeStep); + virtual void solveConstraints(btContactSolverInfo& solverInfo); + virtual void integrateTransforms(btScalar timeStep); +public: + + btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btMultiBodyDynamicsWorld (); + + virtual void addMultiBody(btMultiBody* body, short group= btBroadphaseProxy::DefaultFilter, short mask=btBroadphaseProxy::AllFilter); + + virtual void removeMultiBody(btMultiBody* body); + + virtual void addMultiBodyConstraint( btMultiBodyConstraint* constraint); + + virtual void removeMultiBodyConstraint( btMultiBodyConstraint* constraint); +}; +#endif //BT_MULTIBODY_DYNAMICS_WORLD_H diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp new file mode 100644 index 00000000..ea309e88 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp @@ -0,0 +1,133 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was written by Erwin Coumans + +#include "btMultiBodyJointLimitConstraint.h" +#include "btMultiBody.h" +#include "btMultiBodyLinkCollider.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + + +btMultiBodyJointLimitConstraint::btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper) + :btMultiBodyConstraint(body,body,link,link,2,true), + m_lowerBound(lower), + m_upperBound(upper) +{ + // the data.m_jacobians never change, so may as well + // initialize them here + + // note: we rely on the fact that data.m_jacobians are + // always initialized to zero by the Constraint ctor + + // row 0: the lower bound + jacobianA(0)[6 + link] = 1; + + // row 1: the upper bound + jacobianB(1)[6 + link] = -1; +} +btMultiBodyJointLimitConstraint::~btMultiBodyJointLimitConstraint() +{ +} + +int btMultiBodyJointLimitConstraint::getIslandIdA() const +{ + btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider(); + if (col) + return col->getIslandTag(); + for (int i=0;igetNumLinks();i++) + { + if (m_bodyA->getLink(i).m_collider) + return m_bodyA->getLink(i).m_collider->getIslandTag(); + } + return -1; +} + +int btMultiBodyJointLimitConstraint::getIslandIdB() const +{ + btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider(); + if (col) + return col->getIslandTag(); + + for (int i=0;igetNumLinks();i++) + { + col = m_bodyB->getLink(i).m_collider; + if (col) + return col->getIslandTag(); + } + return -1; +} + + +void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal) +{ + // only positions need to be updated -- data.m_jacobians and force + // directions were set in the ctor and never change. + + // row 0: the lower bound + setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound); + + // row 1: the upper bound + setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA)); + + for (int row=0;row infoGlobal.m_splitImpulsePenetrationThreshold)) + { + erp = infoGlobal.m_erp; + } + if (penetration>0) + { + positionalError = 0; + velocityError = -penetration / infoGlobal.m_timeStep; + } else + { + positionalError = -penetration * erp/infoGlobal.m_timeStep; + } + + btScalar penetrationImpulse = positionalError*constraintRow.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *constraintRow.m_jacDiagABInv; + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + constraintRow.m_rhs = penetrationImpulse+velocityImpulse; + constraintRow.m_rhsPenetration = 0.f; + + } else + { + //split position and velocity into rhs and m_rhsPenetration + constraintRow.m_rhs = velocityImpulse; + constraintRow.m_rhsPenetration = penetrationImpulse; + } + } + } + +} + + + + diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h new file mode 100644 index 00000000..0c7fc170 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h @@ -0,0 +1,44 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H +#define BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H + +#include "btMultiBodyConstraint.h" +struct btSolverInfo; + +class btMultiBodyJointLimitConstraint : public btMultiBodyConstraint +{ +protected: + + btScalar m_lowerBound; + btScalar m_upperBound; +public: + + btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper); + virtual ~btMultiBodyJointLimitConstraint(); + + virtual int getIslandIdA() const; + virtual int getIslandIdB() const; + + virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal); + + +}; + +#endif //BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H + diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp new file mode 100644 index 00000000..ab5a4302 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp @@ -0,0 +1,89 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was written by Erwin Coumans + +#include "btMultiBodyJointMotor.h" +#include "btMultiBody.h" +#include "btMultiBodyLinkCollider.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + + +btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse) + :btMultiBodyConstraint(body,body,link,link,1,true), + m_desiredVelocity(desiredVelocity) +{ + m_maxAppliedImpulse = maxMotorImpulse; + // the data.m_jacobians never change, so may as well + // initialize them here + + // note: we rely on the fact that data.m_jacobians are + // always initialized to zero by the Constraint ctor + + // row 0: the lower bound + jacobianA(0)[6 + link] = 1; +} +btMultiBodyJointMotor::~btMultiBodyJointMotor() +{ +} + +int btMultiBodyJointMotor::getIslandIdA() const +{ + btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider(); + if (col) + return col->getIslandTag(); + for (int i=0;igetNumLinks();i++) + { + if (m_bodyA->getLink(i).m_collider) + return m_bodyA->getLink(i).m_collider->getIslandTag(); + } + return -1; +} + +int btMultiBodyJointMotor::getIslandIdB() const +{ + btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider(); + if (col) + return col->getIslandTag(); + + for (int i=0;igetNumLinks();i++) + { + col = m_bodyB->getLink(i).m_collider; + if (col) + return col->getIslandTag(); + } + return -1; +} + + +void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal) +{ + // only positions need to be updated -- data.m_jacobians and force + // directions were set in the ctor and never change. + + + + for (int row=0;row=0 || (multiBody && !multiBody->hasFixedBase())) + { + m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT); + } + // else + //{ + // m_collisionFlags |= (btCollisionObject::CF_STATIC_OBJECT); + //} + + m_internalType = CO_FEATHERSTONE_LINK; + } + static btMultiBodyLinkCollider* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK) + return (btMultiBodyLinkCollider*)colObj; + return 0; + } + static const btMultiBodyLinkCollider* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK) + return (btMultiBodyLinkCollider*)colObj; + return 0; + } + + virtual bool checkCollideWithOverride(const btCollisionObject* co) const + { + const btMultiBodyLinkCollider* other = btMultiBodyLinkCollider::upcast(co); + if (!other) + return true; + if (other->m_multiBody != this->m_multiBody) + return true; + if (!m_multiBody->hasSelfCollision()) + return false; + + //check if 'link' has collision disabled + if (m_link>=0) + { + const btMultibodyLink& link = m_multiBody->getLink(this->m_link); + if ((link.m_flags&BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION) && link.parent == other->m_link) + return false; + } + + if (other->m_link>=0) + { + const btMultibodyLink& otherLink = other->m_multiBody->getLink(other->m_link); + if ((otherLink.m_flags& BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION) && otherLink.parent == this->m_link) + return false; + } + return true; + } +}; + +#endif //BT_FEATHERSTONE_LINK_COLLIDER_H + diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp new file mode 100644 index 00000000..f6690049 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp @@ -0,0 +1,143 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was written by Erwin Coumans + +#include "btMultiBodyPoint2Point.h" +#include "btMultiBodyLinkCollider.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB) + :btMultiBodyConstraint(body,0,link,-1,3,false), + m_rigidBodyA(0), + m_rigidBodyB(bodyB), + m_pivotInA(pivotInA), + m_pivotInB(pivotInB) +{ +} + +btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB) + :btMultiBodyConstraint(bodyA,bodyB,linkA,linkB,3,false), + m_rigidBodyA(0), + m_rigidBodyB(0), + m_pivotInA(pivotInA), + m_pivotInB(pivotInB) +{ +} + + +btMultiBodyPoint2Point::~btMultiBodyPoint2Point() +{ +} + + +int btMultiBodyPoint2Point::getIslandIdA() const +{ + if (m_rigidBodyA) + return m_rigidBodyA->getIslandTag(); + + if (m_bodyA) + { + btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider(); + if (col) + return col->getIslandTag(); + for (int i=0;igetNumLinks();i++) + { + if (m_bodyA->getLink(i).m_collider) + return m_bodyA->getLink(i).m_collider->getIslandTag(); + } + } + return -1; +} + +int btMultiBodyPoint2Point::getIslandIdB() const +{ + if (m_rigidBodyB) + return m_rigidBodyB->getIslandTag(); + if (m_bodyB) + { + btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider(); + if (col) + return col->getIslandTag(); + + for (int i=0;igetNumLinks();i++) + { + col = m_bodyB->getLink(i).m_collider; + if (col) + return col->getIslandTag(); + } + } + return -1; +} + + + +void btMultiBodyPoint2Point::createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal) +{ + +// int i=1; + for (int i=0;i<3;i++) + { + + btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing(); + + constraintRow.m_solverBodyIdA = data.m_fixedBodyId; + constraintRow.m_solverBodyIdB = data.m_fixedBodyId; + + + btVector3 contactNormalOnB(0,0,0); + contactNormalOnB[i] = -1; + + btScalar penetration = 0; + + // Convert local points back to world + btVector3 pivotAworld = m_pivotInA; + if (m_rigidBodyA) + { + + constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId(); + pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA; + } else + { + if (m_bodyA) + pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA); + } + btVector3 pivotBworld = m_pivotInB; + if (m_rigidBodyB) + { + constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId(); + pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB; + } else + { + if (m_bodyB) + pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB); + + } + btScalar position = (pivotAworld-pivotBworld).dot(contactNormalOnB); + btScalar relaxation = 1.f; + fillMultiBodyConstraintMixed(constraintRow, data, + contactNormalOnB, + pivotAworld, pivotBworld, + position, + infoGlobal, + relaxation, + false); + constraintRow.m_lowerLimit = -m_maxAppliedImpulse; + constraintRow.m_upperLimit = m_maxAppliedImpulse; + + } +} diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h new file mode 100644 index 00000000..26ca12b4 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h @@ -0,0 +1,60 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +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. +*/ + +///This file was written by Erwin Coumans + +#ifndef BT_MULTIBODY_POINT2POINT_H +#define BT_MULTIBODY_POINT2POINT_H + +#include "btMultiBodyConstraint.h" + +class btMultiBodyPoint2Point : public btMultiBodyConstraint +{ +protected: + + btRigidBody* m_rigidBodyA; + btRigidBody* m_rigidBodyB; + btVector3 m_pivotInA; + btVector3 m_pivotInB; + + +public: + + btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB); + btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB); + + virtual ~btMultiBodyPoint2Point(); + + virtual int getIslandIdA() const; + virtual int getIslandIdB() const; + + virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows, + btMultiBodyJacobianData& data, + const btContactSolverInfo& infoGlobal); + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } + + void setPivotInB(const btVector3& pivotInB) + { + m_pivotInB = pivotInB; + } + + +}; + +#endif //BT_MULTIBODY_POINT2POINT_H diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h new file mode 100644 index 00000000..cf06dfb9 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h @@ -0,0 +1,82 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MULTIBODY_SOLVER_CONSTRAINT_H +#define BT_MULTIBODY_SOLVER_CONSTRAINT_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btMultiBody; +#include "BulletDynamics/ConstraintSolver/btSolverBody.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + +///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. +ATTRIBUTE_ALIGNED16 (struct) btMultiBodySolverConstraint +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + + int m_deltaVelAindex;//more generic version of m_relpos1CrossNormal/m_contactNormal1 + btVector3 m_relpos1CrossNormal; + btVector3 m_contactNormal1; + int m_jacAindex; + + int m_deltaVelBindex; + btVector3 m_relpos2CrossNormal; + btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always + int m_jacBindex; + + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + mutable btSimdScalar m_appliedPushImpulse; + mutable btSimdScalar m_appliedImpulse; + + btScalar m_friction; + btScalar m_jacDiagABInv; + btScalar m_rhs; + btScalar m_cfm; + + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_rhsPenetration; + union + { + void* m_originalContactPoint; + btScalar m_unusedPadding4; + }; + + int m_overrideNumSolverIterations; + int m_frictionIndex; + + int m_solverBodyIdA; + btMultiBody* m_multiBodyA; + int m_linkA; + + int m_solverBodyIdB; + btMultiBody* m_multiBodyB; + int m_linkB; + + enum btSolverConstraintType + { + BT_SOLVER_CONTACT_1D = 0, + BT_SOLVER_FRICTION_1D + }; +}; + +typedef btAlignedObjectArray btMultiBodyConstraintArray; + +#endif //BT_MULTIBODY_SOLVER_CONSTRAINT_H diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp new file mode 100644 index 00000000..3bf7b5c1 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp @@ -0,0 +1,2079 @@ +/************************************************************************* +* * +* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * +* All rights reserved. Email: russ@q12.org Web: www.q12.org * +* * +* This library is free software; you can redistribute it and/or * +* modify it under the terms of EITHER: * +* (1) The GNU Lesser General Public License as published by the Free * +* Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. The text of the GNU Lesser * +* General Public License is included with this library in the * +* file LICENSE.TXT. * +* (2) The BSD-style license that is included with this library in * +* the file LICENSE-BSD.TXT. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * +* LICENSE.TXT and LICENSE-BSD.TXT for more details. * +* * +*************************************************************************/ + +/* + + +THE ALGORITHM +------------- + +solve A*x = b+w, with x and w subject to certain LCP conditions. +each x(i),w(i) must lie on one of the three line segments in the following +diagram. each line segment corresponds to one index set : + + w(i) + /|\ | : + | | : + | |i in N : + w>0 | |state[i]=0 : + | | : + | | : i in C + w=0 + +-----------------------+ + | : | + | : | + w<0 | : |i in N + | : |state[i]=1 + | : | + | : | + +-------|-----------|-----------|----------> x(i) + lo 0 hi + +the Dantzig algorithm proceeds as follows: + for i=1:n + * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or + negative towards the line. as this is done, the other (x(j),w(j)) + for j= 0. this makes the algorithm a bit +simpler, because the starting point for x(i),w(i) is always on the dotted +line x=0 and x will only ever increase in one direction, so it can only hit +two out of the three line segments. + + +NOTES +----- + +this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m". +the implementation is split into an LCP problem object (btLCP) and an LCP +driver function. most optimization occurs in the btLCP object. + +a naive implementation of the algorithm requires either a lot of data motion +or a lot of permutation-array lookup, because we are constantly re-ordering +rows and columns. to avoid this and make a more optimized algorithm, a +non-trivial data structure is used to represent the matrix A (this is +implemented in the fast version of the btLCP object). + +during execution of this algorithm, some indexes in A are clamped (set C), +some are non-clamped (set N), and some are "don't care" (where x=0). +A,x,b,w (and other problem vectors) are permuted such that the clamped +indexes are first, the unclamped indexes are next, and the don't-care +indexes are last. this permutation is recorded in the array `p'. +initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped, +the corresponding elements of p are swapped. + +because the C and N elements are grouped together in the rows of A, we can do +lots of work with a fast dot product function. if A,x,etc were not permuted +and we only had a permutation array, then those dot products would be much +slower as we would have a permutation array lookup in some inner loops. + +A is accessed through an array of row pointers, so that element (i,j) of the +permuted matrix is A[i][j]. this makes row swapping fast. for column swapping +we still have to actually move the data. + +during execution of this algorithm we maintain an L*D*L' factorization of +the clamped submatrix of A (call it `AC') which is the top left nC*nC +submatrix of A. there are two ways we could arrange the rows/columns in AC. + +(1) AC is always permuted such that L*D*L' = AC. this causes a problem +when a row/column is removed from C, because then all the rows/columns of A +between the deleted index and the end of C need to be rotated downward. +this results in a lot of data motion and slows things down. +(2) L*D*L' is actually a factorization of a *permutation* of AC (which is +itself a permutation of the underlying A). this is what we do - the +permutation is recorded in the vector C. call this permutation A[C,C]. +when a row/column is removed from C, all we have to do is swap two +rows/columns and manipulate C. + +*/ + + +#include "btDantzigLCP.h" + +#include //memcpy + +bool s_error = false; + +//*************************************************************************** +// code generation parameters + + +#define btLCP_FAST // use fast btLCP object + +// option 1 : matrix row pointers (less data copying) +#define BTROWPTRS +#define BTATYPE btScalar ** +#define BTAROW(i) (m_A[i]) + +// option 2 : no matrix row pointers (slightly faster inner loops) +//#define NOROWPTRS +//#define BTATYPE btScalar * +//#define BTAROW(i) (m_A+(i)*m_nskip) + +#define BTNUB_OPTIMIZATIONS + + + +/* solve L*X=B, with B containing 1 right hand sides. + * L is an n*n lower triangular matrix with ones on the diagonal. + * L is stored by rows and its leading dimension is lskip. + * B is an n*1 matrix that contains the right hand sides. + * B is stored by columns and its leading dimension is also lskip. + * B is overwritten with X. + * this processes blocks of 2*2. + * if this is in the factorizer source file, n must be a multiple of 2. + */ + +static void btSolveL1_1 (const btScalar *L, btScalar *B, int n, int lskip1) +{ + /* declare variables - Z matrix, p and q vectors, etc */ + btScalar Z11,m11,Z21,m21,p1,q1,p2,*ex; + const btScalar *ell; + int i,j; + /* compute all 2 x 1 blocks of X */ + for (i=0; i < n; i+=2) { + /* compute all 2 x 1 block of X, from rows i..i+2-1 */ + /* set the Z matrix to 0 */ + Z11=0; + Z21=0; + ell = L + i*lskip1; + ex = B; + /* the inner loop that computes outer products and adds them to Z */ + for (j=i-2; j >= 0; j -= 2) { + /* compute outer product and add it to the Z matrix */ + p1=ell[0]; + q1=ex[0]; + m11 = p1 * q1; + p2=ell[lskip1]; + m21 = p2 * q1; + Z11 += m11; + Z21 += m21; + /* compute outer product and add it to the Z matrix */ + p1=ell[1]; + q1=ex[1]; + m11 = p1 * q1; + p2=ell[1+lskip1]; + m21 = p2 * q1; + /* advance pointers */ + ell += 2; + ex += 2; + Z11 += m11; + Z21 += m21; + /* end of inner loop */ + } + /* compute left-over iterations */ + j += 2; + for (; j > 0; j--) { + /* compute outer product and add it to the Z matrix */ + p1=ell[0]; + q1=ex[0]; + m11 = p1 * q1; + p2=ell[lskip1]; + m21 = p2 * q1; + /* advance pointers */ + ell += 1; + ex += 1; + Z11 += m11; + Z21 += m21; + } + /* finish computing the X(i) block */ + Z11 = ex[0] - Z11; + ex[0] = Z11; + p1 = ell[lskip1]; + Z21 = ex[1] - Z21 - p1*Z11; + ex[1] = Z21; + /* end of outer loop */ + } +} + +/* solve L*X=B, with B containing 2 right hand sides. + * L is an n*n lower triangular matrix with ones on the diagonal. + * L is stored by rows and its leading dimension is lskip. + * B is an n*2 matrix that contains the right hand sides. + * B is stored by columns and its leading dimension is also lskip. + * B is overwritten with X. + * this processes blocks of 2*2. + * if this is in the factorizer source file, n must be a multiple of 2. + */ + +static void btSolveL1_2 (const btScalar *L, btScalar *B, int n, int lskip1) +{ + /* declare variables - Z matrix, p and q vectors, etc */ + btScalar Z11,m11,Z12,m12,Z21,m21,Z22,m22,p1,q1,p2,q2,*ex; + const btScalar *ell; + int i,j; + /* compute all 2 x 2 blocks of X */ + for (i=0; i < n; i+=2) { + /* compute all 2 x 2 block of X, from rows i..i+2-1 */ + /* set the Z matrix to 0 */ + Z11=0; + Z12=0; + Z21=0; + Z22=0; + ell = L + i*lskip1; + ex = B; + /* the inner loop that computes outer products and adds them to Z */ + for (j=i-2; j >= 0; j -= 2) { + /* compute outer product and add it to the Z matrix */ + p1=ell[0]; + q1=ex[0]; + m11 = p1 * q1; + q2=ex[lskip1]; + m12 = p1 * q2; + p2=ell[lskip1]; + m21 = p2 * q1; + m22 = p2 * q2; + Z11 += m11; + Z12 += m12; + Z21 += m21; + Z22 += m22; + /* compute outer product and add it to the Z matrix */ + p1=ell[1]; + q1=ex[1]; + m11 = p1 * q1; + q2=ex[1+lskip1]; + m12 = p1 * q2; + p2=ell[1+lskip1]; + m21 = p2 * q1; + m22 = p2 * q2; + /* advance pointers */ + ell += 2; + ex += 2; + Z11 += m11; + Z12 += m12; + Z21 += m21; + Z22 += m22; + /* end of inner loop */ + } + /* compute left-over iterations */ + j += 2; + for (; j > 0; j--) { + /* compute outer product and add it to the Z matrix */ + p1=ell[0]; + q1=ex[0]; + m11 = p1 * q1; + q2=ex[lskip1]; + m12 = p1 * q2; + p2=ell[lskip1]; + m21 = p2 * q1; + m22 = p2 * q2; + /* advance pointers */ + ell += 1; + ex += 1; + Z11 += m11; + Z12 += m12; + Z21 += m21; + Z22 += m22; + } + /* finish computing the X(i) block */ + Z11 = ex[0] - Z11; + ex[0] = Z11; + Z12 = ex[lskip1] - Z12; + ex[lskip1] = Z12; + p1 = ell[lskip1]; + Z21 = ex[1] - Z21 - p1*Z11; + ex[1] = Z21; + Z22 = ex[1+lskip1] - Z22 - p1*Z12; + ex[1+lskip1] = Z22; + /* end of outer loop */ + } +} + + +void btFactorLDLT (btScalar *A, btScalar *d, int n, int nskip1) +{ + int i,j; + btScalar sum,*ell,*dee,dd,p1,p2,q1,q2,Z11,m11,Z21,m21,Z22,m22; + if (n < 1) return; + + for (i=0; i<=n-2; i += 2) { + /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */ + btSolveL1_2 (A,A+i*nskip1,i,nskip1); + /* scale the elements in a 2 x i block at A(i,0), and also */ + /* compute Z = the outer product matrix that we'll need. */ + Z11 = 0; + Z21 = 0; + Z22 = 0; + ell = A+i*nskip1; + dee = d; + for (j=i-6; j >= 0; j -= 6) { + p1 = ell[0]; + p2 = ell[nskip1]; + dd = dee[0]; + q1 = p1*dd; + q2 = p2*dd; + ell[0] = q1; + ell[nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + p1 = ell[1]; + p2 = ell[1+nskip1]; + dd = dee[1]; + q1 = p1*dd; + q2 = p2*dd; + ell[1] = q1; + ell[1+nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + p1 = ell[2]; + p2 = ell[2+nskip1]; + dd = dee[2]; + q1 = p1*dd; + q2 = p2*dd; + ell[2] = q1; + ell[2+nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + p1 = ell[3]; + p2 = ell[3+nskip1]; + dd = dee[3]; + q1 = p1*dd; + q2 = p2*dd; + ell[3] = q1; + ell[3+nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + p1 = ell[4]; + p2 = ell[4+nskip1]; + dd = dee[4]; + q1 = p1*dd; + q2 = p2*dd; + ell[4] = q1; + ell[4+nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + p1 = ell[5]; + p2 = ell[5+nskip1]; + dd = dee[5]; + q1 = p1*dd; + q2 = p2*dd; + ell[5] = q1; + ell[5+nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + ell += 6; + dee += 6; + } + /* compute left-over iterations */ + j += 6; + for (; j > 0; j--) { + p1 = ell[0]; + p2 = ell[nskip1]; + dd = dee[0]; + q1 = p1*dd; + q2 = p2*dd; + ell[0] = q1; + ell[nskip1] = q2; + m11 = p1*q1; + m21 = p2*q1; + m22 = p2*q2; + Z11 += m11; + Z21 += m21; + Z22 += m22; + ell++; + dee++; + } + /* solve for diagonal 2 x 2 block at A(i,i) */ + Z11 = ell[0] - Z11; + Z21 = ell[nskip1] - Z21; + Z22 = ell[1+nskip1] - Z22; + dee = d + i; + /* factorize 2 x 2 block Z,dee */ + /* factorize row 1 */ + dee[0] = btRecip(Z11); + /* factorize row 2 */ + sum = 0; + q1 = Z21; + q2 = q1 * dee[0]; + Z21 = q2; + sum += q1*q2; + dee[1] = btRecip(Z22 - sum); + /* done factorizing 2 x 2 block */ + ell[nskip1] = Z21; + } + /* compute the (less than 2) rows at the bottom */ + switch (n-i) { + case 0: + break; + + case 1: + btSolveL1_1 (A,A+i*nskip1,i,nskip1); + /* scale the elements in a 1 x i block at A(i,0), and also */ + /* compute Z = the outer product matrix that we'll need. */ + Z11 = 0; + ell = A+i*nskip1; + dee = d; + for (j=i-6; j >= 0; j -= 6) { + p1 = ell[0]; + dd = dee[0]; + q1 = p1*dd; + ell[0] = q1; + m11 = p1*q1; + Z11 += m11; + p1 = ell[1]; + dd = dee[1]; + q1 = p1*dd; + ell[1] = q1; + m11 = p1*q1; + Z11 += m11; + p1 = ell[2]; + dd = dee[2]; + q1 = p1*dd; + ell[2] = q1; + m11 = p1*q1; + Z11 += m11; + p1 = ell[3]; + dd = dee[3]; + q1 = p1*dd; + ell[3] = q1; + m11 = p1*q1; + Z11 += m11; + p1 = ell[4]; + dd = dee[4]; + q1 = p1*dd; + ell[4] = q1; + m11 = p1*q1; + Z11 += m11; + p1 = ell[5]; + dd = dee[5]; + q1 = p1*dd; + ell[5] = q1; + m11 = p1*q1; + Z11 += m11; + ell += 6; + dee += 6; + } + /* compute left-over iterations */ + j += 6; + for (; j > 0; j--) { + p1 = ell[0]; + dd = dee[0]; + q1 = p1*dd; + ell[0] = q1; + m11 = p1*q1; + Z11 += m11; + ell++; + dee++; + } + /* solve for diagonal 1 x 1 block at A(i,i) */ + Z11 = ell[0] - Z11; + dee = d + i; + /* factorize 1 x 1 block Z,dee */ + /* factorize row 1 */ + dee[0] = btRecip(Z11); + /* done factorizing 1 x 1 block */ + break; + + //default: *((char*)0)=0; /* this should never happen! */ + } +} + +/* solve L*X=B, with B containing 1 right hand sides. + * L is an n*n lower triangular matrix with ones on the diagonal. + * L is stored by rows and its leading dimension is lskip. + * B is an n*1 matrix that contains the right hand sides. + * B is stored by columns and its leading dimension is also lskip. + * B is overwritten with X. + * this processes blocks of 4*4. + * if this is in the factorizer source file, n must be a multiple of 4. + */ + +void btSolveL1 (const btScalar *L, btScalar *B, int n, int lskip1) +{ + /* declare variables - Z matrix, p and q vectors, etc */ + btScalar Z11,Z21,Z31,Z41,p1,q1,p2,p3,p4,*ex; + const btScalar *ell; + int lskip2,lskip3,i,j; + /* compute lskip values */ + lskip2 = 2*lskip1; + lskip3 = 3*lskip1; + /* compute all 4 x 1 blocks of X */ + for (i=0; i <= n-4; i+=4) { + /* compute all 4 x 1 block of X, from rows i..i+4-1 */ + /* set the Z matrix to 0 */ + Z11=0; + Z21=0; + Z31=0; + Z41=0; + ell = L + i*lskip1; + ex = B; + /* the inner loop that computes outer products and adds them to Z */ + for (j=i-12; j >= 0; j -= 12) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + p2=ell[lskip1]; + p3=ell[lskip2]; + p4=ell[lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[1]; + q1=ex[1]; + p2=ell[1+lskip1]; + p3=ell[1+lskip2]; + p4=ell[1+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[2]; + q1=ex[2]; + p2=ell[2+lskip1]; + p3=ell[2+lskip2]; + p4=ell[2+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[3]; + q1=ex[3]; + p2=ell[3+lskip1]; + p3=ell[3+lskip2]; + p4=ell[3+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[4]; + q1=ex[4]; + p2=ell[4+lskip1]; + p3=ell[4+lskip2]; + p4=ell[4+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[5]; + q1=ex[5]; + p2=ell[5+lskip1]; + p3=ell[5+lskip2]; + p4=ell[5+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[6]; + q1=ex[6]; + p2=ell[6+lskip1]; + p3=ell[6+lskip2]; + p4=ell[6+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[7]; + q1=ex[7]; + p2=ell[7+lskip1]; + p3=ell[7+lskip2]; + p4=ell[7+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[8]; + q1=ex[8]; + p2=ell[8+lskip1]; + p3=ell[8+lskip2]; + p4=ell[8+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[9]; + q1=ex[9]; + p2=ell[9+lskip1]; + p3=ell[9+lskip2]; + p4=ell[9+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[10]; + q1=ex[10]; + p2=ell[10+lskip1]; + p3=ell[10+lskip2]; + p4=ell[10+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* load p and q values */ + p1=ell[11]; + q1=ex[11]; + p2=ell[11+lskip1]; + p3=ell[11+lskip2]; + p4=ell[11+lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* advance pointers */ + ell += 12; + ex += 12; + /* end of inner loop */ + } + /* compute left-over iterations */ + j += 12; + for (; j > 0; j--) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + p2=ell[lskip1]; + p3=ell[lskip2]; + p4=ell[lskip3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + Z21 += p2 * q1; + Z31 += p3 * q1; + Z41 += p4 * q1; + /* advance pointers */ + ell += 1; + ex += 1; + } + /* finish computing the X(i) block */ + Z11 = ex[0] - Z11; + ex[0] = Z11; + p1 = ell[lskip1]; + Z21 = ex[1] - Z21 - p1*Z11; + ex[1] = Z21; + p1 = ell[lskip2]; + p2 = ell[1+lskip2]; + Z31 = ex[2] - Z31 - p1*Z11 - p2*Z21; + ex[2] = Z31; + p1 = ell[lskip3]; + p2 = ell[1+lskip3]; + p3 = ell[2+lskip3]; + Z41 = ex[3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31; + ex[3] = Z41; + /* end of outer loop */ + } + /* compute rows at end that are not a multiple of block size */ + for (; i < n; i++) { + /* compute all 1 x 1 block of X, from rows i..i+1-1 */ + /* set the Z matrix to 0 */ + Z11=0; + ell = L + i*lskip1; + ex = B; + /* the inner loop that computes outer products and adds them to Z */ + for (j=i-12; j >= 0; j -= 12) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[1]; + q1=ex[1]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[2]; + q1=ex[2]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[3]; + q1=ex[3]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[4]; + q1=ex[4]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[5]; + q1=ex[5]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[6]; + q1=ex[6]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[7]; + q1=ex[7]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[8]; + q1=ex[8]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[9]; + q1=ex[9]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[10]; + q1=ex[10]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* load p and q values */ + p1=ell[11]; + q1=ex[11]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* advance pointers */ + ell += 12; + ex += 12; + /* end of inner loop */ + } + /* compute left-over iterations */ + j += 12; + for (; j > 0; j--) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + /* compute outer product and add it to the Z matrix */ + Z11 += p1 * q1; + /* advance pointers */ + ell += 1; + ex += 1; + } + /* finish computing the X(i) block */ + Z11 = ex[0] - Z11; + ex[0] = Z11; + } +} + +/* solve L^T * x=b, with b containing 1 right hand side. + * L is an n*n lower triangular matrix with ones on the diagonal. + * L is stored by rows and its leading dimension is lskip. + * b is an n*1 matrix that contains the right hand side. + * b is overwritten with x. + * this processes blocks of 4. + */ + +void btSolveL1T (const btScalar *L, btScalar *B, int n, int lskip1) +{ + /* declare variables - Z matrix, p and q vectors, etc */ + btScalar Z11,m11,Z21,m21,Z31,m31,Z41,m41,p1,q1,p2,p3,p4,*ex; + const btScalar *ell; + int lskip2,lskip3,i,j; + /* special handling for L and B because we're solving L1 *transpose* */ + L = L + (n-1)*(lskip1+1); + B = B + n-1; + lskip1 = -lskip1; + /* compute lskip values */ + lskip2 = 2*lskip1; + lskip3 = 3*lskip1; + /* compute all 4 x 1 blocks of X */ + for (i=0; i <= n-4; i+=4) { + /* compute all 4 x 1 block of X, from rows i..i+4-1 */ + /* set the Z matrix to 0 */ + Z11=0; + Z21=0; + Z31=0; + Z41=0; + ell = L - i; + ex = B; + /* the inner loop that computes outer products and adds them to Z */ + for (j=i-4; j >= 0; j -= 4) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + p2=ell[-1]; + p3=ell[-2]; + p4=ell[-3]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + m21 = p2 * q1; + m31 = p3 * q1; + m41 = p4 * q1; + ell += lskip1; + Z11 += m11; + Z21 += m21; + Z31 += m31; + Z41 += m41; + /* load p and q values */ + p1=ell[0]; + q1=ex[-1]; + p2=ell[-1]; + p3=ell[-2]; + p4=ell[-3]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + m21 = p2 * q1; + m31 = p3 * q1; + m41 = p4 * q1; + ell += lskip1; + Z11 += m11; + Z21 += m21; + Z31 += m31; + Z41 += m41; + /* load p and q values */ + p1=ell[0]; + q1=ex[-2]; + p2=ell[-1]; + p3=ell[-2]; + p4=ell[-3]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + m21 = p2 * q1; + m31 = p3 * q1; + m41 = p4 * q1; + ell += lskip1; + Z11 += m11; + Z21 += m21; + Z31 += m31; + Z41 += m41; + /* load p and q values */ + p1=ell[0]; + q1=ex[-3]; + p2=ell[-1]; + p3=ell[-2]; + p4=ell[-3]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + m21 = p2 * q1; + m31 = p3 * q1; + m41 = p4 * q1; + ell += lskip1; + ex -= 4; + Z11 += m11; + Z21 += m21; + Z31 += m31; + Z41 += m41; + /* end of inner loop */ + } + /* compute left-over iterations */ + j += 4; + for (; j > 0; j--) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + p2=ell[-1]; + p3=ell[-2]; + p4=ell[-3]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + m21 = p2 * q1; + m31 = p3 * q1; + m41 = p4 * q1; + ell += lskip1; + ex -= 1; + Z11 += m11; + Z21 += m21; + Z31 += m31; + Z41 += m41; + } + /* finish computing the X(i) block */ + Z11 = ex[0] - Z11; + ex[0] = Z11; + p1 = ell[-1]; + Z21 = ex[-1] - Z21 - p1*Z11; + ex[-1] = Z21; + p1 = ell[-2]; + p2 = ell[-2+lskip1]; + Z31 = ex[-2] - Z31 - p1*Z11 - p2*Z21; + ex[-2] = Z31; + p1 = ell[-3]; + p2 = ell[-3+lskip1]; + p3 = ell[-3+lskip2]; + Z41 = ex[-3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31; + ex[-3] = Z41; + /* end of outer loop */ + } + /* compute rows at end that are not a multiple of block size */ + for (; i < n; i++) { + /* compute all 1 x 1 block of X, from rows i..i+1-1 */ + /* set the Z matrix to 0 */ + Z11=0; + ell = L - i; + ex = B; + /* the inner loop that computes outer products and adds them to Z */ + for (j=i-4; j >= 0; j -= 4) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + ell += lskip1; + Z11 += m11; + /* load p and q values */ + p1=ell[0]; + q1=ex[-1]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + ell += lskip1; + Z11 += m11; + /* load p and q values */ + p1=ell[0]; + q1=ex[-2]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + ell += lskip1; + Z11 += m11; + /* load p and q values */ + p1=ell[0]; + q1=ex[-3]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + ell += lskip1; + ex -= 4; + Z11 += m11; + /* end of inner loop */ + } + /* compute left-over iterations */ + j += 4; + for (; j > 0; j--) { + /* load p and q values */ + p1=ell[0]; + q1=ex[0]; + /* compute outer product and add it to the Z matrix */ + m11 = p1 * q1; + ell += lskip1; + ex -= 1; + Z11 += m11; + } + /* finish computing the X(i) block */ + Z11 = ex[0] - Z11; + ex[0] = Z11; + } +} + + + +void btVectorScale (btScalar *a, const btScalar *d, int n) +{ + btAssert (a && d && n >= 0); + for (int i=0; i 0 && nskip >= n); + btSolveL1 (L,b,n,nskip); + btVectorScale (b,d,n); + btSolveL1T (L,b,n,nskip); +} + + + +//*************************************************************************** + +// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of +// A is nskip. this only references and swaps the lower triangle. +// if `do_fast_row_swaps' is nonzero and row pointers are being used, then +// rows will be swapped by exchanging row pointers. otherwise the data will +// be copied. + +static void btSwapRowsAndCols (BTATYPE A, int n, int i1, int i2, int nskip, + int do_fast_row_swaps) +{ + btAssert (A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n && + nskip >= n && i1 < i2); + +# ifdef BTROWPTRS + btScalar *A_i1 = A[i1]; + btScalar *A_i2 = A[i2]; + for (int i=i1+1; i0 && i1 >=0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 <= i2); + if (i1==i2) return; + + btSwapRowsAndCols (A,n,i1,i2,nskip,do_fast_row_swaps); + + tmpr = x[i1]; + x[i1] = x[i2]; + x[i2] = tmpr; + + tmpr = b[i1]; + b[i1] = b[i2]; + b[i2] = tmpr; + + tmpr = w[i1]; + w[i1] = w[i2]; + w[i2] = tmpr; + + tmpr = lo[i1]; + lo[i1] = lo[i2]; + lo[i2] = tmpr; + + tmpr = hi[i1]; + hi[i1] = hi[i2]; + hi[i2] = tmpr; + + tmpi = p[i1]; + p[i1] = p[i2]; + p[i2] = tmpi; + + tmpb = state[i1]; + state[i1] = state[i2]; + state[i2] = tmpb; + + if (findex) { + tmpi = findex[i1]; + findex[i1] = findex[i2]; + findex[i2] = tmpi; + } +} + + + + +//*************************************************************************** +// btLCP manipulator object. this represents an n*n LCP problem. +// +// two index sets C and N are kept. each set holds a subset of +// the variable indexes 0..n-1. an index can only be in one set. +// initially both sets are empty. +// +// the index set C is special: solutions to A(C,C)\A(C,i) can be generated. + +//*************************************************************************** +// fast implementation of btLCP. see the above definition of btLCP for +// interface comments. +// +// `p' records the permutation of A,x,b,w,etc. p is initially 1:n and is +// permuted as the other vectors/matrices are permuted. +// +// A,x,b,w,lo,hi,state,findex,p,c are permuted such that sets C,N have +// contiguous indexes. the don't-care indexes follow N. +// +// an L*D*L' factorization is maintained of A(C,C), and whenever indexes are +// added or removed from the set C the factorization is updated. +// thus L*D*L'=A[C,C], i.e. a permuted top left nC*nC submatrix of A. +// the leading dimension of the matrix L is always `nskip'. +// +// at the start there may be other indexes that are unbounded but are not +// included in `nub'. btLCP will permute the matrix so that absolutely all +// unbounded vectors are at the start. thus there may be some initial +// permutation. +// +// the algorithms here assume certain patterns, particularly with respect to +// index transfer. + +#ifdef btLCP_FAST + +struct btLCP +{ + const int m_n; + const int m_nskip; + int m_nub; + int m_nC, m_nN; // size of each index set + BTATYPE const m_A; // A rows + btScalar *const m_x, * const m_b, *const m_w, *const m_lo,* const m_hi; // permuted LCP problem data + btScalar *const m_L, *const m_d; // L*D*L' factorization of set C + btScalar *const m_Dell, *const m_ell, *const m_tmp; + bool *const m_state; + int *const m_findex, *const m_p, *const m_C; + + btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w, + btScalar *_lo, btScalar *_hi, btScalar *_L, btScalar *_d, + btScalar *_Dell, btScalar *_ell, btScalar *_tmp, + bool *_state, int *_findex, int *_p, int *_C, btScalar **Arows); + int getNub() const { return m_nub; } + void transfer_i_to_C (int i); + void transfer_i_to_N (int i) { m_nN++; } // because we can assume C and N span 1:i-1 + void transfer_i_from_N_to_C (int i); + void transfer_i_from_C_to_N (int i, btAlignedObjectArray& scratch); + int numC() const { return m_nC; } + int numN() const { return m_nN; } + int indexC (int i) const { return i; } + int indexN (int i) const { return i+m_nC; } + btScalar Aii (int i) const { return BTAROW(i)[i]; } + btScalar AiC_times_qC (int i, btScalar *q) const { return btLargeDot (BTAROW(i), q, m_nC); } + btScalar AiN_times_qN (int i, btScalar *q) const { return btLargeDot (BTAROW(i)+m_nC, q+m_nC, m_nN); } + void pN_equals_ANC_times_qC (btScalar *p, btScalar *q); + void pN_plusequals_ANi (btScalar *p, int i, int sign=1); + void pC_plusequals_s_times_qC (btScalar *p, btScalar s, btScalar *q); + void pN_plusequals_s_times_qN (btScalar *p, btScalar s, btScalar *q); + void solve1 (btScalar *a, int i, int dir=1, int only_transfer=0); + void unpermute(); +}; + + +btLCP::btLCP (int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w, + btScalar *_lo, btScalar *_hi, btScalar *_L, btScalar *_d, + btScalar *_Dell, btScalar *_ell, btScalar *_tmp, + bool *_state, int *_findex, int *_p, int *_C, btScalar **Arows): + m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0), +# ifdef BTROWPTRS + m_A(Arows), +#else + m_A(_Adata), +#endif + m_x(_x), m_b(_b), m_w(_w), m_lo(_lo), m_hi(_hi), + m_L(_L), m_d(_d), m_Dell(_Dell), m_ell(_ell), m_tmp(_tmp), + m_state(_state), m_findex(_findex), m_p(_p), m_C(_C) +{ + { + btSetZero (m_x,m_n); + } + + { +# ifdef BTROWPTRS + // make matrix row pointers + btScalar *aptr = _Adata; + BTATYPE A = m_A; + const int n = m_n, nskip = m_nskip; + for (int k=0; k nub + { + const int n = m_n; + const int nub = m_nub; + if (nub < n) { + for (int k=0; k<100; k++) { + int i1,i2; + do { + i1 = dRandInt(n-nub)+nub; + i2 = dRandInt(n-nub)+nub; + } + while (i1 > i2); + //printf ("--> %d %d\n",i1,i2); + btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,n,i1,i2,m_nskip,0); + } + } + */ + + // permute the problem so that *all* the unbounded variables are at the + // start, i.e. look for unbounded variables not included in `nub'. we can + // potentially push up `nub' this way and get a bigger initial factorization. + // note that when we swap rows/cols here we must not just swap row pointers, + // as the initial factorization relies on the data being all in one chunk. + // variables that have findex >= 0 are *not* considered to be unbounded even + // if lo=-inf and hi=inf - this is because these limits may change during the + // solution process. + + { + int *findex = m_findex; + btScalar *lo = m_lo, *hi = m_hi; + const int n = m_n; + for (int k = m_nub; k= 0) continue; + if (lo[k]==-BT_INFINITY && hi[k]==BT_INFINITY) { + btSwapProblem (m_A,m_x,m_b,m_w,lo,hi,m_p,m_state,findex,n,m_nub,k,m_nskip,0); + m_nub++; + } + } + } + + // if there are unbounded variables at the start, factorize A up to that + // point and solve for x. this puts all indexes 0..nub-1 into C. + if (m_nub > 0) { + const int nub = m_nub; + { + btScalar *Lrow = m_L; + const int nskip = m_nskip; + for (int j=0; j nub such that all findex variables are at the end + if (m_findex) { + const int nub = m_nub; + int *findex = m_findex; + int num_at_end = 0; + for (int k=m_n-1; k >= nub; k--) { + if (findex[k] >= 0) { + btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,findex,m_n,k,m_n-1-num_at_end,m_nskip,1); + num_at_end++; + } + } + } + + // print info about indexes + /* + { + const int n = m_n; + const int nub = m_nub; + for (int k=0; k 0) { + // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C)) + { + const int nC = m_nC; + btScalar *const Ltgt = m_L + nC*m_nskip, *ell = m_ell; + for (int j=0; j 0) { + { + btScalar *const aptr = BTAROW(i); + btScalar *Dell = m_Dell; + const int *C = m_C; +# ifdef BTNUB_OPTIMIZATIONS + // if nub>0, initial part of aptr unpermuted + const int nub = m_nub; + int j=0; + for ( ; j 0 && nskip >= n && r >= 0 && r < n); + if (r >= n-1) return; + if (r > 0) { + { + const size_t move_size = (n-r-1)*sizeof(btScalar); + btScalar *Adst = A + r; + for (int i=0; i& scratch) +{ + btAssert (L && d && a && n > 0 && nskip >= n); + + if (n < 2) return; + scratch.resize(2*nskip); + btScalar *W1 = &scratch[0]; + + btScalar *W2 = W1 + nskip; + + W1[0] = btScalar(0.0); + W2[0] = btScalar(0.0); + for (int j=1; j j) ? _BTGETA(i,j) : _BTGETA(j,i)) + +inline size_t btEstimateLDLTAddTLTmpbufSize(int nskip) +{ + return nskip * 2 * sizeof(btScalar); +} + + +void btLDLTRemove (btScalar **A, const int *p, btScalar *L, btScalar *d, + int n1, int n2, int r, int nskip, btAlignedObjectArray& scratch) +{ + btAssert(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 && + n1 >= n2 && nskip >= n1); + #ifdef BT_DEBUG + for (int i=0; i= 0 && p[i] < n1); + #endif + + if (r==n2-1) { + return; // deleting last row/col is easy + } + else { + size_t LDLTAddTL_size = btEstimateLDLTAddTLTmpbufSize(nskip); + btAssert(LDLTAddTL_size % sizeof(btScalar) == 0); + scratch.resize(nskip * 2+n2); + btScalar *tmp = &scratch[0]; + if (r==0) { + btScalar *a = (btScalar *)((char *)tmp + LDLTAddTL_size); + const int p_0 = p[0]; + for (int i=0; i& scratch) +{ + { + int *C = m_C; + // remove a row/column from the factorization, and adjust the + // indexes (black magic!) + int last_idx = -1; + const int nC = m_nC; + int j = 0; + for ( ; j 0) { + const int nN = m_nN; + for (int j=0; j 0) { + { + btScalar *Dell = m_Dell; + int *C = m_C; + btScalar *aptr = BTAROW(i); +# ifdef BTNUB_OPTIMIZATIONS + // if nub>0, initial part of aptr[] is guaranteed unpermuted + const int nub = m_nub; + int j=0; + for ( ; j 0) { + int *C = m_C; + btScalar *tmp = m_tmp; + const int nC = m_nC; + for (int j=0; j0 && A && x && b && lo && hi && nub >= 0 && nub <= n); + btAssert(outer_w); + +#ifdef BT_DEBUG + { + // check restrictions on lo and hi + for (int k=0; k= 0); + } +# endif + + + // if all the variables are unbounded then we can just factor, solve, + // and return + if (nub >= n) + { + + + int nskip = (n); + btFactorLDLT (A, outer_w, n, nskip); + btSolveLDLT (A, outer_w, b, n, nskip); + memcpy (x, b, n*sizeof(btScalar)); + + return !s_error; + } + + const int nskip = (n); + scratchMem.L.resize(n*nskip); + + scratchMem.d.resize(n); + + btScalar *w = outer_w; + scratchMem.delta_w.resize(n); + scratchMem.delta_x.resize(n); + scratchMem.Dell.resize(n); + scratchMem.ell.resize(n); + scratchMem.Arows.resize(n); + scratchMem.p.resize(n); + scratchMem.C.resize(n); + + // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i) + scratchMem.state.resize(n); + + + // create LCP object. note that tmp is set to delta_w to save space, this + // optimization relies on knowledge of how tmp is used, so be careful! + btLCP lcp(n,nskip,nub,A,x,b,w,lo,hi,&scratchMem.L[0],&scratchMem.d[0],&scratchMem.Dell[0],&scratchMem.ell[0],&scratchMem.delta_w[0],&scratchMem.state[0],findex,&scratchMem.p[0],&scratchMem.C[0],&scratchMem.Arows[0]); + int adj_nub = lcp.getNub(); + + // loop over all indexes adj_nub..n-1. for index i, if x(i),w(i) satisfy the + // LCP conditions then i is added to the appropriate index set. otherwise + // x(i),w(i) is driven either +ve or -ve to force it to the valid region. + // as we drive x(i), x(C) is also adjusted to keep w(C) at zero. + // while driving x(i) we maintain the LCP conditions on the other variables + // 0..i-1. we do this by watching out for other x(i),w(i) values going + // outside the valid region, and then switching them between index sets + // when that happens. + + bool hit_first_friction_index = false; + for (int i=adj_nub; i= 0) { + // un-permute x into delta_w, which is not being used at the moment + for (int j=0; j= 0) { + lcp.transfer_i_to_N (i); + scratchMem.state[i] = false; + } + else if (hi[i]==0 && w[i] <= 0) { + lcp.transfer_i_to_N (i); + scratchMem.state[i] = true; + } + else if (w[i]==0) { + // this is a degenerate case. by the time we get to this test we know + // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve, + // and similarly that hi > 0. this means that the line segment + // corresponding to set C is at least finite in extent, and we are on it. + // NOTE: we must call lcp.solve1() before lcp.transfer_i_to_C() + lcp.solve1 (&scratchMem.delta_x[0],i,0,1); + + lcp.transfer_i_to_C (i); + } + else { + // we must push x(i) and w(i) + for (;;) { + int dir; + btScalar dirf; + // find direction to push on x(i) + if (w[i] <= 0) { + dir = 1; + dirf = btScalar(1.0); + } + else { + dir = -1; + dirf = btScalar(-1.0); + } + + // compute: delta_x(C) = -dir*A(C,C)\A(C,i) + lcp.solve1 (&scratchMem.delta_x[0],i,dir); + + // note that delta_x[i] = dirf, but we wont bother to set it + + // compute: delta_w = A*delta_x ... note we only care about + // delta_w(N) and delta_w(i), the rest is ignored + lcp.pN_equals_ANC_times_qC (&scratchMem.delta_w[0],&scratchMem.delta_x[0]); + lcp.pN_plusequals_ANi (&scratchMem.delta_w[0],i,dir); + scratchMem.delta_w[i] = lcp.AiC_times_qC (i,&scratchMem.delta_x[0]) + lcp.Aii(i)*dirf; + + // find largest step we can take (size=s), either to drive x(i),w(i) + // to the valid LCP region or to drive an already-valid variable + // outside the valid region. + + int cmd = 1; // index switching command + int si = 0; // si = index to switch if cmd>3 + btScalar s = -w[i]/scratchMem.delta_w[i]; + if (dir > 0) { + if (hi[i] < BT_INFINITY) { + btScalar s2 = (hi[i]-x[i])*dirf; // was (hi[i]-x[i])/dirf // step to x(i)=hi(i) + if (s2 < s) { + s = s2; + cmd = 3; + } + } + } + else { + if (lo[i] > -BT_INFINITY) { + btScalar s2 = (lo[i]-x[i])*dirf; // was (lo[i]-x[i])/dirf // step to x(i)=lo(i) + if (s2 < s) { + s = s2; + cmd = 2; + } + } + } + + { + const int numN = lcp.numN(); + for (int k=0; k < numN; ++k) { + const int indexN_k = lcp.indexN(k); + if (!scratchMem.state[indexN_k] ? scratchMem.delta_w[indexN_k] < 0 : scratchMem.delta_w[indexN_k] > 0) { + // don't bother checking if lo=hi=0 + if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue; + btScalar s2 = -w[indexN_k] / scratchMem.delta_w[indexN_k]; + if (s2 < s) { + s = s2; + cmd = 4; + si = indexN_k; + } + } + } + } + + { + const int numC = lcp.numC(); + for (int k=adj_nub; k < numC; ++k) { + const int indexC_k = lcp.indexC(k); + if (scratchMem.delta_x[indexC_k] < 0 && lo[indexC_k] > -BT_INFINITY) { + btScalar s2 = (lo[indexC_k]-x[indexC_k]) / scratchMem.delta_x[indexC_k]; + if (s2 < s) { + s = s2; + cmd = 5; + si = indexC_k; + } + } + if (scratchMem.delta_x[indexC_k] > 0 && hi[indexC_k] < BT_INFINITY) { + btScalar s2 = (hi[indexC_k]-x[indexC_k]) / scratchMem.delta_x[indexC_k]; + if (s2 < s) { + s = s2; + cmd = 6; + si = indexC_k; + } + } + } + } + + //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C", + // "C->NL","C->NH"}; + //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i); + + // if s <= 0 then we've got a problem. if we just keep going then + // we're going to get stuck in an infinite loop. instead, just cross + // our fingers and exit with the current solution. + if (s <= btScalar(0.0)) + { +// printf("LCP internal error, s <= 0 (s=%.4e)",(double)s); + if (i < n) { + btSetZero (x+i,n-i); + btSetZero (w+i,n-i); + } + s_error = true; + break; + } + + // apply x = x + s * delta_x + lcp.pC_plusequals_s_times_qC (x, s, &scratchMem.delta_x[0]); + x[i] += s * dirf; + + // apply w = w + s * delta_w + lcp.pN_plusequals_s_times_qN (w, s, &scratchMem.delta_w[0]); + w[i] += s * scratchMem.delta_w[i]; + +// void *tmpbuf; + // switch indexes between sets if necessary + switch (cmd) { + case 1: // done + w[i] = 0; + lcp.transfer_i_to_C (i); + break; + case 2: // done + x[i] = lo[i]; + scratchMem.state[i] = false; + lcp.transfer_i_to_N (i); + break; + case 3: // done + x[i] = hi[i]; + scratchMem.state[i] = true; + lcp.transfer_i_to_N (i); + break; + case 4: // keep going + w[si] = 0; + lcp.transfer_i_from_N_to_C (si); + break; + case 5: // keep going + x[si] = lo[si]; + scratchMem.state[si] = false; + lcp.transfer_i_from_C_to_N (si, scratchMem.m_scratch); + break; + case 6: // keep going + x[si] = hi[si]; + scratchMem.state[si] = true; + lcp.transfer_i_from_C_to_N (si, scratchMem.m_scratch); + break; + } + + if (cmd <= 3) break; + } // for (;;) + } // else + + if (s_error) + { + break; + } + } // for (int i=adj_nub; i= 0 + (2) x = hi, w <= 0 + (3) lo < x < hi, w = 0 +A is a matrix of dimension n*n, everything else is a vector of size n*1. +lo and hi can be +/- dInfinity as needed. the first `nub' variables are +unbounded, i.e. hi and lo are assumed to be +/- dInfinity. + +we restrict lo(i) <= 0 and hi(i) >= 0. + +the original data (A,b) may be modified by this function. + +if the `findex' (friction index) parameter is nonzero, it points to an array +of index values. in this case constraints that have findex[i] >= 0 are +special. all non-special constraints are solved for, then the lo and hi values +for the special constraints are set: + hi[i] = abs( hi[i] * x[findex[i]] ) + lo[i] = -hi[i] +and the solution continues. this mechanism allows a friction approximation +to be implemented. the first `nub' variables are assumed to have findex < 0. + +*/ + + +#ifndef _BT_LCP_H_ +#define _BT_LCP_H_ + +#include +#include +#include + + +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" + +struct btDantzigScratchMemory +{ + btAlignedObjectArray m_scratch; + btAlignedObjectArray L; + btAlignedObjectArray d; + btAlignedObjectArray delta_w; + btAlignedObjectArray delta_x; + btAlignedObjectArray Dell; + btAlignedObjectArray ell; + btAlignedObjectArray Arows; + btAlignedObjectArray p; + btAlignedObjectArray C; + btAlignedObjectArray state; +}; + +//return false if solving failed +bool btSolveDantzigLCP (int n, btScalar *A, btScalar *x, btScalar *b, btScalar *w, + int nub, btScalar *lo, btScalar *hi, int *findex,btDantzigScratchMemory& scratch); + + + +#endif //_BT_LCP_H_ diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h new file mode 100644 index 00000000..2a2f2d3d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h @@ -0,0 +1,112 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +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. +*/ +///original version written by Erwin Coumans, October 2013 + +#ifndef BT_DANTZIG_SOLVER_H +#define BT_DANTZIG_SOLVER_H + +#include "btMLCPSolverInterface.h" +#include "btDantzigLCP.h" + + +class btDantzigSolver : public btMLCPSolverInterface +{ +protected: + + btScalar m_acceptableUpperLimitSolution; + + btAlignedObjectArray m_tempBuffer; + + btAlignedObjectArray m_A; + btAlignedObjectArray m_b; + btAlignedObjectArray m_x; + btAlignedObjectArray m_lo; + btAlignedObjectArray m_hi; + btAlignedObjectArray m_dependencies; + btDantzigScratchMemory m_scratchMemory; +public: + + btDantzigSolver() + :m_acceptableUpperLimitSolution(btScalar(1000)) + { + } + + virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray& limitDependency, int numIterations, bool useSparsity = true) + { + bool result = true; + int n = b.rows(); + if (n) + { + int nub = 0; + btAlignedObjectArray ww; + ww.resize(n); + + + const btScalar* Aptr = A.getBufferPointer(); + m_A.resize(n*n); + for (int i=0;i= m_acceptableUpperLimitSolution) + { + return false; + } + + if (x[i] <= -m_acceptableUpperLimitSolution) + { + return false; + } + } + + for (int i=0;i limitDependenciesCopy = m_limitDependencies; +// printf("solve first LCP\n"); + result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo,m_hi, m_limitDependencies,infoGlobal.m_numIterations ); + if (result) + result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo,m_hi, limitDependenciesCopy,infoGlobal.m_numIterations ); + + } else + { + result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo,m_hi, m_limitDependencies,infoGlobal.m_numIterations ); + } + return result; +} + +struct btJointNode +{ + int jointIndex; // pointer to enclosing dxJoint object + int otherBodyIndex; // *other* body this joint is connected to + int nextJointNodeIndex;//-1 for null + int constraintRowIndex; +}; + + + +void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal) +{ + int numContactRows = interleaveContactAndFriction ? 3 : 1; + + int numConstraintRows = m_allConstraintArray.size(); + int n = numConstraintRows; + { + BT_PROFILE("init b (rhs)"); + m_b.resize(numConstraintRows); + m_bSplit.resize(numConstraintRows); + //m_b.setZero(); + for (int i=0;i=0) + { + m_lo[i] = -BT_INFINITY; + m_hi[i] = BT_INFINITY; + } else + { + m_lo[i] = m_allConstraintArray[i].m_lowerLimit; + m_hi[i] = m_allConstraintArray[i].m_upperLimit; + } + } + } + + // + int m=m_allConstraintArray.size(); + + int numBodies = m_tmpSolverBodyPool.size(); + btAlignedObjectArray bodyJointNodeArray; + { + BT_PROFILE("bodyJointNodeArray.resize"); + bodyJointNodeArray.resize(numBodies,-1); + } + btAlignedObjectArray jointNodeArray; + { + BT_PROFILE("jointNodeArray.reserve"); + jointNodeArray.reserve(2*m_allConstraintArray.size()); + } + + static btMatrixXu J3; + { + BT_PROFILE("J3.resize"); + J3.resize(2*m,8); + } + static btMatrixXu JinvM3; + { + BT_PROFILE("JinvM3.resize/setZero"); + + JinvM3.resize(2*m,8); + JinvM3.setZero(); + J3.setZero(); + } + int cur=0; + int rowOffset = 0; + static btAlignedObjectArray ofs; + { + BT_PROFILE("ofs resize"); + ofs.resize(0); + ofs.resizeNoInitialize(m_allConstraintArray.size()); + } + { + BT_PROFILE("Compute J and JinvM"); + int c=0; + + int numRows = 0; + + for (int i=0;igetInvMass(); + btVector3 relPosCrossNormalInvInertia = m_allConstraintArray[i+row].m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld(); + + for (int r=0;r<3;r++) + { + J3.setElem(cur,r,m_allConstraintArray[i+row].m_contactNormal1[r]); + J3.setElem(cur,r+4,m_allConstraintArray[i+row].m_relpos1CrossNormal[r]); + JinvM3.setElem(cur,r,normalInvMass[r]); + JinvM3.setElem(cur,r+4,relPosCrossNormalInvInertia[r]); + } + J3.setElem(cur,3,0); + JinvM3.setElem(cur,3,0); + J3.setElem(cur,7,0); + JinvM3.setElem(cur,7,0); + } + } else + { + cur += numRows; + } + if (orgBodyB) + { + + { + int slotB=-1; + //find free jointNode slot for sbA + slotB =jointNodeArray.size(); + jointNodeArray.expand();//NonInitializing(); + int prevSlot = bodyJointNodeArray[sbB]; + bodyJointNodeArray[sbB] = slotB; + jointNodeArray[slotB].nextJointNodeIndex = prevSlot; + jointNodeArray[slotB].jointIndex = c; + jointNodeArray[slotB].otherBodyIndex = orgBodyA ? sbA : -1; + jointNodeArray[slotB].constraintRowIndex = i; + } + + for (int row=0;rowgetInvMass(); + btVector3 relPosInvInertiaB = m_allConstraintArray[i+row].m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld(); + + for (int r=0;r<3;r++) + { + J3.setElem(cur,r,m_allConstraintArray[i+row].m_contactNormal2[r]); + J3.setElem(cur,r+4,m_allConstraintArray[i+row].m_relpos2CrossNormal[r]); + JinvM3.setElem(cur,r,normalInvMassB[r]); + JinvM3.setElem(cur,r+4,relPosInvInertiaB[r]); + } + J3.setElem(cur,3,0); + JinvM3.setElem(cur,3,0); + J3.setElem(cur,7,0); + JinvM3.setElem(cur,7,0); + } + } + else + { + cur += numRows; + } + rowOffset+=numRows; + + } + + } + + + //compute JinvM = J*invM. + const btScalar* JinvM = JinvM3.getBufferPointer(); + + const btScalar* Jptr = J3.getBufferPointer(); + { + BT_PROFILE("m_A.resize"); + m_A.resize(n,n); + } + + { + BT_PROFILE("m_A.setZero"); + m_A.setZero(); + } + int c=0; + { + int numRows = 0; + BT_PROFILE("Compute A"); + for (int i=0;i=0) + { + int j0 = jointNodeArray[startJointNodeA].jointIndex; + int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex; + if (j0=0) + { + int j1 = jointNodeArray[startJointNodeB].jointIndex; + int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex; + + if (j1m_tmpSolverBodyPool.size(); + int numConstraintRows = m_allConstraintArray.size(); + + m_b.resize(numConstraintRows); + if (infoGlobal.m_splitImpulse) + m_bSplit.resize(numConstraintRows); + + for (int i=0;igetInvInertiaTensorWorld()[r][c] : 0); + } + + static btMatrixXu J; + J.resize(numConstraintRows,6*numBodies); + J.setZero(); + + m_lo.resize(numConstraintRows); + m_hi.resize(numConstraintRows); + + for (int i=0;i m_limitDependencies; + btConstraintArray m_allConstraintArray; + btMLCPSolverInterface* m_solver; + int m_fallback; + + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + virtual void createMLCP(const btContactSolverInfo& infoGlobal); + virtual void createMLCPFast(const btContactSolverInfo& infoGlobal); + + //return true is it solves the problem successfully + virtual bool solveMLCP(const btContactSolverInfo& infoGlobal); + +public: + + btMLCPSolver( btMLCPSolverInterface* solver); + virtual ~btMLCPSolver(); + + void setMLCPSolver(btMLCPSolverInterface* solver) + { + m_solver = solver; + } + + int getNumFallbacks() const + { + return m_fallback; + } + void setNumFallbacks(int num) + { + m_fallback = num; + } + + virtual btConstraintSolverType getSolverType() const + { + return BT_MLCP_SOLVER; + } + +}; + + +#endif //BT_MLCP_SOLVER_H diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h new file mode 100644 index 00000000..25bb3f6d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h @@ -0,0 +1,33 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +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. +*/ +///original version written by Erwin Coumans, October 2013 + +#ifndef BT_MLCP_SOLVER_INTERFACE_H +#define BT_MLCP_SOLVER_INTERFACE_H + +#include "LinearMath/btMatrixX.h" + +class btMLCPSolverInterface +{ +public: + virtual ~btMLCPSolverInterface() + { + } + + //return true is it solves the problem successfully + virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray& limitDependency, int numIterations, bool useSparsity = true)=0; +}; + +#endif //BT_MLCP_SOLVER_INTERFACE_H diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btPATHSolver.h b/Code/Physics/src/BulletDynamics/MLCPSolvers/btPATHSolver.h new file mode 100644 index 00000000..9ec31a6d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/MLCPSolvers/btPATHSolver.h @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +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. +*/ +///original version written by Erwin Coumans, October 2013 + + +#ifndef BT_PATH_SOLVER_H +#define BT_PATH_SOLVER_H + +//#define BT_USE_PATH +#ifdef BT_USE_PATH + +extern "C" { +#include "PATH/SimpleLCP.h" +#include "PATH/License.h" +#include "PATH/Error_Interface.h" +}; + void __stdcall MyError(Void *data, Char *msg) +{ + printf("Path Error: %s\n",msg); +} + void __stdcall MyWarning(Void *data, Char *msg) +{ + printf("Path Warning: %s\n",msg); +} + +Error_Interface e; + + + +#include "btMLCPSolverInterface.h" +#include "Dantzig/lcp.h" + +class btPathSolver : public btMLCPSolverInterface +{ +public: + + btPathSolver() + { + License_SetString("2069810742&Courtesy_License&&&USR&2013&14_12_2011&1000&PATH&GEN&31_12_2013&0_0_0&0&0_0"); + e.error_data = 0; + e.warning = MyWarning; + e.error = MyError; + Error_SetInterface(&e); + } + + + virtual bool solveMLCP(const btMatrixXu & A, const btVectorXu & b, btVectorXu& x, const btVectorXu & lo,const btVectorXu & hi,const btAlignedObjectArray& limitDependency, int numIterations, bool useSparsity = true) + { + MCP_Termination status; + + + int numVariables = b.rows(); + if (0==numVariables) + return true; + + /* - variables - the number of variables in the problem + - m_nnz - the number of nonzeros in the M matrix + - m_i - a vector of size m_nnz containing the row indices for M + - m_j - a vector of size m_nnz containing the column indices for M + - m_ij - a vector of size m_nnz containing the data for M + - q - a vector of size variables + - lb - a vector of size variables containing the lower bounds on x + - ub - a vector of size variables containing the upper bounds on x + */ + btAlignedObjectArray values; + btAlignedObjectArray rowIndices; + btAlignedObjectArray colIndices; + + for (int i=0;i zResult; + zResult.resize(numVariables); + btAlignedObjectArray rhs; + btAlignedObjectArray upperBounds; + btAlignedObjectArray lowerBounds; + for (int i=0;i& limitDependency, int numIterations, bool useSparsity = true) + { + //A is a m-n matrix, m rows, n columns + btAssert(A.rows() == b.rows()); + + int i, j, numRows = A.rows(); + + float delta; + + for (int k = 0; k =0) + { + s = x[limitDependency[i]]; + if (s<0) + s=1; + } + + if (x[i]hi[i]*s) + x[i]=hi[i]*s; + } + } + return true; + } + +}; + +#endif //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp new file mode 100644 index 00000000..77b475b9 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -0,0 +1,771 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ + +#include "LinearMath/btVector3.h" +#include "btRaycastVehicle.h" + +#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h" +#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h" +#include "LinearMath/btQuaternion.h" +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" +#include "btVehicleRaycaster.h" +#include "btWheelInfo.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + +#define ROLLING_INFLUENCE_FIX + + +btRigidBody& btActionInterface::getFixedBody() +{ + static btRigidBody s_fixed(0, 0,0); + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + return s_fixed; +} + +btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) +:m_vehicleRaycaster(raycaster), +m_pitchControl(btScalar(0.)) +{ + m_chassisBody = chassis; + m_indexRightAxis = 0; + m_indexUpAxis = 2; + m_indexForwardAxis = 1; + defaultInit(tuning); +} + + +void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning) +{ + (void)tuning; + m_currentVehicleSpeedKmHour = btScalar(0.); + m_steeringValue = btScalar(0.); + +} + + + +btRaycastVehicle::~btRaycastVehicle() +{ +} + + +// +// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed +// +btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel) +{ + + btWheelInfoConstructionInfo ci; + + ci.m_chassisConnectionCS = connectionPointCS; + ci.m_wheelDirectionCS = wheelDirectionCS0; + ci.m_wheelAxleCS = wheelAxleCS; + ci.m_suspensionRestLength = suspensionRestLength; + ci.m_wheelRadius = wheelRadius; + ci.m_suspensionStiffness = tuning.m_suspensionStiffness; + ci.m_wheelsDampingCompression = tuning.m_suspensionCompression; + ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping; + ci.m_frictionSlip = tuning.m_frictionSlip; + ci.m_bIsFrontWheel = isFrontWheel; + ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm; + ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce; + + m_wheelInfo.push_back( btWheelInfo(ci)); + + btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1]; + + updateWheelTransformsWS( wheel , false ); + updateWheelTransform(getNumWheels()-1,false); + return wheel; +} + + + + +const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const +{ + btAssert(wheelIndex < getNumWheels()); + const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; + return wheel.m_worldTransform; + +} + +void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform) +{ + + btWheelInfo& wheel = m_wheelInfo[ wheelIndex ]; + updateWheelTransformsWS(wheel,interpolatedTransform); + btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS; + const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS; + btVector3 fwd = up.cross(right); + fwd = fwd.normalize(); +// up = right.cross(fwd); +// up.normalize(); + + //rotate around steering over de wheelAxleWS + btScalar steering = wheel.m_steering; + + btQuaternion steeringOrn(up,steering);//wheel.m_steering); + btMatrix3x3 steeringMat(steeringOrn); + + btQuaternion rotatingOrn(right,-wheel.m_rotation); + btMatrix3x3 rotatingMat(rotatingOrn); + + btMatrix3x3 basis2( + right[0],fwd[0],up[0], + right[1],fwd[1],up[1], + right[2],fwd[2],up[2] + ); + + wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2); + wheel.m_worldTransform.setOrigin( + wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength + ); +} + +void btRaycastVehicle::resetSuspension() +{ + + int i; + for (i=0;igetMotionState())) + { + getRigidBody()->getMotionState()->getWorldTransform(chassisTrans); + } + + wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS ); + wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ; + wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS; +} + +btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel) +{ + updateWheelTransformsWS( wheel,false); + + + btScalar depth = -1; + + btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; + + btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); + const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; + wheel.m_raycastInfo.m_contactPointWS = source + rayvector; + const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; + + btScalar param = btScalar(0.); + + btVehicleRaycaster::btVehicleRaycasterResult rayResults; + + btAssert(m_vehicleRaycaster); + + void* object = m_vehicleRaycaster->castRay(source,target,rayResults); + + wheel.m_raycastInfo.m_groundObject = 0; + + if (object) + { + param = rayResults.m_distFraction; + depth = raylen * rayResults.m_distFraction; + wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; + wheel.m_raycastInfo.m_isInContact = true; + + wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!; + //wheel.m_raycastInfo.m_groundObject = object; + + + btScalar hitDistance = param*raylen; + wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; + //clamp on max suspension travel + + btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); + btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); + if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; + } + if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; + } + + wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; + + btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); + + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); + + chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); + + btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + + if ( denominator >= btScalar(-0.1)) + { + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / denominator; + wheel.m_suspensionRelativeVelocity = projVel * inv; + wheel.m_clippedInvContactDotSuspension = inv; + } + + } else + { + //put wheel info as in rest position + wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; + wheel.m_clippedInvContactDotSuspension = btScalar(1.0); + } + + return depth; +} + + +const btTransform& btRaycastVehicle::getChassisWorldTransform() const +{ + /*if (getRigidBody()->getMotionState()) + { + btTransform chassisWorldTrans; + getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans); + return chassisWorldTrans; + } + */ + + + return getRigidBody()->getCenterOfMassTransform(); +} + + +void btRaycastVehicle::updateVehicle( btScalar step ) +{ + { + for (int i=0;igetLinearVelocity().length(); + + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) + { + m_currentVehicleSpeedKmHour *= btScalar(-1.); + } + + // + // simulate suspension + // + + int i=0; + for (i=0;i wheel.m_maxSuspensionForce) + { + suspensionForce = wheel.m_maxSuspensionForce; + } + btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); + + getRigidBody()->applyImpulse(impulse, relpos); + + } + + + + updateFriction( step); + + + for (i=0;igetCenterOfMassPosition(); + btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); + + if (wheel.m_raycastInfo.m_isInContact) + { + const btTransform& chassisWorldTransform = getChassisWorldTransform(); + + btVector3 fwd ( + chassisWorldTransform.getBasis()[0][m_indexForwardAxis], + chassisWorldTransform.getBasis()[1][m_indexForwardAxis], + chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); + + btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); + fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; + + btScalar proj2 = fwd.dot(vel); + + wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); + wheel.m_rotation += wheel.m_deltaRotation; + + } else + { + wheel.m_rotation += wheel.m_deltaRotation; + } + + wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact + + } + + + +} + + +void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) +{ + btAssert(wheel>=0 && wheel < getNumWheels()); + + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_steering = steering; +} + + + +btScalar btRaycastVehicle::getSteeringValue(int wheel) const +{ + return getWheelInfo(wheel).m_steering; +} + + +void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) +{ + btAssert(wheel>=0 && wheel < getNumWheels()); + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_engineForce = force; +} + + +const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +btWheelInfo& btRaycastVehicle::getWheelInfo(int index) +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex) +{ + btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels())); + getWheelInfo(wheelIndex).m_brake = brake; +} + + +void btRaycastVehicle::updateSuspension(btScalar deltaTime) +{ + (void)deltaTime; + + btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); + + for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar relaxation = 1.f; + m_jacDiagABInv = relaxation/(denom0+denom1); + } + + + +}; + +btScalar calcRollingFriction(btWheelContactPoint& contactPoint); +btScalar calcRollingFriction(btWheelContactPoint& contactPoint) +{ + + btScalar j1=0.f; + + const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld; + + btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); + btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition(); + + btScalar maxImpulse = contactPoint.m_maxImpulse; + + btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel); + + // calculate j that moves us to zero relative velocity + j1 = -vrel * contactPoint.m_jacDiagABInv; + btSetMin(j1, maxImpulse); + btSetMax(j1, -maxImpulse); + + return j1; +} + + + + +btScalar sideFrictionStiffness2 = btScalar(1.0); +void btRaycastVehicle::updateFriction(btScalar timeStep) +{ + + //calculate the impulse, so that the wheels don't move sidewards + int numWheel = getNumWheels(); + if (!numWheel) + return; + + m_forwardWS.resize(numWheel); + m_axle.resize(numWheel); + m_forwardImpulse.resize(numWheel); + m_sideImpulse.resize(numWheel); + + int numWheelsOnGround = 0; + + + //collapse all those loops into one! + for (int i=0;i maximpSquared) + { + sliding = true; + + btScalar factor = maximp / btSqrt(impulseSquared); + + m_wheelInfo[wheel].m_skidInfo *= factor; + } + } + + } + } + + + + + if (sliding) + { + for (int wheel = 0;wheel < getNumWheels(); wheel++) + { + if (m_sideImpulse[wheel] != btScalar(0.)) + { + if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) + { + m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + } + } + } + } + + // apply the impulses + { + for (int wheel = 0;wheelgetCenterOfMassPosition(); + + if (m_forwardImpulse[wheel] != btScalar(0.)) + { + m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); + } + if (m_sideImpulse[wheel] != btScalar(0.)) + { + class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; + + btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - + groundObject->getCenterOfMassPosition(); + + + btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; + +#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT. + btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis); + rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence)); +#else + rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence; +#endif + m_chassisBody->applyImpulse(sideImp,rel_pos); + + //apply friction impulse on the ground + groundObject->applyImpulse(-sideImp,rel_pos2); + } + } + } + + +} + + + +void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer) +{ + + for (int v=0;vgetNumWheels();v++) + { + btVector3 wheelColor(0,1,1); + if (getWheelInfo(v).m_raycastInfo.m_isInContact) + { + wheelColor.setValue(0,0,1); + } else + { + wheelColor.setValue(1,0,1); + } + + btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin(); + + btVector3 axle = btVector3( + getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()], + getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]); + + //debug wheels (cylinders) + debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); + debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); + + } +} + + +void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) +{ +// RayResultCallback& resultCallback; + + btCollisionWorld::ClosestRayResultCallback rayCallback(from,to); + + m_dynamicsWorld->rayTest(from, to, rayCallback); + + if (rayCallback.hasHit()) + { + + const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body && body->hasContactResponse()) + { + result.m_hitPointInWorld = rayCallback.m_hitPointWorld; + result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; + result.m_hitNormalInWorld.normalize(); + result.m_distFraction = rayCallback.m_closestHitFraction; + return (void*)body; + } + } + return 0; +} + diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.h new file mode 100644 index 00000000..f59555f9 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef BT_RAYCASTVEHICLE_H +#define BT_RAYCASTVEHICLE_H + +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "btVehicleRaycaster.h" +class btDynamicsWorld; +#include "LinearMath/btAlignedObjectArray.h" +#include "btWheelInfo.h" +#include "BulletDynamics/Dynamics/btActionInterface.h" + +class btVehicleTuning; + +///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. +class btRaycastVehicle : public btActionInterface +{ + + btAlignedObjectArray m_forwardWS; + btAlignedObjectArray m_axle; + btAlignedObjectArray m_forwardImpulse; + btAlignedObjectArray m_sideImpulse; + + ///backwards compatibility + int m_userConstraintType; + int m_userConstraintId; + +public: + class btVehicleTuning + { + public: + + btVehicleTuning() + :m_suspensionStiffness(btScalar(5.88)), + m_suspensionCompression(btScalar(0.83)), + m_suspensionDamping(btScalar(0.88)), + m_maxSuspensionTravelCm(btScalar(500.)), + m_frictionSlip(btScalar(10.5)), + m_maxSuspensionForce(btScalar(6000.)) + { + } + btScalar m_suspensionStiffness; + btScalar m_suspensionCompression; + btScalar m_suspensionDamping; + btScalar m_maxSuspensionTravelCm; + btScalar m_frictionSlip; + btScalar m_maxSuspensionForce; + + }; +private: + + btScalar m_tau; + btScalar m_damping; + btVehicleRaycaster* m_vehicleRaycaster; + btScalar m_pitchControl; + btScalar m_steeringValue; + btScalar m_currentVehicleSpeedKmHour; + + btRigidBody* m_chassisBody; + + int m_indexRightAxis; + int m_indexUpAxis; + int m_indexForwardAxis; + + void defaultInit(const btVehicleTuning& tuning); + +public: + + //constructor to create a car from an existing rigidbody + btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ); + + virtual ~btRaycastVehicle() ; + + + ///btActionInterface interface + virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step) + { + (void) collisionWorld; + updateVehicle(step); + } + + + ///btActionInterface interface + void debugDraw(btIDebugDraw* debugDrawer); + + const btTransform& getChassisWorldTransform() const; + + btScalar rayCast(btWheelInfo& wheel); + + virtual void updateVehicle(btScalar step); + + + void resetSuspension(); + + btScalar getSteeringValue(int wheel) const; + + void setSteeringValue(btScalar steering,int wheel); + + + void applyEngineForce(btScalar force, int wheel); + + const btTransform& getWheelTransformWS( int wheelIndex ) const; + + void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true ); + +// void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth); + + btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel); + + inline int getNumWheels() const { + return int (m_wheelInfo.size()); + } + + btAlignedObjectArray m_wheelInfo; + + + const btWheelInfo& getWheelInfo(int index) const; + + btWheelInfo& getWheelInfo(int index); + + void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true); + + + void setBrake(btScalar brake,int wheelIndex); + + void setPitchControl(btScalar pitch) + { + m_pitchControl = pitch; + } + + void updateSuspension(btScalar deltaTime); + + virtual void updateFriction(btScalar timeStep); + + + + inline btRigidBody* getRigidBody() + { + return m_chassisBody; + } + + const btRigidBody* getRigidBody() const + { + return m_chassisBody; + } + + inline int getRightAxis() const + { + return m_indexRightAxis; + } + inline int getUpAxis() const + { + return m_indexUpAxis; + } + + inline int getForwardAxis() const + { + return m_indexForwardAxis; + } + + + ///Worldspace forward vector + btVector3 getForwardVector() const + { + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + return forwardW; + } + + ///Velocity of vehicle (positive if velocity vector has same direction as foward vector) + btScalar getCurrentSpeedKmHour() const + { + return m_currentVehicleSpeedKmHour; + } + + virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex) + { + m_indexRightAxis = rightIndex; + m_indexUpAxis = upIndex; + m_indexForwardAxis = forwardIndex; + } + + + ///backwards compatibility + int getUserConstraintType() const + { + return m_userConstraintType ; + } + + void setUserConstraintType(int userConstraintType) + { + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; + } + + int getUserConstraintId() const + { + return m_userConstraintId; + } + +}; + +class btDefaultVehicleRaycaster : public btVehicleRaycaster +{ + btDynamicsWorld* m_dynamicsWorld; +public: + btDefaultVehicleRaycaster(btDynamicsWorld* world) + :m_dynamicsWorld(world) + { + } + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result); + +}; + + +#endif //BT_RAYCASTVEHICLE_H + diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/Code/Physics/src/BulletDynamics/Vehicle/btVehicleRaycaster.h new file mode 100644 index 00000000..3cc909c6 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef BT_VEHICLE_RAYCASTER_H +#define BT_VEHICLE_RAYCASTER_H + +#include "LinearMath/btVector3.h" + +/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting +struct btVehicleRaycaster +{ +virtual ~btVehicleRaycaster() +{ +} + struct btVehicleRaycasterResult + { + btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){}; + btVector3 m_hitPointInWorld; + btVector3 m_hitNormalInWorld; + btScalar m_distFraction; + }; + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0; + +}; + +#endif //BT_VEHICLE_RAYCASTER_H + diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.cpp new file mode 100644 index 00000000..ef93c16f --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#include "btWheelInfo.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity + + +btScalar btWheelInfo::getSuspensionRestLength() const +{ + + return m_suspensionRestLength1; + +} + +void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo) +{ + (void)raycastInfo; + + + if (m_raycastInfo.m_isInContact) + + { + btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS ); + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition(); + chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos ); + btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + if ( project >= btScalar(-0.1)) + { + m_suspensionRelativeVelocity = btScalar(0.0); + m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / project; + m_suspensionRelativeVelocity = projVel * inv; + m_clippedInvContactDotSuspension = inv; + } + + } + + else // Not in contact : position wheel in a nice (rest length) position + { + m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength(); + m_suspensionRelativeVelocity = btScalar(0.0); + m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS; + m_clippedInvContactDotSuspension = btScalar(1.0); + } +} diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.h b/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.h new file mode 100644 index 00000000..f916053e --- /dev/null +++ b/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef BT_WHEEL_INFO_H +#define BT_WHEEL_INFO_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" + +class btRigidBody; + +struct btWheelInfoConstructionInfo +{ + btVector3 m_chassisConnectionCS; + btVector3 m_wheelDirectionCS; + btVector3 m_wheelAxleCS; + btScalar m_suspensionRestLength; + btScalar m_maxSuspensionTravelCm; + btScalar m_wheelRadius; + + btScalar m_suspensionStiffness; + btScalar m_wheelsDampingCompression; + btScalar m_wheelsDampingRelaxation; + btScalar m_frictionSlip; + btScalar m_maxSuspensionForce; + bool m_bIsFrontWheel; + +}; + +/// btWheelInfo contains information per wheel about friction and suspension. +struct btWheelInfo +{ + struct RaycastInfo + { + //set by raycaster + btVector3 m_contactNormalWS;//contactnormal + btVector3 m_contactPointWS;//raycast hitpoint + btScalar m_suspensionLength; + btVector3 m_hardPointWS;//raycast starting point + btVector3 m_wheelDirectionWS; //direction in worldspace + btVector3 m_wheelAxleWS; // axle in worldspace + bool m_isInContact; + void* m_groundObject; //could be general void* ptr + }; + + RaycastInfo m_raycastInfo; + + btTransform m_worldTransform; + + btVector3 m_chassisConnectionPointCS; //const + btVector3 m_wheelDirectionCS;//const + btVector3 m_wheelAxleCS; // const or modified by steering + btScalar m_suspensionRestLength1;//const + btScalar m_maxSuspensionTravelCm; + btScalar getSuspensionRestLength() const; + btScalar m_wheelsRadius;//const + btScalar m_suspensionStiffness;//const + btScalar m_wheelsDampingCompression;//const + btScalar m_wheelsDampingRelaxation;//const + btScalar m_frictionSlip; + btScalar m_steering; + btScalar m_rotation; + btScalar m_deltaRotation; + btScalar m_rollInfluence; + btScalar m_maxSuspensionForce; + + btScalar m_engineForce; + + btScalar m_brake; + + bool m_bIsFrontWheel; + + void* m_clientInfo;//can be used to store pointer to sync transforms... + + btWheelInfo(btWheelInfoConstructionInfo& ci) + + { + + m_suspensionRestLength1 = ci.m_suspensionRestLength; + m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm; + + m_wheelsRadius = ci.m_wheelRadius; + m_suspensionStiffness = ci.m_suspensionStiffness; + m_wheelsDampingCompression = ci.m_wheelsDampingCompression; + m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation; + m_chassisConnectionPointCS = ci.m_chassisConnectionCS; + m_wheelDirectionCS = ci.m_wheelDirectionCS; + m_wheelAxleCS = ci.m_wheelAxleCS; + m_frictionSlip = ci.m_frictionSlip; + m_steering = btScalar(0.); + m_engineForce = btScalar(0.); + m_rotation = btScalar(0.); + m_deltaRotation = btScalar(0.); + m_brake = btScalar(0.); + m_rollInfluence = btScalar(0.1); + m_bIsFrontWheel = ci.m_bIsFrontWheel; + m_maxSuspensionForce = ci.m_maxSuspensionForce; + + } + + void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo); + + btScalar m_clippedInvContactDotSuspension; + btScalar m_suspensionRelativeVelocity; + //calculated by suspension + btScalar m_wheelsSuspensionForce; + btScalar m_skidInfo; + +}; + +#endif //BT_WHEEL_INFO_H + diff --git a/Code/Physics/src/BulletDynamics/premake4.lua b/Code/Physics/src/BulletDynamics/premake4.lua new file mode 100644 index 00000000..919edaa7 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/premake4.lua @@ -0,0 +1,11 @@ + project "BulletDynamics" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/CMakeLists.txt new file mode 100644 index 00000000..dcc54277 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/CMakeLists.txt @@ -0,0 +1,126 @@ +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${VECTOR_MATH_INCLUDE} +) + +SET(BulletMultiThreaded_SRCS + SpuFakeDma.cpp + SpuLibspe2Support.cpp + btThreadSupportInterface.cpp + Win32ThreadSupport.cpp + PosixThreadSupport.cpp + SequentialThreadSupport.cpp + SpuSampleTaskProcess.cpp + SpuCollisionObjectWrapper.cpp + SpuCollisionTaskProcess.cpp + SpuGatheringCollisionDispatcher.cpp + SpuContactManifoldCollisionAlgorithm.cpp + btParallelConstraintSolver.cpp + + #SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.cpp + #SpuPEGatherScatterTaskProcess.cpp + + SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp + SpuNarrowPhaseCollisionTask/SpuContactResult.cpp + SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp + SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp + SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp + + #Some GPU related stuff, mainly CUDA and perhaps OpenCL + btGpu3DGridBroadphase.cpp +) + +SET(Root_HDRS + PlatformDefinitions.h + PpuAddressSpace.h + SpuFakeDma.h + SpuDoubleBuffer.h + SpuLibspe2Support.h + btThreadSupportInterface.h + Win32ThreadSupport.h + PosixThreadSupport.h + SequentialThreadSupport.h + SpuSampleTaskProcess.h + SpuCollisionObjectWrapper.cpp + SpuCollisionObjectWrapper.h + SpuCollisionTaskProcess.h + SpuGatheringCollisionDispatcher.h + SpuContactManifoldCollisionAlgorithm.h + btParallelConstraintSolver.h + + #SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.h + #SpuPEGatherScatterTaskProcess.h + + #Some GPU related stuff, mainly CUDA and perhaps OpenCL + btGpu3DGridBroadphase.h + btGpu3DGridBroadphaseSharedCode.h + btGpu3DGridBroadphaseSharedDefs.h + btGpu3DGridBroadphaseSharedTypes.h + btGpuDefines.h + btGpuUtilsSharedCode.h + btGpuUtilsSharedDefs.h +) + +SET(SpuNarrowPhaseCollisionTask_HDRS + SpuNarrowPhaseCollisionTask/Box.h + SpuNarrowPhaseCollisionTask/boxBoxDistance.h + SpuNarrowPhaseCollisionTask/SpuContactResult.h + SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h + SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h + SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h + SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h + SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h +) + +SET(BulletMultiThreaded_HDRS + ${Root_HDRS} + ${SpuNarrowPhaseCollisionTask_HDRS} +) + +ADD_LIBRARY(BulletMultiThreaded ${BulletMultiThreaded_SRCS} ${BulletMultiThreaded_HDRS}) +SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES SOVERSION ${BULLET_VERSION}) + + +SUBDIRS(GpuSoftBodySolvers) + + +IF (BUILD_SHARED_LIBS) + IF (UNIX) + TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision pthread) + ELSE() + TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision) + ENDIF() +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) +# IF(INSTALL_EXTRA_LIBS) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletMultiThreaded DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletMultiThreaded + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY +${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING +PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) +# ENDIF (INSTALL_EXTRA_LIBS) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${SpuNarrowPhaseCollisionTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/SpuNarrowPhaseCollisionTask) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt new file mode 100644 index 00000000..224a3e0a --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt @@ -0,0 +1,13 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + + +SUBDIRS ( + OpenCL +) + +IF( USE_DX11 ) + SUBDIRS( DX11 ) +ENDIF( USE_DX11 ) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt new file mode 100644 index 00000000..52f335d2 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt @@ -0,0 +1,86 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +SET(DXSDK_DIR $ENV{DXSDK_DIR}) +SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Microsoft directX SDK include path") + + +INCLUDE_DIRECTORIES( +${DX11_INCLUDE_PATH} "../Shared/" +${VECTOR_MATH_INCLUDE} +) + +SET(BulletSoftBodyDX11Solvers_SRCS + btSoftBodySolver_DX11.cpp + btSoftBodySolver_DX11SIMDAware.cpp +) + +SET(BulletSoftBodyDX11Solvers_HDRS + btSoftBodySolver_DX11.h + btSoftBodySolver_DX11SIMDAware.h + ../Shared/btSoftBodySolverData.h + btSoftBodySolverVertexData_DX11.h + btSoftBodySolverTriangleData_DX11.h + btSoftBodySolverLinkData_DX11.h + btSoftBodySolverLinkData_DX11SIMDAware.h + btSoftBodySolverBuffer_DX11.h + btSoftBodySolverVertexBuffer_DX11.h + +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyDX11Solvers_Shaders + OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + ComputeBounds + SolvePositions + SolvePositionsSIMDBatched + SolveCollisionsAndUpdateVelocities + SolveCollisionsAndUpdateVelocitiesSIMDBatched + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyDX11Solvers_Shaders}) + LIST(APPEND BulletSoftBodyDX11Solvers_HLSL "HLSL/${f}.hlsl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_DX11 ${BulletSoftBodyDX11Solvers_SRCS} ${BulletSoftBodyDX11Solvers_HDRS} ${BulletSoftBodyDX11Solvers_HLSL}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_DX11 BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_DX11 + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES PUBLIC_HEADER "${BulletSoftBodyDX11Solvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl new file mode 100644 index 00000000..37e22695 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl @@ -0,0 +1,95 @@ +MSTRINGIFY( + +cbuffer ApplyForcesCB : register( b0 ) +{ + unsigned int numNodes; + float solverdt; + float epsilon; + int padding3; +}; + + +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexNormal : register( t1 ); +StructuredBuffer g_vertexArea : register( t2 ); +StructuredBuffer g_vertexInverseMass : register( t3 ); +// TODO: These could be combined into a lift/drag factor array along with medium density +StructuredBuffer g_clothLiftFactor : register( t4 ); +StructuredBuffer g_clothDragFactor : register( t5 ); +StructuredBuffer g_clothWindVelocity : register( t6 ); +StructuredBuffer g_clothAcceleration : register( t7 ); +StructuredBuffer g_clothMediumDensity : register( t8 ); + +RWStructuredBuffer g_vertexForceAccumulator : register( u0 ); +RWStructuredBuffer g_vertexVelocity : register( u1 ); + +float3 projectOnAxis( float3 v, float3 a ) +{ + return (a*dot(v, a)); +} + +[numthreads(128, 1, 1)] +void +ApplyForcesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + unsigned int nodeID = DTid.x; + if( nodeID < numNodes ) + { + int clothId = g_vertexClothIdentifier[nodeID]; + float nodeIM = g_vertexInverseMass[nodeID]; + + if( nodeIM > 0.0f ) + { + float3 nodeV = g_vertexVelocity[nodeID].xyz; + float3 normal = g_vertexNormal[nodeID].xyz; + float area = g_vertexArea[nodeID]; + float3 nodeF = g_vertexForceAccumulator[nodeID].xyz; + + // Read per-cloth values + float3 clothAcceleration = g_clothAcceleration[clothId].xyz; + float3 clothWindVelocity = g_clothWindVelocity[clothId].xyz; + float liftFactor = g_clothLiftFactor[clothId]; + float dragFactor = g_clothDragFactor[clothId]; + float mediumDensity = g_clothMediumDensity[clothId]; + + // Apply the acceleration to the cloth rather than do this via a force + nodeV += (clothAcceleration*solverdt); + + g_vertexVelocity[nodeID] = float4(nodeV, 0.f); + + float3 relativeWindVelocity = nodeV - clothWindVelocity; + float relativeSpeedSquared = dot(relativeWindVelocity, relativeWindVelocity); + + if( relativeSpeedSquared > epsilon ) + { + // Correct direction of normal relative to wind direction and get dot product + normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : 1.f); + float dvNormal = dot(normal, relativeWindVelocity); + if( dvNormal > 0 ) + { + float3 force = float3(0.f, 0.f, 0.f); + float c0 = area * dvNormal * relativeSpeedSquared / 2.f; + float c1 = c0 * mediumDensity; + force += normal * (-c1 * liftFactor); + force += normalize(relativeWindVelocity)*(-c1 * dragFactor); + + float dtim = solverdt * nodeIM; + float3 forceDTIM = force * dtim; + + float3 nodeFPlusForce = nodeF + force; + + // m_nodesf[i] -= ProjectOnAxis(m_nodesv[i], force.normalized())/dtim; + float3 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim); + + nodeF = nodeFPlusForce; + if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) ) + nodeF = nodeFMinus; + + g_vertexForceAccumulator[nodeID] = float4(nodeF, 0.0f); + } + } + } + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl new file mode 100644 index 00000000..65ae515c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl @@ -0,0 +1,83 @@ +MSTRINGIFY( + +cbuffer ComputeBoundsCB : register( b0 ) +{ + int numNodes; + int numSoftBodies; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexPositions : register( t1 ); + +RWStructuredBuffer g_clothMinBounds : register( u0 ); +RWStructuredBuffer g_clothMaxBounds : register( u1 ); + +groupshared uint4 clothMinBounds[256]; +groupshared uint4 clothMaxBounds[256]; + +[numthreads(128, 1, 1)] +void +ComputeBoundsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + const unsigned int UINT_MAX = 0xffffffff; + + // Init min and max bounds arrays + if( GTid.x < numSoftBodies ) + { + clothMinBounds[GTid.x] = uint4(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX); + clothMaxBounds[GTid.x] = uint4(0,0,0,0); + } + + AllMemoryBarrierWithGroupSync(); + + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + if( clothIdentifier >= 0 ) + { + float3 position = g_vertexPositions[nodeID].xyz; + + // Reinterpret position as uint + uint3 positionUInt = uint3(asuint(position.x), asuint(position.y), asuint(position.z)); + + // Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints + //positionUInt.x ^= uint((-int(positionUInt.x >> 31) | 0x80000000)); + //positionUInt.y ^= uint((-int(positionUInt.y >> 31) | 0x80000000)); + //positionUInt.z ^= uint((-int(positionUInt.z >> 31) | 0x80000000)); + positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000); + positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000); + positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000); + + // Min/max with the LDS values + InterlockedMin(clothMinBounds[clothIdentifier].x, positionUInt.x); + InterlockedMin(clothMinBounds[clothIdentifier].y, positionUInt.y); + InterlockedMin(clothMinBounds[clothIdentifier].z, positionUInt.z); + + InterlockedMax(clothMaxBounds[clothIdentifier].x, positionUInt.x); + InterlockedMax(clothMaxBounds[clothIdentifier].y, positionUInt.y); + InterlockedMax(clothMaxBounds[clothIdentifier].z, positionUInt.z); + } + } + + AllMemoryBarrierWithGroupSync(); + + + // Use global atomics to update the global versions of the data + if( GTid.x < numSoftBodies ) + { + InterlockedMin(g_clothMinBounds[GTid.x].x, clothMinBounds[GTid.x].x); + InterlockedMin(g_clothMinBounds[GTid.x].y, clothMinBounds[GTid.x].y); + InterlockedMin(g_clothMinBounds[GTid.x].z, clothMinBounds[GTid.x].z); + + InterlockedMax(g_clothMaxBounds[GTid.x].x, clothMaxBounds[GTid.x].x); + InterlockedMax(g_clothMaxBounds[GTid.x].y, clothMaxBounds[GTid.x].y); + InterlockedMax(g_clothMaxBounds[GTid.x].z, clothMaxBounds[GTid.x].z); + } +} + + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl new file mode 100644 index 00000000..f85fd115 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl @@ -0,0 +1,41 @@ +MSTRINGIFY( + +cbuffer IntegrateCB : register( b0 ) +{ + int numNodes; + float solverdt; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_vertexInverseMasses : register( t0 ); + +RWStructuredBuffer g_vertexPositions : register( u0 ); +RWStructuredBuffer g_vertexVelocity : register( u1 ); +RWStructuredBuffer g_vertexPreviousPositions : register( u2 ); +RWStructuredBuffer g_vertexForceAccumulator : register( u3 ); + +[numthreads(128, 1, 1)] +void +IntegrateKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float3 position = g_vertexPositions[nodeID].xyz; + float3 velocity = g_vertexVelocity[nodeID].xyz; + float3 force = g_vertexForceAccumulator[nodeID].xyz; + float inverseMass = g_vertexInverseMasses[nodeID]; + + g_vertexPreviousPositions[nodeID] = float4(position, 0.f); + velocity += force * inverseMass * solverdt; + position += velocity * solverdt; + + g_vertexForceAccumulator[nodeID] = float4(0.f, 0.f, 0.f, 0.0f); + g_vertexPositions[nodeID] = float4(position, 0.f); + g_vertexVelocity[nodeID] = float4(velocity, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl new file mode 100644 index 00000000..a6fa7b95 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl @@ -0,0 +1,63 @@ +MSTRINGIFY( + +cbuffer OutputToVertexArrayCB : register( b0 ) +{ + int startNode; + int numNodes; + int positionOffset; + int positionStride; + + int normalOffset; + int normalStride; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexPositions : register( t0 ); +StructuredBuffer g_vertexNormals : register( t1 ); + +RWBuffer g_vertexBuffer : register( u0 ); + + +[numthreads(128, 1, 1)] +void +OutputToVertexArrayWithNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + float4 normal = g_vertexNormals[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + + int normalDestination = nodeID * normalStride + normalOffset; + g_vertexBuffer[normalDestination] = normal.x; + g_vertexBuffer[normalDestination+1] = normal.y; + g_vertexBuffer[normalDestination+2] = normal.z; + } +} + +[numthreads(128, 1, 1)] +void +OutputToVertexArrayWithoutNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + float4 normal = g_vertexNormals[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + } +} +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl new file mode 100644 index 00000000..75db8d14 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl @@ -0,0 +1,44 @@ +MSTRINGIFY( + +cbuffer PrepareLinksCB : register( b0 ) +{ + int numLinks; + int padding0; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); +StructuredBuffer g_linksMassLSC : register( t1 ); +StructuredBuffer g_nodesPreviousPosition : register( t2 ); + +RWStructuredBuffer g_linksLengthRatio : register( u0 ); +RWStructuredBuffer g_linksCurrentLength : register( u1 ); + +[numthreads(128, 1, 1)] +void +PrepareLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x; + if( linkID < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0]; + float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1]; + + float massLSC = g_linksMassLSC[linkID]; + + float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0; + + float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC; + linkLengthRatio = 1./linkLengthRatio; + + g_linksCurrentLength[linkID] = linkCurrentLength; + g_linksLengthRatio[linkID] = linkLengthRatio; + } +} +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl new file mode 100644 index 00000000..de979d7f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl @@ -0,0 +1,55 @@ +MSTRINGIFY( + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + int startLink; + int numLinks; + float kst; + float ti; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); + +StructuredBuffer g_linksMassLSC : register( t1 ); +StructuredBuffer g_linksRestLengthSquared : register( t2 ); +StructuredBuffer g_verticesInverseMass : register( t3 ); + +RWStructuredBuffer g_vertexPositions : register( u0 ); + +[numthreads(128, 1, 1)] +void +SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x + startLink; + if( DTid.x < numLinks ) + { + float massLSC = g_linksMassLSC[linkID]; + float restLengthSquared = g_linksRestLengthSquared[linkID]; + + if( massLSC > 0.0f ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float3 position0 = g_vertexPositions[node0].xyz; + float3 position1 = g_vertexPositions[node1].xyz; + + float inverseMass0 = g_verticesInverseMass[node0]; + float inverseMass1 = g_verticesInverseMass[node1]; + + float3 del = position1 - position0; + float len = dot(del, del); + float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + g_vertexPositions[node0] = float4(position0, 0.f); + g_vertexPositions[node1] = float4(position1, 0.f); + + } + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl new file mode 100644 index 00000000..3cbb352e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl @@ -0,0 +1,147 @@ +MSTRINGIFY( + + + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + int startWaveInBatch; + int numWaves; + float kst; + float ti; +}; + + +// Number of batches per wavefront stored one element per logical wavefront +StructuredBuffer g_wavefrontBatchCountsVertexCounts : register( t0 ); +// Set of up to maxNumVertices vertex addresses per wavefront +StructuredBuffer g_vertexAddressesPerWavefront : register( t1 ); + +StructuredBuffer g_verticesInverseMass : register( t2 ); + +// Per-link data layed out structured in terms of sub batches within wavefronts +StructuredBuffer g_linksVertexIndices : register( t3 ); +StructuredBuffer g_linksMassLSC : register( t4 ); +StructuredBuffer g_linksRestLengthSquared : register( t5 ); + +RWStructuredBuffer g_vertexPositions : register( u0 ); + +// Data loaded on a per-wave basis +groupshared int2 wavefrontBatchCountsVertexCounts[WAVEFRONT_BLOCK_MULTIPLIER]; +groupshared float4 vertexPositionSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; +groupshared float vertexInverseMassSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; + +// Storing the vertex addresses actually slowed things down a little +//groupshared int vertexAddressSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; + + +[numthreads(BLOCK_SIZE, 1, 1)] +void +SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + const int laneInWavefront = (DTid.x & (WAVEFRONT_SIZE-1)); + const int wavefront = startWaveInBatch + (DTid.x / WAVEFRONT_SIZE); + const int firstWavefrontInBlock = startWaveInBatch + Gid.x * WAVEFRONT_BLOCK_MULTIPLIER; + const int localWavefront = wavefront - firstWavefrontInBlock; + + int batchesWithinWavefront = 0; + int verticesUsedByWave = 0; + int cond = wavefront < (startWaveInBatch + numWaves); + + // Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier + if( cond) + { + + // Load the batch counts for the wavefronts + + int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront]; + + batchesWithinWavefront = batchesAndVerticesWithinWavefront.x; + verticesUsedByWave = batchesAndVerticesWithinWavefront.y; + + // Load the vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + //vertexAddressSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = vertexAddress; + vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress]; + vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress]; + } + + } + // Ensure compiler does not re-order memory operations + //AllMemoryBarrier(); + AllMemoryBarrierWithGroupSync (); + + if( cond) + { + // Loop through the batches performing the solve on each in LDS + int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE; + + //for( int batch = 0; batch < batchesWithinWavefront; ++batch ) + + int batch = 0; + do + { + int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch; + int locationOfValue = baseDataLocation + laneInWavefront; + + + // These loads should all be perfectly linear across the WF + int2 localVertexIndices = g_linksVertexIndices[locationOfValue]; + float massLSC = g_linksMassLSC[locationOfValue]; + float restLengthSquared = g_linksRestLengthSquared[locationOfValue]; + + + // LDS vertex addresses based on logical wavefront number in block and loaded index + int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x; + int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y; + + float3 position0 = vertexPositionSharedData[vertexAddress0].xyz; + float3 position1 = vertexPositionSharedData[vertexAddress1].xyz; + + float inverseMass0 = vertexInverseMassSharedData[vertexAddress0]; + float inverseMass1 = vertexInverseMassSharedData[vertexAddress1]; + + float3 del = position1 - position0; + float len = dot(del, del); + + float k = 0; + if( massLSC > 0.0f ) + { + k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + } + + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + // Ensure compiler does not re-order memory operations + AllMemoryBarrier(); + + vertexPositionSharedData[vertexAddress0] = float4(position0, 0.f); + vertexPositionSharedData[vertexAddress1] = float4(position1, 0.f); + + // Ensure compiler does not re-order memory operations + AllMemoryBarrier(); + + + ++batch; + } while( batch < batchesWithinWavefront ); + + // Update the global memory vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + g_vertexPositions[vertexAddress] = vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + } + } + + +} + + + + +); + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl new file mode 100644 index 00000000..fafd236f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl @@ -0,0 +1,48 @@ +MSTRINGIFY( + +cbuffer UpdateConstantsCB : register( b0 ) +{ + int numLinks; + int padding0; + int padding1; + int padding2; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); +StructuredBuffer g_vertexPositions : register( t1 ); +StructuredBuffer g_vertexInverseMasses : register( t2 ); +StructuredBuffer g_linksMaterialLSC : register( t3 ); + +RWStructuredBuffer g_linksMassLSC : register( u0 ); +RWStructuredBuffer g_linksRestLengthSquared : register( u1 ); +RWStructuredBuffer g_linksRestLengths : register( u2 ); + +[numthreads(128, 1, 1)] +void +UpdateConstantsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x; + if( linkID < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ]; + + float3 position0 = g_vertexPositions[node0].xyz; + float3 position1 = g_vertexPositions[node1].xyz; + float inverseMass0 = g_vertexInverseMasses[node0]; + float inverseMass1 = g_vertexInverseMasses[node1]; + + float3 difference = position0 - position1; + float length2 = dot(difference, difference); + float length = sqrt(length2); + + g_linksRestLengths[linkID] = length; + g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient; + g_linksRestLengthSquared[linkID] = length*length; + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl new file mode 100644 index 00000000..a16d8943 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl @@ -0,0 +1,49 @@ +MSTRINGIFY( + +cbuffer UpdateVelocitiesFromPositionsWithVelocitiesCB : register( b0 ) +{ + int numNodes; + float isolverdt; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexPositions : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_vertexClothIndices : register( t2 ); +StructuredBuffer g_clothVelocityCorrectionCoefficients : register( t3 ); +StructuredBuffer g_clothDampingFactor : register( t4 ); + +RWStructuredBuffer g_vertexVelocities : register( u0 ); +RWStructuredBuffer g_vertexForces : register( u1 ); + + +[numthreads(128, 1, 1)] +void +updateVelocitiesFromPositionsWithVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float3 position = g_vertexPositions[nodeID].xyz; + float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz; + float3 velocity = g_vertexVelocities[nodeID].xyz; + int clothIndex = g_vertexClothIndices[nodeID]; + float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float3 difference = position - previousPosition; + + velocity += difference*velocityCorrectionCoefficient*isolverdt; + + // Damp the velocity + velocity *= velocityCoefficient; + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl new file mode 100644 index 00000000..54ab3ed2 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl @@ -0,0 +1,98 @@ +MSTRINGIFY( + +cbuffer UpdateSoftBodiesCB : register( b0 ) +{ + unsigned int numNodes; + unsigned int startFace; + unsigned int numFaces; + float epsilon; +}; + + +// Node indices for each link +StructuredBuffer g_triangleVertexIndexSet : register( t0 ); +StructuredBuffer g_vertexPositions : register( t1 ); +StructuredBuffer g_vertexTriangleCount : register( t2 ); + +RWStructuredBuffer g_vertexNormals : register( u0 ); +RWStructuredBuffer g_vertexArea : register( u1 ); +RWStructuredBuffer g_triangleNormals : register( u2 ); +RWStructuredBuffer g_triangleArea : register( u3 ); + + +[numthreads(128, 1, 1)] +void +ResetNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + if( DTid.x < numNodes ) + { + g_vertexNormals[DTid.x] = float4(0.0f, 0.0f, 0.0f, 0.0f); + g_vertexArea[DTid.x] = 0.0f; + } +} + + +[numthreads(128, 1, 1)] +void +UpdateSoftBodiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int faceID = DTid.x + startFace; + if( DTid.x < numFaces ) + { + int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ]; + int nodeIndex0 = triangleIndexSet.x; + int nodeIndex1 = triangleIndexSet.y; + int nodeIndex2 = triangleIndexSet.z; + + float3 node0 = g_vertexPositions[nodeIndex0].xyz; + float3 node1 = g_vertexPositions[nodeIndex1].xyz; + float3 node2 = g_vertexPositions[nodeIndex2].xyz; + float3 nodeNormal0 = g_vertexNormals[nodeIndex0].xyz; + float3 nodeNormal1 = g_vertexNormals[nodeIndex1].xyz; + float3 nodeNormal2 = g_vertexNormals[nodeIndex2].xyz; + float vertexArea0 = g_vertexArea[nodeIndex0]; + float vertexArea1 = g_vertexArea[nodeIndex1]; + float vertexArea2 = g_vertexArea[nodeIndex2]; + + float3 vector0 = node1 - node0; + float3 vector1 = node2 - node0; + + float3 faceNormal = cross(vector0.xyz, vector1.xyz); + float triangleArea = length(faceNormal); + + nodeNormal0 = nodeNormal0 + faceNormal; + nodeNormal1 = nodeNormal1 + faceNormal; + nodeNormal2 = nodeNormal2 + faceNormal; + vertexArea0 = vertexArea0 + triangleArea; + vertexArea1 = vertexArea1 + triangleArea; + vertexArea2 = vertexArea2 + triangleArea; + + g_triangleNormals[faceID] = float4(normalize(faceNormal), 0.f); + g_vertexNormals[nodeIndex0] = float4(nodeNormal0, 0.f); + g_vertexNormals[nodeIndex1] = float4(nodeNormal1, 0.f); + g_vertexNormals[nodeIndex2] = float4(nodeNormal2, 0.f); + g_triangleArea[faceID] = triangleArea; + g_vertexArea[nodeIndex0] = vertexArea0; + g_vertexArea[nodeIndex1] = vertexArea1; + g_vertexArea[nodeIndex2] = vertexArea2; + } +} + +[numthreads(128, 1, 1)] +void +NormalizeNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + if( DTid.x < numNodes ) + { + float4 normal = g_vertexNormals[DTid.x]; + float area = g_vertexArea[DTid.x]; + int numTriangles = g_vertexTriangleCount[DTid.x]; + + float vectorLength = length(normal); + + g_vertexNormals[DTid.x] = normalize(normal); + g_vertexArea[DTid.x] = area/float(numTriangles); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl new file mode 100644 index 00000000..9685fa8f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl @@ -0,0 +1,44 @@ +MSTRINGIFY( + +cbuffer UpdateVelocitiesFromPositionsWithoutVelocitiesCB : register( b0 ) +{ + int numNodes; + float isolverdt; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexPositions : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_vertexClothIndices : register( t2 ); +StructuredBuffer g_clothDampingFactor : register( t3 ); + +RWStructuredBuffer g_vertexVelocities : register( u0 ); +RWStructuredBuffer g_vertexForces : register( u1 ); + + +[numthreads(128, 1, 1)] +void +updateVelocitiesFromPositionsWithoutVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + if( nodeID < numNodes ) + { + float3 position = g_vertexPositions[nodeID].xyz; + float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz; + float3 velocity = g_vertexVelocities[nodeID].xyz; + int clothIndex = g_vertexClothIndices[nodeID]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float3 difference = position - previousPosition; + + velocity = difference*velocityCoefficient*isolverdt; + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl new file mode 100644 index 00000000..e816b1e1 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl @@ -0,0 +1,35 @@ +MSTRINGIFY( + +cbuffer UpdatePositionsFromVelocitiesCB : register( b0 ) +{ + int numNodes; + float solverSDT; + int padding1; + int padding2; +}; + + +StructuredBuffer g_vertexVelocities : register( t0 ); + +RWStructuredBuffer g_vertexPreviousPositions : register( u0 ); +RWStructuredBuffer g_vertexCurrentPosition : register( u1 ); + + +[numthreads(128, 1, 1)] +void +UpdatePositionsFromVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int vertexID = DTid.x; + if( vertexID < numNodes ) + { + float3 previousPosition = g_vertexPreviousPositions[vertexID].xyz; + float3 velocity = g_vertexVelocities[vertexID].xyz; + + float3 newPosition = previousPosition + velocity*solverSDT; + + g_vertexCurrentPosition[vertexID] = float4(newPosition, 0.f); + g_vertexPreviousPositions[vertexID] = float4(newPosition, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl new file mode 100644 index 00000000..14afca67 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl @@ -0,0 +1,55 @@ +MSTRINGIFY( + +cbuffer VSolveLinksCB : register( b0 ) +{ + int startLink; + int numLinks; + float kst; + int padding; +}; + +// Node indices for each link +StructuredBuffer g_linksVertexIndices : register( t0 ); + +StructuredBuffer g_linksLengthRatio : register( t1 ); +StructuredBuffer g_linksCurrentLength : register( t2 ); +StructuredBuffer g_vertexInverseMass : register( t3 ); + +RWStructuredBuffer g_vertexVelocity : register( u0 ); + +[numthreads(128, 1, 1)] +void +VSolveLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int linkID = DTid.x + startLink; + if( DTid.x < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float linkLengthRatio = g_linksLengthRatio[linkID]; + float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz; + + float3 vertexVelocity0 = g_vertexVelocity[node0].xyz; + float3 vertexVelocity1 = g_vertexVelocity[node1].xyz; + + float vertexInverseMass0 = g_vertexInverseMass[node0]; + float vertexInverseMass1 = g_vertexInverseMass[node1]; + + float3 nodeDifference = vertexVelocity0 - vertexVelocity1; + float dotResult = dot(linkCurrentLength, nodeDifference); + float j = -dotResult*linkLengthRatio*kst; + + float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0); + float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1); + + vertexVelocity0 += velocityChange0; + vertexVelocity1 -= velocityChange1; + + g_vertexVelocity[node0] = float4(vertexVelocity0, 0.f); + g_vertexVelocity[node1] = float4(vertexVelocity1, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl new file mode 100644 index 00000000..9d46a596 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl @@ -0,0 +1,170 @@ +MSTRINGIFY( + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + unsigned int numNodes; + float isolverdt; + int padding0; + int padding1; +}; + +struct CollisionObjectIndices +{ + int firstObject; + int endObject; +}; + +struct CollisionShapeDescription +{ + float4x4 shapeTransform; + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + + float margin; + float friction; + + int padding0; + int padding1; + +}; + +// From btBroadphaseProxy.h +static const int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Node indices for each link +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_perClothFriction : register( t2 ); +StructuredBuffer g_clothDampingFactor : register( t3 ); +StructuredBuffer g_perClothCollisionObjectIndices : register( t4 ); +StructuredBuffer g_collisionObjectDetails : register( t5 ); + +RWStructuredBuffer g_vertexForces : register( u0 ); +RWStructuredBuffer g_vertexVelocities : register( u1 ); +RWStructuredBuffer g_vertexPositions : register( u2 ); + +[numthreads(128, 1, 1)] +void +SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + float3 forceOnVertex = float3(0.f, 0.f, 0.f); + if( DTid.x < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f); + float3 velocity; + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + if( collisionObjectIndices.firstObject != collisionObjectIndices.endObject ) + { + velocity = float3(15, 0, 0); + + // We have some possible collisions to deal with + for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) + { + CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = shapeDescription.halfHeight; + float capsuleRadius = shapeDescription.radius; + float capsuleMargin = shapeDescription.margin; + float4x4 worldTransform = shapeDescription.shapeTransform; + + float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f); + float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f); + float4 worldC1 = mul(worldTransform, c1); + float4 worldC2 = mul(worldTransform, c2); + float3 segment = (worldC2 - worldC1).xyz; + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) ); + + float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float3 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = normalize(position - worldC1).xyz; + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = normalize(position - worldC2).xyz; + } else { + dist = distanceFromLine; + normalVector = normalize(position - closestPoint).xyz; + } + + float3 colliderLinearVelocity = shapeDescription.linearVelocity.xyz; + float3 colliderAngularVelocity = shapeDescription.angularVelocity.xyz; + float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + float4((minDistance - dist)*normalVector*0.9, 0.f); + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + float3 relativeVelocity = velocity - velocityOfSurfacePoint; + + float3 p1 = normalize(cross(normalVector, segment)); + float3 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0 ) + forceOnVertex -= frictionVector; + } + + } + } + } else { + // Update velocity + float3 difference = position.xyz - previousPosition.xyz; + velocity = difference*velocityCoefficient*isolverdt; + } + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + + // Update external force + g_vertexForces[nodeID] = float4(forceOnVertex, 0.f); + + g_vertexPositions[nodeID] = float4(position.xyz, 0.f); + } +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl new file mode 100644 index 00000000..0b2a0271 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl @@ -0,0 +1,191 @@ +MSTRINGIFY( + +cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) +{ + unsigned int numNodes; + float isolverdt; + int padding0; + int padding1; +}; + +struct CollisionObjectIndices +{ + int firstObject; + int endObject; +}; + +struct CollisionShapeDescription +{ + float4x4 shapeTransform; + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + + float margin; + float friction; + + int padding0; + int padding1; + +}; + +// From btBroadphaseProxy.h +static const int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Node indices for each link +StructuredBuffer g_vertexClothIdentifier : register( t0 ); +StructuredBuffer g_vertexPreviousPositions : register( t1 ); +StructuredBuffer g_perClothFriction : register( t2 ); +StructuredBuffer g_clothDampingFactor : register( t3 ); +StructuredBuffer g_perClothCollisionObjectIndices : register( t4 ); +StructuredBuffer g_collisionObjectDetails : register( t5 ); + +RWStructuredBuffer g_vertexForces : register( u0 ); +RWStructuredBuffer g_vertexVelocities : register( u1 ); +RWStructuredBuffer g_vertexPositions : register( u2 ); + +// A buffer of local collision shapes +// TODO: Iterate to support more than 16 +groupshared CollisionShapeDescription localCollisionShapes[16]; + +[numthreads(128, 1, 1)] +void +SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) +{ + int nodeID = DTid.x; + float3 forceOnVertex = float3(0.f, 0.f, 0.f); + + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f); + float3 velocity; + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + + // First load all of the collision objects into LDS + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + if( GTid.x < numObjects ) + { + localCollisionShapes[GTid.x] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + GTid.x ]; + } + } + + // Safe as the vertices are padded so that not more than one soft body is in a group + AllMemoryBarrierWithGroupSync(); + + // Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this + if( numObjects > 0 ) + { + velocity = float3(0, 0, 0); + + + // We have some possible collisions to deal with + for( int collision = 0; collision < numObjects; ++collision ) + { + CollisionShapeDescription shapeDescription = localCollisionShapes[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = localCollisionShapes[collision].halfHeight; + float capsuleRadius = localCollisionShapes[collision].radius; + float capsuleMargin = localCollisionShapes[collision].margin; + + float4x4 worldTransform = localCollisionShapes[collision].shapeTransform; + + float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f); + float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f); + float4 worldC1 = mul(worldTransform, c1); + float4 worldC2 = mul(worldTransform, c2); + float3 segment = (worldC2 - worldC1).xyz; + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) ); + + float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float3 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = normalize(position - worldC1).xyz; + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = normalize(position - worldC2).xyz; + } else { + dist = distanceFromLine; + normalVector = normalize(position - closestPoint).xyz; + } + + float3 colliderLinearVelocity = localCollisionShapes[collision].linearVelocity.xyz; + float3 colliderAngularVelocity = localCollisionShapes[collision].angularVelocity.xyz; + float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + float4((minDistance - dist)*normalVector*0.9, 0.f); + velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; + float3 relativeVelocity = velocity - velocityOfSurfacePoint; + + float3 p1 = normalize(cross(normalVector, segment)); + float3 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0 ) + forceOnVertex -= frictionVector; + } + + } + } + } else { + // Update velocity + float3 difference = position.xyz - previousPosition.xyz; + velocity = difference*velocityCoefficient*isolverdt; + } + + g_vertexVelocities[nodeID] = float4(velocity, 0.f); + + // Update external force + g_vertexForces[nodeID] = float4(forceOnVertex, 0.f); + + g_vertexPositions[nodeID] = float4(position.xyz, 0.f); +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h new file mode 100644 index 00000000..b6a99cc1 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h @@ -0,0 +1,323 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H +#define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H + +// DX11 support +#include +#include +#include +#include +#include + +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } +#endif + +/** + * DX11 Buffer that tracks a host buffer on use to ensure size-correctness. + */ +template class btDX11Buffer +{ +protected: + ID3D11Device* m_d3dDevice; + ID3D11DeviceContext* m_d3dDeviceContext; + + ID3D11Buffer* m_Buffer; + ID3D11ShaderResourceView* m_SRV; + ID3D11UnorderedAccessView* m_UAV; + btAlignedObjectArray< ElementType >* m_CPUBuffer; + + // TODO: Separate this from the main class + // as read back buffers can be shared between buffers + ID3D11Buffer* m_readBackBuffer; + + int m_gpuSize; + bool m_onGPU; + + bool m_readOnlyOnGPU; + + bool createBuffer( ID3D11Buffer *preexistingBuffer = 0) + { + HRESULT hr = S_OK; + + // Create all CS buffers + if( preexistingBuffer ) + { + m_Buffer = preexistingBuffer; + } else { + D3D11_BUFFER_DESC buffer_desc; + ZeroMemory(&buffer_desc, sizeof(buffer_desc)); + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + if( m_readOnlyOnGPU ) + buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + else + buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; + buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + + buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType); + // At a minimum the buffer must exist + if( buffer_desc.ByteWidth == 0 ) + buffer_desc.ByteWidth = sizeof(ElementType); + buffer_desc.StructureByteStride = sizeof(ElementType); + hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer); + if( FAILED( hr ) ) + return (hr==S_OK); + } + + if( m_readOnlyOnGPU ) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; + ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); + srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size(); + if( srvbuffer_desc.Buffer.ElementWidth == 0 ) + srvbuffer_desc.Buffer.ElementWidth = 1; + hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV); + if( FAILED( hr ) ) + return (hr==S_OK); + } else { + // Create SRV + D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; + ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); + srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + + srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size(); + if( srvbuffer_desc.Buffer.ElementWidth == 0 ) + srvbuffer_desc.Buffer.ElementWidth = 1; + hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV); + if( FAILED( hr ) ) + return (hr==S_OK); + + // Create UAV + D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc; + ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc)); + uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; + uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + + uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size(); + if( uavbuffer_desc.Buffer.NumElements == 0 ) + uavbuffer_desc.Buffer.NumElements = 1; + hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV); + if( FAILED( hr ) ) + return (hr==S_OK); + + // Create read back buffer + D3D11_BUFFER_DESC readback_buffer_desc; + ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc)); + + readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType); + readback_buffer_desc.Usage = D3D11_USAGE_STAGING; + readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + readback_buffer_desc.StructureByteStride = sizeof(ElementType); + hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer); + if( FAILED( hr ) ) + return (hr==S_OK); + } + + m_gpuSize = m_CPUBuffer->size(); + return true; + } + + + +public: + btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly ) + { + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; + m_Buffer = 0; + m_SRV = 0; + m_UAV = 0; + m_readBackBuffer = 0; + + m_CPUBuffer = CPUBuffer; + + m_gpuSize = 0; + m_onGPU = false; + + m_readOnlyOnGPU = readOnly; + } + + virtual ~btDX11Buffer() + { + SAFE_RELEASE(m_Buffer); + SAFE_RELEASE(m_SRV); + SAFE_RELEASE(m_UAV); + SAFE_RELEASE(m_readBackBuffer); + } + + ID3D11ShaderResourceView* &getSRV() + { + return m_SRV; + } + + ID3D11UnorderedAccessView* &getUAV() + { + return m_UAV; + } + + ID3D11Buffer* &getBuffer() + { + return m_Buffer; + } + + /** + * Move the data to the GPU if it is not there already. + */ + bool moveToGPU() + { + // Reallocate if GPU size is too small + if( (m_CPUBuffer->size() > m_gpuSize ) ) + m_onGPU = false; + if( !m_onGPU && m_CPUBuffer->size() > 0 ) + { + // If the buffer doesn't exist or the CPU-side buffer has changed size, create + // We should really delete the old one, too, but let's leave that for later + if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) ) + { + SAFE_RELEASE(m_Buffer); + SAFE_RELEASE(m_SRV); + SAFE_RELEASE(m_UAV); + SAFE_RELEASE(m_readBackBuffer); + if( !createBuffer() ) + { + btAssert("Buffer creation failed."); + return false; + } + } + + if( m_gpuSize > 0 ) + { + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); + m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0); + + m_onGPU = true; + } + + } + + return true; + } + + /** + * Move the data back from the GPU if it is on there and isn't read only. + */ + bool moveFromGPU() + { + if( m_CPUBuffer->size() > 0 ) + { + if( m_onGPU && !m_readOnlyOnGPU ) + { + // Copy back + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + //m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel); + + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + + destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); + m_d3dDeviceContext->CopySubresourceRegion( + m_readBackBuffer, + 0, + 0, + 0, + 0 , + m_Buffer, + 0, + &destRegion + ); + + m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource); + //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) )); + memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) )); + m_d3dDeviceContext->Unmap(m_readBackBuffer, 0); + + m_onGPU = false; + } + } + + return true; + } + + + /** + * Copy the data back from the GPU without changing its state to be CPU-side. + * Useful if we just want to view it on the host for visualization. + */ + bool copyFromGPU() + { + if( m_CPUBuffer->size() > 0 ) + { + if( m_onGPU && !m_readOnlyOnGPU ) + { + // Copy back + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + + D3D11_BOX destRegion; + destRegion.left = 0; + destRegion.front = 0; + destRegion.top = 0; + destRegion.bottom = 1; + destRegion.back = 1; + + destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); + m_d3dDeviceContext->CopySubresourceRegion( + m_readBackBuffer, + 0, + 0, + 0, + 0 , + m_Buffer, + 0, + &destRegion + ); + + m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource); + //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) )); + memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) )); + m_d3dDeviceContext->Unmap(m_readBackBuffer, 0); + } + } + + return true; + } + + /** + * Call if data has changed on the CPU. + * Can then trigger a move to the GPU as necessary. + */ + virtual void changedOnCPU() + { + m_onGPU = false; + } +}; // class btDX11Buffer + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h new file mode 100644 index 00000000..454c3c8c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + + +#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H +#define BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H + +struct ID3D11Device; +struct ID3D11DeviceContext; + + +class btSoftBodyLinkDataDX11 : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + + + btDX11Buffer m_dx11Links; + btDX11Buffer m_dx11LinkStrength; + btDX11Buffer m_dx11LinksMassLSC; + btDX11Buffer m_dx11LinksRestLengthSquared; + btDX11Buffer m_dx11LinksCLength; + btDX11Buffer m_dx11LinksLengthRatio; + btDX11Buffer m_dx11LinksRestLength; + btDX11Buffer m_dx11LinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_batchStartLengths; + + + //ID3D11Buffer* readBackBuffer; + + btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + + virtual ~btSoftBodyLinkDataDX11(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( const LinkDescription &link, int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h new file mode 100644 index 00000000..6eb26c68 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h @@ -0,0 +1,173 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + +#ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H +#define BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H + +struct ID3D11Device; +struct ID3D11DeviceContext; + + +class btSoftBodyLinkDataDX11SIMDAware : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + + const int m_wavefrontSize; + const int m_linksPerWorkItem; + const int m_maxLinksPerWavefront; + int m_maxBatchesWithinWave; + int m_maxVerticesWithinWave; + int m_numWavefronts; + + int m_maxVertex; + + struct NumBatchesVerticesPair + { + int numBatches; + int numVertices; + }; + + // Array storing number of links in each wavefront + btAlignedObjectArray m_linksPerWavefront; + btAlignedObjectArray m_numBatchesAndVerticesWithinWaves; + btDX11Buffer< NumBatchesVerticesPair > m_dx11NumBatchesAndVerticesWithinWaves; + + // All arrays here will contain batches of m_maxLinksPerWavefront links + // ordered by wavefront. + // with either global vertex pairs or local vertex pairs + btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront + btDX11Buffer m_dx11WavefrontVerticesGlobalAddresses; + btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link + btDX11Buffer m_dx11LinkVerticesLocalAddresses; + btDX11Buffer m_dx11LinkStrength; + btDX11Buffer m_dx11LinksMassLSC; + btDX11Buffer m_dx11LinksRestLengthSquared; + btDX11Buffer m_dx11LinksRestLength; + btDX11Buffer m_dx11LinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths; + + + //ID3D11Buffer* readBackBuffer; + + btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + + virtual ~btSoftBodyLinkDataDX11SIMDAware(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( const LinkDescription &link, int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); + + int getMaxVerticesPerWavefront() + { + return m_maxVerticesWithinWave; + } + + int getWavefrontSize() + { + return m_wavefrontSize; + } + + int getLinksPerWorkItem() + { + return m_linksPerWorkItem; + } + + int getMaxLinksPerWavefront() + { + return m_maxLinksPerWavefront; + } + + int getMaxBatchesPerWavefront() + { + return m_maxBatchesWithinWave; + } + + int getNumWavefronts() + { + return m_numWavefronts; + } + + NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront ) + { + return m_numBatchesAndVerticesWithinWaves[wavefront]; + } + + int getVertexGlobalAddresses( int vertexIndex ) + { + return m_wavefrontVerticesGlobalAddresses[vertexIndex]; + } + + /** + * Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally. + */ + LinkNodePair getVertexPairLocalAddresses( int linkIndex ) + { + return m_linkVerticesLocalAddresses[linkIndex]; + } + +}; + + +#endif // #ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h new file mode 100644 index 00000000..7012fabd --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h @@ -0,0 +1,96 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + + +#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H +#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H + +struct ID3D11Device; +struct ID3D11DeviceContext; + +class btSoftBodyTriangleDataDX11 : public btSoftBodyTriangleData +{ +public: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + + btDX11Buffer m_dx11VertexIndices; + btDX11Buffer m_dx11Area; + btDX11Buffer m_dx11Normal; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_triangleAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_batchStartLengths; + + //ID3D11Buffer* readBackBuffer; + +public: + btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + + virtual ~btSoftBodyTriangleDataDX11(); + + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createTriangles( int numTriangles ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ); + + virtual bool onAccelerator(); + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + /** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h new file mode 100644 index 00000000..66bd90fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H +#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H + + +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" + +#include +#include +#include +#include +#include + +class btDX11VertexBufferDescriptor : public btVertexBufferDescriptor +{ +protected: + /** Context of the DX11 device on which the vertex buffer is stored. */ + ID3D11DeviceContext* m_context; + /** DX11 vertex buffer */ + ID3D11Buffer* m_vertexBuffer; + /** UAV for DX11 buffer */ + ID3D11UnorderedAccessView* m_vertexBufferUAV; + + +public: + /** + * buffer is a pointer to the DX11 buffer to place the vertex data in. + * UAV is a pointer to the UAV representation of the buffer laid out in floats. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride ) + { + m_context = context; + m_vertexBuffer = buffer; + m_vertexBufferUAV = UAV; + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + } + + /** + * buffer is a pointer to the DX11 buffer to place the vertex data in. + * UAV is a pointer to the UAV representation of the buffer laid out in floats. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + * normalOffset is the offset in floats to the first normal. + * normalStride is the stride in floats between normals. + */ + btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) + { + m_context = context; + m_vertexBuffer = buffer; + m_vertexBufferUAV = UAV; + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + + m_normalOffset = normalOffset; + m_normalStride = normalStride; + m_hasNormals = true; + } + + virtual ~btDX11VertexBufferDescriptor() + { + + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const + { + return DX11_BUFFER; + } + + virtual ID3D11DeviceContext* getContext() const + { + return m_context; + } + + virtual ID3D11Buffer* getbtDX11Buffer() const + { + return m_vertexBuffer; + } + + virtual ID3D11UnorderedAccessView* getDX11UAV() const + { + return m_vertexBufferUAV; + } +}; + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h new file mode 100644 index 00000000..dd7cc84c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h @@ -0,0 +1,63 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_DX11.h" + + +#ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H +#define BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H + +class btSoftBodyLinkData; +class btSoftBodyLinkData::LinkDescription; + +struct ID3D11Device; +struct ID3D11DeviceContext; + +class btSoftBodyVertexDataDX11 : public btSoftBodyVertexData +{ +protected: + bool m_onGPU; + ID3D11Device *m_d3dDevice; + ID3D11DeviceContext *m_d3dDeviceContext; + +public: + btDX11Buffer m_dx11ClothIdentifier; + btDX11Buffer m_dx11VertexPosition; + btDX11Buffer m_dx11VertexPreviousPosition; + btDX11Buffer m_dx11VertexVelocity; + btDX11Buffer m_dx11VertexForceAccumulator; + btDX11Buffer m_dx11VertexNormal; + btDX11Buffer m_dx11VertexInverseMass; + btDX11Buffer m_dx11VertexArea; + btDX11Buffer m_dx11VertexTriangleCount; + + + //ID3D11Buffer* readBackBuffer; + +public: + btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); + virtual ~btSoftBodyVertexDataDX11(); + + virtual bool onAccelerator(); + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true); +}; + + +#endif // #ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp new file mode 100644 index 00000000..357c4089 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp @@ -0,0 +1,2236 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" + +#include "btSoftBodySolver_DX11.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include //printf +#define MSTRINGIFY(A) #A +static char* PrepareLinksHLSLString = +#include "HLSL/PrepareLinks.hlsl" +static char* UpdatePositionsFromVelocitiesHLSLString = +#include "HLSL/UpdatePositionsFromVelocities.hlsl" +static char* SolvePositionsHLSLString = +#include "HLSL/SolvePositions.hlsl" +static char* UpdateNodesHLSLString = +#include "HLSL/UpdateNodes.hlsl" +static char* UpdatePositionsHLSLString = +#include "HLSL/UpdatePositions.hlsl" +static char* UpdateConstantsHLSLString = +#include "HLSL/UpdateConstants.hlsl" +static char* IntegrateHLSLString = +#include "HLSL/Integrate.hlsl" +static char* ApplyForcesHLSLString = +#include "HLSL/ApplyForces.hlsl" +static char* UpdateNormalsHLSLString = +#include "HLSL/UpdateNormals.hlsl" +static char* OutputToVertexArrayHLSLString = +#include "HLSL/OutputToVertexArray.hlsl" +static char* VSolveLinksHLSLString = +#include "HLSL/VSolveLinks.hlsl" +static char* ComputeBoundsHLSLString = +#include "HLSL/ComputeBounds.hlsl" +static char* SolveCollisionsAndUpdateVelocitiesHLSLString = +#include "HLSL/SolveCollisionsAndUpdateVelocities.hlsl" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +btSoftBodyLinkDataDX11::btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_dx11Links( d3dDevice, d3dDeviceContext, &m_links, false ), + m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, false ), + m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, false ), + m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, false ), + m_dx11LinksCLength( d3dDevice, d3dDeviceContext, &m_linksCLength, false ), + m_dx11LinksLengthRatio( d3dDevice, d3dDeviceContext, &m_linksLengthRatio, false ), + m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, false ), + m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, false ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyLinkDataDX11::~btSoftBodyLinkDataDX11() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +void btSoftBodyLinkDataDX11::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +void btSoftBodyLinkDataDX11::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataDX11::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataDX11::moveToAccelerator() +{ + bool success = true; + success = success && m_dx11Links.moveToGPU(); + success = success && m_dx11LinkStrength.moveToGPU(); + success = success && m_dx11LinksMassLSC.moveToGPU(); + success = success && m_dx11LinksRestLengthSquared.moveToGPU(); + success = success && m_dx11LinksCLength.moveToGPU(); + success = success && m_dx11LinksLengthRatio.moveToGPU(); + success = success && m_dx11LinksRestLength.moveToGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyLinkDataDX11::moveFromAccelerator() +{ + bool success = true; + success = success && m_dx11Links.moveFromGPU(); + success = success && m_dx11LinkStrength.moveFromGPU(); + success = success && m_dx11LinksMassLSC.moveFromGPU(); + success = success && m_dx11LinksRestLengthSquared.moveFromGPU(); + success = success && m_dx11LinksCLength.moveFromGPU(); + success = success && m_dx11LinksLengthRatio.moveFromGPU(); + success = success && m_dx11LinksRestLength.moveFromGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) + m_onGPU = false; + + return success; +} + +void btSoftBodyLinkDataDX11::generateBatches() +{ + int numLinks = getNumLinks(); + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numLinks, 0 ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int vertex0 = getVertexPair(linkIndex).vertex0; + int vertex1 = getVertexPair(linkIndex).vertex1; + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + + + // Simple algorithm that chooses the lowest batch number + // that none of the links attached to either of the connected + // nodes is in + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int linkLocation = m_linkAddresses[linkIndex]; + + int vertex0 = getVertexPair(linkLocation).vertex0; + int vertex1 = getVertexPair(linkLocation).vertex1; + + // Get the two node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + + // Choose the minimum colour that is in neither list + int colour = 0; + while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ) + ++colour; + // i should now be the minimum colour in neither list + // Add to the two lists so that future edges don't share + // And store the colour against this edge + + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + batchValues[linkIndex] = colour; + } + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numLinks; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + m_batchStartLengths.resize(batchCounts.size()); + if( m_batchStartLengths.size() > 0 ) + { + m_batchStartLengths[0] = BatchPair( 0, 0 ); + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].start = sum; + m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int linkLocation = m_linkAddresses[linkIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[linkIndex]; + int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_links[newLocation] = m_links_Backup[linkLocation]; +#if 1 + m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation]; + m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation]; + m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation]; + m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation]; + m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation]; + m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation]; +#endif + // Update the locations array to account for the moved entry + m_linkAddresses[linkIndex] = newLocation; + } +} // void btSoftBodyLinkDataDX11::generateBatches() + + + +btSoftBodyVertexDataDX11::btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_dx11ClothIdentifier( d3dDevice, d3dDeviceContext, &m_clothIdentifier, false ), + m_dx11VertexPosition( d3dDevice, d3dDeviceContext, &m_vertexPosition, false ), + m_dx11VertexPreviousPosition( d3dDevice, d3dDeviceContext, &m_vertexPreviousPosition, false ), + m_dx11VertexVelocity( d3dDevice, d3dDeviceContext, &m_vertexVelocity, false ), + m_dx11VertexForceAccumulator( d3dDevice, d3dDeviceContext, &m_vertexForceAccumulator, false ), + m_dx11VertexNormal( d3dDevice, d3dDeviceContext, &m_vertexNormal, false ), + m_dx11VertexInverseMass( d3dDevice, d3dDeviceContext, &m_vertexInverseMass, false ), + m_dx11VertexArea( d3dDevice, d3dDeviceContext, &m_vertexArea, false ), + m_dx11VertexTriangleCount( d3dDevice, d3dDeviceContext, &m_vertexTriangleCount, false ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyVertexDataDX11::~btSoftBodyVertexDataDX11() +{ + +} + +bool btSoftBodyVertexDataDX11::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyVertexDataDX11::moveToAccelerator() +{ + bool success = true; + success = success && m_dx11ClothIdentifier.moveToGPU(); + success = success && m_dx11VertexPosition.moveToGPU(); + success = success && m_dx11VertexPreviousPosition.moveToGPU(); + success = success && m_dx11VertexVelocity.moveToGPU(); + success = success && m_dx11VertexForceAccumulator.moveToGPU(); + success = success && m_dx11VertexNormal.moveToGPU(); + success = success && m_dx11VertexInverseMass.moveToGPU(); + success = success && m_dx11VertexArea.moveToGPU(); + success = success && m_dx11VertexTriangleCount.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyVertexDataDX11::moveFromAccelerator(bool bCopy, bool bCopyMinimum) +{ + bool success = true; + + if (!bCopy) + { + success = success && m_dx11ClothIdentifier.moveFromGPU(); + success = success && m_dx11VertexPosition.moveFromGPU(); + success = success && m_dx11VertexPreviousPosition.moveFromGPU(); + success = success && m_dx11VertexVelocity.moveFromGPU(); + success = success && m_dx11VertexForceAccumulator.moveFromGPU(); + success = success && m_dx11VertexNormal.moveFromGPU(); + success = success && m_dx11VertexInverseMass.moveFromGPU(); + success = success && m_dx11VertexArea.moveFromGPU(); + success = success && m_dx11VertexTriangleCount.moveFromGPU(); + } + else + { + if (bCopyMinimum) + { + success = success && m_dx11VertexPosition.copyFromGPU(); + success = success && m_dx11VertexNormal.copyFromGPU(); + } + else + { + success = success && m_dx11ClothIdentifier.copyFromGPU(); + success = success && m_dx11VertexPosition.copyFromGPU(); + success = success && m_dx11VertexPreviousPosition.copyFromGPU(); + success = success && m_dx11VertexVelocity.copyFromGPU(); + success = success && m_dx11VertexForceAccumulator.copyFromGPU(); + success = success && m_dx11VertexNormal.copyFromGPU(); + success = success && m_dx11VertexInverseMass.copyFromGPU(); + success = success && m_dx11VertexArea.copyFromGPU(); + success = success && m_dx11VertexTriangleCount.copyFromGPU(); + } + } + + if( success ) + m_onGPU = true; + + return success; +} + + +btSoftBodyTriangleDataDX11::btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_dx11VertexIndices( d3dDevice, d3dDeviceContext, &m_vertexIndices, false ), + m_dx11Area( d3dDevice, d3dDeviceContext, &m_area, false ), + m_dx11Normal( d3dDevice, d3dDeviceContext, &m_normal, false ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyTriangleDataDX11::~btSoftBodyTriangleDataDX11() +{ + +} + + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyTriangleDataDX11::createTriangles( int numTriangles ) +{ + int previousSize = getNumTriangles(); + int newSize = previousSize + numTriangles; + + btSoftBodyTriangleData::createTriangles( numTriangles ); + + // Resize the link addresses array as well + m_triangleAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyTriangleDataDX11::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ) +{ + btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex ); + + m_triangleAddresses[triangleIndex] = triangleIndex; +} + +bool btSoftBodyTriangleDataDX11::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyTriangleDataDX11::moveToAccelerator() +{ + bool success = true; + success = success && m_dx11VertexIndices.moveToGPU(); + success = success && m_dx11Area.moveToGPU(); + success = success && m_dx11Normal.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyTriangleDataDX11::moveFromAccelerator() +{ + bool success = true; + success = success && m_dx11VertexIndices.moveFromGPU(); + success = success && m_dx11Area.moveFromGPU(); + success = success && m_dx11Normal.moveFromGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +/** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ +void btSoftBodyTriangleDataDX11::generateBatches() +{ + int numTriangles = getNumTriangles(); + if( numTriangles == 0 ) + return; + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numTriangles ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + int vertex0 = getVertexSet(triangleIndex).vertex0; + int vertex1 = getVertexSet(triangleIndex).vertex1; + int vertex2 = getVertexSet(triangleIndex).vertex2; + + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + if( vertex2 > maxVertex ) + maxVertex = vertex2; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + + //std::cout << "\n"; + // Simple algorithm that chooses the lowest batch number + // that none of the faces attached to either of the connected + // nodes is in + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + int vertex0 = getVertexSet(triangleLocation).vertex0; + int vertex1 = getVertexSet(triangleLocation).vertex1; + int vertex2 = getVertexSet(triangleLocation).vertex2; + + // Get the three node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] ); + + // Choose the minimum colour that is in none of the lists + int colour = 0; + while( + colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || + colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() || + colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() ) + { + ++colour; + } + // i should now be the minimum colour in neither list + // Add to the three lists so that future edges don't share + // And store the colour against this face + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + colourListVertex2.push_back(colour); + + batchValues[triangleIndex] = colour; + } + + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numTriangles; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + + m_batchStartLengths.resize(batchCounts.size()); + m_batchStartLengths[0] = BatchPair( 0, 0 ); + + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].start = sum; + m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_vertexIndices_Backup(m_vertexIndices); + btAlignedObjectArray m_area_Backup(m_area); + btAlignedObjectArray m_normal_Backup(m_normal); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[triangleIndex]; + int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation]; + m_area[newLocation] = m_area_Backup[triangleLocation]; + m_normal[newLocation] = m_normal_Backup[triangleLocation]; + + // Update the locations array to account for the moved entry + m_triangleAddresses[triangleIndex] = newLocation; + } +} // btSoftBodyTriangleDataDX11::generateBatches + + + + + + + + + + + + +btDX11SoftBodySolver::btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) : + m_dx11Device( dx11Device ), + m_dx11Context( dx11Context ), + dxFunctions( m_dx11Device, m_dx11Context, dx11CompileFromMemory ), + m_linkData(m_dx11Device, m_dx11Context), + m_vertexData(m_dx11Device, m_dx11Context), + m_triangleData(m_dx11Device, m_dx11Context), + m_dx11PerClothAcceleration( m_dx11Device, m_dx11Context, &m_perClothAcceleration, true ), + m_dx11PerClothWindVelocity( m_dx11Device, m_dx11Context, &m_perClothWindVelocity, true ), + m_dx11PerClothDampingFactor( m_dx11Device, m_dx11Context, &m_perClothDampingFactor, true ), + m_dx11PerClothVelocityCorrectionCoefficient( m_dx11Device, m_dx11Context, &m_perClothVelocityCorrectionCoefficient, true ), + m_dx11PerClothLiftFactor( m_dx11Device, m_dx11Context, &m_perClothLiftFactor, true ), + m_dx11PerClothDragFactor( m_dx11Device, m_dx11Context, &m_perClothDragFactor, true ), + m_dx11PerClothMediumDensity( m_dx11Device, m_dx11Context, &m_perClothMediumDensity, true ), + m_dx11PerClothCollisionObjects( m_dx11Device, m_dx11Context, &m_perClothCollisionObjects, true ), + m_dx11CollisionObjectDetails( m_dx11Device, m_dx11Context, &m_collisionObjectDetails, true ), + m_dx11PerClothMinBounds( m_dx11Device, m_dx11Context, &m_perClothMinBounds, false ), + m_dx11PerClothMaxBounds( m_dx11Device, m_dx11Context, &m_perClothMaxBounds, false ), + m_dx11PerClothFriction( m_dx11Device, m_dx11Context, &m_perClothFriction, false ), + m_enableUpdateBounds(false) +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; +} + +btDX11SoftBodySolver::~btDX11SoftBodySolver() +{ + releaseKernels(); +} + +void btDX11SoftBodySolver::releaseKernels() +{ + + SAFE_RELEASE( prepareLinksKernel.kernel ); + SAFE_RELEASE( prepareLinksKernel.constBuffer ); + SAFE_RELEASE( integrateKernel.kernel ); + SAFE_RELEASE( integrateKernel.constBuffer ); + SAFE_RELEASE( integrateKernel.kernel ); + SAFE_RELEASE( solvePositionsFromLinksKernel.constBuffer ); + SAFE_RELEASE( solvePositionsFromLinksKernel.kernel ); + SAFE_RELEASE( updatePositionsFromVelocitiesKernel.constBuffer ); + SAFE_RELEASE( updatePositionsFromVelocitiesKernel.kernel ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ); + SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel ); + SAFE_RELEASE( resetNormalsAndAreasKernel.constBuffer ); + SAFE_RELEASE( resetNormalsAndAreasKernel.kernel ); + SAFE_RELEASE( normalizeNormalsAndAreasKernel.constBuffer ); + SAFE_RELEASE( normalizeNormalsAndAreasKernel.kernel ); + SAFE_RELEASE( updateSoftBodiesKernel.constBuffer ); + SAFE_RELEASE( updateSoftBodiesKernel.kernel ); + SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.kernel ); + SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.constBuffer ); + SAFE_RELEASE( computeBoundsKernel.kernel ); + SAFE_RELEASE( computeBoundsKernel.constBuffer ); + SAFE_RELEASE( vSolveLinksKernel.kernel ); + SAFE_RELEASE( vSolveLinksKernel.constBuffer ); + + SAFE_RELEASE( addVelocityKernel.constBuffer ); + SAFE_RELEASE( addVelocityKernel.kernel ); + SAFE_RELEASE( applyForcesKernel.constBuffer ); + SAFE_RELEASE( applyForcesKernel.kernel ); + + m_shadersInitialized = false; +} + + +void btDX11SoftBodySolver::copyBackToSoftBodies(bool bMove) +{ + // Move the vertex data back to the host first + m_vertexData.moveFromAccelerator(!bMove); + + // Loop over soft bodies, copying all the vertex positions back for each body in turn + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ]; + btSoftBody *softBody = softBodyInterface->getSoftBody(); + + int firstVertex = softBodyInterface->getFirstVertex(); + int numVertices = softBodyInterface->getNumVertices(); + + // Copy vertices from solver back into the softbody + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + using Vectormath::Aos::Point3; + Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] ); + + softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() ); + softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() ); + softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() ); + + softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() ); + softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() ); + softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() ); + } + } +} // btDX11SoftBodySolver::copyBackToSoftBodies + + +void btDX11SoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate ) +{ + if( forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) ); + m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) ); + m_perClothFriction.push_back( softBody->getFriction() ); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + int maxVertices = numVertices; + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( maxVertices, softBodyIndex ); + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + } + + + + updateConstants(0.f); + + + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + } +} + + +btSoftBodyLinkData &btDX11SoftBodySolver::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + +btSoftBodyVertexData &btDX11SoftBodySolver::getVertexData() +{ + // TODO: Consider setting vertex data to "changed" here + return m_vertexData; +} + +btSoftBodyTriangleData &btDX11SoftBodySolver::getTriangleData() +{ + // TODO: Consider setting triangle data to "changed" here + return m_triangleData; +} + +bool btDX11SoftBodySolver::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + +void btDX11SoftBodySolver::resetNormalsAndAreas( int numVertices ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdateSoftBodiesCB constBuffer; + + constBuffer.numNodes = numVertices; + constBuffer.epsilon = FLT_EPSILON; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( resetNormalsAndAreasKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::resetNormalsAndAreas + +void btDX11SoftBodySolver::normalizeNormalsAndAreas( int numVertices ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdateSoftBodiesCB constBuffer; + + constBuffer.numNodes = numVertices; + constBuffer.epsilon = FLT_EPSILON; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexTriangleCount.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( normalizeNormalsAndAreasKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::normalizeNormalsAndAreas + +void btDX11SoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdateSoftBodiesCB constBuffer; + + constBuffer.startFace = firstTriangle; + constBuffer.numFaces = numTriangles; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updateSoftBodiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); + m_dx11Context->Unmap( updateSoftBodiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updateSoftBodiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_triangleData.m_dx11VertexIndices.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_triangleData.m_dx11Normal.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_triangleData.m_dx11Area.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( updateSoftBodiesKernel.kernel, NULL, 0 ); + + int numBlocks = (numTriangles + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::executeUpdateSoftBodies + +void btDX11SoftBodySolver::updateSoftBodies() +{ + using namespace Vectormath::Aos; + + + int numVertices = m_vertexData.getNumVertices(); + int numTriangles = m_triangleData.getNumTriangles(); + + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_triangleData.moveToAccelerator(); + + resetNormalsAndAreas( numVertices ); + + + // Go through triangle batches so updates occur correctly + for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex ) + { + + int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].start; + int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].length; + + executeUpdateSoftBodies( startTriangle, numTriangles ); + } + + + normalizeNormalsAndAreas( numVertices ); + + +} // btDX11SoftBodySolver::updateSoftBodies + + +Vectormath::Aos::Vector3 btDX11SoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ) +{ + return a*Vectormath::Aos::dot(v, a); +} + +void btDX11SoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ) +{ + float dtInverseMass = solverdt*inverseMass; + if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) ) + { + vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass; + } else { + vertexForce += force; + } +} + +void btDX11SoftBodySolver::applyForces( float solverdt ) +{ + using namespace Vectormath::Aos; + + + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_dx11PerClothAcceleration.moveToGPU(); + m_dx11PerClothLiftFactor.moveToGPU(); + m_dx11PerClothDragFactor.moveToGPU(); + m_dx11PerClothMediumDensity.moveToGPU(); + m_dx11PerClothWindVelocity.moveToGPU(); + + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + ApplyForcesCB constBuffer; + + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.solverdt = solverdt; + constBuffer.epsilon = FLT_EPSILON; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(ApplyForcesCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexNormal.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexArea.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothLiftFactor.getSRV()) ); + m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11PerClothDragFactor.getSRV()) ); + m_dx11Context->CSSetShaderResources( 6, 1, &(m_dx11PerClothWindVelocity.getSRV()) ); + m_dx11Context->CSSetShaderResources( 7, 1, &(m_dx11PerClothAcceleration.getSRV()) ); + m_dx11Context->CSSetShaderResources( 8, 1, &(m_dx11PerClothMediumDensity.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( applyForcesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 6, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 7, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 8, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::applyForces + +/** + * Integrate motion on the solver. + */ +void btDX11SoftBodySolver::integrate( float solverdt ) +{ + // TEMPORARY COPIES + m_vertexData.moveToAccelerator(); + + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + IntegrateCB constBuffer; + + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.solverdt = solverdt; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(IntegrateCB) ); + m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( integrateKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::integrate + +float btDX11SoftBodySolver::computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ) +{ + Vectormath::Aos::Vector3 a = vertex1 - vertex0; + Vectormath::Aos::Vector3 b = vertex2 - vertex0; + Vectormath::Aos::Vector3 crossProduct = cross(a, b); + float area = length( crossProduct ); + return area; +} // btDX11SoftBodySolver::computeTriangleArea + + +void btDX11SoftBodySolver::updateBounds() +{ + using Vectormath::Aos::Point3; + // Interpretation structure for float and int + + struct FPRep { + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + }; + union FloatAsInt + { + float floatValue; + int intValue; + unsigned int uintValue; + FPRep fpRep; + }; + + + // Update bounds array to min and max int values to allow easy atomics + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + m_perClothMinBounds[softBodyIndex] = UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ); + m_perClothMaxBounds[softBodyIndex] = UIntVector3( 0, 0, 0 ); + } + + m_dx11PerClothMinBounds.moveToGPU(); + m_dx11PerClothMaxBounds.moveToGPU(); + + + computeBounds( ); + + + m_dx11PerClothMinBounds.moveFromGPU(); + m_dx11PerClothMaxBounds.moveFromGPU(); + + + + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + UIntVector3 minBoundUInt = m_perClothMinBounds[softBodyIndex]; + UIntVector3 maxBoundUInt = m_perClothMaxBounds[softBodyIndex]; + + // Convert back to float + FloatAsInt fai; + + btVector3 minBound; + fai.uintValue = minBoundUInt.x; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + minBound.setX( fai.floatValue ); + fai.uintValue = minBoundUInt.y; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + minBound.setY( fai.floatValue ); + fai.uintValue = minBoundUInt.z; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + minBound.setZ( fai.floatValue ); + + btVector3 maxBound; + fai.uintValue = maxBoundUInt.x; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + maxBound.setX( fai.floatValue ); + fai.uintValue = maxBoundUInt.y; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + maxBound.setY( fai.floatValue ); + fai.uintValue = maxBoundUInt.z; + fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); + maxBound.setZ( fai.floatValue ); + + // And finally assign to the soft body + m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound ); + } +} + +void btDX11SoftBodySolver::updateConstants( float timeStep ) +{ + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } +} // btDX11SoftBodySolver::updateConstants + +/** + * Sort the collision object details array and generate indexing into it for the per-cloth collision object array. + */ +void btDX11SoftBodySolver::prepareCollisionConstraints() +{ + // First do a simple sort on the collision objects + btAlignedObjectArray numObjectsPerClothPrefixSum; + btAlignedObjectArray numObjectsPerCloth; + numObjectsPerCloth.resize( m_softBodySet.size(), 0 ); + numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 ); + + + class QuickSortCompare + { + public: + + bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const + { + return ( a.softBodyIdentifier < b.softBodyIdentifier ); + } + }; + + QuickSortCompare comparator; + m_collisionObjectDetails.quickSort( comparator ); + + // Generating indexing for perClothCollisionObjects + // First clear the previous values with the "no collision object for cloth" constant + for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex ) + { + m_perClothCollisionObjects[clothIndex].firstObject = -1; + m_perClothCollisionObjects[clothIndex].endObject = -1; + } + int currentCloth = 0; + int startIndex = 0; + for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject ) + { + int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier; + if( nextCloth != currentCloth ) + { + // Changed cloth in the array + // Set the end index and the range is what we need for currentCloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = collisionObject; + currentCloth = nextCloth; + startIndex = collisionObject; + } + } + + // And update last cloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size(); + +} // btDX11SoftBodySolver::prepareCollisionConstraints + + +void btDX11SoftBodySolver::solveConstraints( float solverdt ) +{ + + //std::cerr << "'GPU' solve constraints\n"; + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_dx11PerClothDampingFactor.moveToGPU(); + m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU(); + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + + prepareLinks(); + + for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForVelocity( startLink, numLinks, kst ); + } + } + + + prepareCollisionConstraints(); + + // Compute new positions from velocity + // Also update the previous position so that our position computation is now based on the new position from the velocity solution + // rather than based directly on the original positions + if( m_numberOfVelocityIterations > 0 ) + { + updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt ); + } else { + updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt ); + } + + + // Solve drift + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForPosition( startLink, numLinks, kst, ti ); + } + + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); +} // btDX11SoftBodySolver::solveConstraints + + + + +////////////////////////////////////// +// Kernel dispatches +void btDX11SoftBodySolver::prepareLinks() +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + PrepareLinksCB constBuffer; + + constBuffer.numLinks = m_linkData.getNumLinks(); + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( prepareLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(PrepareLinksCB) ); + m_dx11Context->Unmap( prepareLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &prepareLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_linkData.m_dx11LinksLengthRatio.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_linkData.m_dx11LinksCLength.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( prepareLinksKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numLinks + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::prepareLinks + + +void btDX11SoftBodySolver::updatePositionsFromVelocities( float solverdt ) +{ + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + UpdatePositionsFromVelocitiesCB constBuffer; + + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.solverSDT = solverdt; + + // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updatePositionsFromVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdatePositionsFromVelocitiesCB) ); + m_dx11Context->Unmap( updatePositionsFromVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updatePositionsFromVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( updatePositionsFromVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::updatePositionsFromVelocities + +void btDX11SoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti ) +{ + // Copy kernel parameters to GPU + SolvePositionsFromLinksKernelCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.startLink = startLink; + constBuffer.numLinks = numLinks; + + constBuffer.kst = kst; + constBuffer.ti = ti; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) ); + m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numLinks + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::solveLinksForPosition + +void btDX11SoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst ) +{ + // Copy kernel parameters to GPU + VSolveLinksCB constBuffer; + + // Set the first link of the batch + // and the batch size + + constBuffer.startLink = startLink; + constBuffer.numLinks = numLinks; + constBuffer.kst = kst; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( vSolveLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(VSolveLinksCB) ); + m_dx11Context->Unmap( vSolveLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &vSolveLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksLengthRatio.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksCLength.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( vSolveLinksKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numLinks + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SoftBodySolver::solveLinksForVelocity + + +void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + UpdateVelocitiesFromPositionsWithVelocitiesCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.isolverdt = isolverdt; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); + m_dx11Context->Unmap( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothVelocityCorrectionCoefficient.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + + + // Execute the kernel + m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities + +void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + UpdateVelocitiesFromPositionsWithoutVelocitiesCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.isolverdt = isolverdt; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); + m_dx11Context->Unmap( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + + + // Execute the kernel + m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities + + +void btDX11SoftBodySolver::computeBounds( ) +{ + ComputeBoundsCB constBuffer; + m_vertexData.moveToAccelerator(); + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.numSoftBodies = m_softBodySet.size(); + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( computeBoundsKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(ComputeBoundsCB) ); + m_dx11Context->Unmap( computeBoundsKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &computeBoundsKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_dx11PerClothMinBounds.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_dx11PerClothMaxBounds.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( computeBoundsKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} + +void btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt ) +{ + + // Copy kernel parameters to GPU + m_vertexData.moveToAccelerator(); + m_dx11PerClothFriction.moveToGPU(); + m_dx11PerClothDampingFactor.moveToGPU(); + m_dx11PerClothCollisionObjects.moveToGPU(); + m_dx11CollisionObjectDetails.moveToGPU(); + + SolveCollisionsAndUpdateVelocitiesCB constBuffer; + + // Set the first link of the batch + // and the batch size + constBuffer.numNodes = m_vertexData.getNumVertices(); + constBuffer.isolverdt = isolverdt; + + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); + m_dx11Context->Unmap( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &solveCollisionsAndUpdateVelocitiesKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_dx11PerClothFriction.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothCollisionObjects.getSRV()) ); + m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11CollisionObjectDetails.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( solveCollisionsAndUpdateVelocitiesKernel.kernel, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); + m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + +} // btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities + +// End kernel dispatches +///////////////////////////////////// + + + + + + + + + + + + + + +btDX11SoftBodySolver::btAcceleratedSoftBodyInterface *btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyInterface; + } + return 0; +} + +const btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * const btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) const +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyInterface; + } + return 0; +} + +int btDX11SoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyIndex; + } + return 1; +} + + +void btSoftBodySolverOutputDXtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER ); + btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver ); + + btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData ); + + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + // If we're doing a CPU-buffer copy must copy the data back to the host first + vertexData.m_dx11VertexPosition.copyFromGPU(); + vertexData.m_dx11VertexNormal.copyFromGPU(); + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); + float *basePointer = cpuVertexBuffer->getBasePointer(); + + if( vertexBuffer->hasVertexPositions() ) + { + const int vertexOffset = cpuVertexBuffer->getVertexOffset(); + const int vertexStride = cpuVertexBuffer->getVertexStride(); + float *vertexPointer = basePointer + vertexOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex); + *(vertexPointer + 0) = position.getX(); + *(vertexPointer + 1) = position.getY(); + *(vertexPointer + 2) = position.getZ(); + vertexPointer += vertexStride; + } + } + if( vertexBuffer->hasNormals() ) + { + const int normalOffset = cpuVertexBuffer->getNormalOffset(); + const int normalStride = cpuVertexBuffer->getNormalStride(); + float *normalPointer = basePointer + normalOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex); + *(normalPointer + 0) = normal.getX(); + *(normalPointer + 1) = normal.getY(); + *(normalPointer + 2) = normal.getZ(); + normalPointer += normalStride; + } + } + } +} // btDX11SoftBodySolver::outputToVertexBuffers + + + +bool btSoftBodySolverOutputDXtoDX::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + +void btSoftBodySolverOutputDXtoDX::releaseKernels() +{ + SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.constBuffer ); + SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.kernel ); + SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.constBuffer ); + SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.kernel ); + + m_shadersInitialized = false; +} + + +bool btSoftBodySolverOutputDXtoDX::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + if( m_shadersInitialized ) + return true; + + + outputToVertexArrayWithNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithNormalsKernel", sizeof(OutputToVertexArrayCB) ); + if( !outputToVertexArrayWithNormalsKernel.constBuffer) + returnVal = false; + outputToVertexArrayWithoutNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithoutNormalsKernel", sizeof(OutputToVertexArrayCB) ); + if( !outputToVertexArrayWithoutNormalsKernel.constBuffer ) + returnVal = false; + + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} + + +void btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER ); + btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver ); + checkInitialized(); + btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData ); + + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( softBody, vertexBuffer ); + } else if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::DX11_BUFFER ) + { + // Do a DX11 copy shader DX to DX copy + + const btDX11VertexBufferDescriptor *dx11VertexBuffer = static_cast< btDX11VertexBufferDescriptor* >(vertexBuffer); + + // No need to batch link solver, it is entirely parallel + // Copy kernel parameters to GPU + OutputToVertexArrayCB constBuffer; + ID3D11ComputeShader* outputToVertexArrayShader = outputToVertexArrayWithoutNormalsKernel.kernel; + ID3D11Buffer* outputToVertexArrayConstBuffer = outputToVertexArrayWithoutNormalsKernel.constBuffer; + + constBuffer.startNode = firstVertex; + constBuffer.numNodes = currentCloth->getNumVertices(); + constBuffer.positionOffset = vertexBuffer->getVertexOffset(); + constBuffer.positionStride = vertexBuffer->getVertexStride(); + if( vertexBuffer->hasNormals() ) + { + constBuffer.normalOffset = vertexBuffer->getNormalOffset(); + constBuffer.normalStride = vertexBuffer->getNormalStride(); + outputToVertexArrayShader = outputToVertexArrayWithNormalsKernel.kernel; + outputToVertexArrayConstBuffer = outputToVertexArrayWithNormalsKernel.constBuffer; + } + + // TODO: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + dxFunctions.m_dx11Context->Map( outputToVertexArrayConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(OutputToVertexArrayCB) ); + dxFunctions.m_dx11Context->Unmap( outputToVertexArrayConstBuffer, 0 ); + dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &outputToVertexArrayConstBuffer ); + + // Set resources and dispatch + dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &(vertexData.m_dx11VertexPosition.getSRV()) ); + dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &(vertexData.m_dx11VertexNormal.getSRV()) ); + + ID3D11UnorderedAccessView* dx11UAV = dx11VertexBuffer->getDX11UAV(); + dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(dx11UAV), NULL ); + + // Execute the kernel + dxFunctions.m_dx11Context->CSSetShader( outputToVertexArrayShader, NULL, 0 ); + + int numBlocks = (constBuffer.numNodes + (128-1)) / 128; + dxFunctions.m_dx11Context->Dispatch(numBlocks, 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } + } +} // btDX11SoftBodySolver::outputToVertexBuffers + + + + +DXFunctions::KernelDesc DXFunctions::compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros ) +{ + const char *cs5String = "cs_5_0"; + + HRESULT hr = S_OK; + ID3DBlob* pErrorBlob = NULL; + ID3DBlob* pBlob = NULL; + ID3D11ComputeShader* kernelPointer = 0; + + hr = m_dx11CompileFromMemory( + shaderString, + strlen(shaderString), + shaderName, + compileMacros, + NULL, + shaderName, + cs5String, + D3D10_SHADER_ENABLE_STRICTNESS, + NULL, + NULL, + &pBlob, + &pErrorBlob, + NULL + ); + + if( FAILED(hr) ) + { + if( pErrorBlob ) { + btAssert( "Compilation of compute shader failed\n" ); + char *debugString = (char*)pErrorBlob->GetBufferPointer(); + OutputDebugStringA( debugString ); + } + + SAFE_RELEASE( pErrorBlob ); + SAFE_RELEASE( pBlob ); + + DXFunctions::KernelDesc descriptor; + descriptor.kernel = 0; + descriptor.constBuffer = 0; + return descriptor; + } + + // Create the Compute Shader + hr = m_dx11Device->CreateComputeShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &kernelPointer ); + if( FAILED( hr ) ) + { + DXFunctions::KernelDesc descriptor; + descriptor.kernel = 0; + descriptor.constBuffer = 0; + return descriptor; + } + + ID3D11Buffer* constBuffer = 0; + if( constBufferSize > 0 ) + { + // Create the constant buffer + D3D11_BUFFER_DESC constant_buffer_desc; + ZeroMemory(&constant_buffer_desc, sizeof(constant_buffer_desc)); + constant_buffer_desc.ByteWidth = constBufferSize; + constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + m_dx11Device->CreateBuffer(&constant_buffer_desc, NULL, &constBuffer); + if( FAILED( hr ) ) + { + KernelDesc descriptor; + descriptor.kernel = 0; + descriptor.constBuffer = 0; + return descriptor; + } + } + + SAFE_RELEASE( pErrorBlob ); + SAFE_RELEASE( pBlob ); + + DXFunctions::KernelDesc descriptor; + descriptor.kernel = kernelPointer; + descriptor.constBuffer = constBuffer; + return descriptor; +} // compileComputeShader + + + +bool btDX11SoftBodySolver::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + if( m_shadersInitialized ) + return true; + + prepareLinksKernel = dxFunctions.compileComputeShaderFromString( PrepareLinksHLSLString, "PrepareLinksKernel", sizeof(PrepareLinksCB) ); + if( !prepareLinksKernel.constBuffer ) + returnVal = false; + updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) ); + if( !updatePositionsFromVelocitiesKernel.constBuffer ) + returnVal = false; + solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB) ); + if( !updatePositionsFromVelocitiesKernel.constBuffer ) + returnVal = false; + vSolveLinksKernel = dxFunctions.compileComputeShaderFromString( VSolveLinksHLSLString, "VSolveLinksKernel", sizeof(VSolveLinksCB) ); + if( !vSolveLinksKernel.constBuffer ) + returnVal = false; + updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); + if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ) + returnVal = false; + updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); + if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ) + returnVal = false; + integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) ); + if( !integrateKernel.constBuffer ) + returnVal = false; + applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) ); + if( !applyForcesKernel.constBuffer ) + returnVal = false; + solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); + if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer ) + returnVal = false; + + // TODO: Rename to UpdateSoftBodies + resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !resetNormalsAndAreasKernel.constBuffer ) + returnVal = false; + normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !normalizeNormalsAndAreasKernel.constBuffer ) + returnVal = false; + updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) ); + if( !updateSoftBodiesKernel.constBuffer ) + returnVal = false; + + computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) ); + if( !computeBoundsKernel.constBuffer ) + returnVal = false; + + + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} + + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + + +void btDX11SoftBodySolver::btAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ) +{ + float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin(); + btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin ); + m_softBody->m_bounds[0] = lowerBound - vectorMargin; + m_softBody->m_bounds[1] = upperBound + vectorMargin; +} + +void btDX11SoftBodySolver::processCollision( btSoftBody*, btSoftBody* ) +{ + +} + +// Add the collision object to the set to deal with for a particular soft body +void btDX11SoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObject ) +{ + int softBodyIndex = findSoftBodyIndex( softBody ); + + if( softBodyIndex >= 0 ) + { + const btCollisionShape *collisionShape = collisionObject->getCollisionShape(); + float friction = collisionObject->getCollisionObject()->getFriction(); + int shapeType = collisionShape->getShapeType(); + if( shapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Add to the list of expected collision objects + CollisionShapeDescription newCollisionShapeDescription; + newCollisionShapeDescription.softBodyIdentifier = softBodyIndex; + newCollisionShapeDescription.collisionShapeType = shapeType; + // TODO: May need to transpose this matrix either here or in HLSL + newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform()); + const btCapsuleShape *capsule = static_cast( collisionShape ); + newCollisionShapeDescription.radius = capsule->getRadius(); + newCollisionShapeDescription.halfHeight = capsule->getHalfHeight(); + newCollisionShapeDescription.margin = capsule->getMargin(); + newCollisionShapeDescription.friction = friction; + const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() ); + newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity()); + newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity()); + m_collisionObjectDetails.push_back( newCollisionShapeDescription ); + + } else { +#ifdef _DEBUG + printf("Unsupported collision shape type\n"); +#endif + } + } else { + btAssert("Unknown soft body"); + } +} // btDX11SoftBodySolver::processCollision + + + +void btDX11SoftBodySolver::predictMotion( float timeStep ) +{ + // Clear the collision shape array for the next frame + // Ensure that the DX11 ones are moved off the device so they will be updated correctly + m_dx11CollisionObjectDetails.changedOnCPU(); + m_dx11PerClothCollisionObjects.changedOnCPU(); + m_collisionObjectDetails.clear(); + + // Fill the force arrays with current acceleration data etc + m_perClothWindVelocity.resize( m_softBodySet.size() ); + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); + + m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); + } + m_dx11PerClothWindVelocity.changedOnCPU(); + + // Apply forces that we know about to the cloths + applyForces( timeStep * getTimeScale() ); + + // Itegrate motion for all soft bodies dealt with by the solver + integrate( timeStep * getTimeScale() ); + + // Update bounds + // Will update the bounds for all softBodies being dealt with by the solver and + // set the values in the btSoftBody object + if (m_enableUpdateBounds) + updateBounds(); + + // End prediction work for solvers +} + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h new file mode 100644 index 00000000..0f50ecf7 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h @@ -0,0 +1,691 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H +#define BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H + + +#include "vectormath/vmInclude.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "btSoftBodySolverLinkData_DX11.h" +#include "btSoftBodySolverVertexData_DX11.h" +#include "btSoftBodySolverTriangleData_DX11.h" + + + +class DXFunctions +{ +public: + + typedef HRESULT (WINAPI * CompileFromMemoryFunc)(LPCSTR,SIZE_T,LPCSTR,const D3D10_SHADER_MACRO*,LPD3D10INCLUDE,LPCSTR,LPCSTR,UINT,UINT,ID3DX11ThreadPump*,ID3D10Blob**,ID3D10Blob**,HRESULT*); + + ID3D11Device * m_dx11Device; + ID3D11DeviceContext* m_dx11Context; + CompileFromMemoryFunc m_dx11CompileFromMemory; + + DXFunctions(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, CompileFromMemoryFunc dx11CompileFromMemory) : + m_dx11Device( dx11Device ), + m_dx11Context( dx11Context ), + m_dx11CompileFromMemory( dx11CompileFromMemory ) + { + + } + + class KernelDesc + { + protected: + + + public: + ID3D11ComputeShader* kernel; + ID3D11Buffer* constBuffer; + + KernelDesc() + { + kernel = 0; + constBuffer = 0; + } + + virtual ~KernelDesc() + { + // TODO: this should probably destroy its kernel but we need to be careful + // in case KernelDescs are copied + } + }; + + /** + * Compile a compute shader kernel from a string and return the appropriate KernelDesc object. + */ + KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros = 0 ); + +}; + +class btDX11SoftBodySolver : public btSoftBodySolver +{ +protected: + /** + * Entry in the collision shape array. + * Specifies the shape type, the transform matrix and the necessary details of the collisionShape. + */ + struct CollisionShapeDescription + { + Vectormath::Aos::Transform3 shapeTransform; + Vectormath::Aos::Vector3 linearVelocity; + Vectormath::Aos::Vector3 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + // Both needed for capsule + float radius; + float halfHeight; + + float margin; + float friction; + + CollisionShapeDescription() + { + collisionShapeType = 0; + margin = 0; + friction = 0; + } + }; + + struct UIntVector3 + { + UIntVector3() + { + x = 0; + y = 0; + z = 0; + _padding = 0; + } + + UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ ) + { + x = x_; + y = y_; + z = z_; + _padding = 0; + } + + unsigned int x; + unsigned int y; + unsigned int z; + unsigned int _padding; + }; + + + +public: + /** + * SoftBody class to maintain information about a soft body instance + * within a solver. + * This data addresses the main solver arrays. + */ + class btAcceleratedSoftBodyInterface + { + protected: + /** Current number of vertices that are part of this cloth */ + int m_numVertices; + /** Maximum number of vertices allocated to be part of this cloth */ + int m_maxVertices; + /** Current number of triangles that are part of this cloth */ + int m_numTriangles; + /** Maximum number of triangles allocated to be part of this cloth */ + int m_maxTriangles; + /** Index of first vertex in the world allocated to this cloth */ + int m_firstVertex; + /** Index of first triangle in the world allocated to this cloth */ + int m_firstTriangle; + /** Index of first link in the world allocated to this cloth */ + int m_firstLink; + /** Maximum number of links allocated to this cloth */ + int m_maxLinks; + /** Current number of links allocated to this cloth */ + int m_numLinks; + + /** The actual soft body this data represents */ + btSoftBody *m_softBody; + + + public: + btAcceleratedSoftBodyInterface( btSoftBody *softBody ) : + m_softBody( softBody ) + { + m_numVertices = 0; + m_maxVertices = 0; + m_numTriangles = 0; + m_maxTriangles = 0; + m_firstVertex = 0; + m_firstTriangle = 0; + m_firstLink = 0; + m_maxLinks = 0; + m_numLinks = 0; + } + int getNumVertices() const + { + return m_numVertices; + } + + int getNumTriangles() const + { + return m_numTriangles; + } + + int getMaxVertices() const + { + return m_maxVertices; + } + + int getMaxTriangles() const + { + return m_maxTriangles; + } + + int getFirstVertex() const + { + return m_firstVertex; + } + + int getFirstTriangle() const + { + return m_firstTriangle; + } + + + /** + * Update the bounds in the btSoftBody object + */ + void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ); + + + // TODO: All of these set functions will have to do checks and + // update the world because restructuring of the arrays will be necessary + // Reasonable use of "friend"? + void setNumVertices( int numVertices ) + { + m_numVertices = numVertices; + } + + void setNumTriangles( int numTriangles ) + { + m_numTriangles = numTriangles; + } + + void setMaxVertices( int maxVertices ) + { + m_maxVertices = maxVertices; + } + + void setMaxTriangles( int maxTriangles ) + { + m_maxTriangles = maxTriangles; + } + + void setFirstVertex( int firstVertex ) + { + m_firstVertex = firstVertex; + } + + void setFirstTriangle( int firstTriangle ) + { + m_firstTriangle = firstTriangle; + } + + void setMaxLinks( int maxLinks ) + { + m_maxLinks = maxLinks; + } + + void setNumLinks( int numLinks ) + { + m_numLinks = numLinks; + } + + void setFirstLink( int firstLink ) + { + m_firstLink = firstLink; + } + + int getMaxLinks() + { + return m_maxLinks; + } + + int getNumLinks() + { + return m_numLinks; + } + + int getFirstLink() + { + return m_firstLink; + } + + btSoftBody* getSoftBody() + { + return m_softBody; + } + + }; + + + struct CollisionObjectIndices + { + CollisionObjectIndices( int f, int e ) + { + firstObject = f; + endObject = e; + } + + int firstObject; + int endObject; + }; + + + + + + struct PrepareLinksCB + { + int numLinks; + int padding0; + int padding1; + int padding2; + }; + + struct SolvePositionsFromLinksKernelCB + { + int startLink; + int numLinks; + float kst; + float ti; + }; + + struct IntegrateCB + { + int numNodes; + float solverdt; + int padding1; + int padding2; + }; + + struct UpdatePositionsFromVelocitiesCB + { + int numNodes; + float solverSDT; + int padding1; + int padding2; + }; + + struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB + { + int numNodes; + float isolverdt; + int padding1; + int padding2; + }; + + struct UpdateVelocitiesFromPositionsWithVelocitiesCB + { + int numNodes; + float isolverdt; + int padding1; + int padding2; + }; + + struct UpdateSoftBodiesCB + { + int numNodes; + int startFace; + int numFaces; + float epsilon; + }; + + + struct ApplyForcesCB + { + unsigned int numNodes; + float solverdt; + float epsilon; + int padding3; + }; + + struct AddVelocityCB + { + int startNode; + int lastNode; + float velocityX; + float velocityY; + float velocityZ; + int padding1; + int padding2; + int padding3; + }; + + struct VSolveLinksCB + { + int startLink; + int numLinks; + float kst; + int padding; + }; + + struct ComputeBoundsCB + { + int numNodes; + int numSoftBodies; + int padding1; + int padding2; + }; + + struct SolveCollisionsAndUpdateVelocitiesCB + { + unsigned int numNodes; + float isolverdt; + int padding0; + int padding1; + }; + + + + +protected: + ID3D11Device * m_dx11Device; + ID3D11DeviceContext* m_dx11Context; + + DXFunctions dxFunctions; +public: + /** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */ + btSoftBodyLinkDataDX11 m_linkData; + btSoftBodyVertexDataDX11 m_vertexData; + btSoftBodyTriangleDataDX11 m_triangleData; + +protected: + + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + bool m_shadersInitialized; + + /** + * Cloths owned by this solver. + * Only our cloths are in this array. + */ + btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet; + + /** Acceleration value to be applied to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration; + btDX11Buffer m_dx11PerClothAcceleration; + + /** Wind velocity to be applied normal to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity; + btDX11Buffer m_dx11PerClothWindVelocity; + + /** Velocity damping factor */ + btAlignedObjectArray< float > m_perClothDampingFactor; + btDX11Buffer m_dx11PerClothDampingFactor; + + /** Velocity correction coefficient */ + btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient; + btDX11Buffer m_dx11PerClothVelocityCorrectionCoefficient; + + /** Lift parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothLiftFactor; + btDX11Buffer m_dx11PerClothLiftFactor; + + /** Drag parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothDragFactor; + btDX11Buffer m_dx11PerClothDragFactor; + + /** Density of the medium in which each cloth sits */ + btAlignedObjectArray< float > m_perClothMediumDensity; + btDX11Buffer m_dx11PerClothMediumDensity; + + + /** + * Collision shape details: pair of index of first collision shape for the cloth and number of collision objects. + */ + btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects; + btDX11Buffer m_dx11PerClothCollisionObjects; + + /** + * Collision shapes being passed across to the cloths in this solver. + */ + btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails; + btDX11Buffer< CollisionShapeDescription > m_dx11CollisionObjectDetails; + + /** + * Minimum bounds for each cloth. + * Updated by GPU and returned for use by broad phase. + * These are int vectors as a reminder that they store the int representation of a float, not a float. + * Bit 31 is inverted - is floats are stored with int-sortable values. + */ + btAlignedObjectArray< UIntVector3 > m_perClothMinBounds; + btDX11Buffer< UIntVector3 > m_dx11PerClothMinBounds; + + /** + * Maximum bounds for each cloth. + * Updated by GPU and returned for use by broad phase. + * These are int vectors as a reminder that they store the int representation of a float, not a float. + * Bit 31 is inverted - is floats are stored with int-sortable values. + */ + btAlignedObjectArray< UIntVector3 > m_perClothMaxBounds; + btDX11Buffer< UIntVector3 > m_dx11PerClothMaxBounds; + + + /** + * Friction coefficient for each cloth + */ + btAlignedObjectArray< float > m_perClothFriction; + btDX11Buffer< float > m_dx11PerClothFriction; + + DXFunctions::KernelDesc prepareLinksKernel; + DXFunctions::KernelDesc solvePositionsFromLinksKernel; + DXFunctions::KernelDesc vSolveLinksKernel; + DXFunctions::KernelDesc integrateKernel; + DXFunctions::KernelDesc addVelocityKernel; + DXFunctions::KernelDesc updatePositionsFromVelocitiesKernel; + DXFunctions::KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel; + DXFunctions::KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel; + DXFunctions::KernelDesc solveCollisionsAndUpdateVelocitiesKernel; + DXFunctions::KernelDesc resetNormalsAndAreasKernel; + DXFunctions::KernelDesc normalizeNormalsAndAreasKernel; + DXFunctions::KernelDesc computeBoundsKernel; + DXFunctions::KernelDesc updateSoftBodiesKernel; + + DXFunctions::KernelDesc applyForcesKernel; + + bool m_enableUpdateBounds; + + /** + * Integrate motion on the solver. + */ + virtual void integrate( float solverdt ); + float computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ); + + + virtual bool buildShaders(); + + void resetNormalsAndAreas( int numVertices ); + + void normalizeNormalsAndAreas( int numVertices ); + + void executeUpdateSoftBodies( int firstTriangle, int numTriangles ); + + void prepareCollisionConstraints(); + + Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ); + + void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ); + + virtual void applyForces( float solverdt ); + + virtual void updateConstants( float timeStep ); + int findSoftBodyIndex( const btSoftBody* const softBody ); + + ////////////////////////////////////// + // Kernel dispatches + virtual void prepareLinks(); + + void updatePositionsFromVelocities( float solverdt ); + void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + void solveLinksForVelocity( int startLink, int numLinks, float kst ); + + void updateVelocitiesFromPositionsWithVelocities( float isolverdt ); + void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ); + void computeBounds( ); + void solveCollisionsAndUpdateVelocities( float isolverdt ); + + // End kernel dispatches + ///////////////////////////////////// + + void updateBounds(); + + + void releaseKernels(); + +public: + btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory); + + virtual ~btDX11SoftBodySolver(); + + + virtual SolverTypes getSolverType() const + { + return DX_SOLVER; + } + + void setEnableUpdateBounds(bool enableBounds) + { + m_enableUpdateBounds = enableBounds; + } + bool getEnableUpdateBounds() const + { + return m_enableUpdateBounds; + } + + + + virtual btSoftBodyLinkData &getLinkData(); + + virtual btSoftBodyVertexData &getVertexData(); + + virtual btSoftBodyTriangleData &getTriangleData(); + + + + + + btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody ); + const btAcceleratedSoftBodyInterface * const findSoftBodyInterface( const btSoftBody* const softBody ) const; + + virtual bool checkInitialized(); + + virtual void updateSoftBodies( ); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void copyBackToSoftBodies(bool bMove = true); + + virtual void solveConstraints( float solverdt ); + + virtual void predictMotion( float solverdt ); + + + virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* ); + + virtual void processCollision( btSoftBody*, btSoftBody* ); + +}; + + + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the DX to CPU version. + */ +class btSoftBodySolverOutputDXtoCPU : public btSoftBodySolverOutput +{ +protected: + +public: + btSoftBodySolverOutputDXtoCPU() + { + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the DX to DX version and subclasses DX to CPU so that it works for that too. + */ +class btSoftBodySolverOutputDXtoDX : public btSoftBodySolverOutputDXtoCPU +{ +protected: + struct OutputToVertexArrayCB + { + int startNode; + int numNodes; + int positionOffset; + int positionStride; + + int normalOffset; + int normalStride; + int padding1; + int padding2; + }; + + DXFunctions dxFunctions; + DXFunctions::KernelDesc outputToVertexArrayWithNormalsKernel; + DXFunctions::KernelDesc outputToVertexArrayWithoutNormalsKernel; + + + bool m_shadersInitialized; + + bool checkInitialized(); + bool buildShaders(); + void releaseKernels(); + +public: + btSoftBodySolverOutputDXtoDX(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory) : + dxFunctions( dx11Device, dx11Context, dx11CompileFromMemory ) + { + m_shadersInitialized = false; + } + + ~btSoftBodySolverOutputDXtoDX() + { + releaseKernels(); + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + +#endif // #ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H + + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp new file mode 100644 index 00000000..5c73ee5d --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp @@ -0,0 +1,1051 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include + + +#define WAVEFRONT_SIZE 32 +#define WAVEFRONT_BLOCK_MULTIPLIER 2 +#define GROUP_SIZE (WAVEFRONT_SIZE*WAVEFRONT_BLOCK_MULTIPLIER) +#define LINKS_PER_SIMD_LANE 16 + +#define STRINGIFY( S ) STRINGIFY2( S ) +#define STRINGIFY2( S ) #S + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" + +#include "btSoftBodySolverLinkData_DX11SIMDAware.h" +#include "btSoftBodySolver_DX11SIMDAware.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + +#define MSTRINGIFY(A) #A +static char* UpdatePositionsFromVelocitiesHLSLString = +#include "HLSL/UpdatePositionsFromVelocities.hlsl" +static char* SolvePositionsSIMDBatchedHLSLString = +#include "HLSL/SolvePositionsSIMDBatched.hlsl" +static char* UpdateNodesHLSLString = +#include "HLSL/UpdateNodes.hlsl" +static char* UpdatePositionsHLSLString = +#include "HLSL/UpdatePositions.hlsl" +static char* UpdateConstantsHLSLString = +#include "HLSL/UpdateConstants.hlsl" +static char* IntegrateHLSLString = +#include "HLSL/Integrate.hlsl" +static char* ApplyForcesHLSLString = +#include "HLSL/ApplyForces.hlsl" +static char* UpdateNormalsHLSLString = +#include "HLSL/UpdateNormals.hlsl" +static char* OutputToVertexArrayHLSLString = +#include "HLSL/OutputToVertexArray.hlsl" +static char* VSolveLinksHLSLString = +#include "HLSL/VSolveLinks.hlsl" +static char* ComputeBoundsHLSLString = +#include "HLSL/ComputeBounds.hlsl" +static char* SolveCollisionsAndUpdateVelocitiesHLSLString = +#include "HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl" + + + +btSoftBodyLinkDataDX11SIMDAware::btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : + m_d3dDevice( d3dDevice ), + m_d3dDeviceContext( d3dDeviceContext ), + m_wavefrontSize( WAVEFRONT_SIZE ), + m_linksPerWorkItem( LINKS_PER_SIMD_LANE ), + m_maxBatchesWithinWave( 0 ), + m_maxLinksPerWavefront( m_wavefrontSize * m_linksPerWorkItem ), + m_numWavefronts( 0 ), + m_maxVertex( 0 ), + m_dx11NumBatchesAndVerticesWithinWaves( d3dDevice, d3dDeviceContext, &m_numBatchesAndVerticesWithinWaves, true ), + m_dx11WavefrontVerticesGlobalAddresses( d3dDevice, d3dDeviceContext, &m_wavefrontVerticesGlobalAddresses, true ), + m_dx11LinkVerticesLocalAddresses( d3dDevice, d3dDeviceContext, &m_linkVerticesLocalAddresses, true ), + m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, true ), + m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, true ), + m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, true ), + m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, true ), + m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, true ) +{ + m_d3dDevice = d3dDevice; + m_d3dDeviceContext = d3dDeviceContext; +} + +btSoftBodyLinkDataDX11SIMDAware::~btSoftBodyLinkDataDX11SIMDAware() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +void btSoftBodyLinkDataDX11SIMDAware::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +void btSoftBodyLinkDataDX11SIMDAware::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + if( link.getVertex0() > m_maxVertex ) + m_maxVertex = link.getVertex0(); + if( link.getVertex1() > m_maxVertex ) + m_maxVertex = link.getVertex1(); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataDX11SIMDAware::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataDX11SIMDAware::moveToAccelerator() +{ + bool success = true; + + success = success && m_dx11NumBatchesAndVerticesWithinWaves.moveToGPU(); + success = success && m_dx11WavefrontVerticesGlobalAddresses.moveToGPU(); + success = success && m_dx11LinkVerticesLocalAddresses.moveToGPU(); + success = success && m_dx11LinkStrength.moveToGPU(); + success = success && m_dx11LinksMassLSC.moveToGPU(); + success = success && m_dx11LinksRestLengthSquared.moveToGPU(); + success = success && m_dx11LinksRestLength.moveToGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyLinkDataDX11SIMDAware::moveFromAccelerator() +{ + bool success = true; + success = success && m_dx11NumBatchesAndVerticesWithinWaves.moveFromGPU(); + success = success && m_dx11WavefrontVerticesGlobalAddresses.moveFromGPU(); + success = success && m_dx11LinkVerticesLocalAddresses.moveFromGPU(); + success = success && m_dx11LinkStrength.moveFromGPU(); + success = success && m_dx11LinksMassLSC.moveFromGPU(); + success = success && m_dx11LinksRestLengthSquared.moveFromGPU(); + success = success && m_dx11LinksRestLength.moveFromGPU(); + success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) + m_onGPU = false; + + return success; +} + + + + + + + + + + + + + + + +btDX11SIMDAwareSoftBodySolver::btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) : + btDX11SoftBodySolver( dx11Device, dx11Context, dx11CompileFromMemory ), + m_linkData(m_dx11Device, m_dx11Context) +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; +} + +btDX11SIMDAwareSoftBodySolver::~btDX11SIMDAwareSoftBodySolver() +{ + releaseKernels(); +} + + +btSoftBodyLinkData &btDX11SIMDAwareSoftBodySolver::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + + + +void btDX11SIMDAwareSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate) +{ + if(forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) ); + m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) ); + m_perClothFriction.push_back( softBody->getFriction() ); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + // Round maxVertices to a multiple of the workgroup size so we know we're safe to run over in a given group + // maxVertices can be increased to allow tearing, but should be used sparingly because these extra verts will always be processed + int maxVertices = GROUP_SIZE*((numVertices+GROUP_SIZE)/GROUP_SIZE); + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( numVertices, softBodyIndex, maxVertices ); + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + } + + + + updateConstants(0.f); + + + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + + + // Build the shaders to match the batching parameters + buildShaders(); + } + +} + + + +void btDX11SIMDAwareSoftBodySolver::solveConstraints( float solverdt ) +{ + + //std::cerr << "'GPU' solve constraints\n"; + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_dx11PerClothDampingFactor.moveToGPU(); + m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU(); + + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + + + prepareCollisionConstraints(); + + + // Solve drift + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + + for( int i = 0; i < m_linkData.m_wavefrontBatchStartLengths.size(); ++i ) + { + int startWave = m_linkData.m_wavefrontBatchStartLengths[i].start; + int numWaves = m_linkData.m_wavefrontBatchStartLengths[i].length; + + solveLinksForPosition( startWave, numWaves, kst, ti ); + } + + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + + + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); + +} // btDX11SIMDAwareSoftBodySolver::solveConstraints + + +void btDX11SIMDAwareSoftBodySolver::updateConstants( float timeStep ) +{ + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } +} // btDX11SIMDAwareSoftBodySolver::updateConstants + +////////////////////////////////////// +// Kernel dispatches + + +void btDX11SIMDAwareSoftBodySolver::solveLinksForPosition( int startWave, int numWaves, float kst, float ti ) +{ + + + m_vertexData.moveToAccelerator(); + m_linkData.moveToAccelerator(); + + // Copy kernel parameters to GPU + SolvePositionsFromLinksKernelCB constBuffer; + + // Set the first wave of the batch and the number of waves + constBuffer.startWave = startWave; + constBuffer.numWaves = numWaves; + + constBuffer.kst = kst; + constBuffer.ti = ti; + + D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; + m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); + memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) ); + m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 ); + m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer ); + + // Set resources and dispatch + m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11NumBatchesAndVerticesWithinWaves.getSRV()) ); + m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11WavefrontVerticesGlobalAddresses.getSRV()) ); + m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); + m_dx11Context->CSSetShaderResources( 3, 1, &(m_linkData.m_dx11LinkVerticesLocalAddresses.getSRV()) ); + m_dx11Context->CSSetShaderResources( 4, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); + m_dx11Context->CSSetShaderResources( 5, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) ); + + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); + + // Execute the kernel + m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 ); + + int numBlocks = ((constBuffer.numWaves + WAVEFRONT_BLOCK_MULTIPLIER - 1) / WAVEFRONT_BLOCK_MULTIPLIER ); + m_dx11Context->Dispatch(numBlocks , 1, 1 ); + + { + // Tidy up + ID3D11ShaderResourceView* pViewNULL = NULL; + m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); + m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); + + ID3D11UnorderedAccessView* pUAViewNULL = NULL; + m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); + + ID3D11Buffer *pBufferNull = NULL; + m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); + } +} // btDX11SIMDAwareSoftBodySolver::solveLinksForPosition + + + +// End kernel dispatches +///////////////////////////////////// + + + + + + + + + +bool btDX11SIMDAwareSoftBodySolver::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + + if( m_shadersInitialized ) + return true; + + + updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) ); + if( !updatePositionsFromVelocitiesKernel.constBuffer ) + returnVal = false; + + char maxVerticesPerWavefront[20]; + char maxBatchesPerWavefront[20]; + char waveFrontSize[20]; + char waveFrontBlockMultiplier[20]; + char blockSize[20]; + + sprintf(maxVerticesPerWavefront, "%d", m_linkData.getMaxVerticesPerWavefront()); + sprintf(maxBatchesPerWavefront, "%d", m_linkData.getMaxBatchesPerWavefront()); + sprintf(waveFrontSize, "%d", m_linkData.getWavefrontSize()); + sprintf(waveFrontBlockMultiplier, "%d", WAVEFRONT_BLOCK_MULTIPLIER); + sprintf(blockSize, "%d", WAVEFRONT_BLOCK_MULTIPLIER*m_linkData.getWavefrontSize()); + + D3D10_SHADER_MACRO solvePositionsMacros[6] = { "MAX_NUM_VERTICES_PER_WAVE", maxVerticesPerWavefront, "MAX_BATCHES_PER_WAVE", maxBatchesPerWavefront, "WAVEFRONT_SIZE", waveFrontSize, "WAVEFRONT_BLOCK_MULTIPLIER", waveFrontBlockMultiplier, "BLOCK_SIZE", blockSize, 0, 0 }; + + solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsSIMDBatchedHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB), solvePositionsMacros ); + if( !solvePositionsFromLinksKernel.constBuffer ) + returnVal = false; + + updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); + if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ) + returnVal = false; + updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB)); + if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ) + returnVal = false; + integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) ); + if( !integrateKernel.constBuffer ) + returnVal = false; + applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) ); + if( !applyForcesKernel.constBuffer ) + returnVal = false; + solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); + if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer ) + returnVal = false; + resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !resetNormalsAndAreasKernel.constBuffer ) + returnVal = false; + normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); + if( !normalizeNormalsAndAreasKernel.constBuffer ) + returnVal = false; + updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) ); + if( !updateSoftBodiesKernel.constBuffer ) + returnVal = false; + + computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) ); + if( !computeBoundsKernel.constBuffer ) + returnVal = false; + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} // btDX11SIMDAwareSoftBodySolver::buildShaders + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + + + + + + + + + + + + +static void generateBatchesOfWavefronts( btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, btSoftBodyLinkData &linkData, int numVertices, btAlignedObjectArray < btAlignedObjectArray > &wavefrontBatches ) +{ + // A per-batch map of truth values stating whether a given vertex is in that batch + // This allows us to significantly optimize the batching + btAlignedObjectArray > mapOfVerticesInBatches; + + for( int waveIndex = 0; waveIndex < linksForWavefronts.size(); ++waveIndex ) + { + btAlignedObjectArray &wavefront( linksForWavefronts[waveIndex] ); + + int batch = 0; + bool placed = false; + while( batch < wavefrontBatches.size() && !placed ) + { + // Test the current batch, see if this wave shares any vertex with the waves in the batch + bool foundSharedVertex = false; + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + if( (mapOfVerticesInBatches[batch])[vertices.vertex0] || (mapOfVerticesInBatches[batch])[vertices.vertex1] ) + { + foundSharedVertex = true; + } + } + + if( !foundSharedVertex ) + { + wavefrontBatches[batch].push_back( waveIndex ); + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + placed = true; + } + batch++; + } + if( batch == wavefrontBatches.size() && !placed ) + { + wavefrontBatches.resize( batch + 1 ); + wavefrontBatches[batch].push_back( waveIndex ); + + // And resize map as well + mapOfVerticesInBatches.resize( batch + 1 ); + + // Resize maps with total number of vertices + mapOfVerticesInBatches[batch].resize( numVertices+1, false ); + + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + } + } + mapOfVerticesInBatches.clear(); +} + +// Function to remove an object from a vector maintaining correct ordering of the vector +template< typename T > static void removeFromVector( btAlignedObjectArray< T > &vectorToUpdate, int indexToRemove ) +{ + int currentSize = vectorToUpdate.size(); + for( int i = indexToRemove; i < (currentSize-1); ++i ) + { + vectorToUpdate[i] = vectorToUpdate[i+1]; + } + if( currentSize > 0 ) + vectorToUpdate.resize( currentSize - 1 ); +} + +/** + * Insert element into vectorToUpdate at index index. + */ +template< typename T > static void insertAtIndex( btAlignedObjectArray< T > &vectorToUpdate, int index, T element ) +{ + vectorToUpdate.resize( vectorToUpdate.size() + 1 ); + for( int i = (vectorToUpdate.size() - 1); i > index; --i ) + { + vectorToUpdate[i] = vectorToUpdate[i-1]; + } + vectorToUpdate[index] = element; +} + +/** + * Insert into btAlignedObjectArray assuming the array is ordered and maintaining both ordering and uniqueness. + * ie it treats vectorToUpdate as an ordered set. + */ +template< typename T > static void insertUniqueAndOrderedIntoVector( btAlignedObjectArray &vectorToUpdate, T element ) +{ + int index = 0; + while( index < vectorToUpdate.size() && vectorToUpdate[index] < element ) + { + index++; + } + if( index == vectorToUpdate.size() || vectorToUpdate[index] != element ) + insertAtIndex( vectorToUpdate, index, element ); +} + +static void generateLinksPerVertex( int numVertices, btSoftBodyLinkData &linkData, btAlignedObjectArray< int > &listOfLinksPerVertex, btAlignedObjectArray &numLinksPerVertex, int &maxLinks ) +{ + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numLinksPerVertex[nodes.vertex0]++; + numLinksPerVertex[nodes.vertex1]++; + } + int maxLinksPerVertex = 0; + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + maxLinksPerVertex = btMax(numLinksPerVertex[vertexIndex], maxLinksPerVertex); + } + maxLinks = maxLinksPerVertex; + + btAlignedObjectArray< int > linksFoundPerVertex; + linksFoundPerVertex.resize( numVertices, 0 ); + + listOfLinksPerVertex.resize( maxLinksPerVertex * numVertices ); + + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + { + // Do vertex 0 + int vertexIndex = nodes.vertex0; + int linkForVertex = linksFoundPerVertex[nodes.vertex0]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex0] = linkForVertex + 1; + } + { + // Do vertex 1 + int vertexIndex = nodes.vertex1; + int linkForVertex = linksFoundPerVertex[nodes.vertex1]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex1] = linkForVertex + 1; + } + } +} + +static void computeBatchingIntoWavefronts( + btSoftBodyLinkData &linkData, + int wavefrontSize, + int linksPerWorkItem, + int maxLinksPerWavefront, + btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > &batchesWithinWaves, /* wave, batch, links in batch */ + btAlignedObjectArray< btAlignedObjectArray< int > > &verticesForWavefronts /* wavefront, vertex */ + ) +{ + + + // Attempt generation of larger batches of links. + btAlignedObjectArray< bool > processedLink; + processedLink.resize( linkData.getNumLinks() ); + btAlignedObjectArray< int > listOfLinksPerVertex; + int maxLinksPerVertex = 0; + + // Count num vertices + int numVertices = 0; + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numVertices = btMax( numVertices, nodes.vertex0 + 1 ); + numVertices = btMax( numVertices, nodes.vertex1 + 1 ); + } + + // Need list of links per vertex + // Compute valence of each vertex + btAlignedObjectArray numLinksPerVertex; + numLinksPerVertex.resize(0); + numLinksPerVertex.resize( numVertices, 0 ); + + generateLinksPerVertex( numVertices, linkData, listOfLinksPerVertex, numLinksPerVertex, maxLinksPerVertex ); + + + // At this point we know what links we have for each vertex so we can start batching + + // We want a vertex to start with, let's go with 0 + int currentVertex = 0; + int linksProcessed = 0; + + btAlignedObjectArray verticesToProcess; + + while( linksProcessed < linkData.getNumLinks() ) + { + // Next wavefront + int nextWavefront = linksForWavefronts.size(); + linksForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &linksForWavefront(linksForWavefronts[nextWavefront]); + verticesForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &vertexSet( verticesForWavefronts[nextWavefront] ); + + linksForWavefront.resize(0); + + // Loop to find enough links to fill the wavefront + // Stopping if we either run out of links, or fill it + while( linksProcessed < linkData.getNumLinks() && linksForWavefront.size() < maxLinksPerWavefront ) + { + // Go through the links for the current vertex + for( int link = 0; link < numLinksPerVertex[currentVertex] && linksForWavefront.size() < maxLinksPerWavefront; ++link ) + { + int linkAddress = currentVertex * maxLinksPerVertex + link; + int linkIndex = listOfLinksPerVertex[linkAddress]; + + // If we have not already processed this link, add it to the wavefront + // Claim it as another processed link + // Add the vertex at the far end to the list of vertices to process. + if( !processedLink[linkIndex] ) + { + linksForWavefront.push_back( linkIndex ); + linksProcessed++; + processedLink[linkIndex] = true; + int v0 = linkData.getVertexPair(linkIndex).vertex0; + int v1 = linkData.getVertexPair(linkIndex).vertex1; + if( v0 == currentVertex ) + verticesToProcess.push_back( v1 ); + else + verticesToProcess.push_back( v0 ); + } + } + if( verticesToProcess.size() > 0 ) + { + // Get the element on the front of the queue and remove it + currentVertex = verticesToProcess[0]; + removeFromVector( verticesToProcess, 0 ); + } else { + // If we've not yet processed all the links, find the first unprocessed one + // and select one of its vertices as the current vertex + if( linksProcessed < linkData.getNumLinks() ) + { + int searchLink = 0; + while( processedLink[searchLink] ) + searchLink++; + currentVertex = linkData.getVertexPair(searchLink).vertex0; + } + } + } + + // We have either finished or filled a wavefront + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int v0 = linkData.getVertexPair( linksForWavefront[link] ).vertex0; + int v1 = linkData.getVertexPair( linksForWavefront[link] ).vertex1; + insertUniqueAndOrderedIntoVector( vertexSet, v0 ); + insertUniqueAndOrderedIntoVector( vertexSet, v1 ); + } + // Iterate over links mapped to the wave and batch those + // We can run a batch on each cycle trivially + + batchesWithinWaves.resize( batchesWithinWaves.size() + 1 ); + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWave( batchesWithinWaves[batchesWithinWaves.size()-1] ); + + + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int linkIndex = linksForWavefront[link]; + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( linkIndex ); + + int batch = 0; + bool placed = false; + while( batch < batchesWithinWave.size() && !placed ) + { + bool foundSharedVertex = false; + if( batchesWithinWave[batch].size() >= wavefrontSize ) + { + // If we have already filled this batch, move on to another + foundSharedVertex = true; + } else { + for( int link2 = 0; link2 < batchesWithinWave[batch].size(); ++link2 ) + { + btSoftBodyLinkData::LinkNodePair vertices2 = linkData.getVertexPair( (batchesWithinWave[batch])[link2] ); + + if( vertices.vertex0 == vertices2.vertex0 || + vertices.vertex1 == vertices2.vertex0 || + vertices.vertex0 == vertices2.vertex1 || + vertices.vertex1 == vertices2.vertex1 ) + { + foundSharedVertex = true; + break; + } + } + } + if( !foundSharedVertex ) + { + batchesWithinWave[batch].push_back( linkIndex ); + placed = true; + } else { + ++batch; + } + } + if( batch == batchesWithinWave.size() && !placed ) + { + batchesWithinWave.resize( batch + 1 ); + batchesWithinWave[batch].push_back( linkIndex ); + } + } + + } + +} + +void btSoftBodyLinkDataDX11SIMDAware::generateBatches() +{ + btAlignedObjectArray < btAlignedObjectArray > linksForWavefronts; + btAlignedObjectArray < btAlignedObjectArray > wavefrontBatches; + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > batchesWithinWaves; + btAlignedObjectArray< btAlignedObjectArray< int > > verticesForWavefronts; // wavefronts, vertices in wavefront as an ordered set + + // Group the links into wavefronts + computeBatchingIntoWavefronts( *this, m_wavefrontSize, m_linksPerWorkItem, m_maxLinksPerWavefront, linksForWavefronts, batchesWithinWaves, verticesForWavefronts ); + + + // Batch the wavefronts + generateBatchesOfWavefronts( linksForWavefronts, *this, m_maxVertex, wavefrontBatches ); + + m_numWavefronts = linksForWavefronts.size(); + + // At this point we have a description of which links we need to process in each wavefront + + // First correctly fill the batch ranges vector + int numBatches = wavefrontBatches.size(); + m_wavefrontBatchStartLengths.resize(0); + int prefixSum = 0; + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + int wavesInBatch = wavefrontBatches[batchIndex].size(); + int nextPrefixSum = prefixSum + wavesInBatch; + m_wavefrontBatchStartLengths.push_back( BatchPair( prefixSum, nextPrefixSum - prefixSum ) ); + + prefixSum += wavesInBatch; + } + + // Also find max number of batches within a wave + m_maxBatchesWithinWave = 0; + m_maxVerticesWithinWave = 0; + m_numBatchesAndVerticesWithinWaves.resize( m_numWavefronts ); + for( int waveIndex = 0; waveIndex < m_numWavefronts; ++waveIndex ) + { + // See if the number of batches in this wave is greater than the current maxium + int batchesInCurrentWave = batchesWithinWaves[waveIndex].size(); + int verticesInCurrentWave = verticesForWavefronts[waveIndex].size(); + m_maxBatchesWithinWave = btMax( batchesInCurrentWave, m_maxBatchesWithinWave ); + m_maxVerticesWithinWave = btMax( verticesInCurrentWave, m_maxVerticesWithinWave ); + } + + // Add padding values both for alignment and as dudd addresses within LDS to compute junk rather than branch around + m_maxVerticesWithinWave = 16*((m_maxVerticesWithinWave/16)+2); + + // Now we know the maximum number of vertices per-wave we can resize the global vertices array + m_wavefrontVerticesGlobalAddresses.resize( m_maxVerticesWithinWave * m_numWavefronts ); + + // Grab backup copies of all the link data arrays for the sorting process + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + //btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + //btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + // Resize to a wavefront sized batch per batch per wave so we get perfectly coherent memory accesses. + m_links.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkVerticesLocalAddresses.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkStrength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMassLSC.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLengthSquared.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMaterialLinearStiffnessCoefficient.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + + // Then re-order links into wavefront blocks + + // Total number of wavefronts moved. This will decide the ordering of sorted wavefronts. + int wavefrontCount = 0; + + // Iterate over batches of wavefronts, then wavefronts in the batch + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + btAlignedObjectArray &batch( wavefrontBatches[batchIndex] ); + int wavefrontsInBatch = batch.size(); + + + for( int wavefrontIndex = 0; wavefrontIndex < wavefrontsInBatch; ++wavefrontIndex ) + { + + int originalWavefrontIndex = batch[wavefrontIndex]; + btAlignedObjectArray< int > &wavefrontVertices( verticesForWavefronts[originalWavefrontIndex] ); + int verticesUsedByWavefront = wavefrontVertices.size(); + + // Copy the set of vertices into the correctly structured array for use on the device + // Fill the non-vertices with -1s + // so we can mask out those reads + for( int vertex = 0; vertex < verticesUsedByWavefront; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = wavefrontVertices[vertex]; + } + for( int vertex = verticesUsedByWavefront; vertex < m_maxVerticesWithinWave; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = -1; + } + + // Obtain the set of batches within the current wavefront + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWavefront( batchesWithinWaves[originalWavefrontIndex] ); + // Set the size of the batches for use in the solver, correctly ordered + NumBatchesVerticesPair batchesAndVertices; + batchesAndVertices.numBatches = batchesWithinWavefront.size(); + batchesAndVertices.numVertices = verticesUsedByWavefront; + m_numBatchesAndVerticesWithinWaves[wavefrontCount] = batchesAndVertices; + + + // Now iterate over batches within the wavefront to structure the links correctly + for( int wavefrontBatch = 0; wavefrontBatch < batchesWithinWavefront.size(); ++wavefrontBatch ) + { + btAlignedObjectArray &linksInBatch( batchesWithinWavefront[wavefrontBatch] ); + int wavefrontBatchSize = linksInBatch.size(); + + int batchAddressInTarget = m_maxBatchesWithinWave * m_wavefrontSize * wavefrontCount + m_wavefrontSize * wavefrontBatch; + + for( int linkIndex = 0; linkIndex < wavefrontBatchSize; ++linkIndex ) + { + int originalLinkAddress = linksInBatch[linkIndex]; + // Reorder simple arrays trivially + m_links[batchAddressInTarget + linkIndex] = m_links_Backup[originalLinkAddress]; + m_linkStrength[batchAddressInTarget + linkIndex] = m_linkStrength_Backup[originalLinkAddress]; + m_linksMassLSC[batchAddressInTarget + linkIndex] = m_linksMassLSC_Backup[originalLinkAddress]; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = m_linksRestLengthSquared_Backup[originalLinkAddress]; + m_linksRestLength[batchAddressInTarget + linkIndex] = m_linksRestLength_Backup[originalLinkAddress]; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = m_linksMaterialLinearStiffnessCoefficient_Backup[originalLinkAddress]; + + // The local address is more complicated. We need to work out where a given vertex will end up + // by searching the set of vertices for this link and using the index as the local address + btSoftBodyLinkData::LinkNodePair localPair; + btSoftBodyLinkData::LinkNodePair globalPair = m_links[batchAddressInTarget + linkIndex]; + localPair.vertex0 = wavefrontVertices.findLinearSearch( globalPair.vertex0 ); + localPair.vertex1 = wavefrontVertices.findLinearSearch( globalPair.vertex1 ); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + for( int linkIndex = wavefrontBatchSize; linkIndex < m_wavefrontSize; ++linkIndex ) + { + // Put 0s into these arrays for padding for cleanliness + m_links[batchAddressInTarget + linkIndex] = btSoftBodyLinkData::LinkNodePair(0, 0); + m_linkStrength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMassLSC[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = 0.f; + + + // For local addresses of junk data choose a set of addresses just above the range of valid ones + // and cycling tyhrough % 16 so that we don't have bank conficts between all dud addresses + // The valid addresses will do scatter and gather in the valid range, the junk ones should happily work + // off the end of that range so we need no control + btSoftBodyLinkData::LinkNodePair localPair; + localPair.vertex0 = verticesUsedByWavefront + (linkIndex % 16); + localPair.vertex1 = verticesUsedByWavefront + (linkIndex % 16); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + + } + + + wavefrontCount++; + } + + + } + +} // void btSoftBodyLinkDataDX11SIMDAware::generateBatches() diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h new file mode 100644 index 00000000..34881973 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "vectormath/vmInclude.h" +#include "btSoftBodySolver_DX11.h" +#include "btSoftBodySolverVertexBuffer_DX11.h" +#include "btSoftBodySolverLinkData_DX11SIMDAware.h" +#include "btSoftBodySolverVertexData_DX11.h" +#include "btSoftBodySolverTriangleData_DX11.h" + + +#ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H +#define BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H + +class btDX11SIMDAwareSoftBodySolver : public btDX11SoftBodySolver +{ +protected: + struct SolvePositionsFromLinksKernelCB + { + int startWave; + int numWaves; + float kst; + float ti; + }; + + + /** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */ + btSoftBodyLinkDataDX11SIMDAware m_linkData; + + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + + virtual bool buildShaders(); + + void updateConstants( float timeStep ); + + + ////////////////////////////////////// + // Kernel dispatches + + + void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + + // End kernel dispatches + ///////////////////////////////////// + + + +public: + btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory); + + virtual ~btDX11SIMDAwareSoftBodySolver(); + + virtual btSoftBodyLinkData &getLinkData(); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void solveConstraints( float solverdt ); + + virtual SolverTypes getSolverType() const + { + return DX_SIMD_SOLVER; + } + +}; + +#endif // #ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua new file mode 100644 index 00000000..4625306d --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua @@ -0,0 +1,23 @@ + +hasDX11 = findDirectX11() + +if (hasDX11) then + + project "BulletSoftBodyDX11Solvers" + + initDirectX11() + + kind "StaticLib" + + targetdir "../../../../lib" + + includedirs { + ".", + "../../.." + } + files { + "**.cpp", + "**.h" + } + +end diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt new file mode 100644 index 00000000..1fc07328 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt @@ -0,0 +1,65 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${AMD_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_AMD_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_AMD) + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp + ../btSoftBodySolverOutputCLtoGL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../btSoftBodySolver_OpenCLSIMDAware.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCLSIMDAware.h + ../btSoftBodySolverBuffer_OpenCL.h + ../btSoftBodySolverVertexBuffer_OpenGL.h + ../btSoftBodySolverOutputCLtoGL.h +) + + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_AMD + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_AMD BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua new file mode 100644 index 00000000..8c663a8c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua @@ -0,0 +1,27 @@ + +hasCL = findOpenCL_AMD() + +if (hasCL) then + + project "BulletSoftBodySolvers_OpenCL_AMD" + + defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"} + + initOpenCL_AMD() + + kind "StaticLib" + + targetdir "../../../../../lib" + + includedirs { + ".", + "../../../..", + "../../../../../Glut" + } + files { + "../btSoftBodySolver_OpenCL.cpp", + "../btSoftBodySolver_OpenCLSIMDAware.cpp", + "../btSoftBodySolverOutputCLtoGL.cpp" + } + +end diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt new file mode 100644 index 00000000..6e593a99 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt @@ -0,0 +1,80 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverBuffer_OpenCL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Apple + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + IF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) ) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES LINK_FLAGS "-framework OpenCL") + ENDIF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) ) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Apple BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt new file mode 100644 index 00000000..cf9a0be2 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt @@ -0,0 +1,17 @@ + SUBDIRS( MiniCL ) + +IF(BUILD_INTEL_OPENCL_DEMOS) + SUBDIRS(Intel) +ENDIF() + +IF(BUILD_AMD_OPENCL_DEMOS) + SUBDIRS(AMD) +ENDIF() + +IF(BUILD_NVIDIA_OPENCL_DEMOS) + SUBDIRS(NVidia) +ENDIF() + +IF(APPLE AND OPENCL_LIBRARY) + SUBDIRS(Apple) +ENDIF() diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt new file mode 100644 index 00000000..ecca1813 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt @@ -0,0 +1,85 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${INTEL_OPENCL_INCLUDES} +) + +ADD_DEFINITIONS(-DUSE_INTEL_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_INTEL) + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp + ../btSoftBodySolverOutputCLtoGL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../btSoftBodySolver_OpenCLSIMDAware.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCLSIMDAware.h + ../btSoftBodySolverBuffer_OpenCL.h + ../btSoftBodySolverVertexBuffer_OpenGL.h + ../btSoftBodySolverOutputCLtoGL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Intel + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Intel BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua new file mode 100644 index 00000000..668886d1 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua @@ -0,0 +1,27 @@ + +hasCL = findOpenCL_Intel() + +if (hasCL) then + + project "BulletSoftBodySolvers_OpenCL_Intel" + + defines { "USE_INTEL_OPENCL","CL_PLATFORM_INTEL"} + + initOpenCL_Intel() + + kind "StaticLib" + + targetdir "../../../../../lib" + + includedirs { + ".", + "../../../..", + "../../../../../Glut" + } + files { + "../btSoftBodySolver_OpenCL.cpp", + "../btSoftBodySolver_OpenCLSIMDAware.cpp", + "../btSoftBodySolverOutputCLtoGL.cpp" + } + +end diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt new file mode 100644 index 00000000..97deb7e4 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt @@ -0,0 +1,78 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src +) + +ADD_DEFINITIONS(-DUSE_MINICL) + + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverBuffer_OpenCL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Mini + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Mini MiniCL BulletMultiThreaded BulletSoftBody) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp new file mode 100644 index 00000000..dfa60e66 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp @@ -0,0 +1,249 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 + +#define MSTRINGIFY(A) A +#include "../OpenCLC10/ApplyForces.cl" +#include "../OpenCLC10/Integrate.cl" +#include "../OpenCLC10/PrepareLinks.cl" +#include "../OpenCLC10/SolvePositions.cl" +#include "../OpenCLC10/UpdateNodes.cl" +#include "../OpenCLC10/UpdateNormals.cl" +#include "../OpenCLC10/UpdatePositions.cl" +#include "../OpenCLC10/UpdatePositionsFromVelocities.cl" +#include "../OpenCLC10/VSolveLinks.cl" +#include "../OpenCLC10/UpdateFixedVertexPositions.cl" +//#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl" + + +MINICL_REGISTER(PrepareLinksKernel) +MINICL_REGISTER(VSolveLinksKernel) +MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel) +MINICL_REGISTER(SolvePositionsFromLinksKernel) +MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel) +MINICL_REGISTER(updateVelocitiesFromPositionsWithoutVelocitiesKernel) +MINICL_REGISTER(IntegrateKernel) +MINICL_REGISTER(ApplyForcesKernel) +MINICL_REGISTER(ResetNormalsAndAreasKernel) +MINICL_REGISTER(NormalizeNormalsAndAreasKernel) +MINICL_REGISTER(UpdateSoftBodiesKernel) +MINICL_REGISTER(UpdateFixedVertexPositions) + +float mydot3a(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + + +typedef struct +{ + int firstObject; + int endObject; +} CollisionObjectIndices; + +typedef struct +{ + float4 shapeTransform[4]; // column major 4x4 matrix + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + int padding0; + +} CollisionShapeDescription; + +// From btBroadphaseProxy.h +__constant int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Multiply column-major matrix against vector +float4 matrixVectorMul( float4 matrix[4], float4 vector ) +{ + float4 returnVector; + float4 row0 = float4(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); + float4 row1 = float4(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); + float4 row2 = float4(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); + float4 row3 = float4(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); + returnVector.x = dot(row0, vector); + returnVector.y = dot(row1, vector); + returnVector.z = dot(row2, vector); + returnVector.w = dot(row3, vector); + return returnVector; +} + +__kernel void +SolveCollisionsAndUpdateVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global int *g_vertexClothIdentifier, + __global float4 *g_vertexPreviousPositions, + __global float * g_perClothFriction, + __global float * g_clothDampingFactor, + __global CollisionObjectIndices * g_perClothCollisionObjectIndices, + __global CollisionShapeDescription * g_collisionObjectDetails, + __global float4 * g_vertexForces, + __global float4 *g_vertexVelocities, + __global float4 *g_vertexPositions GUID_ARG) +{ + int nodeID = get_global_id(0); + float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); + + if( get_global_id(0) < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + + // Abort if this is not a valid cloth + if( clothIdentifier < 0 ) + return; + + + float4 position (g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition (g_vertexPreviousPositions[nodeID].xyz, 1.f); + + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + float4 difference = position - previousPosition; + float4 velocity = difference*velocityCoefficient*isolverdt; + + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) + { + CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = shapeDescription.halfHeight; + float capsuleRadius = shapeDescription.radius; + float capsuleMargin = shapeDescription.margin; + int capsuleupAxis = shapeDescription.upAxis; + + // Four columns of worldTransform matrix + float4 worldTransform[4]; + worldTransform[0] = shapeDescription.shapeTransform[0]; + worldTransform[1] = shapeDescription.shapeTransform[1]; + worldTransform[2] = shapeDescription.shapeTransform[2]; + worldTransform[3] = shapeDescription.shapeTransform[3]; + + // Correctly define capsule centerline vector + float4 c1 (0.f, 0.f, 0.f, 1.f); + float4 c2 (0.f, 0.f, 0.f, 1.f); + c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); + c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); + c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); + c2.x = -c1.x; + c2.y = -c1.y; + c2.z = -c1.z; + + + float4 worldC1 = matrixVectorMul(worldTransform, c1); + float4 worldC2 = matrixVectorMul(worldTransform, c2); + float4 segment = (worldC2 - worldC1); + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) ); + + float4 closestPoint = (worldC1 + (segment * distanceAlongSegment)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float4 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = float4(normalize(position - worldC1).xyz, 0.f); + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = float4(normalize(position - worldC2).xyz, 0.f); + } else { + dist = distanceFromLine; + normalVector = float4(normalize(position - closestPoint).xyz, 0.f); + } + + float4 colliderLinearVelocity = shapeDescription.linearVelocity; + float4 colliderAngularVelocity = shapeDescription.angularVelocity; + float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - float4(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + float4(normalVector*(minDistance - dist)*0.9f); + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + float4 relativeVelocity = velocity - velocityOfSurfacePoint; + + float4 p1 = normalize(cross(normalVector, segment)); + float4 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0f ) + forceOnVertex -= frictionVector; + } + } + } + } + + g_vertexVelocities[nodeID] = float4(velocity.xyz, 0.f); + + // Update external force + g_vertexForces[nodeID] = float4(forceOnVertex.xyz, 0.f); + + g_vertexPositions[nodeID] = float4(position.xyz, 0.f); + } +} + + +MINICL_REGISTER(SolveCollisionsAndUpdateVelocitiesKernel); + + + + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt new file mode 100644 index 00000000..884a0ffe --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt @@ -0,0 +1,84 @@ + +ADD_DEFINITIONS(-DUSE_NVIDIA_OPENCL) +ADD_DEFINITIONS(-DCL_PLATFORM_NVIDIA) + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${NVIDIA_OPENCL_INCLUDES} +) + + + +SET(BulletSoftBodyOpenCLSolvers_SRCS + ../btSoftBodySolver_OpenCL.cpp + ../btSoftBodySolver_OpenCLSIMDAware.cpp + ../btSoftBodySolverOutputCLtoGL.cpp +) + +SET(BulletSoftBodyOpenCLSolvers_HDRS + ../btSoftBodySolver_OpenCL.h + ../../Shared/btSoftBodySolverData.h + ../btSoftBodySolverVertexData_OpenCL.h + ../btSoftBodySolverTriangleData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCL.h + ../btSoftBodySolverLinkData_OpenCLSIMDAware.h + ../btSoftBodySolverBuffer_OpenCL.h + ../btSoftBodySolverVertexBuffer_OpenGL.h + ../btSoftBodySolverOutputCLtoGL.h +) + +# OpenCL and HLSL Shaders. +# Build rules generated to stringify these into headers +# which are needed by some of the sources +SET(BulletSoftBodyOpenCLSolvers_Shaders +# OutputToVertexArray + UpdateNormals + Integrate + UpdatePositions + UpdateNodes + SolvePositions + UpdatePositionsFromVelocities + ApplyForces + PrepareLinks + VSolveLinks +) + +foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) + LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") +endforeach(f) + + + +ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_NVidia + ${BulletSoftBodyOpenCLSolvers_SRCS} + ${BulletSoftBodyOpenCLSolvers_HDRS} + ${BulletSoftBodyOpenCLSolvers_OpenCLC} +) + +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_NVidia BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) +#headers are already installed by BulletMultiThreaded library + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua new file mode 100644 index 00000000..0bab1e30 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua @@ -0,0 +1,27 @@ + +hasCL = findOpenCL_NVIDIA() + +if (hasCL) then + + project "BulletSoftBodySolvers_OpenCL_NVIDIA" + + defines { "USE_NVIDIA_OPENCL","CL_PLATFORM_NVIDIA"} + + initOpenCL_NVIDIA() + + kind "StaticLib" + + targetdir "../../../../../lib" + + includedirs { + ".", + "../../../..", + "../../../../../Glut" + } + files { + "../btSoftBodySolver_OpenCL.cpp", + "../btSoftBodySolver_OpenCLSIMDAware.cpp", + "../btSoftBodySolverOutputCLtoGL.cpp" + } + +end diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl new file mode 100644 index 00000000..f9bcb88e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl @@ -0,0 +1,102 @@ +MSTRINGIFY( + + +float adot3(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +float alength3(float4 a) +{ + a.w = 0; + return length(a); +} + +float4 anormalize3(float4 a) +{ + a.w = 0; + return normalize(a); +} + +float4 projectOnAxis( float4 v, float4 a ) +{ + return (a*adot3(v, a)); +} + +__kernel void +ApplyForcesKernel( + const uint numNodes, + const float solverdt, + const float epsilon, + __global int * g_vertexClothIdentifier, + __global float4 * g_vertexNormal, + __global float * g_vertexArea, + __global float * g_vertexInverseMass, + __global float * g_clothLiftFactor, + __global float * g_clothDragFactor, + __global float4 * g_clothWindVelocity, + __global float4 * g_clothAcceleration, + __global float * g_clothMediumDensity, + __global float4 * g_vertexForceAccumulator, + __global float4 * g_vertexVelocity GUID_ARG) +{ + unsigned int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + int clothId = g_vertexClothIdentifier[nodeID]; + float nodeIM = g_vertexInverseMass[nodeID]; + + if( nodeIM > 0.0f ) + { + float4 nodeV = g_vertexVelocity[nodeID]; + float4 normal = g_vertexNormal[nodeID]; + float area = g_vertexArea[nodeID]; + float4 nodeF = g_vertexForceAccumulator[nodeID]; + + // Read per-cloth values + float4 clothAcceleration = g_clothAcceleration[clothId]; + float4 clothWindVelocity = g_clothWindVelocity[clothId]; + float liftFactor = g_clothLiftFactor[clothId]; + float dragFactor = g_clothDragFactor[clothId]; + float mediumDensity = g_clothMediumDensity[clothId]; + + // Apply the acceleration to the cloth rather than do this via a force + nodeV += (clothAcceleration*solverdt); + + g_vertexVelocity[nodeID] = nodeV; + + // Aerodynamics + float4 rel_v = nodeV - clothWindVelocity; + float rel_v_len = alength3(rel_v); + float rel_v2 = dot(rel_v, rel_v); + + if( rel_v2 > epsilon ) + { + float4 rel_v_nrm = anormalize3(rel_v); + float4 nrm = normal; + + nrm = nrm * (dot(nrm, rel_v) < 0 ? -1.f : 1.f); + + float4 fDrag = (float4)(0.f, 0.f, 0.f, 0.f); + float4 fLift = (float4)(0.f, 0.f, 0.f, 0.f); + + float n_dot_v = dot(nrm, rel_v_nrm); + + // drag force + if ( dragFactor > 0.f ) + fDrag = 0.5f * dragFactor * mediumDensity * rel_v2 * area * n_dot_v * (-1.0f) * rel_v_nrm; + + // lift force + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * liftFactor * mediumDensity * rel_v_len * area * sqrt(1.0f-n_dot_v*n_dot_v) * (cross(cross(nrm, rel_v_nrm), rel_v_nrm)); + + nodeF += fDrag + fLift; + g_vertexForceAccumulator[nodeID] = nodeF; + } + } + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl new file mode 100644 index 00000000..2ae7148a --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl @@ -0,0 +1,82 @@ +MSTRINGIFY( +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n + +__kernel void +ComputeBoundsKernel( + const int numNodes, + const int numSoftBodies, + __global int * g_vertexClothIdentifier, + __global float4 * g_vertexPositions, + /* Unfortunately, to get the atomics below to work these arrays cannot be */ + /* uint4, though that is the layout of the data */ + /* Therefore this is little-endian-only code */ + volatile __global uint * g_clothMinBounds, + volatile __global uint * g_clothMaxBounds, + volatile __local uint * clothMinBounds, + volatile __local uint * clothMaxBounds) +{ + // Init min and max bounds arrays + if( get_local_id(0) < numSoftBodies ) + { + + clothMinBounds[get_local_id(0)*4] = UINT_MAX; + clothMinBounds[get_local_id(0)*4+1] = UINT_MAX; + clothMinBounds[get_local_id(0)*4+2] = UINT_MAX; + clothMinBounds[get_local_id(0)*4+3] = UINT_MAX; + clothMaxBounds[get_local_id(0)*4] = 0; + clothMaxBounds[get_local_id(0)*4+1] = 0; + clothMaxBounds[get_local_id(0)*4+2] = 0; + clothMaxBounds[get_local_id(0)*4+3] = 0; + + } + + barrier(CLK_LOCAL_MEM_FENCE); + + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + if( clothIdentifier >= 0 ) + { + + float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f); + + /* Reinterpret position as uint */ + uint4 positionUInt = (uint4)(as_uint(position.x), as_uint(position.y), as_uint(position.z), 0); + + /* Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints */ + positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000); + positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000); + positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000); + + // Min/max with the LDS values + atom_min(&(clothMinBounds[clothIdentifier*4]), positionUInt.x); + atom_min(&(clothMinBounds[clothIdentifier*4+1]), positionUInt.y); + atom_min(&(clothMinBounds[clothIdentifier*4+2]), positionUInt.z); + + atom_max(&(clothMaxBounds[clothIdentifier*4]), positionUInt.x); + atom_max(&(clothMaxBounds[clothIdentifier*4+1]), positionUInt.y); + atom_max(&(clothMaxBounds[clothIdentifier*4+2]), positionUInt.z); + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + + /* Use global atomics to update the global versions of the data */ + if( get_local_id(0) < numSoftBodies ) + { + /*atom_min(&(g_clothMinBounds[get_local_id(0)].x), clothMinBounds[get_local_id(0)].x);*/ + atom_min(&(g_clothMinBounds[get_local_id(0)*4]), clothMinBounds[get_local_id(0)*4]); + atom_min(&(g_clothMinBounds[get_local_id(0)*4+1]), clothMinBounds[get_local_id(0)*4+1]); + atom_min(&(g_clothMinBounds[get_local_id(0)*4+2]), clothMinBounds[get_local_id(0)*4+2]); + + atom_max(&(g_clothMaxBounds[get_local_id(0)*4]), clothMaxBounds[get_local_id(0)*4]); + atom_max(&(g_clothMaxBounds[get_local_id(0)*4+1]), clothMaxBounds[get_local_id(0)*4+1]); + atom_max(&(g_clothMaxBounds[get_local_id(0)*4+2]), clothMaxBounds[get_local_id(0)*4+2]); + } +} + + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl new file mode 100644 index 00000000..bb2d98a5 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl @@ -0,0 +1,35 @@ +MSTRINGIFY( + +// Node indices for each link + + + +__kernel void +IntegrateKernel( + const int numNodes, + const float solverdt, + __global float * g_vertexInverseMasses, + __global float4 * g_vertexPositions, + __global float4 * g_vertexVelocity, + __global float4 * g_vertexPreviousPositions, + __global float4 * g_vertexForceAccumulator GUID_ARG) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID]; + float4 velocity = g_vertexVelocity[nodeID]; + float4 force = g_vertexForceAccumulator[nodeID]; + float inverseMass = g_vertexInverseMasses[nodeID]; + + g_vertexPreviousPositions[nodeID] = position; + velocity += force * inverseMass * solverdt; + position += velocity * solverdt; + + g_vertexForceAccumulator[nodeID] = (float4)(0.f, 0.f, 0.f, 0.0f); + g_vertexPositions[nodeID] = position; + g_vertexVelocity[nodeID] = velocity; + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl new file mode 100644 index 00000000..98913777 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl @@ -0,0 +1,46 @@ +MSTRINGIFY( + +__kernel void +OutputToVertexArrayWithNormalsKernel( + const int startNode, const int numNodes, __global float *g_vertexBuffer, + const int positionOffset, const int positionStride, const __global float4* g_vertexPositions, + const int normalOffset, const int normalStride, const __global float4* g_vertexNormals ) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + float4 normal = g_vertexNormals[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + + int normalDestination = nodeID * normalStride + normalOffset; + g_vertexBuffer[normalDestination] = normal.x; + g_vertexBuffer[normalDestination+1] = normal.y; + g_vertexBuffer[normalDestination+2] = normal.z; + } +} + +__kernel void +OutputToVertexArrayWithoutNormalsKernel( + const int startNode, const int numNodes, __global float *g_vertexBuffer, + const int positionOffset, const int positionStride, const __global float4* g_vertexPositions ) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID + startNode]; + + // Stride should account for the float->float4 conversion + int positionDestination = nodeID * positionStride + positionOffset; + g_vertexBuffer[positionDestination] = position.x; + g_vertexBuffer[positionDestination+1] = position.y; + g_vertexBuffer[positionDestination+2] = position.z; + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl new file mode 100644 index 00000000..542a11ec --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl @@ -0,0 +1,38 @@ +MSTRINGIFY( + + + +__kernel void +PrepareLinksKernel( + const int numLinks, + __global int2 * g_linksVertexIndices, + __global float * g_linksMassLSC, + __global float4 * g_nodesPreviousPosition, + __global float * g_linksLengthRatio, + __global float4 * g_linksCurrentLength GUID_ARG) +{ + int linkID = get_global_id(0); + if( linkID < numLinks ) + { + + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0]; + float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1]; + + float massLSC = g_linksMassLSC[linkID]; + + float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0; + linkCurrentLength.w = 0.f; + + float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC; + linkLengthRatio = 1.0f/linkLengthRatio; + + g_linksCurrentLength[linkID] = linkCurrentLength; + g_linksLengthRatio[linkID] = linkLengthRatio; + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl new file mode 100644 index 00000000..92fb939d --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl @@ -0,0 +1,204 @@ +MSTRINGIFY( + + + +float mydot3a(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + + +typedef struct +{ + int firstObject; + int endObject; +} CollisionObjectIndices; + +typedef struct +{ + float4 shapeTransform[4]; // column major 4x4 matrix + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + int padding0; + +} CollisionShapeDescription; + +// From btBroadphaseProxy.h +__constant int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Multiply column-major matrix against vector +float4 matrixVectorMul( float4 matrix[4], float4 vector ) +{ + float4 returnVector; + float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); + float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); + float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); + float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); + returnVector.x = dot(row0, vector); + returnVector.y = dot(row1, vector); + returnVector.z = dot(row2, vector); + returnVector.w = dot(row3, vector); + return returnVector; +} + +__kernel void +SolveCollisionsAndUpdateVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global int *g_vertexClothIdentifier, + __global float4 *g_vertexPreviousPositions, + __global float * g_perClothFriction, + __global float * g_clothDampingFactor, + __global CollisionObjectIndices * g_perClothCollisionObjectIndices, + __global CollisionShapeDescription * g_collisionObjectDetails, + __global float4 * g_vertexForces, + __global float4 *g_vertexVelocities, + __global float4 *g_vertexPositions GUID_ARG) +{ + int nodeID = get_global_id(0); + float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); + + if( get_global_id(0) < numNodes ) + { + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + + // Abort if this is not a valid cloth + if( clothIdentifier < 0 ) + return; + + + float4 position = (float4)(g_vertexPositions[nodeID].xyz, 1.f); + float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 1.f); + + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + float4 difference = position - previousPosition; + float4 velocity = difference*velocityCoefficient*isolverdt; + + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) + { + CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; + float colliderFriction = shapeDescription.friction; + + if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = shapeDescription.halfHeight; + float capsuleRadius = shapeDescription.radius; + float capsuleMargin = shapeDescription.margin; + int capsuleupAxis = shapeDescription.upAxis; + + // Four columns of worldTransform matrix + float4 worldTransform[4]; + worldTransform[0] = shapeDescription.shapeTransform[0]; + worldTransform[1] = shapeDescription.shapeTransform[1]; + worldTransform[2] = shapeDescription.shapeTransform[2]; + worldTransform[3] = shapeDescription.shapeTransform[3]; + + // Correctly define capsule centerline vector + float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f); + float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f); + c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); + c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); + c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); + c2.x = -c1.x; + c2.y = -c1.y; + c2.z = -c1.z; + + + float4 worldC1 = matrixVectorMul(worldTransform, c1); + float4 worldC2 = matrixVectorMul(worldTransform, c2); + float4 segment = (worldC2 - worldC1); + + // compute distance of tangent to vertex along line segment in capsule + float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) ); + + float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment)); + float distanceFromLine = length(position - closestPoint); + float distanceFromC1 = length(worldC1 - position); + float distanceFromC2 = length(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float4 normalVector; + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = (float4)(normalize(position - worldC1).xyz, 0.f); + } else if( distanceAlongSegment > 1.f ) { + dist = distanceFromC2; + normalVector = (float4)(normalize(position - worldC2).xyz, 0.f); + } else { + dist = distanceFromLine; + normalVector = (float4)(normalize(position - closestPoint).xyz, 0.f); + } + + float4 colliderLinearVelocity = shapeDescription.linearVelocity; + float4 colliderAngularVelocity = shapeDescription.angularVelocity; + float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); + + float minDistance = capsuleRadius + capsuleMargin; + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = position + (float4)((minDistance - dist)*normalVector*0.9f); + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + float4 relativeVelocity = velocity - velocityOfSurfacePoint; + + float4 p1 = normalize(cross(normalVector, segment)); + float4 p2 = normalize(cross(p1, normalVector)); + // Full friction is sum of velocities in each direction of plane + float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); + + // Real friction is peak friction corrected by friction coefficients + frictionVector = frictionVector * (colliderFriction*clothFriction); + + float approachSpeed = dot(relativeVelocity, normalVector); + + if( approachSpeed <= 0.0f ) + forceOnVertex -= frictionVector; + } + } + } + } + + g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f); + + // Update external force + g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f); + + g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f); + } +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl new file mode 100644 index 00000000..8720b72e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl @@ -0,0 +1,242 @@ +MSTRINGIFY( + +//#pragma OPENCL EXTENSION cl_amd_printf:enable\n + +float mydot3a(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +float mylength3(float4 a) +{ + a.w = 0; + return length(a); +} + +float4 mynormalize3(float4 a) +{ + a.w = 0; + return normalize(a); +} + +typedef struct +{ + int firstObject; + int endObject; +} CollisionObjectIndices; + +typedef struct +{ + float4 shapeTransform[4]; // column major 4x4 matrix + float4 linearVelocity; + float4 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + + // Shape information + // Compressed from the union + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + int padding0; + +} CollisionShapeDescription; + +// From btBroadphaseProxy.h +__constant int CAPSULE_SHAPE_PROXYTYPE = 10; + +// Multiply column-major matrix against vector +float4 matrixVectorMul( float4 matrix[4], float4 vector ) +{ + float4 returnVector; + float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); + float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); + float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); + float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); + returnVector.x = dot(row0, vector); + returnVector.y = dot(row1, vector); + returnVector.z = dot(row2, vector); + returnVector.w = dot(row3, vector); + return returnVector; +} + +__kernel void +SolveCollisionsAndUpdateVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global int *g_vertexClothIdentifier, + __global float4 *g_vertexPreviousPositions, + __global float * g_perClothFriction, + __global float * g_clothDampingFactor, + __global CollisionObjectIndices * g_perClothCollisionObjectIndices, + __global CollisionShapeDescription * g_collisionObjectDetails, + __global float4 * g_vertexForces, + __global float4 *g_vertexVelocities, + __global float4 *g_vertexPositions, + __local CollisionShapeDescription *localCollisionShapes, + __global float * g_vertexInverseMasses) +{ + int nodeID = get_global_id(0); + float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); + + int clothIdentifier = g_vertexClothIdentifier[nodeID]; + + // Abort if this is not a valid cloth + if( clothIdentifier < 0 ) + return; + + + float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f); + float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 0.f); + + float clothFriction = g_perClothFriction[clothIdentifier]; + float dampingFactor = g_clothDampingFactor[clothIdentifier]; + float velocityCoefficient = (1.f - dampingFactor); + float4 difference = position - previousPosition; + float4 velocity = difference*velocityCoefficient*isolverdt; + float inverseMass = g_vertexInverseMasses[nodeID]; + + CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; + + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + + if( numObjects > 0 ) + { + // We have some possible collisions to deal with + + // First load all of the collision objects into LDS + int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; + if( get_local_id(0) < numObjects ) + { + localCollisionShapes[get_local_id(0)] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + get_local_id(0) ]; + } + } + + // Safe as the vertices are padded so that not more than one soft body is in a group + barrier(CLK_LOCAL_MEM_FENCE); + + // Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this + if( numObjects > 0 ) + { + + + // We have some possible collisions to deal with + for( int collision = 0; collision < numObjects; ++collision ) + { + CollisionShapeDescription shapeDescription = localCollisionShapes[collision]; + float colliderFriction = localCollisionShapes[collision].friction; + + if( localCollisionShapes[collision].collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Colliding with a capsule + + float capsuleHalfHeight = localCollisionShapes[collision].halfHeight; + float capsuleRadius = localCollisionShapes[collision].radius; + float capsuleMargin = localCollisionShapes[collision].margin; + int capsuleupAxis = localCollisionShapes[collision].upAxis; + + if ( capsuleHalfHeight <= 0 ) + capsuleHalfHeight = 0.0001f; + float4 worldTransform[4]; + worldTransform[0] = localCollisionShapes[collision].shapeTransform[0]; + worldTransform[1] = localCollisionShapes[collision].shapeTransform[1]; + worldTransform[2] = localCollisionShapes[collision].shapeTransform[2]; + worldTransform[3] = localCollisionShapes[collision].shapeTransform[3]; + + // Correctly define capsule centerline vector + float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f); + float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f); + c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); + c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); + c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); + c2.x = -c1.x; + c2.y = -c1.y; + c2.z = -c1.z; + + float4 worldC1 = matrixVectorMul(worldTransform, c1); + float4 worldC2 = matrixVectorMul(worldTransform, c2); + float4 segment = (float4)((worldC2 - worldC1).xyz, 0.f); + + float4 segmentNormalized = mynormalize3(segment); + float distanceAlongSegment =mydot3a( (position - worldC1), segmentNormalized ); + + float4 closestPointOnSegment = (worldC1 + (float4)(segmentNormalized * distanceAlongSegment)); + float distanceFromLine = mylength3(position - closestPointOnSegment); + float distanceFromC1 = mylength3(worldC1 - position); + float distanceFromC2 = mylength3(worldC2 - position); + + // Final distance from collision, point to push from, direction to push in + // for impulse force + float dist; + float4 normalVector; + + if( distanceAlongSegment < 0 ) + { + dist = distanceFromC1; + normalVector = (float4)(normalize(position - worldC1).xyz, 0.f); + } else if( distanceAlongSegment > length(segment) ) { + dist = distanceFromC2; + normalVector = (float4)(normalize(position - worldC2).xyz, 0.f); + } else { + dist = distanceFromLine; + normalVector = (float4)(normalize(position - closestPointOnSegment).xyz, 0.f); + } + + float minDistance = capsuleRadius + capsuleMargin; + float4 closestPointOnSurface = (float4)((position + (minDistance - dist) * normalVector).xyz, 0.f); + + float4 colliderLinearVelocity = shapeDescription.linearVelocity; + float4 colliderAngularVelocity = shapeDescription.angularVelocity; + float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, closestPointOnSurface - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); + + + // Check for a collision + if( dist < minDistance ) + { + // Project back to surface along normal + position = closestPointOnSurface; + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + float4 relativeVelocity = velocity - velocityOfSurfacePoint; + + float4 p1 = mynormalize3(cross(normalVector, segment)); + float4 p2 = mynormalize3(cross(p1, normalVector)); + + float4 tangentialVel = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); + float frictionCoef = (colliderFriction * clothFriction); + if (frictionCoef>1.f) + frictionCoef = 1.f; + + //only apply friction if objects are not moving apart + float projVel = mydot3a(relativeVelocity,normalVector); + if ( projVel >= -0.001f) + { + if ( inverseMass > 0 ) + { + //float4 myforceOnVertex = -tangentialVel * frictionCoef * isolverdt * (1.0f / inverseMass); + position += (-tangentialVel * frictionCoef) / (isolverdt); + } + } + + // In case of no collision, this is the value of velocity + velocity = (position - previousPosition) * velocityCoefficient * isolverdt; + + } + } + } + } + + g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f); + + // Update external force + g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f); + + g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f); +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl new file mode 100644 index 00000000..e4a5341c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl @@ -0,0 +1,57 @@ + + + +MSTRINGIFY( + + +float mydot3(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + + +__kernel void +SolvePositionsFromLinksKernel( + const int startLink, + const int numLinks, + const float kst, + const float ti, + __global int2 * g_linksVertexIndices, + __global float * g_linksMassLSC, + __global float * g_linksRestLengthSquared, + __global float * g_verticesInverseMass, + __global float4 * g_vertexPositions GUID_ARG) + +{ + int linkID = get_global_id(0) + startLink; + if( get_global_id(0) < numLinks ) + { + float massLSC = g_linksMassLSC[linkID]; + float restLengthSquared = g_linksRestLengthSquared[linkID]; + + if( massLSC > 0.0f ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float4 position0 = g_vertexPositions[node0]; + float4 position1 = g_vertexPositions[node1]; + + float inverseMass0 = g_verticesInverseMass[node0]; + float inverseMass1 = g_verticesInverseMass[node1]; + + float4 del = position1 - position0; + float len = mydot3(del, del); + float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + g_vertexPositions[node0] = position0; + g_vertexPositions[node1] = position1; + + } + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl new file mode 100644 index 00000000..e99bbf23 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl @@ -0,0 +1,130 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +MSTRINGIFY( + +float mydot3(float4 a, float4 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +__kernel __attribute__((reqd_work_group_size(WAVEFRONT_BLOCK_MULTIPLIER*WAVEFRONT_SIZE, 1, 1))) +void +SolvePositionsFromLinksKernel( + const int startWaveInBatch, + const int numWaves, + const float kst, + const float ti, + __global int2 *g_wavefrontBatchCountsVertexCounts, + __global int *g_vertexAddressesPerWavefront, + __global int2 * g_linksVertexIndices, + __global float * g_linksMassLSC, + __global float * g_linksRestLengthSquared, + __global float * g_verticesInverseMass, + __global float4 * g_vertexPositions, + __local int2 *wavefrontBatchCountsVertexCounts, + __local float4 *vertexPositionSharedData, + __local float *vertexInverseMassSharedData) +{ + const int laneInWavefront = (get_global_id(0) & (WAVEFRONT_SIZE-1)); + const int wavefront = startWaveInBatch + (get_global_id(0) / WAVEFRONT_SIZE); + const int firstWavefrontInBlock = startWaveInBatch + get_group_id(0) * WAVEFRONT_BLOCK_MULTIPLIER; + const int localWavefront = wavefront - firstWavefrontInBlock; + + // Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier + if( wavefront < (startWaveInBatch + numWaves) ) + { + // Load the batch counts for the wavefronts + + int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront]; + int batchesWithinWavefront = batchesAndVerticesWithinWavefront.x; + int verticesUsedByWave = batchesAndVerticesWithinWavefront.y; + + // Load the vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress]; + vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress]; + } + + barrier(CLK_LOCAL_MEM_FENCE); + + // Loop through the batches performing the solve on each in LDS + int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE; + + //for( int batch = 0; batch < batchesWithinWavefront; ++batch ) + + int batch = 0; + do + { + int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch; + int locationOfValue = baseDataLocation + laneInWavefront; + + + // These loads should all be perfectly linear across the WF + int2 localVertexIndices = g_linksVertexIndices[locationOfValue]; + float massLSC = g_linksMassLSC[locationOfValue]; + float restLengthSquared = g_linksRestLengthSquared[locationOfValue]; + + // LDS vertex addresses based on logical wavefront number in block and loaded index + int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x; + int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y; + + float4 position0 = vertexPositionSharedData[vertexAddress0]; + float4 position1 = vertexPositionSharedData[vertexAddress1]; + + float inverseMass0 = vertexInverseMassSharedData[vertexAddress0]; + float inverseMass1 = vertexInverseMassSharedData[vertexAddress1]; + + float4 del = position1 - position0; + float len = mydot3(del, del); + + float k = 0; + if( massLSC > 0.0f ) + { + k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; + } + + position0 = position0 - del*(k*inverseMass0); + position1 = position1 + del*(k*inverseMass1); + + // Ensure compiler does not re-order memory operations + barrier(CLK_LOCAL_MEM_FENCE); + + vertexPositionSharedData[vertexAddress0] = position0; + vertexPositionSharedData[vertexAddress1] = position1; + + // Ensure compiler does not re-order memory operations + barrier(CLK_LOCAL_MEM_FENCE); + + + ++batch; + } while( batch < batchesWithinWavefront ); + + // Update the global memory vertices for the wavefronts + for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) + { + int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; + + g_vertexPositions[vertexAddress] = (float4)(vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex].xyz, 0.f); + } + + } + +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl new file mode 100644 index 00000000..1d925a31 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl @@ -0,0 +1,44 @@ +MSTRINGIFY( + +/*#define float3 float4 + +float dot3(float3 a, float3 b) +{ + return a.x*b.x + a.y*b.y + a.z*b.z; +}*/ + +__kernel void +UpdateConstantsKernel( + const int numLinks, + __global int2 * g_linksVertexIndices, + __global float4 * g_vertexPositions, + __global float * g_vertexInverseMasses, + __global float * g_linksMaterialLSC, + __global float * g_linksMassLSC, + __global float * g_linksRestLengthSquared, + __global float * g_linksRestLengths) +{ + int linkID = get_global_id(0); + if( linkID < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ]; + + float3 position0 = g_vertexPositions[node0].xyz; + float3 position1 = g_vertexPositions[node1].xyz; + float inverseMass0 = g_vertexInverseMasses[node0]; + float inverseMass1 = g_vertexInverseMasses[node1]; + + float3 difference = position0 - position1; + float length2 = dot(difference, difference); + float length = sqrt(length2); + + g_linksRestLengths[linkID] = length; + g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient; + g_linksRestLengthSquared[linkID] = length*length; + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl new file mode 100644 index 00000000..3b2516e7 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl @@ -0,0 +1,25 @@ +MSTRINGIFY( + +__kernel void +UpdateFixedVertexPositions( + const uint numNodes, + __global int * g_anchorIndex, + __global float4 * g_vertexPositions, + __global float4 * g_anchorPositions GUID_ARG) +{ + unsigned int nodeID = get_global_id(0); + + if( nodeID < numNodes ) + { + int anchorIndex = g_anchorIndex[nodeID]; + float4 position = g_vertexPositions[nodeID]; + + if ( anchorIndex >= 0 ) + { + float4 anchorPosition = g_anchorPositions[anchorIndex]; + g_vertexPositions[nodeID] = anchorPosition; + } + } +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl new file mode 100644 index 00000000..aa7c778a --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl @@ -0,0 +1,39 @@ +MSTRINGIFY( + + +__kernel void +updateVelocitiesFromPositionsWithVelocitiesKernel( + int numNodes, + float isolverdt, + __global float4 * g_vertexPositions, + __global float4 * g_vertexPreviousPositions, + __global int * g_vertexClothIndices, + __global float *g_clothVelocityCorrectionCoefficients, + __global float * g_clothDampingFactor, + __global float4 * g_vertexVelocities, + __global float4 * g_vertexForces GUID_ARG) +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID]; + float4 previousPosition = g_vertexPreviousPositions[nodeID]; + float4 velocity = g_vertexVelocities[nodeID]; + int clothIndex = g_vertexClothIndices[nodeID]; + float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float4 difference = position - previousPosition; + + velocity += difference*velocityCorrectionCoefficient*isolverdt; + + // Damp the velocity + velocity *= velocityCoefficient; + + g_vertexVelocities[nodeID] = velocity; + g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl new file mode 100644 index 00000000..d277b683 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl @@ -0,0 +1,102 @@ +MSTRINGIFY( + +float length3(float4 a) +{ + a.w = 0; + return length(a); +} + +float4 normalize3(float4 a) +{ + a.w = 0; + return normalize(a); +} + +__kernel void +ResetNormalsAndAreasKernel( + const unsigned int numNodes, + __global float4 * g_vertexNormals, + __global float * g_vertexArea GUID_ARG) +{ + if( get_global_id(0) < numNodes ) + { + g_vertexNormals[get_global_id(0)] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); + g_vertexArea[get_global_id(0)] = 0.0f; + } +} + + +__kernel void +UpdateSoftBodiesKernel( + const unsigned int startFace, + const unsigned int numFaces, + __global int4 * g_triangleVertexIndexSet, + __global float4 * g_vertexPositions, + __global float4 * g_vertexNormals, + __global float * g_vertexArea, + __global float4 * g_triangleNormals, + __global float * g_triangleArea GUID_ARG) +{ + int faceID = get_global_id(0) + startFace; + if( get_global_id(0) < numFaces ) + { + int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ]; + int nodeIndex0 = triangleIndexSet.x; + int nodeIndex1 = triangleIndexSet.y; + int nodeIndex2 = triangleIndexSet.z; + + float4 node0 = g_vertexPositions[nodeIndex0]; + float4 node1 = g_vertexPositions[nodeIndex1]; + float4 node2 = g_vertexPositions[nodeIndex2]; + float4 nodeNormal0 = g_vertexNormals[nodeIndex0]; + float4 nodeNormal1 = g_vertexNormals[nodeIndex1]; + float4 nodeNormal2 = g_vertexNormals[nodeIndex2]; + float vertexArea0 = g_vertexArea[nodeIndex0]; + float vertexArea1 = g_vertexArea[nodeIndex1]; + float vertexArea2 = g_vertexArea[nodeIndex2]; + + float4 vector0 = node1 - node0; + float4 vector1 = node2 - node0; + + float4 faceNormal = cross(vector0, vector1); + float triangleArea = length(faceNormal); + + nodeNormal0 = nodeNormal0 + faceNormal; + nodeNormal1 = nodeNormal1 + faceNormal; + nodeNormal2 = nodeNormal2 + faceNormal; + vertexArea0 = vertexArea0 + triangleArea; + vertexArea1 = vertexArea1 + triangleArea; + vertexArea2 = vertexArea2 + triangleArea; + + g_triangleNormals[faceID] = normalize3(faceNormal); + g_vertexNormals[nodeIndex0] = nodeNormal0; + g_vertexNormals[nodeIndex1] = nodeNormal1; + g_vertexNormals[nodeIndex2] = nodeNormal2; + g_triangleArea[faceID] = triangleArea; + g_vertexArea[nodeIndex0] = vertexArea0; + g_vertexArea[nodeIndex1] = vertexArea1; + g_vertexArea[nodeIndex2] = vertexArea2; + } +} + +__kernel void +NormalizeNormalsAndAreasKernel( + const unsigned int numNodes, + __global int * g_vertexTriangleCount, + __global float4 * g_vertexNormals, + __global float * g_vertexArea GUID_ARG) +{ + if( get_global_id(0) < numNodes ) + { + float4 normal = g_vertexNormals[get_global_id(0)]; + float area = g_vertexArea[get_global_id(0)]; + int numTriangles = g_vertexTriangleCount[get_global_id(0)]; + + float vectorLength = length3(normal); + + g_vertexNormals[get_global_id(0)] = normalize3(normal); + g_vertexArea[get_global_id(0)] = area/(float)(numTriangles); + } +} + +); diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl new file mode 100644 index 00000000..a2610314 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl @@ -0,0 +1,34 @@ +MSTRINGIFY( + +__kernel void +updateVelocitiesFromPositionsWithoutVelocitiesKernel( + const int numNodes, + const float isolverdt, + __global float4 * g_vertexPositions, + __global float4 * g_vertexPreviousPositions, + __global int * g_vertexClothIndices, + __global float * g_clothDampingFactor, + __global float4 * g_vertexVelocities, + __global float4 * g_vertexForces GUID_ARG) + +{ + int nodeID = get_global_id(0); + if( nodeID < numNodes ) + { + float4 position = g_vertexPositions[nodeID]; + float4 previousPosition = g_vertexPreviousPositions[nodeID]; + float4 velocity = g_vertexVelocities[nodeID]; + int clothIndex = g_vertexClothIndices[nodeID]; + float dampingFactor = g_clothDampingFactor[clothIndex]; + float velocityCoefficient = (1.f - dampingFactor); + + float4 difference = position - previousPosition; + + velocity = difference*velocityCoefficient*isolverdt; + + g_vertexVelocities[nodeID] = velocity; + g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl new file mode 100644 index 00000000..ec1f4878 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl @@ -0,0 +1,28 @@ + +MSTRINGIFY( + + + + +__kernel void +UpdatePositionsFromVelocitiesKernel( + const int numNodes, + const float solverSDT, + __global float4 * g_vertexVelocities, + __global float4 * g_vertexPreviousPositions, + __global float4 * g_vertexCurrentPosition GUID_ARG) +{ + int vertexID = get_global_id(0); + if( vertexID < numNodes ) + { + float4 previousPosition = g_vertexPreviousPositions[vertexID]; + float4 velocity = g_vertexVelocities[vertexID]; + + float4 newPosition = previousPosition + velocity*solverSDT; + + g_vertexCurrentPosition[vertexID] = newPosition; + g_vertexPreviousPositions[vertexID] = newPosition; + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl new file mode 100644 index 00000000..19224bda --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl @@ -0,0 +1,45 @@ +MSTRINGIFY( + +__kernel void +VSolveLinksKernel( + int startLink, + int numLinks, + float kst, + __global int2 * g_linksVertexIndices, + __global float * g_linksLengthRatio, + __global float4 * g_linksCurrentLength, + __global float * g_vertexInverseMass, + __global float4 * g_vertexVelocity GUID_ARG) +{ + int linkID = get_global_id(0) + startLink; + if( get_global_id(0) < numLinks ) + { + int2 nodeIndices = g_linksVertexIndices[linkID]; + int node0 = nodeIndices.x; + int node1 = nodeIndices.y; + + float linkLengthRatio = g_linksLengthRatio[linkID]; + float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz; + + float3 vertexVelocity0 = g_vertexVelocity[node0].xyz; + float3 vertexVelocity1 = g_vertexVelocity[node1].xyz; + + float vertexInverseMass0 = g_vertexInverseMass[node0]; + float vertexInverseMass1 = g_vertexInverseMass[node1]; + + float3 nodeDifference = vertexVelocity0 - vertexVelocity1; + float dotResult = dot(linkCurrentLength, nodeDifference); + float j = -dotResult*linkLengthRatio*kst; + + float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0); + float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1); + + vertexVelocity0 += velocityChange0; + vertexVelocity1 -= velocityChange1; + + g_vertexVelocity[node0] = (float4)(vertexVelocity0, 0.f); + g_vertexVelocity[node1] = (float4)(vertexVelocity1, 0.f); + } +} + +); \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h new file mode 100644 index 00000000..f824f281 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h @@ -0,0 +1,209 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H +#define BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H + +// OpenCL support + +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #endif //__APPLE__ +#endif//USE_MINICL + +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } +#endif + +template class btOpenCLBuffer +{ +public: + + cl_command_queue m_cqCommandQue; + cl_context m_clContext; + cl_mem m_buffer; + + + + btAlignedObjectArray< ElementType > * m_CPUBuffer; + + int m_gpuSize; + bool m_onGPU; + bool m_readOnlyOnGPU; + bool m_allocated; + + + bool createBuffer( cl_mem* preexistingBuffer = 0) + { + + cl_int err; + + + if( preexistingBuffer ) + { + m_buffer = *preexistingBuffer; + } + else { + + cl_mem_flags flags= m_readOnlyOnGPU ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE; + + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + // At a minimum the buffer must exist + if( size == 0 ) + size = sizeof(ElementType); + m_buffer = clCreateBuffer(m_clContext, flags, size, 0, &err); + if( err != CL_SUCCESS ) + { + btAssert( "Buffer::Buffer(m_buffer)"); + } + } + + m_gpuSize = m_CPUBuffer->size(); + + return true; + } + +public: + btOpenCLBuffer( cl_command_queue commandQue,cl_context ctx, btAlignedObjectArray< ElementType >* CPUBuffer, bool readOnly) + :m_cqCommandQue(commandQue), + m_clContext(ctx), + m_buffer(0), + m_CPUBuffer(CPUBuffer), + m_gpuSize(0), + m_onGPU(false), + m_readOnlyOnGPU(readOnly), + m_allocated(false) + { + } + + ~btOpenCLBuffer() + { + clReleaseMemObject(m_buffer); + } + + + bool moveToGPU() + { + + + cl_int err; + + if( (m_CPUBuffer->size() != m_gpuSize) ) + { + m_onGPU = false; + } + + if( !m_allocated && m_CPUBuffer->size() == 0 ) + { + // If it isn't on the GPU and yet there is no data on the CPU side this may cause a problem with some kernels. + // We should create *something* on the device side + if (!createBuffer()) { + return false; + } + m_allocated = true; + } + + if( !m_onGPU && m_CPUBuffer->size() > 0 ) + { + if (!m_allocated || (m_CPUBuffer->size() != m_gpuSize)) { + if (!createBuffer()) { + return false; + } + m_allocated = true; + } + + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + err = clEnqueueWriteBuffer(m_cqCommandQue,m_buffer, + CL_FALSE, + 0, + size, + &((*m_CPUBuffer)[0]),0,0,0); + if( err != CL_SUCCESS ) + { + btAssert( "CommandQueue::enqueueWriteBuffer(m_buffer)" ); + } + + m_onGPU = true; + } + + return true; + + } + + bool moveFromGPU() + { + + cl_int err; + + if (m_CPUBuffer->size() > 0) { + if (m_onGPU && !m_readOnlyOnGPU) { + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + err = clEnqueueReadBuffer(m_cqCommandQue, + m_buffer, + CL_TRUE, + 0, + size, + &((*m_CPUBuffer)[0]),0,0,0); + + if( err != CL_SUCCESS ) + { + btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)" ); + } + + m_onGPU = false; + } + } + + return true; + } + + bool copyFromGPU() + { + + cl_int err; + size_t size = m_CPUBuffer->size() * sizeof(ElementType); + + if (m_CPUBuffer->size() > 0) { + if (m_onGPU && !m_readOnlyOnGPU) { + err = clEnqueueReadBuffer(m_cqCommandQue, + m_buffer, + CL_TRUE, + 0,size, + &((*m_CPUBuffer)[0]),0,0,0); + + if( err != CL_SUCCESS ) + { + btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)"); + } + + } + } + + return true; + } + + virtual void changedOnCPU() + { + m_onGPU = false; + } +}; // class btOpenCLBuffer + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h new file mode 100644 index 00000000..6921f7da --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h @@ -0,0 +1,99 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + + +#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H +#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H + + +class btSoftBodyLinkDataOpenCL : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + + cl_command_queue m_cqCommandQue; + + + btOpenCLBuffer m_clLinks; + btOpenCLBuffer m_clLinkStrength; + btOpenCLBuffer m_clLinksMassLSC; + btOpenCLBuffer m_clLinksRestLengthSquared; + btOpenCLBuffer m_clLinksCLength; + btOpenCLBuffer m_clLinksLengthRatio; + btOpenCLBuffer m_clLinksRestLength; + btOpenCLBuffer m_clLinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_batchStartLengths; + + btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx); + + virtual ~btSoftBodyLinkDataOpenCL(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( + const LinkDescription &link, + int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h new file mode 100644 index 00000000..b20e8055 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h @@ -0,0 +1,169 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + + +#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H +#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H + + +class btSoftBodyLinkDataOpenCLSIMDAware : public btSoftBodyLinkData +{ +public: + bool m_onGPU; + + cl_command_queue m_cqCommandQue; + + const int m_wavefrontSize; + const int m_linksPerWorkItem; + const int m_maxLinksPerWavefront; + int m_maxBatchesWithinWave; + int m_maxVerticesWithinWave; + int m_numWavefronts; + + int m_maxVertex; + + struct NumBatchesVerticesPair + { + int numBatches; + int numVertices; + }; + + btAlignedObjectArray m_linksPerWavefront; + btAlignedObjectArray m_numBatchesAndVerticesWithinWaves; + btOpenCLBuffer< NumBatchesVerticesPair > m_clNumBatchesAndVerticesWithinWaves; + + // All arrays here will contain batches of m_maxLinksPerWavefront links + // ordered by wavefront. + // with either global vertex pairs or local vertex pairs + btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront + btOpenCLBuffer m_clWavefrontVerticesGlobalAddresses; + btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link + btOpenCLBuffer m_clLinkVerticesLocalAddresses; + btOpenCLBuffer m_clLinkStrength; + btOpenCLBuffer m_clLinksMassLSC; + btOpenCLBuffer m_clLinksRestLengthSquared; + btOpenCLBuffer m_clLinksRestLength; + btOpenCLBuffer m_clLinksMaterialLinearStiffnessCoefficient; + + struct BatchPair + { + int start; + int length; + + BatchPair() : + start(0), + length(0) + { + } + + BatchPair( int s, int l ) : + start( s ), + length( l ) + { + } + }; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_linkAddresses; + + /** + * Start and length values for computation batches over link data. + */ + btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths; + + btSoftBodyLinkDataOpenCLSIMDAware(cl_command_queue queue, cl_context ctx); + + virtual ~btSoftBodyLinkDataOpenCLSIMDAware(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( + const LinkDescription &link, + int linkIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); + + int getMaxVerticesPerWavefront() + { + return m_maxVerticesWithinWave; + } + + int getWavefrontSize() + { + return m_wavefrontSize; + } + + int getLinksPerWorkItem() + { + return m_linksPerWorkItem; + } + + int getMaxLinksPerWavefront() + { + return m_maxLinksPerWavefront; + } + + int getMaxBatchesPerWavefront() + { + return m_maxBatchesWithinWave; + } + + int getNumWavefronts() + { + return m_numWavefronts; + } + + NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront ) + { + return m_numBatchesAndVerticesWithinWaves[wavefront]; + } + + int getVertexGlobalAddresses( int vertexIndex ) + { + return m_wavefrontVerticesGlobalAddresses[vertexIndex]; + } + + /** + * Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally. + */ + LinkNodePair getVertexPairLocalAddresses( int linkIndex ) + { + return m_linkVerticesLocalAddresses[linkIndex]; + } +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp new file mode 100644 index 00000000..1000440b --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp @@ -0,0 +1,126 @@ +#include "btSoftBodySolverOutputCLtoGL.h" +#include //@todo: remove the debugging printf at some stage +#include "btSoftBodySolver_OpenCL.h" +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#include "btSoftBodySolverVertexBuffer_OpenGL.h" +#include "BulletSoftBody/btSoftBody.h" + +////OpenCL 1.0 kernels don't use float3 +#define MSTRINGIFY(A) #A +static char* OutputToVertexArrayCLString = +#include "OpenCLC10/OutputToVertexArray.cl" + + +#define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }} + +static const size_t workGroupSize = 128; + +void btSoftBodySolverOutputCLtoGL::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); + btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); + checkInitialized(); + btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::OPENGL_BUFFER ) { + + const btOpenGLInteropVertexBufferDescriptor *openGLVertexBuffer = static_cast< btOpenGLInteropVertexBufferDescriptor* >(vertexBuffer); + cl_int ciErrNum = CL_SUCCESS; + + cl_mem clBuffer = openGLVertexBuffer->getBuffer(); + cl_kernel outputKernel = outputToVertexArrayWithNormalsKernel; + if( !vertexBuffer->hasNormals() ) + outputKernel = outputToVertexArrayWithoutNormalsKernel; + + ciErrNum = clEnqueueAcquireGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, NULL); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); + } + + int numVertices = currentCloth->getNumVertices(); + + ciErrNum = clSetKernelArg(outputKernel, 0, sizeof(int), &firstVertex ); + ciErrNum = clSetKernelArg(outputKernel, 1, sizeof(int), &numVertices ); + ciErrNum = clSetKernelArg(outputKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); + if( vertexBuffer->hasVertexPositions() ) + { + int vertexOffset = vertexBuffer->getVertexOffset(); + int vertexStride = vertexBuffer->getVertexStride(); + ciErrNum = clSetKernelArg(outputKernel, 3, sizeof(int), &vertexOffset ); + ciErrNum = clSetKernelArg(outputKernel, 4, sizeof(int), &vertexStride ); + ciErrNum = clSetKernelArg(outputKernel, 5, sizeof(cl_mem), (void*)&vertexData.m_clVertexPosition.m_buffer ); + + } + if( vertexBuffer->hasNormals() ) + { + int normalOffset = vertexBuffer->getNormalOffset(); + int normalStride = vertexBuffer->getNormalStride(); + ciErrNum = clSetKernelArg(outputKernel, 6, sizeof(int), &normalOffset ); + ciErrNum = clSetKernelArg(outputKernel, 7, sizeof(int), &normalStride ); + ciErrNum = clSetKernelArg(outputKernel, 8, sizeof(cl_mem), (void*)&vertexData.m_clVertexNormal.m_buffer ); + + } + size_t numWorkItems = workGroupSize*((vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, outputKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(copySoftBodyToVertexBuffer)"); + } + + ciErrNum = clEnqueueReleaseGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, 0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueReleaseGLObjects(copySoftBodyToVertexBuffer)"); + } + } else { + btAssert( "Undefined output for this solver output" == false ); + } + + // clFinish in here may not be the best thing. It's possible that we should have a waitForFrameComplete function. + clFinish(m_cqCommandQue); + +} // btSoftBodySolverOutputCLtoGL::outputToVertexBuffers + +bool btSoftBodySolverOutputCLtoGL::buildShaders() +{ + // Ensure current kernels are released first + releaseKernels(); + + bool returnVal = true; + + if( m_shadersInitialized ) + return true; + + outputToVertexArrayWithNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl"); + outputToVertexArrayWithoutNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithoutNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl"); + + + if( returnVal ) + m_shadersInitialized = true; + + return returnVal; +} // btSoftBodySolverOutputCLtoGL::buildShaders + +void btSoftBodySolverOutputCLtoGL::releaseKernels() +{ + RELEASE_CL_KERNEL( outputToVertexArrayWithNormalsKernel ); + RELEASE_CL_KERNEL( outputToVertexArrayWithoutNormalsKernel ); + + m_shadersInitialized = false; +} // btSoftBodySolverOutputCLtoGL::releaseKernels + +bool btSoftBodySolverOutputCLtoGL::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h new file mode 100644 index 00000000..ab3ea264 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H +#define BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H + +#include "btSoftBodySolver_OpenCL.h" + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the CL to GL interop version. + */ +class btSoftBodySolverOutputCLtoGL : public btSoftBodySolverOutput +{ +protected: + cl_command_queue m_cqCommandQue; + cl_context m_cxMainContext; + CLFunctions clFunctions; + + cl_kernel outputToVertexArrayWithNormalsKernel; + cl_kernel outputToVertexArrayWithoutNormalsKernel; + + bool m_shadersInitialized; + + virtual bool checkInitialized(); + virtual bool buildShaders(); + void releaseKernels(); +public: + btSoftBodySolverOutputCLtoGL(cl_command_queue cqCommandQue, cl_context cxMainContext) : + m_cqCommandQue( cqCommandQue ), + m_cxMainContext( cxMainContext ), + clFunctions(cqCommandQue, cxMainContext), + outputToVertexArrayWithNormalsKernel( 0 ), + outputToVertexArrayWithoutNormalsKernel( 0 ), + m_shadersInitialized( false ) + { + } + + virtual ~btSoftBodySolverOutputCLtoGL() + { + releaseKernels(); + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h new file mode 100644 index 00000000..7e376785 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + + +#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H +#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H + + +class btSoftBodyTriangleDataOpenCL : public btSoftBodyTriangleData +{ +public: + bool m_onGPU; + cl_command_queue m_queue; + + btOpenCLBuffer m_clVertexIndices; + btOpenCLBuffer m_clArea; + btOpenCLBuffer m_clNormal; + + /** + * Link addressing information for each cloth. + * Allows link locations to be computed independently of data batching. + */ + btAlignedObjectArray< int > m_triangleAddresses; + + /** + * Start and length values for computation batches over link data. + */ + struct btSomePair + { + btSomePair() {} + btSomePair(int f,int s) + :first(f),second(s) + { + } + int first; + int second; + }; + btAlignedObjectArray< btSomePair > m_batchStartLengths; + +public: + btSoftBodyTriangleDataOpenCL( cl_command_queue queue, cl_context ctx ); + + virtual ~btSoftBodyTriangleDataOpenCL(); + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createTriangles( int numTriangles ); + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(); + + /** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ + void generateBatches(); +}; // class btSoftBodyTriangleDataOpenCL + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h new file mode 100644 index 00000000..7c223ecc --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h @@ -0,0 +1,166 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H +#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H + + +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #include + #endif //__APPLE__ +#endif//USE_MINICL + + +#ifdef _WIN32//for glut.h +#include +#endif + +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#include +#else + + +#ifdef _WINDOWS +#include +#include +#include +#else +#include +#endif //_WINDOWS +#endif //APPLE + + + +class btOpenGLInteropVertexBufferDescriptor : public btVertexBufferDescriptor +{ +protected: + /** OpenCL context */ + cl_context m_context; + + /** OpenCL command queue */ + cl_command_queue m_commandQueue; + + /** OpenCL interop buffer */ + cl_mem m_buffer; + + /** VBO in GL that is the basis of the interop buffer */ + GLuint m_openGLVBO; + + +public: + /** + * context is the OpenCL context this interop buffer will work in. + * queue is the command queue that kernels and data movement will be enqueued into. + * openGLVBO is the OpenGL vertex buffer data will be copied into. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride ) + { +#ifndef USE_MINICL + cl_int ciErrNum = CL_SUCCESS; + m_context = context; + m_commandQueue = cqCommandQue; + + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + + m_openGLVBO = openGLVBO; + + m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); + } + + m_hasVertexPositions = true; +#else + btAssert(0);//MiniCL shouldn't get here +#endif + } + + /** + * context is the OpenCL context this interop buffer will work in. + * queue is the command queue that kernels and data movement will be enqueued into. + * openGLVBO is the OpenGL vertex buffer data will be copied into. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + * normalOffset is the offset in floats to the first normal. + * normalStride is the stride in floats between normals. + */ + btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) + { +#ifndef USE_MINICL + cl_int ciErrNum = CL_SUCCESS; + m_context = context; + m_commandQueue = cqCommandQue; + + m_openGLVBO = openGLVBO; + + m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); + } + + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + + m_normalOffset = normalOffset; + m_normalStride = normalStride; + m_hasNormals = true; +#else + btAssert(0); +#endif //USE_MINICL + + } + + virtual ~btOpenGLInteropVertexBufferDescriptor() + { + clReleaseMemObject( m_buffer ); + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const + { + return OPENGL_BUFFER; + } + + virtual cl_context getContext() const + { + return m_context; + } + + virtual cl_mem getBuffer() const + { + return m_buffer; + } +}; + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h new file mode 100644 index 00000000..531c3427 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h @@ -0,0 +1,52 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" +#include "btSoftBodySolverBuffer_OpenCL.h" + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H +#define BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H + + +class btSoftBodyVertexDataOpenCL : public btSoftBodyVertexData +{ +protected: + bool m_onGPU; + cl_command_queue m_queue; + +public: + btOpenCLBuffer m_clClothIdentifier; + btOpenCLBuffer m_clVertexPosition; + btOpenCLBuffer m_clVertexPreviousPosition; + btOpenCLBuffer m_clVertexVelocity; + btOpenCLBuffer m_clVertexForceAccumulator; + btOpenCLBuffer m_clVertexNormal; + btOpenCLBuffer m_clVertexInverseMass; + btOpenCLBuffer m_clVertexArea; + btOpenCLBuffer m_clVertexTriangleCount; +public: + btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx); + + virtual ~btSoftBodyVertexDataOpenCL(); + + virtual bool onAccelerator(); + + virtual bool moveToAccelerator(); + + virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true); +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp new file mode 100644 index 00000000..e5f4ebb2 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp @@ -0,0 +1,1820 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" +#include //@todo: remove the debugging printf at some stage +#include "btSoftBodySolver_OpenCL.h" +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletSoftBody/btSoftBodyInternals.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "LinearMath/btQuickprof.h" +#include +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +#define BT_SUPPRESS_OPENCL_ASSERTS + +#ifdef USE_MINICL + #include "MiniCL/cl.h" +#else //USE_MINICL + #ifdef __APPLE__ + #include + #else + #include + #endif //__APPLE__ +#endif//USE_MINICL + +#define BT_DEFAULT_WORKGROUPSIZE 64 + + +#define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }} + + +//CL_VERSION_1_1 seems broken on NVidia SDK so just disable it + +////OpenCL 1.0 kernels don't use float3 +#define MSTRINGIFY(A) #A +static const char* PrepareLinksCLString = +#include "OpenCLC10/PrepareLinks.cl" +static const char* UpdatePositionsFromVelocitiesCLString = +#include "OpenCLC10/UpdatePositionsFromVelocities.cl" +static const char* SolvePositionsCLString = +#include "OpenCLC10/SolvePositions.cl" +static const char* UpdateNodesCLString = +#include "OpenCLC10/UpdateNodes.cl" +static const char* UpdatePositionsCLString = +#include "OpenCLC10/UpdatePositions.cl" +static const char* UpdateConstantsCLString = +#include "OpenCLC10/UpdateConstants.cl" +static const char* IntegrateCLString = +#include "OpenCLC10/Integrate.cl" +static const char* ApplyForcesCLString = +#include "OpenCLC10/ApplyForces.cl" +static const char* UpdateFixedVertexPositionsCLString = +#include "OpenCLC10/UpdateFixedVertexPositions.cl" +static const char* UpdateNormalsCLString = +#include "OpenCLC10/UpdateNormals.cl" +static const char* VSolveLinksCLString = +#include "OpenCLC10/VSolveLinks.cl" +static const char* SolveCollisionsAndUpdateVelocitiesCLString = +#include "OpenCLC10/SolveCollisionsAndUpdateVelocities.cl" + + +btSoftBodyVertexDataOpenCL::btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx) : + m_queue(queue), + m_clClothIdentifier( queue, ctx, &m_clothIdentifier, false ), + m_clVertexPosition( queue, ctx, &m_vertexPosition, false ), + m_clVertexPreviousPosition( queue, ctx, &m_vertexPreviousPosition, false ), + m_clVertexVelocity( queue, ctx, &m_vertexVelocity, false ), + m_clVertexForceAccumulator( queue, ctx, &m_vertexForceAccumulator, false ), + m_clVertexNormal( queue, ctx, &m_vertexNormal, false ), + m_clVertexInverseMass( queue, ctx, &m_vertexInverseMass, false ), + m_clVertexArea( queue, ctx, &m_vertexArea, false ), + m_clVertexTriangleCount( queue, ctx, &m_vertexTriangleCount, false ) +{ +} + +btSoftBodyVertexDataOpenCL::~btSoftBodyVertexDataOpenCL() +{ + +} + +bool btSoftBodyVertexDataOpenCL::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyVertexDataOpenCL::moveToAccelerator() +{ + bool success = true; + success = success && m_clClothIdentifier.moveToGPU(); + success = success && m_clVertexPosition.moveToGPU(); + success = success && m_clVertexPreviousPosition.moveToGPU(); + success = success && m_clVertexVelocity.moveToGPU(); + success = success && m_clVertexForceAccumulator.moveToGPU(); + success = success && m_clVertexNormal.moveToGPU(); + success = success && m_clVertexInverseMass.moveToGPU(); + success = success && m_clVertexArea.moveToGPU(); + success = success && m_clVertexTriangleCount.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyVertexDataOpenCL::moveFromAccelerator(bool bCopy, bool bCopyMinimum) +{ + bool success = true; + + if (!bCopy) + { + success = success && m_clClothIdentifier.moveFromGPU(); + success = success && m_clVertexPosition.moveFromGPU(); + success = success && m_clVertexPreviousPosition.moveFromGPU(); + success = success && m_clVertexVelocity.moveFromGPU(); + success = success && m_clVertexForceAccumulator.moveFromGPU(); + success = success && m_clVertexNormal.moveFromGPU(); + success = success && m_clVertexInverseMass.moveFromGPU(); + success = success && m_clVertexArea.moveFromGPU(); + success = success && m_clVertexTriangleCount.moveFromGPU(); + } + else + { + if (bCopyMinimum) + { + success = success && m_clVertexPosition.copyFromGPU(); + success = success && m_clVertexNormal.copyFromGPU(); + } + else + { + success = success && m_clClothIdentifier.copyFromGPU(); + success = success && m_clVertexPosition.copyFromGPU(); + success = success && m_clVertexPreviousPosition.copyFromGPU(); + success = success && m_clVertexVelocity.copyFromGPU(); + success = success && m_clVertexForceAccumulator.copyFromGPU(); + success = success && m_clVertexNormal.copyFromGPU(); + success = success && m_clVertexInverseMass.copyFromGPU(); + success = success && m_clVertexArea.copyFromGPU(); + success = success && m_clVertexTriangleCount.copyFromGPU(); + } + } + + if( success ) + m_onGPU = true; + + return success; +} + +btSoftBodyLinkDataOpenCL::btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx) +:m_cqCommandQue(queue), + m_clLinks( queue, ctx, &m_links, false ), + m_clLinkStrength( queue, ctx, &m_linkStrength, false ), + m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ), + m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ), + m_clLinksCLength( queue, ctx, &m_linksCLength, false ), + m_clLinksLengthRatio( queue, ctx, &m_linksLengthRatio, false ), + m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ), + m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false ) +{ +} + +btSoftBodyLinkDataOpenCL::~btSoftBodyLinkDataOpenCL() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyLinkDataOpenCL::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyLinkDataOpenCL::setLinkAt( + const LinkDescription &link, + int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataOpenCL::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataOpenCL::moveToAccelerator() +{ + bool success = true; + success = success && m_clLinks.moveToGPU(); + success = success && m_clLinkStrength.moveToGPU(); + success = success && m_clLinksMassLSC.moveToGPU(); + success = success && m_clLinksRestLengthSquared.moveToGPU(); + success = success && m_clLinksCLength.moveToGPU(); + success = success && m_clLinksLengthRatio.moveToGPU(); + success = success && m_clLinksRestLength.moveToGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) { + m_onGPU = true; + } + + return success; +} + +bool btSoftBodyLinkDataOpenCL::moveFromAccelerator() +{ + bool success = true; + success = success && m_clLinks.moveFromGPU(); + success = success && m_clLinkStrength.moveFromGPU(); + success = success && m_clLinksMassLSC.moveFromGPU(); + success = success && m_clLinksRestLengthSquared.moveFromGPU(); + success = success && m_clLinksCLength.moveFromGPU(); + success = success && m_clLinksLengthRatio.moveFromGPU(); + success = success && m_clLinksRestLength.moveFromGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) { + m_onGPU = false; + } + + return success; +} + +/** + * Generate (and later update) the batching for the entire link set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ +void btSoftBodyLinkDataOpenCL::generateBatches() +{ + int numLinks = getNumLinks(); + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numLinks, 0 ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int vertex0 = getVertexPair(linkIndex).vertex0; + int vertex1 = getVertexPair(linkIndex).vertex1; + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + // Simple algorithm that chooses the lowest batch number + // that none of the links attached to either of the connected + // nodes is in + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + int linkLocation = m_linkAddresses[linkIndex]; + + int vertex0 = getVertexPair(linkLocation).vertex0; + int vertex1 = getVertexPair(linkLocation).vertex1; + + // Get the two node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + + // Choose the minimum colour that is in neither list + int colour = 0; + while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ) + ++colour; + // i should now be the minimum colour in neither list + // Add to the two lists so that future edges don't share + // And store the colour against this edge + + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + batchValues[linkIndex] = colour; + } + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numLinks; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + m_batchStartLengths.resize(batchCounts.size()); + if( m_batchStartLengths.size() > 0 ) + { + m_batchStartLengths.resize(batchCounts.size()); + m_batchStartLengths[0] = BatchPair(0, 0); + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].start = sum; + m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int linkLocation = m_linkAddresses[linkIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[linkIndex]; + int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_links[newLocation] = m_links_Backup[linkLocation]; +#if 1 + m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation]; + m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation]; + m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation]; + m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation]; + m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation]; + m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation]; +#endif + // Update the locations array to account for the moved entry + m_linkAddresses[linkIndex] = newLocation; + } + + +} // void generateBatches() + + + + + +btSoftBodyTriangleDataOpenCL::btSoftBodyTriangleDataOpenCL( cl_command_queue queue , cl_context ctx) : + m_queue( queue ), + m_clVertexIndices( queue, ctx, &m_vertexIndices, false ), + m_clArea( queue, ctx, &m_area, false ), + m_clNormal( queue, ctx, &m_normal, false ) +{ +} + +btSoftBodyTriangleDataOpenCL::~btSoftBodyTriangleDataOpenCL() +{ +} + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyTriangleDataOpenCL::createTriangles( int numTriangles ) +{ + int previousSize = getNumTriangles(); + int newSize = previousSize + numTriangles; + + btSoftBodyTriangleData::createTriangles( numTriangles ); + + // Resize the link addresses array as well + m_triangleAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyTriangleDataOpenCL::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ) +{ + btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex ); + + m_triangleAddresses[triangleIndex] = triangleIndex; +} + +bool btSoftBodyTriangleDataOpenCL::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyTriangleDataOpenCL::moveToAccelerator() +{ + bool success = true; + success = success && m_clVertexIndices.moveToGPU(); + success = success && m_clArea.moveToGPU(); + success = success && m_clNormal.moveToGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +bool btSoftBodyTriangleDataOpenCL::moveFromAccelerator() +{ + bool success = true; + success = success && m_clVertexIndices.moveFromGPU(); + success = success && m_clArea.moveFromGPU(); + success = success && m_clNormal.moveFromGPU(); + + if( success ) + m_onGPU = true; + + return success; +} + +/** + * Generate (and later update) the batching for the entire triangle set. + * This redoes a lot of work because it batches the entire set when each cloth is inserted. + * In theory we could delay it until just before we need the cloth. + * It's a one-off overhead, though, so that is a later optimisation. + */ +void btSoftBodyTriangleDataOpenCL::generateBatches() +{ + int numTriangles = getNumTriangles(); + if( numTriangles == 0 ) + return; + + // Do the graph colouring here temporarily + btAlignedObjectArray< int > batchValues; + batchValues.resize( numTriangles ); + + // Find the maximum vertex value internally for now + int maxVertex = 0; + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + int vertex0 = getVertexSet(triangleIndex).vertex0; + int vertex1 = getVertexSet(triangleIndex).vertex1; + int vertex2 = getVertexSet(triangleIndex).vertex2; + + if( vertex0 > maxVertex ) + maxVertex = vertex0; + if( vertex1 > maxVertex ) + maxVertex = vertex1; + if( vertex2 > maxVertex ) + maxVertex = vertex2; + } + int numVertices = maxVertex + 1; + + // Set of lists, one for each node, specifying which colours are connected + // to that node. + // No two edges into a node can share a colour. + btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; + vertexConnectedColourLists.resize(numVertices); + + + //std::cout << "\n"; + // Simple algorithm that chooses the lowest batch number + // that none of the faces attached to either of the connected + // nodes is in + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + int vertex0 = getVertexSet(triangleLocation).vertex0; + int vertex1 = getVertexSet(triangleLocation).vertex1; + int vertex2 = getVertexSet(triangleLocation).vertex2; + + // Get the three node colour lists + btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); + btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); + btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] ); + + // Choose the minimum colour that is in none of the lists + int colour = 0; + while( + colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || + colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() || + colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() ) + { + ++colour; + } + // i should now be the minimum colour in neither list + // Add to the three lists so that future edges don't share + // And store the colour against this face + colourListVertex0.push_back(colour); + colourListVertex1.push_back(colour); + colourListVertex2.push_back(colour); + + batchValues[triangleIndex] = colour; + } + + + // Check the colour counts + btAlignedObjectArray< int > batchCounts; + for( int i = 0; i < numTriangles; ++i ) + { + int batch = batchValues[i]; + if( batch >= batchCounts.size() ) + batchCounts.push_back(1); + else + ++(batchCounts[batch]); + } + + + m_batchStartLengths.resize(batchCounts.size()); + m_batchStartLengths[0] = btSomePair(0,0); + + + int sum = 0; + for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) + { + m_batchStartLengths[batchIndex].first = sum; + m_batchStartLengths[batchIndex].second = batchCounts[batchIndex]; + sum += batchCounts[batchIndex]; + } + + ///////////////////////////// + // Sort data based on batches + + // Create source arrays by copying originals + btAlignedObjectArray m_vertexIndices_Backup(m_vertexIndices); + btAlignedObjectArray m_area_Backup(m_area); + btAlignedObjectArray m_normal_Backup(m_normal); + + + for( int batch = 0; batch < batchCounts.size(); ++batch ) + batchCounts[batch] = 0; + + // Do sort as single pass into destination arrays + for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) + { + // To maintain locations run off the original link locations rather than the current position. + // It's not cache efficient, but as we run this rarely that should not matter. + // It's faster than searching the link location array for the current location and then updating it. + // The other alternative would be to unsort before resorting, but this is equivalent to doing that. + int triangleLocation = m_triangleAddresses[triangleIndex]; + + // Obtain batch and calculate target location for the + // next element in that batch, incrementing the batch counter + // afterwards + int batch = batchValues[triangleIndex]; + int newLocation = m_batchStartLengths[batch].first + batchCounts[batch]; + + batchCounts[batch] = batchCounts[batch] + 1; + m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation]; + m_area[newLocation] = m_area_Backup[triangleLocation]; + m_normal[newLocation] = m_normal_Backup[triangleLocation]; + + // Update the locations array to account for the moved entry + m_triangleAddresses[triangleIndex] = newLocation; + } +} // btSoftBodyTriangleDataOpenCL::generateBatches + + + + + + + +btOpenCLSoftBodySolver::btOpenCLSoftBodySolver(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) : + m_linkData(queue, ctx), + m_vertexData(queue, ctx), + m_triangleData(queue, ctx), + m_defaultCLFunctions(queue, ctx), + m_currentCLFunctions(&m_defaultCLFunctions), + m_clPerClothAcceleration(queue, ctx, &m_perClothAcceleration, true ), + m_clPerClothWindVelocity(queue, ctx, &m_perClothWindVelocity, true ), + m_clPerClothDampingFactor(queue,ctx, &m_perClothDampingFactor, true ), + m_clPerClothVelocityCorrectionCoefficient(queue, ctx,&m_perClothVelocityCorrectionCoefficient, true ), + m_clPerClothLiftFactor(queue, ctx,&m_perClothLiftFactor, true ), + m_clPerClothDragFactor(queue, ctx,&m_perClothDragFactor, true ), + m_clPerClothMediumDensity(queue, ctx,&m_perClothMediumDensity, true ), + m_clPerClothCollisionObjects( queue, ctx, &m_perClothCollisionObjects, true ), + m_clCollisionObjectDetails( queue, ctx, &m_collisionObjectDetails, true ), + m_clPerClothFriction( queue, ctx, &m_perClothFriction, false ), + m_clAnchorPosition( queue, ctx, &m_anchorPosition, true ), + m_clAnchorIndex( queue, ctx, &m_anchorIndex, true), + m_cqCommandQue( queue ), + m_cxMainContext(ctx), + m_defaultWorkGroupSize(BT_DEFAULT_WORKGROUPSIZE), + m_bUpdateAnchoredNodePos(bUpdateAchchoredNodePos) +{ + + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; + + m_prepareLinksKernel = 0; + m_solvePositionsFromLinksKernel = 0; + m_updateConstantsKernel = 0; + m_integrateKernel = 0; + m_addVelocityKernel = 0; + m_updatePositionsFromVelocitiesKernel = 0; + m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = 0; + m_updateVelocitiesFromPositionsWithVelocitiesKernel = 0; + m_vSolveLinksKernel = 0; + m_solveCollisionsAndUpdateVelocitiesKernel = 0; + m_resetNormalsAndAreasKernel = 0; + m_updateSoftBodiesKernel = 0; + m_normalizeNormalsAndAreasKernel = 0; + m_outputToVertexArrayKernel = 0; + m_applyForcesKernel = 0; + m_updateFixedVertexPositionsKernel = 0; +} + +btOpenCLSoftBodySolver::~btOpenCLSoftBodySolver() +{ + releaseKernels(); +} + +void btOpenCLSoftBodySolver::releaseKernels() +{ + RELEASE_CL_KERNEL( m_prepareLinksKernel ); + RELEASE_CL_KERNEL( m_solvePositionsFromLinksKernel ); + RELEASE_CL_KERNEL( m_updateConstantsKernel ); + RELEASE_CL_KERNEL( m_integrateKernel ); + RELEASE_CL_KERNEL( m_addVelocityKernel ); + RELEASE_CL_KERNEL( m_updatePositionsFromVelocitiesKernel ); + RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithoutVelocitiesKernel ); + RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithVelocitiesKernel ); + RELEASE_CL_KERNEL( m_vSolveLinksKernel ); + RELEASE_CL_KERNEL( m_solveCollisionsAndUpdateVelocitiesKernel ); + RELEASE_CL_KERNEL( m_resetNormalsAndAreasKernel ); + RELEASE_CL_KERNEL( m_normalizeNormalsAndAreasKernel ); + RELEASE_CL_KERNEL( m_outputToVertexArrayKernel ); + RELEASE_CL_KERNEL( m_applyForcesKernel ); + RELEASE_CL_KERNEL( m_updateFixedVertexPositionsKernel ); + + m_shadersInitialized = false; +} + +void btOpenCLSoftBodySolver::copyBackToSoftBodies(bool bMove) +{ + + // Move the vertex data back to the host first + m_vertexData.moveFromAccelerator(!bMove); + + // Loop over soft bodies, copying all the vertex positions back for each body in turn + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btOpenCLAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ]; + btSoftBody *softBody = softBodyInterface->getSoftBody(); + + int firstVertex = softBodyInterface->getFirstVertex(); + int numVertices = softBodyInterface->getNumVertices(); + + // Copy vertices from solver back into the softbody + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + using Vectormath::Aos::Point3; + Point3 vertexPosition( m_vertexData.getVertexPositions()[firstVertex + vertex] ); + Point3 normal(m_vertexData.getNormal(firstVertex + vertex)); + + softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() ); + softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() ); + softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() ); + + softBody->m_nodes[vertex].m_n.setX( normal.getX() ); + softBody->m_nodes[vertex].m_n.setY( normal.getY() ); + softBody->m_nodes[vertex].m_n.setZ( normal.getZ() ); + } + } +} // btOpenCLSoftBodySolver::copyBackToSoftBodies + +void btOpenCLSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate ) +{ + if( forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + m_anchorIndex.clear(); + + int maxPiterations = 0; + int maxViterations = 0; + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btOpenCLAcceleratedSoftBodyInterface *newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothFriction.push_back(softBody->m_cfg.kDF); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + int maxVertices = numVertices; + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( maxVertices, softBodyIndex ); + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + + m_anchorIndex.push_back(-1); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); +// int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + + // Find maximum piterations and viterations + int piterations = softBody->m_cfg.piterations; + + if ( piterations > maxPiterations ) + maxPiterations = piterations; + + int viterations = softBody->m_cfg.viterations; + + if ( viterations > maxViterations ) + maxViterations = viterations; + + // zero mass + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + if ( softBody->m_nodes[vertex].m_im == 0 ) + { + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + vertex; + nodeInfo.pNode = &softBody->m_nodes[vertex]; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + + // anchor position + if ( numVertices > 0 ) + { + for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ ) + { + btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node; + btSoftBody::Node* firstNode = &softBody->m_nodes[0]; + + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode); + nodeInfo.pNode = anchorNode; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + } + + + m_anchorPosition.clear(); + m_anchorPosition.resize(m_anchorNodeInfoArray.size()); + + for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ ) + { + const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode]; + m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode; + getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f; + } + + updateConstants(0.f); + + // set position and velocity iterations + setNumberOfPositionIterations(maxPiterations); + setNumberOfVelocityIterations(maxViterations); + + // set wind velocity + m_perClothWindVelocity.resize( m_softBodySet.size() ); + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); + m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); + } + + m_clPerClothWindVelocity.changedOnCPU(); + + // generate batches + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + + // Build the shaders to match the batching parameters + buildShaders(); + } +} + + +btSoftBodyLinkData &btOpenCLSoftBodySolver::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + +btSoftBodyVertexData &btOpenCLSoftBodySolver::getVertexData() +{ + // TODO: Consider setting vertex data to "changed" here + return m_vertexData; +} + +btSoftBodyTriangleData &btOpenCLSoftBodySolver::getTriangleData() +{ + // TODO: Consider setting triangle data to "changed" here + return m_triangleData; +} + +void btOpenCLSoftBodySolver::resetNormalsAndAreas( int numVertices ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 0, sizeof(numVertices), (void*)&numVertices); //oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 1, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexNormal.m_buffer);//oclCHECKERROR(ciErrNum, CL_SUCCESS); + ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 2, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexArea.m_buffer); //oclCHECKERROR(ciErrNum, CL_SUCCESS); + size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_resetNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0 ); + + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_resetNormalsAndAreasKernel)" ); + } + } + +} + +void btOpenCLSoftBodySolver::normalizeNormalsAndAreas( int numVertices ) +{ + cl_int ciErrNum; + + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 0, sizeof(int),(void*) &numVertices); + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 1, sizeof(cl_mem), &m_vertexData.m_clVertexTriangleCount.m_buffer); + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); + ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); + size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_normalizeNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)"); + } + } + +} + +void btOpenCLSoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 0, sizeof(int), (void*) &firstTriangle); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 1, sizeof(int), &numTriangles); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 2, sizeof(cl_mem), &m_triangleData.m_clVertexIndices.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 6, sizeof(cl_mem), &m_triangleData.m_clNormal.m_buffer); + ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 7, sizeof(cl_mem), &m_triangleData.m_clArea.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((numTriangles + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_updateSoftBodiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)"); + } + +} + +void btOpenCLSoftBodySolver::updateSoftBodies() +{ + using namespace Vectormath::Aos; + + + int numVertices = m_vertexData.getNumVertices(); +// int numTriangles = m_triangleData.getNumTriangles(); + + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_triangleData.moveToAccelerator(); + + resetNormalsAndAreas( numVertices ); + + + // Go through triangle batches so updates occur correctly + for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex ) + { + + int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].first; + int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].second; + + executeUpdateSoftBodies( startTriangle, numTriangles ); + } + + + normalizeNormalsAndAreas( numVertices ); +} // updateSoftBodies + + +Vectormath::Aos::Vector3 btOpenCLSoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ) +{ + return a*Vectormath::Aos::dot(v, a); +} + +void btOpenCLSoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ) +{ + float dtInverseMass = solverdt*inverseMass; + if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) ) + { + vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass; + } else { + vertexForce += force; + } +} + +void btOpenCLSoftBodySolver::updateFixedVertexPositions() +{ + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_clAnchorPosition.moveToGPU(); + m_clAnchorIndex.moveToGPU(); + + cl_int ciErrNum ; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,1, sizeof(cl_mem), &m_clAnchorIndex.m_buffer); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,3, sizeof(cl_mem), &m_clAnchorPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateFixedVertexPositionsKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateFixedVertexPositionsKernel)"); + } + } + +} + +void btOpenCLSoftBodySolver::applyForces( float solverdt ) +{ + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + m_clPerClothAcceleration.moveToGPU(); + m_clPerClothLiftFactor.moveToGPU(); + m_clPerClothDragFactor.moveToGPU(); + m_clPerClothMediumDensity.moveToGPU(); + m_clPerClothWindVelocity.moveToGPU(); + + cl_int ciErrNum ; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 1, sizeof(float), &solverdt); + float fl = FLT_EPSILON; + ciErrNum = clSetKernelArg(m_applyForcesKernel, 2, sizeof(float), &fl); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 7, sizeof(cl_mem), &m_clPerClothLiftFactor.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 8 ,sizeof(cl_mem), &m_clPerClothDragFactor.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel, 9, sizeof(cl_mem), &m_clPerClothWindVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,10, sizeof(cl_mem), &m_clPerClothAcceleration.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,11, sizeof(cl_mem), &m_clPerClothMediumDensity.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,12, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); + ciErrNum = clSetKernelArg(m_applyForcesKernel,13, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_applyForcesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_applyForcesKernel)"); + } + } + +} + +/** + * Integrate motion on the solver. + */ +void btOpenCLSoftBodySolver::integrate( float solverdt ) +{ + // Ensure data is on accelerator + m_vertexData.moveToAccelerator(); + + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_integrateKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_integrateKernel, 1, sizeof(float), &solverdt); + ciErrNum = clSetKernelArg(m_integrateKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_integrateKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_integrateKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_integrateKernel)"); + } + } + +} + +float btOpenCLSoftBodySolver::computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ) +{ + Vectormath::Aos::Vector3 a = vertex1 - vertex0; + Vectormath::Aos::Vector3 b = vertex2 - vertex0; + Vectormath::Aos::Vector3 crossProduct = cross(a, b); + float area = length( crossProduct ); + return area; +} + + +void btOpenCLSoftBodySolver::updateBounds() +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btVector3 minBound(-1e30,-1e30,-1e30), maxBound(1e30,1e30,1e30); + m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound ); + } + +} // btOpenCLSoftBodySolver::updateBounds + + +void btOpenCLSoftBodySolver::updateConstants( float timeStep ) +{ + + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } + +} + +class QuickSortCompare +{ + public: + + bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const + { + return ( a.softBodyIdentifier < b.softBodyIdentifier ); + } +}; + + +/** + * Sort the collision object details array and generate indexing into it for the per-cloth collision object array. + */ +void btOpenCLSoftBodySolver::prepareCollisionConstraints() +{ + // First do a simple sort on the collision objects + btAlignedObjectArray numObjectsPerClothPrefixSum; + btAlignedObjectArray numObjectsPerCloth; + numObjectsPerCloth.resize( m_softBodySet.size(), 0 ); + numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 ); + + + + m_collisionObjectDetails.quickSort( QuickSortCompare() ); + + if (!m_perClothCollisionObjects.size()) + return; + + // Generating indexing for perClothCollisionObjects + // First clear the previous values with the "no collision object for cloth" constant + for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex ) + { + m_perClothCollisionObjects[clothIndex].firstObject = -1; + m_perClothCollisionObjects[clothIndex].endObject = -1; + } + int currentCloth = 0; + int startIndex = 0; + for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject ) + { + int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier; + if( nextCloth != currentCloth ) + { + // Changed cloth in the array + // Set the end index and the range is what we need for currentCloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = collisionObject; + currentCloth = nextCloth; + startIndex = collisionObject; + } + } + + // And update last cloth + m_perClothCollisionObjects[currentCloth].firstObject = startIndex; + m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size(); + +} // btOpenCLSoftBodySolver::prepareCollisionConstraints + + + +void btOpenCLSoftBodySolver::solveConstraints( float solverdt ) +{ + + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links +// int numLinks = m_linkData.getNumLinks(); +// int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothVelocityCorrectionCoefficient.moveToGPU(); + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + prepareLinks(); + + + + for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForVelocity( startLink, numLinks, kst ); + } + } + + + prepareCollisionConstraints(); + + // Compute new positions from velocity + // Also update the previous position so that our position computation is now based on the new position from the velocity solution + // rather than based directly on the original positions + if( m_numberOfVelocityIterations > 0 ) + { + updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt ); + } else { + updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt ); + } + + // Solve position + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) + { + int startLink = m_linkData.m_batchStartLengths[i].start; + int numLinks = m_linkData.m_batchStartLengths[i].length; + + solveLinksForPosition( startLink, numLinks, kst, ti ); + } + + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); + +} + + +////////////////////////////////////// +// Kernel dispatches +void btOpenCLSoftBodySolver::prepareLinks() +{ + cl_int ciErrNum; + int numLinks = m_linkData.getNumLinks(); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,0, sizeof(int), &numLinks); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,1, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,2, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer); + ciErrNum = clSetKernelArg(m_prepareLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_linkData.getNumLinks() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_prepareLinksKernel, 1 , NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_prepareLinksKernel)"); + } + +} + +void btOpenCLSoftBodySolver::updatePositionsFromVelocities( float solverdt ) +{ + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,1, sizeof(float), &solverdt); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,4, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updatePositionsFromVelocitiesKernel, 1, NULL, &numWorkItems,&m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updatePositionsFromVelocitiesKernel)"); + } + +} + +void btOpenCLSoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startLink); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numLinks); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&m_defaultWorkGroupSize,0,0,0); + if( ciErrNum!= CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)"); + } + +} // solveLinksForPosition + + +void btOpenCLSoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 0, sizeof(int), &startLink); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 1, sizeof(int), &numLinks); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 2, sizeof(float), &kst); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 3, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_vSolveLinksKernel,1,NULL,&numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_vSolveLinksKernel)"); + } + +} + +void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt ) +{ + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel,0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, sizeof(float), &isolverdt); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 5, sizeof(cl_mem), &m_clPerClothVelocityCorrectionCoefficient.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 6, sizeof(cl_mem), &m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 8, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithVelocitiesKernel)"); + } + + +} // updateVelocitiesFromPositionsWithVelocities + +void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ) +{ + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, sizeof(float), &isolverdt); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 4, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 6, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 7, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)"); + } + +} // updateVelocitiesFromPositionsWithoutVelocities + + + +void btOpenCLSoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + m_vertexData.moveToAccelerator(); + m_clPerClothFriction.moveToGPU(); + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothCollisionObjects.moveToGPU(); + m_clCollisionObjectDetails.moveToGPU(); + + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); + + size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)"); + } + } + +} // btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities + + + +// End kernel dispatches +///////////////////////////////////// + + +void btSoftBodySolverOutputCLtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + + btSoftBodySolver *solver = softBody->getSoftBodySolver(); + btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); + btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); + + btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); + btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); + + + const int firstVertex = currentCloth->getFirstVertex(); + const int lastVertex = firstVertex + currentCloth->getNumVertices(); + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); + float *basePointer = cpuVertexBuffer->getBasePointer(); + + vertexData.m_clVertexPosition.copyFromGPU(); + vertexData.m_clVertexNormal.copyFromGPU(); + + if( vertexBuffer->hasVertexPositions() ) + { + const int vertexOffset = cpuVertexBuffer->getVertexOffset(); + const int vertexStride = cpuVertexBuffer->getVertexStride(); + float *vertexPointer = basePointer + vertexOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex); + *(vertexPointer + 0) = position.getX(); + *(vertexPointer + 1) = position.getY(); + *(vertexPointer + 2) = position.getZ(); + vertexPointer += vertexStride; + } + } + if( vertexBuffer->hasNormals() ) + { + const int normalOffset = cpuVertexBuffer->getNormalOffset(); + const int normalStride = cpuVertexBuffer->getNormalStride(); + float *normalPointer = basePointer + normalOffset; + + for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) + { + Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex); + *(normalPointer + 0) = normal.getX(); + *(normalPointer + 1) = normal.getY(); + *(normalPointer + 2) = normal.getZ(); + normalPointer += normalStride; + } + } + } + +} // btSoftBodySolverOutputCLtoCPU::outputToVertexBuffers + + + +cl_kernel CLFunctions::compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros ,const char* orgSrcFileNameForCaching) +{ + printf("compiling kernelName: %s ",kernelName); + cl_kernel kernel=0; + cl_int ciErrNum; + size_t program_length = strlen(kernelSource); + + cl_program m_cpProgram = clCreateProgramWithSource(m_cxMainContext, 1, (const char**)&kernelSource, &program_length, &ciErrNum); +// oclCHECKERROR(ciErrNum, CL_SUCCESS); + + // Build the program with 'mad' Optimization option + + +#ifdef MAC + char* flags = "-cl-mad-enable -DMAC -DGUID_ARG"; +#else + //const char* flags = "-DGUID_ARG= -fno-alias"; + const char* flags = "-DGUID_ARG= "; +#endif + + char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5]; + sprintf(compileFlags, "%s %s", flags, additionalMacros); + ciErrNum = clBuildProgram(m_cpProgram, 0, NULL, compileFlags, NULL, NULL); + if (ciErrNum != CL_SUCCESS) + { + size_t numDevices; + clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, 0, 0, &numDevices ); + cl_device_id *devices = new cl_device_id[numDevices]; + clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, numDevices, devices, &numDevices ); + for( int i = 0; i < 2; ++i ) + { + char *build_log; + size_t ret_val_size; + clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); + build_log = new char[ret_val_size+1]; + clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); + + // to be carefully, terminate with \0 + // there's no information in the reference whether the string is 0 terminated or not + build_log[ret_val_size] = '\0'; + + + printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log); + delete[] build_log; + } +#ifndef BT_SUPPRESS_OPENCL_ASSERTS + btAssert(0); +#endif //BT_SUPPRESS_OPENCL_ASSERTS + m_kernelCompilationFailures++; + return 0; + } + + + // Create the kernel + kernel = clCreateKernel(m_cpProgram, kernelName, &ciErrNum); + if (ciErrNum != CL_SUCCESS) + { + const char* msg = ""; + switch(ciErrNum) + { + case CL_INVALID_PROGRAM: + msg = "Program is not a valid program object."; + break; + case CL_INVALID_PROGRAM_EXECUTABLE: + msg = "There is no successfully built executable for program."; + break; + case CL_INVALID_KERNEL_NAME: + msg = "kernel_name is not found in program."; + break; + case CL_INVALID_KERNEL_DEFINITION: + msg = "the function definition for __kernel function given by kernel_name such as the number of arguments, the argument types are not the same for all devices for which the program executable has been built."; + break; + case CL_INVALID_VALUE: + msg = "kernel_name is NULL."; + break; + case CL_OUT_OF_HOST_MEMORY: + msg = "Failure to allocate resources required by the OpenCL implementation on the host."; + break; + default: + { + } + } + + printf("Error in clCreateKernel for kernel '%s', error is \"%s\", Line %u in file %s !!!\n\n", kernelName, msg, __LINE__, __FILE__); + +#ifndef BT_SUPPRESS_OPENCL_ASSERTS + btAssert(0); +#endif //BT_SUPPRESS_OPENCL_ASSERTS + m_kernelCompilationFailures++; + return 0; + } + + printf("ready. \n"); + delete [] compileFlags; + if (!kernel) + m_kernelCompilationFailures++; + return kernel; + +} + +void btOpenCLSoftBodySolver::predictMotion( float timeStep ) +{ + // Clear the collision shape array for the next frame + // Ensure that the DX11 ones are moved off the device so they will be updated correctly + m_clCollisionObjectDetails.changedOnCPU(); + m_clPerClothCollisionObjects.changedOnCPU(); + m_collisionObjectDetails.clear(); + + if ( m_bUpdateAnchoredNodePos ) + { + // In OpenCL cloth solver, if softbody node has zero inverse mass(infinite mass) or anchor attached, + // we need to update the node position in case the node or anchor is animated externally. + // If there is no such node, we can eliminate the unnecessary CPU-to-GPU data trasferring. + for ( int i = 0; i < m_anchorNodeInfoArray.size(); i++ ) + { + const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[i]; + btSoftBody::Node* node = anchorNodeInfo.pNode; + + using Vectormath::Aos::Point3; + Point3 pos((float)node->m_x.getX(), (float)node->m_x.getY(), (float)node->m_x.getZ()); + m_anchorPosition[i] = pos; + } + + if ( m_anchorNodeInfoArray.size() > 0 ) + m_clAnchorPosition.changedOnCPU(); + + updateFixedVertexPositions(); + } + + { + BT_PROFILE("applyForces"); + // Apply forces that we know about to the cloths + applyForces( timeStep * getTimeScale() ); + } + + { + BT_PROFILE("integrate"); + // Itegrate motion for all soft bodies dealt with by the solver + integrate( timeStep * getTimeScale() ); + } + + { + BT_PROFILE("updateBounds"); + updateBounds(); + } + // End prediction work for solvers +} + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + +void btOpenCLAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ) +{ + float scalarMargin = (float)getSoftBody()->getCollisionShape()->getMargin(); + btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin ); + m_softBody->m_bounds[0] = lowerBound - vectorMargin; + m_softBody->m_bounds[1] = upperBound + vectorMargin; +} // btOpenCLSoftBodySolver::btDX11AcceleratedSoftBodyInterface::updateBounds + +void btOpenCLSoftBodySolver::processCollision( btSoftBody*, btSoftBody* ) +{ + +} + +// Add the collision object to the set to deal with for a particular soft body +void btOpenCLSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObject ) +{ + int softBodyIndex = findSoftBodyIndex( softBody ); + + if( softBodyIndex >= 0 ) + { + const btCollisionShape *collisionShape = collisionObject->getCollisionShape(); + float friction = collisionObject->getCollisionObject()->getFriction(); + int shapeType = collisionShape->getShapeType(); + if( shapeType == CAPSULE_SHAPE_PROXYTYPE ) + { + // Add to the list of expected collision objects + CollisionShapeDescription newCollisionShapeDescription; + newCollisionShapeDescription.softBodyIdentifier = softBodyIndex; + newCollisionShapeDescription.collisionShapeType = shapeType; + // TODO: May need to transpose this matrix either here or in HLSL + newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform()); + const btCapsuleShape *capsule = static_cast( collisionShape ); + newCollisionShapeDescription.radius = capsule->getRadius(); + newCollisionShapeDescription.halfHeight = capsule->getHalfHeight(); + newCollisionShapeDescription.margin = capsule->getMargin(); + newCollisionShapeDescription.upAxis = capsule->getUpAxis(); + newCollisionShapeDescription.friction = friction; + const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() ); + newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity()); + newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity()); + m_collisionObjectDetails.push_back( newCollisionShapeDescription ); + + } + else { +#ifdef _DEBUG + printf("Unsupported collision shape type\n"); +#endif + //btAssert(0 && "Unsupported collision shape type\n"); + } + } else { + btAssert(0 && "Unknown soft body"); + } +} // btOpenCLSoftBodySolver::processCollision + + + + + +btOpenCLAcceleratedSoftBodyInterface* btOpenCLSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyInterface; + } + return 0; +} + + +int btOpenCLSoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody ) +{ + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex]; + if( softBodyInterface->getSoftBody() == softBody ) + return softBodyIndex; + } + return 1; +} + +bool btOpenCLSoftBodySolver::checkInitialized() +{ + if( !m_shadersInitialized ) + if( buildShaders() ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + +bool btOpenCLSoftBodySolver::buildShaders() +{ + if( m_shadersInitialized ) + return true; + + const char* additionalMacros=""; + + // Ensure current kernels are released first + releaseKernels(); + + m_currentCLFunctions->clearKernelCompilationFailures(); + + m_prepareLinksKernel = m_currentCLFunctions->compileCLKernelFromString( PrepareLinksCLString, "PrepareLinksKernel",additionalMacros,"OpenCLC10/PrepareLinks.cl" ); + m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl"); + m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel",additionalMacros,"OpenCLC10/SolvePositions.cl" ); + m_vSolveLinksKernel = m_currentCLFunctions->compileCLKernelFromString( VSolveLinksCLString, "VSolveLinksKernel" ,additionalMacros,"OpenCLC10/VSolveLinks.cl"); + m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdateNodes.cl"); + m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositions.cl"); + m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel" ,additionalMacros,"OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"); + m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel" ,additionalMacros,"OpenCLC10/Integrate.cl"); + m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel" ,additionalMacros,"OpenCLC10/ApplyForces.cl"); + m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" , additionalMacros, "OpenCLC10/UpdateFixedVertexPositions.cl"); + + // TODO: Rename to UpdateSoftBodies + m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); + m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); + m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); + + + if( m_currentCLFunctions->getKernelCompilationFailures()==0 ) + m_shadersInitialized = true; + + return m_shadersInitialized; +} + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h new file mode 100644 index 00000000..6de58c4f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h @@ -0,0 +1,527 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_OPENCL_H +#define BT_SOFT_BODY_SOLVER_OPENCL_H + +#include "stddef.h" //for size_t +#include "vectormath/vmInclude.h" + +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "BulletSoftBody/btSoftBody.h" +#include "btSoftBodySolverBuffer_OpenCL.h" +#include "btSoftBodySolverLinkData_OpenCL.h" +#include "btSoftBodySolverVertexData_OpenCL.h" +#include "btSoftBodySolverTriangleData_OpenCL.h" + +class CLFunctions +{ +protected: + cl_command_queue m_cqCommandQue; + cl_context m_cxMainContext; + + int m_kernelCompilationFailures; + + +public: + CLFunctions(cl_command_queue cqCommandQue, cl_context cxMainContext) : + m_cqCommandQue( cqCommandQue ), + m_cxMainContext( cxMainContext ), + m_kernelCompilationFailures(0) + { + } + + int getKernelCompilationFailures() const + { + return m_kernelCompilationFailures; + } + + /** + * Compile a compute shader kernel from a string and return the appropriate cl_kernel object. + */ + virtual cl_kernel compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros, const char* srcFileNameForCaching); + + void clearKernelCompilationFailures() + { + m_kernelCompilationFailures=0; + } +}; + +/** + * Entry in the collision shape array. + * Specifies the shape type, the transform matrix and the necessary details of the collisionShape. + */ +struct CollisionShapeDescription +{ + Vectormath::Aos::Transform3 shapeTransform; + Vectormath::Aos::Vector3 linearVelocity; + Vectormath::Aos::Vector3 angularVelocity; + + int softBodyIdentifier; + int collisionShapeType; + + // Both needed for capsule + float radius; + float halfHeight; + int upAxis; + + float margin; + float friction; + + CollisionShapeDescription() + { + collisionShapeType = 0; + margin = 0; + friction = 0; + } +}; + +/** + * SoftBody class to maintain information about a soft body instance + * within a solver. + * This data addresses the main solver arrays. + */ +class btOpenCLAcceleratedSoftBodyInterface +{ +protected: + /** Current number of vertices that are part of this cloth */ + int m_numVertices; + /** Maximum number of vertices allocated to be part of this cloth */ + int m_maxVertices; + /** Current number of triangles that are part of this cloth */ + int m_numTriangles; + /** Maximum number of triangles allocated to be part of this cloth */ + int m_maxTriangles; + /** Index of first vertex in the world allocated to this cloth */ + int m_firstVertex; + /** Index of first triangle in the world allocated to this cloth */ + int m_firstTriangle; + /** Index of first link in the world allocated to this cloth */ + int m_firstLink; + /** Maximum number of links allocated to this cloth */ + int m_maxLinks; + /** Current number of links allocated to this cloth */ + int m_numLinks; + + /** The actual soft body this data represents */ + btSoftBody *m_softBody; + + +public: + btOpenCLAcceleratedSoftBodyInterface( btSoftBody *softBody ) : + m_softBody( softBody ) + { + m_numVertices = 0; + m_maxVertices = 0; + m_numTriangles = 0; + m_maxTriangles = 0; + m_firstVertex = 0; + m_firstTriangle = 0; + m_firstLink = 0; + m_maxLinks = 0; + m_numLinks = 0; + } + int getNumVertices() + { + return m_numVertices; + } + + int getNumTriangles() + { + return m_numTriangles; + } + + int getMaxVertices() + { + return m_maxVertices; + } + + int getMaxTriangles() + { + return m_maxTriangles; + } + + int getFirstVertex() + { + return m_firstVertex; + } + + int getFirstTriangle() + { + return m_firstTriangle; + } + + /** + * Update the bounds in the btSoftBody object + */ + void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ); + + // TODO: All of these set functions will have to do checks and + // update the world because restructuring of the arrays will be necessary + // Reasonable use of "friend"? + void setNumVertices( int numVertices ) + { + m_numVertices = numVertices; + } + + void setNumTriangles( int numTriangles ) + { + m_numTriangles = numTriangles; + } + + void setMaxVertices( int maxVertices ) + { + m_maxVertices = maxVertices; + } + + void setMaxTriangles( int maxTriangles ) + { + m_maxTriangles = maxTriangles; + } + + void setFirstVertex( int firstVertex ) + { + m_firstVertex = firstVertex; + } + + void setFirstTriangle( int firstTriangle ) + { + m_firstTriangle = firstTriangle; + } + + void setMaxLinks( int maxLinks ) + { + m_maxLinks = maxLinks; + } + + void setNumLinks( int numLinks ) + { + m_numLinks = numLinks; + } + + void setFirstLink( int firstLink ) + { + m_firstLink = firstLink; + } + + int getMaxLinks() + { + return m_maxLinks; + } + + int getNumLinks() + { + return m_numLinks; + } + + int getFirstLink() + { + return m_firstLink; + } + + btSoftBody* getSoftBody() + { + return m_softBody; + } + +}; + + + +class btOpenCLSoftBodySolver : public btSoftBodySolver +{ +public: + + + struct UIntVector3 + { + UIntVector3() + { + x = 0; + y = 0; + z = 0; + _padding = 0; + } + + UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ ) + { + x = x_; + y = y_; + z = z_; + _padding = 0; + } + + unsigned int x; + unsigned int y; + unsigned int z; + unsigned int _padding; + }; + + struct CollisionObjectIndices + { + CollisionObjectIndices( int f, int e ) + { + firstObject = f; + endObject = e; + } + + int firstObject; + int endObject; + }; + + btSoftBodyLinkDataOpenCL m_linkData; + btSoftBodyVertexDataOpenCL m_vertexData; + btSoftBodyTriangleDataOpenCL m_triangleData; + +protected: + + CLFunctions m_defaultCLFunctions; + CLFunctions* m_currentCLFunctions; + + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + bool m_shadersInitialized; + + /** + * Cloths owned by this solver. + * Only our cloths are in this array. + */ + btAlignedObjectArray< btOpenCLAcceleratedSoftBodyInterface * > m_softBodySet; + + /** Acceleration value to be applied to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration; + btOpenCLBuffer m_clPerClothAcceleration; + + /** Wind velocity to be applied normal to all non-static vertices in the solver. + * Index n is cloth n, array sized by number of cloths in the world not the solver. + */ + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity; + btOpenCLBuffer m_clPerClothWindVelocity; + + /** Velocity damping factor */ + btAlignedObjectArray< float > m_perClothDampingFactor; + btOpenCLBuffer m_clPerClothDampingFactor; + + /** Velocity correction coefficient */ + btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient; + btOpenCLBuffer m_clPerClothVelocityCorrectionCoefficient; + + /** Lift parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothLiftFactor; + btOpenCLBuffer m_clPerClothLiftFactor; + + /** Drag parameter for wind effect on cloth. */ + btAlignedObjectArray< float > m_perClothDragFactor; + btOpenCLBuffer m_clPerClothDragFactor; + + /** Density of the medium in which each cloth sits */ + btAlignedObjectArray< float > m_perClothMediumDensity; + btOpenCLBuffer m_clPerClothMediumDensity; + + /** + * Collision shape details: pair of index of first collision shape for the cloth and number of collision objects. + */ + btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects; + btOpenCLBuffer m_clPerClothCollisionObjects; + + /** + * Collision shapes being passed across to the cloths in this solver. + */ + btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails; + btOpenCLBuffer< CollisionShapeDescription > m_clCollisionObjectDetails; + + + + /** + * Friction coefficient for each cloth + */ + btAlignedObjectArray< float > m_perClothFriction; + btOpenCLBuffer< float > m_clPerClothFriction; + + // anchor node info + struct AnchorNodeInfoCL + { + int clVertexIndex; + btSoftBody::Node* pNode; + }; + + btAlignedObjectArray m_anchorNodeInfoArray; + btAlignedObjectArray m_anchorPosition; + btOpenCLBuffer m_clAnchorPosition; + btAlignedObjectArray m_anchorIndex; + btOpenCLBuffer m_clAnchorIndex; + + bool m_bUpdateAnchoredNodePos; + + cl_kernel m_prepareLinksKernel; + cl_kernel m_solvePositionsFromLinksKernel; + cl_kernel m_updateConstantsKernel; + cl_kernel m_integrateKernel; + cl_kernel m_addVelocityKernel; + cl_kernel m_updatePositionsFromVelocitiesKernel; + cl_kernel m_updateVelocitiesFromPositionsWithoutVelocitiesKernel; + cl_kernel m_updateVelocitiesFromPositionsWithVelocitiesKernel; + cl_kernel m_vSolveLinksKernel; + cl_kernel m_solveCollisionsAndUpdateVelocitiesKernel; + cl_kernel m_resetNormalsAndAreasKernel; + cl_kernel m_normalizeNormalsAndAreasKernel; + cl_kernel m_updateSoftBodiesKernel; + + cl_kernel m_outputToVertexArrayKernel; + cl_kernel m_applyForcesKernel; + cl_kernel m_updateFixedVertexPositionsKernel; + + cl_command_queue m_cqCommandQue; + cl_context m_cxMainContext; + + size_t m_defaultWorkGroupSize; + + + virtual bool buildShaders(); + + void resetNormalsAndAreas( int numVertices ); + + void normalizeNormalsAndAreas( int numVertices ); + + void executeUpdateSoftBodies( int firstTriangle, int numTriangles ); + + void prepareCollisionConstraints(); + + Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ); + + void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ); + + + int findSoftBodyIndex( const btSoftBody* const softBody ); + + virtual void applyForces( float solverdt ); + + void updateFixedVertexPositions(); + + /** + * Integrate motion on the solver. + */ + virtual void integrate( float solverdt ); + + virtual void updateConstants( float timeStep ); + + float computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ); + + + ////////////////////////////////////// + // Kernel dispatches + void prepareLinks(); + + void solveLinksForVelocity( int startLink, int numLinks, float kst ); + + void updatePositionsFromVelocities( float solverdt ); + + virtual void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + + void updateVelocitiesFromPositionsWithVelocities( float isolverdt ); + + void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ); + virtual void solveCollisionsAndUpdateVelocities( float isolverdt ); + + // End kernel dispatches + ///////////////////////////////////// + + void updateBounds(); + + void releaseKernels(); + +public: + btOpenCLSoftBodySolver(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false); + + virtual ~btOpenCLSoftBodySolver(); + + + + btOpenCLAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody ); + + virtual btSoftBodyLinkData &getLinkData(); + + virtual btSoftBodyVertexData &getVertexData(); + + virtual btSoftBodyTriangleData &getTriangleData(); + + virtual SolverTypes getSolverType() const + { + return CL_SOLVER; + } + + + virtual bool checkInitialized(); + + virtual void updateSoftBodies( ); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void copyBackToSoftBodies(bool bMove = true); + + virtual void solveConstraints( float solverdt ); + + virtual void predictMotion( float solverdt ); + + virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* ); + + virtual void processCollision( btSoftBody*, btSoftBody* ); + + virtual void setDefaultWorkgroupSize(size_t workGroupSize) + { + m_defaultWorkGroupSize = workGroupSize; + } + virtual size_t getDefaultWorkGroupSize() const + { + return m_defaultWorkGroupSize; + } + + void setCLFunctions(CLFunctions* funcs) + { + if (funcs) + m_currentCLFunctions = funcs; + else + m_currentCLFunctions = &m_defaultCLFunctions; + } + +}; // btOpenCLSoftBodySolver + + +/** + * Class to manage movement of data from a solver to a given target. + * This version is the CL to CPU version. + */ +class btSoftBodySolverOutputCLtoCPU : public btSoftBodySolverOutput +{ +protected: + +public: + btSoftBodySolverOutputCLtoCPU() + { + } + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); +}; + + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp new file mode 100644 index 00000000..0380a6dd --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp @@ -0,0 +1,1101 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" +#include //@todo: remove the debugging printf at some stage +#include "btSoftBodySolver_OpenCLSIMDAware.h" +#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" +#include "BulletSoftBody/btSoftBody.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include + +#define WAVEFRONT_SIZE 32 +#define WAVEFRONT_BLOCK_MULTIPLIER 2 +#define GROUP_SIZE (WAVEFRONT_SIZE*WAVEFRONT_BLOCK_MULTIPLIER) +#define LINKS_PER_SIMD_LANE 16 + +static const size_t workGroupSize = GROUP_SIZE; + + +//CL_VERSION_1_1 seems broken on NVidia SDK so just disable it + +////OpenCL 1.0 kernels don't use float3 +#define MSTRINGIFY(A) #A +static const char* UpdatePositionsFromVelocitiesCLString = +#include "OpenCLC10/UpdatePositionsFromVelocities.cl" +static const char* SolvePositionsCLString = +#include "OpenCLC10/SolvePositionsSIMDBatched.cl" +static const char* UpdateNodesCLString = +#include "OpenCLC10/UpdateNodes.cl" +static const char* UpdatePositionsCLString = +#include "OpenCLC10/UpdatePositions.cl" +static const char* UpdateConstantsCLString = +#include "OpenCLC10/UpdateConstants.cl" +static const char* IntegrateCLString = +#include "OpenCLC10/Integrate.cl" +static const char* ApplyForcesCLString = +#include "OpenCLC10/ApplyForces.cl" +static const char* UpdateFixedVertexPositionsCLString = +#include "OpenCLC10/UpdateFixedVertexPositions.cl" +static const char* UpdateNormalsCLString = +#include "OpenCLC10/UpdateNormals.cl" +static const char* VSolveLinksCLString = +#include "OpenCLC10/VSolveLinks.cl" +static const char* SolveCollisionsAndUpdateVelocitiesCLString = +#include "OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl" +static const char* OutputToVertexArrayCLString = +#include "OpenCLC10/OutputToVertexArray.cl" + + + +btSoftBodyLinkDataOpenCLSIMDAware::btSoftBodyLinkDataOpenCLSIMDAware(cl_command_queue queue, cl_context ctx) : + m_cqCommandQue(queue), + m_wavefrontSize( WAVEFRONT_SIZE ), + m_linksPerWorkItem( LINKS_PER_SIMD_LANE ), + m_maxBatchesWithinWave( 0 ), + m_maxLinksPerWavefront( m_wavefrontSize * m_linksPerWorkItem ), + m_numWavefronts( 0 ), + m_maxVertex( 0 ), + m_clNumBatchesAndVerticesWithinWaves( queue, ctx, &m_numBatchesAndVerticesWithinWaves, true ), + m_clWavefrontVerticesGlobalAddresses( queue, ctx, &m_wavefrontVerticesGlobalAddresses, true ), + m_clLinkVerticesLocalAddresses( queue, ctx, &m_linkVerticesLocalAddresses, true ), + m_clLinkStrength( queue, ctx, &m_linkStrength, false ), + m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ), + m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ), + m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ), + m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false ) +{ +} + +btSoftBodyLinkDataOpenCLSIMDAware::~btSoftBodyLinkDataOpenCLSIMDAware() +{ +} + +static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) +{ + Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); + return outVec; +} + +/** Allocate enough space in all link-related arrays to fit numLinks links */ +void btSoftBodyLinkDataOpenCLSIMDAware::createLinks( int numLinks ) +{ + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + btSoftBodyLinkData::createLinks( numLinks ); + + // Resize the link addresses array as well + m_linkAddresses.resize( newSize ); +} + +/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ +void btSoftBodyLinkDataOpenCLSIMDAware::setLinkAt( + const LinkDescription &link, + int linkIndex ) +{ + btSoftBodyLinkData::setLinkAt( link, linkIndex ); + + if( link.getVertex0() > m_maxVertex ) + m_maxVertex = link.getVertex0(); + if( link.getVertex1() > m_maxVertex ) + m_maxVertex = link.getVertex1(); + + // Set the link index correctly for initialisation + m_linkAddresses[linkIndex] = linkIndex; +} + +bool btSoftBodyLinkDataOpenCLSIMDAware::onAccelerator() +{ + return m_onGPU; +} + +bool btSoftBodyLinkDataOpenCLSIMDAware::moveToAccelerator() +{ + bool success = true; + success = success && m_clNumBatchesAndVerticesWithinWaves.moveToGPU(); + success = success && m_clWavefrontVerticesGlobalAddresses.moveToGPU(); + success = success && m_clLinkVerticesLocalAddresses.moveToGPU(); + success = success && m_clLinkStrength.moveToGPU(); + success = success && m_clLinksMassLSC.moveToGPU(); + success = success && m_clLinksRestLengthSquared.moveToGPU(); + success = success && m_clLinksRestLength.moveToGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU(); + + if( success ) { + m_onGPU = true; + } + + return success; +} + +bool btSoftBodyLinkDataOpenCLSIMDAware::moveFromAccelerator() +{ + bool success = true; + success = success && m_clNumBatchesAndVerticesWithinWaves.moveToGPU(); + success = success && m_clWavefrontVerticesGlobalAddresses.moveToGPU(); + success = success && m_clLinkVerticesLocalAddresses.moveToGPU(); + success = success && m_clLinkStrength.moveFromGPU(); + success = success && m_clLinksMassLSC.moveFromGPU(); + success = success && m_clLinksRestLengthSquared.moveFromGPU(); + success = success && m_clLinksRestLength.moveFromGPU(); + success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU(); + + if( success ) { + m_onGPU = false; + } + + return success; +} + + + + + + + + +btOpenCLSoftBodySolverSIMDAware::btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) : + btOpenCLSoftBodySolver( queue, ctx, bUpdateAchchoredNodePos ), + m_linkData(queue, ctx) +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; + + m_shadersInitialized = false; +} + +btOpenCLSoftBodySolverSIMDAware::~btOpenCLSoftBodySolverSIMDAware() +{ + releaseKernels(); +} + +void btOpenCLSoftBodySolverSIMDAware::optimize( btAlignedObjectArray< btSoftBody * > &softBodies ,bool forceUpdate) +{ + if( forceUpdate || m_softBodySet.size() != softBodies.size() ) + { + // Have a change in the soft body set so update, reloading all the data + getVertexData().clear(); + getTriangleData().clear(); + getLinkData().clear(); + m_softBodySet.resize(0); + m_anchorIndex.clear(); + + int maxPiterations = 0; + int maxViterations = 0; + + for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) + { + btSoftBody *softBody = softBodies[ softBodyIndex ]; + using Vectormath::Aos::Matrix3; + using Vectormath::Aos::Point3; + + // Create SoftBody that will store the information within the solver + btOpenCLAcceleratedSoftBodyInterface* newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody ); + m_softBodySet.push_back( newSoftBody ); + + m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); + m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); + m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); + m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); + m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); + m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); + // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time + m_perClothFriction.push_back(softBody->m_cfg.kDF); + m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); + + // Add space for new vertices and triangles in the default solver for now + // TODO: Include space here for tearing too later + int firstVertex = getVertexData().getNumVertices(); + int numVertices = softBody->m_nodes.size(); + // Round maxVertices to a multiple of the workgroup size so we know we're safe to run over in a given group + // maxVertices can be increased to allow tearing, but should be used sparingly because these extra verts will always be processed + int maxVertices = GROUP_SIZE*((numVertices+GROUP_SIZE)/GROUP_SIZE); + // Allocate space for new vertices in all the vertex arrays + getVertexData().createVertices( numVertices, softBodyIndex, maxVertices ); + + + int firstTriangle = getTriangleData().getNumTriangles(); + int numTriangles = softBody->m_faces.size(); + int maxTriangles = numTriangles; + getTriangleData().createTriangles( maxTriangles ); + + // Copy vertices from softbody into the solver + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); + btSoftBodyVertexData::VertexDescription desc; + + // TODO: Position in the softbody might be pre-transformed + // or we may need to adapt for the pose. + //desc.setPosition( cloth.getMeshTransform()*multPoint ); + desc.setPosition( multPoint ); + + float vertexInverseMass = softBody->m_nodes[vertex].m_im; + desc.setInverseMass(vertexInverseMass); + getVertexData().setVertexAt( desc, firstVertex + vertex ); + + m_anchorIndex.push_back(-1); + } + for( int vertex = numVertices; vertex < maxVertices; ++vertex ) + { + m_anchorIndex.push_back(-1.0); + } + + // Copy triangles similarly + // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene + for( int triangle = 0; triangle < numTriangles; ++triangle ) + { + // Note that large array storage is relative to the array not to the cloth + // So we need to add firstVertex to each value + int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); + int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); + int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); + btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); + getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); + + // Increase vertex triangle counts for this triangle + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; + getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; + } + + int firstLink = getLinkData().getNumLinks(); + int numLinks = softBody->m_links.size(); + int maxLinks = numLinks; + + // Allocate space for the links + getLinkData().createLinks( numLinks ); + + // Add the links + for( int link = 0; link < numLinks; ++link ) + { + int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); + int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); + + btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); + newLink.setLinkStrength(1.f); + getLinkData().setLinkAt(newLink, firstLink + link); + } + + newSoftBody->setFirstVertex( firstVertex ); + newSoftBody->setFirstTriangle( firstTriangle ); + newSoftBody->setNumVertices( numVertices ); + newSoftBody->setMaxVertices( maxVertices ); + newSoftBody->setNumTriangles( numTriangles ); + newSoftBody->setMaxTriangles( maxTriangles ); + newSoftBody->setFirstLink( firstLink ); + newSoftBody->setNumLinks( numLinks ); + + // Find maximum piterations and viterations + int piterations = softBody->m_cfg.piterations; + + if ( piterations > maxPiterations ) + maxPiterations = piterations; + + int viterations = softBody->m_cfg.viterations; + + if ( viterations > maxViterations ) + maxViterations = viterations; + + // zero mass + for( int vertex = 0; vertex < numVertices; ++vertex ) + { + if ( softBody->m_nodes[vertex].m_im == 0 ) + { + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + vertex; + nodeInfo.pNode = &softBody->m_nodes[vertex]; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + + // anchor position + if ( numVertices > 0 ) + { + for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ ) + { + btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node; + btSoftBody::Node* firstNode = &softBody->m_nodes[0]; + + AnchorNodeInfoCL nodeInfo; + nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode); + nodeInfo.pNode = anchorNode; + + m_anchorNodeInfoArray.push_back(nodeInfo); + } + } + } + + m_anchorPosition.clear(); + m_anchorPosition.resize(m_anchorNodeInfoArray.size()); + + for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ ) + { + const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode]; + m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode; + getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f; + } + + updateConstants(0.f); + + // set position and velocity iterations + setNumberOfPositionIterations(maxPiterations); + setNumberOfVelocityIterations(maxViterations); + + // set wind velocity + m_perClothWindVelocity.resize( m_softBodySet.size() ); + for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) + { + btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); + m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); + } + + m_clPerClothWindVelocity.changedOnCPU(); + + // generate batches + m_linkData.generateBatches(); + m_triangleData.generateBatches(); + + // Build the shaders to match the batching parameters + buildShaders(); + } +} + + +btSoftBodyLinkData &btOpenCLSoftBodySolverSIMDAware::getLinkData() +{ + // TODO: Consider setting link data to "changed" here + return m_linkData; +} + + + + +void btOpenCLSoftBodySolverSIMDAware::updateConstants( float timeStep ) +{ + + using namespace Vectormath::Aos; + + if( m_updateSolverConstants ) + { + m_updateSolverConstants = false; + + // Will have to redo this if we change the structure (tear, maybe) or various other possible changes + + // Initialise link constants + const int numLinks = m_linkData.getNumLinks(); + for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); + m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); + float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); + float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); + float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); + float massLSC = (invMass0 + invMass1)/linearStiffness; + m_linkData.getMassLSC(linkIndex) = massLSC; + float restLength = m_linkData.getRestLength(linkIndex); + float restLengthSquared = restLength*restLength; + m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; + } + } + +} + + + +void btOpenCLSoftBodySolverSIMDAware::solveConstraints( float solverdt ) +{ + + using Vectormath::Aos::Vector3; + using Vectormath::Aos::Point3; + using Vectormath::Aos::lengthSqr; + using Vectormath::Aos::dot; + + // Prepare links + int numLinks = m_linkData.getNumLinks(); + int numVertices = m_vertexData.getNumVertices(); + + float kst = 1.f; + float ti = 0.f; + + + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothVelocityCorrectionCoefficient.moveToGPU(); + + + // Ensure data is on accelerator + m_linkData.moveToAccelerator(); + m_vertexData.moveToAccelerator(); + + + //prepareLinks(); + + prepareCollisionConstraints(); + + // Solve drift + for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + { + + for( int i = 0; i < m_linkData.m_wavefrontBatchStartLengths.size(); ++i ) + { + int startWave = m_linkData.m_wavefrontBatchStartLengths[i].start; + int numWaves = m_linkData.m_wavefrontBatchStartLengths[i].length; + solveLinksForPosition( startWave, numWaves, kst, ti ); + } + } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) + + + // At this point assume that the force array is blank - we will overwrite it + solveCollisionsAndUpdateVelocities( 1.f/solverdt ); +} + + +////////////////////////////////////// +// Kernel dispatches + + +void btOpenCLSoftBodySolverSIMDAware::solveLinksForPosition( int startWave, int numWaves, float kst, float ti ) +{ + cl_int ciErrNum; + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startWave); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numWaves); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti); + + + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clNumBatchesAndVerticesWithinWaves.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clWavefrontVerticesGlobalAddresses.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinkVerticesLocalAddresses.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); + + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,9, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,10, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); + + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,11, WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_int2), 0); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,12, m_linkData.getMaxVerticesPerWavefront()*WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_float4), 0); + ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,13, m_linkData.getMaxVerticesPerWavefront()*WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_float), 0); + + size_t numWorkItems = workGroupSize*((numWaves*WAVEFRONT_SIZE + (workGroupSize-1)) / workGroupSize); + + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&workGroupSize,0,0,0); + + if( ciErrNum!= CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)"); + } + +} // solveLinksForPosition + +void btOpenCLSoftBodySolverSIMDAware::solveCollisionsAndUpdateVelocities( float isolverdt ) +{ + // Copy kernel parameters to GPU + m_vertexData.moveToAccelerator(); + m_clPerClothFriction.moveToGPU(); + m_clPerClothDampingFactor.moveToGPU(); + m_clPerClothCollisionObjects.moveToGPU(); + m_clCollisionObjectDetails.moveToGPU(); + + cl_int ciErrNum; + int numVerts = m_vertexData.getNumVertices(); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 11, sizeof(CollisionShapeDescription)*16,0); + ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 12, sizeof(cl_mem),&m_vertexData.m_clVertexInverseMass.m_buffer); + size_t numWorkItems = workGroupSize*((m_vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); + + if (numWorkItems) + { + ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &workGroupSize,0,0,0); + + if( ciErrNum != CL_SUCCESS ) + { + btAssert( 0 && "enqueueNDRangeKernel(m_solveCollisionsAndUpdateVelocitiesKernel)"); + } + } + +} // btOpenCLSoftBodySolverSIMDAware::updateVelocitiesFromPositionsWithoutVelocities + +// End kernel dispatches +///////////////////////////////////// + + + +bool btOpenCLSoftBodySolverSIMDAware::buildShaders() +{ + releaseKernels(); + + if( m_shadersInitialized ) + return true; + + const char* additionalMacros=""; + + m_currentCLFunctions->clearKernelCompilationFailures(); + + char *wavefrontMacros = new char[256]; + + sprintf( + wavefrontMacros, + "-DMAX_NUM_VERTICES_PER_WAVE=%d -DMAX_BATCHES_PER_WAVE=%d -DWAVEFRONT_SIZE=%d -DWAVEFRONT_BLOCK_MULTIPLIER=%d -DBLOCK_SIZE=%d", + m_linkData.getMaxVerticesPerWavefront(), + m_linkData.getMaxBatchesPerWavefront(), + m_linkData.getWavefrontSize(), + WAVEFRONT_BLOCK_MULTIPLIER, + WAVEFRONT_BLOCK_MULTIPLIER*m_linkData.getWavefrontSize()); + + m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel", additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl"); + m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel", wavefrontMacros ,"OpenCLC10/SolvePositionsSIMDBatched.cl"); + m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", additionalMacros ,"OpenCLC10/UpdateNodes.cl"); + m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", additionalMacros,"OpenCLC10/UpdatePositions.cl"); + m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel", additionalMacros ,"OpenCLC10/Integrate.cl"); + m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel", additionalMacros,"OpenCLC10/ApplyForces.cl" ); + m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" ,additionalMacros,"OpenCLC10/UpdateFixedVertexPositions.cl"); + m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel", additionalMacros ,"OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl"); + + // TODO: Rename to UpdateSoftBodies + m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); + m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); + m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); + + delete [] wavefrontMacros; + + if( m_currentCLFunctions->getKernelCompilationFailures()==0) + { + m_shadersInitialized = true; + } + + return m_shadersInitialized; +} + + + + +static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) +{ + Vectormath::Aos::Transform3 outTransform; + outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); + outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); + outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); + outTransform.setCol(3, toVector3(transform.getOrigin())); + return outTransform; +} + + +static void generateBatchesOfWavefronts( btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, btSoftBodyLinkData &linkData, int numVertices, btAlignedObjectArray < btAlignedObjectArray > &wavefrontBatches ) +{ + // A per-batch map of truth values stating whether a given vertex is in that batch + // This allows us to significantly optimize the batching + btAlignedObjectArray > mapOfVerticesInBatches; + + for( int waveIndex = 0; waveIndex < linksForWavefronts.size(); ++waveIndex ) + { + btAlignedObjectArray &wavefront( linksForWavefronts[waveIndex] ); + + int batch = 0; + bool placed = false; + while( batch < wavefrontBatches.size() && !placed ) + { + // Test the current batch, see if this wave shares any vertex with the waves in the batch + bool foundSharedVertex = false; + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + if( (mapOfVerticesInBatches[batch])[vertices.vertex0] || (mapOfVerticesInBatches[batch])[vertices.vertex1] ) + { + foundSharedVertex = true; + } + } + + if( !foundSharedVertex ) + { + wavefrontBatches[batch].push_back( waveIndex ); + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + placed = true; + } + batch++; + } + if( batch == wavefrontBatches.size() && !placed ) + { + wavefrontBatches.resize( batch + 1 ); + wavefrontBatches[batch].push_back( waveIndex ); + + // And resize map as well + mapOfVerticesInBatches.resize( batch + 1 ); + + // Resize maps with total number of vertices + mapOfVerticesInBatches[batch].resize( numVertices+1, false ); + + // Insert vertices into this batch too + for( int link = 0; link < wavefront.size(); ++link ) + { + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); + (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; + (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; + } + } + } + mapOfVerticesInBatches.clear(); +} + +// Function to remove an object from a vector maintaining correct ordering of the vector +template< typename T > static void removeFromVector( btAlignedObjectArray< T > &vectorToUpdate, int indexToRemove ) +{ + int currentSize = vectorToUpdate.size(); + for( int i = indexToRemove; i < (currentSize-1); ++i ) + { + vectorToUpdate[i] = vectorToUpdate[i+1]; + } + if( currentSize > 0 ) + vectorToUpdate.resize( currentSize - 1 ); +} + +/** + * Insert element into vectorToUpdate at index index. + */ +template< typename T > static void insertAtIndex( btAlignedObjectArray< T > &vectorToUpdate, int index, T element ) +{ + vectorToUpdate.resize( vectorToUpdate.size() + 1 ); + for( int i = (vectorToUpdate.size() - 1); i > index; --i ) + { + vectorToUpdate[i] = vectorToUpdate[i-1]; + } + vectorToUpdate[index] = element; +} + +/** + * Insert into btAlignedObjectArray assuming the array is ordered and maintaining both ordering and uniqueness. + * ie it treats vectorToUpdate as an ordered set. + */ +template< typename T > static void insertUniqueAndOrderedIntoVector( btAlignedObjectArray &vectorToUpdate, T element ) +{ + int index = 0; + while( index < vectorToUpdate.size() && vectorToUpdate[index] < element ) + { + index++; + } + if( index == vectorToUpdate.size() || vectorToUpdate[index] != element ) + insertAtIndex( vectorToUpdate, index, element ); +} + +static void generateLinksPerVertex( int numVertices, btSoftBodyLinkData &linkData, btAlignedObjectArray< int > &listOfLinksPerVertex, btAlignedObjectArray &numLinksPerVertex, int &maxLinks ) +{ + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numLinksPerVertex[nodes.vertex0]++; + numLinksPerVertex[nodes.vertex1]++; + } + int maxLinksPerVertex = 0; + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + maxLinksPerVertex = btMax(numLinksPerVertex[vertexIndex], maxLinksPerVertex); + } + maxLinks = maxLinksPerVertex; + + btAlignedObjectArray< int > linksFoundPerVertex; + linksFoundPerVertex.resize( numVertices, 0 ); + + listOfLinksPerVertex.resize( maxLinksPerVertex * numVertices ); + + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + { + // Do vertex 0 + int vertexIndex = nodes.vertex0; + int linkForVertex = linksFoundPerVertex[nodes.vertex0]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex0] = linkForVertex + 1; + } + { + // Do vertex 1 + int vertexIndex = nodes.vertex1; + int linkForVertex = linksFoundPerVertex[nodes.vertex1]; + int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; + + listOfLinksPerVertex[linkAddress] = linkIndex; + + linksFoundPerVertex[nodes.vertex1] = linkForVertex + 1; + } + } +} + +static void computeBatchingIntoWavefronts( + btSoftBodyLinkData &linkData, + int wavefrontSize, + int linksPerWorkItem, + int maxLinksPerWavefront, + btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > &batchesWithinWaves, /* wave, batch, links in batch */ + btAlignedObjectArray< btAlignedObjectArray< int > > &verticesForWavefronts /* wavefront, vertex */ + ) +{ + + + // Attempt generation of larger batches of links. + btAlignedObjectArray< bool > processedLink; + processedLink.resize( linkData.getNumLinks() ); + btAlignedObjectArray< int > listOfLinksPerVertex; + int maxLinksPerVertex = 0; + + // Count num vertices + int numVertices = 0; + for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) + { + btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); + numVertices = btMax( numVertices, nodes.vertex0 + 1 ); + numVertices = btMax( numVertices, nodes.vertex1 + 1 ); + } + + // Need list of links per vertex + // Compute valence of each vertex + btAlignedObjectArray numLinksPerVertex; + numLinksPerVertex.resize(0); + numLinksPerVertex.resize( numVertices, 0 ); + + generateLinksPerVertex( numVertices, linkData, listOfLinksPerVertex, numLinksPerVertex, maxLinksPerVertex ); + + if (!numVertices) + return; + + for( int vertex = 0; vertex < 10; ++vertex ) + { + for( int link = 0; link < numLinksPerVertex[vertex]; ++link ) + { + int linkAddress = vertex * maxLinksPerVertex + link; + } + } + + + // At this point we know what links we have for each vertex so we can start batching + + // We want a vertex to start with, let's go with 0 + int currentVertex = 0; + int linksProcessed = 0; + + btAlignedObjectArray verticesToProcess; + + while( linksProcessed < linkData.getNumLinks() ) + { + // Next wavefront + int nextWavefront = linksForWavefronts.size(); + linksForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &linksForWavefront(linksForWavefronts[nextWavefront]); + verticesForWavefronts.resize( nextWavefront + 1 ); + btAlignedObjectArray &vertexSet( verticesForWavefronts[nextWavefront] ); + + linksForWavefront.resize(0); + + // Loop to find enough links to fill the wavefront + // Stopping if we either run out of links, or fill it + while( linksProcessed < linkData.getNumLinks() && linksForWavefront.size() < maxLinksPerWavefront ) + { + // Go through the links for the current vertex + for( int link = 0; link < numLinksPerVertex[currentVertex] && linksForWavefront.size() < maxLinksPerWavefront; ++link ) + { + int linkAddress = currentVertex * maxLinksPerVertex + link; + int linkIndex = listOfLinksPerVertex[linkAddress]; + + // If we have not already processed this link, add it to the wavefront + // Claim it as another processed link + // Add the vertex at the far end to the list of vertices to process. + if( !processedLink[linkIndex] ) + { + linksForWavefront.push_back( linkIndex ); + linksProcessed++; + processedLink[linkIndex] = true; + int v0 = linkData.getVertexPair(linkIndex).vertex0; + int v1 = linkData.getVertexPair(linkIndex).vertex1; + if( v0 == currentVertex ) + verticesToProcess.push_back( v1 ); + else + verticesToProcess.push_back( v0 ); + } + } + if( verticesToProcess.size() > 0 ) + { + // Get the element on the front of the queue and remove it + currentVertex = verticesToProcess[0]; + removeFromVector( verticesToProcess, 0 ); + } else { + // If we've not yet processed all the links, find the first unprocessed one + // and select one of its vertices as the current vertex + if( linksProcessed < linkData.getNumLinks() ) + { + int searchLink = 0; + while( processedLink[searchLink] ) + searchLink++; + currentVertex = linkData.getVertexPair(searchLink).vertex0; + } + } + } + + // We have either finished or filled a wavefront + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int v0 = linkData.getVertexPair( linksForWavefront[link] ).vertex0; + int v1 = linkData.getVertexPair( linksForWavefront[link] ).vertex1; + insertUniqueAndOrderedIntoVector( vertexSet, v0 ); + insertUniqueAndOrderedIntoVector( vertexSet, v1 ); + } + // Iterate over links mapped to the wave and batch those + // We can run a batch on each cycle trivially + + batchesWithinWaves.resize( batchesWithinWaves.size() + 1 ); + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWave( batchesWithinWaves[batchesWithinWaves.size()-1] ); + + + for( int link = 0; link < linksForWavefront.size(); ++link ) + { + int linkIndex = linksForWavefront[link]; + btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( linkIndex ); + + int batch = 0; + bool placed = false; + while( batch < batchesWithinWave.size() && !placed ) + { + bool foundSharedVertex = false; + if( batchesWithinWave[batch].size() >= wavefrontSize ) + { + // If we have already filled this batch, move on to another + foundSharedVertex = true; + } else { + for( int link2 = 0; link2 < batchesWithinWave[batch].size(); ++link2 ) + { + btSoftBodyLinkData::LinkNodePair vertices2 = linkData.getVertexPair( (batchesWithinWave[batch])[link2] ); + + if( vertices.vertex0 == vertices2.vertex0 || + vertices.vertex1 == vertices2.vertex0 || + vertices.vertex0 == vertices2.vertex1 || + vertices.vertex1 == vertices2.vertex1 ) + { + foundSharedVertex = true; + break; + } + } + } + if( !foundSharedVertex ) + { + batchesWithinWave[batch].push_back( linkIndex ); + placed = true; + } else { + ++batch; + } + } + if( batch == batchesWithinWave.size() && !placed ) + { + batchesWithinWave.resize( batch + 1 ); + batchesWithinWave[batch].push_back( linkIndex ); + } + } + + } + +} + +void btSoftBodyLinkDataOpenCLSIMDAware::generateBatches() +{ + btAlignedObjectArray < btAlignedObjectArray > linksForWavefronts; + btAlignedObjectArray < btAlignedObjectArray > wavefrontBatches; + btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > batchesWithinWaves; + btAlignedObjectArray< btAlignedObjectArray< int > > verticesForWavefronts; // wavefronts, vertices in wavefront as an ordered set + + // Group the links into wavefronts + computeBatchingIntoWavefronts( *this, m_wavefrontSize, m_linksPerWorkItem, m_maxLinksPerWavefront, linksForWavefronts, batchesWithinWaves, verticesForWavefronts ); + + + // Batch the wavefronts + generateBatchesOfWavefronts( linksForWavefronts, *this, m_maxVertex, wavefrontBatches ); + + m_numWavefronts = linksForWavefronts.size(); + + // At this point we have a description of which links we need to process in each wavefront + + // First correctly fill the batch ranges vector + int numBatches = wavefrontBatches.size(); + m_wavefrontBatchStartLengths.resize(0); + int prefixSum = 0; + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + int wavesInBatch = wavefrontBatches[batchIndex].size(); + int nextPrefixSum = prefixSum + wavesInBatch; + m_wavefrontBatchStartLengths.push_back( BatchPair( prefixSum, nextPrefixSum - prefixSum ) ); + + prefixSum += wavesInBatch; + } + + // Also find max number of batches within a wave + m_maxBatchesWithinWave = 0; + m_maxVerticesWithinWave = 0; + m_numBatchesAndVerticesWithinWaves.resize( m_numWavefronts ); + for( int waveIndex = 0; waveIndex < m_numWavefronts; ++waveIndex ) + { + // See if the number of batches in this wave is greater than the current maxium + int batchesInCurrentWave = batchesWithinWaves[waveIndex].size(); + int verticesInCurrentWave = verticesForWavefronts[waveIndex].size(); + m_maxBatchesWithinWave = btMax( batchesInCurrentWave, m_maxBatchesWithinWave ); + m_maxVerticesWithinWave = btMax( verticesInCurrentWave, m_maxVerticesWithinWave ); + } + + // Add padding values both for alignment and as dudd addresses within LDS to compute junk rather than branch around + m_maxVerticesWithinWave = 16*((m_maxVerticesWithinWave/16)+2); + + // Now we know the maximum number of vertices per-wave we can resize the global vertices array + m_wavefrontVerticesGlobalAddresses.resize( m_maxVerticesWithinWave * m_numWavefronts ); + + // Grab backup copies of all the link data arrays for the sorting process + btAlignedObjectArray m_links_Backup(m_links); + btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); + btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); + btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); + //btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); + //btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); + btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); + btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); + + // Resize to a wavefront sized batch per batch per wave so we get perfectly coherent memory accesses. + m_links.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkVerticesLocalAddresses.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linkStrength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMassLSC.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLengthSquared.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksRestLength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + m_linksMaterialLinearStiffnessCoefficient.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); + + // Then re-order links into wavefront blocks + + // Total number of wavefronts moved. This will decide the ordering of sorted wavefronts. + int wavefrontCount = 0; + + // Iterate over batches of wavefronts, then wavefronts in the batch + for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) + { + btAlignedObjectArray &batch( wavefrontBatches[batchIndex] ); + int wavefrontsInBatch = batch.size(); + + + for( int wavefrontIndex = 0; wavefrontIndex < wavefrontsInBatch; ++wavefrontIndex ) + { + + int originalWavefrontIndex = batch[wavefrontIndex]; + btAlignedObjectArray< int > &wavefrontVertices( verticesForWavefronts[originalWavefrontIndex] ); + int verticesUsedByWavefront = wavefrontVertices.size(); + + // Copy the set of vertices into the correctly structured array for use on the device + // Fill the non-vertices with -1s + // so we can mask out those reads + for( int vertex = 0; vertex < verticesUsedByWavefront; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = wavefrontVertices[vertex]; + } + for( int vertex = verticesUsedByWavefront; vertex < m_maxVerticesWithinWave; ++vertex ) + { + m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = -1; + } + + // Obtain the set of batches within the current wavefront + btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWavefront( batchesWithinWaves[originalWavefrontIndex] ); + // Set the size of the batches for use in the solver, correctly ordered + NumBatchesVerticesPair batchesAndVertices; + batchesAndVertices.numBatches = batchesWithinWavefront.size(); + batchesAndVertices.numVertices = verticesUsedByWavefront; + m_numBatchesAndVerticesWithinWaves[wavefrontCount] = batchesAndVertices; + + + // Now iterate over batches within the wavefront to structure the links correctly + for( int wavefrontBatch = 0; wavefrontBatch < batchesWithinWavefront.size(); ++wavefrontBatch ) + { + btAlignedObjectArray &linksInBatch( batchesWithinWavefront[wavefrontBatch] ); + int wavefrontBatchSize = linksInBatch.size(); + + int batchAddressInTarget = m_maxBatchesWithinWave * m_wavefrontSize * wavefrontCount + m_wavefrontSize * wavefrontBatch; + + for( int linkIndex = 0; linkIndex < wavefrontBatchSize; ++linkIndex ) + { + int originalLinkAddress = linksInBatch[linkIndex]; + // Reorder simple arrays trivially + m_links[batchAddressInTarget + linkIndex] = m_links_Backup[originalLinkAddress]; + m_linkStrength[batchAddressInTarget + linkIndex] = m_linkStrength_Backup[originalLinkAddress]; + m_linksMassLSC[batchAddressInTarget + linkIndex] = m_linksMassLSC_Backup[originalLinkAddress]; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = m_linksRestLengthSquared_Backup[originalLinkAddress]; + m_linksRestLength[batchAddressInTarget + linkIndex] = m_linksRestLength_Backup[originalLinkAddress]; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = m_linksMaterialLinearStiffnessCoefficient_Backup[originalLinkAddress]; + + // The local address is more complicated. We need to work out where a given vertex will end up + // by searching the set of vertices for this link and using the index as the local address + btSoftBodyLinkData::LinkNodePair localPair; + btSoftBodyLinkData::LinkNodePair globalPair = m_links[batchAddressInTarget + linkIndex]; + localPair.vertex0 = wavefrontVertices.findLinearSearch( globalPair.vertex0 ); + localPair.vertex1 = wavefrontVertices.findLinearSearch( globalPair.vertex1 ); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + for( int linkIndex = wavefrontBatchSize; linkIndex < m_wavefrontSize; ++linkIndex ) + { + // Put 0s into these arrays for padding for cleanliness + m_links[batchAddressInTarget + linkIndex] = btSoftBodyLinkData::LinkNodePair(0, 0); + m_linkStrength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMassLSC[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = 0.f; + m_linksRestLength[batchAddressInTarget + linkIndex] = 0.f; + m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = 0.f; + + + // For local addresses of junk data choose a set of addresses just above the range of valid ones + // and cycling tyhrough % 16 so that we don't have bank conficts between all dud addresses + // The valid addresses will do scatter and gather in the valid range, the junk ones should happily work + // off the end of that range so we need no control + btSoftBodyLinkData::LinkNodePair localPair; + localPair.vertex0 = verticesUsedByWavefront + (linkIndex % 16); + localPair.vertex1 = verticesUsedByWavefront + (linkIndex % 16); + m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; + } + + } + + + wavefrontCount++; + } + + + } + +} // void btSoftBodyLinkDataDX11SIMDAware::generateBatches() + + + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h new file mode 100644 index 00000000..8cd838ad --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h @@ -0,0 +1,81 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H +#define BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H + +#include "stddef.h" //for size_t +#include "vectormath/vmInclude.h" + +#include "btSoftBodySolver_OpenCL.h" +#include "btSoftBodySolverBuffer_OpenCL.h" +#include "btSoftBodySolverLinkData_OpenCLSIMDAware.h" +#include "btSoftBodySolverVertexData_OpenCL.h" +#include "btSoftBodySolverTriangleData_OpenCL.h" + + + + + +class btOpenCLSoftBodySolverSIMDAware : public btOpenCLSoftBodySolver +{ +protected: + + + btSoftBodyLinkDataOpenCLSIMDAware m_linkData; + + + + + virtual bool buildShaders(); + + + void updateConstants( float timeStep ); + + float computeTriangleArea( + const Vectormath::Aos::Point3 &vertex0, + const Vectormath::Aos::Point3 &vertex1, + const Vectormath::Aos::Point3 &vertex2 ); + + + ////////////////////////////////////// + // Kernel dispatches + void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); + + void solveCollisionsAndUpdateVelocities( float isolverdt ); + // End kernel dispatches + ///////////////////////////////////// + +public: + btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false); + + virtual ~btOpenCLSoftBodySolverSIMDAware(); + + virtual SolverTypes getSolverType() const + { + return CL_SIMD_SOLVER; + } + + + virtual btSoftBodyLinkData &getLinkData(); + + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); + + virtual void solveConstraints( float solverdt ); + +}; // btOpenCLSoftBodySolverSIMDAware + +#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h new file mode 100644 index 00000000..ab6721fb --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h @@ -0,0 +1,748 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_DATA_H +#define BT_SOFT_BODY_SOLVER_DATA_H + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "vectormath/vmInclude.h" + + +class btSoftBodyLinkData +{ +public: + /** + * Class representing a link as a set of three indices into the vertex array. + */ + class LinkNodePair + { + public: + int vertex0; + int vertex1; + + LinkNodePair() + { + vertex0 = 0; + vertex1 = 0; + } + + LinkNodePair( int v0, int v1 ) + { + vertex0 = v0; + vertex1 = v1; + } + }; + + /** + * Class describing a link for input into the system. + */ + class LinkDescription + { + protected: + int m_vertex0; + int m_vertex1; + float m_linkLinearStiffness; + float m_linkStrength; + + public: + + LinkDescription() + { + m_vertex0 = 0; + m_vertex1 = 0; + m_linkLinearStiffness = 1.0; + m_linkStrength = 1.0; + } + + LinkDescription( int newVertex0, int newVertex1, float linkLinearStiffness ) + { + m_vertex0 = newVertex0; + m_vertex1 = newVertex1; + m_linkLinearStiffness = linkLinearStiffness; + m_linkStrength = 1.0; + } + + LinkNodePair getVertexPair() const + { + LinkNodePair nodes; + nodes.vertex0 = m_vertex0; + nodes.vertex1 = m_vertex1; + return nodes; + } + + void setVertex0( int vertex ) + { + m_vertex0 = vertex; + } + + void setVertex1( int vertex ) + { + m_vertex1 = vertex; + } + + void setLinkLinearStiffness( float linearStiffness ) + { + m_linkLinearStiffness = linearStiffness; + } + + void setLinkStrength( float strength ) + { + m_linkStrength = strength; + } + + int getVertex0() const + { + return m_vertex0; + } + + int getVertex1() const + { + return m_vertex1; + } + + float getLinkStrength() const + { + return m_linkStrength; + } + + float getLinkLinearStiffness() const + { + return m_linkLinearStiffness; + } + }; + + +protected: + // NOTE: + // Vertex reference data is stored relative to global array, not relative to individual cloth. + // Values must be correct if being passed into single-cloth VBOs or when migrating from one solver + // to another. + + btAlignedObjectArray< LinkNodePair > m_links; // Vertex pair for the link + btAlignedObjectArray< float > m_linkStrength; // Strength of each link + // (inverseMassA + inverseMassB)/ linear stiffness coefficient + btAlignedObjectArray< float > m_linksMassLSC; + btAlignedObjectArray< float > m_linksRestLengthSquared; + // Current vector length of link + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_linksCLength; + // 1/(current length * current length * massLSC) + btAlignedObjectArray< float > m_linksLengthRatio; + btAlignedObjectArray< float > m_linksRestLength; + btAlignedObjectArray< float > m_linksMaterialLinearStiffnessCoefficient; + +public: + btSoftBodyLinkData() + { + } + + virtual ~btSoftBodyLinkData() + { + } + + virtual void clear() + { + m_links.resize(0); + m_linkStrength.resize(0); + m_linksMassLSC.resize(0); + m_linksRestLengthSquared.resize(0); + m_linksLengthRatio.resize(0); + m_linksRestLength.resize(0); + m_linksMaterialLinearStiffnessCoefficient.resize(0); + } + + int getNumLinks() + { + return m_links.size(); + } + + /** Allocate enough space in all link-related arrays to fit numLinks links */ + virtual void createLinks( int numLinks ) + { + int previousSize = m_links.size(); + int newSize = previousSize + numLinks; + + // Resize all the arrays that store link data + m_links.resize( newSize ); + m_linkStrength.resize( newSize ); + m_linksMassLSC.resize( newSize ); + m_linksRestLengthSquared.resize( newSize ); + m_linksCLength.resize( newSize ); + m_linksLengthRatio.resize( newSize ); + m_linksRestLength.resize( newSize ); + m_linksMaterialLinearStiffnessCoefficient.resize( newSize ); + } + + /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ + virtual void setLinkAt( const LinkDescription &link, int linkIndex ) + { + m_links[linkIndex] = link.getVertexPair(); + m_linkStrength[linkIndex] = link.getLinkStrength(); + m_linksMassLSC[linkIndex] = 0.f; + m_linksRestLengthSquared[linkIndex] = 0.f; + m_linksCLength[linkIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_linksLengthRatio[linkIndex] = 0.f; + m_linksRestLength[linkIndex] = 0.f; + m_linksMaterialLinearStiffnessCoefficient[linkIndex] = link.getLinkLinearStiffness(); + } + + + /** + * Return true if data is on the accelerator. + * The CPU version of this class will return true here because + * the CPU is the same as the accelerator. + */ + virtual bool onAccelerator() + { + return true; + } + + /** + * Move data from host memory to the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveToAccelerator() + { + return true; + } + + /** + * Move data from host memory from the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveFromAccelerator() + { + return true; + } + + + + /** + * Return reference to the vertex index pair for link linkIndex as stored on the host. + */ + LinkNodePair &getVertexPair( int linkIndex ) + { + return m_links[linkIndex]; + } + + /** + * Return reference to strength of link linkIndex as stored on the host. + */ + float &getStrength( int linkIndex ) + { + return m_linkStrength[linkIndex]; + } + + /** + * Return a reference to the strength of the link corrected for link sorting. + * This is important if we are using data on an accelerator which has the data sorted in some fashion. + */ + virtual float &getStrengthCorrected( int linkIndex ) + { + return getStrength( linkIndex ); + } + + /** + * Return reference to the rest length of link linkIndex as stored on the host. + */ + float &getRestLength( int linkIndex ) + { + return m_linksRestLength[linkIndex]; + } + + /** + * Return reference to linear stiffness coefficient for link linkIndex as stored on the host. + */ + float &getLinearStiffnessCoefficient( int linkIndex ) + { + return m_linksMaterialLinearStiffnessCoefficient[linkIndex]; + } + + /** + * Return reference to the MassLSC value for link linkIndex as stored on the host. + */ + float &getMassLSC( int linkIndex ) + { + return m_linksMassLSC[linkIndex]; + } + + /** + * Return reference to rest length squared for link linkIndex as stored on the host. + */ + float &getRestLengthSquared( int linkIndex ) + { + return m_linksRestLengthSquared[linkIndex]; + } + + /** + * Return reference to current length of link linkIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getCurrentLength( int linkIndex ) + { + return m_linksCLength[linkIndex]; + } + + /** + * Return the link length ratio from for link linkIndex as stored on the host. + */ + float &getLinkLengthRatio( int linkIndex ) + { + return m_linksLengthRatio[linkIndex]; + } +}; + + + +/** + * Wrapper for vertex data information. + * By wrapping it like this we stand a good chance of being able to optimise for storage format easily. + * It should also help us make sure all the data structures remain consistent. + */ +class btSoftBodyVertexData +{ +public: + /** + * Class describing a vertex for input into the system. + */ + class VertexDescription + { + private: + Vectormath::Aos::Point3 m_position; + /** Inverse mass. If this is 0f then the mass was 0 because that simplifies calculations. */ + float m_inverseMass; + + public: + VertexDescription() + { + m_position = Vectormath::Aos::Point3( 0.f, 0.f, 0.f ); + m_inverseMass = 0.f; + } + + VertexDescription( const Vectormath::Aos::Point3 &position, float mass ) + { + m_position = position; + if( mass > 0.f ) + m_inverseMass = 1.0f/mass; + else + m_inverseMass = 0.f; + } + + void setPosition( const Vectormath::Aos::Point3 &position ) + { + m_position = position; + } + + void setInverseMass( float inverseMass ) + { + m_inverseMass = inverseMass; + } + + void setMass( float mass ) + { + if( mass > 0.f ) + m_inverseMass = 1.0f/mass; + else + m_inverseMass = 0.f; + } + + Vectormath::Aos::Point3 getPosition() const + { + return m_position; + } + + float getInverseMass() const + { + return m_inverseMass; + } + + float getMass() const + { + if( m_inverseMass == 0.f ) + return 0.f; + else + return 1.0f/m_inverseMass; + } + }; +protected: + + // identifier for the individual cloth + // For the CPU we don't really need this as we can grab the cloths and iterate over only their vertices + // For a parallel accelerator knowing on a per-vertex basis which cloth we're part of will help for obtaining + // per-cloth data + // For sorting etc it might also be helpful to be able to use in-array data such as this. + btAlignedObjectArray< int > m_clothIdentifier; + btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPosition; // vertex positions + btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPreviousPosition; // vertex positions + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexVelocity; // Velocity + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexForceAccumulator; // Force accumulator + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexNormal; // Normals + btAlignedObjectArray< float > m_vertexInverseMass; // Inverse mass + btAlignedObjectArray< float > m_vertexArea; // Area controlled by the vertex + btAlignedObjectArray< int > m_vertexTriangleCount; // Number of triangles touching this vertex + +public: + btSoftBodyVertexData() + { + } + + virtual ~btSoftBodyVertexData() + { + } + + virtual void clear() + { + m_clothIdentifier.resize(0); + m_vertexPosition.resize(0); + m_vertexPreviousPosition.resize(0); + m_vertexVelocity.resize(0); + m_vertexForceAccumulator.resize(0); + m_vertexNormal.resize(0); + m_vertexInverseMass.resize(0); + m_vertexArea.resize(0); + m_vertexTriangleCount.resize(0); + } + + int getNumVertices() + { + return m_vertexPosition.size(); + } + + int getClothIdentifier( int vertexIndex ) + { + return m_clothIdentifier[vertexIndex]; + } + + void setVertexAt( const VertexDescription &vertex, int vertexIndex ) + { + m_vertexPosition[vertexIndex] = vertex.getPosition(); + m_vertexPreviousPosition[vertexIndex] = vertex.getPosition(); + m_vertexVelocity[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_vertexForceAccumulator[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_vertexNormal[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); + m_vertexInverseMass[vertexIndex] = vertex.getInverseMass(); + m_vertexArea[vertexIndex] = 0.f; + m_vertexTriangleCount[vertexIndex] = 0; + } + + /** + * Create numVertices new vertices for cloth clothIdentifier + * maxVertices allows a buffer zone of extra vertices for alignment or tearing reasons. + */ + void createVertices( int numVertices, int clothIdentifier, int maxVertices = 0 ) + { + int previousSize = m_vertexPosition.size(); + if( maxVertices == 0 ) + maxVertices = numVertices; + int newSize = previousSize + maxVertices; + + // Resize all the arrays that store vertex data + m_clothIdentifier.resize( newSize ); + m_vertexPosition.resize( newSize ); + m_vertexPreviousPosition.resize( newSize ); + m_vertexVelocity.resize( newSize ); + m_vertexForceAccumulator.resize( newSize ); + m_vertexNormal.resize( newSize ); + m_vertexInverseMass.resize( newSize ); + m_vertexArea.resize( newSize ); + m_vertexTriangleCount.resize( newSize ); + + for( int vertexIndex = previousSize; vertexIndex < newSize; ++vertexIndex ) + m_clothIdentifier[vertexIndex] = clothIdentifier; + for( int vertexIndex = (previousSize + numVertices); vertexIndex < newSize; ++vertexIndex ) + m_clothIdentifier[vertexIndex] = -1; + } + + // Get and set methods in header so they can be inlined + + /** + * Return a reference to the position of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Point3 &getPosition( int vertexIndex ) + { + return m_vertexPosition[vertexIndex]; + } + + Vectormath::Aos::Point3 getPosition( int vertexIndex ) const + { + return m_vertexPosition[vertexIndex]; + } + + /** + * Return a reference to the previous position of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Point3 &getPreviousPosition( int vertexIndex ) + { + return m_vertexPreviousPosition[vertexIndex]; + } + + /** + * Return a reference to the velocity of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getVelocity( int vertexIndex ) + { + return m_vertexVelocity[vertexIndex]; + } + + /** + * Return a reference to the force accumulator of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getForceAccumulator( int vertexIndex ) + { + return m_vertexForceAccumulator[vertexIndex]; + } + + /** + * Return a reference to the normal of vertex vertexIndex as stored on the host. + */ + Vectormath::Aos::Vector3 &getNormal( int vertexIndex ) + { + return m_vertexNormal[vertexIndex]; + } + + Vectormath::Aos::Vector3 getNormal( int vertexIndex ) const + { + return m_vertexNormal[vertexIndex]; + } + + /** + * Return a reference to the inverse mass of vertex vertexIndex as stored on the host. + */ + float &getInverseMass( int vertexIndex ) + { + return m_vertexInverseMass[vertexIndex]; + } + + /** + * Get access to the area controlled by this vertex. + */ + float &getArea( int vertexIndex ) + { + return m_vertexArea[vertexIndex]; + } + + /** + * Get access to the array of how many triangles touch each vertex. + */ + int &getTriangleCount( int vertexIndex ) + { + return m_vertexTriangleCount[vertexIndex]; + } + + + + /** + * Return true if data is on the accelerator. + * The CPU version of this class will return true here because + * the CPU is the same as the accelerator. + */ + virtual bool onAccelerator() + { + return true; + } + + /** + * Move data from host memory to the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveToAccelerator() + { + return true; + } + + /** + * Move data to host memory from the accelerator if bCopy is false. + * If bCopy is true, copy data to host memory from the accelerator so that data + * won't be moved to accelerator when moveToAccelerator() is called next time. + * If bCopyMinimum is true, only vertex position and normal are copied. + * bCopyMinimum will be meaningful only if bCopy is true. + * The CPU version will always return that it has moved it. + */ + virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true) + { + return true; + } + + btAlignedObjectArray< Vectormath::Aos::Point3 > &getVertexPositions() + { + return m_vertexPosition; + } +}; + + +class btSoftBodyTriangleData +{ +public: + /** + * Class representing a triangle as a set of three indices into the + * vertex array. + */ + class TriangleNodeSet + { + public: + int vertex0; + int vertex1; + int vertex2; + int _padding; + + TriangleNodeSet( ) + { + vertex0 = 0; + vertex1 = 0; + vertex2 = 0; + _padding = -1; + } + + TriangleNodeSet( int newVertex0, int newVertex1, int newVertex2 ) + { + vertex0 = newVertex0; + vertex1 = newVertex1; + vertex2 = newVertex2; + } + }; + + class TriangleDescription + { + protected: + int m_vertex0; + int m_vertex1; + int m_vertex2; + + public: + TriangleDescription() + { + m_vertex0 = 0; + m_vertex1 = 0; + m_vertex2 = 0; + } + + TriangleDescription( int newVertex0, int newVertex1, int newVertex2 ) + { + m_vertex0 = newVertex0; + m_vertex1 = newVertex1; + m_vertex2 = newVertex2; + } + + TriangleNodeSet getVertexSet() const + { + btSoftBodyTriangleData::TriangleNodeSet nodes; + nodes.vertex0 = m_vertex0; + nodes.vertex1 = m_vertex1; + nodes.vertex2 = m_vertex2; + return nodes; + } + }; + +protected: + // NOTE: + // Vertex reference data is stored relative to global array, not relative to individual cloth. + // Values must be correct if being passed into single-cloth VBOs or when migrating from one solver + // to another. + btAlignedObjectArray< TriangleNodeSet > m_vertexIndices; + btAlignedObjectArray< float > m_area; + btAlignedObjectArray< Vectormath::Aos::Vector3 > m_normal; + +public: + btSoftBodyTriangleData() + { + } + + virtual ~btSoftBodyTriangleData() + { + + } + + virtual void clear() + { + m_vertexIndices.resize(0); + m_area.resize(0); + m_normal.resize(0); + } + + int getNumTriangles() + { + return m_vertexIndices.size(); + } + + virtual void setTriangleAt( const TriangleDescription &triangle, int triangleIndex ) + { + m_vertexIndices[triangleIndex] = triangle.getVertexSet(); + } + + virtual void createTriangles( int numTriangles ) + { + int previousSize = m_vertexIndices.size(); + int newSize = previousSize + numTriangles; + + // Resize all the arrays that store triangle data + m_vertexIndices.resize( newSize ); + m_area.resize( newSize ); + m_normal.resize( newSize ); + } + + /** + * Return the vertex index set for triangle triangleIndex as stored on the host. + */ + const TriangleNodeSet &getVertexSet( int triangleIndex ) + { + return m_vertexIndices[triangleIndex]; + } + + /** + * Get access to the triangle area. + */ + float &getTriangleArea( int triangleIndex ) + { + return m_area[triangleIndex]; + } + + /** + * Get access to the normal vector for this triangle. + */ + Vectormath::Aos::Vector3 &getNormal( int triangleIndex ) + { + return m_normal[triangleIndex]; + } + + /** + * Return true if data is on the accelerator. + * The CPU version of this class will return true here because + * the CPU is the same as the accelerator. + */ + virtual bool onAccelerator() + { + return true; + } + + /** + * Move data from host memory to the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveToAccelerator() + { + return true; + } + + /** + * Move data from host memory from the accelerator. + * The CPU version will always return that it has moved it. + */ + virtual bool moveFromAccelerator() + { + return true; + } +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVER_DATA_H + diff --git a/Code/Physics/src/BulletMultiThreaded/HeapManager.h b/Code/Physics/src/BulletMultiThreaded/HeapManager.h new file mode 100644 index 00000000..b2da4ef5 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/HeapManager.h @@ -0,0 +1,117 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_HEAP_MANAGER_H__ +#define BT_HEAP_MANAGER_H__ + +#ifdef __SPU__ + #define HEAP_STACK_SIZE 32 +#else + #define HEAP_STACK_SIZE 64 +#endif + +#define MIN_ALLOC_SIZE 16 + + +class HeapManager +{ +private: + ATTRIBUTE_ALIGNED16(unsigned char *mHeap); + ATTRIBUTE_ALIGNED16(unsigned int mHeapBytes); + ATTRIBUTE_ALIGNED16(unsigned char *mPoolStack[HEAP_STACK_SIZE]); + ATTRIBUTE_ALIGNED16(unsigned int mCurStack); + +public: + enum {ALIGN16,ALIGN128}; + + HeapManager(unsigned char *buf,int bytes) + { + mHeap = buf; + mHeapBytes = bytes; + clear(); + } + + ~HeapManager() + { + } + + int getAllocated() + { + return (int)(mPoolStack[mCurStack]-mHeap); + } + + int getRest() + { + return mHeapBytes-getAllocated(); + } + + void *allocate(size_t bytes,int alignment = ALIGN16) + { + if(bytes <= 0) bytes = MIN_ALLOC_SIZE; + btAssert(mCurStack < (HEAP_STACK_SIZE-1)); + + +#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__) + unsigned long long p = (unsigned long long )mPoolStack[mCurStack]; + if(alignment == ALIGN128) { + p = ((p+127) & 0xffffffffffffff80); + bytes = (bytes+127) & 0xffffffffffffff80; + } + else { + bytes = (bytes+15) & 0xfffffffffffffff0; + } + + btAssert(bytes <=(mHeapBytes-(p-(unsigned long long )mHeap)) ); + +#else + unsigned long p = (unsigned long )mPoolStack[mCurStack]; + if(alignment == ALIGN128) { + p = ((p+127) & 0xffffff80); + bytes = (bytes+127) & 0xffffff80; + } + else { + bytes = (bytes+15) & 0xfffffff0; + } + btAssert(bytes <=(mHeapBytes-(p-(unsigned long)mHeap)) ); +#endif + unsigned char * bla = (unsigned char *)(p + bytes); + mPoolStack[++mCurStack] = bla; + return (void*)p; + } + + void deallocate(void *p) + { + (void) p; + mCurStack--; + } + + void clear() + { + mPoolStack[0] = mHeap; + mCurStack = 0; + } + +// void printStack() +// { +// for(unsigned int i=0;i<=mCurStack;i++) { +// PRINTF("memStack %2d 0x%x\n",i,(uint32_t)mPoolStack[i]); +// } +// } + +}; + +#endif //BT_HEAP_MANAGER_H__ + diff --git a/Code/Physics/src/BulletMultiThreaded/PlatformDefinitions.h b/Code/Physics/src/BulletMultiThreaded/PlatformDefinitions.h new file mode 100644 index 00000000..9bf8c96f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/PlatformDefinitions.h @@ -0,0 +1,103 @@ +#ifndef BT_TYPE_DEFINITIONS_H +#define BT_TYPE_DEFINITIONS_H + +///This file provides some platform/compiler checks for common definitions +#include "LinearMath/btScalar.h" +#include "LinearMath/btMinMax.h" + +#ifdef PFX_USE_FREE_VECTORMATH +#include "physics_effects/base_level/base/pfx_vectormath_include.win32.h" +typedef Vectormath::Aos::Vector3 vmVector3; +typedef Vectormath::Aos::Quat vmQuat; +typedef Vectormath::Aos::Matrix3 vmMatrix3; +typedef Vectormath::Aos::Transform3 vmTransform3; +typedef Vectormath::Aos::Point3 vmPoint3; +#else +#include "vectormath/vmInclude.h" +#endif//PFX_USE_FREE_VECTORMATH + + + + + +#ifdef _WIN32 + +typedef union +{ + unsigned int u; + void *p; +} addr64; + +#define USE_WIN32_THREADING 1 + + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #else + #endif //__MINGW32__ + + typedef unsigned char uint8_t; +#ifndef __PHYSICS_COMMON_H__ +#ifndef PFX_USE_FREE_VECTORMATH +#ifndef __BT_SKIP_UINT64_H +#if defined(_WIN64) && defined(_MSC_VER) + typedef unsigned __int64 uint64_t; +#else + typedef unsigned long int uint64_t; +#endif +#endif //__BT_SKIP_UINT64_H +#endif //PFX_USE_FREE_VECTORMATH + typedef unsigned int uint32_t; +#endif //__PHYSICS_COMMON_H__ + typedef unsigned short uint16_t; + + #include + #define memalign(alignment, size) malloc(size); + +#include //memcpy + + + + #include + #define spu_printf printf + +#else + #include + #include + #include //for memcpy + +#if defined (__CELLOS_LV2__) + // Playstation 3 Cell SDK +#include + +#else + // posix system + +#define USE_PTHREADS (1) + +#ifdef USE_LIBSPE2 +#include +#define spu_printf printf +#define DWORD unsigned int + typedef union + { + unsigned long long ull; + unsigned int ui[2]; + void *p; + } addr64; +#endif // USE_LIBSPE2 + +#endif //__CELLOS_LV2__ + +#endif + +#ifdef __SPU__ +#include +#define printf spu_printf +#endif + +/* Included here because we need uint*_t typedefs */ +#include "PpuAddressSpace.h" + +#endif //BT_TYPE_DEFINITIONS_H + + + diff --git a/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.cpp b/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.cpp new file mode 100644 index 00000000..81c0cf86 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.cpp @@ -0,0 +1,409 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 +#include "PosixThreadSupport.h" +#ifdef USE_PTHREADS +#include +#include + +#include "SpuCollisionTaskProcess.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + +#define checkPThreadFunction(returnValue) \ + if(0 != returnValue) { \ + printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \ + } + +// The number of threads should be equal to the number of available cores +// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor. + +// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +// Setup and initialize SPU/CELL/Libspe2 +PosixThreadSupport::PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo) +{ + startThreads(threadConstructionInfo); +} + +// cleanup/shutdown Libspe2 +PosixThreadSupport::~PosixThreadSupport() +{ + stopSPU(); +} + +#if (defined (__APPLE__)) +#define NAMED_SEMAPHORES +#endif + +// this semaphore will signal, if and how many threads are finished with their work +static sem_t* mainSemaphore=0; + +static sem_t* createSem(const char* baseName) +{ + static int semCount = 0; +#ifdef NAMED_SEMAPHORES + /// Named semaphore begin + char name[32]; + snprintf(name, 32, "/%s-%d-%4.4d", baseName, getpid(), semCount++); + sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0); + + if (tempSem != reinterpret_cast(SEM_FAILED)) + { +// printf("Created \"%s\" Semaphore %p\n", name, tempSem); + } + else + { + //printf("Error creating Semaphore %d\n", errno); + exit(-1); + } + /// Named semaphore end +#else + sem_t* tempSem = new sem_t; + checkPThreadFunction(sem_init(tempSem, 0, 0)); +#endif + return tempSem; +} + +static void destroySem(sem_t* semaphore) +{ +#ifdef NAMED_SEMAPHORES + checkPThreadFunction(sem_close(semaphore)); +#else + checkPThreadFunction(sem_destroy(semaphore)); + delete semaphore; +#endif +} + +static void *threadFunction(void *argument) +{ + + PosixThreadSupport::btSpuStatus* status = (PosixThreadSupport::btSpuStatus*)argument; + + + while (1) + { + checkPThreadFunction(sem_wait(status->startSemaphore)); + + void* userPtr = status->m_userPtr; + + if (userPtr) + { + btAssert(status->m_status); + status->m_userThreadFunc(userPtr,status->m_lsMemory); + status->m_status = 2; + checkPThreadFunction(sem_post(mainSemaphore)); + status->threadUsed++; + } else { + //exit Thread + status->m_status = 3; + checkPThreadFunction(sem_post(mainSemaphore)); + printf("Thread with taskId %i exiting\n",status->m_taskId); + break; + } + + } + + printf("Thread TERMINATED\n"); + return 0; + +} + +///send messages to SPUs +void PosixThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) +{ + /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (uint32_t) &taskDesc); + + ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished + + + + switch (uiCommand) + { + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; + btAssert(taskId >= 0); + btAssert(taskId < m_activeSpuStatus.size()); + + spuStatus.m_commandId = uiCommand; + spuStatus.m_status = 1; + spuStatus.m_userPtr = (void*)uiArgument0; + + // fire event to start new task + checkPThreadFunction(sem_post(spuStatus.startSemaphore)); + break; + } + default: + { + ///not implemented + btAssert(0); + } + + }; + + +} + + +///check for messages from SPUs +void PosixThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) +{ + ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response + + ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' + + + btAssert(m_activeSpuStatus.size()); + + // wait for any of the threads to finish + checkPThreadFunction(sem_wait(mainSemaphore)); + + // get at least one thread which has finished + size_t last = -1; + + for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) { + if(2 == m_activeSpuStatus[t].m_status) { + last = t; + break; + } + } + + btSpuStatus& spuStatus = m_activeSpuStatus[last]; + + btAssert(spuStatus.m_status > 1); + spuStatus.m_status = 0; + + // need to find an active spu + btAssert(last >= 0); + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; +} + + + +void PosixThreadSupport::startThreads(ThreadConstructionInfo& threadConstructionInfo) +{ + printf("%s creating %i threads.\n", __FUNCTION__, threadConstructionInfo.m_numThreads); + m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); + + mainSemaphore = createSem("main"); + //checkPThreadFunction(sem_wait(mainSemaphore)); + + for (int i=0;i < threadConstructionInfo.m_numThreads;i++) + { + printf("starting thread %d\n",i); + + btSpuStatus& spuStatus = m_activeSpuStatus[i]; + + spuStatus.startSemaphore = createSem("threadLocal"); + + checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus)); + + spuStatus.m_userPtr=0; + + spuStatus.m_taskId = i; + spuStatus.m_commandId = 0; + spuStatus.m_status = 0; + spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); + spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; + spuStatus.threadUsed = 0; + + printf("started thread %d \n",i); + + } + +} + +void PosixThreadSupport::startSPU() +{ +} + + +///tell the task scheduler we are done with the SPU tasks +void PosixThreadSupport::stopSPU() +{ + for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) + { + btSpuStatus& spuStatus = m_activeSpuStatus[t]; + printf("%s: Thread %i used: %ld\n", __FUNCTION__, int(t), spuStatus.threadUsed); + + spuStatus.m_userPtr = 0; + checkPThreadFunction(sem_post(spuStatus.startSemaphore)); + checkPThreadFunction(sem_wait(mainSemaphore)); + + printf("destroy semaphore\n"); + destroySem(spuStatus.startSemaphore); + printf("semaphore destroyed\n"); + checkPThreadFunction(pthread_join(spuStatus.thread,0)); + + } + printf("destroy main semaphore\n"); + destroySem(mainSemaphore); + printf("main semaphore destroyed\n"); + m_activeSpuStatus.clear(); +} + +class PosixCriticalSection : public btCriticalSection +{ + pthread_mutex_t m_mutex; + +public: + PosixCriticalSection() + { + pthread_mutex_init(&m_mutex, NULL); + } + virtual ~PosixCriticalSection() + { + pthread_mutex_destroy(&m_mutex); + } + + ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]); + + virtual unsigned int getSharedParam(int i) + { + return mCommonBuff[i]; + } + virtual void setSharedParam(int i,unsigned int p) + { + mCommonBuff[i] = p; + } + + virtual void lock() + { + pthread_mutex_lock(&m_mutex); + } + virtual void unlock() + { + pthread_mutex_unlock(&m_mutex); + } +}; + + +#if defined(_POSIX_BARRIERS) && (_POSIX_BARRIERS - 20012L) >= 0 +/* OK to use barriers on this platform */ +class PosixBarrier : public btBarrier +{ + pthread_barrier_t m_barr; + int m_numThreads; +public: + PosixBarrier() + :m_numThreads(0) { } + virtual ~PosixBarrier() { + pthread_barrier_destroy(&m_barr); + } + + virtual void sync() + { + int rc = pthread_barrier_wait(&m_barr); + if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf("Could not wait on barrier\n"); + exit(-1); + } + } + virtual void setMaxCount(int numThreads) + { + int result = pthread_barrier_init(&m_barr, NULL, numThreads); + m_numThreads = numThreads; + btAssert(result==0); + } + virtual int getMaxCount() + { + return m_numThreads; + } +}; +#else +/* Not OK to use barriers on this platform - insert alternate code here */ +class PosixBarrier : public btBarrier +{ + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + + int m_numThreads; + int m_called; + +public: + PosixBarrier() + :m_numThreads(0) + { + } + virtual ~PosixBarrier() + { + if (m_numThreads>0) + { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); + } + } + + virtual void sync() + { + pthread_mutex_lock(&m_mutex); + m_called++; + if (m_called == m_numThreads) { + m_called = 0; + pthread_cond_broadcast(&m_cond); + } else { + pthread_cond_wait(&m_cond,&m_mutex); + } + pthread_mutex_unlock(&m_mutex); + + } + virtual void setMaxCount(int numThreads) + { + if (m_numThreads>0) + { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); + } + m_called = 0; + pthread_mutex_init(&m_mutex,NULL); + pthread_cond_init(&m_cond,NULL); + m_numThreads = numThreads; + } + virtual int getMaxCount() + { + return m_numThreads; + } +}; + +#endif//_POSIX_BARRIERS + + + +btBarrier* PosixThreadSupport::createBarrier() +{ + PosixBarrier* barrier = new PosixBarrier(); + barrier->setMaxCount(getNumTasks()); + return barrier; +} + +btCriticalSection* PosixThreadSupport::createCriticalSection() +{ + return new PosixCriticalSection(); +} + +void PosixThreadSupport::deleteBarrier(btBarrier* barrier) +{ + delete barrier; +} + +void PosixThreadSupport::deleteCriticalSection(btCriticalSection* cs) +{ + delete cs; +} +#endif // USE_PTHREADS + diff --git a/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.h b/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.h new file mode 100644 index 00000000..bf7578f5 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.h @@ -0,0 +1,147 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_POSIX_THREAD_SUPPORT_H +#define BT_POSIX_THREAD_SUPPORT_H + + +#include "LinearMath/btScalar.h" +#include "PlatformDefinitions.h" + +#ifdef USE_PTHREADS //platform specifc defines are defined in PlatformDefinitions.h + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html +#endif //_XOPEN_SOURCE +#include +#include + + + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btThreadSupportInterface.h" + + +typedef void (*PosixThreadFunc)(void* userPtr,void* lsMemory); +typedef void* (*PosixlsMemorySetupFunc)(); + +// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +class PosixThreadSupport : public btThreadSupportInterface +{ +public: + typedef enum sStatus { + STATUS_BUSY, + STATUS_READY, + STATUS_FINISHED + } Status; + + // placeholder, until libspe2 support is there + struct btSpuStatus + { + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + PosixThreadFunc m_userThreadFunc; + void* m_userPtr; //for taskDesc etc + void* m_lsMemory; //initialized using PosixLocalStoreMemorySetupFunc + + pthread_t thread; + sem_t* startSemaphore; + + unsigned long threadUsed; + }; +private: + + btAlignedObjectArray m_activeSpuStatus; +public: + ///Setup and initialize SPU/CELL/Libspe2 + + + + struct ThreadConstructionInfo + { + ThreadConstructionInfo(const char* uniqueName, + PosixThreadFunc userThreadFunc, + PosixlsMemorySetupFunc lsMemoryFunc, + int numThreads=1, + int threadStackSize=65535 + ) + :m_uniqueName(uniqueName), + m_userThreadFunc(userThreadFunc), + m_lsMemoryFunc(lsMemoryFunc), + m_numThreads(numThreads), + m_threadStackSize(threadStackSize) + { + + } + + const char* m_uniqueName; + PosixThreadFunc m_userThreadFunc; + PosixlsMemorySetupFunc m_lsMemoryFunc; + int m_numThreads; + int m_threadStackSize; + + }; + + PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo); + +///cleanup/shutdown Libspe2 + virtual ~PosixThreadSupport(); + + void startThreads(ThreadConstructionInfo& threadInfo); + + +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); + +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); + +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); + +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks) {} + + virtual int getNumTasks() const + { + return m_activeSpuStatus.size(); + } + + virtual btBarrier* createBarrier(); + + virtual btCriticalSection* createCriticalSection(); + + virtual void deleteBarrier(btBarrier* barrier); + + virtual void deleteCriticalSection(btCriticalSection* criticalSection); + + + virtual void* getThreadLocalMemory(int taskId) + { + return m_activeSpuStatus[taskId].m_lsMemory; + } + +}; + +#endif // USE_PTHREADS + +#endif // BT_POSIX_THREAD_SUPPORT_H + + diff --git a/Code/Physics/src/BulletMultiThreaded/PpuAddressSpace.h b/Code/Physics/src/BulletMultiThreaded/PpuAddressSpace.h new file mode 100644 index 00000000..6f228274 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/PpuAddressSpace.h @@ -0,0 +1,37 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_PPU_ADDRESS_SPACE_H +#define BT_PPU_ADDRESS_SPACE_H + + +#ifdef _WIN32 +//stop those casting warnings until we have a better solution for ppu_address_t / void* / uint64 conversions +#pragma warning (disable: 4311) +#pragma warning (disable: 4312) +#endif //_WIN32 + + +#if defined(_WIN64) + typedef unsigned __int64 ppu_address_t; +#elif defined(__LP64__) || defined(__x86_64__) + typedef uint64_t ppu_address_t; +#else + typedef uint32_t ppu_address_t; +#endif //defined(_WIN64) + +#endif //BT_PPU_ADDRESS_SPACE_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.cpp b/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.cpp new file mode 100644 index 00000000..19992772 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.cpp @@ -0,0 +1,181 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 "SequentialThreadSupport.h" + + +#include "SpuCollisionTaskProcess.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + +SequentialThreadSupport::SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo) +{ + startThreads(threadConstructionInfo); +} + +///cleanup/shutdown Libspe2 +SequentialThreadSupport::~SequentialThreadSupport() +{ + stopSPU(); +} + +#include + +///send messages to SPUs +void SequentialThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) +{ + switch (uiCommand) + { + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + spuStatus.m_userPtr=(void*)uiArgument0; + spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); + } + break; + default: + { + ///not implemented + btAssert(0 && "Not implemented"); + } + + }; + + +} + +///check for messages from SPUs +void SequentialThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) +{ + btAssert(m_activeSpuStatus.size()); + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; +} + +void SequentialThreadSupport::startThreads(SequentialThreadConstructionInfo& threadConstructionInfo) +{ + m_activeSpuStatus.resize(1); + printf("STS: Not starting any threads\n"); + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + spuStatus.m_userPtr = 0; + spuStatus.m_taskId = 0; + spuStatus.m_commandId = 0; + spuStatus.m_status = 0; + spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); + spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; + printf("STS: Created local store at %p for task %s\n", spuStatus.m_lsMemory, threadConstructionInfo.m_uniqueName); +} + +void SequentialThreadSupport::startSPU() +{ +} + +void SequentialThreadSupport::stopSPU() +{ + m_activeSpuStatus.clear(); +} + +void SequentialThreadSupport::setNumTasks(int numTasks) +{ + printf("SequentialThreadSupport::setNumTasks(%d) is not implemented and has no effect\n",numTasks); +} + + + + +class btDummyBarrier : public btBarrier +{ +private: + +public: + btDummyBarrier() + { + } + + virtual ~btDummyBarrier() + { + } + + void sync() + { + } + + virtual void setMaxCount(int n) {} + virtual int getMaxCount() {return 1;} +}; + +class btDummyCriticalSection : public btCriticalSection +{ + +public: + btDummyCriticalSection() + { + } + + virtual ~btDummyCriticalSection() + { + } + + unsigned int getSharedParam(int i) + { + btAssert(i>=0&&i<31); + return mCommonBuff[i+1]; + } + + void setSharedParam(int i,unsigned int p) + { + btAssert(i>=0&&i<31); + mCommonBuff[i+1] = p; + } + + void lock() + { + mCommonBuff[0] = 1; + } + + void unlock() + { + mCommonBuff[0] = 0; + } +}; + + + + +btBarrier* SequentialThreadSupport::createBarrier() +{ + return new btDummyBarrier(); +} + +btCriticalSection* SequentialThreadSupport::createCriticalSection() +{ + return new btDummyCriticalSection(); + +} + +void SequentialThreadSupport::deleteBarrier(btBarrier* barrier) +{ + delete barrier; +} + +void SequentialThreadSupport::deleteCriticalSection(btCriticalSection* criticalSection) +{ + delete criticalSection; +} + + + + + diff --git a/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.h b/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.h new file mode 100644 index 00000000..a188ef21 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.h @@ -0,0 +1,100 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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/btScalar.h" +#include "PlatformDefinitions.h" + + +#ifndef BT_SEQUENTIAL_THREAD_SUPPORT_H +#define BT_SEQUENTIAL_THREAD_SUPPORT_H + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btThreadSupportInterface.h" + +typedef void (*SequentialThreadFunc)(void* userPtr,void* lsMemory); +typedef void* (*SequentiallsMemorySetupFunc)(); + + + +///The SequentialThreadSupport is a portable non-parallel implementation of the btThreadSupportInterface +///This is useful for debugging and porting SPU Tasks to other platforms. +class SequentialThreadSupport : public btThreadSupportInterface +{ +public: + struct btSpuStatus + { + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + SequentialThreadFunc m_userThreadFunc; + + void* m_userPtr; //for taskDesc etc + void* m_lsMemory; //initialized using SequentiallsMemorySetupFunc + }; +private: + btAlignedObjectArray m_activeSpuStatus; + btAlignedObjectArray m_completeHandles; +public: + struct SequentialThreadConstructionInfo + { + SequentialThreadConstructionInfo (const char* uniqueName, + SequentialThreadFunc userThreadFunc, + SequentiallsMemorySetupFunc lsMemoryFunc + ) + :m_uniqueName(uniqueName), + m_userThreadFunc(userThreadFunc), + m_lsMemoryFunc(lsMemoryFunc) + { + + } + + const char* m_uniqueName; + SequentialThreadFunc m_userThreadFunc; + SequentiallsMemorySetupFunc m_lsMemoryFunc; + }; + + SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo); + virtual ~SequentialThreadSupport(); + void startThreads(SequentialThreadConstructionInfo& threadInfo); +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks); + + virtual int getNumTasks() const + { + return 1; + } + virtual btBarrier* createBarrier(); + + virtual btCriticalSection* createCriticalSection(); + + virtual void deleteBarrier(btBarrier* barrier); + + virtual void deleteCriticalSection(btCriticalSection* criticalSection); + + +}; + +#endif //BT_SEQUENTIAL_THREAD_SUPPORT_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp b/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp new file mode 100644 index 00000000..182aa269 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 "SpuCollisionObjectWrapper.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + +SpuCollisionObjectWrapper::SpuCollisionObjectWrapper () +{ +} + +#ifndef __SPU__ +SpuCollisionObjectWrapper::SpuCollisionObjectWrapper (const btCollisionObject* collisionObject) +{ + m_shapeType = collisionObject->getCollisionShape()->getShapeType (); + m_collisionObjectPtr = (ppu_address_t)collisionObject; + m_margin = collisionObject->getCollisionShape()->getMargin (); +} +#endif + +int +SpuCollisionObjectWrapper::getShapeType () const +{ + return m_shapeType; +} + +float +SpuCollisionObjectWrapper::getCollisionMargin () const +{ + return m_margin; +} + +ppu_address_t +SpuCollisionObjectWrapper::getCollisionObjectPtr () const +{ + return m_collisionObjectPtr; +} diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h b/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h new file mode 100644 index 00000000..f90da277 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_SPU_COLLISION_OBJECT_WRAPPER_H +#define BT_SPU_COLLISION_OBJECT_WRAPPER_H + +#include "PlatformDefinitions.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +ATTRIBUTE_ALIGNED16(class) SpuCollisionObjectWrapper +{ +protected: + int m_shapeType; + float m_margin; + ppu_address_t m_collisionObjectPtr; + +public: + SpuCollisionObjectWrapper (); + + SpuCollisionObjectWrapper (const btCollisionObject* collisionObject); + + int getShapeType () const; + float getCollisionMargin () const; + ppu_address_t getCollisionObjectPtr () const; +}; + + +#endif //BT_SPU_COLLISION_OBJECT_WRAPPER_H diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp b/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp new file mode 100644 index 00000000..f606d136 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp @@ -0,0 +1,317 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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. +*/ + + +//#define DEBUG_SPU_TASK_SCHEDULING 1 + + +//class OptimizedBvhNode; + +#include "SpuCollisionTaskProcess.h" + + + + +void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks) +{ + if (int(m_maxNumOutstandingTasks) != maxNumTasks) + { + m_maxNumOutstandingTasks = maxNumTasks; + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks); + + for (int i = 0; i < m_taskBusy.size(); i++) + { + m_taskBusy[i] = false; + } + + ///re-allocate task memory buffers + if (m_workUnitTaskBuffers != 0) + { + btAlignedFree(m_workUnitTaskBuffers); + } + + m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128); + } + +} + + + +SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(0) +{ + m_workUnitTaskBuffers = (unsigned char *)0; + setNumTasks(maxNumOutstandingTasks); + m_numBusyTasks = 0; + m_currentTask = 0; + m_currentPage = 0; + m_currentPageEntry = 0; + +#ifdef DEBUG_SpuCollisionTaskProcess + m_initialized = false; +#endif + + m_threadInterface->startSPU(); + + //printf("sizeof vec_float4: %d\n", sizeof(vec_float4)); + printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput))); + +} + +SpuCollisionTaskProcess::~SpuCollisionTaskProcess() +{ + + if (m_workUnitTaskBuffers != 0) + { + btAlignedFree(m_workUnitTaskBuffers); + m_workUnitTaskBuffers = 0; + } + + + + m_threadInterface->stopSPU(); + +} + + + +void SpuCollisionTaskProcess::initialize2(bool useEpa) +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuCollisionTaskProcess::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + for (int i = 0; i < int (m_maxNumOutstandingTasks); i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_currentPage = 0; + m_currentPageEntry = 0; + m_useEpa = useEpa; + +#ifdef DEBUG_SpuCollisionTaskProcess + m_initialized = true; + btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE); +#endif +} + + +void SpuCollisionTaskProcess::issueTask2() +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask); +#endif //DEBUG_SPU_TASK_SCHEDULING + + m_taskBusy[m_currentTask] = true; + m_numBusyTasks++; + + + SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask]; + taskDesc.m_useEpa = m_useEpa; + + { + // send task description in event message + // no error checking here... + // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. + + taskDesc.m_inPairPtr = reinterpret_cast(MIDPHASE_TASK_PTR(m_currentTask)); + + taskDesc.taskId = m_currentTask; + taskDesc.numPages = m_currentPage+1; + taskDesc.numOnLastPage = m_currentPageEntry; + } + + + + m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask); + + // if all tasks busy, wait for spu event to clear the task. + + + if (m_numBusyTasks >= m_maxNumOutstandingTasks) + { + unsigned int taskId; + unsigned int outputSize; + + + for (int i=0;i=0); + + + m_threadInterface->waitForResponse(&taskId, &outputSize); + +// printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks); + + //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); + + //postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + +} + +void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex) +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("#"); +#endif //DEBUG_SPU_TASK_SCHEDULING + +#ifdef DEBUG_SpuCollisionTaskProcess + btAssert(m_initialized); + btAssert(m_workUnitTaskBuffers); + +#endif + + bool batch = true; + + if (batch) + { + if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE) + { + if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1) + { + // task buffer is full, issue current task. + // if all task buffers busy, this waits until SPU is done. + issueTask2(); + + // find new task buffer + for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + //init the task data + + break; + } + } + + m_currentPage = 0; + } + else + { + m_currentPage++; + } + + m_currentPageEntry = 0; + } + } + + { + + + + SpuGatherAndProcessWorkUnitInput &wuInput = + *(reinterpret_cast + (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry))); + + wuInput.m_pairArrayPtr = reinterpret_cast(pairArrayPtr); + wuInput.m_startIndex = startIndex; + wuInput.m_endIndex = endIndex; + + + + m_currentPageEntry++; + + if (!batch) + { + issueTask2(); + + // find new task buffer + for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + //init the task data + + break; + } + } + + m_currentPage = 0; + m_currentPageEntry =0; + } + } +} + + +void +SpuCollisionTaskProcess::flush2() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("\nSpuCollisionTaskProcess::flush()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + // if there's a partially filled task buffer, submit that task + if (m_currentPage > 0 || m_currentPageEntry > 0) + { + issueTask2(); + } + + + // all tasks are issued, wait for all tasks to be complete + while(m_numBusyTasks > 0) + { + // Consolidating SPU code + unsigned int taskId=-1; + unsigned int outputSize; + + for (int i=0;i=0); + + + { + + // SPURS support. + m_threadInterface->waitForResponse(&taskId, &outputSize); + } +// printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks); + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + //postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.h b/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.h new file mode 100644 index 00000000..23b5b05a --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.h @@ -0,0 +1,163 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_SPU_COLLISION_TASK_PROCESS_H +#define BT_SPU_COLLISION_TASK_PROCESS_H + +#include + +#include "LinearMath/btScalar.h" + +#include "PlatformDefinitions.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory + +#include "btThreadSupportInterface.h" + + +//#include "SPUAssert.h" +#include + + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include "LinearMath/btAlignedAllocator.h" + +#include + + +#define DEBUG_SpuCollisionTaskProcess 1 + + +#define CMD_GATHER_AND_PROCESS_PAIRLIST 1 + +class btCollisionObject; +class btPersistentManifold; +class btDispatcher; + + +/////Task Description for SPU collision detection +//struct SpuGatherAndProcessPairsTaskDesc +//{ +// uint64_t inPtr;//m_pairArrayPtr; +// //mutex variable +// uint32_t m_someMutexVariableInMainMemory; +// +// uint64_t m_dispatcher; +// +// uint32_t numOnLastPage; +// +// uint16_t numPages; +// uint16_t taskId; +// +// struct CollisionTask_LocalStoreMemory* m_lsMemory; +//} +// +//#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) +//__attribute__ ((aligned (16))) +//#endif +//; + + +///MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input, to be processed by the SPU. +ATTRIBUTE_ALIGNED16(struct) SpuGatherAndProcessWorkUnitInput +{ + uint64_t m_pairArrayPtr; + int m_startIndex; + int m_endIndex; +}; + + + + +/// SpuCollisionTaskProcess handles SPU processing of collision pairs. +/// Maintains a set of task buffers. +/// When the task is full, the task is issued for SPUs to process. Contact output goes into btPersistentManifold +/// associated with each task. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class SpuCollisionTaskProcess +{ + + unsigned char *m_workUnitTaskBuffers; + + + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArray m_spuGatherTaskDesc; + + class btThreadSupportInterface* m_threadInterface; + + unsigned int m_maxNumOutstandingTasks; + + unsigned int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + unsigned int m_currentTask; + unsigned int m_currentPage; + unsigned int m_currentPageEntry; + + bool m_useEpa; + +#ifdef DEBUG_SpuCollisionTaskProcess + bool m_initialized; +#endif + void issueTask2(); + //void postProcess(unsigned int taskId, int outputSize); + +public: + SpuCollisionTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks); + + ~SpuCollisionTaskProcess(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize2(bool useEpa = false); + + ///batch up additional work to a current task for SPU processing. When batch is full, it issues the task. + void addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush2(); + + /// set the maximum number of SPU tasks allocated + void setNumTasks(int maxNumTasks); + + int getNumTasks() const + { + return m_maxNumOutstandingTasks; + } +}; + + + +#define MIDPHASE_TASK_PTR(task) (&m_workUnitTaskBuffers[0] + MIDPHASE_WORKUNIT_TASK_SIZE*task) +#define MIDPHASE_ENTRY_PTR(task,page,entry) (MIDPHASE_TASK_PTR(task) + MIDPHASE_WORKUNIT_PAGE_SIZE*page + sizeof(SpuGatherAndProcessWorkUnitInput)*entry) +#define MIDPHASE_OUTPUT_PTR(task) (&m_contactOutputBuffers[0] + MIDPHASE_MAX_CONTACT_BUFFER_SIZE*task) +#define MIDPHASE_TREENODES_PTR(task) (&m_complexShapeBuffers[0] + MIDPHASE_COMPLEX_SHAPE_BUFFER_SIZE*task) + + +#define MIDPHASE_WORKUNIT_PAGE_SIZE (16) +//#define MIDPHASE_WORKUNIT_PAGE_SIZE (128) + +#define MIDPHASE_NUM_WORKUNIT_PAGES 1 +#define MIDPHASE_WORKUNIT_TASK_SIZE (MIDPHASE_WORKUNIT_PAGE_SIZE*MIDPHASE_NUM_WORKUNIT_PAGES) +#define MIDPHASE_NUM_WORKUNITS_PER_PAGE (MIDPHASE_WORKUNIT_PAGE_SIZE / sizeof(SpuGatherAndProcessWorkUnitInput)) +#define MIDPHASE_NUM_WORKUNITS_PER_TASK (MIDPHASE_NUM_WORKUNITS_PER_PAGE*MIDPHASE_NUM_WORKUNIT_PAGES) + + +#endif // BT_SPU_COLLISION_TASK_PROCESS_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp b/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp new file mode 100644 index 00000000..62cf4f0f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 "SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" + + + + +void SpuContactManifoldCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btAssert(0); +} + +btScalar SpuContactManifoldCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + btAssert(0); + return 1.f; +} + +#ifndef __SPU__ +SpuContactManifoldCollisionAlgorithm::SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObject* body0,const btCollisionObject* body1) +:btCollisionAlgorithm(ci) +#ifdef USE_SEPDISTANCE_UTIL +,m_sepDistance(body0->getCollisionShape()->getAngularMotionDisc(),body1->getCollisionShape()->getAngularMotionDisc()) +#endif //USE_SEPDISTANCE_UTIL +{ + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_shapeType0 = body0->getCollisionShape()->getShapeType(); + m_shapeType1 = body1->getCollisionShape()->getShapeType(); + m_collisionMargin0 = body0->getCollisionShape()->getMargin(); + m_collisionMargin1 = body1->getCollisionShape()->getMargin(); + m_collisionObject0 = body0; + m_collisionObject1 = body1; + + if (body0->getCollisionShape()->isPolyhedral()) + { + btPolyhedralConvexShape* convex0 = (btPolyhedralConvexShape*)body0->getCollisionShape(); + m_shapeDimensions0 = convex0->getImplicitShapeDimensions(); + } + if (body1->getCollisionShape()->isPolyhedral()) + { + btPolyhedralConvexShape* convex1 = (btPolyhedralConvexShape*)body1->getCollisionShape(); + m_shapeDimensions1 = convex1->getImplicitShapeDimensions(); + } +} +#endif //__SPU__ + + +SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm() +{ + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); +} diff --git a/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h b/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h new file mode 100644 index 00000000..14b0a945 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h @@ -0,0 +1,121 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H +#define BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "LinearMath/btTransformUtil.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +class btPersistentManifold; + +//#define USE_SEPDISTANCE_UTIL 1 + +/// SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU. +ATTRIBUTE_ALIGNED16(class) SpuContactManifoldCollisionAlgorithm : public btCollisionAlgorithm +{ + btVector3 m_shapeDimensions0; + btVector3 m_shapeDimensions1; + btPersistentManifold* m_manifoldPtr; + int m_shapeType0; + int m_shapeType1; + float m_collisionMargin0; + float m_collisionMargin1; + + const btCollisionObject* m_collisionObject0; + const btCollisionObject* m_collisionObject1; + + + + +public: + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + + SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObject* body0,const btCollisionObject* body1); +#ifdef USE_SEPDISTANCE_UTIL + btConvexSeparatingDistanceUtil m_sepDistance; +#endif //USE_SEPDISTANCE_UTIL + + virtual ~SpuContactManifoldCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr) + manifoldArray.push_back(m_manifoldPtr); + } + + btPersistentManifold* getContactManifoldPtr() + { + return m_manifoldPtr; + } + + const btCollisionObject* getCollisionObject0() + { + return m_collisionObject0; + } + + const btCollisionObject* getCollisionObject1() + { + return m_collisionObject1; + } + + int getShapeType0() const + { + return m_shapeType0; + } + + int getShapeType1() const + { + return m_shapeType1; + } + float getCollisionMargin0() const + { + return m_collisionMargin0; + } + float getCollisionMargin1() const + { + return m_collisionMargin1; + } + + const btVector3& getShapeDimensions0() const + { + return m_shapeDimensions0; + } + + const btVector3& getShapeDimensions1() const + { + return m_shapeDimensions1; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(SpuContactManifoldCollisionAlgorithm)); + return new(mem) SpuContactManifoldCollisionAlgorithm(ci,body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + } + }; + +}; + +#endif //BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletMultiThreaded/SpuDoubleBuffer.h b/Code/Physics/src/BulletMultiThreaded/SpuDoubleBuffer.h new file mode 100644 index 00000000..558d6152 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuDoubleBuffer.h @@ -0,0 +1,126 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_DOUBLE_BUFFER_H +#define BT_DOUBLE_BUFFER_H + +#include "SpuFakeDma.h" +#include "LinearMath/btScalar.h" + + +///DoubleBuffer +template +class DoubleBuffer +{ +#if defined(__SPU__) || defined(USE_LIBSPE2) + ATTRIBUTE_ALIGNED128( T m_buffer0[size] ) ; + ATTRIBUTE_ALIGNED128( T m_buffer1[size] ) ; +#else + T m_buffer0[size]; + T m_buffer1[size]; +#endif + + T *m_frontBuffer; + T *m_backBuffer; + + unsigned int m_dmaTag; + bool m_dmaPending; +public: + bool isPending() const { return m_dmaPending;} + DoubleBuffer(); + + void init (); + + // dma get and put commands + void backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag); + void backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag); + + // gets pointer to a buffer + T *getFront(); + T *getBack(); + + // if back buffer dma was started, wait for it to complete + // then move back to front and vice versa + T *swapBuffers(); +}; + +template +DoubleBuffer::DoubleBuffer() +{ + init (); +} + +template +void DoubleBuffer::init() +{ + this->m_dmaPending = false; + this->m_frontBuffer = &this->m_buffer0[0]; + this->m_backBuffer = &this->m_buffer1[0]; +} + +template +void +DoubleBuffer::backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag) +{ + m_dmaPending = true; + m_dmaTag = tag; + if (numBytes) + { + m_backBuffer = (T*)cellDmaLargeGetReadOnly(m_backBuffer, ea, numBytes, tag, 0, 0); + } +} + +template +void +DoubleBuffer::backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag) +{ + m_dmaPending = true; + m_dmaTag = tag; + cellDmaLargePut(m_backBuffer, ea, numBytes, tag, 0, 0); +} + +template +T * +DoubleBuffer::getFront() +{ + return m_frontBuffer; +} + +template +T * +DoubleBuffer::getBack() +{ + return m_backBuffer; +} + +template +T * +DoubleBuffer::swapBuffers() +{ + if (m_dmaPending) + { + cellDmaWaitTagStatusAll(1< //for btAssert +//Disabling memcpy sometimes helps debugging DMA + +#define USE_MEMCPY 1 +#ifdef USE_MEMCPY + +#endif + + +void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) +{ + +#if defined (__SPU__) || defined (USE_LIBSPE2) + cellDmaLargeGet(ls,ea,size,tag,tid,rid); + return ls; +#else + return (void*)(ppu_address_t)ea; +#endif +} + +void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) +{ +#if defined (__SPU__) || defined (USE_LIBSPE2) + mfc_get(ls,ea,size,tag,0,0); + return ls; +#else + return (void*)(ppu_address_t)ea; +#endif +} + + + + +void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) +{ +#if defined (__SPU__) || defined (USE_LIBSPE2) + cellDmaGet(ls,ea,size,tag,tid,rid); + return ls; +#else + return (void*)(ppu_address_t)ea; +#endif +} + + +///this unalignedDma should not be frequently used, only for small data. It handles alignment and performs check on size (<16 bytes) +int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size) +{ + + btAssert(size<32); + + ATTRIBUTE_ALIGNED16(char tmpBuffer[32]); + + + char* localStore = (char*)ls; + uint32_t i; + + + ///make sure last 4 bits are the same, for cellDmaSmallGet + uint32_t last4BitsOffset = ea & 0x0f; + char* tmpTarget = tmpBuffer + last4BitsOffset; + +#if defined (__SPU__) || defined (USE_LIBSPE2) + + int remainingSize = size; + +//#define FORCE_cellDmaUnalignedGet 1 +#ifdef FORCE_cellDmaUnalignedGet + cellDmaUnalignedGet(tmpTarget,ea,size,DMA_TAG(1),0,0); +#else + char* remainingTmpTarget = tmpTarget; + uint64_t remainingEa = ea; + + while (remainingSize) + { + switch (remainingSize) + { + case 1: + case 2: + case 4: + case 8: + case 16: + { + mfc_get(remainingTmpTarget,remainingEa,remainingSize,DMA_TAG(1),0,0); + remainingSize=0; + break; + } + default: + { + //spu_printf("unaligned DMA with non-natural size:%d\n",remainingSize); + int actualSize = 0; + + if (remainingSize > 16) + actualSize = 16; + else + if (remainingSize >8) + actualSize=8; + else + if (remainingSize >4) + actualSize=4; + else + if (remainingSize >2) + actualSize=2; + mfc_get(remainingTmpTarget,remainingEa,actualSize,DMA_TAG(1),0,0); + remainingSize-=actualSize; + remainingTmpTarget+=actualSize; + remainingEa += actualSize; + } + } + } +#endif//FORCE_cellDmaUnalignedGet + +#else + char* mainMem = (char*)ea; + //copy into final destination +#ifdef USE_MEMCPY + + memcpy(tmpTarget,mainMem,size); +#else + for ( i=0;i +#include + +#define DMA_TAG(xfer) (xfer + 1) +#define DMA_MASK(xfer) (1 << DMA_TAG(xfer)) + +#else // !USE_LIBSPE2 + +#define DMA_TAG(xfer) (xfer + 1) +#define DMA_MASK(xfer) (1 << DMA_TAG(xfer)) + +#include + +#define DEBUG_DMA +#ifdef DEBUG_DMA +#define dUASSERT(a,b) if (!(a)) { printf(b);} +#define uintsize ppu_address_t + +#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ + } \ + mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ + } \ + mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaLargePut(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("PUT %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ls,(unsigned int)ea,(unsigned int)size); \ + } \ + mfc_put(ls, ea, size, tag, tid, rid) +#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ + dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ + dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ + dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ + dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ + dUASSERT(size < 16384, "size too big: "); \ + dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ + dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ + printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ + } \ + mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all() + +#else +#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaLargePut(ls, ea, size, tag, tid, rid) mfc_put(ls, ea, size, tag, tid, rid) +#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) +#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all() +#endif // DEBUG_DMA + + + + + + + + +#endif // USE_LIBSPE2 +#else // !__SPU__ +//Simulate DMA using memcpy or direct access on non-CELL platforms that don't have DMAs and SPUs (Win32, Mac, Linux etc) +//Potential to add networked simulation using this interface + +#define DMA_TAG(a) (a) +#define DMA_MASK(a) (a) + + /// cellDmaLargeGet Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) + int cellDmaLargeGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + int cellDmaGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + /// cellDmaLargePut Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) + int cellDmaLargePut(const void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + /// cellDmaWaitTagStatusAll Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) + void cellDmaWaitTagStatusAll(int ignore); + + +#endif //__CELLOS_LV2__ + +///stallingUnalignedDmaSmallGet internally uses DMA_TAG(1) +int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size); + + +void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); +void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); +void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); + + +#endif //BT_FAKE_DMA_H diff --git a/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp b/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp new file mode 100644 index 00000000..c8712dab --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp @@ -0,0 +1,283 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 "SpuGatheringCollisionDispatcher.h" +#include "SpuCollisionTaskProcess.h" + + +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "LinearMath/btQuickprof.h" +#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + + + + +SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration) +:btCollisionDispatcher(collisionConfiguration), +m_spuCollisionTaskProcess(0), +m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + +} + + +bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1) +{ + bool supported0 = ( + (proxyType0 == BOX_SHAPE_PROXYTYPE) || + (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) || + (proxyType0 == SPHERE_SHAPE_PROXYTYPE) || + (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) || + (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) || +// (proxyType0 == CONE_SHAPE_PROXYTYPE) || + (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) || + (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)|| + (proxyType0 == STATIC_PLANE_PROXYTYPE)|| + (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) + ); + + bool supported1 = ( + (proxyType1 == BOX_SHAPE_PROXYTYPE) || + (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) || + (proxyType1 == SPHERE_SHAPE_PROXYTYPE) || + (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) || + (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) || +// (proxyType1 == CONE_SHAPE_PROXYTYPE) || + (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) || + (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) || + (proxyType1 == STATIC_PLANE_PROXYTYPE) || + (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) + ); + + + return supported0 && supported1; +} + + + +SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher() +{ + if (m_spuCollisionTaskProcess) + delete m_spuCollisionTaskProcess; + +} + +#include "stdio.h" + + + +///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) +///this is useful for the collision dispatcher. +class btSpuCollisionPairCallback : public btOverlapCallback +{ + const btDispatcherInfo& m_dispatchInfo; + SpuGatheringCollisionDispatcher* m_dispatcher; + +public: + + btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher* dispatcher) + :m_dispatchInfo(dispatchInfo), + m_dispatcher(dispatcher) + { + } + + virtual bool processOverlap(btBroadphasePair& collisionPair) + { + + + //PPU version + //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo); + + //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD + btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE); + + //by default, Bullet will use this near callback + { + ///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks) + if (!collisionPair.m_internalTmpValue) + { + collisionPair.m_internalTmpValue = 1; + } + if (!collisionPair.m_algorithm) + { + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + ci.m_manifold = 0; + + if (m_dispatcher->needsCollision(colObj0,colObj1)) + { + int proxyType0 = colObj0->getCollisionShape()->getShapeType(); + int proxyType1 = colObj1->getCollisionShape()->getShapeType(); + bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) + && ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0) + && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0); + + if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) + { + btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape(); + if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) + { + //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); + supportsSpuDispatch = false; + } + } + + if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) + { + btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape(); + if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) + { + //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); + supportsSpuDispatch = false; + } + } + + if (supportsSpuDispatch) + { + + int so = sizeof(SpuContactManifoldCollisionAlgorithm); +#ifdef ALLOCATE_SEPARATELY + void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so); +#else + void* mem = m_dispatcher->allocateCollisionAlgorithm(so); +#endif + collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1); + collisionPair.m_internalTmpValue = 2; + } else + { + btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1); + btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1); + + collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1); + collisionPair.m_internalTmpValue = 3; + } + } + } + } + return false; + } +}; + +void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) +{ + + if (dispatchInfo.m_enableSPU) + { + m_maxNumOutstandingTasks = m_threadInterface->getNumTasks(); + + { + BT_PROFILE("processAllOverlappingPairs"); + + if (!m_spuCollisionTaskProcess) + m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks); + + m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks); + // printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks); + + m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa); + + + ///modified version of btCollisionDispatcher::dispatchAllCollisionPairs: + { + btSpuCollisionPairCallback collisionCallback(dispatchInfo,this); + + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); + } + } + + //send one big batch + int numTotalPairs = pairCache->getNumOverlappingPairs(); + if (numTotalPairs) + { + btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr(); + int i; + { + int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS; + if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS)) + { + pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1; + } + + BT_PROFILE("addWorkToTask"); + for (i=0;iaddWorkToTask(pairPtr,i,endIndex); + i = endIndex; + } + } + { + BT_PROFILE("PPU fallback"); + //handle PPU fallback pairs + for (i=0;im_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher->needsCollision(colObj0,colObj1)) + { + //discrete collision detection query + btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1); + btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1); + + btManifoldResult contactPointResult(&ob0,&ob1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + + collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + } + } + } + } + { + BT_PROFILE("flush2"); + //make sure all SPU work is done + m_spuCollisionTaskProcess->flush2(); + } + + } else + { + ///PPU fallback + ///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU + btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher); + } +} diff --git a/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h b/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h new file mode 100644 index 00000000..f8bc7da6 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h @@ -0,0 +1,72 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_SPU_GATHERING_COLLISION__DISPATCHER_H +#define BT_SPU_GATHERING_COLLISION__DISPATCHER_H + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + + +///Tuning value to optimized SPU utilization +///Too small value means Task overhead is large compared to computation (too fine granularity) +///Too big value might render some SPUs are idle, while a few other SPUs are doing all work. +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64 +#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 512 +//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024 + + + +class SpuCollisionTaskProcess; + +///SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection +///Time of Impact, Closest Points and Penetration Depth. +class SpuGatheringCollisionDispatcher : public btCollisionDispatcher +{ + + SpuCollisionTaskProcess* m_spuCollisionTaskProcess; + +protected: + + class btThreadSupportInterface* m_threadInterface; + + unsigned int m_maxNumOutstandingTasks; + + +public: + + //can be used by SPU collision algorithms + SpuCollisionTaskProcess* getSpuCollisionTaskProcess() + { + return m_spuCollisionTaskProcess; + } + + SpuGatheringCollisionDispatcher (class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration); + + virtual ~SpuGatheringCollisionDispatcher(); + + bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1); + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; + +}; + + + +#endif //BT_SPU_GATHERING_COLLISION__DISPATCHER_H + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.cpp b/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.cpp new file mode 100644 index 00000000..a312450e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.cpp @@ -0,0 +1,257 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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. +*/ + +#ifdef USE_LIBSPE2 + +#include "SpuLibspe2Support.h" + + + + +//SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +///Setup and initialize SPU/CELL/Libspe2 +SpuLibspe2Support::SpuLibspe2Support(spe_program_handle_t *speprog, int numThreads) +{ + this->program = speprog; + this->numThreads = ((numThreads <= spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)) ? numThreads : spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)); +} + +///cleanup/shutdown Libspe2 +SpuLibspe2Support::~SpuLibspe2Support() +{ + + stopSPU(); +} + + + +///send messages to SPUs +void SpuLibspe2Support::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1) +{ + spe_context_ptr_t context; + + switch (uiCommand) + { + case CMD_SAMPLE_TASK_COMMAND: + { + //get taskdescription + SpuSampleTaskDesc* taskDesc = (SpuSampleTaskDesc*) uiArgument0; + + btAssert(taskDesc->m_taskIdm_taskId]; + + //set data for spuStatus + spuStatus.m_commandId = uiCommand; + spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" + spuStatus.m_taskDesc.p = taskDesc; + + //get context + context = data[taskDesc->m_taskId].context; + + + taskDesc->m_mainMemoryPtr = reinterpret_cast (spuStatus.m_lsMemory.p); + + + break; + } + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + //get taskdescription + SpuGatherAndProcessPairsTaskDesc* taskDesc = (SpuGatherAndProcessPairsTaskDesc*) uiArgument0; + + btAssert(taskDesc->taskIdtaskId]; + + //set data for spuStatus + spuStatus.m_commandId = uiCommand; + spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" + spuStatus.m_taskDesc.p = taskDesc; + + //get context + context = data[taskDesc->taskId].context; + + + taskDesc->m_lsMemory = (CollisionTask_LocalStoreMemory*)spuStatus.m_lsMemory.p; + + break; + } + default: + { + ///not implemented + btAssert(0); + } + + }; + + + //write taskdescription in mailbox + unsigned int event = Spu_Mailbox_Event_Task; + spe_in_mbox_write(context, &event, 1, SPE_MBOX_ANY_NONBLOCKING); + +} + +///check for messages from SPUs +void SpuLibspe2Support::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) +{ + ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response + + ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' + + btAssert(m_activeSpuStatus.size()); + + + int last = -1; + + //find an active spu/thread + while(last < 0) + { + for (int i=0;i=0); + + + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; + + +} + + +void SpuLibspe2Support::startSPU() +{ + this->internal_startSPU(); +} + + + +///start the spus group (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) +void SpuLibspe2Support::internal_startSPU() +{ + m_activeSpuStatus.resize(numThreads); + + + for (int i=0; i < numThreads; i++) + { + + if(data[i].context == NULL) + { + + /* Create context */ + if ((data[i].context = spe_context_create(0, NULL)) == NULL) + { + perror ("Failed creating context"); + exit(1); + } + + /* Load program into context */ + if(spe_program_load(data[i].context, this->program)) + { + perror ("Failed loading program"); + exit(1); + } + + m_activeSpuStatus[i].m_status = Spu_Status_Startup; + m_activeSpuStatus[i].m_taskId = i; + m_activeSpuStatus[i].m_commandId = 0; + m_activeSpuStatus[i].m_lsMemory.p = NULL; + + + data[i].entry = SPE_DEFAULT_ENTRY; + data[i].flags = 0; + data[i].argp.p = &m_activeSpuStatus[i]; + data[i].envp.p = NULL; + + /* Create thread for each SPE context */ + if (pthread_create(&data[i].pthread, NULL, &ppu_pthread_function, &(data[i]) )) + { + perror ("Failed creating thread"); + exit(1); + } + /* + else + { + printf("started thread %d\n",i); + }*/ + } + } + + + for (int i=0; i < numThreads; i++) + { + if(data[i].context != NULL) + { + while( m_activeSpuStatus[i].m_status == Spu_Status_Startup) + { + // wait for spu to set up + sched_yield(); + } + printf("Spu %d is ready\n", i); + } + } +} + +///tell the task scheduler we are done with the SPU tasks +void SpuLibspe2Support::stopSPU() +{ + // wait for all threads to finish + int i; + for ( i = 0; i < this->numThreads; i++ ) + { + + unsigned int event = Spu_Mailbox_Event_Shutdown; + spe_context_ptr_t context = data[i].context; + spe_in_mbox_write(context, &event, 1, SPE_MBOX_ALL_BLOCKING); + pthread_join (data[i].pthread, NULL); + + } + // close SPE program + spe_image_close(program); + // destroy SPE contexts + for ( i = 0; i < this->numThreads; i++ ) + { + if(data[i].context != NULL) + { + spe_context_destroy (data[i].context); + } + } + + m_activeSpuStatus.clear(); + +} + + + +#endif //USE_LIBSPE2 + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.h b/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.h new file mode 100644 index 00000000..37a5e79f --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.h @@ -0,0 +1,180 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_SPU_LIBSPE2_SUPPORT_H +#define BT_SPU_LIBSPE2_SUPPORT_H + +#include //for uint32_t etc. + +#ifdef USE_LIBSPE2 + +#include +#include +//#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" +#include "PlatformDefinitions.h" + + +//extern struct SpuGatherAndProcessPairsTaskDesc; + +enum +{ + Spu_Mailbox_Event_Nothing = 0, + Spu_Mailbox_Event_Task = 1, + Spu_Mailbox_Event_Shutdown = 2, + + Spu_Mailbox_Event_ForceDword = 0xFFFFFFFF + +}; + +enum +{ + Spu_Status_Free = 0, + Spu_Status_Occupied = 1, + Spu_Status_Startup = 2, + + Spu_Status_ForceDword = 0xFFFFFFFF + +}; + + +struct btSpuStatus +{ + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + addr64 m_taskDesc; + addr64 m_lsMemory; + +} +__attribute__ ((aligned (128))) +; + + + +#ifndef __SPU__ + +#include "LinearMath/btAlignedObjectArray.h" +#include "SpuCollisionTaskProcess.h" +#include "SpuSampleTaskProcess.h" +#include "btThreadSupportInterface.h" +#include +#include +#include + +#define MAX_SPUS 4 + +typedef struct ppu_pthread_data +{ + spe_context_ptr_t context; + pthread_t pthread; + unsigned int entry; + unsigned int flags; + addr64 argp; + addr64 envp; + spe_stop_info_t stopinfo; +} ppu_pthread_data_t; + + +static void *ppu_pthread_function(void *arg) +{ + ppu_pthread_data_t * datap = (ppu_pthread_data_t *)arg; + /* + int rc; + do + {*/ + spe_context_run(datap->context, &datap->entry, datap->flags, datap->argp.p, datap->envp.p, &datap->stopinfo); + if (datap->stopinfo.stop_reason == SPE_EXIT) + { + if (datap->stopinfo.result.spe_exit_code != 0) + { + perror("FAILED: SPE returned a non-zero exit status: \n"); + exit(1); + } + } + else + { + perror("FAILED: SPE abnormally terminated\n"); + exit(1); + } + + + //} while (rc > 0); // loop until exit or error, and while any stop & signal + pthread_exit(NULL); +} + + + + + + +///SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +class SpuLibspe2Support : public btThreadSupportInterface +{ + + btAlignedObjectArray m_activeSpuStatus; + +public: + //Setup and initialize SPU/CELL/Libspe2 + SpuLibspe2Support(spe_program_handle_t *speprog,int numThreads); + + // SPE program handle ptr. + spe_program_handle_t *program; + + // SPE program data + ppu_pthread_data_t data[MAX_SPUS]; + + //cleanup/shutdown Libspe2 + ~SpuLibspe2Support(); + + ///send messages to SPUs + void sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1=0); + + //check for messages from SPUs + void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); + + //start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); + + //tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks) + { + //changing the number of tasks after initialization is not implemented (yet) + } + +private: + + ///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + void internal_startSPU(); + + + + + int numThreads; + +}; + +#endif // NOT __SPU__ + +#endif //USE_LIBSPE2 + +#endif //BT_SPU_LIBSPE2_SUPPORT_H + + + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h new file mode 100644 index 00000000..e5179611 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h @@ -0,0 +1,167 @@ +/* + Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. + All rights reserved. + +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 __BOX_H__ +#define __BOX_H__ + + +#ifndef PE_REF +#define PE_REF(a) a& +#endif + +#include + + +#include "../PlatformDefinitions.h" + + + + +enum FeatureType { F, E, V }; + +//---------------------------------------------------------------------------- +// Box +//---------------------------------------------------------------------------- +///The Box is an internal class used by the boxBoxDistance calculation. +class Box +{ +public: + vmVector3 mHalf; + + inline Box() + {} + inline Box(PE_REF(vmVector3) half_); + inline Box(float hx, float hy, float hz); + + inline void Set(PE_REF(vmVector3) half_); + inline void Set(float hx, float hy, float hz); + + inline vmVector3 GetAABB(const vmMatrix3& rotation) const; +}; + +inline +Box::Box(PE_REF(vmVector3) half_) +{ + Set(half_); +} + +inline +Box::Box(float hx, float hy, float hz) +{ + Set(hx, hy, hz); +} + +inline +void +Box::Set(PE_REF(vmVector3) half_) +{ + mHalf = half_; +} + +inline +void +Box::Set(float hx, float hy, float hz) +{ + mHalf = vmVector3(hx, hy, hz); +} + +inline +vmVector3 +Box::GetAABB(const vmMatrix3& rotation) const +{ + return absPerElem(rotation) * mHalf; +} + +//------------------------------------------------------------------------------------------------- +// BoxPoint +//------------------------------------------------------------------------------------------------- + +///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation. +class BoxPoint +{ +public: + BoxPoint() : localPoint(0.0f) {} + + vmPoint3 localPoint; + FeatureType featureType; + int featureIdx; + + inline void setVertexFeature(int plusX, int plusY, int plusZ); + inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1); + inline void setFaceFeature(int dim, int plus); + + inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const; + inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const; + inline void getFaceFeature(int & dim, int & plus) const; +}; + +inline +void +BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ) +{ + featureType = V; + featureIdx = plusX << 2 | plusY << 1 | plusZ; +} + +inline +void +BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1) +{ + featureType = E; + + if (dim0 > dim1) { + featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0; + } else { + featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1; + } +} + +inline +void +BoxPoint::setFaceFeature(int dim, int plus) +{ + featureType = F; + featureIdx = plus << 2 | dim; +} + +inline +void +BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const +{ + plusX = featureIdx >> 2; + plusY = featureIdx >> 1 & 1; + plusZ = featureIdx & 1; +} + +inline +void +BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const +{ + plus0 = featureIdx >> 5; + dim0 = featureIdx >> 3 & 3; + plus1 = featureIdx >> 2 & 1; + dim1 = featureIdx & 3; +} + +inline +void +BoxPoint::getFaceFeature(int & dim, int & plus) const +{ + plus = featureIdx >> 2; + dim = featureIdx & 3; +} + +#endif /* __BOX_H__ */ diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp new file mode 100644 index 00000000..8d755b22 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp @@ -0,0 +1,302 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "SpuCollisionShapes.h" + +///not supported on IBM SDK, until we fix the alignment of btVector3 +#if defined (__CELLOS_LV2__) && defined (__SPU__) +#include +static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 ) +{ + vec_float4 result; + result = spu_mul( vec0, vec1 ); + result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); + return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); +} +#endif //__SPU__ + + +void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform) +{ + //calculate the aabb, given the types... + switch (shapeType) + { + case CYLINDER_SHAPE_PROXYTYPE: + /* fall through */ + case BOX_SHAPE_PROXYTYPE: + { + btScalar margin=convexShape->getMarginNV(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + halfExtents += btVector3(margin,margin,margin); + const btTransform& t = xform; + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] ); + + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + btScalar margin=convexShape->getMarginNV(); + btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); + //add the radius to y-axis to get full height + btScalar radius = halfExtents[0]; + halfExtents[1] += radius; + halfExtents += btVector3(margin,margin,margin); +#if 0 + int capsuleUpAxis = convexShape->getUpAxis(); + btScalar halfHeight = convexShape->getHalfHeight(); + btScalar radius = convexShape->getRadius(); + halfExtents[capsuleUpAxis] = radius + halfHeight; +#endif + const btTransform& t = xform; + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] ); + + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case SPHERE_SHAPE_PROXYTYPE: + { + btScalar radius = convexShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); + btScalar margin = radius + convexShape->getMarginNV(); + const btTransform& t = xform; + const btVector3& center = t.getOrigin(); + btVector3 extent(margin,margin,margin); + aabbMin = center - extent; + aabbMax = center + extent; + break; + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); + cellDmaGet(&convexHullShape0, convexShapePtr , sizeof(btConvexHullShape), DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + btConvexHullShape* localPtr = (btConvexHullShape*)&convexHullShape0; + const btTransform& t = xform; + btScalar margin = convexShape->getMarginNV(); + localPtr->getNonvirtualAabb(t,aabbMin,aabbMax,margin); + //spu_printf("SPU convex aabbMin=%f,%f,%f=\n",aabbMin.getX(),aabbMin.getY(),aabbMin.getZ()); + //spu_printf("SPU convex aabbMax=%f,%f,%f=\n",aabbMax.getX(),aabbMax.getY(),aabbMax.getZ()); + break; + } + default: + { + // spu_printf("SPU: unsupported shapetype %d in AABB calculation\n"); + } + }; +} + +void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + + dmaSize = sizeof(btTriangleIndexVertexArray); + dmaPpuAddress2 = reinterpret_cast(triMeshShape->getMeshInterface()); + // spu_printf("trimeshShape->getMeshInterface() == %llx\n",dmaPpuAddress2); +#ifdef __SPU__ + cellDmaGet(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + bvhMeshShape->gTriangleMeshInterfacePtr = &bvhMeshShape->gTriangleMeshInterfaceStorage; +#else + bvhMeshShape->gTriangleMeshInterfacePtr = (btTriangleIndexVertexArray*)cellDmaGetReadOnly(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); +#endif + + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + + ///now DMA over the BVH + + dmaSize = sizeof(btOptimizedBvh); + dmaPpuAddress2 = reinterpret_cast(triMeshShape->getOptimizedBvh()); + //spu_printf("trimeshShape->getOptimizedBvh() == %llx\n",dmaPpuAddress2); + cellDmaGet(&bvhMeshShape->gOptimizedBvh, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(2)); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); +} + +void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag) +{ + cellDmaGet(IndexMesh, (ppu_address_t)&indexArray[index] , sizeof(btIndexedMesh), DMA_TAG(dmaTag), 0, 0); + +} + +void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag) +{ + cellDmaGet(subTreeHeaders, subTreePtr, batchSize * sizeof(btBvhSubtreeInfo), DMA_TAG(dmaTag), 0, 0); +} + +void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag) +{ + cellDmaGet(nodes, reinterpret_cast(&nodeArray[subtree.m_rootNodeIndex]) , subtree.m_subtreeSize* sizeof(btQuantizedBvhNode), DMA_TAG(2), 0, 0); +} + +///getShapeTypeSize could easily be optimized, but it is not likely a bottleneck +int getShapeTypeSize(int shapeType) +{ + + + switch (shapeType) + { + case CYLINDER_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btCylinderShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case BOX_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btBoxShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case SPHERE_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btSphereShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btBvhTriangleMeshShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btCapsuleShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btConvexHullShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + + case COMPOUND_SHAPE_PROXYTYPE: + { + int shapeSize = sizeof(btCompoundShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + case STATIC_PLANE_PROXYTYPE: + { + int shapeSize = sizeof(btStaticPlaneShape); + btAssert(shapeSize < MAX_SHAPE_SIZE); + return shapeSize; + } + + default: + btAssert(0); + //unsupported shapetype, please add here + return 0; + } +} + +void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU) +{ + convexVertexData->gNumConvexPoints = convexShapeSPU->getNumPoints(); + if (convexVertexData->gNumConvexPoints>MAX_NUM_SPU_CONVEX_POINTS) + { + btAssert(0); + // spu_printf("SPU: Error: MAX_NUM_SPU_CONVEX_POINTS(%d) exceeded: %d\n",MAX_NUM_SPU_CONVEX_POINTS,convexVertexData->gNumConvexPoints); + return; + } + + register int dmaSize = convexVertexData->gNumConvexPoints*sizeof(btVector3); + ppu_address_t pointsPPU = (ppu_address_t) convexShapeSPU->getUnscaledPoints(); + cellDmaGet(&convexVertexData->g_convexPointBuffer[0], pointsPPU , dmaSize, DMA_TAG(2), 0, 0); +} + +void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType) +{ + register int dmaSize = getShapeTypeSize(shapeType); + cellDmaGet(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0); + //cellDmaGetReadOnly(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(dmaTag)); +} + +void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + int childShapeCount = spuCompoundShape->getNumChildShapes(); + dmaSize = childShapeCount * sizeof(btCompoundShapeChild); + dmaPpuAddress2 = (ppu_address_t)spuCompoundShape->getChildList(); + cellDmaGet(&compoundShapeLocation->gSubshapes[0], dmaPpuAddress2, dmaSize, DMA_TAG(dmaTag), 0, 0); +} + +void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag) +{ + int childShapeCount = spuCompoundShape->getNumChildShapes(); + int i; + // DMA all the subshapes + for ( i = 0; i < childShapeCount; ++i) + { + btCompoundShapeChild& childShape = compoundShapeLocation->gSubshapes[i]; + dmaCollisionShape (&compoundShapeLocation->gSubshapeShape[i],(ppu_address_t)childShape.m_childShape, dmaTag, childShape.m_childShapeType); + } +} + + +void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex) +{ + + int curIndex = startNodeIndex; + int walkIterations = 0; +#ifdef BT_DEBUG + int subTreeSize = endNodeIndex - startNodeIndex; +#endif + + int escapeIndex; + + unsigned int aabbOverlap, isLeafNode; + + while (curIndex < endNodeIndex) + { + //catch bugs in tree data + btAssert (walkIterations < subTreeSize); + + walkIterations++; + aabbOverlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + //printf("overlap with node %d\n",rootNode->getTriangleIndex()); + nodeCallback->processNode(0,rootNode->getTriangleIndex()); + // spu_printf("SPU: overlap detected with triangleIndex:%d\n",rootNode->getTriangleIndex()); + } + + if (aabbOverlap || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + +} diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h new file mode 100644 index 00000000..aa8a2910 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h @@ -0,0 +1,128 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef __SPU_COLLISION_SHAPES_H +#define __SPU_COLLISION_SHAPES_H + +#include "../SpuDoubleBuffer.h" + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" + +#define MAX_NUM_SPU_CONVEX_POINTS 128 //@fallback to PPU if a btConvexHullShape has more than MAX_NUM_SPU_CONVEX_POINTS points +#define MAX_SPU_COMPOUND_SUBSHAPES 16 //@fallback on PPU if compound has more than MAX_SPU_COMPOUND_SUBSHAPES child shapes +#define MAX_SHAPE_SIZE 256 //@todo: assert on this + +ATTRIBUTE_ALIGNED16(struct) SpuConvexPolyhedronVertexData +{ + void* gSpuConvexShapePtr; + btVector3* gConvexPoints; + int gNumConvexPoints; + int unused; + ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]); +}; + + + +ATTRIBUTE_ALIGNED16(struct) CollisionShape_LocalStoreMemory +{ + ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]); +}; + +ATTRIBUTE_ALIGNED16(struct) CompoundShape_LocalStoreMemory +{ + // Compound data + + ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]); + ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]); +}; + +ATTRIBUTE_ALIGNED16(struct) bvhMeshShape_LocalStoreMemory +{ + //ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh); + ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]); + btOptimizedBvh* getOptimizedBvh() + { + return (btOptimizedBvh*) gOptimizedBvh; + } + + ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage); + btTriangleIndexVertexArray* gTriangleMeshInterfacePtr; + ///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment + ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh); + #define MAX_SPU_SUBTREE_HEADERS 32 + //1024 + ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]); + ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]); +}; + + +void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform); +void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape); +void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag); +void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag); +void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag); + +int getShapeTypeSize(int shapeType); +void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU); +void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType); +void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag); +void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag); + + +#define USE_BRANCHFREE_TEST 1 +#ifdef USE_BRANCHFREE_TEST +SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) +{ +#if defined(__CELLOS_LV2__) && defined (__SPU__) + vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0}; + vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0}; + vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax); + return spu_extract(spu_gather(isGt),0)==0; + +#else + return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0); +#endif +} +#else + +SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) +{ + unsigned int overlap = 1; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap; + return overlap; +} +#endif + +void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex); + +#endif diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp new file mode 100644 index 00000000..8584e74c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp @@ -0,0 +1,248 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SpuContactResult.h" + +//#define DEBUG_SPU_COLLISION_DETECTION 1 + +#ifdef DEBUG_SPU_COLLISION_DETECTION +#ifndef __SPU__ +#include +#define spu_printf printf +#endif +#endif //DEBUG_SPU_COLLISION_DETECTION + +SpuContactResult::SpuContactResult() +{ + m_manifoldAddress = 0; + m_spuManifold = NULL; + m_RequiresWriteBack = false; +} + + SpuContactResult::~SpuContactResult() +{ + g_manifoldDmaExport.swapBuffers(); +} + + ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(btScalar friction0,btScalar friction1) +{ + btScalar friction = friction0*friction1; + + const btScalar MAX_FRICTION = btScalar(10.); + + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(btScalar restitution0,btScalar restitution1) +{ + return restitution0*restitution1; +} + + + + void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction1, bool isSwapped) + { + //spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress); + m_rootWorldTransform0 = worldTrans0; + m_rootWorldTransform1 = worldTrans1; + m_manifoldAddress = manifoldAddress; + m_spuManifold = spuManifold; + + m_combinedFriction = calculateCombinedFriction(friction0,friction1); + m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); + m_isSwapped = isSwapped; + } + + void SpuContactResult::setShapeIdentifiersA(int partId0,int index0) + { + + } + + void SpuContactResult::setShapeIdentifiersB(int partId1,int index1) + { + + } + + + + ///return true if it requires a dma transfer back +bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld, + const btVector3& pointInWorld, + float depth, + btPersistentManifold* manifoldPtr, + btTransform& transA, + btTransform& transB, + btScalar combinedFriction, + btScalar combinedRestitution, + bool isSwapped) +{ + +// float contactTreshold = manifoldPtr->getContactBreakingThreshold(); + + //spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr); + +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("SPU: contactTreshold %f\n",contactTreshold); +#endif //DEBUG_SPU_COLLISION_DETECTION + if (depth > manifoldPtr->getContactBreakingThreshold()) + return false; + + //if (depth > manifoldPtr->getContactProcessingThreshold()) + // return false; + + + + btVector3 pointA; + btVector3 localA; + btVector3 localB; + btVector3 normal; + + + if (isSwapped) + { + normal = normalOnBInWorld * -1; + pointA = pointInWorld + normal * depth; + localA = transA.invXform(pointA ); + localB = transB.invXform(pointInWorld); + } + else + { + normal = normalOnBInWorld; + pointA = pointInWorld + normal * depth; + localA = transA.invXform(pointA ); + localB = transB.invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normal,depth); + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + + newPt.m_combinedFriction = combinedFriction; + newPt.m_combinedRestitution = combinedRestitution; + + + int insertIndex = manifoldPtr->getCacheEntry(newPt); + if (insertIndex >= 0) + { + // we need to replace the current contact point, otherwise small errors will accumulate (spheres start rolling etc) + manifoldPtr->replaceContactPoint(newPt,insertIndex); + return true; + + } else + { + + /* + ///@todo: SPU callbacks, either immediate (local on the SPU), or deferred + //User can override friction and/or restitution + if (gContactAddedCallback && + //and if either of the two bodies requires custom material + ((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) || + (m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback))) + { + //experimental feature info, for per-triangle material etc. + (*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1); + } + */ + + manifoldPtr->addManifoldPoint(newPt); + return true; + + } + return false; + +} + + +void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold) +{ + ///only write back the contact information on SPU. Other platforms avoid copying, and use the data in-place + ///see SpuFakeDma.cpp 'cellDmaLargeGetReadOnly' +#if defined (__SPU__) || defined (USE_LIBSPE2) + memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold)); + + g_manifoldDmaExport.swapBuffers(); + ppu_address_t mmAddr = (ppu_address_t)mmManifold; + g_manifoldDmaExport.backBufferDmaPut(mmAddr, sizeof(btPersistentManifold), DMA_TAG(9)); + // Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon? + //no, the swapBuffers does the wait +#endif +} + +void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) +{ +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth); + spu_printf("*** normal = %f,%f,%f\n",normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ()); + spu_printf("*** position = %f,%f,%f\n",pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ()); +#endif //DEBUG_SPU_COLLISION_DETECTION + + +#ifdef DEBUG_SPU_COLLISION_DETECTION + // int sman = sizeof(rage::phManifold); +// spu_printf("sizeof_manifold = %i\n",sman); +#endif //DEBUG_SPU_COLLISION_DETECTION + + btPersistentManifold* localManifold = m_spuManifold; + + btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ()); + btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ()); + + //process the contact point + const bool retVal = ManifoldResultAddContactPoint(normalB, + pointWrld, + depth, + localManifold, + m_rootWorldTransform0, + m_rootWorldTransform1, + m_combinedFriction, + m_combinedRestitution, + m_isSwapped); + m_RequiresWriteBack = m_RequiresWriteBack || retVal; +} + +void SpuContactResult::flush() +{ + + if (m_spuManifold && m_spuManifold->getNumContacts()) + { + m_spuManifold->refreshContactPoints(m_rootWorldTransform0,m_rootWorldTransform1); + m_RequiresWriteBack = true; + } + + + if (m_RequiresWriteBack) + { +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("SPU: Start SpuContactResult::flush (Put) DMA\n"); + spu_printf("Num contacts:%d\n", m_spuManifold->getNumContacts()); + spu_printf("Manifold address: %llu\n", m_manifoldAddress); +#endif //DEBUG_SPU_COLLISION_DETECTION + // spu_printf("writeDoubleBufferedManifold\n"); + writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress); +#ifdef DEBUG_SPU_COLLISION_DETECTION + spu_printf("SPU: Finished (Put) DMA\n"); +#endif //DEBUG_SPU_COLLISION_DETECTION + } + m_spuManifold = NULL; + m_RequiresWriteBack = false; +} + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h new file mode 100644 index 00000000..394f56dc --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h @@ -0,0 +1,106 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SPU_CONTACT_RESULT2_H +#define SPU_CONTACT_RESULT2_H + + +#ifndef _WIN32 +#include +#endif + + + +#include "../SpuDoubleBuffer.h" + + +#include "LinearMath/btTransform.h" + + +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + +class btCollisionShape; + + +struct SpuCollisionPairInput +{ + ppu_address_t m_collisionShapes[2]; + btCollisionShape* m_spuCollisionShapes[2]; + + ppu_address_t m_persistentManifoldPtr; + btVector3 m_primitiveDimensions0; + btVector3 m_primitiveDimensions1; + int m_shapeType0; + int m_shapeType1; + float m_collisionMargin0; + float m_collisionMargin1; + + btTransform m_worldTransform0; + btTransform m_worldTransform1; + + bool m_isSwapped; + bool m_useEpa; +}; + + +struct SpuClosestPointInput : public btDiscreteCollisionDetectorInterface::ClosestPointInput +{ + struct SpuConvexPolyhedronVertexData* m_convexVertexData[2]; +}; + +///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed +///So when an existing contact point is duplicated, no transfer/refresh is performed. +class SpuContactResult : public btDiscreteCollisionDetectorInterface::Result +{ + btTransform m_rootWorldTransform0; + btTransform m_rootWorldTransform1; + ppu_address_t m_manifoldAddress; + + btPersistentManifold* m_spuManifold; + bool m_RequiresWriteBack; + btScalar m_combinedFriction; + btScalar m_combinedRestitution; + + bool m_isSwapped; + + DoubleBuffer g_manifoldDmaExport; + + public: + SpuContactResult(); + virtual ~SpuContactResult(); + + btPersistentManifold* GetSpuManifold() const + { + return m_spuManifold; + } + + virtual void setShapeIdentifiersA(int partId0,int index0); + virtual void setShapeIdentifiersB(int partId1,int index1); + + void setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction01, bool isSwapped); + + + void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold); + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + + void flush(); +}; + + + +#endif //SPU_CONTACT_RESULT2_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h new file mode 100644 index 00000000..b1bd53d9 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h @@ -0,0 +1,50 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef SPU_CONVEX_PENETRATION_DEPTH_H +#define SPU_CONVEX_PENETRATION_DEPTH_H + + + +class btIDebugDraw; +#include "BulletCollision/NarrowphaseCollision/btConvexPenetrationDepthSolver.h" + +#include "LinearMath/btTransform.h" + + +///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. +class SpuConvexPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +public: + + virtual ~SpuConvexPenetrationDepthSolver() {}; + virtual bool calcPenDepth( SpuVoronoiSimplexSolver& simplexSolver, + void* convexA,void* convexB,int shapeTypeA, int shapeTypeB, float marginA, float marginB, + btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw, + struct SpuConvexPolyhedronVertexData* convexVertexDataA, + struct SpuConvexPolyhedronVertexData* convexVertexDataB + ) const = 0; + + +}; + + + +#endif //SPU_CONVEX_PENETRATION_DEPTH_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp new file mode 100644 index 00000000..c2fe2905 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp @@ -0,0 +1,1432 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SpuGatheringCollisionTask.h" + +//#define DEBUG_SPU_COLLISION_DETECTION 1 +#include "../SpuDoubleBuffer.h" + +#include "../SpuCollisionTaskProcess.h" +#include "../SpuGatheringCollisionDispatcher.h" //for SPU_BATCHSIZE_BROADPHASE_PAIRS + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "../SpuContactManifoldCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "SpuContactResult.h" +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h" + +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" + +#include "SpuMinkowskiPenetrationDepthSolver.h" +//#include "SpuEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" + + +#include "boxBoxDistance.h" +#include "BulletMultiThreaded/vectormath2bullet.h" +#include "SpuCollisionShapes.h" //definition of SpuConvexPolyhedronVertexData +#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + +#ifdef __SPU__ +///Software caching from the IBM Cell SDK, it reduces 25% SPU time for our test cases +#ifndef USE_LIBSPE2 +//#define USE_SOFTWARE_CACHE 1 +#endif +#endif //__SPU__ + +int gSkippedCol = 0; +int gProcessedCol = 0; + +//////////////////////////////////////////////// +/// software caching +#if USE_SOFTWARE_CACHE +#include +#include +#include +#include +#define SPE_CACHE_NWAY 4 +//#define SPE_CACHE_NSETS 32, 16 +#define SPE_CACHE_NSETS 8 +//#define SPE_CACHELINE_SIZE 512 +#define SPE_CACHELINE_SIZE 128 +#define SPE_CACHE_SET_TAGID(set) 15 +///make sure that spe_cache.h is below those defines! +#include "../Extras/software_cache/cache/include/spe_cache.h" + + +int g_CacheMisses=0; +int g_CacheHits=0; + +#if 0 // Added to allow cache misses and hits to be tracked, change this to 1 to restore unmodified version +#define spe_cache_read(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1) +#else +#define spe_cache_read(ea) \ +({ \ + int set, idx, line, byte; \ + _spe_cache_nway_lookup_(ea, set, idx); \ + \ + if (btUnlikely(idx < 0)) { \ + ++g_CacheMisses; \ + idx = _spe_cache_miss_(ea, set, -1); \ + spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ + spu_mfcstat(MFC_TAG_UPDATE_ALL); \ + } \ + else \ + { \ + ++g_CacheHits; \ + } \ + line = _spe_cacheline_num_(set, idx); \ + byte = _spe_cacheline_byte_offset_(ea); \ + (void *) &spe_cache_mem[line + byte]; \ +}) + +#endif + +#endif // USE_SOFTWARE_CACHE + +bool gUseEpa = false; + +#ifdef USE_SN_TUNER +#include +#endif //USE_SN_TUNER + +#if defined (__SPU__) && !defined (USE_LIBSPE2) +#include +#elif defined (USE_LIBSPE2) +#define spu_printf(a) +#else +#define IGNORE_ALIGNMENT 1 +#include +#include +#define spu_printf printf + +#endif + +//int gNumConvexPoints0=0; + +///Make sure no destructors are called on this memory +ATTRIBUTE_ALIGNED16(struct) CollisionTask_LocalStoreMemory +{ + ///This CollisionTask_LocalStoreMemory is mainly used for the SPU version, using explicit DMA + ///Other platforms can use other memory programming models. + + ATTRIBUTE_ALIGNED16(btBroadphasePair gBroadphasePairsBuffer[SPU_BATCHSIZE_BROADPHASE_PAIRS]); + DoubleBuffer g_workUnitTaskBuffers; + ATTRIBUTE_ALIGNED16(char gSpuContactManifoldAlgoBuffer [sizeof(SpuContactManifoldCollisionAlgorithm)+16]); + ATTRIBUTE_ALIGNED16(char gColObj0Buffer [sizeof(btCollisionObject)+16]); + ATTRIBUTE_ALIGNED16(char gColObj1Buffer [sizeof(btCollisionObject)+16]); + ///we reserve 32bit integer indices, even though they might be 16bit + ATTRIBUTE_ALIGNED16(int spuIndices[16]); + btPersistentManifold gPersistentManifoldBuffer; + CollisionShape_LocalStoreMemory gCollisionShapes[2]; + bvhMeshShape_LocalStoreMemory bvhShapeData; + ATTRIBUTE_ALIGNED16(SpuConvexPolyhedronVertexData convexVertexData[2]); + CompoundShape_LocalStoreMemory compoundShapeData[2]; + + ///The following pointers might either point into this local store memory, or to the original/other memory locations. + ///See SpuFakeDma for implementation of cellDmaSmallGetReadOnly. + btCollisionObject* m_lsColObj0Ptr; + btCollisionObject* m_lsColObj1Ptr; + btBroadphasePair* m_pairsPointer; + btPersistentManifold* m_lsManifoldPtr; + SpuContactManifoldCollisionAlgorithm* m_lsCollisionAlgorithmPtr; + + bool needsDmaPutContactManifoldAlgo; + + btCollisionObject* getColObj0() + { + return m_lsColObj0Ptr; + } + btCollisionObject* getColObj1() + { + return m_lsColObj1Ptr; + } + + + btBroadphasePair* getBroadphasePairPtr() + { + return m_pairsPointer; + } + + SpuContactManifoldCollisionAlgorithm* getlocalCollisionAlgorithm() + { + return m_lsCollisionAlgorithmPtr; + } + + btPersistentManifold* getContactManifoldPtr() + { + return m_lsManifoldPtr; + } +}; + + +#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) + +ATTRIBUTE_ALIGNED16(CollisionTask_LocalStoreMemory gLocalStoreMemory); + +void* createCollisionLocalStoreMemory() +{ + return &gLocalStoreMemory; +} +void deleteCollisionLocalStoreMemory() +{ +} +#else + +btAlignedObjectArray sLocalStorePointers; + +void* createCollisionLocalStoreMemory() +{ + CollisionTask_LocalStoreMemory* localStore = (CollisionTask_LocalStoreMemory*)btAlignedAlloc( sizeof(CollisionTask_LocalStoreMemory),16); + sLocalStorePointers.push_back(localStore); + return localStore; +} + +void deleteCollisionLocalStoreMemory() +{ + for (int i=0;ibvhShapeData.gIndexMesh.m_indexType == PHY_SHORT) + { + unsigned short int* indexBasePtr = (unsigned short int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride); + ATTRIBUTE_ALIGNED16(unsigned short int tmpIndices[3]); + + small_cache_read_triple(&tmpIndices[0],(ppu_address_t)&indexBasePtr[0], + &tmpIndices[1],(ppu_address_t)&indexBasePtr[1], + &tmpIndices[2],(ppu_address_t)&indexBasePtr[2], + sizeof(unsigned short int)); + + m_lsMemPtr->spuIndices[0] = int(tmpIndices[0]); + m_lsMemPtr->spuIndices[1] = int(tmpIndices[1]); + m_lsMemPtr->spuIndices[2] = int(tmpIndices[2]); + } else + { + unsigned int* indexBasePtr = (unsigned int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride); + + small_cache_read_triple(&m_lsMemPtr->spuIndices[0],(ppu_address_t)&indexBasePtr[0], + &m_lsMemPtr->spuIndices[1],(ppu_address_t)&indexBasePtr[1], + &m_lsMemPtr->spuIndices[2],(ppu_address_t)&indexBasePtr[2], + sizeof(int)); + } + + // spu_printf("SPU index0=%d ,",spuIndices[0]); + // spu_printf("SPU index1=%d ,",spuIndices[1]); + // spu_printf("SPU index2=%d ,",spuIndices[2]); + // spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr); + + const btVector3& meshScaling = m_lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getScaling(); + for (int j=2;btLikely( j>=0 );j--) + { + int graphicsindex = m_lsMemPtr->spuIndices[j]; + + // spu_printf("SPU index=%d ,",graphicsindex); + btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexStride); + // spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr); + + + ///handle un-aligned vertices... + + //another DMA for each vertex + small_cache_read_triple(&spuUnscaledVertex[0],(ppu_address_t)&graphicsbasePtr[0], + &spuUnscaledVertex[1],(ppu_address_t)&graphicsbasePtr[1], + &spuUnscaledVertex[2],(ppu_address_t)&graphicsbasePtr[2], + sizeof(btScalar)); + + m_tmpTriangleShape.getVertexPtr(j).setValue(spuUnscaledVertex[0]*meshScaling.getX(), + spuUnscaledVertex[1]*meshScaling.getY(), + spuUnscaledVertex[2]*meshScaling.getZ()); + + // spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z()); + } + + + SpuCollisionPairInput triangleConcaveInput(*m_wuInput); +// triangleConcaveInput.m_spuCollisionShapes[1] = &spuTriangleVertices[0]; + triangleConcaveInput.m_spuCollisionShapes[1] = &m_tmpTriangleShape; + triangleConcaveInput.m_shapeType1 = TRIANGLE_SHAPE_PROXYTYPE; + + m_spuContacts.setShapeIdentifiersB(subPart,triangleIndex); + + // m_spuContacts.flush(); + + ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts); + ///this flush should be automatic + // m_spuContacts.flush(); + } + +}; + + + +void btConvexPlaneCollideSingleContact (SpuCollisionPairInput* wuInput,CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts) +{ + + btConvexShape* convexShape = (btConvexShape*) wuInput->m_spuCollisionShapes[0]; + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) wuInput->m_spuCollisionShapes[1]; + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + + btTransform convexWorldTransform = wuInput->m_worldTransform0; + btTransform convexInPlaneTrans; + convexInPlaneTrans= wuInput->m_worldTransform1.inverse() * convexWorldTransform; + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * wuInput->m_worldTransform1; + + //btVector3 vtx = convexShape->localGetSupportVertexWithoutMarginNonVirtual(planeInConvex.getBasis()*-planeNormal); + btVector3 vtx = convexShape->localGetSupportVertexNonVirtual(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = wuInput->m_worldTransform1 * vtxInPlaneProjected; + + hasCollision = distance < lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold(); + //resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB =wuInput->m_worldTransform1.getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + spuContacts.addContactPoint(normalOnSurfaceB,pOnB,distance); + } +} + +void ProcessConvexPlaneSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) +{ + + register int dmaSize = 0; + register ppu_address_t dmaPpuAddress2; + btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr; + + ///DMA in the vertices for convex shapes + ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); + ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]); + + if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[0]; + + cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[1]; + cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0); + lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0]; + } + + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1); + lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1]; + } + + + btConvexPointCloudShape cpc0,cpc1; + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[0] = &cpc0; + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[1] = &cpc1; + + } + + +// const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0]; +// const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1]; +// int shapeType0 = wuInput->m_shapeType0; +// int shapeType1 = wuInput->m_shapeType1; + float marginA = wuInput->m_collisionMargin0; + float marginB = wuInput->m_collisionMargin1; + + SpuClosestPointInput cpInput; + cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0]; + cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1]; + cpInput.m_transformA = wuInput->m_worldTransform0; + cpInput.m_transformB = wuInput->m_worldTransform1; + float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold()); + cpInput.m_maximumDistanceSquared = sumMargin * sumMargin; + + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr(); + //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped); + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(), + lsMemPtr->getColObj1()->getWorldTransform(), + lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(), + lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(), + wuInput->m_isSwapped); + + + btConvexPlaneCollideSingleContact(wuInput,lsMemPtr,spuContacts); + + + + +} + + + + +//////////////////////// +/// Convex versus Concave triangle mesh collision detection (handles concave triangle mesh versus sphere, box, cylinder, triangle, cone, convex polyhedron etc) +/////////////////// +void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) +{ + //order: first collision shape is convex, second concave. m_isSwapped is true, if the original order was opposite + + btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)wuInput->m_spuCollisionShapes[1]; + //need the mesh interface, for access to triangle vertices + dmaBvhShapeData (&lsMemPtr->bvhShapeData, trimeshShape); + + btVector3 aabbMin(-1,-400,-1); + btVector3 aabbMax(1,400,1); + + + //recalc aabbs + btTransform convexInTriangleSpace; + convexInTriangleSpace = wuInput->m_worldTransform1.inverse() * wuInput->m_worldTransform0; + btConvexInternalShape* convexShape = (btConvexInternalShape*)wuInput->m_spuCollisionShapes[0]; + + computeAabb (aabbMin, aabbMax, convexShape, wuInput->m_collisionShapes[0], wuInput->m_shapeType0, convexInTriangleSpace); + + + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + //convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); + + // btScalar extraMargin = collisionMarginTriangle; + // btVector3 extra(extraMargin,extraMargin,extraMargin); + // aabbMax += extra; + // aabbMin -= extra; + + ///quantize query AABB + unsigned short int quantizedQueryAabbMin[3]; + unsigned short int quantizedQueryAabbMax[3]; + lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0); + lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1); + + QuantizedNodeArray& nodeArray = lsMemPtr->bvhShapeData.getOptimizedBvh()->getQuantizedNodeArray(); + //spu_printf("SPU: numNodes = %d\n",nodeArray.size()); + + BvhSubtreeInfoArray& subTrees = lsMemPtr->bvhShapeData.getOptimizedBvh()->getSubtreeInfoArray(); + + + spuNodeCallback nodeCallback(wuInput,lsMemPtr,spuContacts); + IndexedMeshArray& indexArray = lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getIndexedMeshArray(); + //spu_printf("SPU:indexArray.size() = %d\n",indexArray.size()); + + // spu_printf("SPU: numSubTrees = %d\n",subTrees.size()); + //not likely to happen + if (subTrees.size() && indexArray.size() == 1) + { + ///DMA in the index info + dmaBvhIndexedMesh (&lsMemPtr->bvhShapeData.gIndexMesh, indexArray, 0 /* index into indexArray */, 1 /* dmaTag */); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + //display the headers + int numBatch = subTrees.size(); + for (int i=0;ibvhShapeData.gSubtreeHeaders[0], (ppu_address_t)(&subTrees[i]), nextBatch, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + // spu_printf("nextBatch = %d\n",nextBatch); + + for (int j=0;jbvhShapeData.gSubtreeHeaders[j]; + + unsigned int overlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap) + { + btAssert(subtree.m_subtreeSize); + + //dma the actual nodes of this subtree + dmaBvhSubTreeNodes (&lsMemPtr->bvhShapeData.gSubtreeNodes[0], subtree, nodeArray, 2); + cellDmaWaitTagStatusAll(DMA_MASK(2)); + + /* Walk this subtree */ + spuWalkStacklessQuantizedTree(&nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + &lsMemPtr->bvhShapeData.gSubtreeNodes[0], + 0, + subtree.m_subtreeSize); + } + // spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize); + } + + // unsigned short int m_quantizedAabbMin[3]; + // unsigned short int m_quantizedAabbMax[3]; + // int m_rootNodeIndex; + // int m_subtreeSize; + i+=nextBatch; + } + + //pre-fetch first tree, then loop and double buffer + } + +} + + +#define MAX_DEGENERATE_STATS 15 +int stats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +int degenerateStats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + +//////////////////////// +/// Convex versus Convex collision detection (handles collision between sphere, box, cylinder, triangle, cone, convex polyhedron etc) +/////////////////// +void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + +#ifdef DEBUG_SPU_COLLISION_DETECTION + //spu_printf("SPU: ProcessSpuConvexConvexCollision\n"); +#endif //DEBUG_SPU_COLLISION_DETECTION + //CollisionShape* shape0 = (CollisionShape*)wuInput->m_collisionShapes[0]; + //CollisionShape* shape1 = (CollisionShape*)wuInput->m_collisionShapes[1]; + btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr; + + bool genericGjk = true; + + if (genericGjk) + { + //try generic GJK + + + + //SpuConvexPenetrationDepthSolver* penetrationSolver=0; + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver epaPenetrationSolver2; + + btConvexPenetrationDepthSolver* penetrationSolver = &epaPenetrationSolver2; + + //SpuMinkowskiPenetrationDepthSolver minkowskiPenetrationSolver; +#ifdef ENABLE_EPA + if (gUseEpa) + { + penetrationSolver = &epaPenetrationSolver2; + } else +#endif + { + //penetrationSolver = &minkowskiPenetrationSolver; + } + + + ///DMA in the vertices for convex shapes + ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); + ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]); + + if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[0]; + + cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + // spu_printf("SPU: DMA btConvexHullShape\n"); + dmaSize = sizeof(btConvexHullShape); + dmaPpuAddress2 = wuInput->m_collisionShapes[1]; + cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + //cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0); + lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0]; + } + + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1); + lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1]; + } + + + btConvexPointCloudShape cpc0,cpc1; + + if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[0] = &cpc0; + } + + if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) + { + cellDmaWaitTagStatusAll(DMA_MASK(2)); + lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0]; + btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1]; + const btVector3& localScaling = ch->getLocalScalingNV(); + cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling); + wuInput->m_spuCollisionShapes[1] = &cpc1; + + } + + + const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0]; + const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1]; + int shapeType0 = wuInput->m_shapeType0; + int shapeType1 = wuInput->m_shapeType1; + float marginA = wuInput->m_collisionMargin0; + float marginB = wuInput->m_collisionMargin1; + + SpuClosestPointInput cpInput; + cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0]; + cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1]; + cpInput.m_transformA = wuInput->m_worldTransform0; + cpInput.m_transformB = wuInput->m_worldTransform1; + float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold()); + cpInput.m_maximumDistanceSquared = sumMargin * sumMargin; + + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr(); + //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped); + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(), + lsMemPtr->getColObj1()->getWorldTransform(), + lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(), + lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(), + wuInput->m_isSwapped); + + { + btGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&simplexSolver,penetrationSolver);//&vsSolver,penetrationSolver); + gjk.getClosestPoints(cpInput,spuContacts,0);//,debugDraw); + + btAssert(gjk.m_lastUsedMethod getContactBreakingThreshold(); + lsMemPtr->getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(gjk.getCachedSeparatingAxis(),sepDist,wuInput->m_worldTransform0,wuInput->m_worldTransform1); + lsMemPtr->needsDmaPutContactManifoldAlgo = true; +#endif //USE_SEPDISTANCE_UTIL + + } + + } + + +} + + +template void DoSwap(T& a, T& b) +{ + char tmp[sizeof(T)]; + memcpy(tmp, &a, sizeof(T)); + memcpy(&a, &b, sizeof(T)); + memcpy(&b, tmp, sizeof(T)); +} + +SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem) +{ + register int dmaSize; + register ppu_address_t dmaPpuAddress2; + + dmaSize = sizeof(btCollisionObject);//btTransform); + dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject0(); + lsMem.m_lsColObj0Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj0Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + + dmaSize = sizeof(btCollisionObject);//btTransform); + dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject1(); + lsMem.m_lsColObj1Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj1Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0); + + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + btCollisionObject* ob0 = lsMem.getColObj0(); + btCollisionObject* ob1 = lsMem.getColObj1(); + + collisionPairInput.m_worldTransform0 = ob0->getWorldTransform(); + collisionPairInput.m_worldTransform1 = ob1->getWorldTransform(); +} + + + +void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem, + SpuContactResult &spuContacts, + ppu_address_t collisionShape0Ptr, void* collisionShape0Loc, + ppu_address_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true) +{ + + if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0) + && btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1)) + { + if (dmaShapes) + { + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + } + + btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; + btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc; + + btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); + btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions(); + + collisionPairInput.m_primitiveDimensions0 = dim0; + collisionPairInput.m_primitiveDimensions1 = dim1; + collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; + collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; + collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; + collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1; + ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts); + } + else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) && + btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1)) + { + //snPause(); + + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + // Both are compounds, do N^2 CD for now + ///@todo: add some AABB-based pruning (probably not -> slower) + + btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc; + btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc; + + dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape0, 1); + dmaCompoundShapeInfo (&lsMem.compoundShapeData[1], spuCompoundShape1, 2); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + + dmaCompoundSubShapes (&lsMem.compoundShapeData[0], spuCompoundShape0, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + dmaCompoundSubShapes (&lsMem.compoundShapeData[1], spuCompoundShape1, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + int childShapeCount0 = spuCompoundShape0->getNumChildShapes(); + btAssert(childShapeCount0< MAX_SPU_COMPOUND_SUBSHAPES); + int childShapeCount1 = spuCompoundShape1->getNumChildShapes(); + btAssert(childShapeCount1< MAX_SPU_COMPOUND_SUBSHAPES); + + // Start the N^2 + for (int i = 0; i < childShapeCount0; ++i) + { + btCompoundShapeChild& childShape0 = lsMem.compoundShapeData[0].gSubshapes[i]; + btAssert(!btBroadphaseProxy::isCompound(childShape0.m_childShapeType)); + + for (int j = 0; j < childShapeCount1; ++j) + { + btCompoundShapeChild& childShape1 = lsMem.compoundShapeData[1].gSubshapes[j]; + btAssert(!btBroadphaseProxy::isCompound(childShape1.m_childShapeType)); + + + /* Create a new collision pair input struct using the two child shapes */ + SpuCollisionPairInput cinput (collisionPairInput); + + cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform; + cinput.m_shapeType0 = childShape0.m_childShapeType; + cinput.m_collisionMargin0 = childShape0.m_childMargin; + + cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform; + cinput.m_shapeType1 = childShape1.m_childShapeType; + cinput.m_collisionMargin1 = childShape1.m_childMargin; + /* Recursively call handleCollisionPair () with new collision pair input */ + + handleCollisionPair(cinput, lsMem, spuContacts, + (ppu_address_t)childShape0.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], + (ppu_address_t)childShape1.m_childShape, lsMem.compoundShapeData[1].gSubshapeShape[j], false); + } + } + } + else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) ) + { + //snPause(); + + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + + // object 0 compound, object 1 non-compound + btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc; + dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + int childShapeCount = spuCompoundShape->getNumChildShapes(); + btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES); + + for (int i = 0; i < childShapeCount; ++i) + { + btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i]; + btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType)); + // Dma the child shape + dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + SpuCollisionPairInput cinput (collisionPairInput); + cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform; + cinput.m_shapeType0 = childShape.m_childShapeType; + cinput.m_collisionMargin0 = childShape.m_childMargin; + + handleCollisionPair(cinput, lsMem, spuContacts, + (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], + collisionShape1Ptr, collisionShape1Loc, false); + } + } + else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) ) + { + //snPause(); + + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + // object 0 non-compound, object 1 compound + btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc; + dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + int childShapeCount = spuCompoundShape->getNumChildShapes(); + btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES); + + + for (int i = 0; i < childShapeCount; ++i) + { + btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i]; + btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType)); + // Dma the child shape + dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + SpuCollisionPairInput cinput (collisionPairInput); + cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform; + cinput.m_shapeType1 = childShape.m_childShapeType; + cinput.m_collisionMargin1 = childShape.m_childMargin; + handleCollisionPair(cinput, lsMem, spuContacts, + collisionShape0Ptr, collisionShape0Loc, + (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], false); + } + + } + else + { + //a non-convex shape is involved + bool handleConvexConcave = false; + + //snPause(); + + if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) && + btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1)) + { + // Swap stuff + DoSwap(collisionShape0Ptr, collisionShape1Ptr); + DoSwap(collisionShape0Loc, collisionShape1Loc); + DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1); + DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1); + DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1); + + collisionPairInput.m_isSwapped = true; + } + + if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&& + btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1)) + { + handleConvexConcave = true; + } + if (handleConvexConcave) + { + if (dmaShapes) + { + dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); + dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); + cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); + } + + if (collisionPairInput.m_shapeType1 == STATIC_PLANE_PROXYTYPE) + { + btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; + btStaticPlaneShape* planeShape= (btStaticPlaneShape*)collisionShape1Loc; + + btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); + collisionPairInput.m_primitiveDimensions0 = dim0; + collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; + collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; + collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; + collisionPairInput.m_spuCollisionShapes[1] = planeShape; + + ProcessConvexPlaneSpuCollision(&collisionPairInput,&lsMem,spuContacts); + } else + { + btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; + btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc; + + btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); + collisionPairInput.m_primitiveDimensions0 = dim0; + collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; + collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; + collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; + collisionPairInput.m_spuCollisionShapes[1] = trimeshShape; + + ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts); + } + } + + } + + spuContacts.flush(); + +} + + +void processCollisionTask(void* userPtr, void* lsMemPtr) +{ + + SpuGatherAndProcessPairsTaskDesc* taskDescPtr = (SpuGatherAndProcessPairsTaskDesc*)userPtr; + SpuGatherAndProcessPairsTaskDesc& taskDesc = *taskDescPtr; + CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr; + CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr); + + gUseEpa = taskDesc.m_useEpa; + + // spu_printf("taskDescPtr=%llx\n",taskDescPtr); + + SpuContactResult spuContacts; + + //////////////////// + + ppu_address_t dmaInPtr = taskDesc.m_inPairPtr; + unsigned int numPages = taskDesc.numPages; + unsigned int numOnLastPage = taskDesc.numOnLastPage; + + // prefetch first set of inputs and wait + lsMem.g_workUnitTaskBuffers.init(); + + unsigned int nextNumOnPage = (numPages > 1)? MIDPHASE_NUM_WORKUNITS_PER_PAGE : numOnLastPage; + lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3)); + dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE; + + + register unsigned char *inputPtr; + register unsigned int numOnPage; + register unsigned int j; + SpuGatherAndProcessWorkUnitInput* wuInputs; + register int dmaSize; + register ppu_address_t dmaPpuAddress; + register ppu_address_t dmaPpuAddress2; + + int numPairs; + register int p; + SpuCollisionPairInput collisionPairInput; + + for (unsigned int i = 0; btLikely(i < numPages); i++) + { + + // wait for back buffer dma and swap buffers + inputPtr = lsMem.g_workUnitTaskBuffers.swapBuffers(); + + // number on current page is number prefetched last iteration + numOnPage = nextNumOnPage; + + + // prefetch next set of inputs +#if MIDPHASE_NUM_WORKUNIT_PAGES > 2 + if ( btLikely( i < numPages-1 ) ) +#else + if ( btUnlikely( i < numPages-1 ) ) +#endif + { + nextNumOnPage = (i == numPages-2)? numOnLastPage : MIDPHASE_NUM_WORKUNITS_PER_PAGE; + lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3)); + dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE; + } + + wuInputs = reinterpret_cast(inputPtr); + + + for (j = 0; btLikely( j < numOnPage ); j++) + { +#ifdef DEBUG_SPU_COLLISION_DETECTION + // printMidphaseInput(&wuInputs[j]); +#endif //DEBUG_SPU_COLLISION_DETECTION + + + numPairs = wuInputs[j].m_endIndex - wuInputs[j].m_startIndex; + + if ( btLikely( numPairs ) ) + { + dmaSize = numPairs*sizeof(btBroadphasePair); + dmaPpuAddress = wuInputs[j].m_pairArrayPtr+wuInputs[j].m_startIndex * sizeof(btBroadphasePair); + lsMem.m_pairsPointer = (btBroadphasePair*)cellDmaGetReadOnly(&lsMem.gBroadphasePairsBuffer, dmaPpuAddress , dmaSize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + for (p=0;pm_userInfo = %d\n",pair.m_userInfo); + spu_printf("pair->m_algorithm = %d\n",pair.m_algorithm); + spu_printf("pair->m_pProxy0 = %d\n",pair.m_pProxy0); + spu_printf("pair->m_pProxy1 = %d\n",pair.m_pProxy1); +#endif //DEBUG_SPU_COLLISION_DETECTION + + if (pair.m_internalTmpValue == 2 && pair.m_algorithm && pair.m_pProxy0 && pair.m_pProxy1) + { + dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm); + dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm; + lsMem.m_lsCollisionAlgorithmPtr = (SpuContactManifoldCollisionAlgorithm*)cellDmaGetReadOnly(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + lsMem.needsDmaPutContactManifoldAlgo = false; + + collisionPairInput.m_persistentManifoldPtr = (ppu_address_t) lsMem.getlocalCollisionAlgorithm()->getContactManifoldPtr(); + collisionPairInput.m_isSwapped = false; + + if (1) + { + + ///can wait on the combined DMA_MASK, or dma on the same tag + + +#ifdef DEBUG_SPU_COLLISION_DETECTION + // spu_printf("SPU collisionPairInput->m_shapeType0 = %d\n",collisionPairInput->m_shapeType0); + // spu_printf("SPU collisionPairInput->m_shapeType1 = %d\n",collisionPairInput->m_shapeType1); +#endif //DEBUG_SPU_COLLISION_DETECTION + + + dmaSize = sizeof(btPersistentManifold); + + dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr; + lsMem.m_lsManifoldPtr = (btPersistentManifold*)cellDmaGetReadOnly(&lsMem.gPersistentManifoldBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + + collisionPairInput.m_shapeType0 = lsMem.getlocalCollisionAlgorithm()->getShapeType0(); + collisionPairInput.m_shapeType1 = lsMem.getlocalCollisionAlgorithm()->getShapeType1(); + collisionPairInput.m_collisionMargin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); + collisionPairInput.m_collisionMargin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); + + + + //??cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + if (1) + { + //snPause(); + + // Get the collision objects + dmaAndSetupCollisionObjects(collisionPairInput, lsMem); + + if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive()) + { + + lsMem.needsDmaPutContactManifoldAlgo = true; +#ifdef USE_SEPDISTANCE_UTIL + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.updateSeparatingDistance(collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1); +#endif //USE_SEPDISTANCE_UTIL + +#define USE_DEDICATED_BOX_BOX 1 +#ifdef USE_DEDICATED_BOX_BOX + bool boxbox = ((lsMem.getlocalCollisionAlgorithm()->getShapeType0()==BOX_SHAPE_PROXYTYPE)&& + (lsMem.getlocalCollisionAlgorithm()->getShapeType1()==BOX_SHAPE_PROXYTYPE)); + if (boxbox) + { + //spu_printf("boxbox dist = %f\n",distance); + btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr(); + btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr; + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(), + lsMem.getColObj1()->getWorldTransform(), + lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(), + lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(), + collisionPairInput.m_isSwapped); + + + //float distance=0.f; + btVector3 normalInB; + + + if (//!gUseEpa && +#ifdef USE_SEPDISTANCE_UTIL + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f +#else + 1 +#endif + ) + { +//#define USE_PE_BOX_BOX 1 +#ifdef USE_PE_BOX_BOX + { + + //getCollisionMargin0 + btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); + btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); + btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0); + btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1); +/* + //Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ()); + vmVector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin()); + vmVector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin()); + vmMatrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis()); + vmMatrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis()); + + vmTransform3 transformA(vmMatrix0,vmPos0); + Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ()); + vmTransform3 transformB(vmMatrix1,vmPos1); + BoxPoint resultClosestBoxPointA; + BoxPoint resultClosestBoxPointB; + vmVector3 resultNormal; + */ + +#ifdef USE_SEPDISTANCE_UTIL + float distanceThreshold = FLT_MAX +#else + //float distanceThreshold = 0.f; +#endif + + + vmVector3 n; + Box boxA; + vmVector3 hA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ()); + vmVector3 hB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ()); + boxA.mHalf= hA; + vmTransform3 trA; + trA.setTranslation(getVmVector3(collisionPairInput.m_worldTransform0.getOrigin())); + trA.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis())); + Box boxB; + boxB.mHalf = hB; + vmTransform3 trB; + trB.setTranslation(getVmVector3(collisionPairInput.m_worldTransform1.getOrigin())); + trB.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis())); + + float distanceThreshold = spuManifold->getContactBreakingThreshold();//0.001f; + + + BoxPoint ptA,ptB; + float dist = boxBoxDistance(n, ptA, ptB, + boxA, trA, boxB, trB, + distanceThreshold ); + + +// float distance = boxBoxDistance(resultNormal,resultClosestBoxPointA,resultClosestBoxPointB, boxA, transformA, boxB,transformB,distanceThreshold); + + normalInB = -getBtVector3(n);//resultNormal); + + //if(dist < distanceThreshold)//spuManifold->getContactBreakingThreshold()) + if(dist < spuManifold->getContactBreakingThreshold()) + { + btVector3 pointOnB = collisionPairInput.m_worldTransform1(getBtVector3(ptB.localPoint)); + + spuContacts.addContactPoint( + normalInB, + pointOnB, + dist); + } + } +#else + { + + btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); + btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); + btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0); + btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1); + + + btBoxShape box0(shapeDim0); + btBoxShape box1(shapeDim1); + + struct SpuBridgeContactCollector : public btDiscreteCollisionDetectorInterface::Result + { + SpuContactResult& m_spuContacts; + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + m_spuContacts.setShapeIdentifiersA(partId0,index0); + } + virtual void setShapeIdentifiersB(int partId1,int index1) + { + m_spuContacts.setShapeIdentifiersB(partId1,index1); + } + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_spuContacts.addContactPoint(normalOnBInWorld,pointInWorld,depth); + } + + SpuBridgeContactCollector(SpuContactResult& spuContacts) + :m_spuContacts(spuContacts) + { + + } + }; + + SpuBridgeContactCollector bridgeOutput(spuContacts); + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = BT_LARGE_FLOAT; + input.m_transformA = collisionPairInput.m_worldTransform0; + input.m_transformB = collisionPairInput.m_worldTransform1; + + btBoxBoxDetector detector(&box0,&box1); + + detector.getClosestPoints(input,bridgeOutput,0); + + } +#endif //USE_PE_BOX_BOX + + lsMem.needsDmaPutContactManifoldAlgo = true; +#ifdef USE_SEPDISTANCE_UTIL + btScalar sepDist2 = distance+spuManifold->getContactBreakingThreshold(); + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(normalInB,sepDist2,collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1); +#endif //USE_SEPDISTANCE_UTIL + gProcessedCol++; + } else + { + gSkippedCol++; + } + + spuContacts.flush(); + + + } else +#endif //USE_DEDICATED_BOX_BOX + { + if ( +#ifdef USE_SEPDISTANCE_UTIL + lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f +#else + 1 +#endif //USE_SEPDISTANCE_UTIL + ) + { + handleCollisionPair(collisionPairInput, lsMem, spuContacts, + (ppu_address_t)lsMem.getColObj0()->getCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape, + (ppu_address_t)lsMem.getColObj1()->getCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape); + } else + { + //spu_printf("boxbox dist = %f\n",distance); + btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr(); + btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr; + ppu_address_t manifoldAddress = (ppu_address_t)manifold; + + spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(), + lsMem.getColObj1()->getWorldTransform(), + lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(), + lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(), + collisionPairInput.m_isSwapped); + + spuContacts.flush(); + } + } + + } + + } + } + +#ifdef USE_SEPDISTANCE_UTIL +#if defined (__SPU__) || defined (USE_LIBSPE2) + if (lsMem.needsDmaPutContactManifoldAlgo) + { + dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm); + dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm; + cellDmaLargePut(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } +#endif +#endif //#ifdef USE_SEPDISTANCE_UTIL + + } + } + } + } //end for (j = 0; j < numOnPage; j++) + + }// for + + + + return; +} + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h new file mode 100644 index 00000000..64af964c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h @@ -0,0 +1,140 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SPU_GATHERING_COLLISION_TASK_H +#define SPU_GATHERING_COLLISION_TASK_H + +#include "../PlatformDefinitions.h" +//#define DEBUG_SPU_COLLISION_DETECTION 1 + + +///Task Description for SPU collision detection +struct SpuGatherAndProcessPairsTaskDesc +{ + ppu_address_t m_inPairPtr;//m_pairArrayPtr; + //mutex variable + uint32_t m_someMutexVariableInMainMemory; + + ppu_address_t m_dispatcher; + + uint32_t numOnLastPage; + + uint16_t numPages; + uint16_t taskId; + bool m_useEpa; + + struct CollisionTask_LocalStoreMemory* m_lsMemory; +} + +#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) +__attribute__ ((aligned (128))) +#endif +; + + +void processCollisionTask(void* userPtr, void* lsMemory); + +void* createCollisionLocalStoreMemory(); +void deleteCollisionLocalStoreMemory(); + +#if defined(USE_LIBSPE2) && defined(__SPU__) +#include "../SpuLibspe2Support.h" +#include +#include +#include + +//#define DEBUG_LIBSPE2_SPU_TASK + + + +int main(unsigned long long speid, addr64 argp, addr64 envp) +{ + printf("SPU: hello \n"); + + ATTRIBUTE_ALIGNED128(btSpuStatus status); + ATTRIBUTE_ALIGNED16( SpuGatherAndProcessPairsTaskDesc taskDesc ) ; + unsigned int received_message = Spu_Mailbox_Event_Nothing; + bool shutdown = false; + + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + status.m_status = Spu_Status_Free; + status.m_lsMemory.p = createCollisionLocalStoreMemory(); + + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + while ( btLikely( !shutdown ) ) + { + + received_message = spu_read_in_mbox(); + + if( btLikely( received_message == Spu_Mailbox_Event_Task )) + { +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU: received Spu_Mailbox_Event_Task\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + + // refresh the status + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + btAssert(status.m_status==Spu_Status_Occupied); + + cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuGatherAndProcessPairsTaskDesc), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU:processCollisionTask\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + processCollisionTask((void*)&taskDesc, taskDesc.m_lsMemory); + +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU:finished processCollisionTask\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + } + else + { +#ifdef DEBUG_LIBSPE2_SPU_TASK + printf("SPU: received ShutDown\n"); +#endif //DEBUG_LIBSPE2_SPU_TASK + if( btLikely( received_message == Spu_Mailbox_Event_Shutdown ) ) + { + shutdown = true; + } + else + { + //printf("SPU - Sth. recieved\n"); + } + } + + // set to status free and wait for next task + status.m_status = Spu_Status_Free; + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + } + + printf("SPU: shutdown\n"); + return 0; +} +#endif // USE_LIBSPE2 + + +#endif //SPU_GATHERING_COLLISION_TASK_H + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h new file mode 100644 index 00000000..8b89de03 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h @@ -0,0 +1,19 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp new file mode 100644 index 00000000..166a38f6 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp @@ -0,0 +1,347 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SpuMinkowskiPenetrationDepthSolver.h" +#include "SpuContactResult.h" +#include "SpuPreferredPenetrationDirections.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "SpuCollisionShapes.h" + +#define NUM_UNITSPHERE_POINTS 42 +static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = +{ +btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), +btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), +btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), +btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), +btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), +btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), +btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), +btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), +btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), +btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), +btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), +btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), +btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), +btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), +btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), +btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), +btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), +btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), +btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), +btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), +btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), +btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), +btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), +btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), +btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), +btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), +btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), +btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), +btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), +btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), +btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), +btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), +btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), +btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), +btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), +btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), +btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), +btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), +btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), +btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), +btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), +btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) +}; + + +bool SpuMinkowskiPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw) +{ +#if 0 + (void)v; + + + struct btIntermediateResult : public SpuContactResult + { + + btIntermediateResult():m_hasResult(false) + { + } + + btVector3 m_normalOnBInWorld; + btVector3 m_pointInWorld; + btScalar m_depth; + bool m_hasResult; + + virtual void setShapeIdentifiersA(int partId0,int index0) + { + (void)partId0; + (void)index0; + } + + virtual void setShapeIdentifiersB(int partId1,int index1) + { + (void)partId1; + (void)index1; + } + void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_normalOnBInWorld = normalOnBInWorld; + m_pointInWorld = pointInWorld; + m_depth = depth; + m_hasResult = true; + } + }; + + //just take fixed number of orientation, and sample the penetration depth in that direction + btScalar minProj = btScalar(BT_LARGE_FLOAT); + btVector3 minNorm(0.f,0.f,0.f); + btVector3 minVertex; + btVector3 minA,minB; + btVector3 seperatingAxisInA,seperatingAxisInB; + btVector3 pInA,qInB,pWorld,qWorld,w; + +//#define USE_BATCHED_SUPPORT 1 +#ifdef USE_BATCHED_SUPPORT + + btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + + for (i=0;igetNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + + + convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); + convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); + + for (i=0;ilocalGetSupportVertexWithoutMarginNonVirtual( seperatingAxisInA);//, NULL); + qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);//, NULL); + + // pInA = convexA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + // qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + + pWorld = transA(pInA); + qWorld = transB(qInB); + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } +#endif //USE_BATCHED_SUPPORT + + //add the margins + + minA += minNorm*marginA; + minB -= minNorm*marginB; + //no penetration + if (minProj < btScalar(0.)) + return false; + + minProj += (marginA + marginB) + btScalar(1.00); + + + + + +//#define DEBUG_DRAW 1 +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(0,1,0); + debugDraw->drawLine(minA,minB,color); + color = btVector3 (1,1,1); + btVector3 vec = minB-minA; + btScalar prj2 = minNorm.dot(vec); + debugDraw->drawLine(minA,minA+(minNorm*minProj),color); + + } +#endif //DEBUG_DRAW + + + btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); + + btScalar offsetDist = minProj; + btVector3 offset = minNorm * offsetDist; + + + SpuClosestPointInput input; + input.m_convexVertexData[0] = convexVertexDataA; + input.m_convexVertexData[1] = convexVertexDataB; + btVector3 newOrg = transA.getOrigin() + offset; + + btTransform displacedTrans = transA; + displacedTrans.setOrigin(newOrg); + + input.m_transformA = displacedTrans; + input.m_transformB = transB; + input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj; + + btIntermediateResult res; + gjkdet.getClosestPoints(input,res,0); + + btScalar correctedMinNorm = minProj - res.m_depth; + + + //the penetration depth is over-estimated, relax it + btScalar penetration_relaxation= btScalar(1.); + minNorm*=penetration_relaxation; + + if (res.m_hasResult) + { + + pa = res.m_pointInWorld - minNorm * correctedMinNorm; + pb = res.m_pointInWorld; + +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(1,0,0); + debugDraw->drawLine(pa,pb,color); + } +#endif//DEBUG_DRAW + + + } else { + // could not seperate shapes + //btAssert (false); + } + return res.m_hasResult; +#endif + return false; +} + + + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h new file mode 100644 index 00000000..98c4fc68 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h @@ -0,0 +1,47 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + +class btIDebugDraw; +class btVoronoiSimplexSolver; +class btConvexShape; + +///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. +///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. +class SpuMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +public: + SpuMinkowskiPenetrationDepthSolver() {} + virtual ~SpuMinkowskiPenetrationDepthSolver() {}; + + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + const btConvexShape* convexA,const btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btVector3& pa, btVector3& pb, + class btIDebugDraw* debugDraw + ); + + +}; + + +#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h new file mode 100644 index 00000000..774a0cb2 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h @@ -0,0 +1,70 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SPU_PREFERRED_PENETRATION_DIRECTIONS_H +#define _SPU_PREFERRED_PENETRATION_DIRECTIONS_H + + +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" + +int spuGetNumPreferredPenetrationDirections(int shapeType, void* shape) +{ + switch (shapeType) + { + case TRIANGLE_SHAPE_PROXYTYPE: + { + return 2; + //spu_printf("2\n"); + break; + } + default: + { +#if __ASSERT + spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType); +#endif // __ASSERT + } + } + + return 0; +} + +void spuGetPreferredPenetrationDirection(int shapeType, void* shape, int index, btVector3& penetrationVector) +{ + + + switch (shapeType) + { + case TRIANGLE_SHAPE_PROXYTYPE: + { + btVector3* vertices = (btVector3*)shape; + ///calcNormal + penetrationVector = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); + penetrationVector.normalize(); + if (index) + penetrationVector *= btScalar(-1.); + break; + } + default: + { + +#if __ASSERT + spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType); +#endif // __ASSERT + } + } + +} + +#endif //_SPU_PREFERRED_PENETRATION_DIRECTIONS_H diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp new file mode 100644 index 00000000..5e1202c0 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp @@ -0,0 +1,1160 @@ +/* + Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. + All rights reserved. + +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 "PfxContactBoxBox.h" + +#include +#include "../PlatformDefinitions.h" +#include "boxBoxDistance.h" + +static inline float sqr( float a ) +{ + return (a * a); +} + +enum BoxSepAxisType +{ + A_AXIS, B_AXIS, CROSS_AXIS +}; + +//------------------------------------------------------------------------------------------------- +// voronoiTol: bevels Voronoi planes slightly which helps when features are parallel. +//------------------------------------------------------------------------------------------------- + +static const float voronoiTol = -1.0e-5f; + +//------------------------------------------------------------------------------------------------- +// separating axis tests: gaps along each axis are computed, and the axis with the maximum +// gap is stored. cross product axes are normalized. +//------------------------------------------------------------------------------------------------- + +#define AaxisTest( dim, letter, first ) \ +{ \ + if ( first ) \ + { \ + maxGap = gap = gapsA.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + axisType = A_AXIS; \ + faceDimA = dim; \ + axisA = identity.getCol##dim(); \ + } \ + else \ + { \ + gap = gapsA.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = A_AXIS; \ + faceDimA = dim; \ + axisA = identity.getCol##dim(); \ + } \ + } \ +} + + +#define BaxisTest( dim, letter ) \ +{ \ + gap = gapsB.get##letter(); \ + if ( gap > distanceThreshold ) return gap; \ + else if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = B_AXIS; \ + faceDimB = dim; \ + axisB = identity.getCol##dim(); \ + } \ +} + +#define CrossAxisTest( dima, dimb, letterb ) \ +{ \ + const float lsqr_tolerance = 1.0e-30f; \ + float lsqr; \ + \ + lsqr = lsqrs.getCol##dima().get##letterb(); \ + \ + if ( lsqr > lsqr_tolerance ) \ + { \ + float l_recip = 1.0f / sqrtf( lsqr ); \ + gap = float(gapsAxB.getCol##dima().get##letterb()) * l_recip; \ + \ + if ( gap > distanceThreshold ) \ + { \ + return gap; \ + } \ + \ + if ( gap > maxGap ) \ + { \ + maxGap = gap; \ + axisType = CROSS_AXIS; \ + edgeDimA = dima; \ + edgeDimB = dimb; \ + axisA = cross(identity.getCol##dima(),matrixAB.getCol##dimb()) * l_recip; \ + } \ + } \ +} + +//------------------------------------------------------------------------------------------------- +// tests whether a vertex of box B and a face of box A are the closest features +//------------------------------------------------------------------------------------------------- + +inline +float +VertexBFaceATest( + bool & inVoronoi, + float & t0, + float & t1, + const vmVector3 & hA, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesB ) +{ + // compute a corner of box B in A's coordinate system + + vmVector3 corner = + vmVector3( faceOffsetAB + matrixAB.getCol0() * scalesB.getX() + matrixAB.getCol1() * scalesB.getY() ); + + // compute the parameters of the point on A, closest to this corner + + t0 = corner[0]; + t1 = corner[1]; + + if ( t0 > hA[0] ) + t0 = hA[0]; + else if ( t0 < -hA[0] ) + t0 = -hA[0]; + if ( t1 > hA[1] ) + t1 = hA[1]; + else if ( t1 < -hA[1] ) + t1 = -hA[1]; + + // do the Voronoi test: already know the point on B is in the Voronoi region of the + // point on A, check the reverse. + + vmVector3 facePointB = + vmVector3( mulPerElem( faceOffsetBA + matrixBA.getCol0() * t0 + matrixBA.getCol1() * t1 - scalesB, signsB ) ); + + inVoronoi = ( ( facePointB[0] >= voronoiTol * facePointB[2] ) && + ( facePointB[1] >= voronoiTol * facePointB[0] ) && + ( facePointB[2] >= voronoiTol * facePointB[1] ) ); + + return (sqr( corner[0] - t0 ) + sqr( corner[1] - t1 ) + sqr( corner[2] )); +} + +#define VertexBFaceA_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + localPointA.setX(t0); \ + localPointA.setY(t1); \ + localPointB.setX( scalesB.getX() ); \ + localPointB.setY( scalesB.getY() ); \ + featureA = F; \ + featureB = V; \ +} + +void +VertexBFaceATests( + bool & done, + float & minDistSqr, + vmPoint3 & localPointA, + vmPoint3 & localPointB, + FeatureType & featureA, + FeatureType & featureB, + const vmVector3 & hA, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesB, + bool first ) +{ + + float t0, t1; + float distSqr; + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( first ) { + VertexBFaceA_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsB, scalesB ); + + if ( distSqr < minDistSqr ) { + VertexBFaceA_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// VertexAFaceBTest: tests whether a vertex of box A and a face of box B are the closest features +//------------------------------------------------------------------------------------------------- + +inline +float +VertexAFaceBTest( + bool & inVoronoi, + float & t0, + float & t1, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) scalesA ) +{ + vmVector3 corner = + vmVector3( faceOffsetBA + matrixBA.getCol0() * scalesA.getX() + matrixBA.getCol1() * scalesA.getY() ); + + t0 = corner[0]; + t1 = corner[1]; + + if ( t0 > hB[0] ) + t0 = hB[0]; + else if ( t0 < -hB[0] ) + t0 = -hB[0]; + if ( t1 > hB[1] ) + t1 = hB[1]; + else if ( t1 < -hB[1] ) + t1 = -hB[1]; + + vmVector3 facePointA = + vmVector3( mulPerElem( faceOffsetAB + matrixAB.getCol0() * t0 + matrixAB.getCol1() * t1 - scalesA, signsA ) ); + + inVoronoi = ( ( facePointA[0] >= voronoiTol * facePointA[2] ) && + ( facePointA[1] >= voronoiTol * facePointA[0] ) && + ( facePointA[2] >= voronoiTol * facePointA[1] ) ); + + return (sqr( corner[0] - t0 ) + sqr( corner[1] - t1 ) + sqr( corner[2] )); +} + +#define VertexAFaceB_SetNewMin() \ +{ \ + minDistSqr = distSqr; \ + localPointB.setX(t0); \ + localPointB.setY(t1); \ + localPointA.setX( scalesA.getX() ); \ + localPointA.setY( scalesA.getY() ); \ + featureA = V; \ + featureB = F; \ +} + +void +VertexAFaceBTests( + bool & done, + float & minDistSqr, + vmPoint3 & localPointA, + vmPoint3 & localPointB, + FeatureType & featureA, + FeatureType & featureB, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) scalesA, + bool first ) +{ + float t0, t1; + float distSqr; + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( first ) { + VertexAFaceB_SetNewMin(); + } else { + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, scalesA ); + + if ( distSqr < minDistSqr ) { + VertexAFaceB_SetNewMin(); + } +} + +//------------------------------------------------------------------------------------------------- +// CustomEdgeEdgeTest: +// +// tests whether a pair of edges are the closest features +// +// note on the shorthand: +// 'a' & 'b' refer to the edges. +// 'c' is the dimension of the axis that points from the face center to the edge Center +// 'd' is the dimension of the edge Direction +// the dimension of the face normal is 2 +//------------------------------------------------------------------------------------------------- + +#define CustomEdgeEdgeTest( ac, ac_letter, ad, ad_letter, bc, bc_letter, bd, bd_letter ) \ +{ \ + vmVector3 edgeOffsetAB; \ + vmVector3 edgeOffsetBA; \ + \ + edgeOffsetAB = faceOffsetAB + matrixAB.getCol##bc() * scalesB.get##bc_letter(); \ + edgeOffsetAB.set##ac_letter( edgeOffsetAB.get##ac_letter() - scalesA.get##ac_letter() ); \ + \ + edgeOffsetBA = faceOffsetBA + matrixBA.getCol##ac() * scalesA.get##ac_letter(); \ + edgeOffsetBA.set##bc_letter( edgeOffsetBA.get##bc_letter() - scalesB.get##bc_letter() ); \ + \ + float dirDot = matrixAB.getCol##bd().get##ad_letter(); \ + float denom = 1.0f - dirDot*dirDot; \ + float edgeOffsetAB_ad = edgeOffsetAB.get##ad_letter(); \ + float edgeOffsetBA_bd = edgeOffsetBA.get##bd_letter(); \ + \ + if ( denom == 0.0f ) \ + { \ + tA = 0.0f; \ + } \ + else \ + { \ + tA = ( edgeOffsetAB_ad + edgeOffsetBA_bd * dirDot ) / denom; \ + } \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + \ + tB = tA * dirDot + edgeOffsetBA_bd; \ + \ + if ( tB < -hB[bd] ) \ + { \ + tB = -hB[bd]; \ + tA = tB * dirDot + edgeOffsetAB_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + else if ( tB > hB[bd] ) \ + { \ + tB = hB[bd]; \ + tA = tB * dirDot + edgeOffsetAB_ad; \ + \ + if ( tA < -hA[ad] ) tA = -hA[ad]; \ + else if ( tA > hA[ad] ) tA = hA[ad]; \ + } \ + \ + vmVector3 edgeOffAB = vmVector3( mulPerElem( edgeOffsetAB + matrixAB.getCol##bd() * tB, signsA ) );\ + vmVector3 edgeOffBA = vmVector3( mulPerElem( edgeOffsetBA + matrixBA.getCol##ad() * tA, signsB ) );\ + \ + inVoronoi = ( edgeOffAB[ac] >= voronoiTol * edgeOffAB[2] ) && \ + ( edgeOffAB[2] >= voronoiTol * edgeOffAB[ac] ) && \ + ( edgeOffBA[bc] >= voronoiTol * edgeOffBA[2] ) && \ + ( edgeOffBA[2] >= voronoiTol * edgeOffBA[bc] ); \ + \ + edgeOffAB[ad] -= tA; \ + edgeOffBA[bd] -= tB; \ + \ + return dot(edgeOffAB,edgeOffAB); \ +} + +float +CustomEdgeEdgeTest_0101( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 0, X, 1, Y, 0, X, 1, Y ); +} + +float +CustomEdgeEdgeTest_0110( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 0, X, 1, Y, 1, Y, 0, X ); +} + +float +CustomEdgeEdgeTest_1001( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 1, Y, 0, X, 0, X, 1, Y ); +} + +float +CustomEdgeEdgeTest_1010( + bool & inVoronoi, + float & tA, + float & tB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB ) +{ + CustomEdgeEdgeTest( 1, Y, 0, X, 1, Y, 0, X ); +} + +#define EdgeEdge_SetNewMin( ac_letter, ad_letter, bc_letter, bd_letter ) \ +{ \ + minDistSqr = distSqr; \ + localPointA.set##ac_letter(scalesA.get##ac_letter()); \ + localPointA.set##ad_letter(tA); \ + localPointB.set##bc_letter(scalesB.get##bc_letter()); \ + localPointB.set##bd_letter(tB); \ + otherFaceDimA = testOtherFaceDimA; \ + otherFaceDimB = testOtherFaceDimB; \ + featureA = E; \ + featureB = E; \ +} + +void +EdgeEdgeTests( + bool & done, + float & minDistSqr, + vmPoint3 & localPointA, + vmPoint3 & localPointB, + int & otherFaceDimA, + int & otherFaceDimB, + FeatureType & featureA, + FeatureType & featureB, + const vmVector3 & hA, + const vmVector3 & hB, + PE_REF(vmVector3) faceOffsetAB, + PE_REF(vmVector3) faceOffsetBA, + const vmMatrix3 & matrixAB, + const vmMatrix3 & matrixBA, + PE_REF(vmVector3) signsA, + PE_REF(vmVector3) signsB, + PE_REF(vmVector3) scalesA, + PE_REF(vmVector3) scalesB, + bool first ) +{ + + float distSqr; + float tA, tB; + + int testOtherFaceDimA, testOtherFaceDimB; + + testOtherFaceDimA = 0; + testOtherFaceDimB = 0; + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( first ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } else { + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + testOtherFaceDimB = 0; + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, X, Y ); + } + + if ( done ) + return; + + testOtherFaceDimA = 0; + testOtherFaceDimB = 1; + signsB.setX( -signsB.getX() ); + scalesB.setX( -scalesB.getX() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + signsA.setX( -signsA.getX() ); + scalesA.setX( -scalesA.getX() ); + + distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( X, Y, Y, X ); + } + + if ( done ) + return; + + testOtherFaceDimA = 1; + testOtherFaceDimB = 1; + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsB.setY( -signsB.getY() ); + scalesB.setY( -scalesB.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } + + if ( done ) + return; + + signsA.setY( -signsA.getY() ); + scalesA.setY( -scalesA.getY() ); + + distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, + matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); + + if ( distSqr < minDistSqr ) { + EdgeEdge_SetNewMin( Y, X, Y, X ); + } +} + + +float +boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB, + PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB, + const vmTransform3 & transformB, + float distanceThreshold) +{ + vmMatrix3 identity; + identity = vmMatrix3::identity(); + vmVector3 ident[3]; + ident[0] = identity.getCol0(); + ident[1] = identity.getCol1(); + ident[2] = identity.getCol2(); + + // get relative transformations + + vmTransform3 transformAB, transformBA; + vmMatrix3 matrixAB, matrixBA; + vmVector3 offsetAB, offsetBA; + + transformAB = orthoInverse(transformA) * transformB; + transformBA = orthoInverse(transformAB); + + matrixAB = transformAB.getUpper3x3(); + offsetAB = transformAB.getTranslation(); + matrixBA = transformBA.getUpper3x3(); + offsetBA = transformBA.getTranslation(); + + vmMatrix3 absMatrixAB = absPerElem(matrixAB); + vmMatrix3 absMatrixBA = absPerElem(matrixBA); + + // find separating axis with largest gap between projections + + BoxSepAxisType axisType; + vmVector3 axisA(0.0f), axisB(0.0f); + float gap, maxGap; + int faceDimA = 0, faceDimB = 0, edgeDimA = 0, edgeDimB = 0; + + // face axes + + vmVector3 gapsA = absPerElem(offsetAB) - boxA.mHalf - absMatrixAB * boxB.mHalf; + + AaxisTest(0,X,true); + AaxisTest(1,Y,false); + AaxisTest(2,Z,false); + + vmVector3 gapsB = absPerElem(offsetBA) - boxB.mHalf - absMatrixBA * boxA.mHalf; + + BaxisTest(0,X); + BaxisTest(1,Y); + BaxisTest(2,Z); + + // cross product axes + + // ŠOÏ‚ª‚O‚Ì‚Æ‚«‚Ì‘Îô + absMatrixAB += vmMatrix3(1.0e-5f); + absMatrixBA += vmMatrix3(1.0e-5f); + + vmMatrix3 lsqrs, projOffset, projAhalf, projBhalf; + + lsqrs.setCol0( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + + mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) ); + lsqrs.setCol1( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + + mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); + lsqrs.setCol2( mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) + + mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); + + projOffset.setCol0(matrixBA.getCol1() * offsetAB.getZ() - matrixBA.getCol2() * offsetAB.getY()); + projOffset.setCol1(matrixBA.getCol2() * offsetAB.getX() - matrixBA.getCol0() * offsetAB.getZ()); + projOffset.setCol2(matrixBA.getCol0() * offsetAB.getY() - matrixBA.getCol1() * offsetAB.getX()); + + projAhalf.setCol0(absMatrixBA.getCol1() * boxA.mHalf.getZ() + absMatrixBA.getCol2() * boxA.mHalf.getY()); + projAhalf.setCol1(absMatrixBA.getCol2() * boxA.mHalf.getX() + absMatrixBA.getCol0() * boxA.mHalf.getZ()); + projAhalf.setCol2(absMatrixBA.getCol0() * boxA.mHalf.getY() + absMatrixBA.getCol1() * boxA.mHalf.getX()); + + projBhalf.setCol0(absMatrixAB.getCol1() * boxB.mHalf.getZ() + absMatrixAB.getCol2() * boxB.mHalf.getY()); + projBhalf.setCol1(absMatrixAB.getCol2() * boxB.mHalf.getX() + absMatrixAB.getCol0() * boxB.mHalf.getZ()); + projBhalf.setCol2(absMatrixAB.getCol0() * boxB.mHalf.getY() + absMatrixAB.getCol1() * boxB.mHalf.getX()); + + vmMatrix3 gapsAxB = absPerElem(projOffset) - projAhalf - transpose(projBhalf); + + CrossAxisTest(0,0,X); + CrossAxisTest(0,1,Y); + CrossAxisTest(0,2,Z); + CrossAxisTest(1,0,X); + CrossAxisTest(1,1,Y); + CrossAxisTest(1,2,Z); + CrossAxisTest(2,0,X); + CrossAxisTest(2,1,Y); + CrossAxisTest(2,2,Z); + + // need to pick the face on each box whose normal best matches the separating axis. + // will transform vectors to be in the coordinate system of this face to simplify things later. + // for this, a permutation matrix can be used, which the next section computes. + + int dimA[3], dimB[3]; + + if ( axisType == A_AXIS ) { + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + axisB = matrixBA * -axisA; + + vmVector3 absAxisB = vmVector3(absPerElem(axisB)); + + if ( ( absAxisB[0] > absAxisB[1] ) && ( absAxisB[0] > absAxisB[2] ) ) + faceDimB = 0; + else if ( absAxisB[1] > absAxisB[2] ) + faceDimB = 1; + else + faceDimB = 2; + } else if ( axisType == B_AXIS ) { + if ( dot(axisB,offsetBA) < 0.0f ) + axisB = -axisB; + axisA = matrixAB * -axisB; + + vmVector3 absAxisA = vmVector3(absPerElem(axisA)); + + if ( ( absAxisA[0] > absAxisA[1] ) && ( absAxisA[0] > absAxisA[2] ) ) + faceDimA = 0; + else if ( absAxisA[1] > absAxisA[2] ) + faceDimA = 1; + else + faceDimA = 2; + } + + if ( axisType == CROSS_AXIS ) { + if ( dot(axisA,offsetAB) < 0.0f ) + axisA = -axisA; + axisB = matrixBA * -axisA; + + vmVector3 absAxisA = vmVector3(absPerElem(axisA)); + vmVector3 absAxisB = vmVector3(absPerElem(axisB)); + + dimA[1] = edgeDimA; + dimB[1] = edgeDimB; + + if ( edgeDimA == 0 ) { + if ( absAxisA[1] > absAxisA[2] ) { + dimA[0] = 2; + dimA[2] = 1; + } else { + dimA[0] = 1; + dimA[2] = 2; + } + } else if ( edgeDimA == 1 ) { + if ( absAxisA[2] > absAxisA[0] ) { + dimA[0] = 0; + dimA[2] = 2; + } else { + dimA[0] = 2; + dimA[2] = 0; + } + } else { + if ( absAxisA[0] > absAxisA[1] ) { + dimA[0] = 1; + dimA[2] = 0; + } else { + dimA[0] = 0; + dimA[2] = 1; + } + } + + if ( edgeDimB == 0 ) { + if ( absAxisB[1] > absAxisB[2] ) { + dimB[0] = 2; + dimB[2] = 1; + } else { + dimB[0] = 1; + dimB[2] = 2; + } + } else if ( edgeDimB == 1 ) { + if ( absAxisB[2] > absAxisB[0] ) { + dimB[0] = 0; + dimB[2] = 2; + } else { + dimB[0] = 2; + dimB[2] = 0; + } + } else { + if ( absAxisB[0] > absAxisB[1] ) { + dimB[0] = 1; + dimB[2] = 0; + } else { + dimB[0] = 0; + dimB[2] = 1; + } + } + } else { + dimA[2] = faceDimA; + dimA[0] = (faceDimA+1)%3; + dimA[1] = (faceDimA+2)%3; + dimB[2] = faceDimB; + dimB[0] = (faceDimB+1)%3; + dimB[1] = (faceDimB+2)%3; + } + + vmMatrix3 aperm_col, bperm_col; + + aperm_col.setCol0(ident[dimA[0]]); + aperm_col.setCol1(ident[dimA[1]]); + aperm_col.setCol2(ident[dimA[2]]); + + bperm_col.setCol0(ident[dimB[0]]); + bperm_col.setCol1(ident[dimB[1]]); + bperm_col.setCol2(ident[dimB[2]]); + + vmMatrix3 aperm_row, bperm_row; + + aperm_row = transpose(aperm_col); + bperm_row = transpose(bperm_col); + + // permute all box parameters to be in the face coordinate systems + + vmMatrix3 matrixAB_perm = aperm_row * matrixAB * bperm_col; + vmMatrix3 matrixBA_perm = transpose(matrixAB_perm); + + vmVector3 offsetAB_perm, offsetBA_perm; + + offsetAB_perm = aperm_row * offsetAB; + offsetBA_perm = bperm_row * offsetBA; + + vmVector3 halfA_perm, halfB_perm; + + halfA_perm = aperm_row * boxA.mHalf; + halfB_perm = bperm_row * boxB.mHalf; + + // compute the vector between the centers of each face, in each face's coordinate frame + + vmVector3 signsA_perm, signsB_perm, scalesA_perm, scalesB_perm, faceOffsetAB_perm, faceOffsetBA_perm; + + signsA_perm = copySignPerElem(vmVector3(1.0f),aperm_row * axisA); + signsB_perm = copySignPerElem(vmVector3(1.0f),bperm_row * axisB); + scalesA_perm = mulPerElem( signsA_perm, halfA_perm ); + scalesB_perm = mulPerElem( signsB_perm, halfB_perm ); + + faceOffsetAB_perm = offsetAB_perm + matrixAB_perm.getCol2() * scalesB_perm.getZ(); + faceOffsetAB_perm.setZ( faceOffsetAB_perm.getZ() - scalesA_perm.getZ() ); + + faceOffsetBA_perm = offsetBA_perm + matrixBA_perm.getCol2() * scalesA_perm.getZ(); + faceOffsetBA_perm.setZ( faceOffsetBA_perm.getZ() - scalesB_perm.getZ() ); + + if ( maxGap < 0.0f ) { + // if boxes overlap, this will separate the faces for finding points of penetration. + + faceOffsetAB_perm -= aperm_row * axisA * maxGap * 1.01f; + faceOffsetBA_perm -= bperm_row * axisB * maxGap * 1.01f; + } + + // for each vertex/face or edge/edge pair of the two faces, find the closest points. + // + // these points each have an associated box feature (vertex, edge, or face). if each + // point is in the external Voronoi region of the other's feature, they are the + // closest points of the boxes, and the algorithm can exit. + // + // the feature pairs are arranged so that in the general case, the first test will + // succeed. degenerate cases (parallel faces) may require up to all tests in the + // worst case. + // + // if for some reason no case passes the Voronoi test, the features with the minimum + // distance are returned. + + vmPoint3 localPointA_perm, localPointB_perm; + float minDistSqr; + bool done; + + vmVector3 hA_perm( halfA_perm ), hB_perm( halfB_perm ); + + localPointA_perm.setZ( scalesA_perm.getZ() ); + localPointB_perm.setZ( scalesB_perm.getZ() ); + scalesA_perm.setZ(0.0f); + scalesB_perm.setZ(0.0f); + + int otherFaceDimA, otherFaceDimB; + FeatureType featureA, featureB; + + if ( axisType == CROSS_AXIS ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, featureA, featureB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); + + if ( !done ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); + } + } + } else if ( axisType == B_AXIS ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, true ); + + if ( !done ) { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, featureA, featureB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, false ); + } + } + } else { + VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, true ); + + if ( !done ) { + VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, + featureA, featureB, + hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); + + if ( !done ) { + EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, + otherFaceDimA, otherFaceDimB, featureA, featureB, + hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, + matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, + scalesA_perm, scalesB_perm, false ); + } + } + } + + // convert local points from face-local to box-local coordinate system + + + boxPointA.localPoint = vmPoint3( aperm_col * vmVector3( localPointA_perm )) ; + boxPointB.localPoint = vmPoint3( bperm_col * vmVector3( localPointB_perm )) ; + +#if 0 + // find which features of the boxes are involved. + // the only feature pairs which occur in this function are VF, FV, and EE, even though the + // closest points might actually lie on sub-features, as in a VF contact might be used for + // what's actually a VV contact. this means some feature pairs could possibly seem distinct + // from others, although their contact positions are the same. don't know yet whether this + // matters. + + int sA[3], sB[3]; + + sA[0] = boxPointA.localPoint.getX() > 0.0f; + sA[1] = boxPointA.localPoint.getY() > 0.0f; + sA[2] = boxPointA.localPoint.getZ() > 0.0f; + + sB[0] = boxPointB.localPoint.getX() > 0.0f; + sB[1] = boxPointB.localPoint.getY() > 0.0f; + sB[2] = boxPointB.localPoint.getZ() > 0.0f; + + if ( featureA == F ) { + boxPointA.setFaceFeature( dimA[2], sA[dimA[2]] ); + } else if ( featureA == E ) { + boxPointA.setEdgeFeature( dimA[2], sA[dimA[2]], dimA[otherFaceDimA], sA[dimA[otherFaceDimA]] ); + } else { + boxPointA.setVertexFeature( sA[0], sA[1], sA[2] ); + } + + if ( featureB == F ) { + boxPointB.setFaceFeature( dimB[2], sB[dimB[2]] ); + } else if ( featureB == E ) { + boxPointB.setEdgeFeature( dimB[2], sB[dimB[2]], dimB[otherFaceDimB], sB[dimB[otherFaceDimB]] ); + } else { + boxPointB.setVertexFeature( sB[0], sB[1], sB[2] ); + } +#endif + + normal = transformA * axisA; + + if ( maxGap < 0.0f ) { + return (maxGap); + } else { + return (sqrtf( minDistSqr )); + } +} diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h new file mode 100644 index 00000000..0d4957de --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. + All rights reserved. + +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 __BOXBOXDISTANCE_H__ +#define __BOXBOXDISTANCE_H__ + + +#include "Box.h" + + +//--------------------------------------------------------------------------- +// boxBoxDistance: +// +// description: +// this computes info that can be used for the collision response of two boxes. when the boxes +// do not overlap, the points are set to the closest points of the boxes, and a positive +// distance between them is returned. if the boxes do overlap, a negative distance is returned +// and the points are set to two points that would touch after the boxes are translated apart. +// the contact normal gives the direction to repel or separate the boxes when they touch or +// overlap (it's being approximated here as one of the 15 "separating axis" directions). +// +// returns: +// positive or negative distance between two boxes. +// +// args: +// vmVector3& normal: set to a unit contact normal pointing from box A to box B. +// +// BoxPoint& boxPointA, BoxPoint& boxPointB: +// set to a closest point or point of penetration on each box. +// +// Box boxA, Box boxB: +// boxes, represented as 3 half-widths +// +// const vmTransform3& transformA, const vmTransform3& transformB: +// box transformations, in world coordinates +// +// float distanceThreshold: +// the algorithm will exit early if it finds that the boxes are more distant than this +// threshold, and not compute a contact normal or points. if this distance returned +// exceeds the threshold, all the other output data may not have been computed. by +// default, this is set to MAX_FLOAT so it will have no effect. +// +//--------------------------------------------------------------------------- + +float +boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB, + PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB, + const vmTransform3 & transformB, + float distanceThreshold = FLT_MAX ); + +#endif /* __BOXBOXDISTANCE_H__ */ diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt new file mode 100644 index 00000000..5b4a9070 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt @@ -0,0 +1 @@ +Empty placeholder for future Libspe2 SPU task diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp b/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp new file mode 100644 index 00000000..fe619555 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp @@ -0,0 +1,214 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 "SpuSampleTask.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "../PlatformDefinitions.h" +#include "../SpuFakeDma.h" +#include "LinearMath/btMinMax.h" + +#ifdef __SPU__ +#include +#else +#include +#define spu_printf printf +#endif + +#define MAX_NUM_BODIES 8192 + +struct SampleTask_LocalStoreMemory +{ + ATTRIBUTE_ALIGNED16(char gLocalRigidBody [sizeof(btRigidBody)+16]); + ATTRIBUTE_ALIGNED16(void* gPointerArray[MAX_NUM_BODIES]); + +}; + + + + +//-- MAIN METHOD +void processSampleTask(void* userPtr, void* lsMemory) +{ + // BT_PROFILE("processSampleTask"); + + SampleTask_LocalStoreMemory* localMemory = (SampleTask_LocalStoreMemory*)lsMemory; + + SpuSampleTaskDesc* taskDescPtr = (SpuSampleTaskDesc*)userPtr; + SpuSampleTaskDesc& taskDesc = *taskDescPtr; + + switch (taskDesc.m_sampleCommand) + { + case CMD_SAMPLE_INTEGRATE_BODIES: + { + btTransform predictedTrans; + btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr; + + int batchSize = taskDesc.m_sampleValue; + if (batchSize>MAX_NUM_BODIES) + { + spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n"); + break; + } + int dmaArraySize = batchSize*sizeof(void*); + + uint64_t ppuArrayAddress = reinterpret_cast(eaPtr); + + // spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize); + + if (dmaArraySize>=16) + { + cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } else + { + stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize); + } + + + for ( int i=0;igLocalRigidBody[0]; + void* shortAdd = localMemory->gPointerArray[i]; + uint64_t ppuRigidBodyAddress = reinterpret_cast(shortAdd); + + // spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr); + + int dmaBodySize = sizeof(btRigidBody); + + cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + float timeStep = 1.f/60.f; + + btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj); + if (body) + { + if (body->isActive() && (!body->isStaticOrKinematicObject())) + { + body->predictIntegratedTransform(timeStep, predictedTrans); + body->proceedToTransform( predictedTrans); + void* ptr = (void*)localPtr; + // spu_printf("cellDmaLargePut from %llx to LS %llx\n",ptr,ppuRigidBodyAddress); + + cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + } + } + + } + break; + } + + + case CMD_SAMPLE_PREDICT_MOTION_BODIES: + { + btTransform predictedTrans; + btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr; + + int batchSize = taskDesc.m_sampleValue; + int dmaArraySize = batchSize*sizeof(void*); + + if (batchSize>MAX_NUM_BODIES) + { + spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n"); + break; + } + + uint64_t ppuArrayAddress = reinterpret_cast(eaPtr); + + // spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize); + + if (dmaArraySize>=16) + { + cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } else + { + stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize); + } + + + for ( int i=0;igLocalRigidBody[0]; + void* shortAdd = localMemory->gPointerArray[i]; + uint64_t ppuRigidBodyAddress = reinterpret_cast(shortAdd); + + // spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr); + + int dmaBodySize = sizeof(btRigidBody); + + cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + + + float timeStep = 1.f/60.f; + + btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj); + if (body) + { + if (!body->isStaticOrKinematicObject()) + { + if (body->isActive()) + { + body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); + + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + + void* ptr = (void*)localPtr; + cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(1)); + } + } + } + + } + break; + } + + + + default: + { + + } + }; +} + + +#if defined(__CELLOS_LV2__) || defined (LIBSPE2) + +ATTRIBUTE_ALIGNED16(SampleTask_LocalStoreMemory gLocalStoreMemory); + +void* createSampleLocalStoreMemory() +{ + return &gLocalStoreMemory; +} +#else +void* createSampleLocalStoreMemory() +{ + return new SampleTask_LocalStoreMemory; +}; + +#endif diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h b/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h new file mode 100644 index 00000000..c8ebdfd6 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h @@ -0,0 +1,54 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 SPU_SAMPLE_TASK_H +#define SPU_SAMPLE_TASK_H + +#include "../PlatformDefinitions.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" + +#include "LinearMath/btAlignedAllocator.h" + + +enum +{ + CMD_SAMPLE_INTEGRATE_BODIES = 1, + CMD_SAMPLE_PREDICT_MOTION_BODIES +}; + + + +ATTRIBUTE_ALIGNED16(struct) SpuSampleTaskDesc +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + uint32_t m_sampleCommand; + uint32_t m_taskId; + + uint64_t m_mainMemoryPtr; + int m_sampleValue; + + +}; + + +void processSampleTask(void* userPtr, void* lsMemory); +void* createSampleLocalStoreMemory(); + + +#endif //SPU_SAMPLE_TASK_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/readme.txt b/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/readme.txt new file mode 100644 index 00000000..5b4a9070 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/readme.txt @@ -0,0 +1 @@ +Empty placeholder for future Libspe2 SPU task diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp b/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp new file mode 100644 index 00000000..11cb9e7c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp @@ -0,0 +1,222 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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. +*/ + +//#define __CELLOS_LV2__ 1 + +#define USE_SAMPLE_PROCESS 1 +#ifdef USE_SAMPLE_PROCESS + + +#include "SpuSampleTaskProcess.h" +#include + +#ifdef __SPU__ + + + +void SampleThreadFunc(void* userPtr,void* lsMemory) +{ + //do nothing + printf("hello world\n"); +} + + +void* SamplelsMemoryFunc() +{ + //don't create local store memory, just return 0 + return 0; +} + + +#else + + +#include "btThreadSupportInterface.h" + +//# include "SPUAssert.h" +#include + + + +extern "C" { + extern char SPU_SAMPLE_ELF_SYMBOL[]; +} + + + + + +SpuSampleTaskProcess::SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks); + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + + m_initialized = false; + + m_threadInterface->startSPU(); + + +} + +SpuSampleTaskProcess::~SpuSampleTaskProcess() +{ + m_threadInterface->stopSPU(); + +} + + + +void SpuSampleTaskProcess::initialize() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuSampleTaskProcess::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_initialized = true; + +} + + +void SpuSampleTaskProcess::issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand) +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuSampleTaskProcess::issueTask (m_currentTask= %d\)n", m_currentTask); +#endif //DEBUG_SPU_TASK_SCHEDULING + + m_taskBusy[m_currentTask] = true; + m_numBusyTasks++; + + SpuSampleTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask]; + { + // send task description in event message + // no error checking here... + // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. + + taskDesc.m_mainMemoryPtr = reinterpret_cast(sampleMainMemPtr); + taskDesc.m_sampleValue = sampleValue; + taskDesc.m_sampleCommand = sampleCommand; + + //some bookkeeping to recognize finished tasks + taskDesc.m_taskId = m_currentTask; + } + + + m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc, m_currentTask); + + // if all tasks busy, wait for spu event to clear the task. + + if (m_numBusyTasks >= m_maxNumOutstandingTasks) + { + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + + //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + // find new task buffer + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + break; + } + } +} + + +///Optional PPU-size post processing for each task +void SpuSampleTaskProcess::postProcess(int taskId, int outputSize) +{ + +} + + +void SpuSampleTaskProcess::flush() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("\nSpuCollisionTaskProcess::flush()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + + // all tasks are issued, wait for all tasks to be complete + while(m_numBusyTasks > 0) + { +// Consolidating SPU code + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + } + + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} + +#endif + + +#endif //USE_SAMPLE_PROCESS diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.h b/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.h new file mode 100644 index 00000000..6173225a --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.h @@ -0,0 +1,153 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_SPU_SAMPLE_TASK_PROCESS_H +#define BT_SPU_SAMPLE_TASK_PROCESS_H + +#include + + +#include "PlatformDefinitions.h" + +#include + +#include "LinearMath/btAlignedObjectArray.h" + + +#include "SpuSampleTask/SpuSampleTask.h" + + +//just add your commands here, try to keep them globally unique for debugging purposes +#define CMD_SAMPLE_TASK_COMMAND 10 + + + +/// SpuSampleTaskProcess handles SPU processing of collision pairs. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class SpuSampleTaskProcess +{ + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArraym_spuSampleTaskDesc; + + int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + int m_currentTask; + + bool m_initialized; + + void postProcess(int taskId, int outputSize); + + class btThreadSupportInterface* m_threadInterface; + + int m_maxNumOutstandingTasks; + + + +public: + SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks); + + ~SpuSampleTaskProcess(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize(); + + void issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush(); +}; + + +#if defined(USE_LIBSPE2) && defined(__SPU__) +////////////////////MAIN///////////////////////////// +#include "../SpuLibspe2Support.h" +#include +#include +#include + +void * SamplelsMemoryFunc(); +void SampleThreadFunc(void* userPtr,void* lsMemory); + +//#define DEBUG_LIBSPE2_MAINLOOP + +int main(unsigned long long speid, addr64 argp, addr64 envp) +{ + printf("SPU is up \n"); + + ATTRIBUTE_ALIGNED128(btSpuStatus status); + ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ; + unsigned int received_message = Spu_Mailbox_Event_Nothing; + bool shutdown = false; + + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + status.m_status = Spu_Status_Free; + status.m_lsMemory.p = SamplelsMemoryFunc(); + + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + while (!shutdown) + { + received_message = spu_read_in_mbox(); + + + + switch(received_message) + { + case Spu_Mailbox_Event_Shutdown: + shutdown = true; + break; + case Spu_Mailbox_Event_Task: + // refresh the status +#ifdef DEBUG_LIBSPE2_MAINLOOP + printf("SPU recieved Task \n"); +#endif //DEBUG_LIBSPE2_MAINLOOP + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + btAssert(status.m_status==Spu_Status_Occupied); + + cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + SampleThreadFunc((void*)&taskDesc, reinterpret_cast (taskDesc.m_mainMemoryPtr) ); + break; + case Spu_Mailbox_Event_Nothing: + default: + break; + } + + // set to status free and wait for next task + status.m_status = Spu_Status_Free; + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + } + return 0; +} +////////////////////////////////////////////////////// +#endif + + + +#endif // BT_SPU_SAMPLE_TASK_PROCESS_H + diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSync.h b/Code/Physics/src/BulletMultiThreaded/SpuSync.h new file mode 100644 index 00000000..4157b8f0 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/SpuSync.h @@ -0,0 +1,149 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marten Svanfeldt +*/ + +#ifndef BT_SPU_SYNC_H +#define BT_SPU_SYNC_H + + +#include "PlatformDefinitions.h" + + +#if defined(WIN32) + +#define WIN32_LEAN_AND_MEAN +#ifdef _XBOX +#include +#else +#include +#endif + +///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms. +class btSpinlock +{ +public: + //typedef volatile LONG SpinVariable; + typedef CRITICAL_SECTION SpinVariable; + + btSpinlock (SpinVariable* var) + : spinVariable (var) + {} + + void Init () + { + //*spinVariable = 0; + InitializeCriticalSection(spinVariable); + } + + void Lock () + { + EnterCriticalSection(spinVariable); + } + + void Unlock () + { + LeaveCriticalSection(spinVariable); + } + +private: + SpinVariable* spinVariable; +}; + + +#elif defined (__CELLOS_LV2__) + +//#include +#include + +///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms. +class btSpinlock +{ +public: + typedef CellSyncMutex SpinVariable; + + btSpinlock (SpinVariable* var) + : spinVariable (var) + {} + + void Init () + { +#ifndef __SPU__ + //*spinVariable = 1; + cellSyncMutexInitialize(spinVariable); +#endif + } + + + + void Lock () + { +#ifdef __SPU__ + // lock semaphore + /*while (cellAtomicTestAndDecr32(atomic_buf, (uint64_t)spinVariable) == 0) + { + + };*/ + cellSyncMutexLock((uint64_t)spinVariable); +#endif + } + + void Unlock () + { +#ifdef __SPU__ + //cellAtomicIncr32(atomic_buf, (uint64_t)spinVariable); + cellSyncMutexUnlock((uint64_t)spinVariable); +#endif + } + + +private: + SpinVariable* spinVariable; + ATTRIBUTE_ALIGNED128(uint32_t atomic_buf[32]); +}; + +#else +//create a dummy implementation (without any locking) useful for serial processing +class btSpinlock +{ +public: + typedef int SpinVariable; + + btSpinlock (SpinVariable* var) + : spinVariable (var) + {} + + void Init () + { + } + + void Lock () + { + } + + void Unlock () + { + } + +private: + SpinVariable* spinVariable; +}; + + +#endif + + +#endif //BT_SPU_SYNC_H + diff --git a/Code/Physics/src/BulletMultiThreaded/TrbDynBody.h b/Code/Physics/src/BulletMultiThreaded/TrbDynBody.h new file mode 100644 index 00000000..a7f4bf1b --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/TrbDynBody.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_RB_DYN_BODY_H__ +#define BT_RB_DYN_BODY_H__ + +#include "vectormath/vmInclude.h" +using namespace Vectormath::Aos; + +#include "TrbStateVec.h" + +class CollObject; + +class TrbDynBody +{ +public: + TrbDynBody() + { + fMass = 0.0f; + fCollObject = NULL; + fElasticity = 0.2f; + fFriction = 0.8f; + } + + // Get methods + float getMass() const {return fMass;}; + float getElasticity() const {return fElasticity;} + float getFriction() const {return fFriction;} + CollObject* getCollObject() const {return fCollObject;} + const Matrix3 &getBodyInertia() const {return fIBody;} + const Matrix3 &getBodyInertiaInv() const {return fIBodyInv;} + float getMassInv() const {return fMassInv;} + + // Set methods + void setMass(float mass) {fMass=mass;fMassInv=mass>0.0f?1.0f/mass:0.0f;} + void setBodyInertia(const Matrix3 bodyInertia) {fIBody = bodyInertia;fIBodyInv = inverse(bodyInertia);} + void setElasticity(float elasticity) {fElasticity = elasticity;} + void setFriction(float friction) {fFriction = friction;} + void setCollObject(CollObject *collObj) {fCollObject = collObj;} + + void setBodyInertiaInv(const Matrix3 bodyInertiaInv) + { + fIBody = inverse(bodyInertiaInv); + fIBodyInv = bodyInertiaInv; + } + void setMassInv(float invMass) { + fMass= invMass>0.0f ? 1.0f/invMass :0.0f; + fMassInv=invMass; + } + + +private: + // Rigid Body constants + float fMass; // Rigid Body mass + float fMassInv; // Inverse of mass + Matrix3 fIBody; // Inertia matrix in body's coords + Matrix3 fIBodyInv; // Inertia matrix inverse in body's coords + float fElasticity; // Coefficient of restitution + float fFriction; // Coefficient of friction + +public: + CollObject* fCollObject; // Collision object corresponding the RB +} __attribute__ ((aligned(16))); + +#endif //BT_RB_DYN_BODY_H__ + diff --git a/Code/Physics/src/BulletMultiThreaded/TrbStateVec.h b/Code/Physics/src/BulletMultiThreaded/TrbStateVec.h new file mode 100644 index 00000000..b6d895e1 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/TrbStateVec.h @@ -0,0 +1,339 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef BT_TRBSTATEVEC_H__ +#define BT_TRBSTATEVEC_H__ + +#include +#ifdef PFX_USE_FREE_VECTORMATH +#include "vecmath/vmInclude.h" +#else +#include "vectormath/vmInclude.h" +#endif //PFX_USE_FREE_VECTORMATH + + +#include "PlatformDefinitions.h" + + +static inline vmVector3 read_Vector3(const float* p) +{ + vmVector3 v; + loadXYZ(v, p); + return v; +} + +static inline vmQuat read_Quat(const float* p) +{ + vmQuat vq; + loadXYZW(vq, p); + return vq; +} + +static inline void store_Vector3(const vmVector3 &src, float* p) +{ + vmVector3 v = src; + storeXYZ(v, p); +} + +static inline void store_Quat(const vmQuat &src, float* p) +{ + vmQuat vq = src; + storeXYZW(vq, p); +} + +// Motion Type +enum { + PfxMotionTypeFixed = 0, + PfxMotionTypeActive, + PfxMotionTypeKeyframe, + PfxMotionTypeOneWay, + PfxMotionTypeTrigger, + PfxMotionTypeCount +}; + +#define PFX_MOTION_MASK_DYNAMIC 0x0a // Active,OneWay +#define PFX_MOTION_MASK_STATIC 0x95 // Fixed,Keyframe,Trigger,Sleeping +#define PFX_MOTION_MASK_SLEEP 0x0e // Can sleep +#define PFX_MOTION_MASK_TYPE 0x7f + +// +// Rigid Body state +// + +#ifdef __CELLOS_LV2__ +ATTRIBUTE_ALIGNED128(class) TrbState +#else +ATTRIBUTE_ALIGNED16(class) TrbState +#endif + +{ +public: + TrbState() + { + setMotionType(PfxMotionTypeActive); + contactFilterSelf=contactFilterTarget=0xffffffff; + deleted = 0; + mSleeping = 0; + useSleep = 1; + trbBodyIdx=0; + mSleepCount=0; + useCcd = 0; + useContactCallback = 0; + useSleepCallback = 0; + linearDamping = 1.0f; + angularDamping = 0.99f; + } + + TrbState(const uint8_t m, const vmVector3& x, const vmQuat& q, const vmVector3& v, const vmVector3& omega ); + + uint16_t mSleepCount; + uint8_t mMotionType; + uint8_t deleted : 1; + uint8_t mSleeping : 1; + uint8_t useSleep : 1; + uint8_t useCcd : 1; + uint8_t useContactCallback : 1; + uint8_t useSleepCallback : 1; + + uint16_t trbBodyIdx; + uint32_t contactFilterSelf; + uint32_t contactFilterTarget; + + float center[3]; // AABB center(World) + float half[3]; // AABB half(World) + + float linearDamping; + float angularDamping; + + float deltaLinearVelocity[3]; + float deltaAngularVelocity[3]; + + float fX[3]; // position + float fQ[4]; // orientation + float fV[3]; // velocity + float fOmega[3]; // angular velocity + + inline void setZero(); // Zeroes out the elements + inline void setIdentity(); // Sets the rotation to identity and zeroes out the other elements + + bool isDeleted() const {return deleted==1;} + + uint16_t getRigidBodyId() const {return trbBodyIdx;} + void setRigidBodyId(uint16_t i) {trbBodyIdx = i;} + + + uint32_t getContactFilterSelf() const {return contactFilterSelf;} + void setContactFilterSelf(uint32_t filter) {contactFilterSelf = filter;} + + uint32_t getContactFilterTarget() const {return contactFilterTarget;} + void setContactFilterTarget(uint32_t filter) {contactFilterTarget = filter;} + + float getLinearDamping() const {return linearDamping;} + float getAngularDamping() const {return angularDamping;} + + void setLinearDamping(float damping) {linearDamping=damping;} + void setAngularDamping(float damping) {angularDamping=damping;} + + + uint8_t getMotionType() const {return mMotionType;} + void setMotionType(uint8_t t) {mMotionType = t;mSleeping=0;mSleepCount=0;} + + uint8_t getMotionMask() const {return (1< + +#include "SpuCollisionTaskProcess.h" + +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + + + +///The number of threads should be equal to the number of available cores +///@todo: each worker should be linked to a single core, using SetThreadIdealProcessor. + +///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +///Setup and initialize SPU/CELL/Libspe2 +Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo) +{ + m_maxNumTasks = threadConstructionInfo.m_numThreads; + startThreads(threadConstructionInfo); +} + +///cleanup/shutdown Libspe2 +Win32ThreadSupport::~Win32ThreadSupport() +{ + stopSPU(); +} + + + + +#include + +DWORD WINAPI Thread_no_1( LPVOID lpParam ) +{ + + Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam; + + + while (1) + { + WaitForSingleObject(status->m_eventStartHandle,INFINITE); + + void* userPtr = status->m_userPtr; + + if (userPtr) + { + btAssert(status->m_status); + status->m_userThreadFunc(userPtr,status->m_lsMemory); + status->m_status = 2; + SetEvent(status->m_eventCompletetHandle); + } else + { + //exit Thread + status->m_status = 3; + printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle); + SetEvent(status->m_eventCompletetHandle); + break; + } + + } + + printf("Thread TERMINATED\n"); + return 0; + +} + +///send messages to SPUs +void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) +{ + /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc); + + ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished + + + + switch (uiCommand) + { + case CMD_GATHER_AND_PROCESS_PAIRLIST: + { + + +//#define SINGLE_THREADED 1 +#ifdef SINGLE_THREADED + + btSpuStatus& spuStatus = m_activeSpuStatus[0]; + spuStatus.m_userPtr=(void*)uiArgument0; + spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); + HANDLE handle =0; +#else + + + btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; + btAssert(taskId>=0); + btAssert(int(taskId) 1); + spuStatus.m_status = 0; + + ///need to find an active spu + btAssert(last>=0); + +#else + last=0; + btSpuStatus& spuStatus = m_activeSpuStatus[last]; +#endif //SINGLE_THREADED + + + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; + + +} + + +///check for messages from SPUs +bool Win32ThreadSupport::isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds) +{ + ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response + + ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' + + + btAssert(m_activeSpuStatus.size()); + + int last = -1; +#ifndef SINGLE_THREADED + DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, timeOutInMilliseconds); + + if ((res != STATUS_TIMEOUT) && (res != WAIT_FAILED)) + { + + btAssert(res != WAIT_FAILED); + last = res - WAIT_OBJECT_0; + + btSpuStatus& spuStatus = m_activeSpuStatus[last]; + btAssert(spuStatus.m_threadHandle); + btAssert(spuStatus.m_eventCompletetHandle); + + //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); + btAssert(spuStatus.m_status > 1); + spuStatus.m_status = 0; + + ///need to find an active spu + btAssert(last>=0); + + #else + last=0; + btSpuStatus& spuStatus = m_activeSpuStatus[last]; + #endif //SINGLE_THREADED + + + + *puiArgument0 = spuStatus.m_taskId; + *puiArgument1 = spuStatus.m_status; + + return true; + } + + return false; +} + + +void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo) +{ + + m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); + m_completeHandles.resize(threadConstructionInfo.m_numThreads); + + m_maxNumTasks = threadConstructionInfo.m_numThreads; + + for (int i=0;i0) + { + WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); + } + + + spuStatus.m_userPtr = 0; + SetEvent(spuStatus.m_eventStartHandle); + WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); + + CloseHandle(spuStatus.m_eventCompletetHandle); + CloseHandle(spuStatus.m_eventStartHandle); + CloseHandle(spuStatus.m_threadHandle); + + } + + m_activeSpuStatus.clear(); + m_completeHandles.clear(); + +} + + + +class btWin32Barrier : public btBarrier +{ +private: + CRITICAL_SECTION mExternalCriticalSection; + CRITICAL_SECTION mLocalCriticalSection; + HANDLE mRunEvent,mNotifyEvent; + int mCounter,mEnableCounter; + int mMaxCount; + +public: + btWin32Barrier() + { + mCounter = 0; + mMaxCount = 1; + mEnableCounter = 0; + InitializeCriticalSection(&mExternalCriticalSection); + InitializeCriticalSection(&mLocalCriticalSection); + mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + } + + virtual ~btWin32Barrier() + { + DeleteCriticalSection(&mExternalCriticalSection); + DeleteCriticalSection(&mLocalCriticalSection); + CloseHandle(mRunEvent); + CloseHandle(mNotifyEvent); + } + + void sync() + { + int eventId; + + EnterCriticalSection(&mExternalCriticalSection); + + //PFX_PRINTF("enter taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); + + if(mEnableCounter > 0) { + ResetEvent(mNotifyEvent); + LeaveCriticalSection(&mExternalCriticalSection); + WaitForSingleObject(mNotifyEvent,INFINITE); + EnterCriticalSection(&mExternalCriticalSection); + } + + eventId = mCounter; + mCounter++; + + if(eventId == mMaxCount-1) { + SetEvent(mRunEvent); + + mEnableCounter = mCounter-1; + mCounter = 0; + } + else { + ResetEvent(mRunEvent); + LeaveCriticalSection(&mExternalCriticalSection); + WaitForSingleObject(mRunEvent,INFINITE); + EnterCriticalSection(&mExternalCriticalSection); + mEnableCounter--; + } + + if(mEnableCounter == 0) { + SetEvent(mNotifyEvent); + } + + //PFX_PRINTF("leave taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); + + LeaveCriticalSection(&mExternalCriticalSection); + } + + virtual void setMaxCount(int n) {mMaxCount = n;} + virtual int getMaxCount() {return mMaxCount;} +}; + +class btWin32CriticalSection : public btCriticalSection +{ +private: + CRITICAL_SECTION mCriticalSection; + +public: + btWin32CriticalSection() + { + InitializeCriticalSection(&mCriticalSection); + } + + ~btWin32CriticalSection() + { + DeleteCriticalSection(&mCriticalSection); + } + + unsigned int getSharedParam(int i) + { + btAssert(i>=0&&i<31); + return mCommonBuff[i+1]; + } + + void setSharedParam(int i,unsigned int p) + { + btAssert(i>=0&&i<31); + mCommonBuff[i+1] = p; + } + + void lock() + { + EnterCriticalSection(&mCriticalSection); + mCommonBuff[0] = 1; + } + + void unlock() + { + mCommonBuff[0] = 0; + LeaveCriticalSection(&mCriticalSection); + } +}; + + +btBarrier* Win32ThreadSupport::createBarrier() +{ + unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16); + btWin32Barrier* barrier = new(mem) btWin32Barrier(); + barrier->setMaxCount(getNumTasks()); + return barrier; +} + +btCriticalSection* Win32ThreadSupport::createCriticalSection() +{ + unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16); + btWin32CriticalSection* cs = new(mem) btWin32CriticalSection(); + return cs; +} + +void Win32ThreadSupport::deleteBarrier(btBarrier* barrier) +{ + barrier->~btBarrier(); + btAlignedFree(barrier); +} + +void Win32ThreadSupport::deleteCriticalSection(btCriticalSection* criticalSection) +{ + criticalSection->~btCriticalSection(); + btAlignedFree(criticalSection); +} + + +#endif //USE_WIN32_THREADING + + diff --git a/Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.h b/Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.h new file mode 100644 index 00000000..f688e6c8 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.h @@ -0,0 +1,141 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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/btScalar.h" +#include "PlatformDefinitions.h" + +#ifdef USE_WIN32_THREADING //platform specific defines are defined in PlatformDefinitions.h + +#ifndef BT_WIN32_THREAD_SUPPORT_H +#define BT_WIN32_THREAD_SUPPORT_H + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btThreadSupportInterface.h" + + +typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory); +typedef void* (*Win32lsMemorySetupFunc)(); + + +///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication +class Win32ThreadSupport : public btThreadSupportInterface +{ +public: + ///placeholder, until libspe2 support is there + struct btSpuStatus + { + uint32_t m_taskId; + uint32_t m_commandId; + uint32_t m_status; + + Win32ThreadFunc m_userThreadFunc; + void* m_userPtr; //for taskDesc etc + void* m_lsMemory; //initialized using Win32LocalStoreMemorySetupFunc + + void* m_threadHandle; //this one is calling 'Win32ThreadFunc' + + void* m_eventStartHandle; + char m_eventStartHandleName[32]; + + void* m_eventCompletetHandle; + char m_eventCompletetHandleName[32]; + + + }; +private: + + btAlignedObjectArray m_activeSpuStatus; + btAlignedObjectArray m_completeHandles; + + int m_maxNumTasks; +public: + ///Setup and initialize SPU/CELL/Libspe2 + + struct Win32ThreadConstructionInfo + { + Win32ThreadConstructionInfo(const char* uniqueName, + Win32ThreadFunc userThreadFunc, + Win32lsMemorySetupFunc lsMemoryFunc, + int numThreads=1, + int threadStackSize=65535 + ) + :m_uniqueName(uniqueName), + m_userThreadFunc(userThreadFunc), + m_lsMemoryFunc(lsMemoryFunc), + m_numThreads(numThreads), + m_threadStackSize(threadStackSize) + { + + } + + const char* m_uniqueName; + Win32ThreadFunc m_userThreadFunc; + Win32lsMemorySetupFunc m_lsMemoryFunc; + int m_numThreads; + int m_threadStackSize; + + }; + + + + Win32ThreadSupport(const Win32ThreadConstructionInfo& threadConstructionInfo); + +///cleanup/shutdown Libspe2 + virtual ~Win32ThreadSupport(); + + void startThreads(const Win32ThreadConstructionInfo& threadInfo); + + +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); + +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); + + virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds); + +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU(); + +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU(); + + virtual void setNumTasks(int numTasks) + { + m_maxNumTasks = numTasks; + } + + virtual int getNumTasks() const + { + return m_maxNumTasks; + } + + virtual void* getThreadLocalMemory(int taskId) + { + return m_activeSpuStatus[taskId].m_lsMemory; + } + virtual btBarrier* createBarrier(); + + virtual btCriticalSection* createCriticalSection(); + + virtual void deleteBarrier(btBarrier* barrier); + + virtual void deleteCriticalSection(btCriticalSection* criticalSection); +}; + +#endif //BT_WIN32_THREAD_SUPPORT_H + +#endif //USE_WIN32_THREADING diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp new file mode 100644 index 00000000..e1d0219d --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp @@ -0,0 +1,590 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +///The 3 following lines include the CPU implementation of the kernels, keep them in this order. +#include "BulletMultiThreaded/btGpuDefines.h" +#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" +#include "BulletMultiThreaded/btGpuUtilsSharedCode.h" + + + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + + + +#include "btGpuDefines.h" +#include "btGpuUtilsSharedDefs.h" + +#include "btGpu3DGridBroadphaseSharedDefs.h" + +#include "btGpu3DGridBroadphase.h" +#include //for memset + + +#include + + + +static bt3DGridBroadphaseParams s3DGridBroadphaseParams; + + + +btGpu3DGridBroadphase::btGpu3DGridBroadphase( const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) : + btSimpleBroadphase(maxSmallProxies, +// new (btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16)) btSortedOverlappingPairCache), + new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache), + m_bInitialized(false), + m_numBodies(0) +{ + _initialize(worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerBody, + maxBodiesPerCell, cellFactorAABB); +} + + + +btGpu3DGridBroadphase::btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) : + btSimpleBroadphase(maxSmallProxies, overlappingPairCache), + m_bInitialized(false), + m_numBodies(0) +{ + _initialize(worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, + maxSmallProxies, maxLargeProxies, maxPairsPerBody, + maxBodiesPerCell, cellFactorAABB); +} + + + +btGpu3DGridBroadphase::~btGpu3DGridBroadphase() +{ + //btSimpleBroadphase will free memory of btSortedOverlappingPairCache, because m_ownsPairCache + btAssert(m_bInitialized); + _finalize(); +} + + + +void btGpu3DGridBroadphase::_initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell, + btScalar cellFactorAABB) +{ + // set various paramerers + m_ownsPairCache = true; + m_params.m_gridSizeX = gridSizeX; + m_params.m_gridSizeY = gridSizeY; + m_params.m_gridSizeZ = gridSizeZ; + m_params.m_numCells = m_params.m_gridSizeX * m_params.m_gridSizeY * m_params.m_gridSizeZ; + btVector3 w_org = worldAabbMin; + m_params.m_worldOriginX = w_org.getX(); + m_params.m_worldOriginY = w_org.getY(); + m_params.m_worldOriginZ = w_org.getZ(); + btVector3 w_size = worldAabbMax - worldAabbMin; + m_params.m_cellSizeX = w_size.getX() / m_params.m_gridSizeX; + m_params.m_cellSizeY = w_size.getY() / m_params.m_gridSizeY; + m_params.m_cellSizeZ = w_size.getZ() / m_params.m_gridSizeZ; + m_maxRadius = btMin(btMin(m_params.m_cellSizeX, m_params.m_cellSizeY), m_params.m_cellSizeZ); + m_maxRadius *= btScalar(0.5f); + m_params.m_numBodies = m_numBodies; + m_params.m_maxBodiesPerCell = maxBodiesPerCell; + + m_numLargeHandles = 0; + m_maxLargeHandles = maxLargeProxies; + + m_maxPairsPerBody = maxPairsPerBody; + + m_cellFactorAABB = cellFactorAABB; + + m_LastLargeHandleIndex = -1; + + btAssert(!m_bInitialized); + // allocate host storage + m_hBodiesHash = new unsigned int[m_maxHandles * 2]; + memset(m_hBodiesHash, 0x00, m_maxHandles*2*sizeof(unsigned int)); + + m_hCellStart = new unsigned int[m_params.m_numCells]; + memset(m_hCellStart, 0x00, m_params.m_numCells * sizeof(unsigned int)); + + m_hPairBuffStartCurr = new unsigned int[m_maxHandles * 2 + 2]; + // --------------- for now, init with m_maxPairsPerBody for each body + m_hPairBuffStartCurr[0] = 0; + m_hPairBuffStartCurr[1] = 0; + for(int i = 1; i <= m_maxHandles; i++) + { + m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; + m_hPairBuffStartCurr[i * 2 + 1] = 0; + } + //---------------- + unsigned int numAABB = m_maxHandles + m_maxLargeHandles; + m_hAABB = new bt3DGrid3F1U[numAABB * 2]; // AABB Min & Max + + m_hPairBuff = new unsigned int[m_maxHandles * m_maxPairsPerBody]; + memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed? + + m_hPairScan = new unsigned int[m_maxHandles + 1]; + + m_hPairOut = new unsigned int[m_maxHandles * m_maxPairsPerBody]; + +// large proxies + + // allocate handles buffer and put all handles on free list + m_pLargeHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * m_maxLargeHandles, 16); + m_pLargeHandles = new(m_pLargeHandlesRawPtr) btSimpleBroadphaseProxy[m_maxLargeHandles]; + m_firstFreeLargeHandle = 0; + { + for (int i = m_firstFreeLargeHandle; i < m_maxLargeHandles; i++) + { + m_pLargeHandles[i].SetNextFree(i + 1); + m_pLargeHandles[i].m_uniqueId = m_maxHandles+2+i; + } + m_pLargeHandles[m_maxLargeHandles - 1].SetNextFree(0); + } + +// debug data + m_numPairsAdded = 0; + m_numOverflows = 0; + + m_bInitialized = true; +} + + + +void btGpu3DGridBroadphase::_finalize() +{ + btAssert(m_bInitialized); + delete [] m_hBodiesHash; + delete [] m_hCellStart; + delete [] m_hPairBuffStartCurr; + delete [] m_hAABB; + delete [] m_hPairBuff; + delete [] m_hPairScan; + delete [] m_hPairOut; + btAlignedFree(m_pLargeHandlesRawPtr); + m_bInitialized = false; +} + + + +void btGpu3DGridBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + if(m_numHandles <= 0) + { + BT_PROFILE("addLarge2LargePairsToCache"); + addLarge2LargePairsToCache(dispatcher); + return; + } + // update constants + setParameters(&m_params); + // prepare AABB array + prepareAABB(); + // calculate hash + calcHashAABB(); + // sort bodies based on hash + sortHash(); + // find start of each cell + findCellStart(); + // findOverlappingPairs (small/small) + findOverlappingPairs(); + // findOverlappingPairs (small/large) + findPairsLarge(); + // add pairs to CPU cache + computePairCacheChanges(); + scanOverlappingPairBuff(); + squeezeOverlappingPairBuff(); + addPairsToCache(dispatcher); + // find and add large/large pairs to CPU cache + addLarge2LargePairsToCache(dispatcher); + return; +} + + + +void btGpu3DGridBroadphase::addPairsToCache(btDispatcher* dispatcher) +{ + m_numPairsAdded = 0; + m_numPairsRemoved = 0; + for(int i = 0; i < m_numHandles; i++) + { + unsigned int num = m_hPairScan[i+1] - m_hPairScan[i]; + if(!num) + { + continue; + } + unsigned int* pInp = m_hPairOut + m_hPairScan[i]; + unsigned int index0 = m_hAABB[i * 2].uw; + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[index0]; + for(unsigned int j = 0; j < num; j++) + { + unsigned int indx1_s = pInp[j]; + unsigned int index1 = indx1_s & (~BT_3DGRID_PAIR_ANY_FLG); + btSimpleBroadphaseProxy* proxy1; + if(index1 < (unsigned int)m_maxHandles) + { + proxy1 = &m_pHandles[index1]; + } + else + { + index1 -= m_maxHandles; + btAssert((index1 >= 0) && (index1 < (unsigned int)m_maxLargeHandles)); + proxy1 = &m_pLargeHandles[index1]; + } + if(indx1_s & BT_3DGRID_PAIR_NEW_FLG) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + m_numPairsAdded++; + } + else + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + m_numPairsRemoved++; + } + } + } +} + + + +btBroadphaseProxy* btGpu3DGridBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) +{ + btBroadphaseProxy* proxy; + bool bIsLarge = isLargeProxy(aabbMin, aabbMax); + if(bIsLarge) + { + if (m_numLargeHandles >= m_maxLargeHandles) + { + ///you have to increase the cell size, so 'large' proxies become 'small' proxies (fitting a cell) + btAssert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + btAssert((aabbMin[0]<= aabbMax[0]) && (aabbMin[1]<= aabbMax[1]) && (aabbMin[2]<= aabbMax[2])); + int newHandleIndex = allocLargeHandle(); + proxy = new (&m_pLargeHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + } + else + { + proxy = btSimpleBroadphase::createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher, multiSapProxy); + } + return proxy; +} + + + +void btGpu3DGridBroadphase::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) +{ + bool bIsLarge = isLargeProxy(proxy); + if(bIsLarge) + { + + btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); + freeLargeHandle(proxy0); + m_pairCache->removeOverlappingPairsContainingProxy(proxy,dispatcher); + } + else + { + btSimpleBroadphase::destroyProxy(proxy, dispatcher); + } + return; +} + + + +void btGpu3DGridBroadphase::resetPool(btDispatcher* dispatcher) +{ + m_hPairBuffStartCurr[0] = 0; + m_hPairBuffStartCurr[1] = 0; + for(int i = 1; i <= m_maxHandles; i++) + { + m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; + m_hPairBuffStartCurr[i * 2 + 1] = 0; + } +} + + + +bool btGpu3DGridBroadphase::isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax) +{ + btVector3 diag = aabbMax - aabbMin; + + ///use the bounding sphere radius of this bounding box, to include rotation + btScalar radius = diag.length() * btScalar(0.5f); + radius *= m_cellFactorAABB; // user-defined factor + + return (radius > m_maxRadius); +} + + + +bool btGpu3DGridBroadphase::isLargeProxy(btBroadphaseProxy* proxy) +{ + return (proxy->getUid() >= (m_maxHandles+2)); +} + + + +void btGpu3DGridBroadphase::addLarge2LargePairsToCache(btDispatcher* dispatcher) +{ + int i,j; + if (m_numLargeHandles <= 0) + { + return; + } + int new_largest_index = -1; + for(i = 0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + for(j = i + 1; j <= m_LastLargeHandleIndex; j++) + { + btSimpleBroadphaseProxy* proxy1 = &m_pLargeHandles[j]; + if(!proxy1->m_clientObject) + { + continue; + } + btAssert(proxy0 != proxy1); + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + if(aabbOverlap(p0,p1)) + { + if (!m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } + else + { + if(m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } + } + } + m_LastLargeHandleIndex = new_largest_index; + return; +} + + + +void btGpu3DGridBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) +{ + btSimpleBroadphase::rayTest(rayFrom, rayTo, rayCallback); + for (int i=0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy = &m_pLargeHandles[i]; + if(!proxy->m_clientObject) + { + continue; + } + rayCallback.process(proxy); + } +} + + + +// +// overrides for CPU version +// + + + +void btGpu3DGridBroadphase::prepareAABB() +{ + BT_PROFILE("prepareAABB"); + bt3DGrid3F1U* pBB = m_hAABB; + int i; + int new_largest_index = -1; + unsigned int num_small = 0; + for(i = 0; i <= m_LastHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + pBB->fx = proxy0->m_aabbMin.getX(); + pBB->fy = proxy0->m_aabbMin.getY(); + pBB->fz = proxy0->m_aabbMin.getZ(); + pBB->uw = i; + pBB++; + pBB->fx = proxy0->m_aabbMax.getX(); + pBB->fy = proxy0->m_aabbMax.getY(); + pBB->fz = proxy0->m_aabbMax.getZ(); + pBB->uw = num_small; + pBB++; + num_small++; + } + m_LastHandleIndex = new_largest_index; + new_largest_index = -1; + unsigned int num_large = 0; + for(i = 0; i <= m_LastLargeHandleIndex; i++) + { + btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; + if(!proxy0->m_clientObject) + { + continue; + } + new_largest_index = i; + pBB->fx = proxy0->m_aabbMin.getX(); + pBB->fy = proxy0->m_aabbMin.getY(); + pBB->fz = proxy0->m_aabbMin.getZ(); + pBB->uw = i + m_maxHandles; + pBB++; + pBB->fx = proxy0->m_aabbMax.getX(); + pBB->fy = proxy0->m_aabbMax.getY(); + pBB->fz = proxy0->m_aabbMax.getZ(); + pBB->uw = num_large + m_maxHandles; + pBB++; + num_large++; + } + m_LastLargeHandleIndex = new_largest_index; + // paranoid checks + btAssert(num_small == m_numHandles); + btAssert(num_large == m_numLargeHandles); + return; +} + + + +void btGpu3DGridBroadphase::setParameters(bt3DGridBroadphaseParams* hostParams) +{ + s3DGridBroadphaseParams = *hostParams; + return; +} + + + +void btGpu3DGridBroadphase::calcHashAABB() +{ + BT_PROFILE("bt3DGrid_calcHashAABB"); + btGpu_calcHashAABB(m_hAABB, m_hBodiesHash, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::sortHash() +{ + class bt3DGridHashKey + { + public: + unsigned int hash; + unsigned int index; + void quickSort(bt3DGridHashKey* pData, int lo, int hi) + { + int i=lo, j=hi; + bt3DGridHashKey x = pData[(lo+hi)/2]; + do + { + while(pData[i].hash > x.hash) i++; + while(x.hash > pData[j].hash) j--; + if(i <= j) + { + bt3DGridHashKey t = pData[i]; + pData[i] = pData[j]; + pData[j] = t; + i++; j--; + } + } while(i <= j); + if(lo < j) pData->quickSort(pData, lo, j); + if(i < hi) pData->quickSort(pData, i, hi); + } + }; + BT_PROFILE("bt3DGrid_sortHash"); + bt3DGridHashKey* pHash = (bt3DGridHashKey*)m_hBodiesHash; + pHash->quickSort(pHash, 0, m_numHandles - 1); + return; +} + + + +void btGpu3DGridBroadphase::findCellStart() +{ + BT_PROFILE("bt3DGrid_findCellStart"); + btGpu_findCellStart(m_hBodiesHash, m_hCellStart, m_numHandles, m_params.m_numCells); + return; +} + + + +void btGpu3DGridBroadphase::findOverlappingPairs() +{ + BT_PROFILE("bt3DGrid_findOverlappingPairs"); + btGpu_findOverlappingPairs(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::findPairsLarge() +{ + BT_PROFILE("bt3DGrid_findPairsLarge"); + btGpu_findPairsLarge(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles, m_numLargeHandles); + return; +} + + + +void btGpu3DGridBroadphase::computePairCacheChanges() +{ + BT_PROFILE("bt3DGrid_computePairCacheChanges"); + btGpu_computePairCacheChanges(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScan, m_hAABB, m_numHandles); + return; +} + + + +void btGpu3DGridBroadphase::scanOverlappingPairBuff() +{ + BT_PROFILE("bt3DGrid_scanOverlappingPairBuff"); + m_hPairScan[0] = 0; + for(int i = 1; i <= m_numHandles; i++) + { + unsigned int delta = m_hPairScan[i]; + m_hPairScan[i] = m_hPairScan[i-1] + delta; + } + return; +} + + + +void btGpu3DGridBroadphase::squeezeOverlappingPairBuff() +{ + BT_PROFILE("bt3DGrid_squeezeOverlappingPairBuff"); + btGpu_squeezeOverlappingPairBuff(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScan, m_hPairOut, m_hAABB, m_numHandles); + return; +} + + + +#include "btGpu3DGridBroadphaseSharedCode.h" + + diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.h b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.h new file mode 100644 index 00000000..1154a5fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.h @@ -0,0 +1,140 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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 BTGPU3DGRIDBROADPHASE_H +#define BTGPU3DGRIDBROADPHASE_H + +//---------------------------------------------------------------------------------------- + +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" + +#include "btGpu3DGridBroadphaseSharedTypes.h" + +//---------------------------------------------------------------------------------------- + +///The btGpu3DGridBroadphase uses GPU-style code compiled for CPU to compute overlapping pairs + +class btGpu3DGridBroadphase : public btSimpleBroadphase +{ +protected: + bool m_bInitialized; + unsigned int m_numBodies; + unsigned int m_numCells; + unsigned int m_maxPairsPerBody; + btScalar m_cellFactorAABB; + unsigned int m_maxBodiesPerCell; + bt3DGridBroadphaseParams m_params; + btScalar m_maxRadius; + // CPU data + unsigned int* m_hBodiesHash; + unsigned int* m_hCellStart; + unsigned int* m_hPairBuffStartCurr; + bt3DGrid3F1U* m_hAABB; + unsigned int* m_hPairBuff; + unsigned int* m_hPairScan; + unsigned int* m_hPairOut; +// large proxies + int m_numLargeHandles; + int m_maxLargeHandles; + int m_LastLargeHandleIndex; + btSimpleBroadphaseProxy* m_pLargeHandles; + void* m_pLargeHandlesRawPtr; + int m_firstFreeLargeHandle; + int allocLargeHandle() + { + btAssert(m_numLargeHandles < m_maxLargeHandles); + int freeLargeHandle = m_firstFreeLargeHandle; + m_firstFreeLargeHandle = m_pLargeHandles[freeLargeHandle].GetNextFree(); + m_numLargeHandles++; + if(freeLargeHandle > m_LastLargeHandleIndex) + { + m_LastLargeHandleIndex = freeLargeHandle; + } + return freeLargeHandle; + } + void freeLargeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy - m_pLargeHandles); + btAssert((handle >= 0) && (handle < m_maxHandles)); + if(handle == m_LastLargeHandleIndex) + { + m_LastLargeHandleIndex--; + } + proxy->SetNextFree(m_firstFreeLargeHandle); + m_firstFreeLargeHandle = handle; + proxy->m_clientObject = 0; + m_numLargeHandles--; + } + bool isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax); + bool isLargeProxy(btBroadphaseProxy* proxy); +// debug + unsigned int m_numPairsAdded; + unsigned int m_numPairsRemoved; + unsigned int m_numOverflows; +// +public: + btGpu3DGridBroadphase(const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell = 8, + btScalar cellFactorAABB = btScalar(1.0f)); + btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, + const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell = 8, + btScalar cellFactorAABB = btScalar(1.0f)); + virtual ~btGpu3DGridBroadphase(); + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); + + + virtual void resetPool(btDispatcher* dispatcher); + +protected: + void _initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, + int gridSizeX, int gridSizeY, int gridSizeZ, + int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, + int maxBodiesPerCell = 8, + btScalar cellFactorAABB = btScalar(1.0f)); + void _finalize(); + void addPairsToCache(btDispatcher* dispatcher); + void addLarge2LargePairsToCache(btDispatcher* dispatcher); + +// overrides for CPU version + virtual void setParameters(bt3DGridBroadphaseParams* hostParams); + virtual void prepareAABB(); + virtual void calcHashAABB(); + virtual void sortHash(); + virtual void findCellStart(); + virtual void findOverlappingPairs(); + virtual void findPairsLarge(); + virtual void computePairCacheChanges(); + virtual void scanOverlappingPairBuff(); + virtual void squeezeOverlappingPairBuff(); +}; + +//---------------------------------------------------------------------------------------- + +#endif //BTGPU3DGRIDBROADPHASE_H + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h new file mode 100644 index 00000000..e0afb87b --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h @@ -0,0 +1,430 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +// K E R N E L F U N C T I O N S +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +// calculate position in uniform grid +BT_GPU___device__ int3 bt3DGrid_calcGridPos(float4 p) +{ + int3 gridPos; + gridPos.x = (int)floor((p.x - BT_GPU_params.m_worldOriginX) / BT_GPU_params.m_cellSizeX); + gridPos.y = (int)floor((p.y - BT_GPU_params.m_worldOriginY) / BT_GPU_params.m_cellSizeY); + gridPos.z = (int)floor((p.z - BT_GPU_params.m_worldOriginZ) / BT_GPU_params.m_cellSizeZ); + return gridPos; +} // bt3DGrid_calcGridPos() + +//---------------------------------------------------------------------------------------- + +// calculate address in grid from position (clamping to edges) +BT_GPU___device__ uint bt3DGrid_calcGridHash(int3 gridPos) +{ + gridPos.x = BT_GPU_max(0, BT_GPU_min(gridPos.x, (int)BT_GPU_params.m_gridSizeX - 1)); + gridPos.y = BT_GPU_max(0, BT_GPU_min(gridPos.y, (int)BT_GPU_params.m_gridSizeY - 1)); + gridPos.z = BT_GPU_max(0, BT_GPU_min(gridPos.z, (int)BT_GPU_params.m_gridSizeZ - 1)); + return BT_GPU___mul24(BT_GPU___mul24(gridPos.z, BT_GPU_params.m_gridSizeY), BT_GPU_params.m_gridSizeX) + BT_GPU___mul24(gridPos.y, BT_GPU_params.m_gridSizeX) + gridPos.x; +} // bt3DGrid_calcGridHash() + +//---------------------------------------------------------------------------------------- + +// calculate grid hash value for each body using its AABB +BT_GPU___global__ void calcHashAABBD(bt3DGrid3F1U* pAABB, uint2* pHash, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index*2]; + bt3DGrid3F1U bbMax = pAABB[index*2 + 1]; + float4 pos; + pos.x = (bbMin.fx + bbMax.fx) * 0.5f; + pos.y = (bbMin.fy + bbMax.fy) * 0.5f; + pos.z = (bbMin.fz + bbMax.fz) * 0.5f; + // get address in grid + int3 gridPos = bt3DGrid_calcGridPos(pos); + uint gridHash = bt3DGrid_calcGridHash(gridPos); + // store grid hash and body index + pHash[index] = BT_GPU_make_uint2(gridHash, index); +} // calcHashAABBD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findCellStartD(uint2* pHash, uint* cellStart, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + // Load hash data into shared memory so that we can look + // at neighboring body's hash value without loading + // two hash values per thread + BT_GPU___shared__ uint sharedHash[257]; + sharedHash[BT_GPU_threadIdx.x+1] = sortedData.x; + if((index > 0) && (BT_GPU_threadIdx.x == 0)) + { + // first thread in block must load neighbor body hash + volatile uint2 prevData = pHash[index-1]; + sharedHash[0] = prevData.x; + } + BT_GPU___syncthreads(); + if((index == 0) || (sortedData.x != sharedHash[BT_GPU_threadIdx.x])) + { + cellStart[sortedData.x] = index; + } +} // findCellStartD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ uint cudaTestAABBOverlap(bt3DGrid3F1U min0, bt3DGrid3F1U max0, bt3DGrid3F1U min1, bt3DGrid3F1U max1) +{ + return (min0.fx <= max1.fx)&& (min1.fx <= max0.fx) && + (min0.fy <= max1.fy)&& (min1.fy <= max0.fy) && + (min0.fz <= max1.fz)&& (min1.fz <= max0.fz); +} // cudaTestAABBOverlap() + +//---------------------------------------------------------------------------------------- + +BT_GPU___device__ void findPairsInCell( int3 gridPos, + uint index, + uint2* pHash, + uint* pCellStart, + bt3DGrid3F1U* pAABB, + uint* pPairBuff, + uint2* pPairBuffStartCurr, + uint numBodies) +{ + if ( (gridPos.x < 0) || (gridPos.x > (int)BT_GPU_params.m_gridSizeX - 1) + || (gridPos.y < 0) || (gridPos.y > (int)BT_GPU_params.m_gridSizeY - 1) + || (gridPos.z < 0) || (gridPos.z > (int)BT_GPU_params.m_gridSizeZ - 1)) + { + return; + } + uint gridHash = bt3DGrid_calcGridHash(gridPos); + // get start of bucket for this cell + uint bucketStart = pCellStart[gridHash]; + if (bucketStart == 0xffffffff) + { + return; // cell empty + } + // iterate over bodies in this cell + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + uint handleIndex = min0.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + uint curr_max = start_curr_next.x - start - 1; + uint bucketEnd = bucketStart + BT_GPU_params.m_maxBodiesPerCell; + bucketEnd = (bucketEnd > numBodies) ? numBodies : bucketEnd; + for(uint index2 = bucketStart; index2 < bucketEnd; index2++) + { + uint2 cellData = pHash[index2]; + if (cellData.x != gridHash) + { + break; // no longer in same bucket + } + uint unsorted_indx2 = cellData.y; + if (unsorted_indx2 < unsorted_indx) // check not colliding with self + { + bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2); + bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2 + 1); + if(cudaTestAABBOverlap(min0, max0, min1, max1)) + { + uint handleIndex2 = min1.uw; + uint k; + for(k = 0; k < curr; k++) + { + uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; + break; + } + } + if(k == curr) + { + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; + curr++; + } + } + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); + return; +} // findPairsInCell() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findOverlappingPairsD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, + uint* pPairBuff, uint2* pPairBuffStartCurr, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U bbMin = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U bbMax = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + float4 pos; + pos.x = (bbMin.fx + bbMax.fx) * 0.5f; + pos.y = (bbMin.fy + bbMax.fy) * 0.5f; + pos.z = (bbMin.fz + bbMax.fz) * 0.5f; + // get address in grid + int3 gridPos = bt3DGrid_calcGridPos(pos); + // examine only neighbouring cells + for(int z=-1; z<=1; z++) { + for(int y=-1; y<=1; y++) { + for(int x=-1; x<=1; x++) { + findPairsInCell(gridPos + BT_GPU_make_int3(x, y, z), index, pHash, pCellStart, pAABB, pPairBuff, pPairBuffStartCurr, numBodies); + } + } + } +} // findOverlappingPairsD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void findPairsLargeD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, uint* pPairBuff, + uint2* pPairBuffStartCurr, uint numBodies, uint numLarge) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + uint2 sortedData = pHash[index]; + uint unsorted_indx = sortedData.y; + bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); + bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); + uint handleIndex = min0.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; + uint curr_max = start_curr_next.x - start - 1; + for(uint i = 0; i < numLarge; i++) + { + uint indx2 = numBodies + i; + bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, indx2*2); + bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, indx2*2 + 1); + if(cudaTestAABBOverlap(min0, max0, min1, max1)) + { + uint k; + uint handleIndex2 = min1.uw; + for(k = 0; k < curr; k++) + { + uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); + if(old_pair == handleIndex2) + { + pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; + break; + } + } + if(k == curr) + { + pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; + if(curr >= curr_max) + { // not a good solution, but let's avoid crash + break; + } + curr++; + } + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); + return; +} // findPairsLargeD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void computePairCacheChangesD(uint* pPairBuff, uint2* pPairBuffStartCurr, + uint* pPairScan, bt3DGrid3F1U* pAABB, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index * 2]; + uint handleIndex = bbMin.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint *pInp = pPairBuff + start; + uint num_changes = 0; + for(uint k = 0; k < curr; k++, pInp++) + { + if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) + { + num_changes++; + } + } + pPairScan[index+1] = num_changes; +} // computePairCacheChangesD() + +//---------------------------------------------------------------------------------------- + +BT_GPU___global__ void squeezeOverlappingPairBuffD(uint* pPairBuff, uint2* pPairBuffStartCurr, uint* pPairScan, + uint* pPairOut, bt3DGrid3F1U* pAABB, uint numBodies) +{ + int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; + if(index >= (int)numBodies) + { + return; + } + bt3DGrid3F1U bbMin = pAABB[index * 2]; + uint handleIndex = bbMin.uw; + uint2 start_curr = pPairBuffStartCurr[handleIndex]; + uint start = start_curr.x; + uint curr = start_curr.y; + uint* pInp = pPairBuff + start; + uint* pOut = pPairOut + pPairScan[index]; + uint* pOut2 = pInp; + uint num = 0; + for(uint k = 0; k < curr; k++, pInp++) + { + if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) + { + *pOut = *pInp; + pOut++; + } + if((*pInp) & BT_3DGRID_PAIR_ANY_FLG) + { + *pOut2 = (*pInp) & (~BT_3DGRID_PAIR_ANY_FLG); + pOut2++; + num++; + } + } + pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, num); +} // squeezeOverlappingPairBuffD() + + +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +// E N D O F K E R N E L F U N C T I O N S +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + // execute the kernel + BT_GPU_EXECKERNEL(numBlocks, numThreads, calcHashAABBD, (pAABB, (uint2*)hash, numBodies)); + // check if kernel invocation generated an error + BT_GPU_CHECK_ERROR("calcHashAABBD kernel execution failed"); +} // calcHashAABB() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findCellStart(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_SAFE_CALL(BT_GPU_Memset(cellStart, 0xffffffff, numCells*sizeof(uint))); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findCellStartD, ((uint2*)hash, (uint*)cellStart, numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: findCellStartD"); +} // findCellStart() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findOverlappingPairs(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies)) +{ +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, numBodies * 2 * sizeof(bt3DGrid3F1U))); +#endif + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findOverlappingPairsD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: bt_CudaFindOverlappingPairsD"); +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); +#endif +} // findOverlappingPairs() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(findPairsLarge(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge)) +{ +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, (numBodies+numLarge) * 2 * sizeof(bt3DGrid3F1U))); +#endif + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, findPairsLargeD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies,numLarge)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_findPairsLargeD"); +#if B_CUDA_USE_TEX + BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); +#endif +} // findPairsLarge() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(computePairCacheChanges(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, computePairCacheChangesD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,pAABB,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaComputePairCacheChangesD"); +} // computePairCacheChanges() + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(squeezeOverlappingPairBuff(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies)) +{ + int numThreads, numBlocks; + BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); + BT_GPU_EXECKERNEL(numBlocks, numThreads, squeezeOverlappingPairBuffD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,(uint*)pPairOut,pAABB,numBodies)); + BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaSqueezeOverlappingPairBuffD"); +} // btCuda_squeezeOverlappingPairBuff() + +//------------------------------------------------------------------------------------------------ + +} // extern "C" + +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h new file mode 100644 index 00000000..607bda7e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h @@ -0,0 +1,61 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +// Shared definitions for GPU-based 3D Grid collision detection broadphase + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// Keep this file free from Bullet headers +// it is included into both CUDA and CPU code +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//---------------------------------------------------------------------------------------- + +#ifndef BTGPU3DGRIDBROADPHASESHAREDDEFS_H +#define BTGPU3DGRIDBROADPHASESHAREDDEFS_H + +//---------------------------------------------------------------------------------------- + +#include "btGpu3DGridBroadphaseSharedTypes.h" + +//---------------------------------------------------------------------------------------- + +extern "C" +{ + +//---------------------------------------------------------------------------------------- + +void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies); + +void BT_GPU_PREF(findCellStart)(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells); + +void BT_GPU_PREF(findOverlappingPairs)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies); + +void BT_GPU_PREF(findPairsLarge)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge); + +void BT_GPU_PREF(computePairCacheChanges)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies); + +void BT_GPU_PREF(squeezeOverlappingPairBuff)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies); + + +//---------------------------------------------------------------------------------------- + +} // extern "C" + +//---------------------------------------------------------------------------------------- + +#endif // BTGPU3DGRIDBROADPHASESHAREDDEFS_H + diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h new file mode 100644 index 00000000..616a4009 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h @@ -0,0 +1,67 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + +//---------------------------------------------------------------------------------------- + +// Shared definitions for GPU-based 3D Grid collision detection broadphase + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// Keep this file free from Bullet headers +// it is included into both CUDA and CPU code +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +//---------------------------------------------------------------------------------------- + +#ifndef BTGPU3DGRIDBROADPHASESHAREDTYPES_H +#define BTGPU3DGRIDBROADPHASESHAREDTYPES_H + +//---------------------------------------------------------------------------------------- + +#define BT_3DGRID_PAIR_FOUND_FLG (0x40000000) +#define BT_3DGRID_PAIR_NEW_FLG (0x20000000) +#define BT_3DGRID_PAIR_ANY_FLG (BT_3DGRID_PAIR_FOUND_FLG | BT_3DGRID_PAIR_NEW_FLG) + +//---------------------------------------------------------------------------------------- + +struct bt3DGridBroadphaseParams +{ + unsigned int m_gridSizeX; + unsigned int m_gridSizeY; + unsigned int m_gridSizeZ; + unsigned int m_numCells; + float m_worldOriginX; + float m_worldOriginY; + float m_worldOriginZ; + float m_cellSizeX; + float m_cellSizeY; + float m_cellSizeZ; + unsigned int m_numBodies; + unsigned int m_maxBodiesPerCell; +}; + +//---------------------------------------------------------------------------------------- + +struct bt3DGrid3F1U +{ + float fx; + float fy; + float fz; + unsigned int uw; +}; + +//---------------------------------------------------------------------------------------- + +#endif // BTGPU3DGRIDBROADPHASESHAREDTYPES_H + diff --git a/Code/Physics/src/BulletMultiThreaded/btGpuDefines.h b/Code/Physics/src/BulletMultiThreaded/btGpuDefines.h new file mode 100644 index 00000000..f9315ab6 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btGpuDefines.h @@ -0,0 +1,211 @@ +/* +Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org +Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. + +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. +*/ + + + +// definitions for "GPU on CPU" code + + +#ifndef BT_GPU_DEFINES_H +#define BT_GPU_DEFINES_H + +typedef unsigned int uint; + +struct int2 +{ + int x, y; +}; + +struct uint2 +{ + unsigned int x, y; +}; + +struct int3 +{ + int x, y, z; +}; + +struct uint3 +{ + unsigned int x, y, z; +}; + +struct float4 +{ + float x, y, z, w; +}; + +struct float3 +{ + float x, y, z; +}; + + +#define BT_GPU___device__ inline +#define BT_GPU___devdata__ +#define BT_GPU___constant__ +#define BT_GPU_max(a, b) ((a) > (b) ? (a) : (b)) +#define BT_GPU_min(a, b) ((a) < (b) ? (a) : (b)) +#define BT_GPU_params s3DGridBroadphaseParams +#define BT_GPU___mul24(a, b) ((a)*(b)) +#define BT_GPU___global__ inline +#define BT_GPU___shared__ static +#define BT_GPU___syncthreads() +#define CUDART_PI_F SIMD_PI + +static inline uint2 bt3dGrid_make_uint2(unsigned int x, unsigned int y) +{ + uint2 t; t.x = x; t.y = y; return t; +} +#define BT_GPU_make_uint2(x, y) bt3dGrid_make_uint2(x, y) + +static inline int3 bt3dGrid_make_int3(int x, int y, int z) +{ + int3 t; t.x = x; t.y = y; t.z = z; return t; +} +#define BT_GPU_make_int3(x, y, z) bt3dGrid_make_int3(x, y, z) + +static inline float3 bt3dGrid_make_float3(float x, float y, float z) +{ + float3 t; t.x = x; t.y = y; t.z = z; return t; +} +#define BT_GPU_make_float3(x, y, z) bt3dGrid_make_float3(x, y, z) + +static inline float3 bt3dGrid_make_float34(float4 f) +{ + float3 t; t.x = f.x; t.y = f.y; t.z = f.z; return t; +} +#define BT_GPU_make_float34(f) bt3dGrid_make_float34(f) + +static inline float3 bt3dGrid_make_float31(float f) +{ + float3 t; t.x = t.y = t.z = f; return t; +} +#define BT_GPU_make_float31(x) bt3dGrid_make_float31(x) + +static inline float4 bt3dGrid_make_float42(float3 v, float f) +{ + float4 t; t.x = v.x; t.y = v.y; t.z = v.z; t.w = f; return t; +} +#define BT_GPU_make_float42(a, b) bt3dGrid_make_float42(a, b) + +static inline float4 bt3dGrid_make_float44(float a, float b, float c, float d) +{ + float4 t; t.x = a; t.y = b; t.z = c; t.w = d; return t; +} +#define BT_GPU_make_float44(a, b, c, d) bt3dGrid_make_float44(a, b, c, d) + +inline int3 operator+(int3 a, int3 b) +{ + return bt3dGrid_make_int3(a.x + b.x, a.y + b.y, a.z + b.z); +} + +inline float4 operator+(const float4& a, const float4& b) +{ + float4 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; r.w = a.w+b.w; return r; +} +inline float4 operator*(const float4& a, float fact) +{ + float4 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; r.w = a.w*fact; return r; +} +inline float4 operator*(float fact, float4& a) +{ + return (a * fact); +} +inline float4& operator*=(float4& a, float fact) +{ + a = fact * a; + return a; +} +inline float4& operator+=(float4& a, const float4& b) +{ + a = a + b; + return a; +} + +inline float3 operator+(const float3& a, const float3& b) +{ + float3 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; return r; +} +inline float3 operator-(const float3& a, const float3& b) +{ + float3 r; r.x = a.x-b.x; r.y = a.y-b.y; r.z = a.z-b.z; return r; +} +static inline float bt3dGrid_dot(float3& a, float3& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z; +} +#define BT_GPU_dot(a,b) bt3dGrid_dot(a,b) + +static inline float bt3dGrid_dot4(float4& a, float4& b) +{ + return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; +} +#define BT_GPU_dot4(a,b) bt3dGrid_dot4(a,b) + +static inline float3 bt3dGrid_cross(const float3& a, const float3& b) +{ + float3 r; r.x = a.y*b.z-a.z*b.y; r.y = -a.x*b.z+a.z*b.x; r.z = a.x*b.y-a.y*b.x; return r; +} +#define BT_GPU_cross(a,b) bt3dGrid_cross(a,b) + + +inline float3 operator*(const float3& a, float fact) +{ + float3 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; return r; +} + + +inline float3& operator+=(float3& a, const float3& b) +{ + a = a + b; + return a; +} +inline float3& operator-=(float3& a, const float3& b) +{ + a = a - b; + return a; +} +inline float3& operator*=(float3& a, float fact) +{ + a = a * fact; + return a; +} +inline float3 operator-(const float3& v) +{ + float3 r; r.x = -v.x; r.y = -v.y; r.z = -v.z; return r; +} + + +#define BT_GPU_FETCH(a, b) a[b] +#define BT_GPU_FETCH4(a, b) a[b] +#define BT_GPU_PREF(func) btGpu_##func +#define BT_GPU_SAFE_CALL(func) func +#define BT_GPU_Memset memset +#define BT_GPU_MemcpyToSymbol(a, b, c) memcpy(&a, b, c) +#define BT_GPU_BindTexture(a, b, c, d) +#define BT_GPU_UnbindTexture(a) + +static uint2 s_blockIdx, s_blockDim, s_threadIdx; +#define BT_GPU_blockIdx s_blockIdx +#define BT_GPU_blockDim s_blockDim +#define BT_GPU_threadIdx s_threadIdx +#define BT_GPU_EXECKERNEL(numb, numt, kfunc, args) {s_blockDim.x=numt;for(int nb=0;nb c.m_upperLimit) + { + deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; + c.m_appliedImpulse = c.m_upperLimit; + } + else + { + c.m_appliedImpulse = sum; + } + + + if (body1.mMassInv) + { + btVector3 linearComponent = c.m_contactNormal1*body1.mMassInv; + body1.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse); + btVector3 tmp=c.m_angularComponentA*(btVector3(deltaImpulse,deltaImpulse,deltaImpulse)); + body1.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + + if (body2.mMassInv) + { + btVector3 linearComponent = c.m_contactNormal2*body2.mMassInv; + body2.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse); + btVector3 tmp = c.m_angularComponentB*((btVector3(deltaImpulse,deltaImpulse,deltaImpulse)));//*m_angularFactor); + body2.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ()); + } + + //body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); + //body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); + +} + + +static SIMD_FORCE_INLINE +void pfxSolveLinearConstraintRow(btConstraintRow &constraint, + vmVector3 &deltaLinearVelocityA,vmVector3 &deltaAngularVelocityA, + float massInvA,const vmMatrix3 &inertiaInvA,const vmVector3 &rA, + vmVector3 &deltaLinearVelocityB,vmVector3 &deltaAngularVelocityB, + float massInvB,const vmMatrix3 &inertiaInvB,const vmVector3 &rB) +{ + const vmVector3 normal(btReadVector3(constraint.m_normal)); + btScalar deltaImpulse = constraint.m_rhs; + vmVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); + vmVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); + deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); + btScalar oldImpulse = constraint.m_accumImpulse; + constraint.m_accumImpulse = btClamped(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); + deltaImpulse = constraint.m_accumImpulse - oldImpulse; + deltaLinearVelocityA += deltaImpulse * massInvA * normal; + deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); + deltaLinearVelocityB -= deltaImpulse * massInvB * normal; + deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); + +} + +void btSolveContactConstraint( + btConstraintRow &constraintResponse, + btConstraintRow &constraintFriction1, + btConstraintRow &constraintFriction2, + const vmVector3 &contactPointA, + const vmVector3 &contactPointB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + float friction + ) +{ + vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA); + vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB); + + pfxSolveLinearConstraintRow(constraintResponse, + solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, + solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); + + float mf = friction*fabsf(constraintResponse.m_accumImpulse); + constraintFriction1.m_lowerLimit = -mf; + constraintFriction1.m_upperLimit = mf; + constraintFriction2.m_lowerLimit = -mf; + constraintFriction2.m_upperLimit = mf; + + pfxSolveLinearConstraintRow(constraintFriction1, + solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, + solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); + + pfxSolveLinearConstraintRow(constraintFriction2, + solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, + solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); +} + + +void CustomSolveConstraintsTaskParallel( + const PfxParallelGroup *contactParallelGroup,const PfxParallelBatch *contactParallelBatches, + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + btPersistentManifold* offsetContactManifolds, + btConstraintRow* offsetContactConstraintRows, + const PfxParallelGroup *jointParallelGroup,const PfxParallelBatch *jointParallelBatches, + PfxConstraintPair *jointPairs,uint32_t numJointPairs, + btSolverConstraint* offsetSolverConstraints, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + int iteration,unsigned int taskId,unsigned int numTasks,btBarrier *barrier) +{ + + PfxSolverBody staticBody; + staticBody.mMassInv = 0.f; + staticBody.mDeltaAngularVelocity=vmVector3(0,0,0); + staticBody.mDeltaLinearVelocity =vmVector3(0,0,0); + + + for(int k=0;knumPhases;phaseId++) { + for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { + uint32_t numPairs = jointParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + if(batchId%numTasks == taskId && numPairs > 0) { + const PfxParallelBatch &batch = jointParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + for(uint32_t i=0;isync(); + } + + // Contact + for(uint32_t phaseId=0;phaseIdnumPhases;phaseId++) { + for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { + uint32_t numPairs = contactParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + if(batchId%numTasks == taskId && numPairs > 0) { + const PfxParallelBatch &batch = contactParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; + for(uint32_t i=0;isync(); + } + } +} + +void CustomPostSolverTask( + TrbState *states, + PfxSolverBody *solverBodies, + uint32_t numRigidBodies) +{ + for(uint32_t i=0;i 0.707f) { + // choose p in y-z plane + float a = n[1]*n[1] + n[2]*n[2]; + float k = 1.0f/sqrtf(a); + p[0] = 0; + p[1] = -n[2]*k; + p[2] = n[1]*k; + // set q = n x p + q[0] = a*k; + q[1] = -n[0]*p[2]; + q[2] = n[0]*p[1]; + } + else { + // choose p in x-y plane + float a = n[0]*n[0] + n[1]*n[1]; + float k = 1.0f/sqrtf(a); + p[0] = -n[1]*k; + p[1] = n[0]*k; + p[2] = 0; + // set q = n x p + q[0] = -n[2]*p[1]; + q[1] = n[2]*p[0]; + q[2] = a*k; + } +} + + + +#define PFX_CONTACT_SLOP 0.001f + +void btSetupContactConstraint( + btConstraintRow &constraintResponse, + btConstraintRow &constraintFriction1, + btConstraintRow &constraintFriction2, + float penetrationDepth, + float restitution, + float friction, + const vmVector3 &contactNormal, + const vmVector3 &contactPointA, + const vmVector3 &contactPointB, + const TrbState &stateA, + const TrbState &stateB, + PfxSolverBody &solverBodyA, + PfxSolverBody &solverBodyB, + const vmVector3& linVelA, + const vmVector3& angVelA, + const vmVector3& linVelB, + const vmVector3& angVelB, + + float separateBias, + float timeStep + ) +{ + vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA); + vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB); + + vmMatrix3 K = vmMatrix3::scale(vmVector3(solverBodyA.mMassInv + solverBodyB.mMassInv)) - + crossMatrix(rA) * solverBodyA.mInertiaInv * crossMatrix(rA) - + crossMatrix(rB) * solverBodyB.mInertiaInv * crossMatrix(rB); + + //use the velocities without the applied (gravity and external) forces for restitution computation + vmVector3 vArestitution = linVelA + cross(angVelA,rA); + vmVector3 vBrestitution = linVelB + cross(angVelB,rB); + vmVector3 vABrestitution = vArestitution-vBrestitution; + + vmVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); + vmVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); + vmVector3 vAB = vA-vB; + + + vmVector3 tangent1,tangent2; + btPlaneSpace1(contactNormal,tangent1,tangent2); + +// constraintResponse.m_accumImpulse = 0.f; +// constraintFriction1.m_accumImpulse = 0.f; +// constraintFriction2.m_accumImpulse = 0.f; + + // Contact Constraint + { + vmVector3 normal = contactNormal; + + float denom = dot(K*normal,normal); + + constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error + constraintResponse.m_rhs -= (separateBias * btMin(0.0f,penetrationDepth+PFX_CONTACT_SLOP)) / timeStep; // position error + constraintResponse.m_rhs /= denom; + constraintResponse.m_jacDiagInv = 1.0f/denom; + constraintResponse.m_lowerLimit = 0.0f; + constraintResponse.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintResponse.m_normal); + } + + // Friction Constraint 1 + { + vmVector3 normal = tangent1; + + float denom = dot(K*normal,normal); + + constraintFriction1.m_jacDiagInv = 1.0f/denom; + constraintFriction1.m_rhs = -dot(vAB,normal); + constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv; + constraintFriction1.m_lowerLimit = 0.0f; + constraintFriction1.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintFriction1.m_normal); + } + + // Friction Constraint 2 + { + vmVector3 normal = tangent2; + + float denom = dot(K*normal,normal); + + constraintFriction2.m_jacDiagInv = 1.0f/denom; + constraintFriction2.m_rhs = -dot(vAB,normal); + constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv; + constraintFriction2.m_lowerLimit = 0.0f; + constraintFriction2.m_upperLimit = SIMD_INFINITY; + btStoreVector3(normal,constraintFriction2.m_normal); + } +} + + +void CustomSetupContactConstraintsTask( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + btPersistentManifold* offsetContactManifolds, + btConstraintRow* offsetContactConstraintRows, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separateBias, + float timeStep) +{ + for(uint32_t i=0;i 1) restitution = 0.0f; + + float friction = sqrtf(solverBodyA.friction * solverBodyB.friction); + + for(int j=0;jgetInvMass()>0.f)) + { + linVelA = rbA->getLinearVelocity(); + angVelA = rbA->getAngularVelocity(); + } else + { + linVelA.setValue(0,0,0); + angVelA.setValue(0,0,0); + } + + if (rbB && (rbB->getInvMass()>0.f)) + { + linVelB = rbB->getLinearVelocity(); + angVelB = rbB->getAngularVelocity(); + } else + { + linVelB.setValue(0,0,0); + angVelB.setValue(0,0,0); + } + + + + btSetupContactConstraint( + contactConstraintRows[j*3], + contactConstraintRows[j*3+1], + contactConstraintRows[j*3+2], + cp.getDistance(), + restitution, + friction, + btReadVector3(cp.m_normalWorldOnB),//.mConstraintRow[0].m_normal), + btReadVector3(cp.m_localPointA), + btReadVector3(cp.m_localPointB), + stateA, + stateB, + solverBodyA, + solverBodyB, + (const vmVector3&)linVelA, (const vmVector3&)angVelA, + (const vmVector3&)linVelB, (const vmVector3&)angVelB, + separateBias, + timeStep + ); + } + + //contact.setCompositeFriction(friction); + } +} + + +void CustomWritebackContactConstraintsTask( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + btPersistentManifold* offsetContactManifolds, + btConstraintRow* offsetContactConstraintRows, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separateBias, + float timeStep) +{ + for(uint32_t i=0;iio); + btCriticalSection* criticalsection = io->setupContactConstraints.criticalSection; + + + //CustomCriticalSection *criticalsection = &io->m_cs; + switch(io->cmd) { + + case PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS: + CustomSolveConstraintsTaskParallel( + io->solveConstraints.contactParallelGroup, + io->solveConstraints.contactParallelBatches, + io->solveConstraints.contactPairs, + io->solveConstraints.numContactPairs, + io->solveConstraints.offsetContactManifolds, + io->solveConstraints.offsetContactConstraintRows, + + io->solveConstraints.jointParallelGroup, + io->solveConstraints.jointParallelBatches, + io->solveConstraints.jointPairs, + io->solveConstraints.numJointPairs, + io->solveConstraints.offsetSolverConstraints, + io->solveConstraints.offsetRigStates1, + io->solveConstraints.offsetSolverBodies, + io->solveConstraints.numRigidBodies, + io->solveConstraints.iteration, + + io->solveConstraints.taskId, + io->maxTasks1, + io->solveConstraints.barrier + ); + break; + + case PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER: + CustomPostSolverTask( io->postSolver.states,io->postSolver.solverBodies, io->postSolver.numRigidBodies); + break; + + + case PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS: + { + bool empty = false; + while(!empty) { + int start,batch; + + criticalsection->lock(); + + start = (int)criticalsection->getSharedParam(0); + batch = (int)criticalsection->getSharedParam(1); + + //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch); + + // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg + int nextStart = start + batch; + int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0); + int nextBatch = (rest > batch)?batch:rest; + + criticalsection->setSharedParam(0,nextStart); + criticalsection->setSharedParam(1,nextBatch); + + criticalsection->unlock(); + + if(batch > 0) { + CustomSetupContactConstraintsTask( + io->setupContactConstraints.offsetContactPairs+start,batch, + io->setupContactConstraints.offsetContactManifolds, + io->setupContactConstraints.offsetContactConstraintRows, + io->setupContactConstraints.offsetRigStates, +// io->setupContactConstraints.offsetRigBodies, + io->setupContactConstraints.offsetSolverBodies, + io->setupContactConstraints.numRigidBodies, + io->setupContactConstraints.separateBias, + io->setupContactConstraints.timeStep); + } + else { + empty = true; + } + } + } + break; + + case PFX_CONSTRAINT_SOLVER_CMD_WRITEBACK_APPLIED_IMPULSES_CONTACT_CONSTRAINTS: + { + bool empty = false; + while(!empty) { + int start,batch; + + criticalsection->lock(); + + start = (int)criticalsection->getSharedParam(0); + batch = (int)criticalsection->getSharedParam(1); + + //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch); + + // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg + int nextStart = start + batch; + int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0); + int nextBatch = (rest > batch)?batch:rest; + + criticalsection->setSharedParam(0,nextStart); + criticalsection->setSharedParam(1,nextBatch); + + criticalsection->unlock(); + + if(batch > 0) { + CustomWritebackContactConstraintsTask( + io->setupContactConstraints.offsetContactPairs+start,batch, + io->setupContactConstraints.offsetContactManifolds, + io->setupContactConstraints.offsetContactConstraintRows, + io->setupContactConstraints.offsetRigStates, +// io->setupContactConstraints.offsetRigBodies, + io->setupContactConstraints.offsetSolverBodies, + io->setupContactConstraints.numRigidBodies, + io->setupContactConstraints.separateBias, + io->setupContactConstraints.timeStep); + } + else { + empty = true; + } + } + } + break; + + default: + { + btAssert(0); + } + } + +} + + +void CustomSetupContactConstraintsNew( + PfxConstraintPair *contactPairs1,uint32_t numContactPairs, + btPersistentManifold *offsetContactManifolds, + btConstraintRow* offsetContactConstraintRows, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + float separationBias, + float timeStep, + class btThreadSupportInterface* threadSupport, + btCriticalSection* criticalSection, + btConstraintSolverIO *io , + uint8_t cmd + ) +{ + int maxTasks = threadSupport->getNumTasks(); + + int div = (int)maxTasks * 4; + int batch = ((int)numContactPairs + div - 1) / div; +#ifdef __PPU__ + BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; +#endif + if (criticalSection) + { + criticalSection->setSharedParam(0,0); + criticalSection->setSharedParam(1,btMin(batch,64)); // batched number + } else + { +#ifdef __PPU__ + spursThread->setSharedParam(0,0); + spursThread->setSharedParam(1,btMin(batch,64)); // batched number +#endif //__PPU__ + } + + for(int t=0;tgetBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + + +//#define SEQUENTIAL_SETUP +#ifdef SEQUENTIAL_SETUP + CustomSetupContactConstraintsTask(contactPairs1,numContactPairs,offsetContactManifolds,offsetRigStates,offsetSolverBodies,numRigidBodies,separationBias,timeStep); +#else + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); +#endif + + } +#ifndef SEQUENTIAL_SETUP + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); + } +#endif //SEQUENTIAL_SETUP + +} + + +void CustomSplitConstraints( + PfxConstraintPair *pairs,uint32_t numPairs, + PfxParallelGroup &group,PfxParallelBatch *batches, + uint32_t numTasks, + uint32_t numRigidBodies, + void *poolBuff, + uint32_t poolBytes + ) +{ + HeapManager pool((unsigned char*)poolBuff,poolBytes); + + // ƒXƒe[ƒgƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ + int bufSize = sizeof(uint8_t)*numRigidBodies; + bufSize = ((bufSize+127)>>7)<<7; // 128 bytes alignment + uint8_t *bodyTable = (uint8_t*)pool.allocate(bufSize,HeapManager::ALIGN128); + + // ƒyƒAƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ + uint32_t *pairTable; + size_t allocSize = sizeof(uint32_t)*((numPairs+31)/32); + pairTable = (uint32_t*)pool.allocate(allocSize); + memset(pairTable,0,allocSize); + + // –Ú•W‚Æ‚·‚镪Š„” + uint32_t targetCount = btMax(uint32_t(PFX_MIN_SOLVER_PAIRS),btMin(numPairs / (numTasks*2),uint32_t(PFX_MAX_SOLVER_PAIRS))); + uint32_t startIndex = 0; + + uint32_t phaseId; + uint32_t batchId; + uint32_t totalCount=0; + + uint32_t maxBatches = btMin(numTasks,uint32_t(PFX_MAX_SOLVER_BATCHES)); + + for(phaseId=0;phaseId>5; + uint32_t maskP = 1L << (i & 31); + + //pair is already assigned to a phase/batch + if(pairTable[idxP] & maskP) { + continue; + } + + uint32_t idxA = pfxGetRigidBodyIdA(pairs[i]); + uint32_t idxB = pfxGetRigidBodyIdB(pairs[i]); + + // —¼•û‚Æ‚àƒAƒNƒeƒBƒu‚Å‚È‚¢A‚Ü‚½‚ÍÕ“Ë“_‚ª‚O‚̃yƒA‚Í“o˜^‘ÎÛ‚©‚ç‚Í‚¸‚· + if(!pfxGetActive(pairs[i]) || pfxGetNumConstraints(pairs[i]) == 0 || + ((pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_STATIC)) ) { + if(startIndexCheck) + startIndex++; + //assign pair -> skip it because it has no constraints + pairTable[idxP] |= maskP; + totalCount++; + continue; + } + + // ˆË‘¶«‚̃`ƒFƒbƒN + if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) || + (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) { + startIndexCheck = false; + //bodies of the pair are already assigned to another batch within this phase + continue; + } + + // ˆË‘¶«”»’èƒe[ƒuƒ‹‚É“o˜^ + if(pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_DYNAMIC) + bodyTable[idxA] = batchId; + if(pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_DYNAMIC) + bodyTable[idxB] = batchId; + + if(startIndexCheck) + startIndex++; + + pairTable[idxP] |= maskP; + //add the pair 'i' to the current batch + batch.pairIndices[pairId++] = i; + pairCount++; + } + + group.numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId] = (uint16_t)pairId; + totalCount += pairCount; + } + + group.numBatches[phaseId] = batchId; + } + + group.numPhases = phaseId; + + pool.clear(); +} + + + +void CustomSolveConstraintsParallel( + PfxConstraintPair *contactPairs,uint32_t numContactPairs, + + PfxConstraintPair *jointPairs,uint32_t numJointPairs, + btPersistentManifold* offsetContactManifolds, + btConstraintRow* offsetContactConstraintRows, + btSolverConstraint* offsetSolverConstraints, + TrbState *offsetRigStates, + PfxSolverBody *offsetSolverBodies, + uint32_t numRigidBodies, + struct btConstraintSolverIO* io, + class btThreadSupportInterface* threadSupport, + int iteration, + void* poolBuf, + int poolBytes, + class btBarrier* barrier) + { + + int maxTasks = threadSupport->getNumTasks(); +// config.taskManager->setTaskEntry(PFX_SOLVER_ENTRY); + + HeapManager pool((unsigned char*)poolBuf,poolBytes); + + { + PfxParallelGroup *cgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *cbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128); + PfxParallelGroup *jgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); + PfxParallelBatch *jbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128); + + uint32_t tmpBytes = poolBytes - 2 * (sizeof(PfxParallelGroup) + sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES) + 128); + void *tmpBuff = pool.allocate(tmpBytes); + + { + BT_PROFILE("CustomSplitConstraints"); + CustomSplitConstraints(contactPairs,numContactPairs,*cgroup,cbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); + CustomSplitConstraints(jointPairs,numJointPairs,*jgroup,jbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); + } + + { + BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS"); +//#define SOLVE_SEQUENTIAL +#ifdef SOLVE_SEQUENTIAL + CustomSolveConstraintsTask( + io->solveConstraints.contactParallelGroup, + io->solveConstraints.contactParallelBatches, + io->solveConstraints.contactPairs, + io->solveConstraints.numContactPairs, + io->solveConstraints.offsetContactManifolds, + + io->solveConstraints.jointParallelGroup, + io->solveConstraints.jointParallelBatches, + io->solveConstraints.jointPairs, + io->solveConstraints.numJointPairs, + io->solveConstraints.offsetSolverConstraints, + + io->solveConstraints.offsetRigStates1, + io->solveConstraints.offsetSolverBodies, + io->solveConstraints.numRigidBodies, + io->solveConstraints.iteration,0,1,0);//arg->taskId,1,0);//,arg->maxTasks,arg->barrier); +#else + for(int t=0;tgetBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); + } + + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); + } +#endif + } + pool.clear(); + } + + { + BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER"); + int batch = ((int)numRigidBodies + maxTasks - 1) / maxTasks; + int rest = (int)numRigidBodies; + int start = 0; + + for(int t=0;t 0 ? batch : rest; + io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER; + io[t].postSolver.states = offsetRigStates + start; + io[t].postSolver.solverBodies = offsetSolverBodies + start; + io[t].postSolver.numRigidBodies = (uint32_t)num; + io[t].maxTasks1 = maxTasks; +#ifdef __PPU__ + BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; + io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress(); + io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); +#endif + +#ifdef SOLVE_SEQUENTIAL + CustomPostSolverTask( io[t].postSolver.states,io[t].postSolver.solverBodies, io[t].postSolver.numRigidBodies); +#else + threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); +#endif + rest -= num; + start += num; + } + + unsigned int arg0,arg1; + for(int t=0;twaitForResponse(&arg0,&arg1); +#endif + } + } + +} + + + +void BPE_customConstraintSolverSequentialNew(unsigned int new_num, PfxBroadphasePair *new_pairs1 , + btPersistentManifold* offsetContactManifolds, + PfxConstraintRow* offsetContactConstraintRows, + TrbState* states,int numRigidBodies, + struct PfxSolverBody* solverBodies, + PfxConstraintPair* jointPairs, unsigned int numJoints, + btSolverConstraint* offsetSolverConstraints, + float separateBias, + float timeStep, + int iteration, + btThreadSupportInterface* solverThreadSupport, + btCriticalSection* criticalSection, + struct btConstraintSolverIO* solverIO, + btBarrier* barrier + ) +{ + + { + BT_PROFILE("pfxSetupConstraints"); + + for(uint32_t i=0;i m_mystates; + btAlignedObjectArray m_mysolverbodies; + btAlignedObjectArray m_mypairs; + btAlignedObjectArray m_jointPairs; + btAlignedObjectArray m_constraintRows; + +}; + + +btConstraintSolverIO* createSolverIO(int numThreads) +{ + return new btConstraintSolverIO[numThreads]; +} + +btParallelConstraintSolver::btParallelConstraintSolver(btThreadSupportInterface* solverThreadSupport) +{ + + m_solverThreadSupport = solverThreadSupport;//createSolverThreadSupport(maxNumThreads); + m_solverIO = createSolverIO(m_solverThreadSupport->getNumTasks()); + + m_barrier = m_solverThreadSupport->createBarrier(); + m_criticalSection = m_solverThreadSupport->createCriticalSection(); + + m_memoryCache = new btParallelSolverMemoryCache(); +} + +btParallelConstraintSolver::~btParallelConstraintSolver() +{ + delete m_memoryCache; + delete m_solverIO; + m_solverThreadSupport->deleteBarrier(m_barrier); + m_solverThreadSupport->deleteCriticalSection(m_criticalSection); +} + + + +btScalar btParallelConstraintSolver::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer,btDispatcher* dispatcher) +{ + +/* int sz = sizeof(PfxSolverBody); + int sz2 = sizeof(vmVector3); + int sz3 = sizeof(vmMatrix3); + int sz4 = sizeof(vmQuat); + int sz5 = sizeof(btConstraintRow); + int sz6 = sizeof(btSolverConstraint); + int sz7 = sizeof(TrbState); +*/ + + btPersistentManifold* offsetContactManifolds= (btPersistentManifold*) dispatcher->getInternalManifoldPool()->getPoolAddress(); + + + m_memoryCache->m_mysolverbodies.resize(numRigidBodies); + m_memoryCache->m_mystates.resize(numRigidBodies); + + { + BT_PROFILE("create states and solver bodies"); + for (int i=0;isetCompanionId(i); + + PfxSolverBody& solverBody = m_memoryCache->m_mysolverbodies[i]; + btRigidBody* rb = btRigidBody::upcast(obj); + TrbState& state = m_memoryCache->m_mystates[i]; + + state.reset(); + const btQuaternion& orgOri = obj->getWorldTransform().getRotation(); + vmQuat orn(orgOri.getX(),orgOri.getY(),orgOri.getZ(),orgOri.getW()); + state.setPosition(getVmVector3(obj->getWorldTransform().getOrigin())); + state.setOrientation(orn); + state.setPosition(state.getPosition()); + state.setRigidBodyId(i); + state.setAngularDamping(0); + state.setLinearDamping(0); + + + solverBody.mOrientation = state.getOrientation(); + solverBody.mDeltaLinearVelocity = vmVector3(0.0f); + solverBody.mDeltaAngularVelocity = vmVector3(0.0f); + solverBody.friction = obj->getFriction(); + solverBody.restitution = obj->getRestitution(); + + state.resetSleepCount(); + + //if(state.getMotionMask()&PFX_MOTION_MASK_DYNAMIC) { + if (rb && (rb->getInvMass()>0.f)) + { + btVector3 angVelPlusForces = rb->getAngularVelocity()+rb->getTotalTorque()*rb->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; + btVector3 linVelPlusForces = rb->getLinearVelocity()+rb->getTotalForce()*rb->getInvMass()*infoGlobal.m_timeStep; + + state.setAngularVelocity(btReadVector3(angVelPlusForces)); + state.setLinearVelocity(btReadVector3(linVelPlusForces)); + + state.setMotionType(PfxMotionTypeActive); + vmMatrix3 ori(solverBody.mOrientation); + vmMatrix3 localInvInertia = vmMatrix3::identity(); + localInvInertia.setCol(0,vmVector3(rb->getInvInertiaDiagLocal().getX(),0,0)); + localInvInertia.setCol(1,vmVector3(0, rb->getInvInertiaDiagLocal().getY(),0)); + localInvInertia.setCol(2,vmVector3(0,0, rb->getInvInertiaDiagLocal().getZ())); + + solverBody.mMassInv = rb->getInvMass(); + solverBody.mInertiaInv = ori * localInvInertia * transpose(ori); + } else + { + state.setAngularVelocity(vmVector3(0)); + state.setLinearVelocity(vmVector3(0)); + + state.setMotionType(PfxMotionTypeFixed); + m_memoryCache->m_mysolverbodies[i].mMassInv = 0.f; + m_memoryCache->m_mysolverbodies[i].mInertiaInv = vmMatrix3(0.0f); + } + + } + } + + + + int totalPoints = 0; +#ifndef USE_C_ARRAYS + m_memoryCache->m_mypairs.resize(numManifolds); + //4 points per manifold and 3 rows per point makes 12 rows per manifold + m_memoryCache->m_constraintRows.resize(numManifolds*12); + m_memoryCache->m_jointPairs.resize(numConstraints); +#endif//USE_C_ARRAYS + + int actualNumManifolds= 0; + { + BT_PROFILE("convert manifolds"); + for (int i1=0;i1getNumContacts()>0) + { + btPersistentManifold* m = manifoldPtr[i1]; + btCollisionObject* obA = (btCollisionObject*)m->getBody0(); + btCollisionObject* obB = (btCollisionObject*)m->getBody1(); + bool obAisActive = !obA->isStaticOrKinematicObject() && obA->isActive(); + bool obBisActive = !obB->isStaticOrKinematicObject() && obB->isActive(); + + if (!obAisActive && !obBisActive) + continue; + + + //int contactId = i1;//actualNumManifolds; + + PfxBroadphasePair& pair = m_memoryCache->m_mypairs[actualNumManifolds]; + //init those + // float compFric = obA->getFriction()*obB->getFriction();//@todo + int idA = obA->getCompanionId(); + int idB = obB->getCompanionId(); + + m->m_companionIdA = idA; + m->m_companionIdB = idB; + + + // if ((mysolverbodies[idA].mMassInv!=0)&&(mysolverbodies[idB].mMassInv!=0)) + // continue; + int numPosPoints=0; + for (int p=0;pgetNumContacts();p++) + { + //btManifoldPoint& pt = m->getContactPoint(p); + //float dist = pt.getDistance(); + //if (dist<0.001) + numPosPoints++; + } + + + totalPoints+=numPosPoints; + pfxSetRigidBodyIdA(pair,idA); + pfxSetRigidBodyIdB(pair,idB); + pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); + pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); + pfxSetActive(pair,numPosPoints>0); + + pfxSetBroadphaseFlag(pair,0); + int contactId = m-offsetContactManifolds; + //likely the contact pool is not contiguous, make sure to allocate large enough contact pool + btAssert(contactId>=0); + btAssert(contactIdgetInternalManifoldPool()->getMaxCount()); + + pfxSetContactId(pair,contactId); + pfxSetNumConstraints(pair,numPosPoints);//manifoldPtr[i]->getNumContacts()); + actualNumManifolds++; + } + + } + } + + PfxConstraintPair* jointPairs=0; + jointPairs = numConstraints? &m_memoryCache->m_jointPairs[0]:0; + int actualNumJoints=0; + + + btSolverConstraint* offsetSolverConstraints = 0; + + //if (1) + { + + { + BT_PROFILE("convert constraints"); + + int totalNumRows = 0; + int i; + + m_tmpConstraintSizesPool.resize(numConstraints); + //calculate the total number of contraint rows + for (i=0;igetInfo1(&info1); + totalNumRows += info1.m_numConstraintRows; + } + m_tmpSolverNonContactConstraintPool.resize(totalNumRows); + offsetSolverConstraints =totalNumRows? &m_tmpSolverNonContactConstraintPool[0]:0; + + + ///setup the btSolverConstraints + int currentRow = 0; + + for (i=0;igetRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + + int idA = constraint->getRigidBodyA().getCompanionId(); + int idB = constraint->getRigidBodyB().getCompanionId(); + + + int j; + for ( j=0;jm_contactNormal1; + info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; + info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2; + info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; + info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + ///the size of btSolverConstraint needs be a multiple of btScalar + btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + info2.m_constraintError = ¤tConstraintRow->m_rhs; + currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; + info2.cfm = ¤tConstraintRow->m_cfm; + info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; + info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; + info2.m_numIterations = infoGlobal.m_numIterations; + constraints[i]->getInfo2(&info2); + + + + + ///finalize the constraint setup + for ( j=0;jgetRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + } + { + const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + } + + { + btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + + btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1); + sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); + sum += iMJlB.dot(solverConstraint.m_contactNormal2); + sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); + + solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + } + + + ///fix rhs + ///todo: add force/torque accelerators + { + btScalar rel_vel; + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); + + rel_vel = vel1Dotn+vel2Dotn; + + btScalar restitution = 0.f; + btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel;// * damping; + btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + solverConstraint.m_appliedImpulse = 0.f; + + } + } + + PfxConstraintPair& pair = jointPairs[actualNumJoints]; + + int numConstraintRows= info1.m_numConstraintRows; + pfxSetNumConstraints(pair,numConstraintRows); + + + + pfxSetRigidBodyIdA(pair,idA); + pfxSetRigidBodyIdB(pair,idB); + //is this needed? + if (idA>=0) + pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); + if (idB>=0) + pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); + + pfxSetActive(pair,true); + int id = currentConstraintRow-offsetSolverConstraints; + pfxSetContactId(pair,id); + actualNumJoints++; + + + } + currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows; + } + } + } + + + + float separateBias=0.1;//info.m_erp;//or m_erp2? + float timeStep=infoGlobal.m_timeStep; + int iteration=infoGlobal.m_numIterations; + + //create a pair for each constraints, copy over info etc + + + + + + { + BT_PROFILE("compute num contacts"); + int totalContacts =0; + + for (int i=0;im_mypairs[i]; + totalContacts += pfxGetNumConstraints(*pair); + } + //printf("numManifolds = %d\n",numManifolds); + //printf("totalContacts=%d\n",totalContacts); + } + + + +// printf("actualNumManifolds=%d\n",actualNumManifolds); + { + BT_PROFILE("BPE_customConstraintSolverSequentialNew"); + if (numRigidBodies>0 && (actualNumManifolds+actualNumJoints)>0) + { +// PFX_PRINTF("num points = %d\n",totalPoints); +// PFX_PRINTF("num points PFX = %d\n",total); + + + PfxConstraintRow* contactRows = actualNumManifolds? &m_memoryCache->m_constraintRows[0] : 0; + PfxBroadphasePair* actualPairs = m_memoryCache->m_mypairs.size() ? &m_memoryCache->m_mypairs[0] : 0; + BPE_customConstraintSolverSequentialNew( + actualNumManifolds, + actualPairs, + offsetContactManifolds, + contactRows, + &m_memoryCache->m_mystates[0],numRigidBodies, + &m_memoryCache->m_mysolverbodies[0], + jointPairs,actualNumJoints, + offsetSolverConstraints, + separateBias,timeStep,iteration, + m_solverThreadSupport,m_criticalSection,m_solverIO,m_barrier); + } + } + + //copy results back to bodies + { + BT_PROFILE("copy back"); + for (int i=0;im_mystates[i]; + if (rb && (rb->getInvMass()>0.f)) + { + rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ())); + rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ())); + } + } + } + + + return 0.f; +} diff --git a/Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.h b/Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.h new file mode 100644 index 00000000..b5b475a1 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.h @@ -0,0 +1,288 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +#ifndef __BT_PARALLEL_CONSTRAINT_SOLVER_H +#define __BT_PARALLEL_CONSTRAINT_SOLVER_H + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + + + +#include "LinearMath/btScalar.h" +#include "PlatformDefinitions.h" + + +#define PFX_MAX_SOLVER_PHASES 64 +#define PFX_MAX_SOLVER_BATCHES 16 +#define PFX_MAX_SOLVER_PAIRS 128 +#define PFX_MIN_SOLVER_PAIRS 16 + +#ifdef __CELLOS_LV2__ +ATTRIBUTE_ALIGNED128(struct) PfxParallelBatch { +#else +ATTRIBUTE_ALIGNED16(struct) PfxParallelBatch { +#endif + uint16_t pairIndices[PFX_MAX_SOLVER_PAIRS]; +}; + +#ifdef __CELLOS_LV2__ +ATTRIBUTE_ALIGNED128(struct) PfxParallelGroup { +#else +ATTRIBUTE_ALIGNED16(struct) PfxParallelGroup { +#endif + uint16_t numPhases; + uint16_t numBatches[PFX_MAX_SOLVER_PHASES]; + uint16_t numPairs[PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES]; +}; + + + +ATTRIBUTE_ALIGNED16(struct) PfxSortData16 { + union { + uint8_t i8data[16]; + uint16_t i16data[8]; + uint32_t i32data[4]; +#ifdef __SPU__ + vec_uint4 vdata; +#endif + }; + +#ifdef __SPU__ + void set8(int elem,uint8_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uchar16)vdata,elem);} + void set16(int elem,uint16_t data) {vdata=(vec_uint4)spu_insert(data,(vec_ushort8)vdata,elem);} + void set32(int elem,uint32_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uint4)vdata,elem);} + uint8_t get8(int elem) const {return spu_extract((vec_uchar16)vdata,elem);} + uint16_t get16(int elem) const {return spu_extract((vec_ushort8)vdata,elem);} + uint32_t get32(int elem) const {return spu_extract((vec_uint4)vdata,elem);} +#else + void set8(int elem,uint8_t data) {i8data[elem] = data;} + void set16(int elem,uint16_t data) {i16data[elem] = data;} + void set32(int elem,uint32_t data) {i32data[elem] = data;} + uint8_t get8(int elem) const {return i8data[elem];} + uint16_t get16(int elem) const {return i16data[elem];} + uint32_t get32(int elem) const {return i32data[elem];} +#endif +}; + +typedef PfxSortData16 PfxConstraintPair; + + +//J PfxBroadphasePair‚Æ‹¤’Ê + +SIMD_FORCE_INLINE void pfxSetConstraintId(PfxConstraintPair &pair,uint32_t i) {pair.set32(2,i);} +SIMD_FORCE_INLINE void pfxSetNumConstraints(PfxConstraintPair &pair,uint8_t n) {pair.set8(7,n);} + +SIMD_FORCE_INLINE uint32_t pfxGetConstraintId1(const PfxConstraintPair &pair) {return pair.get32(2);} +SIMD_FORCE_INLINE uint8_t pfxGetNumConstraints(const PfxConstraintPair &pair) {return pair.get8(7);} + +typedef PfxSortData16 PfxBroadphasePair; + +SIMD_FORCE_INLINE void pfxSetRigidBodyIdA(PfxBroadphasePair &pair,uint16_t i) {pair.set16(0,i);} +SIMD_FORCE_INLINE void pfxSetRigidBodyIdB(PfxBroadphasePair &pair,uint16_t i) {pair.set16(1,i);} +SIMD_FORCE_INLINE void pfxSetMotionMaskA(PfxBroadphasePair &pair,uint8_t i) {pair.set8(4,i);} +SIMD_FORCE_INLINE void pfxSetMotionMaskB(PfxBroadphasePair &pair,uint8_t i) {pair.set8(5,i);} +SIMD_FORCE_INLINE void pfxSetBroadphaseFlag(PfxBroadphasePair &pair,uint8_t f) {pair.set8(6,(pair.get8(6)&0xf0)|(f&0x0f));} +SIMD_FORCE_INLINE void pfxSetActive(PfxBroadphasePair &pair,bool b) {pair.set8(6,(pair.get8(6)&0x0f)|((b?1:0)<<4));} +SIMD_FORCE_INLINE void pfxSetContactId(PfxBroadphasePair &pair,uint32_t i) {pair.set32(2,i);} + +SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdA(const PfxBroadphasePair &pair) {return pair.get16(0);} +SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdB(const PfxBroadphasePair &pair) {return pair.get16(1);} +SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskA(const PfxBroadphasePair &pair) {return pair.get8(4);} +SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskB(const PfxBroadphasePair &pair) {return pair.get8(5);} +SIMD_FORCE_INLINE uint8_t pfxGetBroadphaseFlag(const PfxBroadphasePair &pair) {return pair.get8(6)&0x0f;} +SIMD_FORCE_INLINE bool pfxGetActive(const PfxBroadphasePair &pair) {return (pair.get8(6)>>4)!=0;} +SIMD_FORCE_INLINE uint32_t pfxGetContactId1(const PfxBroadphasePair &pair) {return pair.get32(2);} + + + +#if defined(__PPU__) || defined (__SPU__) +ATTRIBUTE_ALIGNED128(struct) PfxSolverBody { +#else +ATTRIBUTE_ALIGNED16(struct) PfxSolverBody { +#endif + vmVector3 mDeltaLinearVelocity; + vmVector3 mDeltaAngularVelocity; + vmMatrix3 mInertiaInv; + vmQuat mOrientation; + float mMassInv; + float friction; + float restitution; + float unused; + float unused2; + float unused3; + float unused4; + float unused5; +}; + + +#ifdef __PPU__ +#include "SpuDispatch/BulletPE2ConstraintSolverSpursSupport.h" +#endif + +static SIMD_FORCE_INLINE vmVector3 btReadVector3(const double* p) +{ + float tmp[3] = {float(p[0]),float(p[1]),float(p[2])}; + vmVector3 v; + loadXYZ(v, tmp); + return v; +} + +static SIMD_FORCE_INLINE vmQuat btReadQuat(const double* p) +{ + float tmp[4] = {float(p[0]),float(p[1]),float(p[2]),float(p[4])}; + vmQuat vq; + loadXYZW(vq, tmp); + return vq; +} + +static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, double* p) +{ + float tmp[3]; + vmVector3 v = src; + storeXYZ(v, tmp); + p[0] = tmp[0]; + p[1] = tmp[1]; + p[2] = tmp[2]; +} + + +static SIMD_FORCE_INLINE vmVector3 btReadVector3(const float* p) +{ + vmVector3 v; + loadXYZ(v, p); + return v; +} + +static SIMD_FORCE_INLINE vmQuat btReadQuat(const float* p) +{ + vmQuat vq; + loadXYZW(vq, p); + return vq; +} + +static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, float* p) +{ + vmVector3 v = src; + storeXYZ(v, p); +} + + + + +class btPersistentManifold; + +enum { + PFX_CONSTRAINT_SOLVER_CMD_SETUP_SOLVER_BODIES, + PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_WRITEBACK_APPLIED_IMPULSES_CONTACT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_SETUP_JOINT_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS, + PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER +}; + + +struct PfxSetupContactConstraintsIO { + PfxConstraintPair *offsetContactPairs; + uint32_t numContactPairs1; + btPersistentManifold* offsetContactManifolds; + btConstraintRow* offsetContactConstraintRows; + class TrbState *offsetRigStates; + struct PfxSolverBody *offsetSolverBodies; + uint32_t numRigidBodies; + float separateBias; + float timeStep; + class btCriticalSection* criticalSection; +}; + + + +struct PfxSolveConstraintsIO { + PfxParallelGroup *contactParallelGroup; + PfxParallelBatch *contactParallelBatches; + PfxConstraintPair *contactPairs; + uint32_t numContactPairs; + btPersistentManifold *offsetContactManifolds; + btConstraintRow* offsetContactConstraintRows; + PfxParallelGroup *jointParallelGroup; + PfxParallelBatch *jointParallelBatches; + PfxConstraintPair *jointPairs; + uint32_t numJointPairs; + struct btSolverConstraint* offsetSolverConstraints; + TrbState *offsetRigStates1; + PfxSolverBody *offsetSolverBodies; + uint32_t numRigidBodies; + uint32_t iteration; + + uint32_t taskId; + + class btBarrier* barrier; + +}; + +struct PfxPostSolverIO { + TrbState *states; + PfxSolverBody *solverBodies; + uint32_t numRigidBodies; +}; + +ATTRIBUTE_ALIGNED16(struct) btConstraintSolverIO { + uint8_t cmd; + union { + PfxSetupContactConstraintsIO setupContactConstraints; + PfxSolveConstraintsIO solveConstraints; + PfxPostSolverIO postSolver; + }; + + //SPU only + uint32_t barrierAddr2; + uint32_t criticalsectionAddr2; + uint32_t maxTasks1; +}; + + + + +void SolverThreadFunc(void* userPtr,void* lsMemory); +void* SolverlsMemoryFunc(); +///The btParallelConstraintSolver performs computations on constraint rows in parallel +///Using the cross-platform threading it supports Windows, Linux, Mac OSX and PlayStation 3 Cell SPUs +class btParallelConstraintSolver : public btSequentialImpulseConstraintSolver +{ + +protected: + struct btParallelSolverMemoryCache* m_memoryCache; + + class btThreadSupportInterface* m_solverThreadSupport; + + struct btConstraintSolverIO* m_solverIO; + class btBarrier* m_barrier; + class btCriticalSection* m_criticalSection; + + +public: + + btParallelConstraintSolver(class btThreadSupportInterface* solverThreadSupport); + + virtual ~btParallelConstraintSolver(); + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher); + +}; + + + +#endif //__BT_PARALLEL_CONSTRAINT_SOLVER_H \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.cpp b/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.cpp new file mode 100644 index 00000000..8192aa46 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.cpp @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 "btThreadSupportInterface.h" + +btThreadSupportInterface::~btThreadSupportInterface() +{ + +} + diff --git a/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.h b/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.h new file mode 100644 index 00000000..54f1769c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.h @@ -0,0 +1,89 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 BT_THREAD_SUPPORT_INTERFACE_H +#define BT_THREAD_SUPPORT_INTERFACE_H + + +#include //for ATTRIBUTE_ALIGNED16 +#include "PlatformDefinitions.h" +#include "PpuAddressSpace.h" + +class btBarrier { +public: + btBarrier() {} + virtual ~btBarrier() {} + + virtual void sync() = 0; + virtual void setMaxCount(int n) = 0; + virtual int getMaxCount() = 0; +}; + +class btCriticalSection { +public: + btCriticalSection() {} + virtual ~btCriticalSection() {} + + ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]); + + virtual unsigned int getSharedParam(int i) = 0; + virtual void setSharedParam(int i,unsigned int p) = 0; + + virtual void lock() = 0; + virtual void unlock() = 0; +}; + + +class btThreadSupportInterface +{ +public: + + virtual ~btThreadSupportInterface(); + +///send messages to SPUs + virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1) =0; + +///check for messages from SPUs + virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) =0; + + + ///non-blocking test if a task is completed. First implement all versions, and then enable this API + ///virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)=0; + +///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) + virtual void startSPU() =0; + +///tell the task scheduler we are done with the SPU tasks + virtual void stopSPU()=0; + + ///tell the task scheduler to use no more than numTasks tasks + virtual void setNumTasks(int numTasks)=0; + + virtual int getNumTasks() const = 0; + + virtual btBarrier* createBarrier() = 0; + + virtual btCriticalSection* createCriticalSection() = 0; + + virtual void deleteBarrier(btBarrier* barrier)=0; + + virtual void deleteCriticalSection(btCriticalSection* criticalSection)=0; + + virtual void* getThreadLocalMemory(int taskId) { return 0; } + +}; + +#endif //BT_THREAD_SUPPORT_INTERFACE_H + diff --git a/Code/Physics/src/BulletMultiThreaded/vectormath2bullet.h b/Code/Physics/src/BulletMultiThreaded/vectormath2bullet.h new file mode 100644 index 00000000..4cc72ac5 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/vectormath2bullet.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef BT_AOS_VECTORMATH_BULLET_CONVERT_H +#define BT_AOS_VECTORMATH_BULLET_CONVERT_H + +#include "PlatformDefinitions.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btMatrix3x3.h" + +inline Vectormath::Aos::Vector3 getVmVector3(const btVector3& bulletVec) +{ + return Vectormath::Aos::Vector3((float)bulletVec.getX(),(float)bulletVec.getY(),(float)bulletVec.getZ()); +} + +inline btVector3 getBtVector3(const Vectormath::Aos::Vector3& vmVec) +{ + return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ()); +} +inline btVector3 getBtVector3(const Vectormath::Aos::Point3& vmVec) +{ + return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ()); +} + +inline Vectormath::Aos::Quat getVmQuat(const btQuaternion& bulletQuat) +{ + Vectormath::Aos::Quat vmQuat((float)bulletQuat.getX(),(float)bulletQuat.getY(),(float)bulletQuat.getZ(),(float)bulletQuat.getW()); + return vmQuat; +} + +inline btQuaternion getBtQuat(const Vectormath::Aos::Quat& vmQuat) +{ + return btQuaternion (vmQuat.getX(),vmQuat.getY(),vmQuat.getZ(),vmQuat.getW()); +} + +inline Vectormath::Aos::Matrix3 getVmMatrix3(const btMatrix3x3& btMat) +{ + Vectormath::Aos::Matrix3 mat( + getVmVector3(btMat.getColumn(0)), + getVmVector3(btMat.getColumn(1)), + getVmVector3(btMat.getColumn(2))); + return mat; +} + + +#endif //BT_AOS_VECTORMATH_BULLET_CONVERT_H diff --git a/Code/Physics/src/BulletSoftBody/CMakeLists.txt b/Code/Physics/src/BulletSoftBody/CMakeLists.txt new file mode 100644 index 00000000..e66bd02d --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/CMakeLists.txt @@ -0,0 +1,67 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src + +) + +#SUBDIRS( Solvers ) + +SET(BulletSoftBody_SRCS + btSoftBody.cpp + btSoftBodyConcaveCollisionAlgorithm.cpp + btSoftBodyHelpers.cpp + btSoftBodyRigidBodyCollisionConfiguration.cpp + btSoftRigidCollisionAlgorithm.cpp + btSoftRigidDynamicsWorld.cpp + btSoftSoftCollisionAlgorithm.cpp + btDefaultSoftBodySolver.cpp + +) + +SET(BulletSoftBody_HDRS + btSoftBody.h + btSoftBodyData.h + btSoftBodyConcaveCollisionAlgorithm.h + btSoftBodyHelpers.h + btSoftBodyRigidBodyCollisionConfiguration.h + btSoftRigidCollisionAlgorithm.h + btSoftRigidDynamicsWorld.h + btSoftSoftCollisionAlgorithm.h + btSparseSDF.h + + btSoftBodySolvers.h + btDefaultSoftBodySolver.h + + btSoftBodySolverVertexBuffer.h +) + + + +ADD_LIBRARY(BulletSoftBody ${BulletSoftBody_SRCS} ${BulletSoftBody_HDRS}) +SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION}) +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBody DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS BulletSoftBody RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES PUBLIC_HEADER "${BulletSoftBody_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.cpp new file mode 100644 index 00000000..e90d24e6 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.cpp @@ -0,0 +1,151 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + +#include "btDefaultSoftBodySolver.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletSoftBody/btSoftBody.h" + + +btDefaultSoftBodySolver::btDefaultSoftBodySolver() +{ + // Initial we will clearly need to update solver constants + // For now this is global for the cloths linked with this solver - we should probably make this body specific + // for performance in future once we understand more clearly when constants need to be updated + m_updateSolverConstants = true; +} + +btDefaultSoftBodySolver::~btDefaultSoftBodySolver() +{ +} + +// In this case the data is already in the soft bodies so there is no need for us to do anything +void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove) +{ + +} + +void btDefaultSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate) +{ + m_softBodySet.copyFromArray( softBodies ); +} + +void btDefaultSoftBodySolver::updateSoftBodies( ) +{ + for ( int i=0; i < m_softBodySet.size(); i++) + { + btSoftBody* psb=(btSoftBody*)m_softBodySet[i]; + if (psb->isActive()) + { + psb->integrateMotion(); + } + } +} // updateSoftBodies + +bool btDefaultSoftBodySolver::checkInitialized() +{ + return true; +} + +void btDefaultSoftBodySolver::solveConstraints( float solverdt ) +{ + // Solve constraints for non-solver softbodies + for(int i=0; i < m_softBodySet.size(); ++i) + { + btSoftBody* psb = static_cast(m_softBodySet[i]); + if (psb->isActive()) + { + psb->solveConstraints(); + } + } +} // btDefaultSoftBodySolver::solveConstraints + + +void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer ) +{ + // Currently only support CPU output buffers + // TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer + // and use them together on a single kernel call if possible by setting up a + // per-cloth target buffer array for the copy kernel. + + if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) + { + const btAlignedObjectArray &clothVertices( softBody->m_nodes ); + int numVertices = clothVertices.size(); + + const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); + float *basePointer = cpuVertexBuffer->getBasePointer(); + + if( vertexBuffer->hasVertexPositions() ) + { + const int vertexOffset = cpuVertexBuffer->getVertexOffset(); + const int vertexStride = cpuVertexBuffer->getVertexStride(); + float *vertexPointer = basePointer + vertexOffset; + + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + btVector3 position = clothVertices[vertexIndex].m_x; + *(vertexPointer + 0) = position.getX(); + *(vertexPointer + 1) = position.getY(); + *(vertexPointer + 2) = position.getZ(); + vertexPointer += vertexStride; + } + } + if( vertexBuffer->hasNormals() ) + { + const int normalOffset = cpuVertexBuffer->getNormalOffset(); + const int normalStride = cpuVertexBuffer->getNormalStride(); + float *normalPointer = basePointer + normalOffset; + + for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) + { + btVector3 normal = clothVertices[vertexIndex].m_n; + *(normalPointer + 0) = normal.getX(); + *(normalPointer + 1) = normal.getY(); + *(normalPointer + 2) = normal.getZ(); + normalPointer += normalStride; + } + } + } +} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer + +void btDefaultSoftBodySolver::processCollision( btSoftBody* softBody, btSoftBody* otherSoftBody) +{ + softBody->defaultCollisionHandler( otherSoftBody); +} + +// For the default solver just leave the soft body to do its collision processing +void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObjectWrap ) +{ + softBody->defaultCollisionHandler( collisionObjectWrap ); +} // btDefaultSoftBodySolver::processCollision + + +void btDefaultSoftBodySolver::predictMotion( float timeStep ) +{ + for ( int i=0; i < m_softBodySet.size(); ++i) + { + btSoftBody* psb = m_softBodySet[i]; + + if (psb->isActive()) + { + psb->predictMotion(timeStep); + } + } +} + diff --git a/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.h b/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.h new file mode 100644 index 00000000..1c17ffcb --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.h @@ -0,0 +1,63 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_DEFAULT_SOLVER_H +#define BT_SOFT_BODY_DEFAULT_SOLVER_H + + +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBodySolverVertexBuffer.h" +struct btCollisionObjectWrapper; + +class btDefaultSoftBodySolver : public btSoftBodySolver +{ +protected: + /** Variable to define whether we need to update solver constants on the next iteration */ + bool m_updateSolverConstants; + + btAlignedObjectArray< btSoftBody * > m_softBodySet; + + +public: + btDefaultSoftBodySolver(); + + virtual ~btDefaultSoftBodySolver(); + + virtual SolverTypes getSolverType() const + { + return DEFAULT_SOLVER; + } + + virtual bool checkInitialized(); + + virtual void updateSoftBodies( ); + + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies,bool forceUpdate=false ); + + virtual void copyBackToSoftBodies(bool bMove = true); + + virtual void solveConstraints( float solverdt ); + + virtual void predictMotion( float solverdt ); + + virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer ); + + virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* ); + + virtual void processCollision( btSoftBody*, btSoftBody* ); + +}; + +#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftBody.cpp b/Code/Physics/src/BulletSoftBody/btSoftBody.cpp new file mode 100644 index 00000000..a0c8cca4 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBody.cpp @@ -0,0 +1,3655 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#include "btSoftBodyInternals.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBodyData.h" +#include "LinearMath/btSerializer.h" + + +// +btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) +:m_softBodySolver(0),m_worldInfo(worldInfo) +{ + /* Init */ + initDefaults(); + + /* Default material */ + Material* pm=appendMaterial(); + pm->m_kLST = 1; + pm->m_kAST = 1; + pm->m_kVST = 1; + pm->m_flags = fMaterial::Default; + + /* Nodes */ + const btScalar margin=getCollisionShape()->getMargin(); + m_nodes.resize(node_count); + for(int i=0,ni=node_count;i0?1/n.m_im:0; + n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); + n.m_material= pm; + } + updateBounds(); + +} + +btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo) +:m_worldInfo(worldInfo) +{ + initDefaults(); +} + + +void btSoftBody::initDefaults() +{ + m_internalType = CO_SOFT_BODY; + m_cfg.aeromodel = eAeroModel::V_Point; + m_cfg.kVCF = 1; + m_cfg.kDG = 0; + m_cfg.kLF = 0; + m_cfg.kDP = 0; + m_cfg.kPR = 0; + m_cfg.kVC = 0; + m_cfg.kDF = (btScalar)0.2; + m_cfg.kMT = 0; + m_cfg.kCHR = (btScalar)1.0; + m_cfg.kKHR = (btScalar)0.1; + m_cfg.kSHR = (btScalar)1.0; + m_cfg.kAHR = (btScalar)0.7; + m_cfg.kSRHR_CL = (btScalar)0.1; + m_cfg.kSKHR_CL = (btScalar)1; + m_cfg.kSSHR_CL = (btScalar)0.5; + m_cfg.kSR_SPLT_CL = (btScalar)0.5; + m_cfg.kSK_SPLT_CL = (btScalar)0.5; + m_cfg.kSS_SPLT_CL = (btScalar)0.5; + m_cfg.maxvolume = (btScalar)1; + m_cfg.timescale = 1; + m_cfg.viterations = 0; + m_cfg.piterations = 1; + m_cfg.diterations = 0; + m_cfg.citerations = 4; + m_cfg.collisions = fCollision::Default; + m_pose.m_bvolume = false; + m_pose.m_bframe = false; + m_pose.m_volume = 0; + m_pose.m_com = btVector3(0,0,0); + m_pose.m_rot.setIdentity(); + m_pose.m_scl.setIdentity(); + m_tag = 0; + m_timeacc = 0; + m_bUpdateRtCst = true; + m_bounds[0] = btVector3(0,0,0); + m_bounds[1] = btVector3(0,0,0); + m_worldTransform.setIdentity(); + setSolver(eSolverPresets::Positions); + + /* Collision shape */ + ///for now, create a collision shape internally + m_collisionShape = new btSoftBodyCollisionShape(this); + m_collisionShape->setMargin(0.25f); + + m_initialWorldTransform.setIdentity(); + + m_windVelocity = btVector3(0,0,0); + m_restLengthScale = btScalar(1.0); +} + +// +btSoftBody::~btSoftBody() +{ + //for now, delete the internal shape + delete m_collisionShape; + int i; + + releaseClusters(); + for(i=0;i0) + *pm=*m_materials[0]; + else + ZeroInitialize(*pm); + m_materials.push_back(pm); + return(pm); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + const btVector4& c, + Node* n0, + Node* n1, + Node* n2, + Node* n3) +{ + Note n; + ZeroInitialize(n); + n.m_rank = 0; + n.m_text = text; + n.m_offset = o; + n.m_coords[0] = c.x(); + n.m_coords[1] = c.y(); + n.m_coords[2] = c.z(); + n.m_coords[3] = c.w(); + n.m_nodes[0] = n0;n.m_rank+=n0?1:0; + n.m_nodes[1] = n1;n.m_rank+=n1?1:0; + n.m_nodes[2] = n2;n.m_rank+=n2?1:0; + n.m_nodes[3] = n3;n.m_rank+=n3?1:0; + m_notes.push_back(n); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Node* feature) +{ + appendNote(text,o,btVector4(1,0,0,0),feature); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Link* feature) +{ + static const btScalar w=1/(btScalar)2; + appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0], + feature->m_n[1]); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Face* feature) +{ + static const btScalar w=1/(btScalar)3; + appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0], + feature->m_n[1], + feature->m_n[2]); +} + +// +void btSoftBody::appendNode( const btVector3& x,btScalar m) +{ + if(m_nodes.capacity()==m_nodes.size()) + { + pointersToIndices(); + m_nodes.reserve(m_nodes.size()*2+1); + indicesToPointers(); + } + const btScalar margin=getCollisionShape()->getMargin(); + m_nodes.push_back(Node()); + Node& n=m_nodes[m_nodes.size()-1]; + ZeroInitialize(n); + n.m_x = x; + n.m_q = n.m_x; + n.m_im = m>0?1/m:0; + n.m_material = m_materials[0]; + n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); +} + +// +void btSoftBody::appendLink(int model,Material* mat) +{ + Link l; + if(model>=0) + l=m_links[model]; + else + { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; } + m_links.push_back(l); +} + +// +void btSoftBody::appendLink( int node0, + int node1, + Material* mat, + bool bcheckexist) +{ + appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist); +} + +// +void btSoftBody::appendLink( Node* node0, + Node* node1, + Material* mat, + bool bcheckexist) +{ + if((!bcheckexist)||(!checkLink(node0,node1))) + { + appendLink(-1,mat); + Link& l=m_links[m_links.size()-1]; + l.m_n[0] = node0; + l.m_n[1] = node1; + l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); + m_bUpdateRtCst=true; + } +} + +// +void btSoftBody::appendFace(int model,Material* mat) +{ + Face f; + if(model>=0) + { f=m_faces[model]; } + else + { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; } + m_faces.push_back(f); +} + +// +void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) +{ + if (node0==node1) + return; + if (node1==node2) + return; + if (node2==node0) + return; + + appendFace(-1,mat); + Face& f=m_faces[m_faces.size()-1]; + btAssert(node0!=node1); + btAssert(node1!=node2); + btAssert(node2!=node0); + f.m_n[0] = &m_nodes[node0]; + f.m_n[1] = &m_nodes[node1]; + f.m_n[2] = &m_nodes[node2]; + f.m_ra = AreaOf( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + m_bUpdateRtCst=true; +} + +// +void btSoftBody::appendTetra(int model,Material* mat) +{ +Tetra t; +if(model>=0) + t=m_tetras[model]; + else + { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; } +m_tetras.push_back(t); +} + +// +void btSoftBody::appendTetra(int node0, + int node1, + int node2, + int node3, + Material* mat) +{ + appendTetra(-1,mat); + Tetra& t=m_tetras[m_tetras.size()-1]; + t.m_n[0] = &m_nodes[node0]; + t.m_n[1] = &m_nodes[node1]; + t.m_n[2] = &m_nodes[node2]; + t.m_n[3] = &m_nodes[node3]; + t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x); + m_bUpdateRtCst=true; +} + +// + +void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence) +{ + btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x; + appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence); +} + +// +void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence) +{ + if (disableCollisionBetweenLinkedBodies) + { + if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size()) + { + m_collisionDisabledObjects.push_back(body); + } + } + + Anchor a; + a.m_node = &m_nodes[node]; + a.m_body = body; + a.m_local = localPivot; + a.m_node->m_battach = 1; + a.m_influence = influence; + m_anchors.push_back(a); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1) +{ + LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint(); + pj->m_bodies[0] = body0; + pj->m_bodies[1] = body1; + pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position; + pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position; + pj->m_cfm = specs.cfm; + pj->m_erp = specs.erp; + pj->m_split = specs.split; + m_joints.push_back(pj); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body) +{ + appendLinearJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) +{ + appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1) +{ + AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint(); + pj->m_bodies[0] = body0; + pj->m_bodies[1] = body1; + pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis; + pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis; + pj->m_cfm = specs.cfm; + pj->m_erp = specs.erp; + pj->m_split = specs.split; + pj->m_icontrol = specs.icontrol; + m_joints.push_back(pj); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body) +{ + appendAngularJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) +{ + appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::addForce(const btVector3& force) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_f += force; + } +} + +void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex) +{ + btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size()); + + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + //const btScalar kPR = m_cfg.kPR; + //const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_aero = as_lift || as_drag; + const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); + + Node& n = m_nodes[nodeIndex]; + + if( n.m_im>0 ) + { + btSoftBody::sMedium medium; + + EvaluateMedium(m_worldInfo, n.m_x, medium); + medium.m_velocity = windVelocity; + medium.m_density = m_worldInfo->air_density; + + /* Aerodynamics */ + if(as_vaero) + { + const btVector3 rel_v = n.m_v - medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); + const btScalar rel_v2 = rel_v.length2(); + + if(rel_v2>SIMD_EPSILON) + { + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = n.m_n; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag) + { + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * n.m_area; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node. + btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt; + btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2(); + btScalar v_len2 = n.m_v.length2(); + + if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0) + { + btScalar del_v_by_fDrag_len = del_v_by_fDrag.length(); + btScalar v_len = n.m_v.length(); + fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len); + } + + n.m_f += fDrag; + n.m_f += fLift; + } + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided) + { + if (btSoftBody::eAeroModel::V_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn = btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = n.m_area * dvn * rel_v2/2; + const btScalar c1 = c0 * medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized() * (-c1 * kDG); + ApplyClampedForce(n, force, dt); + } + } + } + } + } +} + +void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex) +{ + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; +// const btScalar kPR = m_cfg.kPR; +// const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_aero = as_lift || as_drag; + const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); + + if(as_faero) + { + btSoftBody::Face& f=m_faces[faceIndex]; + + btSoftBody::sMedium medium; + + const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; + const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; + EvaluateMedium(m_worldInfo,x,medium); + medium.m_velocity = windVelocity; + medium.m_density = m_worldInfo->air_density; + const btVector3 rel_v=v-medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); + const btScalar rel_v2=rel_v.length2(); + + if(rel_v2>SIMD_EPSILON) + { + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = f.m_normal; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag) + { + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * f.m_ra; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + fDrag /= 3; + fLift /= 3; + + for(int j=0;j<3;++j) + { + if (f.m_n[j]->m_im>0) + { + // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node. + btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt; + btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2(); + btScalar v_len2 = f.m_n[j]->m_v.length2(); + + if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0) + { + btScalar del_v_by_fDrag_len = del_v_by_fDrag.length(); + btScalar v_len = f.m_n[j]->m_v.length(); + fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len); + } + + f.m_n[j]->m_f += fDrag; + f.m_n[j]->m_f += fLift; + } + } + } + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided) + { + if (btSoftBody::eAeroModel::F_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn=btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = f.m_ra*dvn*rel_v2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + force /= 3; + for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + } + } + } + } + +} + +// +void btSoftBody::addVelocity(const btVector3& velocity) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_v = velocity; + } + } +} + + +// +void btSoftBody::addVelocity(const btVector3& velocity,int node) +{ + Node& n=m_nodes[node]; + if(n.m_im>0) + { + n.m_v += velocity; + } +} + +// +void btSoftBody::setMass(int node,btScalar mass) +{ + m_nodes[node].m_im=mass>0?1/mass:0; + m_bUpdateRtCst=true; +} + +// +btScalar btSoftBody::getMass(int node) const +{ + return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); +} + +// +btScalar btSoftBody::getTotalMass() const +{ + btScalar mass=0; + for(int i=0;im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + for(int j=0;j<3;++j) + { + f.m_n[j]->m_im+=twicearea; + } + } + for( i=0;i ranks; +ranks.resize(m_nodes.size(),0); +int i; + +for(i=0;im_im+=btFabs(t.m_rv); + ranks[int(t.m_n[j]-&m_nodes[0])]+=1; + } + } +for( i=0;i0) + { + m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im; + } + } +setTotalMass(mass,false); +} + +// +void btSoftBody::setVolumeDensity(btScalar density) +{ +btScalar volume=0; +for(int i=0;igetMargin(); + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + + for(int i=0,ni=m_nodes.size();igetMargin(); + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + + for(int i=0,ni=m_nodes.size();i0 ? + 1/(m_nodes[i].m_im*tmass) : + kmass/tmass; + } + /* Pos */ + const btVector3 com=evaluateCom(); + m_pose.m_pos.resize(m_nodes.size()); + for( i=0,ni=m_nodes.size();im_x-l.m_n[1]->m_x).length(); + l.m_c1 = l.m_rl*l.m_rl; + } +} + +// +btScalar btSoftBody::getVolume() const +{ + btScalar vol=0; + if(m_nodes.size()>0) + { + int i,ni; + + const btVector3 org=m_nodes[0].m_x; + for(i=0,ni=m_faces.size();im_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); + } + vol/=(btScalar)6; + } + return(vol); +} + +// +int btSoftBody::clusterCount() const +{ + return(m_clusters.size()); +} + +// +btVector3 btSoftBody::clusterCom(const Cluster* cluster) +{ + btVector3 com(0,0,0); + for(int i=0,ni=cluster->m_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; + } + return(com*cluster->m_imass); +} + +// +btVector3 btSoftBody::clusterCom(int cluster) const +{ + return(clusterCom(m_clusters[cluster])); +} + +// +btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) +{ + return(cluster->m_lv+btCross(cluster->m_av,rpos)); +} + +// +void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ + const btVector3 li=cluster->m_imass*impulse; + const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse); + cluster->m_vimpulses[0]+=li;cluster->m_lv+=li; + cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; + cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ + const btVector3 li=cluster->m_imass*impulse; + const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse); + cluster->m_dimpulses[0]+=li; + cluster->m_dimpulses[1]+=ai; + cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse) +{ + if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity); + if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift); +} + +// +void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse) +{ + const btVector3 ai=cluster->m_invwi*impulse; + cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; + cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse) +{ + const btVector3 ai=cluster->m_invwi*impulse; + cluster->m_dimpulses[1]+=ai; + cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse) +{ + if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity); + if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift); +} + +// +void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse) +{ + cluster->m_dimpulses[0]+=impulse*cluster->m_imass; + cluster->m_ndimpulses++; +} + +struct NodeLinks +{ + btAlignedObjectArray m_links; +}; + + + +// +int btSoftBody::generateBendingConstraints(int distance,Material* mat) +{ + int i,j; + + if(distance>1) + { + /* Build graph */ + const int n=m_nodes.size(); + const unsigned inf=(~(unsigned)0)>>1; + unsigned* adj=new unsigned[n*n]; + + +#define IDX(_x_,_y_) ((_y_)*n+(_x_)) + for(j=0;j nodeLinks; + + + /* Build node links */ + nodeLinks.resize(m_nodes.size()); + + for( i=0;isum) + { + adj[IDX(i,j)]=adj[IDX(j,i)]=sum; + } + } + + } + } + } + } else + { + ///generic Floyd's algorithm + for(int k=0;ksum) + { + adj[IDX(i,j)]=adj[IDX(j,i)]=sum; + } + } + } + } + } + + + /* Build links */ + int nlinks=0; + for(j=0;jm_leaf) m_cdbvt.remove(c->m_leaf); + c->~Cluster(); + btAlignedFree(c); + m_clusters.remove(c); +} + +// +void btSoftBody::releaseClusters() +{ + while(m_clusters.size()>0) releaseCluster(0); +} + +// +int btSoftBody::generateClusters(int k,int maxiterations) +{ + int i; + releaseClusters(); + m_clusters.resize(btMin(k,m_nodes.size())); + for(i=0;im_collide= true; + } + k=m_clusters.size(); + if(k>0) + { + /* Initialize */ + btAlignedObjectArray centers; + btVector3 cog(0,0,0); + int i; + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + cog/=(btScalar)m_nodes.size(); + centers.resize(k,cog); + /* Iterate */ + const btScalar slope=16; + bool changed; + int iterations=0; + do { + const btScalar w=2-btMin(1,iterations/slope); + changed=false; + iterations++; + int i; + + for(i=0;im_nodes.size();++j) + { + c+=m_clusters[i]->m_nodes[j]->m_x; + } + if(m_clusters[i]->m_nodes.size()) + { + c /= (btScalar)m_clusters[i]->m_nodes.size(); + c = centers[i]+(c-centers[i])*w; + changed |= ((c-centers[i]).length2()>SIMD_EPSILON); + centers[i] = c; + m_clusters[i]->m_nodes.resize(0); + } + } + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + } while(changed&&(iterations cids; + cids.resize(m_nodes.size(),-1); + for(i=0;im_nodes.size();++j) + { + cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; + } + } + for(i=0;im_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) + { + m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); + } + } + } + } + } + /* Master */ + if(m_clusters.size()>1) + { + Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); + pmaster->m_collide = false; + pmaster->m_nodes.reserve(m_nodes.size()); + for(int i=0;im_nodes.push_back(&m_nodes[i]); + m_clusters.push_back(pmaster); + btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]); + } + /* Terminate */ + for(i=0;im_nodes.size()==0) + { + releaseCluster(i--); + } + } + } else + { + //create a cluster for each tetrahedron (if tetrahedra exist) or each face + if (m_tetras.size()) + { + m_clusters.resize(m_tetras.size()); + for(i=0;im_collide= true; + } + for (i=0;im_nodes.push_back(m_tetras[i].m_n[j]); + } + } + + } else + { + m_clusters.resize(m_faces.size()); + for(i=0;im_collide= true; + } + + for(i=0;im_nodes.push_back(m_faces[i].m_n[j]); + } + } + } + } + + if (m_clusters.size()) + { + initializeClusters(); + updateClusters(); + + + //for self-collision + m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size()); + { + for (int c0=0;c0m_clusterIndex=c0; + for (int c1=0;c1m_nodes.size();i++) + { + for (int j=0;jm_nodes.size();j++) + { + if (cla->m_nodes[i] == clb->m_nodes[j]) + { + connected=true; + break; + } + } + } + m_clusterConnectivity[c0+c1*m_clusters.size()]=connected; + } + } + } + } + + return(m_clusters.size()); +} + +// +void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut) +{ + const Node* nbase = &m_nodes[0]; + int ncount = m_nodes.size(); + btSymMatrix edges(ncount,-2); + int newnodes=0; + int i,j,k,ni; + + /* Filter out */ + for(i=0;iEval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x))) + { + btSwap(m_links[i],m_links[m_links.size()-1]); + m_links.pop_back();--i; + } + } + } + /* Fill edges */ + for(i=0;i0) + { + const btVector3 x=Lerp(a.m_x,b.m_x,t); + const btVector3 v=Lerp(a.m_v,b.m_v,t); + btScalar m=0; + if(a.m_im>0) + { + if(b.m_im>0) + { + const btScalar ma=1/a.m_im; + const btScalar mb=1/b.m_im; + const btScalar mc=Lerp(ma,mb,t); + const btScalar f=(ma+mb)/(ma+mb+mc); + a.m_im=1/(ma*f); + b.m_im=1/(mb*f); + m=mc*f; + } + else + { a.m_im/=0.5f;m=1/a.m_im; } + } + else + { + if(b.m_im>0) + { b.m_im/=0.5f;m=1/b.m_im; } + else + m=0; + } + appendNode(x,m); + edges(i,j)=m_nodes.size()-1; + m_nodes[edges(i,j)].m_v=v; + ++newnodes; + } + } + } + } + nbase=&m_nodes[0]; + /* Refine links */ + for(i=0,ni=m_links.size();i0) + { + appendLink(i); + Link* pft[]={ &m_links[i], + &m_links[m_links.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[0]]; + pft[0]->m_n[1]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[1]]; + } + } + } + /* Refine faces */ + for(i=0;i0) + { + appendFace(i); + const int l=(k+1)%3; + Face* pft[]={ &m_faces[i], + &m_faces[m_faces.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[l]]; + pft[0]->m_n[1]=&m_nodes[idx[j]]; + pft[0]->m_n[2]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[k]]; + pft[1]->m_n[2]=&m_nodes[idx[l]]; + appendLink(ni,idx[l],pft[0]->m_material); + --i;break; + } + } + } + } + /* Cut */ + if(cut) + { + btAlignedObjectArray cnodes; + const int pcount=ncount; + int i; + ncount=m_nodes.size(); + cnodes.resize(ncount,0); + /* Nodes */ + for(i=0;i=pcount)||(btFabs(ifn->Eval(x))0) { m*=0.5f;m_nodes[i].m_im/=0.5f; } + appendNode(x,m); + cnodes[i]=m_nodes.size()-1; + m_nodes[cnodes[i]].m_v=v; + } + } + nbase=&m_nodes[0]; + /* Links */ + for(i=0,ni=m_links.size();iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)Eval(n[0]->m_x)Eval(n[1]->m_x)Eval(n[2]->m_x) ranks; + btAlignedObjectArray todelete; + ranks.resize(nnodes,0); + for(i=0,ni=m_links.size();i=0;--i) + { + if(!ranks[i]) todelete.push_back(i); + } + if(todelete.size()) + { + btAlignedObjectArray& map=ranks; + for(int i=0;im_v=v; + pn[1]->m_v=v; + for(i=0,ni=m_links.size();im_n[1]=pn[mtch]; + pft[1]->m_n[0]=pn[1-mtch]; + done=true; + } + } + for(i=0,ni=m_faces.size();im_n[l]=pn[mtch]; + pft[1]->m_n[k]=pn[1-mtch]; + appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + } + } + } + if(!done) + { + m_ndbvt.remove(pn[0]->m_leaf); + m_ndbvt.remove(pn[1]->m_leaf); + m_nodes.pop_back(); + m_nodes.pop_back(); + } + return(done); +} + +// +bool btSoftBody::rayTest(const btVector3& rayFrom, + const btVector3& rayTo, + sRayCast& results) +{ + if(m_faces.size()&&m_fdbvt.empty()) + initializeFaceTree(); + + results.body = this; + results.fraction = 1.f; + results.feature = eFeature::None; + results.index = -1; + + return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0); +} + +// +void btSoftBody::setSolver(eSolverPresets::_ preset) +{ + m_cfg.m_vsequence.clear(); + m_cfg.m_psequence.clear(); + m_cfg.m_dsequence.clear(); + switch(preset) + { + case eSolverPresets::Positions: + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + m_cfg.m_psequence.push_back(ePSolver::Linear); + break; + case eSolverPresets::Velocities: + m_cfg.m_vsequence.push_back(eVSolver::Linear); + + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + + m_cfg.m_dsequence.push_back(ePSolver::Linear); + break; + } +} + +// +void btSoftBody::predictMotion(btScalar dt) +{ + + int i,ni; + + /* Update */ + if(m_bUpdateRtCst) + { + m_bUpdateRtCst=false; + updateConstants(); + m_fdbvt.clear(); + if(m_cfg.collisions&fCollision::VF_SS) + { + initializeFaceTree(); + } + } + + /* Prepare */ + m_sst.sdt = dt*m_cfg.timescale; + m_sst.isdt = 1/m_sst.sdt; + m_sst.velmrg = m_sst.sdt*3; + m_sst.radmrg = getCollisionShape()->getMargin(); + m_sst.updmrg = m_sst.radmrg*(btScalar)0.25; + /* Forces */ + addVelocity(m_worldInfo->m_gravity*m_sst.sdt); + applyForces(); + /* Integrate */ + for(i=0,ni=m_nodes.size();im_maxDisplacement; + btScalar clampDeltaV = maxDisplacement/m_sst.sdt; + for (int c=0;c<3;c++) + { + if (deltaV[c]>clampDeltaV) + { + deltaV[c] = clampDeltaV; + } + if (deltaV[c]<-clampDeltaV) + { + deltaV[c]=-clampDeltaV; + } + } + } + n.m_v += deltaV; + n.m_x += n.m_v*m_sst.sdt; + n.m_f = btVector3(0,0,0); + } + /* Clusters */ + updateClusters(); + /* Bounds */ + updateBounds(); + /* Nodes */ + ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; + for(i=0,ni=m_nodes.size();im_v+ + f.m_n[1]->m_v+ + f.m_n[2]->m_v)/3; + vol = VolumeOf(f,m_sst.radmrg); + m_fdbvt.update( f.m_leaf, + vol, + v*m_sst.velmrg, + m_sst.updmrg); + } + } + /* Pose */ + updatePose(); + /* Match */ + if(m_pose.m_bframe&&(m_cfg.kMT>0)) + { + const btMatrix3x3 posetrs=m_pose.m_rot; + for(int i=0,ni=m_nodes.size();i0) + { + const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com; + n.m_x=Lerp(n.m_x,x,m_cfg.kMT); + } + } + } + /* Clear contacts */ + m_rcontacts.resize(0); + m_scontacts.resize(0); + /* Optimize dbvt's */ + m_ndbvt.optimizeIncremental(1); + m_fdbvt.optimizeIncremental(1); + m_cdbvt.optimizeIncremental(1); +} + +// +void btSoftBody::solveConstraints() +{ + + /* Apply clusters */ + applyClusters(false); + /* Prepare links */ + + int i,ni; + + for(i=0,ni=m_links.size();im_q-l.m_n[0]->m_q; + l.m_c2 = 1/(l.m_c3.length2()*l.m_c0); + } + /* Prepare anchors */ + for(i=0,ni=m_anchors.size();igetWorldTransform().getBasis()*a.m_local; + a.m_c0 = ImpulseMatrix( m_sst.sdt, + a.m_node->m_im, + a.m_body->getInvMass(), + a.m_body->getInvInertiaTensorWorld(), + ra); + a.m_c1 = ra; + a.m_c2 = m_sst.sdt*a.m_node->m_im; + a.m_body->activate(); + } + /* Solve velocities */ + if(m_cfg.viterations>0) + { + /* Solve */ + for(int isolve=0;isolve0) + { + for(int isolve=0;isolve0) + { + const btScalar vcf=m_cfg.kVCF*m_sst.isdt; + for(i=0,ni=m_nodes.size();i& bodies) +{ + const int nb=bodies.size(); + int iterations=0; + int i; + + for(i=0;im_cfg.citerations); + } + for(i=0;iprepareClusters(iterations); + } + for(i=0;isolveClusters(sor); + } + } + for(i=0;icleanupClusters(); + } +} + +// +void btSoftBody::integrateMotion() +{ + /* Update */ + updateNormals(); +} + +// +btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt) +{ + m_rayFrom = rayFrom; + m_rayNormalizedDirection = (rayTo-rayFrom); + m_rayTo = rayTo; + m_mint = mxt; + m_face = 0; + m_tests = 0; +} + +// +void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf) +{ + btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; + const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection, + f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + m_mint); + if((t>0)&&(tteps)&&(tceps) && + (btDot(n,btCross(b-hit,c-hit))>ceps) && + (btDot(n,btCross(c-hit,a-hit))>ceps)) + { + return(t); + } + } + } + return(-1); +} + +// +void btSoftBody::pointersToIndices() +{ +#define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) + btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0; + int i,ni; + + for(i=0,ni=m_nodes.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_links.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_anchors.size();idata=&m_nodes[i]; + } + } + for(i=0,ni=m_links.size();idata=&m_faces[i]; + } + } + for(i=0,ni=m_anchors.size();im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Face; + index=i; + mint=t; + } + } + } + } + else + {/* Use dbvt */ + RayFromToCaster collider(rayFrom,rayTo,mint); + + btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider); + if(collider.m_face) + { + mint=collider.m_mint; + feature=btSoftBody::eFeature::Face; + index=(int)(collider.m_face-&m_faces[0]); + cnt=1; + } + } + + for (int i=0;im_x; + btVector3 v1=tet.m_n[index1]->m_x; + btVector3 v2=tet.m_n[index2]->m_x; + + + const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir, + v0,v1,v2, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Tetra; + index=i; + mint=t; + } + } + } + } + return(cnt); +} + +// +void btSoftBody::initializeFaceTree() +{ + m_fdbvt.clear(); + for(int i=0;igetCollisionShape(); +// const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject()); + //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform(); + const btTransform &wtr = colObjWrap->getWorldTransform(); + //todo: check which transform is needed here + + btScalar dst = + m_worldInfo->m_sparsesdf.Evaluate( + wtr.invXform(x), + shp, + nrm, + margin); + if(dst<0) + { + cti.m_colObj = colObjWrap->getCollisionObject(); + cti.m_normal = wtr.getBasis()*nrm; + cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst ); + return(true); + } + return(false); +} + +// +void btSoftBody::updateNormals() +{ + + const btVector3 zv(0,0,0); + int i,ni; + + for(i=0,ni=m_nodes.size();im_x-f.m_n[0]->m_x, + f.m_n[2]->m_x-f.m_n[0]->m_x); + f.m_normal=n.normalized(); + f.m_n[0]->m_n+=n; + f.m_n[1]->m_n+=n; + f.m_n[2]->m_n+=n; + } + for(i=0,ni=m_nodes.size();iSIMD_EPSILON) + m_nodes[i].m_n /= len; + } +} + +// +void btSoftBody::updateBounds() +{ + /*if( m_acceleratedSoftBody ) + { + // If we have an accelerated softbody we need to obtain the bounds correctly + // For now (slightly hackily) just have a very large AABB + // TODO: Write get bounds kernel + // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could + // probably do a test and exchange reasonably efficiently. + + m_bounds[0] = btVector3(-1000, -1000, -1000); + m_bounds[1] = btVector3(1000, 1000, 1000); + + } else {*/ + if(m_ndbvt.m_root) + { + const btVector3& mins=m_ndbvt.m_root->volume.Mins(); + const btVector3& maxs=m_ndbvt.m_root->volume.Maxs(); + const btScalar csm=getCollisionShape()->getMargin(); + const btVector3 mrg=btVector3( csm, + csm, + csm)*1; // ??? to investigate... + m_bounds[0]=mins-mrg; + m_bounds[1]=maxs+mrg; + if(0!=getBroadphaseHandle()) + { + m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), + m_bounds[0], + m_bounds[1], + m_worldInfo->m_dispatcher); + } + } + else + { + m_bounds[0]= + m_bounds[1]=btVector3(0,0,0); + } + //} +} + + +// +void btSoftBody::updatePose() +{ + if(m_pose.m_bframe) + { + btSoftBody::Pose& pose=m_pose; + const btVector3 com=evaluateCom(); + /* Com */ + pose.m_com = com; + /* Rotation */ + btMatrix3x3 Apq; + const btScalar eps=SIMD_EPSILON; + Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); + Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); + for(int i=0,ni=m_nodes.size();i1) + { + const btScalar idet=Clamp( 1/pose.m_scl.determinant(), + 1,m_cfg.maxvolume); + pose.m_scl=Mul(pose.m_scl,idet); + } + + } +} + +// +void btSoftBody::updateArea(bool averageArea) +{ + int i,ni; + + /* Face area */ + for(i=0,ni=m_faces.size();im_x,f.m_n[1]->m_x,f.m_n[2]->m_x); + } + + /* Node area */ + + if (averageArea) + { + btAlignedObjectArray counts; + counts.resize(m_nodes.size(),0); + for(i=0,ni=m_nodes.size();im_area+=btFabs(f.m_ra); + } + } + for(i=0,ni=m_nodes.size();i0) + m_nodes[i].m_area/=(btScalar)counts[i]; + else + m_nodes[i].m_area=0; + } + } + else + { + // initialize node area as zero + for(i=0,ni=m_nodes.size();im_area += f.m_ra; + } + } + + for(i=0,ni=m_nodes.size();im_im+l.m_n[1]->m_im)/m.m_kLST; + } +} + +void btSoftBody::updateConstants() +{ + resetLinkRestLengths(); + updateLinkConstants(); + updateArea(); +} + + + +// +void btSoftBody::initializeClusters() +{ + int i; + + for( i=0;im_im==0) + { + c.m_containsAnchor = true; + c.m_masses[j] = BT_LARGE_FLOAT; + } else + { + c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im; + } + c.m_imass += c.m_masses[j]; + } + c.m_imass = btScalar(1.)/c.m_imass; + c.m_com = btSoftBody::clusterCom(&c); + c.m_lv = btVector3(0,0,0); + c.m_av = btVector3(0,0,0); + c.m_leaf = 0; + /* Inertia */ + btMatrix3x3& ii=c.m_locii; + ii[0]=ii[1]=ii[2]=btVector3(0,0,0); + { + int i,ni; + + for(i=0,ni=c.m_nodes.size();im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=c.m_masses[i]; + ii[0][0] += m*(q[1]+q[2]); + ii[1][1] += m*(q[0]+q[2]); + ii[2][2] += m*(q[0]+q[1]); + ii[0][1] -= m*k[0]*k[1]; + ii[0][2] -= m*k[0]*k[2]; + ii[1][2] -= m*k[1]*k[2]; + } + } + ii[1][0]=ii[0][1]; + ii[2][0]=ii[0][2]; + ii[2][1]=ii[1][2]; + + ii = ii.inverse(); + + /* Frame */ + c.m_framexform.setIdentity(); + c.m_framexform.setOrigin(c.m_com); + c.m_framerefs.resize(c.m_nodes.size()); + { + int i; + for(i=0;im_x-c.m_com; + } + } + } +} + +// +void btSoftBody::updateClusters() +{ + BT_PROFILE("UpdateClusters"); + int i; + + for(i=0;im_x-c.m_com; + const btVector3& b=c.m_framerefs[i]; + m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b; + } + PolarDecompose(m,r,s); + c.m_framexform.setOrigin(c.m_com); + c.m_framexform.setBasis(r); + /* Inertia */ +#if 1/* Constant */ + c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose(); +#else +#if 0/* Sphere */ + const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass); + const btVector3 inertia(rk,rk,rk); + const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0, + btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0, + btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0); + + c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose(); +#else/* Actual */ + c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0); + for(int i=0;im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=1/c.m_nodes[i]->m_im; + c.m_invwi[0][0] += m*(q[1]+q[2]); + c.m_invwi[1][1] += m*(q[0]+q[2]); + c.m_invwi[2][2] += m*(q[0]+q[1]); + c.m_invwi[0][1] -= m*k[0]*k[1]; + c.m_invwi[0][2] -= m*k[0]*k[2]; + c.m_invwi[1][2] -= m*k[1]*k[2]; + } + c.m_invwi[1][0]=c.m_invwi[0][1]; + c.m_invwi[2][0]=c.m_invwi[0][2]; + c.m_invwi[2][1]=c.m_invwi[1][2]; + c.m_invwi=c.m_invwi.inverse(); +#endif +#endif + /* Velocities */ + c.m_lv=btVector3(0,0,0); + c.m_av=btVector3(0,0,0); + { + int i; + + for(i=0;im_v*c.m_masses[i]; + c.m_lv += v; + c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v); + } + } + c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping); + c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping); + c.m_vimpulses[0] = + c.m_vimpulses[1] = btVector3(0,0,0); + c.m_dimpulses[0] = + c.m_dimpulses[1] = btVector3(0,0,0); + c.m_nvimpulses = 0; + c.m_ndimpulses = 0; + /* Matching */ + if(c.m_matching>0) + { + for(int j=0;jm_x; + btVector3 mx=mi; + for(int j=1;jm_x); + mx.setMax(c.m_nodes[j]->m_x); + } + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); + if(c.m_leaf) + m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); + else + c.m_leaf=m_cdbvt.insert(bounds,&c); + } + } + } + + +} + + + + +// +void btSoftBody::cleanupClusters() +{ + for(int i=0;iTerminate(m_sst.sdt); + if(m_joints[i]->m_delete) + { + btAlignedFree(m_joints[i]); + m_joints.remove(m_joints[i--]); + } + } +} + +// +void btSoftBody::prepareClusters(int iterations) +{ + for(int i=0;iPrepare(m_sst.sdt,iterations); + } +} + + +// +void btSoftBody::solveClusters(btScalar sor) +{ + for(int i=0,ni=m_joints.size();iSolve(m_sst.sdt,sor); + } +} + +// +void btSoftBody::applyClusters(bool drift) +{ + BT_PROFILE("ApplyClusters"); +// const btScalar f0=m_sst.sdt; + //const btScalar f1=f0/2; + btAlignedObjectArray deltas; + btAlignedObjectArray weights; + deltas.resize(m_nodes.size(),btVector3(0,0,0)); + weights.resize(m_nodes.size(),0); + int i; + + if(drift) + { + for(i=0;im_x; + const btScalar q=c.m_masses[j]; + deltas[idx] += (v+btCross(w,x-c.m_com))*q; + weights[idx] += q; + } + } + } + for(i=0;i0) + { + m_nodes[i].m_x+=deltas[i]/weights[i]; + } + } +} + +// +void btSoftBody::dampClusters() +{ + int i; + + for(i=0;i0) + { + for(int j=0;j0) + { + const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com); + if(vx.length2()<=n.m_v.length2()) + { + n.m_v += c.m_ndamping*(vx-n.m_v); + } + } + } + } + } +} + +// +void btSoftBody::Joint::Prepare(btScalar dt,int) +{ + m_bodies[0].activate(); + m_bodies[1].activate(); +} + +// +void btSoftBody::LJoint::Prepare(btScalar dt,int iterations) +{ + static const btScalar maxdrift=4; + Joint::Prepare(dt,iterations); + m_rpos[0] = m_bodies[0].xform()*m_refs[0]; + m_rpos[1] = m_bodies[1].xform()*m_refs[1]; + m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt; + m_rpos[0] -= m_bodies[0].xform().getOrigin(); + m_rpos[1] -= m_bodies[1].xform().getOrigin(); + m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0], + m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]); + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor) +{ + const btVector3 va=m_bodies[0].velocity(m_rpos[0]); + const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); + const btVector3 vr=va-vb; + btSoftBody::Impulse impulse; + impulse.m_asVelocity = 1; + impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor; + m_bodies[0].applyImpulse(-impulse,m_rpos[0]); + m_bodies[1].applyImpulse( impulse,m_rpos[1]); +} + +// +void btSoftBody::LJoint::Terminate(btScalar dt) +{ + if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::AJoint::Prepare(btScalar dt,int iterations) +{ + static const btScalar maxdrift=SIMD_PI/16; + m_icontrol->Prepare(this); + Joint::Prepare(dt,iterations); + m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0]; + m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1]; + m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0])); + m_drift *= btMin(maxdrift,btAcos(Clamp(btDot(m_axis[0],m_axis[1]),-1,+1))); + m_drift *= m_erp/dt; + m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia()); + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor) +{ + const btVector3 va=m_bodies[0].angularVelocity(); + const btVector3 vb=m_bodies[1].angularVelocity(); + const btVector3 vr=va-vb; + const btScalar sp=btDot(vr,m_axis[0]); + const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp); + btSoftBody::Impulse impulse; + impulse.m_asVelocity = 1; + impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor; + m_bodies[0].applyAImpulse(-impulse); + m_bodies[1].applyAImpulse( impulse); +} + +// +void btSoftBody::AJoint::Terminate(btScalar dt) +{ + if(m_split>0) + { + m_bodies[0].applyDAImpulse(-m_sdrift); + m_bodies[1].applyDAImpulse( m_sdrift); + } +} + +// +void btSoftBody::CJoint::Prepare(btScalar dt,int iterations) +{ + Joint::Prepare(dt,iterations); + const bool dodrift=(m_life==0); + m_delete=(++m_life)>m_maxlife; + if(dodrift) + { + m_drift=m_drift*m_erp/dt; + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift/=(btScalar)iterations; + } + else + { + m_drift=m_sdrift=btVector3(0,0,0); + } +} + +// +void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor) +{ + const btVector3 va=m_bodies[0].velocity(m_rpos[0]); + const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); + const btVector3 vrel=va-vb; + const btScalar rvac=btDot(vrel,m_normal); + btSoftBody::Impulse impulse; + impulse.m_asVelocity = 1; + impulse.m_velocity = m_drift; + if(rvac<0) + { + const btVector3 iv=m_normal*rvac; + const btVector3 fv=vrel-iv; + impulse.m_velocity += iv+fv*m_friction; + } + impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor; + + if (m_bodies[0].m_soft==m_bodies[1].m_soft) + { + if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&& + (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ())) + { + if (impulse.m_asVelocity) + { + if (impulse.m_velocity.length() m_maxSelfCollisionImpulse) + { + + } else + { + m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]); + m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]); + } + } + } + } else + { + m_bodies[0].applyImpulse(-impulse,m_rpos[0]); + m_bodies[1].applyImpulse( impulse,m_rpos[1]); + } +} + +// +void btSoftBody::CJoint::Terminate(btScalar dt) +{ + if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::applyForces() +{ + + BT_PROFILE("SoftBody applyForces"); +// const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + const btScalar kPR = m_cfg.kPR; + const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_pressure = kPR!=0; + const bool as_volume = kVC>0; + const bool as_aero = as_lift || + as_drag ; + //const bool as_vaero = as_aero && + // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); + //const bool as_faero = as_aero && + // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); + const bool use_medium = as_aero; + const bool use_volume = as_pressure || + as_volume ; + btScalar volume = 0; + btScalar ivolumetp = 0; + btScalar dvolumetv = 0; + btSoftBody::sMedium medium; + if(use_volume) + { + volume = getVolume(); + ivolumetp = 1/btFabs(volume)*kPR; + dvolumetv = (m_pose.m_volume-volume)*kVC; + } + /* Per vertex forces */ + int i,ni; + + for(i=0,ni=m_nodes.size();i0) + { + if(use_medium) + { + /* Aerodynamics */ + addAeroForceToNode(m_windVelocity, i); + } + /* Pressure */ + if(as_pressure) + { + n.m_f += n.m_n*(n.m_area*ivolumetp); + } + /* Volume */ + if(as_volume) + { + n.m_f += n.m_n*(n.m_area*dvolumetv); + } + } + } + + /* Per face forces */ + for(i=0,ni=m_faces.size();im_cfg.kAHR*kst; + const btScalar dt=psb->m_sst.sdt; + for(int i=0,ni=psb->m_anchors.size();im_anchors[i]; + const btTransform& t=a.m_body->getWorldTransform(); + Node& n=*a.m_node; + const btVector3 wa=t*a.m_local; + const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; + const btVector3 impulse=a.m_c0*vr*a.m_influence; + n.m_x+=impulse*a.m_c2; + a.m_body->applyImpulse(-impulse,a.m_c1); + } +} + +// +void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti) +{ + const btScalar dt = psb->m_sst.sdt; + const btScalar mrg = psb->getCollisionShape()->getMargin(); + for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; + const sCti& cti = c.m_cti; + btRigidBody* tmpRigid = (btRigidBody*)btRigidBody::upcast(cti.m_colObj); + + const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); + const btVector3 vb = c.m_node->m_x-c.m_node->m_q; + const btVector3 vr = vb-va; + const btScalar dn = btDot(vr, cti.m_normal); + if(dn<=SIMD_EPSILON) + { + const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg ); + const btVector3 fv = vr - (cti.m_normal * dn); + // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient + const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst ); + c.m_node->m_x -= impulse * c.m_c2; + if (tmpRigid) + tmpRigid->applyImpulse(impulse,c.m_c1); + } + } +} + +// +void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) +{ + for(int i=0,ni=psb->m_scontacts.size();im_scontacts[i]; + const btVector3& nr=c.m_normal; + Node& n=*c.m_node; + Face& f=*c.m_face; + const btVector3 p=BaryEval( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + c.m_weights); + const btVector3 q=BaryEval( f.m_n[0]->m_q, + f.m_n[1]->m_q, + f.m_n[2]->m_q, + c.m_weights); + const btVector3 vr=(n.m_x-n.m_q)-(p-q); + btVector3 corr(0,0,0); + btScalar dot = btDot(vr,nr); + if(dot<0) + { + const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p)); + corr+=c.m_normal*j; + } + corr -= ProjectOnPlane(vr,nr)*c.m_friction; + n.m_x += corr*c.m_cfm[0]; + f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x()); + f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y()); + f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z()); + } +} + +// +void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) +{ + for(int i=0,ni=psb->m_links.size();im_links[i]; + if(l.m_c0>0) + { + Node& a=*l.m_n[0]; + Node& b=*l.m_n[1]; + const btVector3 del=b.m_x-a.m_x; + const btScalar len=del.length2(); + if (l.m_c1+len > SIMD_EPSILON) + { + const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst; + a.m_x-=del*(k*a.m_im); + b.m_x+=del*(k*b.m_im); + } + } + } +} + +// +void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) +{ + for(int i=0,ni=psb->m_links.size();im_links[i]; + Node** n=l.m_n; + const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst; + n[0]->m_v+= l.m_c3*(j*n[0]->m_im); + n[1]->m_v-= l.m_c3*(j*n[1]->m_im); + } +} + +// +btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver) +{ + switch(solver) + { + case ePSolver::Anchors: + return(&btSoftBody::PSolve_Anchors); + case ePSolver::Linear: + return(&btSoftBody::PSolve_Links); + case ePSolver::RContacts: + return(&btSoftBody::PSolve_RContacts); + case ePSolver::SContacts: + return(&btSoftBody::PSolve_SContacts); + default: + { + } + } + return(0); +} + +// +btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) +{ + switch(solver) + { + case eVSolver::Linear: return(&btSoftBody::VSolve_Links); + default: + { + } + } + return(0); +} + +// +void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap) +{ + + switch(m_cfg.collisions&fCollision::RVSmask) + { + case fCollision::SDF_RS: + { + btSoftColliders::CollideSDF_RS docollide; + btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject()); + btTransform wtr=pcoWrap->getWorldTransform(); + + const btTransform ctr=pcoWrap->getWorldTransform(); + const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length(); + const btScalar basemargin=getCollisionShape()->getMargin(); + btVector3 mins; + btVector3 maxs; + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(), + mins, + maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(basemargin,basemargin,basemargin)); + docollide.psb = this; + docollide.m_colObj1Wrap = pcoWrap; + docollide.m_rigidBody = prb1; + + docollide.dynmargin = basemargin+timemargin; + docollide.stamargin = basemargin; + m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide); + } + break; + case fCollision::CL_RS: + { + btSoftColliders::CollideCL_RS collider; + collider.ProcessColObj(this,pcoWrap); + } + break; + } +} + +// +void btSoftBody::defaultCollisionHandler(btSoftBody* psb) +{ + const int cf=m_cfg.collisions&psb->m_cfg.collisions; + switch(cf&fCollision::SVSmask) + { + case fCollision::CL_SS: + { + + //support self-collision if CL_SELF flag set + if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF) + { + btSoftColliders::CollideCL_SS docollide; + docollide.ProcessSoftSoft(this,psb); + } + + } + break; + case fCollision::VF_SS: + { + //only self-collision for Cluster, not Vertex-Face yet + if (this!=psb) + { + btSoftColliders::CollideVF_SS docollide; + /* common */ + docollide.mrg= getCollisionShape()->getMargin()+ + psb->getCollisionShape()->getMargin(); + /* psb0 nodes vs psb1 faces */ + docollide.psb[0]=this; + docollide.psb[1]=psb; + docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + /* psb1 nodes vs psb0 faces */ + docollide.psb[0]=psb; + docollide.psb[1]=this; + docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + } + } + break; + default: + { + + } + } +} + + + +void btSoftBody::setWindVelocity( const btVector3 &velocity ) +{ + m_windVelocity = velocity; +} + + +const btVector3& btSoftBody::getWindVelocity() +{ + return m_windVelocity; +} + + + +int btSoftBody::calculateSerializeBufferSize() const +{ + int sz = sizeof(btSoftBodyData); + return sz; +} + + ///fills the dataBuffer and returns the struct name (and 0 on failure) +const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const +{ + btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer; + + btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer); + + btHashMap m_nodeIndexMap; + + sbd->m_numMaterials = m_materials.size(); + sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0; + + if (sbd->m_materials) + { + int sz = sizeof(SoftBodyMaterialData*); + int numElem = sbd->m_numMaterials; + btChunk* chunk = serializer->allocate(sz,numElem); + //SoftBodyMaterialData** memPtr = chunk->m_oldPtr; + SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr; + for (int i=0;igetUniquePointer((void*)mat) : 0; + if (!serializer->findPointer(mat)) + { + //serialize it here + btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1); + SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr; + memPtr->m_flags = mat->m_flags; + memPtr->m_angularStiffness = mat->m_kAST; + memPtr->m_linearStiffness = mat->m_kLST; + memPtr->m_volumeStiffness = mat->m_kVST; + serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat); + } + } + serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials); + } + + + + + sbd->m_numNodes = m_nodes.size(); + sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0; + if (sbd->m_nodes) + { + int sz = sizeof(SoftBodyNodeData); + int numElem = sbd->m_numNodes; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr; + for (int i=0;im_accumulatedForce); + memPtr->m_area = m_nodes[i].m_area; + memPtr->m_attach = m_nodes[i].m_battach; + memPtr->m_inverseMass = m_nodes[i].m_im; + memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0; + m_nodes[i].m_n.serializeFloat(memPtr->m_normal); + m_nodes[i].m_x.serializeFloat(memPtr->m_position); + m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition); + m_nodes[i].m_v.serializeFloat(memPtr->m_velocity); + m_nodeIndexMap.insert(&m_nodes[i],i); + } + serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes); + } + + sbd->m_numLinks = m_links.size(); + sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0; + if (sbd->m_links) + { + int sz = sizeof(SoftBodyLinkData); + int numElem = sbd->m_numLinks; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr; + for (int i=0;im_bbending = m_links[i].m_bbending; + memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0; + memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1; + memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1; + btAssert(memPtr->m_nodeIndices[0]m_nodeIndices[1]m_restLength = m_links[i].m_rl; + } + serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]); + + } + + + sbd->m_numFaces = m_faces.size(); + sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0; + if (sbd->m_faces) + { + int sz = sizeof(SoftBodyFaceData); + int numElem = sbd->m_numFaces; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr; + for (int i=0;im_material = m_faces[i].m_material ? (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0; + m_faces[i].m_normal.serializeFloat( memPtr->m_normal); + for (int j=0;j<3;j++) + { + memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1; + } + memPtr->m_restArea = m_faces[i].m_ra; + } + serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]); + } + + + sbd->m_numTetrahedra = m_tetras.size(); + sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0; + if (sbd->m_tetrahedra) + { + int sz = sizeof(SoftBodyTetraData); + int numElem = sbd->m_numTetrahedra; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr; + for (int i=0;im_c0[j] ); + memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1; + } + memPtr->m_c1 = m_tetras[i].m_c1; + memPtr->m_c2 = m_tetras[i].m_c2; + memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0; + memPtr->m_restVolume = m_tetras[i].m_rv; + } + serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]); + } + + sbd->m_numAnchors = m_anchors.size(); + sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0; + if (sbd->m_anchors) + { + int sz = sizeof(SoftRigidAnchorData); + int numElem = sbd->m_numAnchors; + btChunk* chunk = serializer->allocate(sz,numElem); + SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr; + for (int i=0;im_c0); + m_anchors[i].m_c1.serializeFloat(memPtr->m_c1); + memPtr->m_c2 = m_anchors[i].m_c2; + m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame); + memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1; + + memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*) serializer->getUniquePointer((void*)m_anchors[i].m_body): 0; + btAssert(memPtr->m_nodeIndex < m_nodes.size()); + } + serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]); + } + + + sbd->m_config.m_dynamicFriction = m_cfg.kDF; + sbd->m_config.m_baumgarte = m_cfg.kVCF; + sbd->m_config.m_pressure = m_cfg.kPR; + sbd->m_config.m_aeroModel = this->m_cfg.aeromodel; + sbd->m_config.m_lift = m_cfg.kLF; + sbd->m_config.m_drag = m_cfg.kDG; + sbd->m_config.m_positionIterations = m_cfg.piterations; + sbd->m_config.m_driftIterations = m_cfg.diterations; + sbd->m_config.m_clusterIterations = m_cfg.citerations; + sbd->m_config.m_velocityIterations = m_cfg.viterations; + sbd->m_config.m_maxVolume = m_cfg.maxvolume; + sbd->m_config.m_damping = m_cfg.kDP; + sbd->m_config.m_poseMatch = m_cfg.kMT; + sbd->m_config.m_collisionFlags = m_cfg.collisions; + sbd->m_config.m_volume = m_cfg.kVC; + sbd->m_config.m_rigidContactHardness = m_cfg.kCHR; + sbd->m_config.m_kineticContactHardness = m_cfg.kKHR; + sbd->m_config.m_softContactHardness = m_cfg.kSHR; + sbd->m_config.m_anchorHardness = m_cfg.kAHR; + sbd->m_config.m_timeScale = m_cfg.timescale; + sbd->m_config.m_maxVolume = m_cfg.maxvolume; + sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL; + sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL; + sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL; + sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL; + sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL; + sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL; + + //pose for shape matching + { + sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose); + + int sz = sizeof(SoftBodyPoseData); + btChunk* chunk = serializer->allocate(sz,1); + SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr; + + m_pose.m_aqq.serializeFloat(memPtr->m_aqq); + memPtr->m_bframe = m_pose.m_bframe; + memPtr->m_bvolume = m_pose.m_bvolume; + m_pose.m_com.serializeFloat(memPtr->m_com); + + memPtr->m_numPositions = m_pose.m_pos.size(); + memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0; + if (memPtr->m_numPositions) + { + int numElem = memPtr->m_numPositions; + int sz = sizeof(btVector3Data); + btChunk* chunk = serializer->allocate(sz,numElem); + btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]); + } + memPtr->m_restVolume = m_pose.m_volume; + m_pose.m_rot.serializeFloat(memPtr->m_rot); + m_pose.m_scl.serializeFloat(memPtr->m_scale); + + memPtr->m_numWeigts = m_pose.m_wgh.size(); + memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0; + if (memPtr->m_numWeigts) + { + + int numElem = memPtr->m_numWeigts; + int sz = sizeof(float); + btChunk* chunk = serializer->allocate(sz,numElem); + float* memPtr = (float*) chunk->m_oldPtr; + for (int i=0;ifinalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]); + } + + serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose); + } + + //clusters for convex-cluster collision detection + + sbd->m_numClusters = m_clusters.size(); + sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0; + if (sbd->m_numClusters) + { + int numElem = sbd->m_numClusters; + int sz = sizeof(SoftBodyClusterData); + btChunk* chunk = serializer->allocate(sz,numElem); + SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr; + for (int i=0;im_adamping= m_clusters[i]->m_adamping; + m_clusters[i]->m_av.serializeFloat(memPtr->m_av); + memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex; + memPtr->m_collide = m_clusters[i]->m_collide; + m_clusters[i]->m_com.serializeFloat(memPtr->m_com); + memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor; + m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]); + m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]); + m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform); + memPtr->m_idmass = m_clusters[i]->m_idmass; + memPtr->m_imass = m_clusters[i]->m_imass; + m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi); + memPtr->m_ldamping = m_clusters[i]->m_ldamping; + m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii); + m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv); + memPtr->m_matching = m_clusters[i]->m_matching; + memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse; + memPtr->m_ndamping = m_clusters[i]->m_ndamping; + memPtr->m_ldamping = m_clusters[i]->m_ldamping; + memPtr->m_adamping = m_clusters[i]->m_adamping; + memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor; + + memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size(); + memPtr->m_numMasses = m_clusters[i]->m_masses.size(); + memPtr->m_numNodes = m_clusters[i]->m_nodes.size(); + + memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses; + m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]); + m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]); + memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses; + + + + memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0; + if (memPtr->m_framerefs) + { + int numElem = memPtr->m_numFrameRefs; + int sz = sizeof(btVector3FloatData); + btChunk* chunk = serializer->allocate(sz,numElem); + btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr; + for (int j=0;jm_framerefs[j].serializeFloat(*memPtr); + } + serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]); + } + + memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0; + if (memPtr->m_masses) + { + int numElem = memPtr->m_numMasses; + int sz = sizeof(float); + btChunk* chunk = serializer->allocate(sz,numElem); + float* memPtr = (float*) chunk->m_oldPtr; + for (int j=0;jm_masses[j]; + } + serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]); + } + + memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0; + if (memPtr->m_nodeIndices ) + { + int numElem = memPtr->m_numMasses; + int sz = sizeof(int); + btChunk* chunk = serializer->allocate(sz,numElem); + int* memPtr = (int*) chunk->m_oldPtr; + for (int j=0;jm_nodes[j]); + btAssert(indexPtr); + *memPtr = *indexPtr; + } + serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes); + } + } + serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]); + + } + + + + sbd->m_numJoints = m_joints.size(); + sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0; + + if (sbd->m_joints) + { + int sz = sizeof(btSoftBodyJointData); + int numElem = m_joints.size(); + btChunk* chunk = serializer->allocate(sz,numElem); + btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr; + + for (int i=0;im_jointType = (int)m_joints[i]->Type(); + m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]); + m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]); + memPtr->m_cfm = m_joints[i]->m_cfm; + memPtr->m_erp = m_joints[i]->m_erp; + memPtr->m_split = m_joints[i]->m_split; + memPtr->m_delete = m_joints[i]->m_delete; + + for (int j=0;j<4;j++) + { + memPtr->m_relPosition[0].m_floats[j] = 0.f; + memPtr->m_relPosition[1].m_floats[j] = 0.f; + } + memPtr->m_bodyA = 0; + memPtr->m_bodyB = 0; + if (m_joints[i]->m_bodies[0].m_soft) + { + memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER; + memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft); + } + if (m_joints[i]->m_bodies[0].m_collisionObject) + { + memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT; + memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject); + } + if (m_joints[i]->m_bodies[0].m_rigid) + { + memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY; + memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid); + } + + if (m_joints[i]->m_bodies[1].m_soft) + { + memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER; + memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft); + } + if (m_joints[i]->m_bodies[1].m_collisionObject) + { + memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT; + memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject); + } + if (m_joints[i]->m_bodies[1].m_rigid) + { + memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY; + memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid); + } + } + serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]); + } + + + return btSoftBodyDataName; +} + diff --git a/Code/Physics/src/BulletSoftBody/btSoftBody.h b/Code/Physics/src/BulletSoftBody/btSoftBody.h new file mode 100644 index 00000000..ee1a3d95 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBody.h @@ -0,0 +1,1000 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_H +#define _BT_SOFT_BODY_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btSparseSDF.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" + +//#ifdef BT_USE_DOUBLE_PRECISION +//#define btRigidBodyData btRigidBodyDoubleData +//#define btRigidBodyDataName "btRigidBodyDoubleData" +//#else +#define btSoftBodyData btSoftBodyFloatData +#define btSoftBodyDataName "btSoftBodyFloatData" +//#endif //BT_USE_DOUBLE_PRECISION + +class btBroadphaseInterface; +class btDispatcher; +class btSoftBodySolver; + +/* btSoftBodyWorldInfo */ +struct btSoftBodyWorldInfo +{ + btScalar air_density; + btScalar water_density; + btScalar water_offset; + btScalar m_maxDisplacement; + btVector3 water_normal; + btBroadphaseInterface* m_broadphase; + btDispatcher* m_dispatcher; + btVector3 m_gravity; + btSparseSdf<3> m_sparsesdf; + + btSoftBodyWorldInfo() + :air_density((btScalar)1.2), + water_density(0), + water_offset(0), + m_maxDisplacement(1000.f),//avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame + water_normal(0,0,0), + m_broadphase(0), + m_dispatcher(0), + m_gravity(0,-10,0) + { + } +}; + + +///The btSoftBody is an class to simulate cloth and volumetric soft bodies. +///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject. +class btSoftBody : public btCollisionObject +{ +public: + btAlignedObjectArray m_collisionDisabledObjects; + + // The solver object that handles this soft body + btSoftBodySolver *m_softBodySolver; + + // + // Enumerations + // + + ///eAeroModel + struct eAeroModel { enum _ { + V_Point, ///Vertex normals are oriented toward velocity + V_TwoSided, ///Vertex normals are flipped to match velocity + V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied + V_OneSided, ///Vertex normals are taken as it is + F_TwoSided, ///Face normals are flipped to match velocity + F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied + F_OneSided, ///Face normals are taken as it is + END + };}; + + ///eVSolver : velocities solvers + struct eVSolver { enum _ { + Linear, ///Linear solver + END + };}; + + ///ePSolver : positions solvers + struct ePSolver { enum _ { + Linear, ///Linear solver + Anchors, ///Anchor solver + RContacts, ///Rigid contacts solver + SContacts, ///Soft contacts solver + END + };}; + + ///eSolverPresets + struct eSolverPresets { enum _ { + Positions, + Velocities, + Default = Positions, + END + };}; + + ///eFeature + struct eFeature { enum _ { + None, + Node, + Link, + Face, + Tetra, + END + };}; + + typedef btAlignedObjectArray tVSolverArray; + typedef btAlignedObjectArray tPSolverArray; + + // + // Flags + // + + ///fCollision + struct fCollision { enum _ { + RVSmask = 0x000f, ///Rigid versus soft mask + SDF_RS = 0x0001, ///SDF based rigid vs soft + CL_RS = 0x0002, ///Cluster vs convex rigid vs soft + + SVSmask = 0x0030, ///Rigid versus soft mask + VF_SS = 0x0010, ///Vertex vs face soft vs soft handling + CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling + CL_SELF = 0x0040, ///Cluster soft body self collision + /* presets */ + Default = SDF_RS, + END + };}; + + ///fMaterial + struct fMaterial { enum _ { + DebugDraw = 0x0001, /// Enable debug draw + /* presets */ + Default = DebugDraw, + END + };}; + + // + // API Types + // + + /* sRayCast */ + struct sRayCast + { + btSoftBody* body; /// soft body + eFeature::_ feature; /// feature type + int index; /// feature index + btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction) + }; + + /* ImplicitFn */ + struct ImplicitFn + { + virtual btScalar Eval(const btVector3& x)=0; + }; + + // + // Internal types + // + + typedef btAlignedObjectArray tScalarArray; + typedef btAlignedObjectArray tVector3Array; + + /* sCti is Softbody contact info */ + struct sCti + { + const btCollisionObject* m_colObj; /* Rigid body */ + btVector3 m_normal; /* Outward normal */ + btScalar m_offset; /* Offset from origin */ + }; + + /* sMedium */ + struct sMedium + { + btVector3 m_velocity; /* Velocity */ + btScalar m_pressure; /* Pressure */ + btScalar m_density; /* Density */ + }; + + /* Base type */ + struct Element + { + void* m_tag; // User data + Element() : m_tag(0) {} + }; + /* Material */ + struct Material : Element + { + btScalar m_kLST; // Linear stiffness coefficient [0,1] + btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] + btScalar m_kVST; // Volume stiffness coefficient [0,1] + int m_flags; // Flags + }; + + /* Feature */ + struct Feature : Element + { + Material* m_material; // Material + }; + /* Node */ + struct Node : Feature + { + btVector3 m_x; // Position + btVector3 m_q; // Previous step position + btVector3 m_v; // Velocity + btVector3 m_f; // Force accumulator + btVector3 m_n; // Normal + btScalar m_im; // 1/mass + btScalar m_area; // Area + btDbvtNode* m_leaf; // Leaf data + int m_battach:1; // Attached + }; + /* Link */ + struct Link : Feature + { + Node* m_n[2]; // Node pointers + btScalar m_rl; // Rest length + int m_bbending:1; // Bending link + btScalar m_c0; // (ima+imb)*kLST + btScalar m_c1; // rl^2 + btScalar m_c2; // |gradient|^2/c0 + btVector3 m_c3; // gradient + }; + /* Face */ + struct Face : Feature + { + Node* m_n[3]; // Node pointers + btVector3 m_normal; // Normal + btScalar m_ra; // Rest area + btDbvtNode* m_leaf; // Leaf data + }; + /* Tetra */ + struct Tetra : Feature + { + Node* m_n[4]; // Node pointers + btScalar m_rv; // Rest volume + btDbvtNode* m_leaf; // Leaf data + btVector3 m_c0[4]; // gradients + btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3) + btScalar m_c2; // m_c1/sum(|g0..3|^2) + }; + /* RContact */ + struct RContact + { + sCti m_cti; // Contact infos + Node* m_node; // Owner node + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + btScalar m_c3; // Friction + btScalar m_c4; // Hardness + }; + /* SContact */ + struct SContact + { + Node* m_node; // Node + Face* m_face; // Face + btVector3 m_weights; // Weigths + btVector3 m_normal; // Normal + btScalar m_margin; // Margin + btScalar m_friction; // Friction + btScalar m_cfm[2]; // Constraint force mixing + }; + /* Anchor */ + struct Anchor + { + Node* m_node; // Node pointer + btVector3 m_local; // Anchor position in body space + btRigidBody* m_body; // Body + btScalar m_influence; + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + }; + /* Note */ + struct Note : Element + { + const char* m_text; // Text + btVector3 m_offset; // Offset + int m_rank; // Rank + Node* m_nodes[4]; // Nodes + btScalar m_coords[4]; // Coordinates + }; + /* Pose */ + struct Pose + { + bool m_bvolume; // Is valid + bool m_bframe; // Is frame + btScalar m_volume; // Rest volume + tVector3Array m_pos; // Reference positions + tScalarArray m_wgh; // Weights + btVector3 m_com; // COM + btMatrix3x3 m_rot; // Rotation + btMatrix3x3 m_scl; // Scale + btMatrix3x3 m_aqq; // Base scaling + }; + /* Cluster */ + struct Cluster + { + tScalarArray m_masses; + btAlignedObjectArray m_nodes; + tVector3Array m_framerefs; + btTransform m_framexform; + btScalar m_idmass; + btScalar m_imass; + btMatrix3x3 m_locii; + btMatrix3x3 m_invwi; + btVector3 m_com; + btVector3 m_vimpulses[2]; + btVector3 m_dimpulses[2]; + int m_nvimpulses; + int m_ndimpulses; + btVector3 m_lv; + btVector3 m_av; + btDbvtNode* m_leaf; + btScalar m_ndamping; /* Node damping */ + btScalar m_ldamping; /* Linear damping */ + btScalar m_adamping; /* Angular damping */ + btScalar m_matching; + btScalar m_maxSelfCollisionImpulse; + btScalar m_selfCollisionImpulseFactor; + bool m_containsAnchor; + bool m_collide; + int m_clusterIndex; + Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) + ,m_maxSelfCollisionImpulse(100.f), + m_selfCollisionImpulseFactor(0.01f), + m_containsAnchor(false) + {} + }; + /* Impulse */ + struct Impulse + { + btVector3 m_velocity; + btVector3 m_drift; + int m_asVelocity:1; + int m_asDrift:1; + Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} + Impulse operator -() const + { + Impulse i=*this; + i.m_velocity=-i.m_velocity; + i.m_drift=-i.m_drift; + return(i); + } + Impulse operator*(btScalar x) const + { + Impulse i=*this; + i.m_velocity*=x; + i.m_drift*=x; + return(i); + } + }; + /* Body */ + struct Body + { + Cluster* m_soft; + btRigidBody* m_rigid; + const btCollisionObject* m_collisionObject; + + Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {} + Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {} + Body(const btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj) + { + m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject); + } + + void activate() const + { + if(m_rigid) + m_rigid->activate(); + if (m_collisionObject) + m_collisionObject->activate(); + + } + const btMatrix3x3& invWorldInertia() const + { + static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); + if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); + if(m_soft) return(m_soft->m_invwi); + return(iwi); + } + btScalar invMass() const + { + if(m_rigid) return(m_rigid->getInvMass()); + if(m_soft) return(m_soft->m_imass); + return(0); + } + const btTransform& xform() const + { + static const btTransform identity=btTransform::getIdentity(); + if(m_collisionObject) return(m_collisionObject->getWorldTransform()); + if(m_soft) return(m_soft->m_framexform); + return(identity); + } + btVector3 linearVelocity() const + { + if(m_rigid) return(m_rigid->getLinearVelocity()); + if(m_soft) return(m_soft->m_lv); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity(const btVector3& rpos) const + { + if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos)); + if(m_soft) return(btCross(m_soft->m_av,rpos)); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity() const + { + if(m_rigid) return(m_rigid->getAngularVelocity()); + if(m_soft) return(m_soft->m_av); + return(btVector3(0,0,0)); + } + btVector3 velocity(const btVector3& rpos) const + { + return(linearVelocity()+angularVelocity(rpos)); + } + void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); + } + void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); + } + void applyImpulse(const Impulse& impulse,const btVector3& rpos) const + { + if(impulse.m_asVelocity) + { +// printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ()); + applyVImpulse(impulse.m_velocity,rpos); + } + if(impulse.m_asDrift) + { +// printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ()); + applyDImpulse(impulse.m_drift,rpos); + } + } + void applyVAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); + } + void applyDAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); + } + void applyAImpulse(const Impulse& impulse) const + { + if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); + if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); + } + void applyDCImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyCentralImpulse(impulse); + if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); + } + }; + /* Joint */ + struct Joint + { + struct eType { enum _ { + Linear=0, + Angular, + Contact + };}; + struct Specs + { + Specs() : erp(1),cfm(1),split(1) {} + btScalar erp; + btScalar cfm; + btScalar split; + }; + Body m_bodies[2]; + btVector3 m_refs[2]; + btScalar m_cfm; + btScalar m_erp; + btScalar m_split; + btVector3 m_drift; + btVector3 m_sdrift; + btMatrix3x3 m_massmatrix; + bool m_delete; + virtual ~Joint() {} + Joint() : m_delete(false) {} + virtual void Prepare(btScalar dt,int iterations); + virtual void Solve(btScalar dt,btScalar sor)=0; + virtual void Terminate(btScalar dt)=0; + virtual eType::_ Type() const=0; + }; + /* LJoint */ + struct LJoint : Joint + { + struct Specs : Joint::Specs + { + btVector3 position; + }; + btVector3 m_rpos[2]; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Linear); } + }; + /* AJoint */ + struct AJoint : Joint + { + struct IControl + { + virtual void Prepare(AJoint*) {} + virtual btScalar Speed(AJoint*,btScalar current) { return(current); } + static IControl* Default() { static IControl def;return(&def); } + }; + struct Specs : Joint::Specs + { + Specs() : icontrol(IControl::Default()) {} + btVector3 axis; + IControl* icontrol; + }; + btVector3 m_axis[2]; + IControl* m_icontrol; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Angular); } + }; + /* CJoint */ + struct CJoint : Joint + { + int m_life; + int m_maxlife; + btVector3 m_rpos[2]; + btVector3 m_normal; + btScalar m_friction; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Contact); } + }; + /* Config */ + struct Config + { + eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) + btScalar kVCF; // Velocities correction factor (Baumgarte) + btScalar kDP; // Damping coefficient [0,1] + btScalar kDG; // Drag coefficient [0,+inf] + btScalar kLF; // Lift coefficient [0,+inf] + btScalar kPR; // Pressure coefficient [-inf,+inf] + btScalar kVC; // Volume conversation coefficient [0,+inf] + btScalar kDF; // Dynamic friction coefficient [0,1] + btScalar kMT; // Pose matching coefficient [0,1] + btScalar kCHR; // Rigid contacts hardness [0,1] + btScalar kKHR; // Kinetic contacts hardness [0,1] + btScalar kSHR; // Soft contacts hardness [0,1] + btScalar kAHR; // Anchors hardness [0,1] + btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) + btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only) + btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) + btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar maxvolume; // Maximum volume ratio for pose + btScalar timescale; // Time scale + int viterations; // Velocities solver iterations + int piterations; // Positions solver iterations + int diterations; // Drift solver iterations + int citerations; // Cluster solver iterations + int collisions; // Collisions flags + tVSolverArray m_vsequence; // Velocity solvers sequence + tPSolverArray m_psequence; // Position solvers sequence + tPSolverArray m_dsequence; // Drift solvers sequence + }; + /* SolverState */ + struct SolverState + { + btScalar sdt; // dt*timescale + btScalar isdt; // 1/sdt + btScalar velmrg; // velocity margin + btScalar radmrg; // radial margin + btScalar updmrg; // Update margin + }; + /// RayFromToCaster takes a ray from, ray to (instead of direction!) + struct RayFromToCaster : btDbvt::ICollide + { + btVector3 m_rayFrom; + btVector3 m_rayTo; + btVector3 m_rayNormalizedDirection; + btScalar m_mint; + Face* m_face; + int m_tests; + RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt); + void Process(const btDbvtNode* leaf); + + static inline btScalar rayFromToTriangle(const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& rayNormalizedDirection, + const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar maxt=SIMD_INFINITY); + }; + + // + // Typedefs + // + + typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); + typedef void (*vsolver_t)(btSoftBody*,btScalar); + typedef btAlignedObjectArray tClusterArray; + typedef btAlignedObjectArray tNoteArray; + typedef btAlignedObjectArray tNodeArray; + typedef btAlignedObjectArray tLeafArray; + typedef btAlignedObjectArray tLinkArray; + typedef btAlignedObjectArray tFaceArray; + typedef btAlignedObjectArray tTetraArray; + typedef btAlignedObjectArray tAnchorArray; + typedef btAlignedObjectArray tRContactArray; + typedef btAlignedObjectArray tSContactArray; + typedef btAlignedObjectArray tMaterialArray; + typedef btAlignedObjectArray tJointArray; + typedef btAlignedObjectArray tSoftBodyArray; + + // + // Fields + // + + Config m_cfg; // Configuration + SolverState m_sst; // Solver state + Pose m_pose; // Pose + void* m_tag; // User data + btSoftBodyWorldInfo* m_worldInfo; // World info + tNoteArray m_notes; // Notes + tNodeArray m_nodes; // Nodes + tLinkArray m_links; // Links + tFaceArray m_faces; // Faces + tTetraArray m_tetras; // Tetras + tAnchorArray m_anchors; // Anchors + tRContactArray m_rcontacts; // Rigid contacts + tSContactArray m_scontacts; // Soft contacts + tJointArray m_joints; // Joints + tMaterialArray m_materials; // Materials + btScalar m_timeacc; // Time accumulator + btVector3 m_bounds[2]; // Spatial bounds + bool m_bUpdateRtCst; // Update runtime constants + btDbvt m_ndbvt; // Nodes tree + btDbvt m_fdbvt; // Faces tree + btDbvt m_cdbvt; // Clusters tree + tClusterArray m_clusters; // Clusters + + btAlignedObjectArraym_clusterConnectivity;//cluster connectivity, for self-collision + + btTransform m_initialWorldTransform; + + btVector3 m_windVelocity; + + btScalar m_restLengthScale; + + // + // Api + // + + /* ctor */ + btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m); + + /* ctor */ + btSoftBody( btSoftBodyWorldInfo* worldInfo); + + void initDefaults(); + + /* dtor */ + virtual ~btSoftBody(); + /* Check for existing link */ + + btAlignedObjectArray m_userIndexMapping; + + btSoftBodyWorldInfo* getWorldInfo() + { + return m_worldInfo; + } + + ///@todo: avoid internal softbody shape hack and move collision code to collision library + virtual void setCollisionShape(btCollisionShape* collisionShape) + { + + } + + bool checkLink( int node0, + int node1) const; + bool checkLink( const Node* node0, + const Node* node1) const; + /* Check for existring face */ + bool checkFace( int node0, + int node1, + int node2) const; + /* Append material */ + Material* appendMaterial(); + /* Append note */ + void appendNote( const char* text, + const btVector3& o, + const btVector4& c=btVector4(1,0,0,0), + Node* n0=0, + Node* n1=0, + Node* n2=0, + Node* n3=0); + void appendNote( const char* text, + const btVector3& o, + Node* feature); + void appendNote( const char* text, + const btVector3& o, + Link* feature); + void appendNote( const char* text, + const btVector3& o, + Face* feature); + /* Append node */ + void appendNode( const btVector3& x,btScalar m); + /* Append link */ + void appendLink(int model=-1,Material* mat=0); + void appendLink( int node0, + int node1, + Material* mat=0, + bool bcheckexist=false); + void appendLink( Node* node0, + Node* node1, + Material* mat=0, + bool bcheckexist=false); + /* Append face */ + void appendFace(int model=-1,Material* mat=0); + void appendFace( int node0, + int node1, + int node2, + Material* mat=0); + void appendTetra(int model,Material* mat); + // + void appendTetra(int node0, + int node1, + int node2, + int node3, + Material* mat=0); + + + /* Append anchor */ + void appendAnchor( int node, + btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); + void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); + /* Append linear joint */ + void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); + void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); + void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); + /* Append linear joint */ + void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); + void appendAngularJoint(const AJoint::Specs& specs,Body body=Body()); + void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); + /* Add force (or gravity) to the entire body */ + void addForce( const btVector3& force); + /* Add force (or gravity) to a node of the body */ + void addForce( const btVector3& force, + int node); + /* Add aero force to a node of the body */ + void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex); + + /* Add aero force to a face of the body */ + void addAeroForceToFace(const btVector3& windVelocity,int faceIndex); + + /* Add velocity to the entire body */ + void addVelocity( const btVector3& velocity); + + /* Set velocity for the entire body */ + void setVelocity( const btVector3& velocity); + + /* Add velocity to a node of the body */ + void addVelocity( const btVector3& velocity, + int node); + /* Set mass */ + void setMass( int node, + btScalar mass); + /* Get mass */ + btScalar getMass( int node) const; + /* Get total mass */ + btScalar getTotalMass() const; + /* Set total mass (weighted by previous masses) */ + void setTotalMass( btScalar mass, + bool fromfaces=false); + /* Set total density */ + void setTotalDensity(btScalar density); + /* Set volume mass (using tetrahedrons) */ + void setVolumeMass( btScalar mass); + /* Set volume density (using tetrahedrons) */ + void setVolumeDensity( btScalar density); + /* Transform */ + void transform( const btTransform& trs); + /* Translate */ + void translate( const btVector3& trs); + /* Rotate */ + void rotate( const btQuaternion& rot); + /* Scale */ + void scale( const btVector3& scl); + /* Get link resting lengths scale */ + btScalar getRestLengthScale(); + /* Scale resting length of all springs */ + void setRestLengthScale(btScalar restLength); + /* Set current state as pose */ + void setPose( bool bvolume, + bool bframe); + /* Set current link lengths as resting lengths */ + void resetLinkRestLengths(); + /* Return the volume */ + btScalar getVolume() const; + /* Cluster count */ + int clusterCount() const; + /* Cluster center of mass */ + static btVector3 clusterCom(const Cluster* cluster); + btVector3 clusterCom(int cluster) const; + /* Cluster velocity at rpos */ + static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); + /* Cluster impulse */ + static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); + static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); + static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); + /* Generate bending constraints based on distance in the adjency graph */ + int generateBendingConstraints( int distance, + Material* mat=0); + /* Randomize constraints to reduce solver bias */ + void randomizeConstraints(); + /* Release clusters */ + void releaseCluster(int index); + void releaseClusters(); + /* Generate clusters (K-mean) */ + ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle + ///otherwise an approximation will be used (better performance) + int generateClusters(int k,int maxiterations=8192); + /* Refine */ + void refine(ImplicitFn* ifn,btScalar accurary,bool cut); + /* CutLink */ + bool cutLink(int node0,int node1,btScalar position); + bool cutLink(const Node* node0,const Node* node1,btScalar position); + + ///Ray casting using rayFrom and rayTo in worldspace, (not direction!) + bool rayTest(const btVector3& rayFrom, + const btVector3& rayTo, + sRayCast& results); + /* Solver presets */ + void setSolver(eSolverPresets::_ preset); + /* predictMotion */ + void predictMotion(btScalar dt); + /* solveConstraints */ + void solveConstraints(); + /* staticSolve */ + void staticSolve(int iterations); + /* solveCommonConstraints */ + static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); + /* solveClusters */ + static void solveClusters(const btAlignedObjectArray& bodies); + /* integrateMotion */ + void integrateMotion(); + /* defaultCollisionHandlers */ + void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap); + void defaultCollisionHandler(btSoftBody* psb); + + + + // + // Functionality to deal with new accelerated solvers. + // + + /** + * Set a wind velocity for interaction with the air. + */ + void setWindVelocity( const btVector3 &velocity ); + + + /** + * Return the wind velocity for interaction with the air. + */ + const btVector3& getWindVelocity(); + + // + // Set the solver that handles this soft body + // Should not be allowed to get out of sync with reality + // Currently called internally on addition to the world + void setSoftBodySolver( btSoftBodySolver *softBodySolver ) + { + m_softBodySolver = softBodySolver; + } + + // + // Return the solver that handles this soft body + // + btSoftBodySolver *getSoftBodySolver() + { + return m_softBodySolver; + } + + // + // Return the solver that handles this soft body + // + btSoftBodySolver *getSoftBodySolver() const + { + return m_softBodySolver; + } + + + // + // Cast + // + + static const btSoftBody* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (const btSoftBody*)colObj; + return 0; + } + static btSoftBody* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (btSoftBody*)colObj; + return 0; + } + + // + // ::btCollisionObject + // + + virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_bounds[0]; + aabbMax = m_bounds[1]; + } + // + // Private + // + void pointersToIndices(); + void indicesToPointers(const int* map=0); + + int rayTest(const btVector3& rayFrom,const btVector3& rayTo, + btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; + void initializeFaceTree(); + btVector3 evaluateCom() const; + bool checkContact(const btCollisionObjectWrapper* colObjWrap,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; + void updateNormals(); + void updateBounds(); + void updatePose(); + void updateConstants(); + void updateLinkConstants(); + void updateArea(bool averageArea = true); + void initializeClusters(); + void updateClusters(); + void cleanupClusters(); + void prepareClusters(int iterations); + void solveClusters(btScalar sor); + void applyClusters(bool drift); + void dampClusters(); + void applyForces(); + static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti); + static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); + static void VSolve_Links(btSoftBody* psb,btScalar kst); + static psolver_t getSolver(ePSolver::_ solver); + static vsolver_t getSolver(eVSolver::_ solver); + + + virtual int calculateSerializeBufferSize() const; + + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; + + //virtual void serializeSingleObject(class btSerializer* serializer) const; + + +}; + + + + +#endif //_BT_SOFT_BODY_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp new file mode 100644 index 00000000..9f0d4452 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -0,0 +1,357 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletSoftBody/btSoftBody.h" + +#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable + +btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) +: btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped) +{ +} + + + +btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() +{ +} + + + +btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped): +m_dispatcher(dispatcher), +m_dispatchInfoPtr(0) +{ + m_softBody = (isSwapped? (btSoftBody*)body1Wrap->getCollisionObject():(btSoftBody*)body0Wrap->getCollisionObject()); + m_triBody = isSwapped? body0Wrap->getCollisionObject():body1Wrap->getCollisionObject(); + + // + // create the manifold from the dispatcher 'manifold pool' + // + // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); + + clearCache(); +} + +btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() +{ + clearCache(); + // m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btSoftBodyTriangleCallback::clearCache() +{ + for (int i=0;im_childShape); + m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary? + delete tmp->m_childShape; + } + m_shapeCache.clear(); +} + + +void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + //just for debugging purposes + //printf("triangle %d",m_triangleCount++); + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe)) + { + btVector3 color(1,1,0); + const btTransform& tr = m_triBody->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + } + + btTriIndex triIndex(partId,triangleIndex,0); + btHashKey triKey(triIndex.getUid()); + + + btTriIndex* shapeIndex = m_shapeCache[triKey]; + if (shapeIndex) + { + btCollisionShape* tm = shapeIndex->m_childShape; + btAssert(tm); + + //copy over user pointers to temporary shape + tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer()); + + btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1); + //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//?? + btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex); + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr); + + colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + + return; + } + + //aabb filter is already applied! + + //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); + + // if (m_softBody->getCollisionShape()->getShapeType()== + { + // btVector3 other; + btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + normal.normalize(); + normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; + // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; + // other+=normal*22.f; + btVector3 pts[6] = {triangle[0]+normal, + triangle[1]+normal, + triangle[2]+normal, + triangle[0]-normal, + triangle[1]-normal, + triangle[2]-normal}; + + btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6); + + + // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); + + //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + // tm.setMargin(m_collisionMarginTriangle); + + //copy over user pointers to temporary shape + tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer()); + + + btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1); + btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//?? + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr); + + colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + + triIndex.m_childShape = tm; + m_shapeCache.insert(triKey,triIndex); + + } + + + +} + + + +void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); + m_resultOut = resultOut; + + + btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; + m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); + btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); + btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5); + + btTransform softTransform; + softTransform.setIdentity(); + softTransform.setOrigin(softBodyCenter); + + btTransform convexInTriangleSpace; + convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform; + btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax); +} + +void btSoftBodyConcaveCollisionAlgorithm::clearCache() +{ + m_btSoftBodyTriangleCallback.clearCache(); + +} + +void btSoftBodyConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + //btCollisionObject* convexBody = m_isSwapped ? body1 : body0; + const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap; + + if (triBody->getCollisionShape()->isConcave()) + { + + + const btCollisionObject* triOb = triBody->getCollisionObject(); + const btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); + + // if (convexBody->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + + // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,triBody,dispatchInfo,resultOut); + + + concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); + + // resultOut->refreshContactPoints(); + + } + + } + +} + + +btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h new file mode 100644 index 00000000..11c7b88f --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h @@ -0,0 +1,155 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#define BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btSoftBody; +class btCollisionShape; + +#include "LinearMath/btHashMap.h" + +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS + +struct btTriIndex +{ + int m_PartIdTriangleIndex; + class btCollisionShape* m_childShape; + + btTriIndex(int partId,int triangleIndex,btCollisionShape* shape) + { + m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + m_childShape = shape; + } + + int getTriangleIndex() const + { + // Get only the lower bits where the triangle index is stored + unsigned int x = 0; + unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS); + return (m_PartIdTriangleIndex&~(y)); + } + int getPartId() const + { + // Get only the highest bits where the part index is stored + return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); + } + int getUid() const + { + return m_PartIdTriangleIndex; + } +}; + + +///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called. +class btSoftBodyTriangleCallback : public btTriangleCallback +{ + btSoftBody* m_softBody; + const btCollisionObject* m_triBody; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + btManifoldResult* m_resultOut; + + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + + btHashMap,btTriIndex> m_shapeCache; + +public: + int m_triangleCount; + + // btPersistentManifold* m_manifoldPtr; + + btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triObjWrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual ~btSoftBodyTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + SIMD_FORCE_INLINE const btVector3& getAabbMin() const + { + return m_aabbMin; + } + SIMD_FORCE_INLINE const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes. +class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm +{ + + bool m_isSwapped; + + btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback; + +public: + + btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); + + virtual ~btSoftBodyConcaveCollisionAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true); + } + }; + +}; + +#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyData.h b/Code/Physics/src/BulletSoftBody/btSoftBodyData.h new file mode 100644 index 00000000..87d8841c --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyData.h @@ -0,0 +1,217 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFTBODY_FLOAT_DATA +#define BT_SOFTBODY_FLOAT_DATA + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + + +struct SoftBodyMaterialData +{ + float m_linearStiffness; + float m_angularStiffness; + float m_volumeStiffness; + int m_flags; +}; + +struct SoftBodyNodeData +{ + SoftBodyMaterialData *m_material; + btVector3FloatData m_position; + btVector3FloatData m_previousPosition; + btVector3FloatData m_velocity; + btVector3FloatData m_accumulatedForce; + btVector3FloatData m_normal; + float m_inverseMass; + float m_area; + int m_attach; + int m_pad; +}; + +struct SoftBodyLinkData +{ + SoftBodyMaterialData *m_material; + int m_nodeIndices[2]; // Node pointers + float m_restLength; // Rest length + int m_bbending; // Bending link +}; + +struct SoftBodyFaceData +{ + btVector3FloatData m_normal; // Normal + SoftBodyMaterialData *m_material; + int m_nodeIndices[3]; // Node pointers + float m_restArea; // Rest area +}; + +struct SoftBodyTetraData +{ + btVector3FloatData m_c0[4]; // gradients + SoftBodyMaterialData *m_material; + int m_nodeIndices[4]; // Node pointers + float m_restVolume; // Rest volume + float m_c1; // (4*kVST)/(im0+im1+im2+im3) + float m_c2; // m_c1/sum(|g0..3|^2) + int m_pad; +}; + +struct SoftRigidAnchorData +{ + btMatrix3x3FloatData m_c0; // Impulse matrix + btVector3FloatData m_c1; // Relative anchor + btVector3FloatData m_localFrame; // Anchor position in body space + btRigidBodyData *m_rigidBody; + int m_nodeIndex; // Node pointer + float m_c2; // ima*dt +}; + + + +struct SoftBodyConfigData +{ + int m_aeroModel; // Aerodynamic model (default: V_Point) + float m_baumgarte; // Velocities correction factor (Baumgarte) + float m_damping; // Damping coefficient [0,1] + float m_drag; // Drag coefficient [0,+inf] + float m_lift; // Lift coefficient [0,+inf] + float m_pressure; // Pressure coefficient [-inf,+inf] + float m_volume; // Volume conversation coefficient [0,+inf] + float m_dynamicFriction; // Dynamic friction coefficient [0,1] + float m_poseMatch; // Pose matching coefficient [0,1] + float m_rigidContactHardness; // Rigid contacts hardness [0,1] + float m_kineticContactHardness; // Kinetic contacts hardness [0,1] + float m_softContactHardness; // Soft contacts hardness [0,1] + float m_anchorHardness; // Anchors hardness [0,1] + float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only) + float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only) + float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only) + float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) + float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) + float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) + float m_maxVolume; // Maximum volume ratio for pose + float m_timeScale; // Time scale + int m_velocityIterations; // Velocities solver iterations + int m_positionIterations; // Positions solver iterations + int m_driftIterations; // Drift solver iterations + int m_clusterIterations; // Cluster solver iterations + int m_collisionFlags; // Collisions flags +}; + +struct SoftBodyPoseData +{ + btMatrix3x3FloatData m_rot; // Rotation + btMatrix3x3FloatData m_scale; // Scale + btMatrix3x3FloatData m_aqq; // Base scaling + btVector3FloatData m_com; // COM + + btVector3FloatData *m_positions; // Reference positions + float *m_weights; // Weights + int m_numPositions; + int m_numWeigts; + + int m_bvolume; // Is valid + int m_bframe; // Is frame + float m_restVolume; // Rest volume + int m_pad; +}; + +struct SoftBodyClusterData +{ + btTransformFloatData m_framexform; + btMatrix3x3FloatData m_locii; + btMatrix3x3FloatData m_invwi; + btVector3FloatData m_com; + btVector3FloatData m_vimpulses[2]; + btVector3FloatData m_dimpulses[2]; + btVector3FloatData m_lv; + btVector3FloatData m_av; + + btVector3FloatData *m_framerefs; + int *m_nodeIndices; + float *m_masses; + + int m_numFrameRefs; + int m_numNodes; + int m_numMasses; + + float m_idmass; + float m_imass; + int m_nvimpulses; + int m_ndimpulses; + float m_ndamping; + float m_ldamping; + float m_adamping; + float m_matching; + float m_maxSelfCollisionImpulse; + float m_selfCollisionImpulseFactor; + int m_containsAnchor; + int m_collide; + int m_clusterIndex; +}; + + +enum btSoftJointBodyType +{ + BT_JOINT_SOFT_BODY_CLUSTER=1, + BT_JOINT_RIGID_BODY, + BT_JOINT_COLLISION_OBJECT +}; + +struct btSoftBodyJointData +{ + void *m_bodyA; + void *m_bodyB; + btVector3FloatData m_refs[2]; + float m_cfm; + float m_erp; + float m_split; + int m_delete; + btVector3FloatData m_relPosition[2];//linear + int m_bodyAtype; + int m_bodyBtype; + int m_jointType; + int m_pad; +}; + +///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 +struct btSoftBodyFloatData +{ + btCollisionObjectFloatData m_collisionObjectData; + + SoftBodyPoseData *m_pose; + SoftBodyMaterialData **m_materials; + SoftBodyNodeData *m_nodes; + SoftBodyLinkData *m_links; + SoftBodyFaceData *m_faces; + SoftBodyTetraData *m_tetrahedra; + SoftRigidAnchorData *m_anchors; + SoftBodyClusterData *m_clusters; + btSoftBodyJointData *m_joints; + + int m_numMaterials; + int m_numNodes; + int m_numLinks; + int m_numFaces; + int m_numTetrahedra; + int m_numAnchors; + int m_numClusters; + int m_numJoints; + SoftBodyConfigData m_config; +}; + +#endif //BT_SOFTBODY_FLOAT_DATA + diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.cpp b/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.cpp new file mode 100644 index 00000000..36f675a6 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -0,0 +1,1055 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBodyHelpers.cpp by Nathanael Presson + +#include "btSoftBodyInternals.h" +#include +#include +#include "btSoftBodyHelpers.h" +#include "LinearMath/btConvexHull.h" +#include "LinearMath/btConvexHullComputer.h" + + +// +static void drawVertex( btIDebugDraw* idraw, + const btVector3& x,btScalar s,const btVector3& c) +{ + idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); + idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); + idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); +} + +// +static void drawBox( btIDebugDraw* idraw, + const btVector3& mins, + const btVector3& maxs, + const btVector3& color) +{ + const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), + btVector3(maxs.x(),mins.y(),mins.z()), + btVector3(maxs.x(),maxs.y(),mins.z()), + btVector3(mins.x(),maxs.y(),mins.z()), + btVector3(mins.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),maxs.y(),maxs.z()), + btVector3(mins.x(),maxs.y(),maxs.z())}; + idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); + idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); + idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); + idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); + idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); + idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); +} + +// +static void drawTree( btIDebugDraw* idraw, + const btDbvtNode* node, + int depth, + const btVector3& ncolor, + const btVector3& lcolor, + int mindepth, + int maxdepth) +{ + if(node) + { + if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); + } + if(depth>=mindepth) + { + const btScalar scl=(btScalar)(node->isinternal()?1:1); + const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; + const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; + drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); + } + } +} + +// +template +static inline T sum(const btAlignedObjectArray& items) +{ + T v; + if(items.size()) + { + v=items[0]; + for(int i=1,ni=items.size();i +static inline void add(btAlignedObjectArray& items,const Q& value) +{ + for(int i=0,ni=items.size();i +static inline void mul(btAlignedObjectArray& items,const Q& value) +{ + for(int i=0,ni=items.size();i +static inline T average(const btAlignedObjectArray& items) +{ + const btScalar n=(btScalar)(items.size()>0?items.size():1); + return(sum(items)/n); +} + +// +static inline btScalar tetravolume(const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(btDot(a,btCross(b,c))); +} + +// +#if 0 +static btVector3 stresscolor(btScalar stress) +{ + static const btVector3 spectrum[]= { btVector3(1,0,1), + btVector3(0,0,1), + btVector3(0,1,1), + btVector3(0,1,0), + btVector3(1,1,0), + btVector3(1,0,0), + btVector3(1,0,0)}; + static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; + static const btScalar one=1; + stress=btMax(0,btMin(1,stress))*ncolors; + const int sel=(int)stress; + const btScalar frc=stress-sel; + return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); +} +#endif + +// +void btSoftBodyHelpers::Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags) +{ + const btScalar scl=(btScalar)0.1; + const btScalar nscl=scl*5; + const btVector3 lcolor=btVector3(0,0,0); + const btVector3 ncolor=btVector3(1,1,1); + const btVector3 ccolor=btVector3(1,0,0); + int i,j,nj; + + /* Clusters */ + if(0!=(drawflags&fDrawFlags::Clusters)) + { + srand(1806); + for(i=0;im_clusters.size();++i) + { + if(psb->m_clusters[i]->m_collide) + { + btVector3 color( rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX); + color=color.normalized()*0.75; + btAlignedObjectArray vertices; + vertices.resize(psb->m_clusters[i]->m_nodes.size()); + for(j=0,nj=vertices.size();jm_clusters[i]->m_nodes[j]->m_x; + } +#define USE_NEW_CONVEX_HULL_COMPUTER +#ifdef USE_NEW_CONVEX_HULL_COMPUTER + btConvexHullComputer computer; + int stride = sizeof(btVector3); + int count = vertices.size(); + btScalar shrink=0.f; + btScalar shrinkClamp=0.f; + computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp); + for (int i=0;igetNextEdgeOfFace(); + + int v0 = firstEdge->getSourceVertex(); + int v1 = firstEdge->getTargetVertex(); + while (edge!=firstEdge) + { + int v2 = edge->getTargetVertex(); + idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1); + edge = edge->getNextEdgeOfFace(); + v0=v1; + v1=v2; + }; + } +#else + + HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); + HullResult hres; + HullLibrary hlib; + hdsc.mMaxVertices=vertices.size(); + hlib.CreateConvexHull(hdsc,hres); + const btVector3 center=average(hres.m_OutputVertices); + add(hres.m_OutputVertices,-center); + mul(hres.m_OutputVertices,(btScalar)1); + add(hres.m_OutputVertices,center); + for(j=0;j<(int)hres.mNumFaces;++j) + { + const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]}; + idraw->drawTriangle(hres.m_OutputVertices[idx[0]], + hres.m_OutputVertices[idx[1]], + hres.m_OutputVertices[idx[2]], + color,1); + } + hlib.ReleaseResult(hres); +#endif + + } + /* Velocities */ +#if 0 + for(int j=0;jm_clusters[i].m_nodes.size();++j) + { + const btSoftBody::Cluster& c=psb->m_clusters[i]; + const btVector3 r=c.m_nodes[j]->m_x-c.m_com; + const btVector3 v=c.m_lv+btCross(c.m_av,r); + idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0)); + } +#endif + /* Frame */ + // btSoftBody::Cluster& c=*psb->m_clusters[i]; + // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0)); + // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0)); + // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1)); + } + } + else + { + /* Nodes */ + if(0!=(drawflags&fDrawFlags::Nodes)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); + idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); + idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); + } + } + /* Links */ + if(0!=(drawflags&fDrawFlags::Links)) + { + for(i=0;im_links.size();++i) + { + const btSoftBody::Link& l=psb->m_links[i]; + if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); + } + } + /* Normals */ + if(0!=(drawflags&fDrawFlags::Normals)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 d=n.m_n*nscl; + idraw->drawLine(n.m_x,n.m_x+d,ncolor); + idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); + } + } + /* Contacts */ + if(0!=(drawflags&fDrawFlags::Contacts)) + { + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + for(i=0;im_rcontacts.size();++i) + { + const btSoftBody::RContact& c=psb->m_rcontacts[i]; + const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* + (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); + const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); + const btVector3 y=btCross(x,c.m_cti.m_normal).normalized(); + idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); + idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); + idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); + } + } + /* Faces */ + if(0!=(drawflags&fDrawFlags::Faces)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col(0,(btScalar)0.7,0); + for(i=0;im_faces.size();++i) + { + const btSoftBody::Face& f=psb->m_faces[i]; + if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2])/3; + idraw->drawTriangle((x[0]-c)*scl+c, + (x[1]-c)*scl+c, + (x[2]-c)*scl+c, + col,alp); + } + } + /* Tetras */ + if(0!=(drawflags&fDrawFlags::Tetras)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7); + for(int i=0;im_tetras.size();++i) + { + const btSoftBody::Tetra& t=psb->m_tetras[i]; + if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4; + idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp); + idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp); + idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp); + idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp); + } + } + } + /* Anchors */ + if(0!=(drawflags&fDrawFlags::Anchors)) + { + for(i=0;im_anchors.size();++i) + { + const btSoftBody::Anchor& a=psb->m_anchors[i]; + const btVector3 q=a.m_body->getWorldTransform()*a.m_local; + drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); + drawVertex(idraw,q,0.25,btVector3(0,1,0)); + idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); + } + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + if(n.m_im<=0) + { + drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); + } + } + } + + + /* Notes */ + if(0!=(drawflags&fDrawFlags::Notes)) + { + for(i=0;im_notes.size();++i) + { + const btSoftBody::Note& n=psb->m_notes[i]; + btVector3 p=n.m_offset; + for(int j=0;jm_x*n.m_coords[j]; + } + idraw->draw3dText(p,n.m_text); + } + } + /* Node tree */ + if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw); + /* Face tree */ + if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw); + /* Cluster tree */ + if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw); + /* Joints */ + if(0!=(drawflags&fDrawFlags::Joints)) + { + for(i=0;im_joints.size();++i) + { + const btSoftBody::Joint* pj=psb->m_joints[i]; + switch(pj->Type()) + { + case btSoftBody::Joint::eType::Linear: + { + const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj; + const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1]; + idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0)); + idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1)); + drawVertex(idraw,a0,0.25,btVector3(1,1,0)); + drawVertex(idraw,a1,0.25,btVector3(0,1,1)); + } + break; + case btSoftBody::Joint::eType::Angular: + { + //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj; + const btVector3 o0=pj->m_bodies[0].xform().getOrigin(); + const btVector3 o1=pj->m_bodies[1].xform().getOrigin(); + const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1]; + idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0)); + idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0)); + idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1)); + idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1)); + break; + } + default: + { + } + + } + } + } +} + +// +void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool /*stress*/) +{ + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + char text[2048]={0}; + char buff[1024]; + if(masses) + { + sprintf(buff," M(%.2f)",1/n.m_im); + strcat(text,buff); + } + if(areas) + { + sprintf(buff," A(%.2f)",n.m_area); + strcat(text,buff); + } + if(text[0]) idraw->draw3dText(n.m_x,text); + } +} + +// +void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ + drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ + drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ + drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw) +{ + if(psb->m_pose.m_bframe) + { + static const btScalar ascl=10; + static const btScalar nscl=(btScalar)0.1; + const btVector3 com=psb->m_pose.m_com; + const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; + const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); + const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); + const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); + idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); + idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); + idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); + for(int i=0;im_pose.m_pos.size();++i) + { + const btVector3 x=com+trs*psb->m_pose.m_pos[i]; + drawVertex(idraw,x,nscl,btVector3(1,0,1)); + } + } +} + +// +btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, + const btVector3& to, + int res, + int fixeds) +{ + /* Create nodes */ + const int r=res+2; + btVector3* x=new btVector3[r]; + btScalar* m=new btScalar[r]; + int i; + + for(i=0;isetMass(0,0); + if(fixeds&2) psb->setMass(r-1,0); + delete[] x; + delete[] m; + /* Create links */ + for(i=1;iappendLink(i-1,i); + } + /* Finished */ + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags) +{ +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + int iy; + + for(iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + delete[] x; + delete[] m; + /* Create links and faces */ + for(iy=0;iyappendLink(idx,IDX(ix+1,iy)); + if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); + if(mdx&&mdy) + { + if((ix+iy)&1) + { + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); + } + } + else + { + psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); + psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); + } + } + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags, + float* tex_coords) +{ + + /* + * + * corners: + * + * [0][0] corner00 ------- corner01 [resx][0] + * | | + * | | + * [0][resy] corner10 -------- corner11 [resx][resy] + * + * + * + * + * + * + * "fixedgs" map: + * + * corner00 --> +1 + * corner01 --> +2 + * corner10 --> +4 + * corner11 --> +8 + * upper middle --> +16 + * left middle --> +32 + * right middle --> +64 + * lower middle --> +128 + * center --> +256 + * + * + * tex_coords size (resx-1)*(resy-1)*12 + * + * + * + * SINGLE QUAD INTERNALS + * + * 1) btSoftBody's nodes and links, + * diagonal link is optional ("gendiags") + * + * + * node00 ------ node01 + * | . + * | . + * | . + * | . + * | . + * node10 node11 + * + * + * + * 2) Faces: + * two triangles, + * UV Coordinates (hier example for single quad) + * + * (0,1) (0,1) (1,1) + * 1 |\ 3 \-----| 2 + * | \ \ | + * | \ \ | + * | \ \ | + * | \ \ | + * 2 |-----\ 3 \| 1 + * (0,0) (1,0) (1,0) + * + * + * + * + * + * + */ + +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + + int iy; + + for(iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0); + if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0); + if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0); + if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0); + if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0); + delete[] x; + delete[] m; + + + int z = 0; + /* Create links and faces */ + for(iy=0;iyappendLink(node00,node01); + if(mdy) psb->appendLink(node00,node10); + if(mdx&&mdy) + { + psb->appendFace(node00,node10,node11); + if (tex_coords) { + tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1); + tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2); + tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2); + } + psb->appendFace(node11,node01,node00); + if (tex_coords) { + tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2); + tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3); + tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1); + tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0); + tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1); + } + if (gendiags) psb->appendLink(node00,node11); + z += 12; + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id) +{ + + /* + * + * + * node00 --- node01 + * | | + * node10 --- node11 + * + * + * ID map: + * + * node00 s --> 0 + * node00 t --> 1 + * + * node01 s --> 3 + * node01 t --> 1 + * + * node10 s --> 0 + * node10 t --> 2 + * + * node11 s --> 3 + * node11 t --> 2 + * + * + */ + + float tc=0.0f; + if (id == 0) { + tc = (1.0f/((resx-1))*ix); + } + else if (id==1) { + tc = (1.0f/((resy-1))*(resy-1-iy)); + } + else if (id==2) { + tc = (1.0f/((resy-1))*(resy-1-iy-1)); + } + else if (id==3) { + tc = (1.0f/((resx-1))*(ix+1)); + } + return tc; +} +// +btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, + const btVector3& radius, + int res) +{ + struct Hammersley + { + static void Generate(btVector3* x,int n) + { + for(int i=0;i>=1) if(j&1) t+=p; + btScalar w=2*t-1; + btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; + btScalar s=btSqrt(1-w*w); + *x++=btVector3(s*btCos(a),s*btSin(a),w); + } + } + }; + btAlignedObjectArray vtx; + vtx.resize(3+res); + Hammersley::Generate(&vtx[0],vtx.size()); + for(int i=0;i chks; + btAlignedObjectArray vtx; + chks.resize(maxidx*maxidx,false); + vtx.resize(maxidx); + for(i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); + } + } +#undef IDX + psb->appendFace(idx[0],idx[1],idx[2]); + } + + if (randomizeConstraints) + { + psb->randomizeConstraints(); + } + + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, + int nvertices, bool randomizeConstraints) +{ + HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); + HullResult hres; + HullLibrary hlib;/*??*/ + hdsc.mMaxVertices=nvertices; + hlib.CreateConvexHull(hdsc,hres); + btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0],0); + for(int i=0;i<(int)hres.mNumFaces;++i) + { + const int idx[]={ static_cast(hres.m_Indices[i*3+0]), + static_cast(hres.m_Indices[i*3+1]), + static_cast(hres.m_Indices[i*3+2])}; + if(idx[0]appendLink( idx[0],idx[1]); + if(idx[1]appendLink( idx[1],idx[2]); + if(idx[2]appendLink( idx[2],idx[0]); + psb->appendFace(idx[0],idx[1],idx[2]); + } + hlib.ReleaseResult(hres); + if (randomizeConstraints) + { + psb->randomizeConstraints(); + } + return(psb); +} + + + + +static int nextLine(const char* buffer) +{ + int numBytesRead=0; + + while (*buffer != '\n') + { + buffer++; + numBytesRead++; + } + + + if (buffer[0]==0x0a) + { + buffer++; + numBytesRead++; + } + return numBytesRead; +} + +/* Create from TetGen .ele, .face, .node data */ +btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo, + const char* ele, + const char* face, + const char* node, + bool bfacelinks, + bool btetralinks, + bool bfacesfromtetras) +{ +btAlignedObjectArray pos; +int nnode=0; +int ndims=0; +int nattrb=0; +int hasbounds=0; +int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds); +result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds); +node += nextLine(node); + +pos.resize(nnode); +for(int i=0;i>index; +// sn>>x;sn>>y;sn>>z; + node += nextLine(node); + + //for(int j=0;j>a; + + //if(hasbounds) + // sn>>bound; + + pos[index].setX(btScalar(x)); + pos[index].setY(btScalar(y)); + pos[index].setZ(btScalar(z)); + } +btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0); +#if 0 +if(face&&face[0]) + { + int nface=0; + sf>>nface;sf>>hasbounds; + for(int i=0;i>index; + sf>>ni[0];sf>>ni[1];sf>>ni[2]; + sf>>bound; + psb->appendFace(ni[0],ni[1],ni[2]); + if(btetralinks) + { + psb->appendLink(ni[0],ni[1],0,true); + psb->appendLink(ni[1],ni[2],0,true); + psb->appendLink(ni[2],ni[0],0,true); + } + } + } +#endif + +if(ele&&ele[0]) + { + int ntetra=0; + int ncorner=0; + int neattrb=0; + sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb); + ele += nextLine(ele); + + //se>>ntetra;se>>ncorner;se>>neattrb; + for(int i=0;i>index; + //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3]; + sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]); + ele+=nextLine(ele); + //for(int j=0;j>a; + psb->appendTetra(ni[0],ni[1],ni[2],ni[3]); + if(btetralinks) + { + psb->appendLink(ni[0],ni[1],0,true); + psb->appendLink(ni[1],ni[2],0,true); + psb->appendLink(ni[2],ni[0],0,true); + psb->appendLink(ni[0],ni[3],0,true); + psb->appendLink(ni[1],ni[3],0,true); + psb->appendLink(ni[2],ni[3],0,true); + } + } + } +printf("Nodes: %u\r\n",psb->m_nodes.size()); +printf("Links: %u\r\n",psb->m_links.size()); +printf("Faces: %u\r\n",psb->m_faces.size()); +printf("Tetras: %u\r\n",psb->m_tetras.size()); +return(psb); +} + diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.h b/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.h new file mode 100644 index 00000000..620a52fe --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.h @@ -0,0 +1,143 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_HELPERS_H +#define BT_SOFT_BODY_HELPERS_H + +#include "btSoftBody.h" + +// +// Helpers +// + +/* fDrawFlags */ +struct fDrawFlags { enum _ { + Nodes = 0x0001, + Links = 0x0002, + Faces = 0x0004, + Tetras = 0x0008, + Normals = 0x0010, + Contacts = 0x0020, + Anchors = 0x0040, + Notes = 0x0080, + Clusters = 0x0100, + NodeTree = 0x0200, + FaceTree = 0x0400, + ClusterTree = 0x0800, + Joints = 0x1000, + /* presets */ + Std = Links+Faces+Tetras+Anchors+Notes+Joints, + StdTetra = Std-Faces+Tetras +};}; + +struct btSoftBodyHelpers +{ + /* Draw body */ + static void Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags=fDrawFlags::Std); + /* Draw body infos */ + static void DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool stress); + /* Draw node tree */ + static void DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw face tree */ + static void DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw cluster tree */ + static void DrawClusterTree(btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw rigid frame */ + static void DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw); + /* Create a rope */ + static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, + const btVector3& from, + const btVector3& to, + int res, + int fixeds); + /* Create a patch */ + static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags); + /* Create a patch with UV Texture Coordinates */ + static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags, + float* tex_coords=0); + static float CalculateUV(int resx,int resy,int ix,int iy,int id); + /* Create an ellipsoid */ + static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, + const btVector3& center, + const btVector3& radius, + int res); + /* Create from trimesh */ + static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, + const btScalar* vertices, + const int* triangles, + int ntriangles, + bool randomizeConstraints = true); + /* Create from convex-hull */ + static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, + const btVector3* vertices, + int nvertices, + bool randomizeConstraints = true); + + + /* Export TetGen compatible .smesh file */ +// static void ExportAsSMeshFile( btSoftBody* psb, +// const char* filename); + /* Create from TetGen .ele, .face, .node files */ +// static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo, +// const char* ele, +// const char* face, +// const char* node, +// bool bfacelinks, +// bool btetralinks, +// bool bfacesfromtetras); + /* Create from TetGen .ele, .face, .node data */ + static btSoftBody* CreateFromTetGenData( btSoftBodyWorldInfo& worldInfo, + const char* ele, + const char* face, + const char* node, + bool bfacelinks, + bool btetralinks, + bool bfacesfromtetras); + +}; + +#endif //BT_SOFT_BODY_HELPERS_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyInternals.h b/Code/Physics/src/BulletSoftBody/btSoftBodyInternals.h new file mode 100644 index 00000000..19d0543e --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyInternals.h @@ -0,0 +1,908 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_INTERNALS_H +#define _BT_SOFT_BODY_INTERNALS_H + +#include "btSoftBody.h" + + +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btPolarDecomposition.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include //for memset +// +// btSymMatrix +// +template +struct btSymMatrix +{ + btSymMatrix() : dim(0) {} + btSymMatrix(int n,const T& init=T()) { resize(n,init); } + void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); } + int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r store; + int dim; +}; + +// +// btSoftBodyCollisionShape +// +class btSoftBodyCollisionShape : public btConcaveShape +{ +public: + btSoftBody* m_body; + + btSoftBodyCollisionShape(btSoftBody* backptr) + { + m_shapeType = SOFTBODY_SHAPE_PROXYTYPE; + m_body=backptr; + } + + virtual ~btSoftBodyCollisionShape() + { + + } + + void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const + { + //not yet + btAssert(0); + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */ + const btVector3 mins=m_body->m_bounds[0]; + const btVector3 maxs=m_body->m_bounds[1]; + const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),maxs.y(),maxs.z()), + t*btVector3(mins.x(),maxs.y(),maxs.z())}; + aabbMin=aabbMax=crns[0]; + for(int i=1;i<8;++i) + { + aabbMin.setMin(crns[i]); + aabbMax.setMax(crns[i]); + } + } + + + virtual void setLocalScaling(const btVector3& /*scaling*/) + { + ///na + } + virtual const btVector3& getLocalScaling() const + { + static const btVector3 dummy(1,1,1); + return dummy; + } + virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const + { + ///not yet + btAssert(0); + } + virtual const char* getName()const + { + return "SoftBody"; + } + +}; + +// +// btSoftClusterCollisionShape +// +class btSoftClusterCollisionShape : public btConvexInternalShape +{ +public: + const btSoftBody::Cluster* m_cluster; + + btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btSoftBody::Node* const * n=&m_cluster->m_nodes[0]; + btScalar d=btDot(vec,n[0]->m_x); + int j=0; + for(int i=1,ni=m_cluster->m_nodes.size();im_x); + if(k>d) { d=k;j=i; } + } + return(n[j]->m_x); + } + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + return(localGetSupportingVertex(vec)); + } + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + {} + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const + {} + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + {} + + virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } + + //debugging + virtual const char* getName()const {return "SOFTCLUSTER";} + + virtual void setMargin(btScalar margin) + { + btConvexInternalShape::setMargin(margin); + } + virtual btScalar getMargin() const + { + return getMargin(); + } +}; + +// +// Inline's +// + +// +template +static inline void ZeroInitialize(T& value) +{ + memset(&value,0,sizeof(T)); +} +// +template +static inline bool CompLess(const T& a,const T& b) +{ return(a +static inline bool CompGreater(const T& a,const T& b) +{ return(a>b); } +// +template +static inline T Lerp(const T& a,const T& b,btScalar t) +{ return(a+(b-a)*t); } +// +template +static inline T InvLerp(const T& a,const T& b,btScalar t) +{ return((b+a*t-b*t)/(a*b)); } +// +static inline btMatrix3x3 Lerp( const btMatrix3x3& a, + const btMatrix3x3& b, + btScalar t) +{ + btMatrix3x3 r; + r[0]=Lerp(a[0],b[0],t); + r[1]=Lerp(a[1],b[1],t); + r[2]=Lerp(a[2],b[2],t); + return(r); +} +// +static inline btVector3 Clamp(const btVector3& v,btScalar maxlength) +{ + const btScalar sql=v.length2(); + if(sql>(maxlength*maxlength)) + return((v*maxlength)/btSqrt(sql)); + else + return(v); +} +// +template +static inline T Clamp(const T& x,const T& l,const T& h) +{ return(xh?h:x); } +// +template +static inline T Sq(const T& x) +{ return(x*x); } +// +template +static inline T Cube(const T& x) +{ return(x*x*x); } +// +template +static inline T Sign(const T& x) +{ return((T)(x<0?-1:+1)); } +// +template +static inline bool SameSign(const T& x,const T& y) +{ return((x*y)>0); } +// +static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y) +{ + const btVector3 d=x-y; + return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); +} +// +static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) +{ + const btScalar xx=a.x()*a.x(); + const btScalar yy=a.y()*a.y(); + const btScalar zz=a.z()*a.z(); + const btScalar xy=a.x()*a.y(); + const btScalar yz=a.y()*a.z(); + const btScalar zx=a.z()*a.x(); + btMatrix3x3 m; + m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx); + m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz); + m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s); + return(m); +} +// +static inline btMatrix3x3 Cross(const btVector3& v) +{ + btMatrix3x3 m; + m[0]=btVector3(0,-v.z(),+v.y()); + m[1]=btVector3(+v.z(),0,-v.x()); + m[2]=btVector3(-v.y(),+v.x(),0); + return(m); +} +// +static inline btMatrix3x3 Diagonal(btScalar x) +{ + btMatrix3x3 m; + m[0]=btVector3(x,0,0); + m[1]=btVector3(0,x,0); + m[2]=btVector3(0,0,x); + return(m); +} +// +static inline btMatrix3x3 Add(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]+b[i]; + return(r); +} +// +static inline btMatrix3x3 Sub(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]-b[i]; + return(r); +} +// +static inline btMatrix3x3 Mul(const btMatrix3x3& a, + btScalar b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]*b; + return(r); +} +// +static inline void Orthogonalize(btMatrix3x3& m) +{ + m[2]=btCross(m[0],m[1]).normalized(); + m[1]=btCross(m[2],m[0]).normalized(); + m[0]=btCross(m[1],m[2]).normalized(); +} +// +static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r) +{ + const btMatrix3x3 cr=Cross(r); + return(Sub(Diagonal(im),cr*iwi*cr)); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar dt, + btScalar ima, + btScalar imb, + const btMatrix3x3& iwi, + const btVector3& r) +{ + return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse()); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra, + btScalar imb,const btMatrix3x3& iib,const btVector3& rb) +{ + return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); +} + +// +static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, + const btMatrix3x3& iib) +{ + return(Add(iia,iib).inverse()); +} + +// +static inline btVector3 ProjectOnAxis( const btVector3& v, + const btVector3& a) +{ + return(a*btDot(v,a)); +} +// +static inline btVector3 ProjectOnPlane( const btVector3& v, + const btVector3& a) +{ + return(v-ProjectOnAxis(v,a)); +} + +// +static inline void ProjectOrigin( const btVector3& a, + const btVector3& b, + btVector3& prj, + btScalar& sqd) +{ + const btVector3 d=b-a; + const btScalar m2=d.length2(); + if(m2>SIMD_EPSILON) + { + const btScalar t=Clamp(-btDot(a,d)/m2,0,1); + const btVector3 p=a+d*t; + const btScalar l2=p.length2(); + if(l2SIMD_EPSILON) + { + const btVector3 n=q/btSqrt(m2); + const btScalar k=btDot(a,n); + const btScalar k2=k*k; + if(k20)&& + (btDot(btCross(b-p,c-p),q)>0)&& + (btDot(btCross(c-p,a-p),q)>0)) + { + prj=p; + sqd=k2; + } + else + { + ProjectOrigin(a,b,prj,sqd); + ProjectOrigin(b,c,prj,sqd); + ProjectOrigin(c,a,prj,sqd); + } + } + } +} + +// +template +static inline T BaryEval( const T& a, + const T& b, + const T& c, + const btVector3& coord) +{ + return(a*coord.x()+b*coord.y()+c*coord.z()); +} +// +static inline btVector3 BaryCoord( const btVector3& a, + const btVector3& b, + const btVector3& c, + const btVector3& p) +{ + const btScalar w[]={ btCross(a-p,b-p).length(), + btCross(b-p,c-p).length(), + btCross(c-p,a-p).length()}; + const btScalar isum=1/(w[0]+w[1]+w[2]); + return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum)); +} + +// +static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, + const btVector3& a, + const btVector3& b, + const btScalar accuracy, + const int maxiterations=256) +{ + btScalar span[2]={0,1}; + btScalar values[2]={fn->Eval(a),fn->Eval(b)}; + if(values[0]>values[1]) + { + btSwap(span[0],span[1]); + btSwap(values[0],values[1]); + } + if(values[0]>-accuracy) return(-1); + if(values[1]<+accuracy) return(-1); + for(int i=0;iEval(Lerp(a,b,t)); + if((t<=0)||(t>=1)) break; + if(btFabs(v)SIMD_EPSILON) + return(v/l); + else + return(btVector3(0,0,0)); +} + +// +static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f, + btScalar margin) +{ + const btVector3* pts[]={ &f.m_n[0]->m_x, + &f.m_n[1]->m_x, + &f.m_n[2]->m_x}; + btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3); + vol.Expand(btVector3(margin,margin,margin)); + return(vol); +} + +// +static inline btVector3 CenterOf( const btSoftBody::Face& f) +{ + return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3); +} + +// +static inline btScalar AreaOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 cr=btCross(a,b); + const btScalar area=cr.length(); + return(area); +} + +// +static inline btScalar VolumeOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(btDot(a,btCross(b,c))); +} + +// +static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, + const btVector3& x, + btSoftBody::sMedium& medium) +{ + medium.m_velocity = btVector3(0,0,0); + medium.m_pressure = 0; + medium.m_density = wfi->air_density; + if(wfi->water_density>0) + { + const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset); + if(depth>0) + { + medium.m_density = wfi->water_density; + medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); + } + } +} + +// +static inline void ApplyClampedForce( btSoftBody::Node& n, + const btVector3& f, + btScalar dt) +{ + const btScalar dtim=dt*n.m_im; + if((f*dtim).length2()>n.m_v.length2()) + {/* Clamp */ + n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim; + } + else + {/* Apply */ + n.m_f+=f; + } +} + +// +static inline int MatchEdge( const btSoftBody::Node* a, + const btSoftBody::Node* b, + const btSoftBody::Node* ma, + const btSoftBody::Node* mb) +{ + if((a==ma)&&(b==mb)) return(0); + if((a==mb)&&(b==ma)) return(1); + return(-1); +} + +// +// btEigen : Extract eigen system, +// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html +// outputs are NOT sorted. +// +struct btEigen +{ + static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) + { + static const int maxiterations=16; + static const btScalar accuracy=(btScalar)0.0001; + btMatrix3x3& v=*vectors; + int iterations=0; + vectors->setIdentity(); + do { + int p=0,q=1; + if(btFabs(a[p][q])accuracy) + { + const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]); + const btScalar z=btFabs(w); + const btScalar t=w/(z*(btSqrt(1+w*w)+z)); + if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ + { + const btScalar c=1/btSqrt(t*t+1); + const btScalar s=c*t; + mulPQ(a,c,s,p,q); + mulTPQ(a,c,s,p,q); + mulPQ(v,c,s,p,q); + } else break; + } else break; + } while((++iterations)data; + btSoftClusterCollisionShape cshape(cluster); + + const btConvexShape* rshape=(const btConvexShape*)m_colObjWrap->getCollisionShape(); + + ///don't collide an anchored cluster with a static/kinematic object + if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor) + return; + + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), + rshape,m_colObjWrap->getWorldTransform(), + btVector3(1,0,0),res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cluster,m_colObjWrap->getCollisionObject(),joint))//prb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;psb->m_joints.push_back(pj); + if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject()) + { + pj->m_erp *= psb->m_cfg.kSKHR_CL; + pj->m_split *= psb->m_cfg.kSK_SPLT_CL; + } + else + { + pj->m_erp *= psb->m_cfg.kSRHR_CL; + pj->m_split *= psb->m_cfg.kSR_SPLT_CL; + } + } + } + } + void ProcessColObj(btSoftBody* ps,const btCollisionObjectWrapper* colObWrap) + { + psb = ps; + m_colObjWrap = colObWrap; + idt = ps->m_sst.isdt; + m_margin = m_colObjWrap->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin(); + ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful. + friction = btMin(psb->m_cfg.kDF,m_colObjWrap->getCollisionObject()->getFriction()); + btVector3 mins; + btVector3 maxs; + + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(),mins,maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(1,1,1)*m_margin); + ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this); + } + }; + // + // CollideCL_SS + // + struct CollideCL_SS : ClusterBase + { + btSoftBody* bodies[2]; + void Process(const btDbvtNode* la,const btDbvtNode* lb) + { + btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data; + btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; + + + bool connected=false; + if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size())) + { + connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex]; + } + + if (!connected) + { + btSoftClusterCollisionShape csa(cla); + btSoftClusterCollisionShape csb(clb); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(), + &csb,btTransform::getIdentity(), + cla->m_com-clb->m_com,res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cla,clb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;bodies[0]->m_joints.push_back(pj); + pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL); + pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2; + } + } + } else + { + static int count=0; + count++; + //printf("count=%d\n",count); + + } + } + void ProcessSoftSoft(btSoftBody* psa,btSoftBody* psb) + { + idt = psa->m_sst.isdt; + //m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2; + m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin()); + friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF); + bodies[0] = psa; + bodies[1] = psb; + psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); + } + }; + // + // CollideSDF_RS + // + struct CollideSDF_RS : btDbvt::ICollide + { + void Process(const btDbvtNode* leaf) + { + btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; + DoNode(*node); + } + void DoNode(btSoftBody::Node& n) const + { + const btScalar m=n.m_im>0?dynmargin:stamargin; + btSoftBody::RContact c; + + if( (!n.m_battach)&& + psb->checkContact(m_colObj1Wrap,n.m_x,m,c.m_cti)) + { + const btScalar ima=n.m_im; + const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f; + const btScalar ms=ima+imb; + if(ms>0) + { + const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform(); + static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0); + const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic; + const btVector3 ra=n.m_x-wtr.getOrigin(); + const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0); + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=vb-va; + const btScalar dn=btDot(vr,c.m_cti.m_normal); + const btVector3 fv=vr-c.m_cti.m_normal*dn; + const btScalar fc=psb->m_cfg.kDF*m_colObj1Wrap->getCollisionObject()->getFriction(); + c.m_node = &n; + c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra); + c.m_c1 = ra; + c.m_c2 = ima*psb->m_sst.sdt; + c.m_c3 = fv.length2()<(dn*fc*dn*fc)?0:1-fc; + c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; + psb->m_rcontacts.push_back(c); + if (m_rigidBody) + m_rigidBody->activate(); + } + } + } + btSoftBody* psb; + const btCollisionObjectWrapper* m_colObj1Wrap; + btRigidBody* m_rigidBody; + btScalar dynmargin; + btScalar stamargin; + }; + // + // CollideVF_SS + // + struct CollideVF_SS : btDbvt::ICollide + { + void Process(const btDbvtNode* lnode, + const btDbvtNode* lface) + { + btSoftBody::Node* node=(btSoftBody::Node*)lnode->data; + btSoftBody::Face* face=(btSoftBody::Face*)lface->data; + btVector3 o=node->m_x; + btVector3 p; + btScalar d=SIMD_INFINITY; + ProjectOrigin( face->m_n[0]->m_x-o, + face->m_n[1]->m_x-o, + face->m_n[2]->m_x-o, + p,d); + const btScalar m=mrg+(o-node->m_q).length()*2; + if(d<(m*m)) + { + const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]}; + const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o); + const btScalar ma=node->m_im; + btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w); + if( (n[0]->m_im<=0)|| + (n[1]->m_im<=0)|| + (n[2]->m_im<=0)) + { + mb=0; + } + const btScalar ms=ma+mb; + if(ms>0) + { + btSoftBody::SContact c; + c.m_normal = p/-btSqrt(d); + c.m_margin = m; + c.m_node = node; + c.m_face = face; + c.m_weights = w; + c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF); + c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR; + c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR; + psb[0]->m_scontacts.push_back(c); + } + } + } + btSoftBody* psb[2]; + btScalar mrg; + }; +}; + +#endif //_BT_SOFT_BODY_INTERNALS_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp new file mode 100644 index 00000000..f5a67f6d --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp @@ -0,0 +1,134 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftBodyRigidBodyCollisionConfiguration.h" +#include "btSoftRigidCollisionAlgorithm.h" +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "btSoftSoftCollisionAlgorithm.h" + +#include "LinearMath/btPoolAllocator.h" + +#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1 + +btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +:btDefaultCollisionConfiguration(constructionInfo) +{ + void* mem; + + mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16); + m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + m_swappedSoftRigidConvexCreateFunc->m_swapped=true; + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc; + m_swappedSoftRigidConcaveCreateFunc->m_swapped=true; +#endif + + //replace pool by a new one, with potential larger size + + if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool) + { + int curElemSize = m_collisionAlgorithmPool->getElementSize(); + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + + + int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm); + int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm); + int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm); + + int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); + + if (collisionAlgorithmMaxElementSize > curElemSize) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + } + +} + +btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() +{ + m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softSoftCreateFunc); + + m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConvexCreateFunc); + + m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConvexCreateFunc); + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConcaveCreateFunc); + + m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConcaveCreateFunc); +#endif +} + +///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation +btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + ///try to handle the softbody interactions first + + if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE)) + { + return m_softSoftCreateFunc; + } + + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_softRigidConvexCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConvexCreateFunc; + } + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_softRigidConcaveCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConcaveCreateFunc; + } +#endif + + ///fallback to the regular rigid collision shape + return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); +} diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h new file mode 100644 index 00000000..21addcfe --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION +#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +class btVoronoiSimplexSolver; +class btGjkEpaPenetrationDepthSolver; + + +///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration +class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration +{ + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; + +public: + + btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btSoftBodyRigidBodyCollisionConfiguration(); + + ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + +}; + +#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/Code/Physics/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h new file mode 100644 index 00000000..c4733d64 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h @@ -0,0 +1,165 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H +#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H + + +class btVertexBufferDescriptor +{ +public: + enum BufferTypes + { + CPU_BUFFER, + DX11_BUFFER, + OPENGL_BUFFER + }; + +protected: + + bool m_hasVertexPositions; + bool m_hasNormals; + + int m_vertexOffset; + int m_vertexStride; + + int m_normalOffset; + int m_normalStride; + +public: + btVertexBufferDescriptor() + { + m_hasVertexPositions = false; + m_hasNormals = false; + m_vertexOffset = 0; + m_vertexStride = 0; + m_normalOffset = 0; + m_normalStride = 0; + } + + virtual ~btVertexBufferDescriptor() + { + + } + + virtual bool hasVertexPositions() const + { + return m_hasVertexPositions; + } + + virtual bool hasNormals() const + { + return m_hasNormals; + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const = 0; + + /** + * Return the vertex offset in floats from the base pointer. + */ + virtual int getVertexOffset() const + { + return m_vertexOffset; + } + + /** + * Return the vertex stride in number of floats between vertices. + */ + virtual int getVertexStride() const + { + return m_vertexStride; + } + + /** + * Return the vertex offset in floats from the base pointer. + */ + virtual int getNormalOffset() const + { + return m_normalOffset; + } + + /** + * Return the vertex stride in number of floats between vertices. + */ + virtual int getNormalStride() const + { + return m_normalStride; + } +}; + + +class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor +{ +protected: + float *m_basePointer; + +public: + /** + * vertexBasePointer is pointer to beginning of the buffer. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride ) + { + m_basePointer = basePointer; + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + } + + /** + * vertexBasePointer is pointer to beginning of the buffer. + * vertexOffset is the offset in floats to the first vertex. + * vertexStride is the stride in floats between vertices. + */ + btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) + { + m_basePointer = basePointer; + + m_vertexOffset = vertexOffset; + m_vertexStride = vertexStride; + m_hasVertexPositions = true; + + m_normalOffset = normalOffset; + m_normalStride = normalStride; + m_hasNormals = true; + } + + virtual ~btCPUVertexBufferDescriptor() + { + + } + + /** + * Return the type of the vertex buffer descriptor. + */ + virtual BufferTypes getBufferType() const + { + return CPU_BUFFER; + } + + /** + * Return the base pointer in memory to the first vertex. + */ + virtual float *getBasePointer() const + { + return m_basePointer; + } +}; + +#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodySolvers.h b/Code/Physics/src/BulletSoftBody/btSoftBodySolvers.h new file mode 100644 index 00000000..6947bc27 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftBodySolvers.h @@ -0,0 +1,154 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_BODY_SOLVERS_H +#define BT_SOFT_BODY_SOLVERS_H + +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" + + +class btSoftBodyTriangleData; +class btSoftBodyLinkData; +class btSoftBodyVertexData; +class btVertexBufferDescriptor; +class btCollisionObject; +class btSoftBody; + + +class btSoftBodySolver +{ +public: + enum SolverTypes + { + DEFAULT_SOLVER, + CPU_SOLVER, + CL_SOLVER, + CL_SIMD_SOLVER, + DX_SOLVER, + DX_SIMD_SOLVER + }; + + +protected: + int m_numberOfPositionIterations; + int m_numberOfVelocityIterations; + // Simulation timescale + float m_timeScale; + +public: + btSoftBodySolver() : + m_numberOfPositionIterations( 10 ), + m_timeScale( 1 ) + { + m_numberOfVelocityIterations = 0; + m_numberOfPositionIterations = 5; + } + + virtual ~btSoftBodySolver() + { + } + + /** + * Return the type of the solver. + */ + virtual SolverTypes getSolverType() const = 0; + + + /** Ensure that this solver is initialized. */ + virtual bool checkInitialized() = 0; + + /** Optimize soft bodies in this solver. */ + virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false) = 0; + + /** Copy necessary data back to the original soft body source objects. */ + virtual void copyBackToSoftBodies(bool bMove = true) = 0; + + /** Predict motion of soft bodies into next timestep */ + virtual void predictMotion( float solverdt ) = 0; + + /** Solve constraints for a set of soft bodies */ + virtual void solveConstraints( float solverdt ) = 0; + + /** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */ + virtual void updateSoftBodies() = 0; + + /** Process a collision between one of the world's soft bodies and another collision object */ + virtual void processCollision( btSoftBody *, const struct btCollisionObjectWrapper* ) = 0; + + /** Process a collision between two soft bodies */ + virtual void processCollision( btSoftBody*, btSoftBody* ) = 0; + + /** Set the number of velocity constraint solver iterations this solver uses. */ + virtual void setNumberOfPositionIterations( int iterations ) + { + m_numberOfPositionIterations = iterations; + } + + /** Get the number of velocity constraint solver iterations this solver uses. */ + virtual int getNumberOfPositionIterations() + { + return m_numberOfPositionIterations; + } + + /** Set the number of velocity constraint solver iterations this solver uses. */ + virtual void setNumberOfVelocityIterations( int iterations ) + { + m_numberOfVelocityIterations = iterations; + } + + /** Get the number of velocity constraint solver iterations this solver uses. */ + virtual int getNumberOfVelocityIterations() + { + return m_numberOfVelocityIterations; + } + + /** Return the timescale that the simulation is using */ + float getTimeScale() + { + return m_timeScale; + } + +#if 0 + /** + * Add a collision object to be used by the indicated softbody. + */ + virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject ) = 0; +#endif +}; + +/** + * Class to manage movement of data from a solver to a given target. + * This version is abstract. Subclasses will have custom pairings for different combinations. + */ +class btSoftBodySolverOutput +{ +protected: + +public: + btSoftBodySolverOutput() + { + } + + virtual ~btSoftBodySolverOutput() + { + } + + + /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ + virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) = 0; +}; + + +#endif // #ifndef BT_SOFT_BODY_SOLVERS_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp new file mode 100644 index 00000000..01c148a2 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftRigidCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btSoftBody.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +///TODO: include all the shapes that the softbody can collide with +///alternatively, implement special case collision algorithms (just like for rigid collision shapes) + +//#include + +btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* , bool isSwapped) +: btCollisionAlgorithm(ci), +//m_ownManifold(false), +//m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ +} + + +btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() +{ + + //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); + + /*if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } + */ + +} + + +#include + +void btSoftRigidCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + //printf("btSoftRigidCollisionAlgorithm\n"); +// const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap; +// const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap; + btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject(); + const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped? body0Wrap : body1Wrap; + + if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject())==softBody->m_collisionDisabledObjects.size()) + { + softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap); + } + + +} + +btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + + diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h new file mode 100644 index 00000000..a9b513e3 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_RIGID_COLLISION_ALGORITHM_H +#define BT_SOFT_RIGID_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" +class btSoftBody; + +/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody +class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm +{ + // bool m_ownManifold; + // btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody; + btCollisionObject* m_rigidCollisionObject; + + ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean + bool m_isSwapped; + +public: + + btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0,const btCollisionObjectWrapper* col1Wrap, bool isSwapped); + + virtual ~btSoftRigidCollisionAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false); + } else + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true); + } + } + }; + +}; + +#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H + + diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp new file mode 100644 index 00000000..5f359354 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -0,0 +1,367 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSoftRigidDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//softbody & helpers +#include "btSoftBody.h" +#include "btSoftBodyHelpers.h" +#include "btSoftBodySolvers.h" +#include "btDefaultSoftBodySolver.h" +#include "LinearMath/btSerializer.h" + + +btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld( + btDispatcher* dispatcher, + btBroadphaseInterface* pairCache, + btConstraintSolver* constraintSolver, + btCollisionConfiguration* collisionConfiguration, + btSoftBodySolver *softBodySolver ) : + btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration), + m_softBodySolver( softBodySolver ), + m_ownsSolver(false) +{ + if( !m_softBodySolver ) + { + void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16); + m_softBodySolver = new(ptr) btDefaultSoftBodySolver(); + m_ownsSolver = true; + } + + m_drawFlags = fDrawFlags::Std; + m_drawNodeTree = true; + m_drawFaceTree = false; + m_drawClusterTree = false; + m_sbi.m_broadphase = pairCache; + m_sbi.m_dispatcher = dispatcher; + m_sbi.m_sparsesdf.Initialize(); + m_sbi.m_sparsesdf.Reset(); + + m_sbi.air_density = (btScalar)1.2; + m_sbi.water_density = 0; + m_sbi.water_offset = 0; + m_sbi.water_normal = btVector3(0,0,0); + m_sbi.m_gravity.setValue(0,-10,0); + + m_sbi.m_sparsesdf.Initialize(); + + +} + +btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() +{ + if (m_ownsSolver) + { + m_softBodySolver->~btSoftBodySolver(); + btAlignedFree(m_softBodySolver); + } +} + +void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep ); + { + BT_PROFILE("predictUnconstraintMotionSoftBody"); + m_softBodySolver->predictMotion( timeStep ); + } +} + +void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep ) +{ + + // Let the solver grab the soft bodies and if necessary optimize for it + m_softBodySolver->optimize( getSoftBodyArray() ); + + if( !m_softBodySolver->checkInitialized() ) + { + btAssert( "Solver initialization failed\n" ); + } + + btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); + + ///solve soft bodies constraints + solveSoftBodiesConstraints( timeStep ); + + //self collisions + for ( int i=0;idefaultCollisionHandler(psb); + } + + ///update soft bodies + m_softBodySolver->updateSoftBodies( ); + + // End solver-wise simulation step + // /////////////////////////////// + +} + +void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep ) +{ + BT_PROFILE("solveSoftConstraints"); + + if(m_softBodies.size()) + { + btSoftBody::solveClusters(m_softBodies); + } + + // Solve constraints solver-wise + m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() ); + +} + +void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask) +{ + m_softBodies.push_back(body); + + // Set the soft body solver that will deal with this body + // to be the world's solver + body->setSoftBodySolver( m_softBodySolver ); + + btCollisionWorld::addCollisionObject(body, + collisionFilterGroup, + collisionFilterMask); + +} + +void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body) +{ + m_softBodies.remove(body); + + btCollisionWorld::removeCollisionObject(body); +} + +void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + btSoftBody* body = btSoftBody::upcast(collisionObject); + if (body) + removeSoftBody(body); + else + btDiscreteDynamicsWorld::removeCollisionObject(collisionObject); +} + +void btSoftRigidDynamicsWorld::debugDrawWorld() +{ + btDiscreteDynamicsWorld::debugDrawWorld(); + + if (getDebugDrawer()) + { + int i; + for ( i=0;im_softBodies.size();i++) + { + btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); + btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); + } + + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); + if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); + if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); + } + } + } +} + + + + +struct btSoftSingleRayCallback : public btBroadphaseRayCallback +{ + btVector3 m_rayFromWorld; + btVector3 m_rayToWorld; + btTransform m_rayFromTrans; + btTransform m_rayToTrans; + btVector3 m_hitNormal; + + const btSoftRigidDynamicsWorld* m_world; + btCollisionWorld::RayResultCallback& m_resultCallback; + + btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_world(world), + m_resultCallback(resultCallback) + { + m_rayFromTrans.setIdentity(); + m_rayFromTrans.setOrigin(m_rayFromWorld); + m_rayToTrans.setIdentity(); + m_rayToTrans.setOrigin(m_rayToWorld); + + btVector3 rayDir = (rayToWorld-rayFromWorld); + + rayDir.normalize (); + ///what about division by zero? --> just set rayDirection[i] to INF/1e30 + m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; + m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; + m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; + m_signs[0] = m_rayDirectionInverse[0] < 0.0; + m_signs[1] = m_rayDirectionInverse[1] < 0.0; + m_signs[2] = m_rayDirectionInverse[2] < 0.0; + + m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); + + } + + + + virtual bool process(const btBroadphaseProxy* proxy) + { + ///terminate further ray tests, once the closestHitFraction reached zero + if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) + return false; + + btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; + + //only perform raycast if filterMask matches + if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) + { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; +#if 0 +#ifdef RECALCULATE_AABB + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); +#else + //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); + const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; + const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; +#endif +#endif + //btScalar hitLambda = m_resultCallback.m_closestHitFraction; + //culling already done by broadphase + //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) + { + m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + m_resultCallback); + } + } + return true; + } +}; + +void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +{ + BT_PROFILE("rayTest"); + /// use the broadphase to accelerate the search for objects, based on their aabb + /// and for each object with ray-aabb overlap, perform an exact ray test + btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); + +#ifndef USE_BRUTEFORCE_RAYBROADPHASE + m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); +#else + for (int i=0;igetNumCollisionObjects();i++) + { + rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); + } +#endif //USE_BRUTEFORCE_RAYBROADPHASE + +} + + +void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback) +{ + if (collisionShape->isSoftBody()) { + btSoftBody* softBody = btSoftBody::upcast(collisionObject); + if (softBody) { + btSoftBody::sRayCast softResult; + if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) + { + + if (softResult.fraction<= resultCallback.m_closestHitFraction) + { + + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = 0; + shapeInfo.m_triangleIndex = softResult.index; + // get the normal + btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); + btVector3 normal=-rayDir; + normal.normalize(); + + if (softResult.feature == btSoftBody::eFeature::Face) + { + normal = softBody->m_faces[softResult.index].m_normal; + if (normal.dot(rayDir) > 0) { + // normal always point toward origin of the ray + normal = -normal; + } + } + + btCollisionWorld::LocalRayResult rayResult + (collisionObject, + &shapeInfo, + normal, + softResult.fraction); + bool normalInWorldSpace = true; + resultCallback.addSingleResult(rayResult,normalInWorldSpace); + } + } + } + } + else { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback); + } +} + + +void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer) +{ + int i; + //serialize all collision objects + for (i=0;igetInternalType() & btCollisionObject::CO_SOFT_BODY) + { + int len = colObj->calculateSerializeBufferSize(); + btChunk* chunk = serializer->allocate(len,1); + const char* structType = colObj->serialize(chunk->m_oldPtr, serializer); + serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj); + } + } + +} + +void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer) +{ + + serializer->startSerialization(); + + serializeDynamicsWorldInfo( serializer); + + serializeSoftBodies(serializer); + + serializeRigidBodies(serializer); + + serializeCollisionObjects(serializer); + + serializer->finishSerialization(); +} + + diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.h new file mode 100644 index 00000000..3e0efafd --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H +#define BT_SOFT_RIGID_DYNAMICS_WORLD_H + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "btSoftBody.h" + +typedef btAlignedObjectArray btSoftBodyArray; + +class btSoftBodySolver; + +class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld +{ + + btSoftBodyArray m_softBodies; + int m_drawFlags; + bool m_drawNodeTree; + bool m_drawFaceTree; + bool m_drawClusterTree; + btSoftBodyWorldInfo m_sbi; + ///Solver classes that encapsulate multiple soft bodies for solving + btSoftBodySolver *m_softBodySolver; + bool m_ownsSolver; + +protected: + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void solveSoftBodiesConstraints( btScalar timeStep ); + + void serializeSoftBodies(btSerializer* serializer); + +public: + + btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 ); + + virtual ~btSoftRigidDynamicsWorld(); + + virtual void debugDrawWorld(); + + void addSoftBody(btSoftBody* body,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + + void removeSoftBody(btSoftBody* body); + + ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject + virtual void removeCollisionObject(btCollisionObject* collisionObject); + + int getDrawFlags() const { return(m_drawFlags); } + void setDrawFlags(int f) { m_drawFlags=f; } + + btSoftBodyWorldInfo& getWorldInfo() + { + return m_sbi; + } + const btSoftBodyWorldInfo& getWorldInfo() const + { + return m_sbi; + } + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SOFT_RIGID_DYNAMICS_WORLD; + } + + btSoftBodyArray& getSoftBodyArray() + { + return m_softBodies; + } + + const btSoftBodyArray& getSoftBodyArray() const + { + return m_softBodies; + } + + + virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback); + + virtual void serialize(btSerializer* serializer); + +}; + +#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp new file mode 100644 index 00000000..72043e69 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftSoftCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "btSoftBody.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* /*obj0*/,const btCollisionObjectWrapper* /*obj1*/) +: btCollisionAlgorithm(ci) +//m_ownManifold(false), +//m_manifoldPtr(mf) +{ +} + +btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm() +{ +} + +void btSoftSoftCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject(); + btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject(); + soft0->getSoftBodySolver()->processCollision(soft0, soft1); +} + +btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h new file mode 100644 index 00000000..43b1439c --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFT_SOFT_COLLISION_ALGORITHM_H +#define BT_SOFT_SOFT_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; +class btSoftBody; + +///collision detection between two btSoftBody shapes +class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody0; + btSoftBody* m_softBody1; + + +public: + btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btSoftSoftCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + int bbsize = sizeof(btSoftSoftCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0Wrap,body1Wrap); + } + }; + +}; + +#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H + + diff --git a/Code/Physics/src/BulletSoftBody/btSparseSDF.h b/Code/Physics/src/BulletSoftBody/btSparseSDF.h new file mode 100644 index 00000000..bcf0c798 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/btSparseSDF.h @@ -0,0 +1,319 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSparseSdf implementation by Nathanael Presson + +#ifndef BT_SPARSE_SDF_H +#define BT_SPARSE_SDF_H + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +// Modified Paul Hsieh hash +template +unsigned int HsiehHash(const void* pdata) +{ + const unsigned short* data=(const unsigned short*)pdata; + unsigned hash=DWORDLEN<<2,tmp; + for(int i=0;i>11; + } + hash^=hash<<3;hash+=hash>>5; + hash^=hash<<4;hash+=hash>>17; + hash^=hash<<25;hash+=hash>>6; + return(hash); +} + +template +struct btSparseSdf +{ + // + // Inner types + // + struct IntFrac + { + int b; + int i; + btScalar f; + }; + struct Cell + { + btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]; + int c[3]; + int puid; + unsigned hash; + const btCollisionShape* pclient; + Cell* next; + }; + // + // Fields + // + + btAlignedObjectArray cells; + btScalar voxelsz; + int puid; + int ncells; + int m_clampCells; + int nprobes; + int nqueries; + + // + // Methods + // + + // + void Initialize(int hashsize=2383, int clampCells = 256*1024) + { + //avoid a crash due to running out of memory, so clamp the maximum number of cells allocated + //if this limit is reached, the SDF is reset (at the cost of some performance during the reset) + m_clampCells = clampCells; + cells.resize(hashsize,0); + Reset(); + } + // + void Reset() + { + for(int i=0,ni=cells.size();inext; + delete pc; + pc=pn; + } + } + voxelsz =0.25; + puid =0; + ncells =0; + nprobes =1; + nqueries =1; + } + // + void GarbageCollect(int lifetime=256) + { + const int life=puid-lifetime; + for(int i=0;inext; + if(pc->puidnext=pn; else root=pn; + delete pc;pc=pp;--ncells; + } + pp=pc;pc=pn; + } + } + //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries); + nqueries=1; + nprobes=1; + ++puid; ///@todo: Reset puid's when int range limit is reached */ + /* else setup a priority list... */ + } + // + int RemoveReferences(btCollisionShape* pcs) + { + int refcount=0; + for(int i=0;inext; + if(pc->pclient==pcs) + { + if(pp) pp->next=pn; else root=pn; + delete pc;pc=pp;++refcount; + } + pp=pc;pc=pn; + } + } + return(refcount); + } + // + btScalar Evaluate( const btVector3& x, + const btCollisionShape* shape, + btVector3& normal, + btScalar margin) + { + /* Lookup cell */ + const btVector3 scx=x/voxelsz; + const IntFrac ix=Decompose(scx.x()); + const IntFrac iy=Decompose(scx.y()); + const IntFrac iz=Decompose(scx.z()); + const unsigned h=Hash(ix.b,iy.b,iz.b,shape); + Cell*& root=cells[static_cast(h%cells.size())]; + Cell* c=root; + ++nqueries; + while(c) + { + ++nprobes; + if( (c->hash==h) && + (c->c[0]==ix.b) && + (c->c[1]==iy.b) && + (c->c[2]==iz.b) && + (c->pclient==shape)) + { break; } + else + { c=c->next; } + } + if(!c) + { + ++nprobes; + ++ncells; + int sz = sizeof(Cell); + if (ncells>m_clampCells) + { + static int numResets=0; + numResets++; +// printf("numResets=%d\n",numResets); + Reset(); + } + + c=new Cell(); + c->next=root;root=c; + c->pclient=shape; + c->hash=h; + c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b; + BuildCell(*c); + } + c->puid=puid; + /* Extract infos */ + const int o[]={ ix.i,iy.i,iz.i}; + const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+1][o[2]+1], + c->d[o[0]+0][o[1]+1][o[2]+1]}; + /* Normal */ +#if 1 + const btScalar gx[]={ d[1]-d[0],d[2]-d[3], + d[5]-d[4],d[6]-d[7]}; + const btScalar gy[]={ d[3]-d[0],d[2]-d[1], + d[7]-d[4],d[6]-d[5]}; + const btScalar gz[]={ d[4]-d[0],d[5]-d[1], + d[7]-d[3],d[6]-d[2]}; + normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f), + Lerp(gx[2],gx[3],iy.f),iz.f)); + normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f), + Lerp(gy[2],gy[3],ix.f),iz.f)); + normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f), + Lerp(gz[2],gz[3],ix.f),iy.f)); + normal = normal.normalized(); +#else + normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); +#endif + /* Distance */ + const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), + Lerp(d[3],d[2],ix.f),iy.f); + const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f), + Lerp(d[7],d[6],ix.f),iy.f); + return(Lerp(d0,d1,iz.f)-margin); + } + // + void BuildCell(Cell& c) + { + const btVector3 org=btVector3( (btScalar)c.c[0], + (btScalar)c.c[1], + (btScalar)c.c[2]) * + CELLSIZE*voxelsz; + for(int k=0;k<=CELLSIZE;++k) + { + const btScalar z=voxelsz*k+org.z(); + for(int j=0;j<=CELLSIZE;++j) + { + const btScalar y=voxelsz*j+org.y(); + for(int i=0;i<=CELLSIZE;++i) + { + const btScalar x=voxelsz*i+org.x(); + c.d[i][j][k]=DistanceToShape( btVector3(x,y,z), + c.pclient); + } + } + } + } + // + static inline btScalar DistanceToShape(const btVector3& x, + const btCollisionShape* shape) + { + btTransform unit; + unit.setIdentity(); + if(shape->isConvex()) + { + btGjkEpaSolver2::sResults res; + const btConvexShape* csh=static_cast(shape); + return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res)); + } + return(0); + } + // + static inline IntFrac Decompose(btScalar x) + { + /* That one need a lot of improvements... */ + /* Remove test, faster floor... */ + IntFrac r; + x/=CELLSIZE; + const int o=x<0?(int)(-x+1):0; + x+=o;r.b=(int)x; + const btScalar k=(x-r.b)*CELLSIZE; + r.i=(int)k;r.f=k-r.i;r.b-=o; + return(r); + } + // + static inline btScalar Lerp(btScalar a,btScalar b,btScalar t) + { + return(a+(b-a)*t); + } + + + + // + static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape) + { + struct btS + { + int x,y,z; + void* p; + }; + + btS myset; + + myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape; + const void* ptr = &myset; + + unsigned int result = HsiehHash (ptr); + + + return result; + } +}; + + +#endif //BT_SPARSE_SDF_H diff --git a/Code/Physics/src/BulletSoftBody/premake4.lua b/Code/Physics/src/BulletSoftBody/premake4.lua new file mode 100644 index 00000000..339043f5 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/premake4.lua @@ -0,0 +1,11 @@ + project "BulletSoftBody" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Code/Physics/src/CMakeLists.txt b/Code/Physics/src/CMakeLists.txt new file mode 100644 index 00000000..3a736b42 --- /dev/null +++ b/Code/Physics/src/CMakeLists.txt @@ -0,0 +1,32 @@ +SUBDIRS( BulletSoftBody BulletCollision BulletDynamics LinearMath ) + +IF(BUILD_MULTITHREADING) + SUBDIRS(MiniCL BulletMultiThreaded) +ENDIF() + +IF(INSTALL_LIBS) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + # Don't actually need to install any common files, the frameworks include everything + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(FILES btBulletCollisionCommon.h btBulletDynamicsCommon.h Bullet-C-Api.h DESTINATION ${INCLUDE_INSTALL_DIR}) + INSTALL(FILES vectormath/vmInclude.h DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath) + INSTALL(FILES vectormath/scalar/boolInVec.h + vectormath/scalar/floatInVec.h + vectormath/scalar/mat_aos.h + vectormath/scalar/quat_aos.h + vectormath/scalar/vec_aos.h + vectormath/scalar/vectormath_aos.h + DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath/scalar) + INSTALL(FILES vectormath/sse/boolInVec.h + vectormath/sse/floatInVec.h + vectormath/sse/mat_aos.h + vectormath/sse/quat_aos.h + vectormath/sse/vec_aos.h + vectormath/sse/vecidx_aos.h + vectormath/sse/vectormath_aos.h + DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath/sse) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) +ENDIF(INSTALL_LIBS) diff --git a/Code/Physics/src/LinearMath/CMakeLists.txt b/Code/Physics/src/LinearMath/CMakeLists.txt new file mode 100644 index 00000000..8d8a54b9 --- /dev/null +++ b/Code/Physics/src/LinearMath/CMakeLists.txt @@ -0,0 +1,72 @@ + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src +) + +SET(LinearMath_SRCS + btAlignedAllocator.cpp + btConvexHull.cpp + btConvexHullComputer.cpp + btGeometryUtil.cpp + btPolarDecomposition.cpp + btQuickprof.cpp + btSerializer.cpp + btVector3.cpp +) + +SET(LinearMath_HDRS + btAabbUtil2.h + btAlignedAllocator.h + btAlignedObjectArray.h + btConvexHull.h + btConvexHullComputer.h + btDefaultMotionState.h + btGeometryUtil.h + btGrahamScan2dConvexHull.h + btHashMap.h + btIDebugDraw.h + btList.h + btMatrix3x3.h + btMinMax.h + btMotionState.h + btPolarDecomposition.h + btPoolAllocator.h + btQuadWord.h + btQuaternion.h + btQuickprof.h + btRandom.h + btScalar.h + btSerializer.h + btStackAlloc.h + btTransform.h + btTransformUtil.h + btVector3.h +) + +ADD_LIBRARY(LinearMath ${LinearMath_SRCS} ${LinearMath_HDRS}) +SET_TARGET_PROPERTIES(LinearMath PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(LinearMath PROPERTIES SOVERSION ${BULLET_VERSION}) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #FILES_MATCHING requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS LinearMath DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS LinearMath + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN +".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(LinearMath PROPERTIES FRAMEWORK true) + SET_TARGET_PROPERTIES(LinearMath PROPERTIES PUBLIC_HEADER "${LinearMath_HDRS}") + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/src/LinearMath/btAabbUtil2.h b/Code/Physics/src/LinearMath/btAabbUtil2.h new file mode 100644 index 00000000..d2997b4e --- /dev/null +++ b/Code/Physics/src/LinearMath/btAabbUtil2.h @@ -0,0 +1,232 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_AABB_UTIL2 +#define BT_AABB_UTIL2 + +#include "btTransform.h" +#include "btVector3.h" +#include "btMinMax.h" + + + +SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, + btVector3& aabbMax, + const btVector3& expansionMin, + const btVector3& expansionMax) +{ + aabbMin = aabbMin + expansionMin; + aabbMax = aabbMax + expansionMax; +} + +/// conservative test for overlap between two aabbs +SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, + const btVector3 &point) +{ + bool overlap = true; + overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap; + overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap; + overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap; + return overlap; +} + + +/// conservative test for overlap between two aabbs +SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, + const btVector3 &aabbMin2, const btVector3 &aabbMax2) +{ + bool overlap = true; + overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap; + overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap; + overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap; + return overlap; +} + +/// conservative test for overlap between triangle and aabb +SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices, + const btVector3 &aabbMin, const btVector3 &aabbMax) +{ + const btVector3 &p1 = vertices[0]; + const btVector3 &p2 = vertices[1]; + const btVector3 &p3 = vertices[2]; + + if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false; + if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false; + + if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false; + if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false; + + if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false; + if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false; + return true; +} + + +SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) +{ + return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) | + (p.getX() > halfExtent.getX() ? 0x08 : 0x0) | + (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) | + (p.getY() > halfExtent.getY() ? 0x10 : 0x0) | + (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) | + (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0); +} + + + +SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, + const btVector3& rayInvDirection, + const unsigned int raySign[3], + const btVector3 bounds[2], + btScalar& tmin, + btScalar lambda_min, + btScalar lambda_max) +{ + btScalar tmax, tymin, tymax, tzmin, tzmax; + tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); + tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); + tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); + tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); + + if ( (tmin > tymax) || (tymin > tmax) ) + return false; + + if (tymin > tmin) + tmin = tymin; + + if (tymax < tmax) + tmax = tymax; + + tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ(); + tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ(); + + if ( (tmin > tzmax) || (tzmin > tmax) ) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ( (tmin < lambda_max) && (tmax > lambda_min) ); +} + +SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& aabbMin, + const btVector3& aabbMax, + btScalar& param, btVector3& normal) +{ + btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5); + btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5); + btVector3 source = rayFrom - aabbCenter; + btVector3 target = rayTo - aabbCenter; + int sourceOutcode = btOutcode(source,aabbHalfExtent); + int targetOutcode = btOutcode(target,aabbHalfExtent); + if ((sourceOutcode & targetOutcode) == 0x0) + { + btScalar lambda_enter = btScalar(0.0); + btScalar lambda_exit = param; + btVector3 r = target - source; + int i; + btScalar normSign = 1; + btVector3 hitNormal(0,0,0); + int bit=1; + + for (int j=0;j<2;j++) + { + for (i = 0; i != 3; ++i) + { + if (sourceOutcode & bit) + { + btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; + if (lambda_enter <= lambda) + { + lambda_enter = lambda; + hitNormal.setValue(0,0,0); + hitNormal[i] = normSign; + } + } + else if (targetOutcode & bit) + { + btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; + btSetMin(lambda_exit, lambda); + } + bit<<=1; + } + normSign = btScalar(-1.); + } + if (lambda_enter <= lambda_exit) + { + param = lambda_enter; + normal = hitNormal; + return true; + } + } + return false; +} + + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] ); + aabbMinOut = center - extent; + aabbMaxOut = center + extent; +} + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btAssert(localAabbMin.getX() <= localAabbMax.getX()); + btAssert(localAabbMin.getY() <= localAabbMax.getY()); + btAssert(localAabbMin.getZ() <= localAabbMax.getZ()); + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + localHalfExtents+=btVector3(margin,margin,margin); + + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + btMatrix3x3 abs_b = trans.getBasis().absolute(); + btVector3 center = trans(localCenter); + btVector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] ); + aabbMinOut = center-extent; + aabbMaxOut = center+extent; +} + +#define USE_BANCHLESS 1 +#ifdef USE_BANCHLESS + //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) + SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) + { + return static_cast(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0)); + } +#else + SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } +#endif //USE_BANCHLESS + +#endif //BT_AABB_UTIL2 + + diff --git a/Code/Physics/src/LinearMath/btAlignedAllocator.cpp b/Code/Physics/src/LinearMath/btAlignedAllocator.cpp new file mode 100644 index 00000000..a65296c6 --- /dev/null +++ b/Code/Physics/src/LinearMath/btAlignedAllocator.cpp @@ -0,0 +1,181 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btAlignedAllocator.h" + +int gNumAlignedAllocs = 0; +int gNumAlignedFree = 0; +int gTotalBytesAlignedAllocs = 0;//detect memory leaks + +static void *btAllocDefault(size_t size) +{ + return malloc(size); +} + +static void btFreeDefault(void *ptr) +{ + free(ptr); +} + +static btAllocFunc *sAllocFunc = btAllocDefault; +static btFreeFunc *sFreeFunc = btFreeDefault; + + + +#if defined (BT_HAS_ALIGNED_ALLOCATOR) +#include +static void *btAlignedAllocDefault(size_t size, int alignment) +{ + return _aligned_malloc(size, (size_t)alignment); +} + +static void btAlignedFreeDefault(void *ptr) +{ + _aligned_free(ptr); +} +#elif defined(__CELLOS_LV2__) +#include + +static inline void *btAlignedAllocDefault(size_t size, int alignment) +{ + return memalign(alignment, size); +} + +static inline void btAlignedFreeDefault(void *ptr) +{ + free(ptr); +} +#else + + + + + +static inline void *btAlignedAllocDefault(size_t size, int alignment) +{ + void *ret; + char *real; + real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); + if (real) { + ret = btAlignPointer(real + sizeof(void *),alignment); + *((void **)(ret)-1) = (void *)(real); + } else { + ret = (void *)(real); + } + return (ret); +} + +static inline void btAlignedFreeDefault(void *ptr) +{ + void* real; + + if (ptr) { + real = *((void **)(ptr)-1); + sFreeFunc(real); + } +} +#endif + + +static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; +static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; + +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) +{ + sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault; + sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault; +} + +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) +{ + sAllocFunc = allocFunc ? allocFunc : btAllocDefault; + sFreeFunc = freeFunc ? freeFunc : btFreeDefault; +} + +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS +//this generic allocator provides the total allocated number of bytes +#include + +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) +{ + void *ret; + char *real; + + gTotalBytesAlignedAllocs += size; + gNumAlignedAllocs++; + + + real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); + if (real) { + ret = (void*) btAlignPointer(real + 2*sizeof(void *), alignment); + *((void **)(ret)-1) = (void *)(real); + *((int*)(ret)-2) = size; + + } else { + ret = (void *)(real);//?? + } + + printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); + + int* ptr = (int*)ret; + *ptr = 12; + return (ret); +} + +void btAlignedFreeInternal (void* ptr,int line,char* filename) +{ + + void* real; + gNumAlignedFree++; + + if (ptr) { + real = *((void **)(ptr)-1); + int size = *((int*)(ptr)-2); + gTotalBytesAlignedAllocs -= size; + + printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); + + sFreeFunc(real); + } else + { + printf("NULL ptr\n"); + } +} + +#else //BT_DEBUG_MEMORY_ALLOCATIONS + +void* btAlignedAllocInternal (size_t size, int alignment) +{ + gNumAlignedAllocs++; + void* ptr; + ptr = sAlignedAllocFunc(size, alignment); +// printf("btAlignedAllocInternal %d, %x\n",size,ptr); + return ptr; +} + +void btAlignedFreeInternal (void* ptr) +{ + if (!ptr) + { + return; + } + + gNumAlignedFree++; +// printf("btAlignedFreeInternal %x\n",ptr); + sAlignedFreeFunc(ptr); +} + +#endif //BT_DEBUG_MEMORY_ALLOCATIONS + diff --git a/Code/Physics/src/LinearMath/btAlignedAllocator.h b/Code/Physics/src/LinearMath/btAlignedAllocator.h new file mode 100644 index 00000000..f168f3c6 --- /dev/null +++ b/Code/Physics/src/LinearMath/btAlignedAllocator.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_ALIGNED_ALLOCATOR +#define BT_ALIGNED_ALLOCATOR + +///we probably replace this with our own aligned memory allocator +///so we replace _aligned_malloc and _aligned_free with our own +///that is better portable and more predictable + +#include "btScalar.h" +//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS + +#define btAlignedAlloc(a,b) \ + btAlignedAllocInternal(a,b,__LINE__,__FILE__) + +#define btAlignedFree(ptr) \ + btAlignedFreeInternal(ptr,__LINE__,__FILE__) + +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); + +void btAlignedFreeInternal (void* ptr,int line,char* filename); + +#else + void* btAlignedAllocInternal (size_t size, int alignment); + void btAlignedFreeInternal (void* ptr); + + #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment) + #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) + +#endif +typedef int size_type; + +typedef void *(btAlignedAllocFunc)(size_t size, int alignment); +typedef void (btAlignedFreeFunc)(void *memblock); +typedef void *(btAllocFunc)(size_t size); +typedef void (btFreeFunc)(void *memblock); + +///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); +///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it. +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); + + +///The btAlignedAllocator is a portable class for aligned memory allocations. +///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. +template < typename T , unsigned Alignment > +class btAlignedAllocator { + + typedef btAlignedAllocator< T , Alignment > self_type; + +public: + + //just going down a list: + btAlignedAllocator() {} + /* + btAlignedAllocator( const self_type & ) {} + */ + + template < typename Other > + btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {} + + typedef const T* const_pointer; + typedef const T& const_reference; + typedef T* pointer; + typedef T& reference; + typedef T value_type; + + pointer address ( reference ref ) const { return &ref; } + const_pointer address ( const_reference ref ) const { return &ref; } + pointer allocate ( size_type n , const_pointer * hint = 0 ) { + (void)hint; + return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment )); + } + void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); } + void deallocate( pointer ptr ) { + btAlignedFree( reinterpret_cast< void * >( ptr ) ); + } + void destroy ( pointer ptr ) { ptr->~value_type(); } + + + template < typename O > struct rebind { + typedef btAlignedAllocator< O , Alignment > other; + }; + template < typename O > + self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; } + + friend bool operator==( const self_type & , const self_type & ) { return true; } +}; + + + +#endif //BT_ALIGNED_ALLOCATOR + diff --git a/Code/Physics/src/LinearMath/btAlignedObjectArray.h b/Code/Physics/src/LinearMath/btAlignedObjectArray.h new file mode 100644 index 00000000..24e59ab6 --- /dev/null +++ b/Code/Physics/src/LinearMath/btAlignedObjectArray.h @@ -0,0 +1,511 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_OBJECT_ARRAY__ +#define BT_OBJECT_ARRAY__ + +#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE +#include "btAlignedAllocator.h" + +///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW +///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors +///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator= +///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and +///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240 + +#define BT_USE_PLACEMENT_NEW 1 +//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in or or otherwise... +#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful + +#ifdef BT_USE_MEMCPY +#include +#include +#endif //BT_USE_MEMCPY + +#ifdef BT_USE_PLACEMENT_NEW +#include //for placement new +#endif //BT_USE_PLACEMENT_NEW + + +///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods +///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data +template +//template +class btAlignedObjectArray +{ + btAlignedAllocator m_allocator; + + int m_size; + int m_capacity; + T* m_data; + //PCK: added this line + bool m_ownsMemory; + +#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR +public: + SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other) + { + copyFromArray(other); + return *this; + } +#else//BT_ALLOW_ARRAY_COPY_OPERATOR +private: + SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other); +#endif//BT_ALLOW_ARRAY_COPY_OPERATOR + +protected: + SIMD_FORCE_INLINE int allocSize(int size) + { + return (size ? size*2 : 1); + } + SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const + { + int i; + for (i=start;i=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n0); + m_size--; + m_data[m_size].~T(); + } + + + ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument. + ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations. + SIMD_FORCE_INLINE void resizeNoInitialize(int newsize) + { + int curSize = size(); + + if (newsize < curSize) + { + } else + { + if (newsize > size()) + { + reserve(newsize); + } + //leave this uninitialized + } + m_size = newsize; + } + + SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T()) + { + int curSize = size(); + + if (newsize < curSize) + { + for(int i = newsize; i < curSize; i++) + { + m_data[i].~T(); + } + } else + { + if (newsize > size()) + { + reserve(newsize); + } +#ifdef BT_USE_PLACEMENT_NEW + for (int i=curSize;i + void quickSortInternal(const L& CompareFunc,int lo, int hi) + { + // lo is the lower index, hi is the upper index + // of the region of array a that is to be sorted + int i=lo, j=hi; + T x=m_data[(lo+hi)/2]; + + // partition + do + { + while (CompareFunc(m_data[i],x)) + i++; + while (CompareFunc(x,m_data[j])) + j--; + if (i<=j) + { + swap(i,j); + i++; j--; + } + } while (i<=j); + + // recursion + if (lo + void quickSort(const L& CompareFunc) + { + //don't sort 0 or 1 elements + if (size()>1) + { + quickSortInternal(CompareFunc,0,size()-1); + } + } + + + ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ + template + void downHeap(T *pArr, int k, int n, const L& CompareFunc) + { + /* PRE: a[k+1..N] is a heap */ + /* POST: a[k..N] is a heap */ + + T temp = pArr[k - 1]; + /* k has child(s) */ + while (k <= n/2) + { + int child = 2*k; + + if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child])) + { + child++; + } + /* pick larger child */ + if (CompareFunc(temp , pArr[child - 1])) + { + /* move child up */ + pArr[k - 1] = pArr[child - 1]; + k = child; + } + else + { + break; + } + } + pArr[k - 1] = temp; + } /*downHeap*/ + + void swap(int index0,int index1) + { +#ifdef BT_USE_MEMCPY + char temp[sizeof(T)]; + memcpy(temp,&m_data[index0],sizeof(T)); + memcpy(&m_data[index0],&m_data[index1],sizeof(T)); + memcpy(&m_data[index1],temp,sizeof(T)); +#else + T temp = m_data[index0]; + m_data[index0] = m_data[index1]; + m_data[index1] = temp; +#endif //BT_USE_PLACEMENT_NEW + + } + + template + void heapSort(const L& CompareFunc) + { + /* sort a[0..N-1], N.B. 0 to N-1 */ + int k; + int n = m_size; + for (k = n/2; k > 0; k--) + { + downHeap(m_data, k, n, CompareFunc); + } + + /* a[1..N] is now a heap */ + while ( n>=1 ) + { + swap(0,n-1); /* largest of a[0..n-1] */ + + + n = n - 1; + /* restore a[1..i-1] heap */ + downHeap(m_data, 1, n, CompareFunc); + } + } + + ///non-recursive binary search, assumes sorted array + int findBinarySearch(const T& key) const + { + int first = 0; + int last = size()-1; + + //assume sorted array + while (first <= last) { + int mid = (first + last) / 2; // compute mid point. + if (key > m_data[mid]) + first = mid + 1; // repeat search in top half. + else if (key < m_data[mid]) + last = mid - 1; // repeat search in bottom half. + else + return mid; // found it. return position ///// + } + return size(); // failed to find key + } + + + int findLinearSearch(const T& key) const + { + int index=size(); + int i; + + for (i=0;i + +#include "btConvexHull.h" +#include "btAlignedObjectArray.h" +#include "btMinMax.h" +#include "btVector3.h" + + + + + +//---------------------------------- + +class int3 +{ +public: + int x,y,z; + int3(){}; + int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + + +//------- btPlane ---------- + + +inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);} +inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); } +inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); } + + +//--------- Utility Functions ------ + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1); +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point); + +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2); +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2) +{ + btVector3 N1 = p0.normal; + btVector3 N2 = p1.normal; + btVector3 N3 = p2.normal; + + btVector3 n2n3; n2n3 = N2.cross(N3); + btVector3 n3n1; n3n1 = N3.cross(N1); + btVector3 n1n2; n1n2 = N1.cross(N2); + + btScalar quotient = (N1.dot(n2n3)); + + btAssert(btFabs(quotient) > btScalar(0.000001)); + + quotient = btScalar(-1.) / quotient; + n2n3 *= p0.dist; + n3n1 *= p1.dist; + n1n2 *= p2.dist; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ()); + return result; + +} + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL); +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2); +btVector3 NormalOf(const btVector3 *vert, const int n); + + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1) +{ + // returns the point where the line p0-p1 intersects the plane n&d + static btVector3 dif; + dif = p1-p0; + btScalar dn= btDot(plane.normal,dif); + btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn; + return p0 + (dif*t); +} + +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point) +{ + return point - plane.normal * (btDot(point,plane.normal)+plane.dist); +} + +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) +{ + // return the normal of the triangle + // inscribed by v0, v1, and v2 + btVector3 cp=btCross(v1-v0,v2-v1); + btScalar m=cp.length(); + if(m==0) return btVector3(1,0,0); + return cp*(btScalar(1.0)/m); +} + + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint) +{ + static btVector3 cp; + cp = btCross(udir,vdir).normalized(); + + btScalar distu = -btDot(cp,ustart); + btScalar distv = -btDot(cp,vstart); + btScalar dist = (btScalar)fabs(distu-distv); + if(upoint) + { + btPlane plane; + plane.normal = btCross(vdir,cp).normalized(); + plane.dist = -btDot(plane.normal,vstart); + *upoint = PlaneLineIntersection(plane,ustart,ustart+udir); + } + if(vpoint) + { + btPlane plane; + plane.normal = btCross(udir,cp).normalized(); + plane.dist = -btDot(plane.normal,ustart); + *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir); + } + return dist; +} + + + + + + + +#define COPLANAR (0) +#define UNDER (1) +#define OVER (2) +#define SPLIT (OVER|UNDER) +#define PAPERWIDTH (btScalar(0.001)) + +btScalar planetestepsilon = PAPERWIDTH; + + + +typedef ConvexH::HalfEdge HalfEdge; + +ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size) +{ + vertices.resize(vertices_size); + edges.resize(edges_size); + facets.resize(facets_size); +} + + +int PlaneTest(const btPlane &p, const btVector3 &v); +int PlaneTest(const btPlane &p, const btVector3 &v) { + btScalar a = btDot(v,p.normal)+p.dist; + int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR); + return flag; +} + +int SplitTest(ConvexH &convex,const btPlane &plane); +int SplitTest(ConvexH &convex,const btPlane &plane) { + int flag=0; + for(int i=0;i +int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + btAssert(count); + int m=-1; + for(int i=0;ibtDot(p[m],dir)) + m=i; + } + btAssert(m!=-1); + return m; +} + +btVector3 orth(const btVector3 &v); +btVector3 orth(const btVector3 &v) +{ + btVector3 a=btCross(v,btVector3(0,0,1)); + btVector3 b=btCross(v,btVector3(0,1,0)); + if (a.length() > b.length()) + { + return a.normalized(); + } else { + return b.normalized(); + } +} + + +template +int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + int m=-1; + while(m==-1) + { + m = maxdirfiltered(p,count,dir,allow); + if(allow[m]==3) return m; + T u = orth(dir); + T v = btCross(u,dir); + int ma=-1; + for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0)) + { + btScalar s = btSin(SIMD_RADS_PER_DEG*(x)); + btScalar c = btCos(SIMD_RADS_PER_DEG*(x)); + int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(ma==m && mb==m) + { + allow[m]=3; + return m; + } + if(ma!=-1 && ma!=mb) // Yuck - this is really ugly + { + int mc = ma; + for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0)) + { + btScalar s = btSin(SIMD_RADS_PER_DEG*(xx)); + btScalar c = btCos(SIMD_RADS_PER_DEG*(xx)); + int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(mc==m && md==m) + { + allow[m]=3; + return m; + } + mc=md; + } + } + ma=mb; + } + allow[m]=0; + m=-1; + } + btAssert(0); + return m; +} + + + + +int operator ==(const int3 &a,const int3 &b); +int operator ==(const int3 &a,const int3 &b) +{ + for(int i=0;i<3;i++) + { + if(a[i]!=b[i]) return 0; + } + return 1; +} + + +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon); +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) +{ + btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]); + return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON??? +} +int hasedge(const int3 &t, int a,int b); +int hasedge(const int3 &t, int a,int b) +{ + for(int i=0;i<3;i++) + { + int i1= (i+1)%3; + if(t[i]==a && t[i1]==b) return 1; + } + return 0; +} +int hasvert(const int3 &t, int v); +int hasvert(const int3 &t, int v) +{ + return (t[0]==v || t[1]==v || t[2]==v) ; +} +int shareedge(const int3 &a,const int3 &b); +int shareedge(const int3 &a,const int3 &b) +{ + int i; + for(i=0;i<3;i++) + { + int i1= (i+1)%3; + if(hasedge(a,b[i1],b[i])) return 1; + } + return 0; +} + +class btHullTriangle; + + + +class btHullTriangle : public int3 +{ +public: + int3 n; + int id; + int vmax; + btScalar rise; + btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1) + { + vmax=-1; + rise = btScalar(0.0); + } + ~btHullTriangle() + { + } + int &neib(int a,int b); +}; + + +int &btHullTriangle::neib(int a,int b) +{ + static int er=-1; + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + if((*this)[i]==a && (*this)[i1]==b) return n[i2]; + if((*this)[i]==b && (*this)[i1]==a) return n[i2]; + } + btAssert(0); + return er; +} +void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t) +{ + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*s)[i1]; + int b = (*s)[i2]; + btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id); + btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id); + m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a); + m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b); + } +} + +void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t) +{ + b2bfix(s,t); + deAllocateTriangle(s); + + deAllocateTriangle(t); +} + +void HullLibrary::checkit(btHullTriangle *t) +{ + (void)t; + + int i; + btAssert(m_tris[t->id]==t); + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*t)[i1]; + int b = (*t)[i2]; + + // release compile fix + (void)i1; + (void)i2; + (void)a; + (void)b; + + btAssert(a!=b); + btAssert( m_tris[t->n[i]]->neib(b,a) == t->id); + } +} + +btHullTriangle* HullLibrary::allocateTriangle(int a,int b,int c) +{ + void* mem = btAlignedAlloc(sizeof(btHullTriangle),16); + btHullTriangle* tr = new (mem)btHullTriangle(a,b,c); + tr->id = m_tris.size(); + m_tris.push_back(tr); + + return tr; +} + +void HullLibrary::deAllocateTriangle(btHullTriangle* tri) +{ + btAssert(m_tris[tri->id]==tri); + m_tris[tri->id]=NULL; + tri->~btHullTriangle(); + btAlignedFree(tri); +} + + +void HullLibrary::extrude(btHullTriangle *t0,int v) +{ + int3 t= *t0; + int n = m_tris.size(); + btHullTriangle* ta = allocateTriangle(v,t[1],t[2]); + ta->n = int3(t0->n[0],n+1,n+2); + m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0; + btHullTriangle* tb = allocateTriangle(v,t[2],t[0]); + tb->n = int3(t0->n[1],n+2,n+0); + m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1; + btHullTriangle* tc = allocateTriangle(v,t[0],t[1]); + tc->n = int3(t0->n[2],n+0,n+1); + m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2; + checkit(ta); + checkit(tb); + checkit(tc); + if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]); + if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]); + if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]); + deAllocateTriangle(t0); + +} + +btHullTriangle* HullLibrary::extrudable(btScalar epsilon) +{ + int i; + btHullTriangle *t=NULL; + for(i=0;iriserise)) + { + t = m_tris[i]; + } + } + return (t->rise >epsilon)?t:NULL ; +} + + + + +int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow) +{ + btVector3 basis[3]; + basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) ); + int p0 = maxdirsterid(verts,verts_count, basis[0],allow); + int p1 = maxdirsterid(verts,verts_count,-basis[0],allow); + basis[0] = verts[p0]-verts[p1]; + if(p0==p1 || basis[0]==btVector3(0,0,0)) + return int4(-1,-1,-1,-1); + basis[1] = btCross(btVector3( btScalar(1),btScalar(0.02), btScalar(0)),basis[0]); + basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)),basis[0]); + if (basis[1].length() > basis[2].length()) + { + basis[1].normalize(); + } else { + basis[1] = basis[2]; + basis[1].normalize (); + } + int p2 = maxdirsterid(verts,verts_count,basis[1],allow); + if(p2 == p0 || p2 == p1) + { + p2 = maxdirsterid(verts,verts_count,-basis[1],allow); + } + if(p2 == p0 || p2 == p1) + return int4(-1,-1,-1,-1); + basis[1] = verts[p2] - verts[p0]; + basis[2] = btCross(basis[1],basis[0]).normalized(); + int p3 = maxdirsterid(verts,verts_count,basis[2],allow); + if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow); + if(p3==p0||p3==p1||p3==p2) + return int4(-1,-1,-1,-1); + btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3)); + if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {btSwap(p2,p3);} + return int4(p0,p1,p2,p3); +} + +int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) +{ + if(verts_count <4) return 0; + if(vlimit==0) vlimit=1000000000; + int j; + btVector3 bmin(*verts),bmax(*verts); + btAlignedObjectArray isextreme; + isextreme.reserve(verts_count); + btAlignedObjectArray allow; + allow.reserve(verts_count); + + for(j=0;jn=int3(2,3,1); + btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); + btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); + btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2); + isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; + checkit(t0);checkit(t1);checkit(t2);checkit(t3); + + for(j=0;jvmax<0); + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]); + } + btHullTriangle *te; + vlimit-=4; + while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) + { + //int3 ti=*te; + int v=te->vmax; + btAssert(v != -1); + btAssert(!isextreme[v]); // wtf we've already done this vertex + isextreme[v]=1; + //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already + j=m_tris.size(); + while(j--) { + if(!m_tris[j]) continue; + int3 t=*m_tris[j]; + if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) + { + extrude(m_tris[j],v); + } + } + // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle + j=m_tris.size(); + while(j--) + { + if(!m_tris[j]) continue; + if(!hasvert(*m_tris[j],v)) break; + int3 nt=*m_tris[j]; + if(above(verts,nt,center,btScalar(0.01)*epsilon) || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) ) + { + btHullTriangle *nb = m_tris[m_tris[j]->n[0]]; + btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->idvmax>=0) break; + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + if(isextreme[t->vmax]) + { + t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. + } + else + { + t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]); + } + } + vlimit --; + } + return 1; +} + +int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) +{ + int rc=calchullgen(verts,verts_count, vlimit) ; + if(!rc) return 0; + btAlignedObjectArray ts; + int i; + + for(i=0;i(ts[i]); + } + m_tris.resize(0); + + return 1; +} + + + + + +bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit) +{ + + int tris_count; + int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast(vlimit) ); + if(!ret) return false; + result.mIndexCount = (unsigned int) (tris_count*3); + result.mFaceCount = (unsigned int) tris_count; + result.mVertices = (btVector3*) vertices; + result.mVcount = (unsigned int) vcount; + return true; + +} + + +void ReleaseHull(PHullResult &result); +void ReleaseHull(PHullResult &result) +{ + if ( result.m_Indices.size() ) + { + result.m_Indices.clear(); + } + + result.mVcount = 0; + result.mIndexCount = 0; + result.mVertices = 0; +} + + +//********************************************************************* +//********************************************************************* +//******** HullLib header +//********************************************************************* +//********************************************************************* + +//********************************************************************* +//********************************************************************* +//******** HullLib implementation +//********************************************************************* +//********************************************************************* + +HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request + HullResult &result) // contains the resulst +{ + HullError ret = QE_FAIL; + + + PHullResult hr; + + unsigned int vcount = desc.mVcount; + if ( vcount < 8 ) vcount = 8; + + btAlignedObjectArray vertexSource; + vertexSource.resize(static_cast(vcount)); + + btVector3 scale; + + unsigned int ovcount; + + bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates! + + if ( ok ) + { + + +// if ( 1 ) // scale vertices back to their original size. + { + for (unsigned int i=0; i(i)]; + v[0]*=scale[0]; + v[1]*=scale[1]; + v[2]*=scale[2]; + } + } + + ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices); + + if ( ok ) + { + + // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. + btAlignedObjectArray vertexScratch; + vertexScratch.resize(static_cast(hr.mVcount)); + + BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount ); + + ret = QE_OK; + + if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle! + { + result.mPolygons = false; + result.mNumOutputVertices = ovcount; + result.m_OutputVertices.resize(static_cast(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount; + + result.m_Indices.resize(static_cast(hr.mIndexCount)); + + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + + if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) + { + + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + + for (unsigned int i=0; i(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount+hr.mFaceCount; + result.m_Indices.resize(static_cast(result.mNumIndices)); + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + +// if ( 1 ) + { + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + btVector3 center; + + center[0] = dx*btScalar(0.5) + bmin[0]; + center[1] = dy*btScalar(0.5) + bmin[1]; + center[2] = dz*btScalar(0.5) + bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 ) + { + + btScalar len = FLT_MAX; + + if ( dx > EPSILON && dx < len ) len = dx; + if ( dy > EPSILON && dy < len ) len = dy; + if ( dz > EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = center[0] - dx; + btScalar x2 = center[0] + dx; + + btScalar y1 = center[1] - dy; + btScalar y2 = center[1] + dy; + + btScalar z1 = center[2] - dz; + btScalar z2 = center[2] + dz; + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; // return cube + + + } + else + { + if ( scale ) + { + scale[0] = dx; + scale[1] = dy; + scale[2] = dz; + + recip[0] = 1 / dx; + recip[1] = 1 / dy; + recip[2] = 1 / dz; + + center[0]*=recip[0]; + center[1]*=recip[1]; + center[2]*=recip[2]; + + } + + } + + + + vtx = (const char *) svertices; + + for (unsigned int i=0; igetX(); + btScalar py = p->getY(); + btScalar pz = p->getZ(); + + if ( scale ) + { + px = px*recip[0]; // normalize + py = py*recip[1]; // normalize + pz = pz*recip[2]; // normalize + } + +// if ( 1 ) + { + unsigned int j; + + for (j=0; j dist2 ) + { + v[0] = px; + v[1] = py; + v[2] = pz; + + } + + break; + } + } + + if ( j == vcount ) + { + btVector3& dest = vertices[vcount]; + dest[0] = px; + dest[1] = py; + dest[2] = pz; + vcount++; + } + m_vertexIndexMapping.push_back(j); + } + } + + // ok..now make sure we didn't prune so many vertices it is now invalid. +// if ( 1 ) + { + btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; + btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3) + { + btScalar cx = dx*btScalar(0.5) + bmin[0]; + btScalar cy = dy*btScalar(0.5) + bmin[1]; + btScalar cz = dz*btScalar(0.5) + bmin[2]; + + btScalar len = FLT_MAX; + + if ( dx >= EPSILON && dx < len ) len = dx; + if ( dy >= EPSILON && dy < len ) len = dy; + if ( dz >= EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = cx - dx; + btScalar x2 = cx + dx; + + btScalar y1 = cy - dy; + btScalar y2 = cy + dy; + + btScalar z1 = cz - dz; + btScalar z2 = cz + dz; + + vcount = 0; // add box + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; + } + } + + return true; +} + +void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount) +{ + btAlignedObjectArraytmpIndices; + tmpIndices.resize(m_vertexIndexMapping.size()); + int i; + + for (i=0;i(vcount)); + memset(&usedIndices[0],0,sizeof(unsigned int)*vcount); + + ocount = 0; + + for (i=0; i= 0 && v < vcount ); + + if ( usedIndices[static_cast(v)] ) // if already remapped + { + indices[i] = usedIndices[static_cast(v)]-1; // index to new array + } + else + { + + indices[i] = ocount; // new index mapping + + overts[ocount][0] = verts[v][0]; // copy old vert to new vert array + overts[ocount][1] = verts[v][1]; + overts[ocount][2] = verts[v][2]; + + for (int k=0;k=0 && ocount <= vcount ); + + usedIndices[static_cast(v)] = ocount; // assign new index remapping + + + } + } + + +} diff --git a/Code/Physics/src/LinearMath/btConvexHull.h b/Code/Physics/src/LinearMath/btConvexHull.h new file mode 100644 index 00000000..69c52bc6 --- /dev/null +++ b/Code/Physics/src/LinearMath/btConvexHull.h @@ -0,0 +1,241 @@ + +/* +Stan Melax Convex Hull Computation +Copyright (c) 2008 Stan Melax http://www.melax.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. +*/ + +///includes modifications/improvements by John Ratcliff, see BringOutYourDead below. + +#ifndef BT_CD_HULL_H +#define BT_CD_HULL_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +typedef btAlignedObjectArray TUIntArray; + +class HullResult +{ +public: + HullResult(void) + { + mPolygons = true; + mNumOutputVertices = 0; + mNumFaces = 0; + mNumIndices = 0; + } + bool mPolygons; // true if indices represents polygons, false indices are triangles + unsigned int mNumOutputVertices; // number of vertices in the output hull + btAlignedObjectArray m_OutputVertices; // array of vertices + unsigned int mNumFaces; // the number of faces produced + unsigned int mNumIndices; // the total number of indices + btAlignedObjectArray m_Indices; // pointer to indices. + +// If triangles, then indices are array indexes into the vertex list. +// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc.. +}; + +enum HullFlag +{ + QF_TRIANGLES = (1<<0), // report results as triangles, not polygons. + QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices. + QF_DEFAULT = QF_TRIANGLES +}; + + +class HullDesc +{ +public: + HullDesc(void) + { + mFlags = QF_DEFAULT; + mVcount = 0; + mVertices = 0; + mVertexStride = sizeof(btVector3); + mNormalEpsilon = 0.001f; + mMaxVertices = 4096; // maximum number of points to be considered for a convex hull. + mMaxFaces = 4096; + }; + + HullDesc(HullFlag flag, + unsigned int vcount, + const btVector3 *vertices, + unsigned int stride = sizeof(btVector3)) + { + mFlags = flag; + mVcount = vcount; + mVertices = vertices; + mVertexStride = stride; + mNormalEpsilon = btScalar(0.001); + mMaxVertices = 4096; + } + + bool HasHullFlag(HullFlag flag) const + { + if ( mFlags & flag ) return true; + return false; + } + + void SetHullFlag(HullFlag flag) + { + mFlags|=flag; + } + + void ClearHullFlag(HullFlag flag) + { + mFlags&=~flag; + } + + unsigned int mFlags; // flags to use when generating the convex hull. + unsigned int mVcount; // number of vertices in the input point cloud + const btVector3 *mVertices; // the array of vertices. + unsigned int mVertexStride; // the stride of each vertex, in bytes. + btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on. + unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull! + unsigned int mMaxFaces; +}; + +enum HullError +{ + QE_OK, // success! + QE_FAIL // failed. +}; + +class btPlane +{ + public: + btVector3 normal; + btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0 + btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){} + btPlane():normal(),dist(0){} + +}; + + + +class ConvexH +{ + public: + class HalfEdge + { + public: + short ea; // the other half of the edge (index into edges list) + unsigned char v; // the vertex at the start of this edge (index into vertices list) + unsigned char p; // the facet on which this edge lies (index into facets list) + HalfEdge(){} + HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){} + }; + ConvexH() + { + } + ~ConvexH() + { + } + btAlignedObjectArray vertices; + btAlignedObjectArray edges; + btAlignedObjectArray facets; + ConvexH(int vertices_size,int edges_size,int facets_size); +}; + + +class int4 +{ +public: + int x,y,z,w; + int4(){}; + int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + +class PHullResult +{ +public: + + PHullResult(void) + { + mVcount = 0; + mIndexCount = 0; + mFaceCount = 0; + mVertices = 0; + } + + unsigned int mVcount; + unsigned int mIndexCount; + unsigned int mFaceCount; + btVector3* mVertices; + TUIntArray m_Indices; +}; + + + +///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method. +///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape. +class HullLibrary +{ + + btAlignedObjectArray m_tris; + +public: + + btAlignedObjectArray m_vertexIndexMapping; + + + HullError CreateConvexHull(const HullDesc& desc, // describes the input request + HullResult& result); // contains the resulst + HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. + +private: + + bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit); + + class btHullTriangle* allocateTriangle(int a,int b,int c); + void deAllocateTriangle(btHullTriangle*); + void b2bfix(btHullTriangle* s,btHullTriangle*t); + + void removeb2b(btHullTriangle* s,btHullTriangle*t); + + void checkit(btHullTriangle *t); + + btHullTriangle* extrudable(btScalar epsilon); + + int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit); + + int calchullgen(btVector3 *verts,int verts_count, int vlimit); + + int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow); + + class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice); + + void extrude(class btHullTriangle* t0,int v); + + ConvexH* test_cube(); + + //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. + //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud. + //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull. + //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation. + void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount); + + bool CleanupVertices(unsigned int svcount, + const btVector3* svertices, + unsigned int stride, + unsigned int &vcount, // output number of vertices + btVector3* vertices, // location to store the results. + btScalar normalepsilon, + btVector3& scale); +}; + + +#endif //BT_CD_HULL_H + diff --git a/Code/Physics/src/LinearMath/btConvexHullComputer.cpp b/Code/Physics/src/LinearMath/btConvexHullComputer.cpp new file mode 100644 index 00000000..d58ac955 --- /dev/null +++ b/Code/Physics/src/LinearMath/btConvexHullComputer.cpp @@ -0,0 +1,2755 @@ +/* +Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net + +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 + +#include "btConvexHullComputer.h" +#include "btAlignedObjectArray.h" +#include "btMinMax.h" +#include "btVector3.h" + +#ifdef __GNUC__ + #include +#elif defined(_MSC_VER) + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; +#else + typedef int int32_t; + typedef long long int int64_t; + typedef unsigned int uint32_t; + typedef unsigned long long int uint64_t; +#endif + + +//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines +//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly +// #define USE_X86_64_ASM +//#endif + + +//#define DEBUG_CONVEX_HULL +//#define SHOW_ITERATIONS + +#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS) + #include +#endif + +// Convex hull implementation based on Preparata and Hong +// Ole Kniemeyer, MAXON Computer GmbH +class btConvexHullInternal +{ + public: + + class Point64 + { + public: + int64_t x; + int64_t y; + int64_t z; + + Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z) + { + } + + bool isZero() + { + return (x == 0) && (y == 0) && (z == 0); + } + + int64_t dot(const Point64& b) const + { + return x * b.x + y * b.y + z * b.z; + } + }; + + class Point32 + { + public: + int32_t x; + int32_t y; + int32_t z; + int index; + + Point32() + { + } + + Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1) + { + } + + bool operator==(const Point32& b) const + { + return (x == b.x) && (y == b.y) && (z == b.z); + } + + bool operator!=(const Point32& b) const + { + return (x != b.x) || (y != b.y) || (z != b.z); + } + + bool isZero() + { + return (x == 0) && (y == 0) && (z == 0); + } + + Point64 cross(const Point32& b) const + { + return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + + Point64 cross(const Point64& b) const + { + return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + + int64_t dot(const Point32& b) const + { + return x * b.x + y * b.y + z * b.z; + } + + int64_t dot(const Point64& b) const + { + return x * b.x + y * b.y + z * b.z; + } + + Point32 operator+(const Point32& b) const + { + return Point32(x + b.x, y + b.y, z + b.z); + } + + Point32 operator-(const Point32& b) const + { + return Point32(x - b.x, y - b.y, z - b.z); + } + }; + + class Int128 + { + public: + uint64_t low; + uint64_t high; + + Int128() + { + } + + Int128(uint64_t low, uint64_t high): low(low), high(high) + { + } + + Int128(uint64_t low): low(low), high(0) + { + } + + Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL) + { + } + + static Int128 mul(int64_t a, int64_t b); + + static Int128 mul(uint64_t a, uint64_t b); + + Int128 operator-() const + { + return Int128((uint64_t) -(int64_t)low, ~high + (low == 0)); + } + + Int128 operator+(const Int128& b) const + { +#ifdef USE_X86_64_ASM + Int128 result; + __asm__ ("addq %[bl], %[rl]\n\t" + "adcq %[bh], %[rh]\n\t" + : [rl] "=r" (result.low), [rh] "=r" (result.high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); + return result; +#else + uint64_t lo = low + b.low; + return Int128(lo, high + b.high + (lo < low)); +#endif + } + + Int128 operator-(const Int128& b) const + { +#ifdef USE_X86_64_ASM + Int128 result; + __asm__ ("subq %[bl], %[rl]\n\t" + "sbbq %[bh], %[rh]\n\t" + : [rl] "=r" (result.low), [rh] "=r" (result.high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); + return result; +#else + return *this + -b; +#endif + } + + Int128& operator+=(const Int128& b) + { +#ifdef USE_X86_64_ASM + __asm__ ("addq %[bl], %[rl]\n\t" + "adcq %[bh], %[rh]\n\t" + : [rl] "=r" (low), [rh] "=r" (high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); +#else + uint64_t lo = low + b.low; + if (lo < low) + { + ++high; + } + low = lo; + high += b.high; +#endif + return *this; + } + + Int128& operator++() + { + if (++low == 0) + { + ++high; + } + return *this; + } + + Int128 operator*(int64_t b) const; + + btScalar toScalar() const + { + return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low) + : -(-*this).toScalar(); + } + + int getSign() const + { + return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0; + } + + bool operator<(const Int128& b) const + { + return (high < b.high) || ((high == b.high) && (low < b.low)); + } + + int ucmp(const Int128&b) const + { + if (high < b.high) + { + return -1; + } + if (high > b.high) + { + return 1; + } + if (low < b.low) + { + return -1; + } + if (low > b.low) + { + return 1; + } + return 0; + } + }; + + + class Rational64 + { + private: + uint64_t m_numerator; + uint64_t m_denominator; + int sign; + + public: + Rational64(int64_t numerator, int64_t denominator) + { + if (numerator > 0) + { + sign = 1; + m_numerator = (uint64_t) numerator; + } + else if (numerator < 0) + { + sign = -1; + m_numerator = (uint64_t) -numerator; + } + else + { + sign = 0; + m_numerator = 0; + } + if (denominator > 0) + { + m_denominator = (uint64_t) denominator; + } + else if (denominator < 0) + { + sign = -sign; + m_denominator = (uint64_t) -denominator; + } + else + { + m_denominator = 0; + } + } + + bool isNegativeInfinity() const + { + return (sign < 0) && (m_denominator == 0); + } + + bool isNaN() const + { + return (sign == 0) && (m_denominator == 0); + } + + int compare(const Rational64& b) const; + + btScalar toScalar() const + { + return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator); + } + }; + + + class Rational128 + { + private: + Int128 numerator; + Int128 denominator; + int sign; + bool isInt64; + + public: + Rational128(int64_t value) + { + if (value > 0) + { + sign = 1; + this->numerator = value; + } + else if (value < 0) + { + sign = -1; + this->numerator = -value; + } + else + { + sign = 0; + this->numerator = (uint64_t) 0; + } + this->denominator = (uint64_t) 1; + isInt64 = true; + } + + Rational128(const Int128& numerator, const Int128& denominator) + { + sign = numerator.getSign(); + if (sign >= 0) + { + this->numerator = numerator; + } + else + { + this->numerator = -numerator; + } + int dsign = denominator.getSign(); + if (dsign >= 0) + { + this->denominator = denominator; + } + else + { + sign = -sign; + this->denominator = -denominator; + } + isInt64 = false; + } + + int compare(const Rational128& b) const; + + int compare(int64_t b) const; + + btScalar toScalar() const + { + return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar()); + } + }; + + class PointR128 + { + public: + Int128 x; + Int128 y; + Int128 z; + Int128 denominator; + + PointR128() + { + } + + PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator) + { + } + + btScalar xvalue() const + { + return x.toScalar() / denominator.toScalar(); + } + + btScalar yvalue() const + { + return y.toScalar() / denominator.toScalar(); + } + + btScalar zvalue() const + { + return z.toScalar() / denominator.toScalar(); + } + }; + + + class Edge; + class Face; + + class Vertex + { + public: + Vertex* next; + Vertex* prev; + Edge* edges; + Face* firstNearbyFace; + Face* lastNearbyFace; + PointR128 point128; + Point32 point; + int copy; + + Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1) + { + } + +#ifdef DEBUG_CONVEX_HULL + void print() + { + printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z); + } + + void printGraph(); +#endif + + Point32 operator-(const Vertex& b) const + { + return point - b.point; + } + + Rational128 dot(const Point64& b) const + { + return (point.index >= 0) ? Rational128(point.dot(b)) + : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator); + } + + btScalar xvalue() const + { + return (point.index >= 0) ? btScalar(point.x) : point128.xvalue(); + } + + btScalar yvalue() const + { + return (point.index >= 0) ? btScalar(point.y) : point128.yvalue(); + } + + btScalar zvalue() const + { + return (point.index >= 0) ? btScalar(point.z) : point128.zvalue(); + } + + void receiveNearbyFaces(Vertex* src) + { + if (lastNearbyFace) + { + lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace; + } + else + { + firstNearbyFace = src->firstNearbyFace; + } + if (src->lastNearbyFace) + { + lastNearbyFace = src->lastNearbyFace; + } + for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex) + { + btAssert(f->nearbyVertex == src); + f->nearbyVertex = this; + } + src->firstNearbyFace = NULL; + src->lastNearbyFace = NULL; + } + }; + + + class Edge + { + public: + Edge* next; + Edge* prev; + Edge* reverse; + Vertex* target; + Face* face; + int copy; + + ~Edge() + { + next = NULL; + prev = NULL; + reverse = NULL; + target = NULL; + face = NULL; + } + + void link(Edge* n) + { + btAssert(reverse->target == n->reverse->target); + next = n; + n->prev = this; + } + +#ifdef DEBUG_CONVEX_HULL + void print() + { + printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev, + reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z); + } +#endif + }; + + class Face + { + public: + Face* next; + Vertex* nearbyVertex; + Face* nextWithSameNearbyVertex; + Point32 origin; + Point32 dir0; + Point32 dir1; + + Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL) + { + } + + void init(Vertex* a, Vertex* b, Vertex* c) + { + nearbyVertex = a; + origin = a->point; + dir0 = *b - *a; + dir1 = *c - *a; + if (a->lastNearbyFace) + { + a->lastNearbyFace->nextWithSameNearbyVertex = this; + } + else + { + a->firstNearbyFace = this; + } + a->lastNearbyFace = this; + } + + Point64 getNormal() + { + return dir0.cross(dir1); + } + }; + + template class DMul + { + private: + static uint32_t high(uint64_t value) + { + return (uint32_t) (value >> 32); + } + + static uint32_t low(uint64_t value) + { + return (uint32_t) value; + } + + static uint64_t mul(uint32_t a, uint32_t b) + { + return (uint64_t) a * (uint64_t) b; + } + + static void shlHalf(uint64_t& value) + { + value <<= 32; + } + + static uint64_t high(Int128 value) + { + return value.high; + } + + static uint64_t low(Int128 value) + { + return value.low; + } + + static Int128 mul(uint64_t a, uint64_t b) + { + return Int128::mul(a, b); + } + + static void shlHalf(Int128& value) + { + value.high = value.low; + value.low = 0; + } + + public: + + static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh) + { + UWord p00 = mul(low(a), low(b)); + UWord p01 = mul(low(a), high(b)); + UWord p10 = mul(high(a), low(b)); + UWord p11 = mul(high(a), high(b)); + UWord p0110 = UWord(low(p01)) + UWord(low(p10)); + p11 += high(p01); + p11 += high(p10); + p11 += high(p0110); + shlHalf(p0110); + p00 += p0110; + if (p00 < p0110) + { + ++p11; + } + resLow = p00; + resHigh = p11; + } + }; + + private: + + class IntermediateHull + { + public: + Vertex* minXy; + Vertex* maxXy; + Vertex* minYx; + Vertex* maxYx; + + IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL) + { + } + + void print(); + }; + + enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE}; + + template class PoolArray + { + private: + T* array; + int size; + + public: + PoolArray* next; + + PoolArray(int size): size(size), next(NULL) + { + array = (T*) btAlignedAlloc(sizeof(T) * size, 16); + } + + ~PoolArray() + { + btAlignedFree(array); + } + + T* init() + { + T* o = array; + for (int i = 0; i < size; i++, o++) + { + o->next = (i+1 < size) ? o + 1 : NULL; + } + return array; + } + }; + + template class Pool + { + private: + PoolArray* arrays; + PoolArray* nextArray; + T* freeObjects; + int arraySize; + + public: + Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256) + { + } + + ~Pool() + { + while (arrays) + { + PoolArray* p = arrays; + arrays = p->next; + p->~PoolArray(); + btAlignedFree(p); + } + } + + void reset() + { + nextArray = arrays; + freeObjects = NULL; + } + + void setArraySize(int arraySize) + { + this->arraySize = arraySize; + } + + T* newObject() + { + T* o = freeObjects; + if (!o) + { + PoolArray* p = nextArray; + if (p) + { + nextArray = p->next; + } + else + { + p = new(btAlignedAlloc(sizeof(PoolArray), 16)) PoolArray(arraySize); + p->next = arrays; + arrays = p; + } + o = p->init(); + } + freeObjects = o->next; + return new(o) T(); + }; + + void freeObject(T* object) + { + object->~T(); + object->next = freeObjects; + freeObjects = object; + } + }; + + btVector3 scaling; + btVector3 center; + Pool vertexPool; + Pool edgePool; + Pool facePool; + btAlignedObjectArray originalVertices; + int mergeStamp; + int minAxis; + int medAxis; + int maxAxis; + int usedEdgePairs; + int maxUsedEdgePairs; + + static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t); + Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot); + void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1); + + Edge* newEdgePair(Vertex* from, Vertex* to); + + void removeEdgePair(Edge* edge) + { + Edge* n = edge->next; + Edge* r = edge->reverse; + + btAssert(edge->target && r->target); + + if (n != edge) + { + n->prev = edge->prev; + edge->prev->next = n; + r->target->edges = n; + } + else + { + r->target->edges = NULL; + } + + n = r->next; + + if (n != r) + { + n->prev = r->prev; + r->prev->next = n; + edge->target->edges = n; + } + else + { + edge->target->edges = NULL; + } + + edgePool.freeObject(edge); + edgePool.freeObject(r); + usedEdgePairs--; + } + + void computeInternal(int start, int end, IntermediateHull& result); + + bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1); + + void merge(IntermediateHull& h0, IntermediateHull& h1); + + btVector3 toBtVector(const Point32& v); + + btVector3 getBtNormal(Face* face); + + bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray stack); + + public: + Vertex* vertexList; + + void compute(const void* coords, bool doubleCoords, int stride, int count); + + btVector3 getCoordinates(const Vertex* v); + + btScalar shrink(btScalar amount, btScalar clampAmount); +}; + + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const +{ + bool negative = (int64_t) high < 0; + Int128 a = negative ? -*this : *this; + if (b < 0) + { + negative = !negative; + b = -b; + } + Int128 result = mul(a.low, (uint64_t) b); + result.high += a.high * (uint64_t) b; + return negative ? -result : result; +} + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b) +{ + Int128 result; + +#ifdef USE_X86_64_ASM + __asm__ ("imulq %[b]" + : "=a" (result.low), "=d" (result.high) + : "0"(a), [b] "r"(b) + : "cc" ); + return result; + +#else + bool negative = a < 0; + if (negative) + { + a = -a; + } + if (b < 0) + { + negative = !negative; + b = -b; + } + DMul::mul((uint64_t) a, (uint64_t) b, result.low, result.high); + return negative ? -result : result; +#endif +} + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b) +{ + Int128 result; + +#ifdef USE_X86_64_ASM + __asm__ ("mulq %[b]" + : "=a" (result.low), "=d" (result.high) + : "0"(a), [b] "r"(b) + : "cc" ); + +#else + DMul::mul(a, b, result.low, result.high); +#endif + + return result; +} + +int btConvexHullInternal::Rational64::compare(const Rational64& b) const +{ + if (sign != b.sign) + { + return sign - b.sign; + } + else if (sign == 0) + { + return 0; + } + + // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0; + +#ifdef USE_X86_64_ASM + + int result; + int64_t tmp; + int64_t dummy; + __asm__ ("mulq %[bn]\n\t" + "movq %%rax, %[tmp]\n\t" + "movq %%rdx, %%rbx\n\t" + "movq %[tn], %%rax\n\t" + "mulq %[bd]\n\t" + "subq %[tmp], %%rax\n\t" + "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator" + "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise + "orq %%rdx, %%rax\n\t" + "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero + "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference) + "shll $16, %%ebx\n\t" // ebx has same sign as difference + : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy) + : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator) + : "%rdx", "cc" ); + return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero) + // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero) + : 0; + +#else + + return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator)); + +#endif +} + +int btConvexHullInternal::Rational128::compare(const Rational128& b) const +{ + if (sign != b.sign) + { + return sign - b.sign; + } + else if (sign == 0) + { + return 0; + } + if (isInt64) + { + return -b.compare(sign * (int64_t) numerator.low); + } + + Int128 nbdLow, nbdHigh, dbnLow, dbnHigh; + DMul::mul(numerator, b.denominator, nbdLow, nbdHigh); + DMul::mul(denominator, b.numerator, dbnLow, dbnHigh); + + int cmp = nbdHigh.ucmp(dbnHigh); + if (cmp) + { + return cmp * sign; + } + return nbdLow.ucmp(dbnLow) * sign; +} + +int btConvexHullInternal::Rational128::compare(int64_t b) const +{ + if (isInt64) + { + int64_t a = sign * (int64_t) numerator.low; + return (a > b) ? 1 : (a < b) ? -1 : 0; + } + if (b > 0) + { + if (sign <= 0) + { + return -1; + } + } + else if (b < 0) + { + if (sign >= 0) + { + return 1; + } + b = -b; + } + else + { + return sign; + } + + return numerator.ucmp(denominator * b) * sign; +} + + +btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to) +{ + btAssert(from && to); + Edge* e = edgePool.newObject(); + Edge* r = edgePool.newObject(); + e->reverse = r; + r->reverse = e; + e->copy = mergeStamp; + r->copy = mergeStamp; + e->target = to; + r->target = from; + e->face = NULL; + r->face = NULL; + usedEdgePairs++; + if (usedEdgePairs > maxUsedEdgePairs) + { + maxUsedEdgePairs = usedEdgePairs; + } + return e; +} + +bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1) +{ + Vertex* v0 = h0.maxYx; + Vertex* v1 = h1.minYx; + if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y)) + { + btAssert(v0->point.z < v1->point.z); + Vertex* v1p = v1->prev; + if (v1p == v1) + { + c0 = v0; + if (v1->edges) + { + btAssert(v1->edges->next == v1->edges); + v1 = v1->edges->target; + btAssert(v1->edges->next == v1->edges); + } + c1 = v1; + return false; + } + Vertex* v1n = v1->next; + v1p->next = v1n; + v1n->prev = v1p; + if (v1 == h1.minXy) + { + if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y))) + { + h1.minXy = v1n; + } + else + { + h1.minXy = v1p; + } + } + if (v1 == h1.maxXy) + { + if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y))) + { + h1.maxXy = v1n; + } + else + { + h1.maxXy = v1p; + } + } + } + + v0 = h0.maxXy; + v1 = h1.maxXy; + Vertex* v00 = NULL; + Vertex* v10 = NULL; + int32_t sign = 1; + + for (int side = 0; side <= 1; side++) + { + int32_t dx = (v1->point.x - v0->point.x) * sign; + if (dx > 0) + { + while (true) + { + int32_t dy = v1->point.y - v0->point.y; + + Vertex* w0 = side ? v0->next : v0->prev; + if (w0 != v0) + { + int32_t dx0 = (w0->point.x - v0->point.x) * sign; + int32_t dy0 = w0->point.y - v0->point.y; + if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0)))) + { + v0 = w0; + dx = (v1->point.x - v0->point.x) * sign; + continue; + } + } + + Vertex* w1 = side ? v1->next : v1->prev; + if (w1 != v1) + { + int32_t dx1 = (w1->point.x - v1->point.x) * sign; + int32_t dy1 = w1->point.y - v1->point.y; + int32_t dxn = (w1->point.x - v0->point.x) * sign; + if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1)))) + { + v1 = w1; + dx = dxn; + continue; + } + } + + break; + } + } + else if (dx < 0) + { + while (true) + { + int32_t dy = v1->point.y - v0->point.y; + + Vertex* w1 = side ? v1->prev : v1->next; + if (w1 != v1) + { + int32_t dx1 = (w1->point.x - v1->point.x) * sign; + int32_t dy1 = w1->point.y - v1->point.y; + if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1)))) + { + v1 = w1; + dx = (v1->point.x - v0->point.x) * sign; + continue; + } + } + + Vertex* w0 = side ? v0->prev : v0->next; + if (w0 != v0) + { + int32_t dx0 = (w0->point.x - v0->point.x) * sign; + int32_t dy0 = w0->point.y - v0->point.y; + int32_t dxn = (v1->point.x - w0->point.x) * sign; + if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0)))) + { + v0 = w0; + dx = dxn; + continue; + } + } + + break; + } + } + else + { + int32_t x = v0->point.x; + int32_t y0 = v0->point.y; + Vertex* w0 = v0; + Vertex* t; + while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0)) + { + w0 = t; + y0 = t->point.y; + } + v0 = w0; + + int32_t y1 = v1->point.y; + Vertex* w1 = v1; + while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1)) + { + w1 = t; + y1 = t->point.y; + } + v1 = w1; + } + + if (side == 0) + { + v00 = v0; + v10 = v1; + + v0 = h0.minXy; + v1 = h1.minXy; + sign = -1; + } + } + + v0->prev = v1; + v1->next = v0; + + v00->next = v10; + v10->prev = v00; + + if (h1.minXy->point.x < h0.minXy->point.x) + { + h0.minXy = h1.minXy; + } + if (h1.maxXy->point.x >= h0.maxXy->point.x) + { + h0.maxXy = h1.maxXy; + } + + h0.maxYx = h1.maxYx; + + c0 = v00; + c1 = v10; + + return true; +} + +void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result) +{ + int n = end - start; + switch (n) + { + case 0: + result.minXy = NULL; + result.maxXy = NULL; + result.minYx = NULL; + result.maxYx = NULL; + return; + case 2: + { + Vertex* v = originalVertices[start]; + Vertex* w = v + 1; + if (v->point != w->point) + { + int32_t dx = v->point.x - w->point.x; + int32_t dy = v->point.y - w->point.y; + + if ((dx == 0) && (dy == 0)) + { + if (v->point.z > w->point.z) + { + Vertex* t = w; + w = v; + v = t; + } + btAssert(v->point.z < w->point.z); + v->next = v; + v->prev = v; + result.minXy = v; + result.maxXy = v; + result.minYx = v; + result.maxYx = v; + } + else + { + v->next = w; + v->prev = w; + w->next = v; + w->prev = v; + + if ((dx < 0) || ((dx == 0) && (dy < 0))) + { + result.minXy = v; + result.maxXy = w; + } + else + { + result.minXy = w; + result.maxXy = v; + } + + if ((dy < 0) || ((dy == 0) && (dx < 0))) + { + result.minYx = v; + result.maxYx = w; + } + else + { + result.minYx = w; + result.maxYx = v; + } + } + + Edge* e = newEdgePair(v, w); + e->link(e); + v->edges = e; + + e = e->reverse; + e->link(e); + w->edges = e; + + return; + } + } + // lint -fallthrough + case 1: + { + Vertex* v = originalVertices[start]; + v->edges = NULL; + v->next = v; + v->prev = v; + + result.minXy = v; + result.maxXy = v; + result.minYx = v; + result.maxYx = v; + + return; + } + } + + int split0 = start + n / 2; + Point32 p = originalVertices[split0-1]->point; + int split1 = split0; + while ((split1 < end) && (originalVertices[split1]->point == p)) + { + split1++; + } + computeInternal(start, split0, result); + IntermediateHull hull1; + computeInternal(split1, end, hull1); +#ifdef DEBUG_CONVEX_HULL + printf("\n\nMerge\n"); + result.print(); + hull1.print(); +#endif + merge(result, hull1); +#ifdef DEBUG_CONVEX_HULL + printf("\n Result\n"); + result.print(); +#endif +} + +#ifdef DEBUG_CONVEX_HULL +void btConvexHullInternal::IntermediateHull::print() +{ + printf(" Hull\n"); + for (Vertex* v = minXy; v; ) + { + printf(" "); + v->print(); + if (v == maxXy) + { + printf(" maxXy"); + } + if (v == minYx) + { + printf(" minYx"); + } + if (v == maxYx) + { + printf(" maxYx"); + } + if (v->next->prev != v) + { + printf(" Inconsistency"); + } + printf("\n"); + v = v->next; + if (v == minXy) + { + break; + } + } + if (minXy) + { + minXy->copy = (minXy->copy == -1) ? -2 : -1; + minXy->printGraph(); + } +} + +void btConvexHullInternal::Vertex::printGraph() +{ + print(); + printf("\nEdges\n"); + Edge* e = edges; + if (e) + { + do + { + e->print(); + printf("\n"); + e = e->next; + } while (e != edges); + do + { + Vertex* v = e->target; + if (v->copy != copy) + { + v->copy = copy; + v->printGraph(); + } + e = e->next; + } while (e != edges); + } +} +#endif + +btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t) +{ + btAssert(prev->reverse->target == next->reverse->target); + if (prev->next == next) + { + if (prev->prev == next) + { + Point64 n = t.cross(s); + Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target); + btAssert(!m.isZero()); + int64_t dot = n.dot(m); + btAssert(dot != 0); + return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE; + } + return COUNTER_CLOCKWISE; + } + else if (prev->prev == next) + { + return CLOCKWISE; + } + else + { + return NONE; + } +} + +btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot) +{ + Edge* minEdge = NULL; + +#ifdef DEBUG_CONVEX_HULL + printf("find max edge for %d\n", start->point.index); +#endif + Edge* e = start->edges; + if (e) + { + do + { + if (e->copy > mergeStamp) + { + Point32 t = *e->target - *start; + Rational64 cot(t.dot(sxrxs), t.dot(rxs)); +#ifdef DEBUG_CONVEX_HULL + printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN()); + e->print(); +#endif + if (cot.isNaN()) + { + btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0)); + } + else + { + int cmp; + if (minEdge == NULL) + { + minCot = cot; + minEdge = e; + } + else if ((cmp = cot.compare(minCot)) < 0) + { + minCot = cot; + minEdge = e; + } + else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE))) + { + minEdge = e; + } + } +#ifdef DEBUG_CONVEX_HULL + printf("\n"); +#endif + } + e = e->next; + } while (e != start->edges); + } + return minEdge; +} + +void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1) +{ + Edge* start0 = e0; + Edge* start1 = e1; + Point32 et0 = start0 ? start0->target->point : c0->point; + Point32 et1 = start1 ? start1->target->point : c1->point; + Point32 s = c1->point - c0->point; + Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s); + int64_t dist = c0->point.dot(normal); + btAssert(!start1 || (start1->target->point.dot(normal) == dist)); + Point64 perp = s.cross(normal); + btAssert(!perp.isZero()); + +#ifdef DEBUG_CONVEX_HULL + printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1); +#endif + + int64_t maxDot0 = et0.dot(perp); + if (e0) + { + while (e0->target != stop0) + { + Edge* e = e0->reverse->prev; + if (e->target->point.dot(normal) < dist) + { + break; + } + btAssert(e->target->point.dot(normal) == dist); + if (e->copy == mergeStamp) + { + break; + } + int64_t dot = e->target->point.dot(perp); + if (dot <= maxDot0) + { + break; + } + maxDot0 = dot; + e0 = e; + et0 = e->target->point; + } + } + + int64_t maxDot1 = et1.dot(perp); + if (e1) + { + while (e1->target != stop1) + { + Edge* e = e1->reverse->next; + if (e->target->point.dot(normal) < dist) + { + break; + } + btAssert(e->target->point.dot(normal) == dist); + if (e->copy == mergeStamp) + { + break; + } + int64_t dot = e->target->point.dot(perp); + if (dot <= maxDot1) + { + break; + } + maxDot1 = dot; + e1 = e; + et1 = e->target->point; + } + } + +#ifdef DEBUG_CONVEX_HULL + printf(" Starting at %d %d\n", et0.index, et1.index); +#endif + + int64_t dx = maxDot1 - maxDot0; + if (dx > 0) + { + while (true) + { + int64_t dy = (et1 - et0).dot(s); + + if (e0 && (e0->target != stop0)) + { + Edge* f0 = e0->next->reverse; + if (f0->copy > mergeStamp) + { + int64_t dx0 = (f0->target->point - et0).dot(perp); + int64_t dy0 = (f0->target->point - et0).dot(s); + if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0))) + { + et0 = f0->target->point; + dx = (et1 - et0).dot(perp); + e0 = (e0 == start0) ? NULL : f0; + continue; + } + } + } + + if (e1 && (e1->target != stop1)) + { + Edge* f1 = e1->reverse->next; + if (f1->copy > mergeStamp) + { + Point32 d1 = f1->target->point - et1; + if (d1.dot(normal) == 0) + { + int64_t dx1 = d1.dot(perp); + int64_t dy1 = d1.dot(s); + int64_t dxn = (f1->target->point - et0).dot(perp); + if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0)))) + { + e1 = f1; + et1 = e1->target->point; + dx = dxn; + continue; + } + } + else + { + btAssert((e1 == start1) && (d1.dot(normal) < 0)); + } + } + } + + break; + } + } + else if (dx < 0) + { + while (true) + { + int64_t dy = (et1 - et0).dot(s); + + if (e1 && (e1->target != stop1)) + { + Edge* f1 = e1->prev->reverse; + if (f1->copy > mergeStamp) + { + int64_t dx1 = (f1->target->point - et1).dot(perp); + int64_t dy1 = (f1->target->point - et1).dot(s); + if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0))) + { + et1 = f1->target->point; + dx = (et1 - et0).dot(perp); + e1 = (e1 == start1) ? NULL : f1; + continue; + } + } + } + + if (e0 && (e0->target != stop0)) + { + Edge* f0 = e0->reverse->prev; + if (f0->copy > mergeStamp) + { + Point32 d0 = f0->target->point - et0; + if (d0.dot(normal) == 0) + { + int64_t dx0 = d0.dot(perp); + int64_t dy0 = d0.dot(s); + int64_t dxn = (et1 - f0->target->point).dot(perp); + if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0)))) + { + e0 = f0; + et0 = e0->target->point; + dx = dxn; + continue; + } + } + else + { + btAssert((e0 == start0) && (d0.dot(normal) < 0)); + } + } + } + + break; + } + } +#ifdef DEBUG_CONVEX_HULL + printf(" Advanced edges to %d %d\n", et0.index, et1.index); +#endif +} + + +void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1) +{ + if (!h1.maxXy) + { + return; + } + if (!h0.maxXy) + { + h0 = h1; + return; + } + + mergeStamp--; + + Vertex* c0 = NULL; + Edge* toPrev0 = NULL; + Edge* firstNew0 = NULL; + Edge* pendingHead0 = NULL; + Edge* pendingTail0 = NULL; + Vertex* c1 = NULL; + Edge* toPrev1 = NULL; + Edge* firstNew1 = NULL; + Edge* pendingHead1 = NULL; + Edge* pendingTail1 = NULL; + Point32 prevPoint; + + if (mergeProjection(h0, h1, c0, c1)) + { + Point32 s = *c1 - *c0; + Point64 normal = Point32(0, 0, -1).cross(s); + Point64 t = s.cross(normal); + btAssert(!t.isZero()); + + Edge* e = c0->edges; + Edge* start0 = NULL; + if (e) + { + do + { + int64_t dot = (*e->target - *c0).dot(normal); + btAssert(dot <= 0); + if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) + { + if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) + { + start0 = e; + } + } + e = e->next; + } while (e != c0->edges); + } + + e = c1->edges; + Edge* start1 = NULL; + if (e) + { + do + { + int64_t dot = (*e->target - *c1).dot(normal); + btAssert(dot <= 0); + if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) + { + if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) + { + start1 = e; + } + } + e = e->next; + } while (e != c1->edges); + } + + if (start0 || start1) + { + findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL); + if (start0) + { + c0 = start0->target; + } + if (start1) + { + c1 = start1->target; + } + } + + prevPoint = c1->point; + prevPoint.z++; + } + else + { + prevPoint = c1->point; + prevPoint.x++; + } + + Vertex* first0 = c0; + Vertex* first1 = c1; + bool firstRun = true; + + while (true) + { + Point32 s = *c1 - *c0; + Point32 r = prevPoint - c0->point; + Point64 rxs = r.cross(s); + Point64 sxrxs = s.cross(rxs); + +#ifdef DEBUG_CONVEX_HULL + printf("\n Checking %d %d\n", c0->point.index, c1->point.index); +#endif + Rational64 minCot0(0, 0); + Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0); + Rational64 minCot1(0, 0); + Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1); + if (!min0 && !min1) + { + Edge* e = newEdgePair(c0, c1); + e->link(e); + c0->edges = e; + + e = e->reverse; + e->link(e); + c1->edges = e; + return; + } + else + { + int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1); +#ifdef DEBUG_CONVEX_HULL + printf(" -> Result %d\n", cmp); +#endif + if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity())) + { + Edge* e = newEdgePair(c0, c1); + if (pendingTail0) + { + pendingTail0->prev = e; + } + else + { + pendingHead0 = e; + } + e->next = pendingTail0; + pendingTail0 = e; + + e = e->reverse; + if (pendingTail1) + { + pendingTail1->next = e; + } + else + { + pendingHead1 = e; + } + e->prev = pendingTail1; + pendingTail1 = e; + } + + Edge* e0 = min0; + Edge* e1 = min1; + +#ifdef DEBUG_CONVEX_HULL + printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1); +#endif + + if (cmp == 0) + { + findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL); + } + + if ((cmp >= 0) && e1) + { + if (toPrev1) + { + for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n) + { + n = e->next; + removeEdgePair(e); + } + } + + if (pendingTail1) + { + if (toPrev1) + { + toPrev1->link(pendingHead1); + } + else + { + min1->prev->link(pendingHead1); + firstNew1 = pendingHead1; + } + pendingTail1->link(min1); + pendingHead1 = NULL; + pendingTail1 = NULL; + } + else if (!toPrev1) + { + firstNew1 = min1; + } + + prevPoint = c1->point; + c1 = e1->target; + toPrev1 = e1->reverse; + } + + if ((cmp <= 0) && e0) + { + if (toPrev0) + { + for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n) + { + n = e->prev; + removeEdgePair(e); + } + } + + if (pendingTail0) + { + if (toPrev0) + { + pendingHead0->link(toPrev0); + } + else + { + pendingHead0->link(min0->next); + firstNew0 = pendingHead0; + } + min0->link(pendingTail0); + pendingHead0 = NULL; + pendingTail0 = NULL; + } + else if (!toPrev0) + { + firstNew0 = min0; + } + + prevPoint = c0->point; + c0 = e0->target; + toPrev0 = e0->reverse; + } + } + + if ((c0 == first0) && (c1 == first1)) + { + if (toPrev0 == NULL) + { + pendingHead0->link(pendingTail0); + c0->edges = pendingTail0; + } + else + { + for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n) + { + n = e->prev; + removeEdgePair(e); + } + if (pendingTail0) + { + pendingHead0->link(toPrev0); + firstNew0->link(pendingTail0); + } + } + + if (toPrev1 == NULL) + { + pendingTail1->link(pendingHead1); + c1->edges = pendingTail1; + } + else + { + for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n) + { + n = e->next; + removeEdgePair(e); + } + if (pendingTail1) + { + toPrev1->link(pendingHead1); + pendingTail1->link(firstNew1); + } + } + + return; + } + + firstRun = false; + } +} + +class pointCmp +{ + public: + + bool operator() ( const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q ) const + { + return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z)))); + } +}; + +void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count) +{ + btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30)); + const char* ptr = (const char*) coords; + if (doubleCoords) + { + for (int i = 0; i < count; i++) + { + const double* v = (const double*) ptr; + btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); + ptr += stride; + min.setMin(p); + max.setMax(p); + } + } + else + { + for (int i = 0; i < count; i++) + { + const float* v = (const float*) ptr; + btVector3 p(v[0], v[1], v[2]); + ptr += stride; + min.setMin(p); + max.setMax(p); + } + } + + btVector3 s = max - min; + maxAxis = s.maxAxis(); + minAxis = s.minAxis(); + if (minAxis == maxAxis) + { + minAxis = (maxAxis + 1) % 3; + } + medAxis = 3 - maxAxis - minAxis; + + s /= btScalar(10216); + if (((medAxis + 1) % 3) != maxAxis) + { + s *= -1; + } + scaling = s; + + if (s[0] != 0) + { + s[0] = btScalar(1) / s[0]; + } + if (s[1] != 0) + { + s[1] = btScalar(1) / s[1]; + } + if (s[2] != 0) + { + s[2] = btScalar(1) / s[2]; + } + + center = (min + max) * btScalar(0.5); + + btAlignedObjectArray points; + points.resize(count); + ptr = (const char*) coords; + if (doubleCoords) + { + for (int i = 0; i < count; i++) + { + const double* v = (const double*) ptr; + btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); + ptr += stride; + p = (p - center) * s; + points[i].x = (int32_t) p[medAxis]; + points[i].y = (int32_t) p[maxAxis]; + points[i].z = (int32_t) p[minAxis]; + points[i].index = i; + } + } + else + { + for (int i = 0; i < count; i++) + { + const float* v = (const float*) ptr; + btVector3 p(v[0], v[1], v[2]); + ptr += stride; + p = (p - center) * s; + points[i].x = (int32_t) p[medAxis]; + points[i].y = (int32_t) p[maxAxis]; + points[i].z = (int32_t) p[minAxis]; + points[i].index = i; + } + } + points.quickSort(pointCmp()); + + vertexPool.reset(); + vertexPool.setArraySize(count); + originalVertices.resize(count); + for (int i = 0; i < count; i++) + { + Vertex* v = vertexPool.newObject(); + v->edges = NULL; + v->point = points[i]; + v->copy = -1; + originalVertices[i] = v; + } + + points.clear(); + + edgePool.reset(); + edgePool.setArraySize(6 * count); + + usedEdgePairs = 0; + maxUsedEdgePairs = 0; + + mergeStamp = -3; + + IntermediateHull hull; + computeInternal(0, count, hull); + vertexList = hull.minXy; +#ifdef DEBUG_CONVEX_HULL + printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count); +#endif +} + +btVector3 btConvexHullInternal::toBtVector(const Point32& v) +{ + btVector3 p; + p[medAxis] = btScalar(v.x); + p[maxAxis] = btScalar(v.y); + p[minAxis] = btScalar(v.z); + return p * scaling; +} + +btVector3 btConvexHullInternal::getBtNormal(Face* face) +{ + return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized(); +} + +btVector3 btConvexHullInternal::getCoordinates(const Vertex* v) +{ + btVector3 p; + p[medAxis] = v->xvalue(); + p[maxAxis] = v->yvalue(); + p[minAxis] = v->zvalue(); + return p * scaling + center; +} + +btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount) +{ + if (!vertexList) + { + return 0; + } + int stamp = --mergeStamp; + btAlignedObjectArray stack; + vertexList->copy = stamp; + stack.push_back(vertexList); + btAlignedObjectArray faces; + + Point32 ref = vertexList->point; + Int128 hullCenterX(0, 0); + Int128 hullCenterY(0, 0); + Int128 hullCenterZ(0, 0); + Int128 volume(0, 0); + + while (stack.size() > 0) + { + Vertex* v = stack[stack.size() - 1]; + stack.pop_back(); + Edge* e = v->edges; + if (e) + { + do + { + if (e->target->copy != stamp) + { + e->target->copy = stamp; + stack.push_back(e->target); + } + if (e->copy != stamp) + { + Face* face = facePool.newObject(); + face->init(e->target, e->reverse->prev->target, v); + faces.push_back(face); + Edge* f = e; + + Vertex* a = NULL; + Vertex* b = NULL; + do + { + if (a && b) + { + int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref)); + btAssert(vol >= 0); + Point32 c = v->point + a->point + b->point + ref; + hullCenterX += vol * c.x; + hullCenterY += vol * c.y; + hullCenterZ += vol * c.z; + volume += vol; + } + + btAssert(f->copy != stamp); + f->copy = stamp; + f->face = face; + + a = b; + b = f->target; + + f = f->reverse->prev; + } while (f != e); + } + e = e->next; + } while (e != v->edges); + } + } + + if (volume.getSign() <= 0) + { + return 0; + } + + btVector3 hullCenter; + hullCenter[medAxis] = hullCenterX.toScalar(); + hullCenter[maxAxis] = hullCenterY.toScalar(); + hullCenter[minAxis] = hullCenterZ.toScalar(); + hullCenter /= 4 * volume.toScalar(); + hullCenter *= scaling; + + int faceCount = faces.size(); + + if (clampAmount > 0) + { + btScalar minDist = SIMD_INFINITY; + for (int i = 0; i < faceCount; i++) + { + btVector3 normal = getBtNormal(faces[i]); + btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter); + if (dist < minDist) + { + minDist = dist; + } + } + + if (minDist <= 0) + { + return 0; + } + + amount = btMin(amount, minDist * clampAmount); + } + + unsigned int seed = 243703; + for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223) + { + btSwap(faces[i], faces[seed % faceCount]); + } + + for (int i = 0; i < faceCount; i++) + { + if (!shiftFace(faces[i], amount, stack)) + { + return -amount; + } + } + + return amount; +} + +bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray stack) +{ + btVector3 origShift = getBtNormal(face) * -amount; + if (scaling[0] != 0) + { + origShift[0] /= scaling[0]; + } + if (scaling[1] != 0) + { + origShift[1] /= scaling[1]; + } + if (scaling[2] != 0) + { + origShift[2] /= scaling[2]; + } + Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]); + if (shift.isZero()) + { + return true; + } + Point64 normal = face->getNormal(); +#ifdef DEBUG_CONVEX_HULL + printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n", + face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z); +#endif + int64_t origDot = face->origin.dot(normal); + Point32 shiftedOrigin = face->origin + shift; + int64_t shiftedDot = shiftedOrigin.dot(normal); + btAssert(shiftedDot <= origDot); + if (shiftedDot >= origDot) + { + return false; + } + + Edge* intersection = NULL; + + Edge* startEdge = face->nearbyVertex->edges; +#ifdef DEBUG_CONVEX_HULL + printf("Start edge is "); + startEdge->print(); + printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot); +#endif + Rational128 optDot = face->nearbyVertex->dot(normal); + int cmp = optDot.compare(shiftedDot); +#ifdef SHOW_ITERATIONS + int n = 0; +#endif + if (cmp >= 0) + { + Edge* e = startEdge; + do + { +#ifdef SHOW_ITERATIONS + n++; +#endif + Rational128 dot = e->target->dot(normal); + btAssert(dot.compare(origDot) <= 0); +#ifdef DEBUG_CONVEX_HULL + printf("Moving downwards, edge is "); + e->print(); + printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); +#endif + if (dot.compare(optDot) < 0) + { + int c = dot.compare(shiftedDot); + optDot = dot; + e = e->reverse; + startEdge = e; + if (c < 0) + { + intersection = e; + break; + } + cmp = c; + } + e = e->prev; + } while (e != startEdge); + + if (!intersection) + { + return false; + } + } + else + { + Edge* e = startEdge; + do + { +#ifdef SHOW_ITERATIONS + n++; +#endif + Rational128 dot = e->target->dot(normal); + btAssert(dot.compare(origDot) <= 0); +#ifdef DEBUG_CONVEX_HULL + printf("Moving upwards, edge is "); + e->print(); + printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); +#endif + if (dot.compare(optDot) > 0) + { + cmp = dot.compare(shiftedDot); + if (cmp >= 0) + { + intersection = e; + break; + } + optDot = dot; + e = e->reverse; + startEdge = e; + } + e = e->prev; + } while (e != startEdge); + + if (!intersection) + { + return true; + } + } + +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to find initial intersection\n", n); +#endif + + if (cmp == 0) + { + Edge* e = intersection->reverse->next; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (e->target->dot(normal).compare(shiftedDot) <= 0) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + e = e->next; + if (e == intersection->reverse) + { + return true; + } +#ifdef DEBUG_CONVEX_HULL + printf("Checking for outwards edge, current edge is "); + e->print(); + printf("\n"); +#endif + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to check for complete containment\n", n); +#endif + } + + Edge* firstIntersection = NULL; + Edge* faceEdge = NULL; + Edge* firstFaceEdge = NULL; + +#ifdef SHOW_ITERATIONS + int m = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + m++; +#endif +#ifdef DEBUG_CONVEX_HULL + printf("Intersecting edge is "); + intersection->print(); + printf("\n"); +#endif + if (cmp == 0) + { + Edge* e = intersection->reverse->next; + startEdge = e; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + if (e->target->dot(normal).compare(shiftedDot) >= 0) + { + break; + } + intersection = e->reverse; + e = e->next; + if (e == startEdge) + { + return true; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to advance intersection\n", n); +#endif + } + +#ifdef DEBUG_CONVEX_HULL + printf("Advanced intersecting edge to "); + intersection->print(); + printf(", cmp = %d\n", cmp); +#endif + + if (!firstIntersection) + { + firstIntersection = intersection; + } + else if (intersection == firstIntersection) + { + break; + } + + int prevCmp = cmp; + Edge* prevIntersection = intersection; + Edge* prevFaceEdge = faceEdge; + + Edge* e = intersection->reverse; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + e = e->reverse->prev; + btAssert(e != intersection->reverse); + cmp = e->target->dot(normal).compare(shiftedDot); +#ifdef DEBUG_CONVEX_HULL + printf("Testing edge "); + e->print(); + printf(" -> cmp = %d\n", cmp); +#endif + if (cmp >= 0) + { + intersection = e; + break; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to find other intersection of face\n", n); +#endif + + if (cmp > 0) + { + Vertex* removed = intersection->target; + e = intersection->reverse; + if (e->prev == e) + { + removed->edges = NULL; + } + else + { + removed->edges = e->prev; + e->prev->link(e->next); + e->link(e); + } +#ifdef DEBUG_CONVEX_HULL + printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + + Point64 n0 = intersection->face->getNormal(); + Point64 n1 = intersection->reverse->face->getNormal(); + int64_t m00 = face->dir0.dot(n0); + int64_t m01 = face->dir1.dot(n0); + int64_t m10 = face->dir0.dot(n1); + int64_t m11 = face->dir1.dot(n1); + int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0); + int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1); + Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10); + btAssert(det.getSign() != 0); + Vertex* v = vertexPool.newObject(); + v->point.index = -1; + v->copy = -1; + v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x, + Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y, + Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z, + det); + v->point.x = (int32_t) v->point128.xvalue(); + v->point.y = (int32_t) v->point128.yvalue(); + v->point.z = (int32_t) v->point128.zvalue(); + intersection->target = v; + v->edges = e; + + stack.push_back(v); + stack.push_back(removed); + stack.push_back(NULL); + } + + if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target)) + { + faceEdge = newEdgePair(prevIntersection->target, intersection->target); + if (prevCmp == 0) + { + faceEdge->link(prevIntersection->reverse->next); + } + if ((prevCmp == 0) || prevFaceEdge) + { + prevIntersection->reverse->link(faceEdge); + } + if (cmp == 0) + { + intersection->reverse->prev->link(faceEdge->reverse); + } + faceEdge->reverse->link(intersection->reverse); + } + else + { + faceEdge = prevIntersection->reverse->next; + } + + if (prevFaceEdge) + { + if (prevCmp > 0) + { + faceEdge->link(prevFaceEdge->reverse); + } + else if (faceEdge != prevFaceEdge->reverse) + { + stack.push_back(prevFaceEdge->target); + while (faceEdge->next != prevFaceEdge->reverse) + { + Vertex* removed = faceEdge->next->target; + removeEdgePair(faceEdge->next); + stack.push_back(removed); +#ifdef DEBUG_CONVEX_HULL + printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + } + stack.push_back(NULL); + } + } + faceEdge->face = face; + faceEdge->reverse->face = intersection->face; + + if (!firstFaceEdge) + { + firstFaceEdge = faceEdge; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to process all intersections\n", m); +#endif + + if (cmp > 0) + { + firstFaceEdge->reverse->target = faceEdge->target; + firstIntersection->reverse->link(firstFaceEdge); + firstFaceEdge->link(faceEdge->reverse); + } + else if (firstFaceEdge != faceEdge->reverse) + { + stack.push_back(faceEdge->target); + while (firstFaceEdge->next != faceEdge->reverse) + { + Vertex* removed = firstFaceEdge->next->target; + removeEdgePair(firstFaceEdge->next); + stack.push_back(removed); +#ifdef DEBUG_CONVEX_HULL + printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + } + stack.push_back(NULL); + } + + btAssert(stack.size() > 0); + vertexList = stack[0]; + +#ifdef DEBUG_CONVEX_HULL + printf("Removing part\n"); +#endif +#ifdef SHOW_ITERATIONS + n = 0; +#endif + int pos = 0; + while (pos < stack.size()) + { + int end = stack.size(); + while (pos < end) + { + Vertex* kept = stack[pos++]; +#ifdef DEBUG_CONVEX_HULL + kept->print(); +#endif + bool deeper = false; + Vertex* removed; + while ((removed = stack[pos++]) != NULL) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + kept->receiveNearbyFaces(removed); + while (removed->edges) + { + if (!deeper) + { + deeper = true; + stack.push_back(kept); + } + stack.push_back(removed->edges->target); + removeEdgePair(removed->edges); + } + } + if (deeper) + { + stack.push_back(NULL); + } + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to remove part\n", n); +#endif + + stack.resize(0); + face->origin = shiftedOrigin; + + return true; +} + + +static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray& vertices) +{ + int index = vertex->copy; + if (index < 0) + { + index = vertices.size(); + vertex->copy = index; + vertices.push_back(vertex); +#ifdef DEBUG_CONVEX_HULL + printf("Vertex %d gets index *%d\n", vertex->point.index, index); +#endif + } + return index; +} + +btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp) +{ + if (count <= 0) + { + vertices.clear(); + edges.clear(); + faces.clear(); + return 0; + } + + btConvexHullInternal hull; + hull.compute(coords, doubleCoords, stride, count); + + btScalar shift = 0; + if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0)) + { + vertices.clear(); + edges.clear(); + faces.clear(); + return shift; + } + + vertices.resize(0); + edges.resize(0); + faces.resize(0); + + btAlignedObjectArray oldVertices; + getVertexCopy(hull.vertexList, oldVertices); + int copied = 0; + while (copied < oldVertices.size()) + { + btConvexHullInternal::Vertex* v = oldVertices[copied]; + vertices.push_back(hull.getCoordinates(v)); + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { + int firstCopy = -1; + int prevCopy = -1; + btConvexHullInternal::Edge* e = firstEdge; + do + { + if (e->copy < 0) + { + int s = edges.size(); + edges.push_back(Edge()); + edges.push_back(Edge()); + Edge* c = &edges[s]; + Edge* r = &edges[s + 1]; + e->copy = s; + e->reverse->copy = s + 1; + c->reverse = 1; + r->reverse = -1; + c->targetVertex = getVertexCopy(e->target, oldVertices); + r->targetVertex = copied; +#ifdef DEBUG_CONVEX_HULL + printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex()); +#endif + } + if (prevCopy >= 0) + { + edges[e->copy].next = prevCopy - e->copy; + } + else + { + firstCopy = e->copy; + } + prevCopy = e->copy; + e = e->next; + } while (e != firstEdge); + edges[firstCopy].next = prevCopy - firstCopy; + } + copied++; + } + + for (int i = 0; i < copied; i++) + { + btConvexHullInternal::Vertex* v = oldVertices[i]; + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { + btConvexHullInternal::Edge* e = firstEdge; + do + { + if (e->copy >= 0) + { +#ifdef DEBUG_CONVEX_HULL + printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex()); +#endif + faces.push_back(e->copy); + btConvexHullInternal::Edge* f = e; + do + { +#ifdef DEBUG_CONVEX_HULL + printf(" Face *%d\n", edges[f->copy].getTargetVertex()); +#endif + f->copy = -1; + f = f->reverse->prev; + } while (f != e); + } + e = e->next; + } while (e != firstEdge); + } + } + + return shift; +} + + + + + diff --git a/Code/Physics/src/LinearMath/btConvexHullComputer.h b/Code/Physics/src/LinearMath/btConvexHullComputer.h new file mode 100644 index 00000000..7240ac4f --- /dev/null +++ b/Code/Physics/src/LinearMath/btConvexHullComputer.h @@ -0,0 +1,103 @@ +/* +Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_HULL_COMPUTER_H +#define BT_CONVEX_HULL_COMPUTER_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +/// Convex hull implementation based on Preparata and Hong +/// See http://code.google.com/p/bullet/issues/detail?id=275 +/// Ole Kniemeyer, MAXON Computer GmbH +class btConvexHullComputer +{ + private: + btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp); + + public: + + class Edge + { + private: + int next; + int reverse; + int targetVertex; + + friend class btConvexHullComputer; + + public: + int getSourceVertex() const + { + return (this + reverse)->targetVertex; + } + + int getTargetVertex() const + { + return targetVertex; + } + + const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex + { + return this + next; + } + + const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face + { + return (this + reverse)->getNextEdgeOfVertex(); + } + + const Edge* getReverseEdge() const + { + return this + reverse; + } + }; + + + // Vertices of the output hull + btAlignedObjectArray vertices; + + // Edges of the output hull + btAlignedObjectArray edges; + + // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons + btAlignedObjectArray faces; + + /* + Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes + between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken + by that amount (each face is moved by "shrink" length units towards the center along its normal). + If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius" + is the minimum distance of a face to the center of the convex hull. + + The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large + that the resulting convex hull is empty. + + The output convex hull can be found in the member variables "vertices", "edges", "faces". + */ + btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) + { + return compute(coords, false, stride, count, shrink, shrinkClamp); + } + + // same as above, but double precision + btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) + { + return compute(coords, true, stride, count, shrink, shrinkClamp); + } +}; + + +#endif //BT_CONVEX_HULL_COMPUTER_H + diff --git a/Code/Physics/src/LinearMath/btDefaultMotionState.h b/Code/Physics/src/LinearMath/btDefaultMotionState.h new file mode 100644 index 00000000..c90b7492 --- /dev/null +++ b/Code/Physics/src/LinearMath/btDefaultMotionState.h @@ -0,0 +1,42 @@ +#ifndef BT_DEFAULT_MOTION_STATE_H +#define BT_DEFAULT_MOTION_STATE_H + +#include "btMotionState.h" + +///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets. +ATTRIBUTE_ALIGNED16(struct) btDefaultMotionState : public btMotionState +{ + btTransform m_graphicsWorldTrans; + btTransform m_centerOfMassOffset; + btTransform m_startWorldTrans; + void* m_userPointer; + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity()) + : m_graphicsWorldTrans(startTrans), + m_centerOfMassOffset(centerOfMassOffset), + m_startWorldTrans(startTrans), + m_userPointer(0) + + { + } + + ///synchronizes world transform from user to physics + virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const + { + centerOfMassWorldTrans = m_centerOfMassOffset.inverse() * m_graphicsWorldTrans ; + } + + ///synchronizes world transform from physics to user + ///Bullet only calls the update of worldtransform for active objects + virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans) + { + m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset ; + } + + + +}; + +#endif //BT_DEFAULT_MOTION_STATE_H diff --git a/Code/Physics/src/LinearMath/btGeometryUtil.cpp b/Code/Physics/src/LinearMath/btGeometryUtil.cpp new file mode 100644 index 00000000..5ac230f7 --- /dev/null +++ b/Code/Physics/src/LinearMath/btGeometryUtil.cpp @@ -0,0 +1,185 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "btGeometryUtil.h" + + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" +{ + void btBulletMathProbe (); + + void btBulletMathProbe () {} +} + + +bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin) +{ + int numbrushes = planeEquations.size(); + for (int i=0;ibtScalar(0.)) + { + return false; + } + } + return true; + +} + + +bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin) +{ + int numvertices = vertices.size(); + for (int i=0;ibtScalar(0.)) + { + return false; + } + } + return true; +} + +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations); + +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) +{ + int numbrushes = planeEquations.size(); + for (int i=0;i btScalar(0.999)) + { + return false; + } + } + return true; +} + +void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ) +{ + const int numvertices = vertices.size(); + // brute force: + for (int i=0;i btScalar(0.0001)) + { + planeEquation.normalize(); + if (notExist(planeEquation,planeEquationsOut)) + { + planeEquation[3] = -planeEquation.dot(N1); + + //check if inside, and replace supportingVertexOut if needed + if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01))) + { + planeEquationsOut.push_back(planeEquation); + } + } + } + normalSign = btScalar(-1.); + } + + } + } + } + +} + +void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ) +{ + const int numbrushes = planeEquations.size(); + // brute force: + for (int i=0;i btScalar(0.0001) ) && + ( n3n1.length2() > btScalar(0.0001) ) && + ( n1n2.length2() > btScalar(0.0001) ) ) + { + //point P out of 3 plane equations: + + // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) + //P = ------------------------------------------------------------------------- + // N1 . ( N2 * N3 ) + + + btScalar quotient = (N1.dot(n2n3)); + if (btFabs(quotient) > btScalar(0.000001)) + { + quotient = btScalar(-1.) / quotient; + n2n3 *= N1[3]; + n3n1 *= N2[3]; + n1n2 *= N3[3]; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + //check if inside, and replace supportingVertexOut if needed + if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01))) + { + verticesOut.push_back(potentialVertex); + } + } + } + } + } + } +} + diff --git a/Code/Physics/src/LinearMath/btGeometryUtil.h b/Code/Physics/src/LinearMath/btGeometryUtil.h new file mode 100644 index 00000000..a4b13b45 --- /dev/null +++ b/Code/Physics/src/LinearMath/btGeometryUtil.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_GEOMETRY_UTIL_H +#define BT_GEOMETRY_UTIL_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices. +class btGeometryUtil +{ + public: + + + static void getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ); + + static void getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ); + + static bool isInside(const btAlignedObjectArray& vertices, const btVector3& planeNormal, btScalar margin); + + static bool isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin); + + static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin); + +}; + + +#endif //BT_GEOMETRY_UTIL_H + diff --git a/Code/Physics/src/LinearMath/btGrahamScan2dConvexHull.h b/Code/Physics/src/LinearMath/btGrahamScan2dConvexHull.h new file mode 100644 index 00000000..e658c5cf --- /dev/null +++ b/Code/Physics/src/LinearMath/btGrahamScan2dConvexHull.h @@ -0,0 +1,117 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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 GRAHAM_SCAN_2D_CONVEX_HULL_H +#define GRAHAM_SCAN_2D_CONVEX_HULL_H + + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +struct GrahamVector3 : public btVector3 +{ + GrahamVector3(const btVector3& org, int orgIndex) + :btVector3(org), + m_orgIndex(orgIndex) + { + } + btScalar m_angle; + int m_orgIndex; +}; + + +struct btAngleCompareFunc { + btVector3 m_anchor; + btAngleCompareFunc(const btVector3& anchor) + : m_anchor(anchor) + { + } + bool operator()(const GrahamVector3& a, const GrahamVector3& b) const { + if (a.m_angle != b.m_angle) + return a.m_angle < b.m_angle; + else + { + btScalar al = (a-m_anchor).length2(); + btScalar bl = (b-m_anchor).length2(); + if (al != bl) + return al < bl; + else + { + return a.m_orgIndex < b.m_orgIndex; + } + } + } +}; + +inline void GrahamScanConvexHull2D(btAlignedObjectArray& originalPoints, btAlignedObjectArray& hull, const btVector3& normalAxis) +{ + btVector3 axis0,axis1; + btPlaneSpace1(normalAxis,axis0,axis1); + + + if (originalPoints.size()<=1) + { + for (int i=0;i1) { + btVector3& a = hull[hull.size()-2]; + btVector3& b = hull[hull.size()-1]; + isConvex = btCross(a-b,a-originalPoints[i]).dot(normalAxis)> 0; + if (!isConvex) + hull.pop_back(); + else + hull.push_back(originalPoints[i]); + } + } +} + +#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H diff --git a/Code/Physics/src/LinearMath/btHashMap.h b/Code/Physics/src/LinearMath/btHashMap.h new file mode 100644 index 00000000..ce07db3a --- /dev/null +++ b/Code/Physics/src/LinearMath/btHashMap.h @@ -0,0 +1,450 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_HASH_MAP_H +#define BT_HASH_MAP_H + +#include "btAlignedObjectArray.h" + +///very basic hashable string implementation, compatible with btHashMap +struct btHashString +{ + const char* m_string; + unsigned int m_hash; + + SIMD_FORCE_INLINE unsigned int getHash()const + { + return m_hash; + } + + btHashString(const char* name) + :m_string(name) + { + /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */ + static const unsigned int InitialFNV = 2166136261u; + static const unsigned int FNVMultiple = 16777619u; + + /* Fowler / Noll / Vo (FNV) Hash */ + unsigned int hash = InitialFNV; + + for(int i = 0; m_string[i]; i++) + { + hash = hash ^ (m_string[i]); /* xor the low 8 bits */ + hash = hash * FNVMultiple; /* multiply by the magic number */ + } + m_hash = hash; + } + + int portableStringCompare(const char* src, const char* dst) const + { + int ret = 0 ; + + while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) + ++src, ++dst; + + if ( ret < 0 ) + ret = -1 ; + else if ( ret > 0 ) + ret = 1 ; + + return( ret ); + } + + bool equals(const btHashString& other) const + { + return (m_string == other.m_string) || + (0==portableStringCompare(m_string,other.m_string)); + + } + +}; + +const int BT_HASH_NULL=0xffffffff; + + +class btHashInt +{ + int m_uid; +public: + btHashInt(int uid) :m_uid(uid) + { + } + + int getUid1() const + { + return m_uid; + } + + void setUid1(int uid) + { + m_uid = uid; + } + + bool equals(const btHashInt& other) const + { + return getUid1() == other.getUid1(); + } + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } +}; + + + +class btHashPtr +{ + + union + { + const void* m_pointer; + int m_hashValues[2]; + }; + +public: + + btHashPtr(const void* ptr) + :m_pointer(ptr) + { + } + + const void* getPointer() const + { + return m_pointer; + } + + bool equals(const btHashPtr& other) const + { + return getPointer() == other.getPointer(); + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + const bool VOID_IS_8 = ((sizeof(void*)==8)); + + int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0]; + + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } + + +}; + + +template +class btHashKeyPtr +{ + int m_uid; +public: + + btHashKeyPtr(int uid) :m_uid(uid) + { + } + + int getUid1() const + { + return m_uid; + } + + bool equals(const btHashKeyPtr& other) const + { + return getUid1() == other.getUid1(); + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } + + +}; + + +template +class btHashKey +{ + int m_uid; +public: + + btHashKey(int uid) :m_uid(uid) + { + } + + int getUid1() const + { + return m_uid; + } + + bool equals(const btHashKey& other) const + { + return getUid1() == other.getUid1(); + } + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16); + return key; + } +}; + + +///The btHashMap template class implements a generic and lightweight hashmap. +///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp +template +class btHashMap +{ + +protected: + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + + btAlignedObjectArray m_valueArray; + btAlignedObjectArray m_keyArray; + + void growTables(const Key& /*key*/) + { + int newCapacity = m_valueArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_HASH_NULL; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_HASH_NULL; + } + + for(i=0;i= (unsigned int)m_hashTable.size()) + { + return BT_HASH_NULL; + } + + int index = m_hashTable[hash]; + while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false) + { + index = m_next[index]; + } + return index; + } + + void clear() + { + m_hashTable.clear(); + m_next.clear(); + m_valueArray.clear(); + m_keyArray.clear(); + } + +}; + +#endif //BT_HASH_MAP_H diff --git a/Code/Physics/src/LinearMath/btIDebugDraw.h b/Code/Physics/src/LinearMath/btIDebugDraw.h new file mode 100644 index 00000000..de97c3f8 --- /dev/null +++ b/Code/Physics/src/LinearMath/btIDebugDraw.h @@ -0,0 +1,445 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_IDEBUG_DRAW__H +#define BT_IDEBUG_DRAW__H + +#include "btVector3.h" +#include "btTransform.h" + + +///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations. +///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld. +///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum. +///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1] +class btIDebugDraw +{ + public: + + enum DebugDrawModes + { + DBG_NoDebug=0, + DBG_DrawWireframe = 1, + DBG_DrawAabb=2, + DBG_DrawFeaturesText=4, + DBG_DrawContactPoints=8, + DBG_NoDeactivation=16, + DBG_NoHelpText = 32, + DBG_DrawText=64, + DBG_ProfileTimings = 128, + DBG_EnableSatComparison = 256, + DBG_DisableBulletLCP = 512, + DBG_EnableCCD = 1024, + DBG_DrawConstraints = (1 << 11), + DBG_DrawConstraintLimits = (1 << 12), + DBG_FastWireframe = (1<<13), + DBG_DrawNormals = (1<<14), + DBG_MAX_DEBUG_DRAW_MODE + }; + + virtual ~btIDebugDraw() {}; + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; + + virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor) + { + (void) toColor; + drawLine (from, to, fromColor); + } + + virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color) + { + + btVector3 center = transform.getOrigin(); + btVector3 up = transform.getBasis().getColumn(1); + btVector3 axis = transform.getBasis().getColumn(0); + btScalar minTh = -SIMD_HALF_PI; + btScalar maxTh = SIMD_HALF_PI; + btScalar minPs = -SIMD_HALF_PI; + btScalar maxPs = SIMD_HALF_PI; + btScalar stepDegrees = 30.f; + drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees ,false); + drawSpherePatch(center, up, -axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees,false ); + } + + virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color) + { + btTransform tr; + tr.setIdentity(); + tr.setOrigin(p); + drawSphere(radius,tr,color); + } + + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha) + { + drawTriangle(v0,v1,v2,color,alpha); + } + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/) + { + drawLine(v0,v1,color); + drawLine(v1,v2,color); + drawLine(v2,v0,color); + } + + virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; + + virtual void reportErrorWarning(const char* warningString) = 0; + + virtual void draw3dText(const btVector3& location,const char* textString) = 0; + + virtual void setDebugMode(int debugMode) =0; + + virtual int getDebugMode() const = 0; + + virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color) + { + + btVector3 halfExtents = (to-from)* 0.5f; + btVector3 center = (to+from) *0.5f; + int i,j; + + btVector3 edgecoord(1.f,1.f,1.f),pa,pb; + for (i=0;i<4;i++) + { + for (j=0;j<3;j++) + { + pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + edgecoord[2]*halfExtents[2]); + pa+=center; + + int othercoord = j%3; + edgecoord[othercoord]*=-1.f; + pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + edgecoord[2]*halfExtents[2]); + pb+=center; + + drawLine(pa,pb,color); + } + edgecoord = btVector3(-1.f,-1.f,-1.f); + if (i<3) + edgecoord[i]*=-1.f; + } + } + virtual void drawTransform(const btTransform& transform, btScalar orthoLen) + { + btVector3 start = transform.getOrigin(); + drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0)); + drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0)); + drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f)); + } + + virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, + const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f)) + { + const btVector3& vx = axis; + btVector3 vy = normal.cross(axis); + btScalar step = stepDegrees * SIMD_RADS_PER_DEG; + int nSteps = (int)((maxAngle - minAngle) / step); + if(!nSteps) nSteps = 1; + btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle); + if(drawSect) + { + drawLine(center, prev, color); + } + for(int i = 1; i <= nSteps; i++) + { + btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps); + btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle); + drawLine(prev, next, color); + prev = next; + } + if(drawSect) + { + drawLine(center, prev, color); + } + } + virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius, + btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f),bool drawCenter = true) + { + btVector3 vA[74]; + btVector3 vB[74]; + btVector3 *pvA = vA, *pvB = vB, *pT; + btVector3 npole = center + up * radius; + btVector3 spole = center - up * radius; + btVector3 arcStart; + btScalar step = stepDegrees * SIMD_RADS_PER_DEG; + const btVector3& kv = up; + const btVector3& iv = axis; + btVector3 jv = kv.cross(iv); + bool drawN = false; + bool drawS = false; + if(minTh <= -SIMD_HALF_PI) + { + minTh = -SIMD_HALF_PI + step; + drawN = true; + } + if(maxTh >= SIMD_HALF_PI) + { + maxTh = SIMD_HALF_PI - step; + drawS = true; + } + if(minTh > maxTh) + { + minTh = -SIMD_HALF_PI + step; + maxTh = SIMD_HALF_PI - step; + drawN = drawS = true; + } + int n_hor = (int)((maxTh - minTh) / step) + 1; + if(n_hor < 2) n_hor = 2; + btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1); + bool isClosed = false; + if(minPs > maxPs) + { + minPs = -SIMD_PI + step; + maxPs = SIMD_PI; + isClosed = true; + } + else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f)) + { + isClosed = true; + } + else + { + isClosed = false; + } + int n_vert = (int)((maxPs - minPs) / step) + 1; + if(n_vert < 2) n_vert = 2; + btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1); + for(int i = 0; i < n_hor; i++) + { + btScalar th = minTh + btScalar(i) * step_h; + btScalar sth = radius * btSin(th); + btScalar cth = radius * btCos(th); + for(int j = 0; j < n_vert; j++) + { + btScalar psi = minPs + btScalar(j) * step_v; + btScalar sps = btSin(psi); + btScalar cps = btCos(psi); + pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv; + if(i) + { + drawLine(pvA[j], pvB[j], color); + } + else if(drawS) + { + drawLine(spole, pvB[j], color); + } + if(j) + { + drawLine(pvB[j-1], pvB[j], color); + } + else + { + arcStart = pvB[j]; + } + if((i == (n_hor - 1)) && drawN) + { + drawLine(npole, pvB[j], color); + } + + if (drawCenter) + { + if(isClosed) + { + if(j == (n_vert-1)) + { + drawLine(arcStart, pvB[j], color); + } + } + else + { + if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1)))) + { + drawLine(center, pvB[j], color); + } + } + } + } + pT = pvA; pvA = pvB; pvB = pT; + } + } + + + virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color) + { + drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color); + drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + } + virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color) + { + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color); + drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color); + } + + virtual void drawCapsule(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color) + { + int stepDegrees = 30; + + btVector3 capStart(0.f,0.f,0.f); + capStart[upAxis] = -halfHeight; + + btVector3 capEnd(0.f,0.f,0.f); + capEnd[upAxis] = halfHeight; + + // Draw the ends + { + + btTransform childTransform = transform; + childTransform.getOrigin() = transform * capStart; + { + btVector3 center = childTransform.getOrigin(); + btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3); + btVector3 axis = -childTransform.getBasis().getColumn(upAxis); + btScalar minTh = -SIMD_HALF_PI; + btScalar maxTh = SIMD_HALF_PI; + btScalar minPs = -SIMD_HALF_PI; + btScalar maxPs = SIMD_HALF_PI; + + drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false); + } + + + + } + + { + btTransform childTransform = transform; + childTransform.getOrigin() = transform * capEnd; + { + btVector3 center = childTransform.getOrigin(); + btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3); + btVector3 axis = childTransform.getBasis().getColumn(upAxis); + btScalar minTh = -SIMD_HALF_PI; + btScalar maxTh = SIMD_HALF_PI; + btScalar minPs = -SIMD_HALF_PI; + btScalar maxPs = SIMD_HALF_PI; + drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false); + } + } + + // Draw some additional lines + btVector3 start = transform.getOrigin(); + + for (int i=0;i<360;i+=stepDegrees) + { + capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius; + capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius; + drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color); + } + + } + + virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color) + { + btVector3 start = transform.getOrigin(); + btVector3 offsetHeight(0,0,0); + offsetHeight[upAxis] = halfHeight; + int stepDegrees=30; + btVector3 capStart(0.f,0.f,0.f); + capStart[upAxis] = -halfHeight; + btVector3 capEnd(0.f,0.f,0.f); + capEnd[upAxis] = halfHeight; + + for (int i=0;i<360;i+=stepDegrees) + { + capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius; + capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius; + drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color); + } + // Drawing top and bottom caps of the cylinder + btVector3 yaxis(0,0,0); + yaxis[upAxis] = btScalar(1.0); + btVector3 xaxis(0,0,0); + xaxis[(upAxis+1)%3] = btScalar(1.0); + drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0)); + drawArc(start+transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0)); + } + + virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color) + { + int stepDegrees = 30; + btVector3 start = transform.getOrigin(); + + btVector3 offsetHeight(0,0,0); + btScalar halfHeight = height * btScalar(0.5); + offsetHeight[upAxis] = halfHeight; + btVector3 offsetRadius(0,0,0); + offsetRadius[(upAxis+1)%3] = radius; + btVector3 offset2Radius(0,0,0); + offset2Radius[(upAxis+2)%3] = radius; + + + btVector3 capEnd(0.f,0.f,0.f); + capEnd[upAxis] = -halfHeight; + + for (int i=0;i<360;i+=stepDegrees) + { + capEnd[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius; + capEnd[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius; + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * capEnd, color); + } + + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offsetRadius),color); + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offsetRadius),color); + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offset2Radius),color); + drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offset2Radius),color); + + // Drawing the base of the cone + btVector3 yaxis(0,0,0); + yaxis[upAxis] = btScalar(1.0); + btVector3 xaxis(0,0,0); + xaxis[(upAxis+1)%3] = btScalar(1.0); + drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0); + } + + virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color) + { + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + drawLine(transform*pt0,transform*pt1,color); + drawLine(transform*pt2,transform*pt3,color); + } +}; + + +#endif //BT_IDEBUG_DRAW__H + diff --git a/Code/Physics/src/LinearMath/btList.h b/Code/Physics/src/LinearMath/btList.h new file mode 100644 index 00000000..eec80a70 --- /dev/null +++ b/Code/Physics/src/LinearMath/btList.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEN_LIST_H +#define BT_GEN_LIST_H + +class btGEN_Link { +public: + btGEN_Link() : m_next(0), m_prev(0) {} + btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {} + + btGEN_Link *getNext() const { return m_next; } + btGEN_Link *getPrev() const { return m_prev; } + + bool isHead() const { return m_prev == 0; } + bool isTail() const { return m_next == 0; } + + void insertBefore(btGEN_Link *link) { + m_next = link; + m_prev = link->m_prev; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void insertAfter(btGEN_Link *link) { + m_next = link->m_next; + m_prev = link; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void remove() { + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + +private: + btGEN_Link *m_next; + btGEN_Link *m_prev; +}; + +class btGEN_List { +public: + btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {} + + btGEN_Link *getHead() const { return m_head.getNext(); } + btGEN_Link *getTail() const { return m_tail.getPrev(); } + + void addHead(btGEN_Link *link) { link->insertAfter(&m_head); } + void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); } + +private: + btGEN_Link m_head; + btGEN_Link m_tail; +}; + +#endif //BT_GEN_LIST_H + + + diff --git a/Code/Physics/src/LinearMath/btMatrix3x3.h b/Code/Physics/src/LinearMath/btMatrix3x3.h new file mode 100644 index 00000000..14fe704f --- /dev/null +++ b/Code/Physics/src/LinearMath/btMatrix3x3.h @@ -0,0 +1,1367 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_MATRIX3x3_H +#define BT_MATRIX3x3_H + +#include "btVector3.h" +#include "btQuaternion.h" +#include + +#ifdef BT_USE_SSE +//const __m128 ATTRIBUTE_ALIGNED16(v2220) = {2.0f, 2.0f, 2.0f, 0.0f}; +//const __m128 ATTRIBUTE_ALIGNED16(vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f}; +#define vMPPP (_mm_set_ps (+0.0f, +0.0f, +0.0f, -0.0f)) +#endif + +#if defined(BT_USE_SSE) +#define v1000 (_mm_set_ps(0.0f,0.0f,0.0f,1.0f)) +#define v0100 (_mm_set_ps(0.0f,0.0f,1.0f,0.0f)) +#define v0010 (_mm_set_ps(0.0f,1.0f,0.0f,0.0f)) +#elif defined(BT_USE_NEON) +const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f}; +const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f}; +const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f}; +#endif + +#ifdef BT_USE_DOUBLE_PRECISION +#define btMatrix3x3Data btMatrix3x3DoubleData +#else +#define btMatrix3x3Data btMatrix3x3FloatData +#endif //BT_USE_DOUBLE_PRECISION + + +/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3. +* Make sure to only include a pure orthogonal matrix without scaling. */ +ATTRIBUTE_ALIGNED16(class) btMatrix3x3 { + + ///Data storage for the matrix, each vector is a row of the matrix + btVector3 m_el[3]; + +public: + /** @brief No initializaion constructor */ + btMatrix3x3 () {} + + // explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); } + + /**@brief Constructor from Quaternion */ + explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); } + /* + template + Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + setEulerYPR(yaw, pitch, roll); + } + */ + /** @brief Constructor with row major formatting */ + btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz, + const btScalar& yx, const btScalar& yy, const btScalar& yz, + const btScalar& zx, const btScalar& zy, const btScalar& zz) + { + setValue(xx, xy, xz, + yx, yy, yz, + zx, zy, zz); + } + +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + SIMD_FORCE_INLINE btMatrix3x3 (const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2 ) + { + m_el[0].mVec128 = v0; + m_el[1].mVec128 = v1; + m_el[2].mVec128 = v2; + } + + SIMD_FORCE_INLINE btMatrix3x3 (const btVector3& v0, const btVector3& v1, const btVector3& v2 ) + { + m_el[0] = v0; + m_el[1] = v1; + m_el[2] = v2; + } + + // Copy constructor + SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& rhs) + { + m_el[0].mVec128 = rhs.m_el[0].mVec128; + m_el[1].mVec128 = rhs.m_el[1].mVec128; + m_el[2].mVec128 = rhs.m_el[2].mVec128; + } + + // Assignment Operator + SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m) + { + m_el[0].mVec128 = m.m_el[0].mVec128; + m_el[1].mVec128 = m.m_el[1].mVec128; + m_el[2].mVec128 = m.m_el[2].mVec128; + + return *this; + } + +#else + + /** @brief Copy constructor */ + SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other) + { + m_el[0] = other.m_el[0]; + m_el[1] = other.m_el[1]; + m_el[2] = other.m_el[2]; + } + + /** @brief Assignment Operator */ + SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other) + { + m_el[0] = other.m_el[0]; + m_el[1] = other.m_el[1]; + m_el[2] = other.m_el[2]; + return *this; + } + +#endif + + /** @brief Get a column of the matrix as a vector + * @param i Column number 0 indexed */ + SIMD_FORCE_INLINE btVector3 getColumn(int i) const + { + return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]); + } + + + /** @brief Get a row of the matrix as a vector + * @param i Row number 0 indexed */ + SIMD_FORCE_INLINE const btVector3& getRow(int i) const + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + /** @brief Get a mutable reference to a row of the matrix as a vector + * @param i Row number 0 indexed */ + SIMD_FORCE_INLINE btVector3& operator[](int i) + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + /** @brief Get a const reference to a row of the matrix as a vector + * @param i Row number 0 indexed */ + SIMD_FORCE_INLINE const btVector3& operator[](int i) const + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + /** @brief Multiply by the target matrix on the right + * @param m Rotation matrix to be applied + * Equivilant to this = this * m */ + btMatrix3x3& operator*=(const btMatrix3x3& m); + + /** @brief Adds by the target matrix on the right + * @param m matrix to be applied + * Equivilant to this = this + m */ + btMatrix3x3& operator+=(const btMatrix3x3& m); + + /** @brief Substractss by the target matrix on the right + * @param m matrix to be applied + * Equivilant to this = this - m */ + btMatrix3x3& operator-=(const btMatrix3x3& m); + + /** @brief Set from the rotational part of a 4x4 OpenGL matrix + * @param m A pointer to the beginning of the array of scalars*/ + void setFromOpenGLSubMatrix(const btScalar *m) + { + m_el[0].setValue(m[0],m[4],m[8]); + m_el[1].setValue(m[1],m[5],m[9]); + m_el[2].setValue(m[2],m[6],m[10]); + + } + /** @brief Set the values of the matrix explicitly (row major) + * @param xx Top left + * @param xy Top Middle + * @param xz Top Right + * @param yx Middle Left + * @param yy Middle Middle + * @param yz Middle Right + * @param zx Bottom Left + * @param zy Bottom Middle + * @param zz Bottom Right*/ + void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, + const btScalar& yx, const btScalar& yy, const btScalar& yz, + const btScalar& zx, const btScalar& zy, const btScalar& zz) + { + m_el[0].setValue(xx,xy,xz); + m_el[1].setValue(yx,yy,yz); + m_el[2].setValue(zx,zy,zz); + } + + /** @brief Set the matrix from a quaternion + * @param q The Quaternion to match */ + void setRotation(const btQuaternion& q) + { + btScalar d = q.length2(); + btFullAssert(d != btScalar(0.0)); + btScalar s = btScalar(2.0) / d; + + #if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vs, Q = q.get128(); + __m128i Qi = btCastfTo128i(Q); + __m128 Y, Z; + __m128 V1, V2, V3; + __m128 V11, V21, V31; + __m128 NQ = _mm_xor_ps(Q, btvMzeroMask); + __m128i NQi = btCastfTo128i(NQ); + + V1 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,2,3))); // Y X Z W + V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0,0,1,3)); // -X -X Y W + V3 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(2,1,0,3))); // Z Y X W + V1 = _mm_xor_ps(V1, vMPPP); // change the sign of the first element + + V11 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,1,0,3))); // Y Y X W + V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W + V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0,2,0,3)); // X Z -X -W + + V2 = V2 * V1; // + V1 = V1 * V11; // + V3 = V3 * V31; // + + V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2,3,1,3)); // -Z -W Y W + V11 = V11 * V21; // + V21 = _mm_xor_ps(V21, vMPPP); // change the sign of the first element + V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3,3,1,3)); // W W -Y -W + V31 = _mm_xor_ps(V31, vMPPP); // change the sign of the first element + Y = btCastiTo128f(_mm_shuffle_epi32 (NQi, BT_SHUFFLE(3,2,0,3))); // -W -Z -X -W + Z = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,1,3))); // Y X Y W + + vs = _mm_load_ss(&s); + V21 = V21 * Y; + V31 = V31 * Z; + + V1 = V1 + V11; + V2 = V2 + V21; + V3 = V3 + V31; + + vs = bt_splat3_ps(vs, 0); + // s ready + V1 = V1 * vs; + V2 = V2 * vs; + V3 = V3 * vs; + + V1 = V1 + v1000; + V2 = V2 + v0100; + V3 = V3 + v0010; + + m_el[0] = V1; + m_el[1] = V2; + m_el[2] = V3; + #else + btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s; + btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs; + btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs; + btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs; + setValue( + btScalar(1.0) - (yy + zz), xy - wz, xz + wy, + xy + wz, btScalar(1.0) - (xx + zz), yz - wx, + xz - wy, yz + wx, btScalar(1.0) - (xx + yy)); + #endif + } + + + /** @brief Set the matrix from euler angles using YPR around YXZ respectively + * @param yaw Yaw about Y axis + * @param pitch Pitch about X axis + * @param roll Roll about Z axis + */ + void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + setEulerZYX(roll, pitch, yaw); + } + + /** @brief Set the matrix from euler angles YPR around ZYX axes + * @param eulerX Roll about X axis + * @param eulerY Pitch around Y axis + * @param eulerZ Yaw aboud Z axis + * + * These angles are used to produce a rotation matrix. The euler + * angles are applied in ZYX order. I.e a vector is first rotated + * about X then Y and then Z + **/ + void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { + ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code + btScalar ci ( btCos(eulerX)); + btScalar cj ( btCos(eulerY)); + btScalar ch ( btCos(eulerZ)); + btScalar si ( btSin(eulerX)); + btScalar sj ( btSin(eulerY)); + btScalar sh ( btSin(eulerZ)); + btScalar cc = ci * ch; + btScalar cs = ci * sh; + btScalar sc = si * ch; + btScalar ss = si * sh; + + setValue(cj * ch, sj * sc - cs, sj * cc + ss, + cj * sh, sj * ss + cc, sj * cs - sc, + -sj, cj * si, cj * ci); + } + + /**@brief Set the matrix to the identity */ + void setIdentity() + { +#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON) + m_el[0] = v1000; + m_el[1] = v0100; + m_el[2] = v0010; +#else + setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), + btScalar(0.0), btScalar(1.0), btScalar(0.0), + btScalar(0.0), btScalar(0.0), btScalar(1.0)); +#endif + } + + static const btMatrix3x3& getIdentity() + { +#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON) + static const btMatrix3x3 + identityMatrix(v1000, v0100, v0010); +#else + static const btMatrix3x3 + identityMatrix( + btScalar(1.0), btScalar(0.0), btScalar(0.0), + btScalar(0.0), btScalar(1.0), btScalar(0.0), + btScalar(0.0), btScalar(0.0), btScalar(1.0)); +#endif + return identityMatrix; + } + + /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective + * @param m The array to be filled */ + void getOpenGLSubMatrix(btScalar *m) const + { +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 v0 = m_el[0].mVec128; + __m128 v1 = m_el[1].mVec128; + __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2 + __m128 *vm = (__m128 *)m; + __m128 vT; + + v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0 + + vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * * + v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1 + + v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0 + v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0 + v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0 + + vm[0] = v0; + vm[1] = v1; + vm[2] = v2; +#elif defined(BT_USE_NEON) + // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions. + static const uint32x2_t zMask = (const uint32x2_t) {static_cast(-1), 0 }; + float32x4_t *vm = (float32x4_t *)m; + float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1} + float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0} + float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] ); + float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] ); + float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask ); + float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0 + + vm[0] = v0; + vm[1] = v1; + vm[2] = v2; +#else + m[0] = btScalar(m_el[0].x()); + m[1] = btScalar(m_el[1].x()); + m[2] = btScalar(m_el[2].x()); + m[3] = btScalar(0.0); + m[4] = btScalar(m_el[0].y()); + m[5] = btScalar(m_el[1].y()); + m[6] = btScalar(m_el[2].y()); + m[7] = btScalar(0.0); + m[8] = btScalar(m_el[0].z()); + m[9] = btScalar(m_el[1].z()); + m[10] = btScalar(m_el[2].z()); + m[11] = btScalar(0.0); +#endif + } + + /**@brief Get the matrix represented as a quaternion + * @param q The quaternion which will be set */ + void getRotation(btQuaternion& q) const + { +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z(); + btScalar s, x; + + union { + btSimdFloat4 vec; + btScalar f[4]; + } temp; + + if (trace > btScalar(0.0)) + { + x = trace + btScalar(1.0); + + temp.f[0]=m_el[2].y() - m_el[1].z(); + temp.f[1]=m_el[0].z() - m_el[2].x(); + temp.f[2]=m_el[1].x() - m_el[0].y(); + temp.f[3]=x; + //temp.f[3]= s * btScalar(0.5); + } + else + { + int i, j, k; + if(m_el[0].x() < m_el[1].y()) + { + if( m_el[1].y() < m_el[2].z() ) + { i = 2; j = 0; k = 1; } + else + { i = 1; j = 2; k = 0; } + } + else + { + if( m_el[0].x() < m_el[2].z()) + { i = 2; j = 0; k = 1; } + else + { i = 0; j = 1; k = 2; } + } + + x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0); + + temp.f[3] = (m_el[k][j] - m_el[j][k]); + temp.f[j] = (m_el[j][i] + m_el[i][j]); + temp.f[k] = (m_el[k][i] + m_el[i][k]); + temp.f[i] = x; + //temp.f[i] = s * btScalar(0.5); + } + + s = btSqrt(x); + q.set128(temp.vec); + s = btScalar(0.5) / s; + + q *= s; +#else + btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z(); + + btScalar temp[4]; + + if (trace > btScalar(0.0)) + { + btScalar s = btSqrt(trace + btScalar(1.0)); + temp[3]=(s * btScalar(0.5)); + s = btScalar(0.5) / s; + + temp[0]=((m_el[2].y() - m_el[1].z()) * s); + temp[1]=((m_el[0].z() - m_el[2].x()) * s); + temp[2]=((m_el[1].x() - m_el[0].y()) * s); + } + else + { + int i = m_el[0].x() < m_el[1].y() ? + (m_el[1].y() < m_el[2].z() ? 2 : 1) : + (m_el[0].x() < m_el[2].z() ? 2 : 0); + int j = (i + 1) % 3; + int k = (i + 2) % 3; + + btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0)); + temp[i] = s * btScalar(0.5); + s = btScalar(0.5) / s; + + temp[3] = (m_el[k][j] - m_el[j][k]) * s; + temp[j] = (m_el[j][i] + m_el[i][j]) * s; + temp[k] = (m_el[k][i] + m_el[i][k]) * s; + } + q.setValue(temp[0],temp[1],temp[2],temp[3]); +#endif + } + + /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR + * @param yaw Yaw around Y axis + * @param pitch Pitch around X axis + * @param roll around Z axis */ + void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const + { + + // first use the normal calculus + yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x())); + pitch = btScalar(btAsin(-m_el[2].x())); + roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z())); + + // on pitch = +/-HalfPI + if (btFabs(pitch)==SIMD_HALF_PI) + { + if (yaw>0) + yaw-=SIMD_PI; + else + yaw+=SIMD_PI; + + if (roll>0) + roll-=SIMD_PI; + else + roll+=SIMD_PI; + } + }; + + + /**@brief Get the matrix represented as euler angles around ZYX + * @param yaw Yaw around X axis + * @param pitch Pitch around Y axis + * @param roll around X axis + * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/ + void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const + { + struct Euler + { + btScalar yaw; + btScalar pitch; + btScalar roll; + }; + + Euler euler_out; + Euler euler_out2; //second solution + //get the pointer to the raw data + + // Check that pitch is not at a singularity + if (btFabs(m_el[2].x()) >= 1) + { + euler_out.yaw = 0; + euler_out2.yaw = 0; + + // From difference of angles formula + btScalar delta = btAtan2(m_el[0].x(),m_el[0].z()); + if (m_el[2].x() > 0) //gimbal locked up + { + euler_out.pitch = SIMD_PI / btScalar(2.0); + euler_out2.pitch = SIMD_PI / btScalar(2.0); + euler_out.roll = euler_out.pitch + delta; + euler_out2.roll = euler_out.pitch + delta; + } + else // gimbal locked down + { + euler_out.pitch = -SIMD_PI / btScalar(2.0); + euler_out2.pitch = -SIMD_PI / btScalar(2.0); + euler_out.roll = -euler_out.pitch + delta; + euler_out2.roll = -euler_out.pitch + delta; + } + } + else + { + euler_out.pitch = - btAsin(m_el[2].x()); + euler_out2.pitch = SIMD_PI - euler_out.pitch; + + euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch), + m_el[2].z()/btCos(euler_out.pitch)); + euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch), + m_el[2].z()/btCos(euler_out2.pitch)); + + euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch), + m_el[0].x()/btCos(euler_out.pitch)); + euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch), + m_el[0].x()/btCos(euler_out2.pitch)); + } + + if (solution_number == 1) + { + yaw = euler_out.yaw; + pitch = euler_out.pitch; + roll = euler_out.roll; + } + else + { + yaw = euler_out2.yaw; + pitch = euler_out2.pitch; + roll = euler_out2.roll; + } + } + + /**@brief Create a scaled copy of the matrix + * @param s Scaling vector The elements of the vector will scale each column */ + + btMatrix3x3 scaled(const btVector3& s) const + { +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + return btMatrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s); +#else + return btMatrix3x3( + m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(), + m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(), + m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z()); +#endif + } + + /**@brief Return the determinant of the matrix */ + btScalar determinant() const; + /**@brief Return the adjoint of the matrix */ + btMatrix3x3 adjoint() const; + /**@brief Return the matrix with all values non negative */ + btMatrix3x3 absolute() const; + /**@brief Return the transpose of the matrix */ + btMatrix3x3 transpose() const; + /**@brief Return the inverse of the matrix */ + btMatrix3x3 inverse() const; + + btMatrix3x3 transposeTimes(const btMatrix3x3& m) const; + btMatrix3x3 timesTranspose(const btMatrix3x3& m) const; + + SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const + { + return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z(); + } + SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const + { + return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z(); + } + SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const + { + return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z(); + } + + + /**@brief diagonalizes this matrix by the Jacobi method. + * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original + * coordinate system, i.e., old_this = rot * new_this * rot^T. + * @param threshold See iteration + * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied + * by the sum of the absolute values of the diagonal, or when maxSteps have been executed. + * + * Note that this matrix is assumed to be symmetric. + */ + void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps) + { + rot.setIdentity(); + for (int step = maxSteps; step > 0; step--) + { + // find off-diagonal element [p][q] with largest magnitude + int p = 0; + int q = 1; + int r = 2; + btScalar max = btFabs(m_el[0][1]); + btScalar v = btFabs(m_el[0][2]); + if (v > max) + { + q = 2; + r = 1; + max = v; + } + v = btFabs(m_el[1][2]); + if (v > max) + { + p = 1; + q = 2; + r = 0; + max = v; + } + + btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2])); + if (max <= t) + { + if (max <= SIMD_EPSILON * t) + { + return; + } + step = 1; + } + + // compute Jacobi rotation J which leads to a zero for element [p][q] + btScalar mpq = m_el[p][q]; + btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq); + btScalar theta2 = theta * theta; + btScalar cos; + btScalar sin; + if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON)) + { + t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2)) + : 1 / (theta - btSqrt(1 + theta2)); + cos = 1 / btSqrt(1 + t * t); + sin = cos * t; + } + else + { + // approximation for large theta-value, i.e., a nearly diagonal matrix + t = 1 / (theta * (2 + btScalar(0.5) / theta2)); + cos = 1 - btScalar(0.5) * t * t; + sin = cos * t; + } + + // apply rotation to matrix (this = J^T * this * J) + m_el[p][q] = m_el[q][p] = 0; + m_el[p][p] -= t * mpq; + m_el[q][q] += t * mpq; + btScalar mrp = m_el[r][p]; + btScalar mrq = m_el[r][q]; + m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq; + m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp; + + // apply rotation to rot (rot = rot * J) + for (int i = 0; i < 3; i++) + { + btVector3& row = rot[i]; + mrp = row[p]; + mrq = row[q]; + row[p] = cos * mrp - sin * mrq; + row[q] = cos * mrq + sin * mrp; + } + } + } + + + + + /**@brief Calculate the matrix cofactor + * @param r1 The first row to use for calculating the cofactor + * @param c1 The first column to use for calculating the cofactor + * @param r1 The second row to use for calculating the cofactor + * @param c1 The second column to use for calculating the cofactor + * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details + */ + btScalar cofac(int r1, int c1, int r2, int c2) const + { + return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1]; + } + + void serialize(struct btMatrix3x3Data& dataOut) const; + + void serializeFloat(struct btMatrix3x3FloatData& dataOut) const; + + void deSerialize(const struct btMatrix3x3Data& dataIn); + + void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn); + + void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn); + +}; + + +SIMD_FORCE_INLINE btMatrix3x3& +btMatrix3x3::operator*=(const btMatrix3x3& m) +{ +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 rv00, rv01, rv02; + __m128 rv10, rv11, rv12; + __m128 rv20, rv21, rv22; + __m128 mv0, mv1, mv2; + + rv02 = m_el[0].mVec128; + rv12 = m_el[1].mVec128; + rv22 = m_el[2].mVec128; + + mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask); + mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask); + mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask); + + // rv0 + rv00 = bt_splat_ps(rv02, 0); + rv01 = bt_splat_ps(rv02, 1); + rv02 = bt_splat_ps(rv02, 2); + + rv00 = _mm_mul_ps(rv00, mv0); + rv01 = _mm_mul_ps(rv01, mv1); + rv02 = _mm_mul_ps(rv02, mv2); + + // rv1 + rv10 = bt_splat_ps(rv12, 0); + rv11 = bt_splat_ps(rv12, 1); + rv12 = bt_splat_ps(rv12, 2); + + rv10 = _mm_mul_ps(rv10, mv0); + rv11 = _mm_mul_ps(rv11, mv1); + rv12 = _mm_mul_ps(rv12, mv2); + + // rv2 + rv20 = bt_splat_ps(rv22, 0); + rv21 = bt_splat_ps(rv22, 1); + rv22 = bt_splat_ps(rv22, 2); + + rv20 = _mm_mul_ps(rv20, mv0); + rv21 = _mm_mul_ps(rv21, mv1); + rv22 = _mm_mul_ps(rv22, mv2); + + rv00 = _mm_add_ps(rv00, rv01); + rv10 = _mm_add_ps(rv10, rv11); + rv20 = _mm_add_ps(rv20, rv21); + + m_el[0].mVec128 = _mm_add_ps(rv00, rv02); + m_el[1].mVec128 = _mm_add_ps(rv10, rv12); + m_el[2].mVec128 = _mm_add_ps(rv20, rv22); + +#elif defined(BT_USE_NEON) + + float32x4_t rv0, rv1, rv2; + float32x4_t v0, v1, v2; + float32x4_t mv0, mv1, mv2; + + v0 = m_el[0].mVec128; + v1 = m_el[1].mVec128; + v2 = m_el[2].mVec128; + + mv0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask); + mv1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask); + mv2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask); + + rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0); + rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0); + rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0); + + rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1); + rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1); + rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1); + + rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0); + rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0); + rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0); + + m_el[0].mVec128 = rv0; + m_el[1].mVec128 = rv1; + m_el[2].mVec128 = rv2; +#else + setValue( + m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]), + m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]), + m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2])); +#endif + return *this; +} + +SIMD_FORCE_INLINE btMatrix3x3& +btMatrix3x3::operator+=(const btMatrix3x3& m) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128; + m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128; + m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128; +#else + setValue( + m_el[0][0]+m.m_el[0][0], + m_el[0][1]+m.m_el[0][1], + m_el[0][2]+m.m_el[0][2], + m_el[1][0]+m.m_el[1][0], + m_el[1][1]+m.m_el[1][1], + m_el[1][2]+m.m_el[1][2], + m_el[2][0]+m.m_el[2][0], + m_el[2][1]+m.m_el[2][1], + m_el[2][2]+m.m_el[2][2]); +#endif + return *this; +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator*(const btMatrix3x3& m, const btScalar & k) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + __m128 vk = bt_splat_ps(_mm_load_ss((float *)&k), 0x80); + return btMatrix3x3( + _mm_mul_ps(m[0].mVec128, vk), + _mm_mul_ps(m[1].mVec128, vk), + _mm_mul_ps(m[2].mVec128, vk)); +#elif defined(BT_USE_NEON) + return btMatrix3x3( + vmulq_n_f32(m[0].mVec128, k), + vmulq_n_f32(m[1].mVec128, k), + vmulq_n_f32(m[2].mVec128, k)); +#else + return btMatrix3x3( + m[0].x()*k,m[0].y()*k,m[0].z()*k, + m[1].x()*k,m[1].y()*k,m[1].z()*k, + m[2].x()*k,m[2].y()*k,m[2].z()*k); +#endif +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator+(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + return btMatrix3x3( + m1[0].mVec128 + m2[0].mVec128, + m1[1].mVec128 + m2[1].mVec128, + m1[2].mVec128 + m2[2].mVec128); +#else + return btMatrix3x3( + m1[0][0]+m2[0][0], + m1[0][1]+m2[0][1], + m1[0][2]+m2[0][2], + + m1[1][0]+m2[1][0], + m1[1][1]+m2[1][1], + m1[1][2]+m2[1][2], + + m1[2][0]+m2[2][0], + m1[2][1]+m2[2][1], + m1[2][2]+m2[2][2]); +#endif +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator-(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + return btMatrix3x3( + m1[0].mVec128 - m2[0].mVec128, + m1[1].mVec128 - m2[1].mVec128, + m1[2].mVec128 - m2[2].mVec128); +#else + return btMatrix3x3( + m1[0][0]-m2[0][0], + m1[0][1]-m2[0][1], + m1[0][2]-m2[0][2], + + m1[1][0]-m2[1][0], + m1[1][1]-m2[1][1], + m1[1][2]-m2[1][2], + + m1[2][0]-m2[2][0], + m1[2][1]-m2[2][1], + m1[2][2]-m2[2][2]); +#endif +} + + +SIMD_FORCE_INLINE btMatrix3x3& +btMatrix3x3::operator-=(const btMatrix3x3& m) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128; + m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128; + m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128; +#else + setValue( + m_el[0][0]-m.m_el[0][0], + m_el[0][1]-m.m_el[0][1], + m_el[0][2]-m.m_el[0][2], + m_el[1][0]-m.m_el[1][0], + m_el[1][1]-m.m_el[1][1], + m_el[1][2]-m.m_el[1][2], + m_el[2][0]-m.m_el[2][0], + m_el[2][1]-m.m_el[2][1], + m_el[2][2]-m.m_el[2][2]); +#endif + return *this; +} + + +SIMD_FORCE_INLINE btScalar +btMatrix3x3::determinant() const +{ + return btTriple((*this)[0], (*this)[1], (*this)[2]); +} + + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::absolute() const +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + return btMatrix3x3( + _mm_and_ps(m_el[0].mVec128, btvAbsfMask), + _mm_and_ps(m_el[1].mVec128, btvAbsfMask), + _mm_and_ps(m_el[2].mVec128, btvAbsfMask)); +#elif defined(BT_USE_NEON) + return btMatrix3x3( + (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask), + (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask), + (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask)); +#else + return btMatrix3x3( + btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()), + btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()), + btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z())); +#endif +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::transpose() const +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + __m128 v0 = m_el[0].mVec128; + __m128 v1 = m_el[1].mVec128; + __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2 + __m128 vT; + + v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0 + + vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * * + v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1 + + v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0 + v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0 + v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0 + + + return btMatrix3x3( v0, v1, v2 ); +#elif defined(BT_USE_NEON) + // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions. + static const uint32x2_t zMask = (const uint32x2_t) {static_cast(-1), 0 }; + float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1} + float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0} + float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] ); + float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] ); + float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask ); + float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0 + return btMatrix3x3( v0, v1, v2 ); +#else + return btMatrix3x3( m_el[0].x(), m_el[1].x(), m_el[2].x(), + m_el[0].y(), m_el[1].y(), m_el[2].y(), + m_el[0].z(), m_el[1].z(), m_el[2].z()); +#endif +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::adjoint() const +{ + return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2), + cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0), + cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1)); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::inverse() const +{ + btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)); + btScalar det = (*this)[0].dot(co); + btFullAssert(det != btScalar(0.0)); + btScalar s = btScalar(1.0) / det; + return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s, + co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s, + co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s); +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::transposeTimes(const btMatrix3x3& m) const +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + // zeros w +// static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL }; + __m128 row = m_el[0].mVec128; + __m128 m0 = _mm_and_ps( m.getRow(0).mVec128, btvFFF0fMask ); + __m128 m1 = _mm_and_ps( m.getRow(1).mVec128, btvFFF0fMask); + __m128 m2 = _mm_and_ps( m.getRow(2).mVec128, btvFFF0fMask ); + __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0)); + __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55)); + __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa)); + row = m_el[1].mVec128; + r0 = _mm_add_ps( r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0))); + r1 = _mm_add_ps( r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55))); + r2 = _mm_add_ps( r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa))); + row = m_el[2].mVec128; + r0 = _mm_add_ps( r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0))); + r1 = _mm_add_ps( r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55))); + r2 = _mm_add_ps( r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa))); + return btMatrix3x3( r0, r1, r2 ); + +#elif defined BT_USE_NEON + // zeros w + static const uint32x4_t xyzMask = (const uint32x4_t){ static_cast(-1), static_cast(-1), static_cast(-1), 0 }; + float32x4_t m0 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(0).mVec128, xyzMask ); + float32x4_t m1 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(1).mVec128, xyzMask ); + float32x4_t m2 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(2).mVec128, xyzMask ); + float32x4_t row = m_el[0].mVec128; + float32x4_t r0 = vmulq_lane_f32( m0, vget_low_f32(row), 0); + float32x4_t r1 = vmulq_lane_f32( m0, vget_low_f32(row), 1); + float32x4_t r2 = vmulq_lane_f32( m0, vget_high_f32(row), 0); + row = m_el[1].mVec128; + r0 = vmlaq_lane_f32( r0, m1, vget_low_f32(row), 0); + r1 = vmlaq_lane_f32( r1, m1, vget_low_f32(row), 1); + r2 = vmlaq_lane_f32( r2, m1, vget_high_f32(row), 0); + row = m_el[2].mVec128; + r0 = vmlaq_lane_f32( r0, m2, vget_low_f32(row), 0); + r1 = vmlaq_lane_f32( r1, m2, vget_low_f32(row), 1); + r2 = vmlaq_lane_f32( r2, m2, vget_high_f32(row), 0); + return btMatrix3x3( r0, r1, r2 ); +#else + return btMatrix3x3( + m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(), + m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(), + m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(), + m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(), + m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(), + m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), + m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), + m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); +#endif +} + +SIMD_FORCE_INLINE btMatrix3x3 +btMatrix3x3::timesTranspose(const btMatrix3x3& m) const +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + __m128 a0 = m_el[0].mVec128; + __m128 a1 = m_el[1].mVec128; + __m128 a2 = m_el[2].mVec128; + + btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here + __m128 mx = mT[0].mVec128; + __m128 my = mT[1].mVec128; + __m128 mz = mT[2].mVec128; + + __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00)); + __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00)); + __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00)); + r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55))); + r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55))); + r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55))); + r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa))); + r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa))); + r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa))); + return btMatrix3x3( r0, r1, r2); + +#elif defined BT_USE_NEON + float32x4_t a0 = m_el[0].mVec128; + float32x4_t a1 = m_el[1].mVec128; + float32x4_t a2 = m_el[2].mVec128; + + btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here + float32x4_t mx = mT[0].mVec128; + float32x4_t my = mT[1].mVec128; + float32x4_t mz = mT[2].mVec128; + + float32x4_t r0 = vmulq_lane_f32( mx, vget_low_f32(a0), 0); + float32x4_t r1 = vmulq_lane_f32( mx, vget_low_f32(a1), 0); + float32x4_t r2 = vmulq_lane_f32( mx, vget_low_f32(a2), 0); + r0 = vmlaq_lane_f32( r0, my, vget_low_f32(a0), 1); + r1 = vmlaq_lane_f32( r1, my, vget_low_f32(a1), 1); + r2 = vmlaq_lane_f32( r2, my, vget_low_f32(a2), 1); + r0 = vmlaq_lane_f32( r0, mz, vget_high_f32(a0), 0); + r1 = vmlaq_lane_f32( r1, mz, vget_high_f32(a1), 0); + r2 = vmlaq_lane_f32( r2, mz, vget_high_f32(a2), 0); + return btMatrix3x3( r0, r1, r2 ); + +#else + return btMatrix3x3( + m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]), + m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]), + m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2])); +#endif +} + +SIMD_FORCE_INLINE btVector3 +operator*(const btMatrix3x3& m, const btVector3& v) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON) + return v.dot3(m[0], m[1], m[2]); +#else + return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v)); +#endif +} + + +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v, const btMatrix3x3& m) +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + + const __m128 vv = v.mVec128; + + __m128 c0 = bt_splat_ps( vv, 0); + __m128 c1 = bt_splat_ps( vv, 1); + __m128 c2 = bt_splat_ps( vv, 2); + + c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask) ); + c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask) ); + c0 = _mm_add_ps(c0, c1); + c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask) ); + + return btVector3(_mm_add_ps(c0, c2)); +#elif defined(BT_USE_NEON) + const float32x4_t vv = v.mVec128; + const float32x2_t vlo = vget_low_f32(vv); + const float32x2_t vhi = vget_high_f32(vv); + + float32x4_t c0, c1, c2; + + c0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask); + c1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask); + c2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask); + + c0 = vmulq_lane_f32(c0, vlo, 0); + c1 = vmulq_lane_f32(c1, vlo, 1); + c2 = vmulq_lane_f32(c2, vhi, 0); + c0 = vaddq_f32(c0, c1); + c0 = vaddq_f32(c0, c2); + + return btVector3(c0); +#else + return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v)); +#endif +} + +SIMD_FORCE_INLINE btMatrix3x3 +operator*(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + + __m128 m10 = m1[0].mVec128; + __m128 m11 = m1[1].mVec128; + __m128 m12 = m1[2].mVec128; + + __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask); + + __m128 c0 = bt_splat_ps( m10, 0); + __m128 c1 = bt_splat_ps( m11, 0); + __m128 c2 = bt_splat_ps( m12, 0); + + c0 = _mm_mul_ps(c0, m2v); + c1 = _mm_mul_ps(c1, m2v); + c2 = _mm_mul_ps(c2, m2v); + + m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask); + + __m128 c0_1 = bt_splat_ps( m10, 1); + __m128 c1_1 = bt_splat_ps( m11, 1); + __m128 c2_1 = bt_splat_ps( m12, 1); + + c0_1 = _mm_mul_ps(c0_1, m2v); + c1_1 = _mm_mul_ps(c1_1, m2v); + c2_1 = _mm_mul_ps(c2_1, m2v); + + m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask); + + c0 = _mm_add_ps(c0, c0_1); + c1 = _mm_add_ps(c1, c1_1); + c2 = _mm_add_ps(c2, c2_1); + + m10 = bt_splat_ps( m10, 2); + m11 = bt_splat_ps( m11, 2); + m12 = bt_splat_ps( m12, 2); + + m10 = _mm_mul_ps(m10, m2v); + m11 = _mm_mul_ps(m11, m2v); + m12 = _mm_mul_ps(m12, m2v); + + c0 = _mm_add_ps(c0, m10); + c1 = _mm_add_ps(c1, m11); + c2 = _mm_add_ps(c2, m12); + + return btMatrix3x3(c0, c1, c2); + +#elif defined(BT_USE_NEON) + + float32x4_t rv0, rv1, rv2; + float32x4_t v0, v1, v2; + float32x4_t mv0, mv1, mv2; + + v0 = m1[0].mVec128; + v1 = m1[1].mVec128; + v2 = m1[2].mVec128; + + mv0 = (float32x4_t) vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask); + mv1 = (float32x4_t) vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask); + mv2 = (float32x4_t) vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask); + + rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0); + rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0); + rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0); + + rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1); + rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1); + rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1); + + rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0); + rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0); + rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0); + + return btMatrix3x3(rv0, rv1, rv2); + +#else + return btMatrix3x3( + m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]), + m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]), + m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2])); +#endif +} + +/* +SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) { +return btMatrix3x3( +m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0], +m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1], +m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2], +m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0], +m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1], +m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2], +m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0], +m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1], +m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]); +} +*/ + +/**@brief Equality operator between two matrices +* It will test all elements are equal. */ +SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + + __m128 c0, c1, c2; + + c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128); + c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128); + c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128); + + c0 = _mm_and_ps(c0, c1); + c0 = _mm_and_ps(c0, c2); + + return (0x7 == _mm_movemask_ps((__m128)c0)); +#else + return + ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] && + m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] && + m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] ); +#endif +} + +///for serialization +struct btMatrix3x3FloatData +{ + btVector3FloatData m_el[3]; +}; + +///for serialization +struct btMatrix3x3DoubleData +{ + btVector3DoubleData m_el[3]; +}; + + + + +SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const +{ + for (int i=0;i<3;i++) + m_el[i].serialize(dataOut.m_el[i]); +} + +SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const +{ + for (int i=0;i<3;i++) + m_el[i].serializeFloat(dataOut.m_el[i]); +} + + +SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn) +{ + for (int i=0;i<3;i++) + m_el[i].deSerialize(dataIn.m_el[i]); +} + +SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn) +{ + for (int i=0;i<3;i++) + m_el[i].deSerializeFloat(dataIn.m_el[i]); +} + +SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn) +{ + for (int i=0;i<3;i++) + m_el[i].deSerializeDouble(dataIn.m_el[i]); +} + +#endif //BT_MATRIX3x3_H + diff --git a/Code/Physics/src/LinearMath/btMatrixX.h b/Code/Physics/src/LinearMath/btMatrixX.h new file mode 100644 index 00000000..1c29632c --- /dev/null +++ b/Code/Physics/src/LinearMath/btMatrixX.h @@ -0,0 +1,504 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +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. +*/ +///original version written by Erwin Coumans, October 2013 + +#ifndef BT_MATRIX_X_H +#define BT_MATRIX_X_H + +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btAlignedObjectArray.h" + +class btIntSortPredicate +{ + public: + bool operator() ( const int& a, const int& b ) const + { + return a < b; + } +}; + + +template +struct btMatrixX +{ + int m_rows; + int m_cols; + int m_operations; + int m_resizeOperations; + int m_setElemOperations; + + btAlignedObjectArray m_storage; + btAlignedObjectArray< btAlignedObjectArray > m_rowNonZeroElements1; + btAlignedObjectArray< btAlignedObjectArray > m_colNonZeroElements; + + T* getBufferPointerWritable() + { + return m_storage.size() ? &m_storage[0] : 0; + } + + const T* getBufferPointer() const + { + return m_storage.size() ? &m_storage[0] : 0; + } + btMatrixX() + :m_rows(0), + m_cols(0), + m_operations(0), + m_resizeOperations(0), + m_setElemOperations(0) + { + } + btMatrixX(int rows,int cols) + :m_rows(rows), + m_cols(cols), + m_operations(0), + m_resizeOperations(0), + m_setElemOperations(0) + { + resize(rows,cols); + } + void resize(int rows, int cols) + { + m_resizeOperations++; + m_rows = rows; + m_cols = cols; + { + BT_PROFILE("m_storage.resize"); + m_storage.resize(rows*cols); + } + clearSparseInfo(); + } + int cols() const + { + return m_cols; + } + int rows() const + { + return m_rows; + } + ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead + /*T& operator() (int row,int col) + { + return m_storage[col*m_rows+row]; + } + */ + + void addElem(int row,int col, T val) + { + if (val) + { + if (m_storage[col+row*m_cols]==0.f) + { + setElem(row,col,val); + } else + { + m_storage[row*m_cols+col] += val; + } + } + } + + void copyLowerToUpperTriangle() + { + int count=0; + for (int row=0;row0 && numRowsOther>0 && B && C); + const btScalar *bb = B; + for ( int i = 0;i +struct btVectorX +{ + btAlignedObjectArray m_storage; + + btVectorX() + { + } + btVectorX(int numRows) + { + m_storage.resize(numRows); + } + + void resize(int rows) + { + m_storage.resize(rows); + } + int cols() const + { + return 1; + } + int rows() const + { + return m_storage.size(); + } + int size() const + { + return rows(); + } + void setZero() + { + // for (int i=0;i +void setElem(btMatrixX& mat, int row, int col, T val) +{ + mat.setElem(row,col,val); +} +*/ + + +typedef btMatrixX btMatrixXf; +typedef btVectorX btVectorXf; + +typedef btMatrixX btMatrixXd; +typedef btVectorX btVectorXd; + + + +inline void setElem(btMatrixXd& mat, int row, int col, double val) +{ + mat.setElem(row,col,val); +} + +inline void setElem(btMatrixXf& mat, int row, int col, float val) +{ + mat.setElem(row,col,val); +} + +#ifdef BT_USE_DOUBLE_PRECISION + #define btVectorXu btVectorXd + #define btMatrixXu btMatrixXd +#else + #define btVectorXu btVectorXf + #define btMatrixXu btMatrixXf +#endif //BT_USE_DOUBLE_PRECISION + + + +#endif//BT_MATRIX_H_H diff --git a/Code/Physics/src/LinearMath/btMinMax.h b/Code/Physics/src/LinearMath/btMinMax.h new file mode 100644 index 00000000..5b436e9b --- /dev/null +++ b/Code/Physics/src/LinearMath/btMinMax.h @@ -0,0 +1,71 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEN_MINMAX_H +#define BT_GEN_MINMAX_H + +#include "btScalar.h" + +template +SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) +{ + return a < b ? a : b ; +} + +template +SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) +{ + return a > b ? a : b; +} + +template +SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub) +{ + return a < lb ? lb : (ub < a ? ub : a); +} + +template +SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) +{ + if (b < a) + { + a = b; + } +} + +template +SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) +{ + if (a < b) + { + a = b; + } +} + +template +SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) +{ + if (a < lb) + { + a = lb; + } + else if (ub < a) + { + a = ub; + } +} + +#endif //BT_GEN_MINMAX_H diff --git a/Code/Physics/src/LinearMath/btMotionState.h b/Code/Physics/src/LinearMath/btMotionState.h new file mode 100644 index 00000000..94318140 --- /dev/null +++ b/Code/Physics/src/LinearMath/btMotionState.h @@ -0,0 +1,40 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_MOTIONSTATE_H +#define BT_MOTIONSTATE_H + +#include "btTransform.h" + +///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics +///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) +class btMotionState +{ + public: + + virtual ~btMotionState() + { + + } + + virtual void getWorldTransform(btTransform& worldTrans ) const =0; + + //Bullet only calls the update of worldtransform for active objects + virtual void setWorldTransform(const btTransform& worldTrans)=0; + + +}; + +#endif //BT_MOTIONSTATE_H diff --git a/Code/Physics/src/LinearMath/btPolarDecomposition.cpp b/Code/Physics/src/LinearMath/btPolarDecomposition.cpp new file mode 100644 index 00000000..a4dca7fd --- /dev/null +++ b/Code/Physics/src/LinearMath/btPolarDecomposition.cpp @@ -0,0 +1,99 @@ +#include "btPolarDecomposition.h" +#include "btMinMax.h" + +namespace +{ + btScalar abs_column_sum(const btMatrix3x3& a, int i) + { + return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]); + } + + btScalar abs_row_sum(const btMatrix3x3& a, int i) + { + return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]); + } + + btScalar p1_norm(const btMatrix3x3& a) + { + const btScalar sum0 = abs_column_sum(a,0); + const btScalar sum1 = abs_column_sum(a,1); + const btScalar sum2 = abs_column_sum(a,2); + return btMax(btMax(sum0, sum1), sum2); + } + + btScalar pinf_norm(const btMatrix3x3& a) + { + const btScalar sum0 = abs_row_sum(a,0); + const btScalar sum1 = abs_row_sum(a,1); + const btScalar sum2 = abs_row_sum(a,2); + return btMax(btMax(sum0, sum1), sum2); + } +} + +const btScalar btPolarDecomposition::DEFAULT_TOLERANCE = btScalar(0.0001); +const unsigned int btPolarDecomposition::DEFAULT_MAX_ITERATIONS = 16; + +btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations) +: m_tolerance(tolerance) +, m_maxIterations(maxIterations) +{ +} + +unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const +{ + // Use the 'u' and 'h' matrices for intermediate calculations + u = a; + h = a.inverse(); + + for (unsigned int i = 0; i < m_maxIterations; ++i) + { + const btScalar h_1 = p1_norm(h); + const btScalar h_inf = pinf_norm(h); + const btScalar u_1 = p1_norm(u); + const btScalar u_inf = pinf_norm(u); + + const btScalar h_norm = h_1 * h_inf; + const btScalar u_norm = u_1 * u_inf; + + // The matrix is effectively singular so we cannot invert it + if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm)) + break; + + const btScalar gamma = btPow(h_norm / u_norm, 0.25f); + const btScalar inv_gamma = btScalar(1.0) / gamma; + + // Determine the delta to 'u' + const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5); + + // Update the matrices + u += delta; + h = u.inverse(); + + // Check for convergence + if (p1_norm(delta) <= m_tolerance * u_1) + { + h = u.transpose() * a; + h = (h + h.transpose()) * 0.5; + return i; + } + } + + // The algorithm has failed to converge to the specified tolerance, but we + // want to make sure that the matrices returned are in the right form. + h = u.transpose() * a; + h = (h + h.transpose()) * 0.5; + + return m_maxIterations; +} + +unsigned int btPolarDecomposition::maxIterations() const +{ + return m_maxIterations; +} + +unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) +{ + static btPolarDecomposition polar; + return polar.decompose(a, u, h); +} + diff --git a/Code/Physics/src/LinearMath/btPolarDecomposition.h b/Code/Physics/src/LinearMath/btPolarDecomposition.h new file mode 100644 index 00000000..56156676 --- /dev/null +++ b/Code/Physics/src/LinearMath/btPolarDecomposition.h @@ -0,0 +1,73 @@ +#ifndef POLARDECOMPOSITION_H +#define POLARDECOMPOSITION_H + +#include "btMatrix3x3.h" + +/** + * This class is used to compute the polar decomposition of a matrix. In + * general, the polar decomposition factorizes a matrix, A, into two parts: a + * unitary matrix (U) and a positive, semi-definite Hermitian matrix (H). + * However, in this particular implementation the original matrix, A, is + * required to be a square 3x3 matrix with real elements. This means that U will + * be an orthogonal matrix and H with be a positive-definite, symmetric matrix. + */ +class btPolarDecomposition +{ + public: + static const btScalar DEFAULT_TOLERANCE; + static const unsigned int DEFAULT_MAX_ITERATIONS; + + /** + * Creates an instance with optional parameters. + * + * @param tolerance - the tolerance used to determine convergence of the + * algorithm + * @param maxIterations - the maximum number of iterations used to achieve + * convergence + */ + btPolarDecomposition(btScalar tolerance = DEFAULT_TOLERANCE, + unsigned int maxIterations = DEFAULT_MAX_ITERATIONS); + + /** + * Decomposes a matrix into orthogonal and symmetric, positive-definite + * parts. If the number of iterations returned by this function is equal to + * the maximum number of iterations, the algorithm has failed to converge. + * + * @param a - the original matrix + * @param u - the resulting orthogonal matrix + * @param h - the resulting symmetric matrix + * + * @return the number of iterations performed by the algorithm. + */ + unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const; + + /** + * Returns the maximum number of iterations that this algorithm will perform + * to achieve convergence. + * + * @return maximum number of iterations + */ + unsigned int maxIterations() const; + + private: + btScalar m_tolerance; + unsigned int m_maxIterations; +}; + +/** + * This functions decomposes the matrix 'a' into two parts: an orthogonal matrix + * 'u' and a symmetric, positive-definite matrix 'h'. If the number of + * iterations returned by this function is equal to + * btPolarDecomposition::DEFAULT_MAX_ITERATIONS, the algorithm has failed to + * converge. + * + * @param a - the original matrix + * @param u - the resulting orthogonal matrix + * @param h - the resulting symmetric matrix + * + * @return the number of iterations performed by the algorithm. + */ +unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h); + +#endif // POLARDECOMPOSITION_H + diff --git a/Code/Physics/src/LinearMath/btPoolAllocator.h b/Code/Physics/src/LinearMath/btPoolAllocator.h new file mode 100644 index 00000000..ef208453 --- /dev/null +++ b/Code/Physics/src/LinearMath/btPoolAllocator.h @@ -0,0 +1,121 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef _BT_POOL_ALLOCATOR_H +#define _BT_POOL_ALLOCATOR_H + +#include "btScalar.h" +#include "btAlignedAllocator.h" + +///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. +class btPoolAllocator +{ + int m_elemSize; + int m_maxElements; + int m_freeCount; + void* m_firstFree; + unsigned char* m_pool; + +public: + + btPoolAllocator(int elemSize, int maxElements) + :m_elemSize(elemSize), + m_maxElements(maxElements) + { + m_pool = (unsigned char*) btAlignedAlloc( static_cast(m_elemSize*m_maxElements),16); + + unsigned char* p = m_pool; + m_firstFree = p; + m_freeCount = m_maxElements; + int count = m_maxElements; + while (--count) { + *(void**)p = (p + m_elemSize); + p += m_elemSize; + } + *(void**)p = 0; + } + + ~btPoolAllocator() + { + btAlignedFree( m_pool); + } + + int getFreeCount() const + { + return m_freeCount; + } + + int getUsedCount() const + { + return m_maxElements - m_freeCount; + } + + int getMaxCount() const + { + return m_maxElements; + } + + void* allocate(int size) + { + // release mode fix + (void)size; + btAssert(!size || size<=m_elemSize); + btAssert(m_freeCount>0); + void* result = m_firstFree; + m_firstFree = *(void**)m_firstFree; + --m_freeCount; + return result; + } + + bool validPtr(void* ptr) + { + if (ptr) { + if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) + { + return true; + } + } + return false; + } + + void freeMemory(void* ptr) + { + if (ptr) { + btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); + + *(void**)ptr = m_firstFree; + m_firstFree = ptr; + ++m_freeCount; + } + } + + int getElementSize() const + { + return m_elemSize; + } + + unsigned char* getPoolAddress() + { + return m_pool; + } + + const unsigned char* getPoolAddress() const + { + return m_pool; + } + +}; + +#endif //_BT_POOL_ALLOCATOR_H diff --git a/Code/Physics/src/LinearMath/btQuadWord.h b/Code/Physics/src/LinearMath/btQuadWord.h new file mode 100644 index 00000000..11067ef4 --- /dev/null +++ b/Code/Physics/src/LinearMath/btQuadWord.h @@ -0,0 +1,244 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_SIMD_QUADWORD_H +#define BT_SIMD_QUADWORD_H + +#include "btScalar.h" +#include "btMinMax.h" + + + + + +#if defined (__CELLOS_LV2) && defined (__SPU__) +#include +#endif + +/**@brief The btQuadWord class is base class for btVector3 and btQuaternion. + * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. + */ +#ifndef USE_LIBSPE2 +ATTRIBUTE_ALIGNED16(class) btQuadWord +#else +class btQuadWord +#endif +{ +protected: + +#if defined (__SPU__) && defined (__CELLOS_LV2__) + union { + vec_float4 mVec128; + btScalar m_floats[4]; + }; +public: + vec_float4 get128() const + { + return mVec128; + } +protected: +#else //__CELLOS_LV2__ __SPU__ + +#if defined(BT_USE_SSE) || defined(BT_USE_NEON) + union { + btSimdFloat4 mVec128; + btScalar m_floats[4]; + }; +public: + SIMD_FORCE_INLINE btSimdFloat4 get128() const + { + return mVec128; + } + SIMD_FORCE_INLINE void set128(btSimdFloat4 v128) + { + mVec128 = v128; + } +#else + btScalar m_floats[4]; +#endif // BT_USE_SSE + +#endif //__CELLOS_LV2__ __SPU__ + + public: + +#if defined(BT_USE_SSE) || defined(BT_USE_NEON) + + // Set Vector + SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec) + { + mVec128 = vec; + } + + // Copy constructor + SIMD_FORCE_INLINE btQuadWord(const btQuadWord& rhs) + { + mVec128 = rhs.mVec128; + } + + // Assignment Operator + SIMD_FORCE_INLINE btQuadWord& + operator=(const btQuadWord& v) + { + mVec128 = v.mVec128; + + return *this; + } + +#endif + + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } + /**@brief Set the x value */ + SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;}; + /**@brief Set the y value */ + SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;}; + /**@brief Set the z value */ + SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;}; + /**@brief Set the w value */ + SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;}; + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } + /**@brief Return the w value */ + SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } + + //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } + //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } + ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. + SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } + + SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const + { +#ifdef BT_USE_SSE + return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128))); +#else + return ((m_floats[3]==other.m_floats[3]) && + (m_floats[2]==other.m_floats[2]) && + (m_floats[1]==other.m_floats[1]) && + (m_floats[0]==other.m_floats[0])); +#endif + } + + SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const + { + return !(*this == other); + } + + /**@brief Set x,y,z and zero w + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z) + { + m_floats[0]=_x; + m_floats[1]=_y; + m_floats[2]=_z; + m_floats[3] = 0.f; + } + +/* void getValue(btScalar *m) const + { + m[0] = m_floats[0]; + m[1] = m_floats[1]; + m[2] = m_floats[2]; + } +*/ +/**@brief Set the values + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w) + { + m_floats[0]=_x; + m_floats[1]=_y; + m_floats[2]=_z; + m_floats[3]=_w; + } + /**@brief No initialization constructor */ + SIMD_FORCE_INLINE btQuadWord() + // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.)) + { + } + + /**@brief Three argument constructor (zeros w) + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z) + { + m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f; + } + +/**@brief Initializing constructor + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w) + { + m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w; + } + + /**@brief Set each element to the max of the current values and the values of another btQuadWord + * @param other The other btQuadWord to compare with + */ + SIMD_FORCE_INLINE void setMax(const btQuadWord& other) + { + #ifdef BT_USE_SSE + mVec128 = _mm_max_ps(mVec128, other.mVec128); + #elif defined(BT_USE_NEON) + mVec128 = vmaxq_f32(mVec128, other.mVec128); + #else + btSetMax(m_floats[0], other.m_floats[0]); + btSetMax(m_floats[1], other.m_floats[1]); + btSetMax(m_floats[2], other.m_floats[2]); + btSetMax(m_floats[3], other.m_floats[3]); + #endif + } + /**@brief Set each element to the min of the current values and the values of another btQuadWord + * @param other The other btQuadWord to compare with + */ + SIMD_FORCE_INLINE void setMin(const btQuadWord& other) + { + #ifdef BT_USE_SSE + mVec128 = _mm_min_ps(mVec128, other.mVec128); + #elif defined(BT_USE_NEON) + mVec128 = vminq_f32(mVec128, other.mVec128); + #else + btSetMin(m_floats[0], other.m_floats[0]); + btSetMin(m_floats[1], other.m_floats[1]); + btSetMin(m_floats[2], other.m_floats[2]); + btSetMin(m_floats[3], other.m_floats[3]); + #endif + } + + + +}; + +#endif //BT_SIMD_QUADWORD_H diff --git a/Code/Physics/src/LinearMath/btQuaternion.h b/Code/Physics/src/LinearMath/btQuaternion.h new file mode 100644 index 00000000..665421de --- /dev/null +++ b/Code/Physics/src/LinearMath/btQuaternion.h @@ -0,0 +1,909 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_SIMD__QUATERNION_H_ +#define BT_SIMD__QUATERNION_H_ + + +#include "btVector3.h" +#include "btQuadWord.h" + + + + + +#ifdef BT_USE_SSE + +//const __m128 ATTRIBUTE_ALIGNED16(vOnes) = {1.0f, 1.0f, 1.0f, 1.0f}; +#define vOnes (_mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f)) + +#endif + +#if defined(BT_USE_SSE) + +#define vQInv (_mm_set_ps(+0.0f, -0.0f, -0.0f, -0.0f)) +#define vPPPM (_mm_set_ps(-0.0f, +0.0f, +0.0f, +0.0f)) + +#elif defined(BT_USE_NEON) + +const btSimdFloat4 ATTRIBUTE_ALIGNED16(vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f}; +const btSimdFloat4 ATTRIBUTE_ALIGNED16(vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f}; + +#endif + +/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */ +class btQuaternion : public btQuadWord { +public: + /**@brief No initialization constructor */ + btQuaternion() {} + +#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))|| defined(BT_USE_NEON) + // Set Vector + SIMD_FORCE_INLINE btQuaternion(const btSimdFloat4 vec) + { + mVec128 = vec; + } + + // Copy constructor + SIMD_FORCE_INLINE btQuaternion(const btQuaternion& rhs) + { + mVec128 = rhs.mVec128; + } + + // Assignment Operator + SIMD_FORCE_INLINE btQuaternion& + operator=(const btQuaternion& v) + { + mVec128 = v.mVec128; + + return *this; + } + +#endif + + // template + // explicit Quaternion(const btScalar *v) : Tuple4(v) {} + /**@brief Constructor from scalars */ + btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w) + : btQuadWord(_x, _y, _z, _w) + {} + /**@brief Axis angle Constructor + * @param axis The axis which the rotation is around + * @param angle The magnitude of the rotation around the angle (Radians) */ + btQuaternion(const btVector3& _axis, const btScalar& _angle) + { + setRotation(_axis, _angle); + } + /**@brief Constructor from Euler angles + * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z + * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y + * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */ + btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { +#ifndef BT_EULER_DEFAULT_ZYX + setEuler(yaw, pitch, roll); +#else + setEulerZYX(yaw, pitch, roll); +#endif + } + /**@brief Set the rotation using axis angle notation + * @param axis The axis around which to rotate + * @param angle The magnitude of the rotation in Radians */ + void setRotation(const btVector3& axis, const btScalar& _angle) + { + btScalar d = axis.length(); + btAssert(d != btScalar(0.0)); + btScalar s = btSin(_angle * btScalar(0.5)) / d; + setValue(axis.x() * s, axis.y() * s, axis.z() * s, + btCos(_angle * btScalar(0.5))); + } + /**@brief Set the quaternion using Euler angles + * @param yaw Angle around Y + * @param pitch Angle around X + * @param roll Angle around Z */ + void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + btScalar halfYaw = btScalar(yaw) * btScalar(0.5); + btScalar halfPitch = btScalar(pitch) * btScalar(0.5); + btScalar halfRoll = btScalar(roll) * btScalar(0.5); + btScalar cosYaw = btCos(halfYaw); + btScalar sinYaw = btSin(halfYaw); + btScalar cosPitch = btCos(halfPitch); + btScalar sinPitch = btSin(halfPitch); + btScalar cosRoll = btCos(halfRoll); + btScalar sinRoll = btSin(halfRoll); + setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, + sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); + } + /**@brief Set the quaternion using euler angles + * @param yaw Angle around Z + * @param pitch Angle around Y + * @param roll Angle around X */ + void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + btScalar halfYaw = btScalar(yaw) * btScalar(0.5); + btScalar halfPitch = btScalar(pitch) * btScalar(0.5); + btScalar halfRoll = btScalar(roll) * btScalar(0.5); + btScalar cosYaw = btCos(halfYaw); + btScalar sinYaw = btSin(halfYaw); + btScalar cosPitch = btCos(halfPitch); + btScalar sinPitch = btSin(halfPitch); + btScalar cosRoll = btCos(halfRoll); + btScalar sinRoll = btSin(halfRoll); + setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x + cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx + } + /**@brief Add two quaternions + * @param q The quaternion to add to this one */ + SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q) + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_add_ps(mVec128, q.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vaddq_f32(mVec128, q.mVec128); +#else + m_floats[0] += q.x(); + m_floats[1] += q.y(); + m_floats[2] += q.z(); + m_floats[3] += q.m_floats[3]; +#endif + return *this; + } + + /**@brief Subtract out a quaternion + * @param q The quaternion to subtract from this one */ + btQuaternion& operator-=(const btQuaternion& q) + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_sub_ps(mVec128, q.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vsubq_f32(mVec128, q.mVec128); +#else + m_floats[0] -= q.x(); + m_floats[1] -= q.y(); + m_floats[2] -= q.z(); + m_floats[3] -= q.m_floats[3]; +#endif + return *this; + } + + /**@brief Scale this quaternion + * @param s The scalar to scale by */ + btQuaternion& operator*=(const btScalar& s) + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vs = _mm_load_ss(&s); // (S 0 0 0) + vs = bt_pshufd_ps(vs, 0); // (S S S S) + mVec128 = _mm_mul_ps(mVec128, vs); +#elif defined(BT_USE_NEON) + mVec128 = vmulq_n_f32(mVec128, s); +#else + m_floats[0] *= s; + m_floats[1] *= s; + m_floats[2] *= s; + m_floats[3] *= s; +#endif + return *this; + } + + /**@brief Multiply this quaternion by q on the right + * @param q The other quaternion + * Equivilant to this = this * q */ + btQuaternion& operator*=(const btQuaternion& q) + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vQ2 = q.get128(); + + __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0,1,2,0)); + __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); + + A1 = A1 * B1; + + __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1,2,0,1)); + __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); + + A2 = A2 * B2; + + B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2,0,1,2)); + B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); + + B1 = B1 * B2; // A3 *= B3 + + mVec128 = bt_splat_ps(mVec128, 3); // A0 + mVec128 = mVec128 * vQ2; // A0 * B0 + + A1 = A1 + A2; // AB12 + mVec128 = mVec128 - B1; // AB03 = AB0 - AB3 + A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element + mVec128 = mVec128+ A1; // AB03 + AB12 + +#elif defined(BT_USE_NEON) + + float32x4_t vQ1 = mVec128; + float32x4_t vQ2 = q.get128(); + float32x4_t A0, A1, B1, A2, B2, A3, B3; + float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz; + + { + float32x2x2_t tmp; + tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y} + vQ1zx = tmp.val[0]; + + tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y} + vQ2zx = tmp.val[0]; + } + vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1); + + vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1); + + vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1); + vQ2xz = vext_f32(vQ2zx, vQ2zx, 1); + + A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x + B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X + + A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1)); + B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1)); + + A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z + B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z + + A1 = vmulq_f32(A1, B1); + A2 = vmulq_f32(A2, B2); + A3 = vmulq_f32(A3, B3); // A3 *= B3 + A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0 + + A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2 + A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3 + + // change the sign of the last element + A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM); + A0 = vaddq_f32(A0, A1); // AB03 + AB12 + + mVec128 = A0; +#else + setValue( + m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(), + m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(), + m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(), + m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z()); +#endif + return *this; + } + /**@brief Return the dot product between this quaternion and another + * @param q The other quaternion */ + btScalar dot(const btQuaternion& q) const + { +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vd; + + vd = _mm_mul_ps(mVec128, q.mVec128); + + __m128 t = _mm_movehl_ps(vd, vd); + vd = _mm_add_ps(vd, t); + t = _mm_shuffle_ps(vd, vd, 0x55); + vd = _mm_add_ss(vd, t); + + return _mm_cvtss_f32(vd); +#elif defined(BT_USE_NEON) + float32x4_t vd = vmulq_f32(mVec128, q.mVec128); + float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd)); + x = vpadd_f32(x, x); + return vget_lane_f32(x, 0); +#else + return m_floats[0] * q.x() + + m_floats[1] * q.y() + + m_floats[2] * q.z() + + m_floats[3] * q.m_floats[3]; +#endif + } + + /**@brief Return the length squared of the quaternion */ + btScalar length2() const + { + return dot(*this); + } + + /**@brief Return the length of the quaternion */ + btScalar length() const + { + return btSqrt(length2()); + } + + /**@brief Normalize the quaternion + * Such that x^2 + y^2 + z^2 +w^2 = 1 */ + btQuaternion& normalize() + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vd; + + vd = _mm_mul_ps(mVec128, mVec128); + + __m128 t = _mm_movehl_ps(vd, vd); + vd = _mm_add_ps(vd, t); + t = _mm_shuffle_ps(vd, vd, 0x55); + vd = _mm_add_ss(vd, t); + + vd = _mm_sqrt_ss(vd); + vd = _mm_div_ss(vOnes, vd); + vd = bt_pshufd_ps(vd, 0); // splat + mVec128 = _mm_mul_ps(mVec128, vd); + + return *this; +#else + return *this /= length(); +#endif + } + + /**@brief Return a scaled version of this quaternion + * @param s The scale factor */ + SIMD_FORCE_INLINE btQuaternion + operator*(const btScalar& s) const + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vs = _mm_load_ss(&s); // (S 0 0 0) + vs = bt_pshufd_ps(vs, 0x00); // (S S S S) + + return btQuaternion(_mm_mul_ps(mVec128, vs)); +#elif defined(BT_USE_NEON) + return btQuaternion(vmulq_n_f32(mVec128, s)); +#else + return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s); +#endif + } + + /**@brief Return an inversely scaled versionof this quaternion + * @param s The inverse scale factor */ + btQuaternion operator/(const btScalar& s) const + { + btAssert(s != btScalar(0.0)); + return *this * (btScalar(1.0) / s); + } + + /**@brief Inversely scale this quaternion + * @param s The scale factor */ + btQuaternion& operator/=(const btScalar& s) + { + btAssert(s != btScalar(0.0)); + return *this *= btScalar(1.0) / s; + } + + /**@brief Return a normalized version of this quaternion */ + btQuaternion normalized() const + { + return *this / length(); + } + /**@brief Return the ***half*** angle between this quaternion and the other + * @param q The other quaternion */ + btScalar angle(const btQuaternion& q) const + { + btScalar s = btSqrt(length2() * q.length2()); + btAssert(s != btScalar(0.0)); + return btAcos(dot(q) / s); + } + + /**@brief Return the angle between this quaternion and the other along the shortest path + * @param q The other quaternion */ + btScalar angleShortestPath(const btQuaternion& q) const + { + btScalar s = btSqrt(length2() * q.length2()); + btAssert(s != btScalar(0.0)); + if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp + return btAcos(dot(-q) / s) * btScalar(2.0); + else + return btAcos(dot(q) / s) * btScalar(2.0); + } + + /**@brief Return the angle of rotation represented by this quaternion */ + btScalar getAngle() const + { + btScalar s = btScalar(2.) * btAcos(m_floats[3]); + return s; + } + + /**@brief Return the angle of rotation represented by this quaternion along the shortest path*/ + btScalar getAngleShortestPath() const + { + btScalar s; + if (dot(*this) < 0) + s = btScalar(2.) * btAcos(m_floats[3]); + else + s = btScalar(2.) * btAcos(-m_floats[3]); + + return s; + } + + + /**@brief Return the axis of the rotation represented by this quaternion */ + btVector3 getAxis() const + { + btScalar s_squared = 1.f-m_floats[3]*m_floats[3]; + + if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero + return btVector3(1.0, 0.0, 0.0); // Arbitrary + btScalar s = 1.f/btSqrt(s_squared); + return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s); + } + + /**@brief Return the inverse of this quaternion */ + btQuaternion inverse() const + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btQuaternion(_mm_xor_ps(mVec128, vQInv)); +#elif defined(BT_USE_NEON) + return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv)); +#else + return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]); +#endif + } + + /**@brief Return the sum of this quaternion and the other + * @param q2 The other quaternion */ + SIMD_FORCE_INLINE btQuaternion + operator+(const btQuaternion& q2) const + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btQuaternion(_mm_add_ps(mVec128, q2.mVec128)); +#elif defined(BT_USE_NEON) + return btQuaternion(vaddq_f32(mVec128, q2.mVec128)); +#else + const btQuaternion& q1 = *this; + return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]); +#endif + } + + /**@brief Return the difference between this quaternion and the other + * @param q2 The other quaternion */ + SIMD_FORCE_INLINE btQuaternion + operator-(const btQuaternion& q2) const + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btQuaternion(_mm_sub_ps(mVec128, q2.mVec128)); +#elif defined(BT_USE_NEON) + return btQuaternion(vsubq_f32(mVec128, q2.mVec128)); +#else + const btQuaternion& q1 = *this; + return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]); +#endif + } + + /**@brief Return the negative of this quaternion + * This simply negates each element */ + SIMD_FORCE_INLINE btQuaternion operator-() const + { +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btQuaternion(_mm_xor_ps(mVec128, btvMzeroMask)); +#elif defined(BT_USE_NEON) + return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask) ); +#else + const btQuaternion& q2 = *this; + return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]); +#endif + } + /**@todo document this and it's use */ + SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const + { + btQuaternion diff,sum; + diff = *this - qd; + sum = *this + qd; + if( diff.dot(diff) > sum.dot(sum) ) + return qd; + return (-qd); + } + + /**@todo document this and it's use */ + SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const + { + btQuaternion diff,sum; + diff = *this - qd; + sum = *this + qd; + if( diff.dot(diff) < sum.dot(sum) ) + return qd; + return (-qd); + } + + + /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion + * @param q The other quaternion to interpolate with + * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q. + * Slerp interpolates assuming constant velocity. */ + btQuaternion slerp(const btQuaternion& q, const btScalar& t) const + { + btScalar magnitude = btSqrt(length2() * q.length2()); + btAssert(magnitude > btScalar(0)); + + btScalar product = dot(q) / magnitude; + if (btFabs(product) < btScalar(1)) + { + // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp + const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1); + + const btScalar theta = btAcos(sign * product); + const btScalar s1 = btSin(sign * t * theta); + const btScalar d = btScalar(1.0) / btSin(theta); + const btScalar s0 = btSin((btScalar(1.0) - t) * theta); + + return btQuaternion( + (m_floats[0] * s0 + q.x() * s1) * d, + (m_floats[1] * s0 + q.y() * s1) * d, + (m_floats[2] * s0 + q.z() * s1) * d, + (m_floats[3] * s0 + q.m_floats[3] * s1) * d); + } + else + { + return *this; + } + } + + static const btQuaternion& getIdentity() + { + static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.)); + return identityQuat; + } + + SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; } + + +}; + + + + + +/**@brief Return the product of two quaternions */ +SIMD_FORCE_INLINE btQuaternion +operator*(const btQuaternion& q1, const btQuaternion& q2) +{ +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vQ1 = q1.get128(); + __m128 vQ2 = q2.get128(); + __m128 A0, A1, B1, A2, B2; + + A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x // vtrn + B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X // vdup vext + + A1 = A1 * B1; + + A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1)); // Y Z X Y // vext + B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); // z x Y Y // vtrn vdup + + A2 = A2 * B2; + + B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2)); // z x Y Z // vtrn vext + B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); // Y Z x z // vext vtrn + + B1 = B1 * B2; // A3 *= B3 + + A0 = bt_splat_ps(vQ1, 3); // A0 + A0 = A0 * vQ2; // A0 * B0 + + A1 = A1 + A2; // AB12 + A0 = A0 - B1; // AB03 = AB0 - AB3 + + A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element + A0 = A0 + A1; // AB03 + AB12 + + return btQuaternion(A0); + +#elif defined(BT_USE_NEON) + + float32x4_t vQ1 = q1.get128(); + float32x4_t vQ2 = q2.get128(); + float32x4_t A0, A1, B1, A2, B2, A3, B3; + float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz; + + { + float32x2x2_t tmp; + tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y} + vQ1zx = tmp.val[0]; + + tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y} + vQ2zx = tmp.val[0]; + } + vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1); + + vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1); + + vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1); + vQ2xz = vext_f32(vQ2zx, vQ2zx, 1); + + A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x + B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X + + A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1)); + B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1)); + + A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z + B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z + + A1 = vmulq_f32(A1, B1); + A2 = vmulq_f32(A2, B2); + A3 = vmulq_f32(A3, B3); // A3 *= B3 + A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0 + + A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2 + A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3 + + // change the sign of the last element + A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM); + A0 = vaddq_f32(A0, A1); // AB03 + AB12 + + return btQuaternion(A0); + +#else + return btQuaternion( + q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(), + q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(), + q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(), + q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); +#endif +} + +SIMD_FORCE_INLINE btQuaternion +operator*(const btQuaternion& q, const btVector3& w) +{ +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vQ1 = q.get128(); + __m128 vQ2 = w.get128(); + __m128 A1, B1, A2, B2, A3, B3; + + A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3,3,3,0)); + B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0,1,2,0)); + + A1 = A1 * B1; + + A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1)); + B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); + + A2 = A2 * B2; + + A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2)); + B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); + + A3 = A3 * B3; // A3 *= B3 + + A1 = A1 + A2; // AB12 + A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element + A1 = A1 - A3; // AB123 = AB12 - AB3 + + return btQuaternion(A1); + +#elif defined(BT_USE_NEON) + + float32x4_t vQ1 = q.get128(); + float32x4_t vQ2 = w.get128(); + float32x4_t A1, B1, A2, B2, A3, B3; + float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz; + + vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1); + { + float32x2x2_t tmp; + + tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y} + vQ2zx = tmp.val[0]; + + tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y} + vQ1zx = tmp.val[0]; + } + + vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1); + + vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1); + vQ2xz = vext_f32(vQ2zx, vQ2zx, 1); + + A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X + B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x + + A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1)); + B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1)); + + A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z + B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z + + A1 = vmulq_f32(A1, B1); + A2 = vmulq_f32(A2, B2); + A3 = vmulq_f32(A3, B3); // A3 *= B3 + + A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2 + + // change the sign of the last element + A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM); + + A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3 + + return btQuaternion(A1); + +#else + return btQuaternion( + q.w() * w.x() + q.y() * w.z() - q.z() * w.y(), + q.w() * w.y() + q.z() * w.x() - q.x() * w.z(), + q.w() * w.z() + q.x() * w.y() - q.y() * w.x(), + -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); +#endif +} + +SIMD_FORCE_INLINE btQuaternion +operator*(const btVector3& w, const btQuaternion& q) +{ +#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vQ1 = w.get128(); + __m128 vQ2 = q.get128(); + __m128 A1, B1, A2, B2, A3, B3; + + A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x + B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X + + A1 = A1 * B1; + + A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1)); + B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); + + A2 = A2 *B2; + + A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2)); + B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); + + A3 = A3 * B3; // A3 *= B3 + + A1 = A1 + A2; // AB12 + A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element + A1 = A1 - A3; // AB123 = AB12 - AB3 + + return btQuaternion(A1); + +#elif defined(BT_USE_NEON) + + float32x4_t vQ1 = w.get128(); + float32x4_t vQ2 = q.get128(); + float32x4_t A1, B1, A2, B2, A3, B3; + float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz; + + { + float32x2x2_t tmp; + + tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y} + vQ1zx = tmp.val[0]; + + tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y} + vQ2zx = tmp.val[0]; + } + vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1); + + vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1); + + vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1); + vQ2xz = vext_f32(vQ2zx, vQ2zx, 1); + + A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x + B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X + + A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1)); + B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1)); + + A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z + B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z + + A1 = vmulq_f32(A1, B1); + A2 = vmulq_f32(A2, B2); + A3 = vmulq_f32(A3, B3); // A3 *= B3 + + A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2 + + // change the sign of the last element + A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM); + + A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3 + + return btQuaternion(A1); + +#else + return btQuaternion( + +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(), + +w.y() * q.w() + w.z() * q.x() - w.x() * q.z(), + +w.z() * q.w() + w.x() * q.y() - w.y() * q.x(), + -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); +#endif +} + +/**@brief Calculate the dot product between two quaternions */ +SIMD_FORCE_INLINE btScalar +dot(const btQuaternion& q1, const btQuaternion& q2) +{ + return q1.dot(q2); +} + + +/**@brief Return the length of a quaternion */ +SIMD_FORCE_INLINE btScalar +length(const btQuaternion& q) +{ + return q.length(); +} + +/**@brief Return the angle between two quaternions*/ +SIMD_FORCE_INLINE btScalar +btAngle(const btQuaternion& q1, const btQuaternion& q2) +{ + return q1.angle(q2); +} + +/**@brief Return the inverse of a quaternion*/ +SIMD_FORCE_INLINE btQuaternion +inverse(const btQuaternion& q) +{ + return q.inverse(); +} + +/**@brief Return the result of spherical linear interpolation betwen two quaternions + * @param q1 The first quaternion + * @param q2 The second quaternion + * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2 + * Slerp assumes constant velocity between positions. */ +SIMD_FORCE_INLINE btQuaternion +slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) +{ + return q1.slerp(q2, t); +} + +SIMD_FORCE_INLINE btVector3 +quatRotate(const btQuaternion& rotation, const btVector3& v) +{ + btQuaternion q = rotation * v; + q *= rotation.inverse(); +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btVector3(_mm_and_ps(q.get128(), btvFFF0fMask)); +#elif defined(BT_USE_NEON) + return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask)); +#else + return btVector3(q.getX(),q.getY(),q.getZ()); +#endif +} + +SIMD_FORCE_INLINE btQuaternion +shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +{ + btVector3 c = v0.cross(v1); + btScalar d = v0.dot(v1); + + if (d < -1.0 + SIMD_EPSILON) + { + btVector3 n,unused; + btPlaneSpace1(v0,n,unused); + return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0 + } + + btScalar s = btSqrt((1.0f + d) * 2.0f); + btScalar rs = 1.0f / s; + + return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f); +} + +SIMD_FORCE_INLINE btQuaternion +shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) +{ + v0.normalize(); + v1.normalize(); + return shortestArcQuat(v0,v1); +} + +#endif //BT_SIMD__QUATERNION_H_ + + + diff --git a/Code/Physics/src/LinearMath/btQuickprof.cpp b/Code/Physics/src/LinearMath/btQuickprof.cpp new file mode 100644 index 00000000..544aee89 --- /dev/null +++ b/Code/Physics/src/LinearMath/btQuickprof.cpp @@ -0,0 +1,566 @@ +/* + +*************************************************************************************************** +** +** profile.cpp +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ + +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + +#include "btQuickprof.h" + +#ifndef BT_NO_PROFILE + + +static btClock gProfileClock; + + +#ifdef __CELLOS_LV2__ +#include +#include +#include +#endif + +#if defined (SUNOS) || defined (__SUNOS__) +#include +#endif + +#if defined(WIN32) || defined(_WIN32) + +#define BT_USE_WINDOWS_TIMERS +#define WIN32_LEAN_AND_MEAN +#define NOWINRES +#define NOMCX +#define NOIME + +#ifdef _XBOX + #include +#else //_XBOX + #include +#endif //_XBOX + +#include + + +#else //_WIN32 +#include +#endif //_WIN32 + +#define mymin(a,b) (a > b ? a : b) + +struct btClockData +{ + +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; +#else +#ifdef __CELLOS_LV2__ + uint64_t mStartTime; +#else + struct timeval mStartTime; +#endif +#endif //__CELLOS_LV2__ + +}; + +///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. +btClock::btClock() +{ + m_data = new btClockData; +#ifdef BT_USE_WINDOWS_TIMERS + QueryPerformanceFrequency(&m_data->mClockFrequency); +#endif + reset(); +} + +btClock::~btClock() +{ + delete m_data; +} + +btClock::btClock(const btClock& other) +{ + m_data = new btClockData; + *m_data = *other.m_data; +} + +btClock& btClock::operator=(const btClock& other) +{ + *m_data = *other.m_data; + return *this; +} + + + /// Resets the initial reference time. +void btClock::reset() +{ +#ifdef BT_USE_WINDOWS_TIMERS + QueryPerformanceCounter(&m_data->mStartTime); + m_data->mStartTick = GetTickCount(); + m_data->mPrevElapsedTime = 0; +#else +#ifdef __CELLOS_LV2__ + + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + m_data->mStartTime = newTime; +#else + gettimeofday(&m_data->mStartTime, 0); +#endif +#endif +} + +/// Returns the time in ms since the last call to reset or since +/// the btClock was created. +unsigned long int btClock::getTimeMilliseconds() +{ +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + m_data->mStartTime.QuadPart; + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + m_data->mClockFrequency.QuadPart / 1000, elapsedTime - + m_data->mPrevElapsedTime); + m_data->mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + + // Recompute the number of millisecond ticks elapsed. + msecTicks = (unsigned long)(1000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + } + + // Store the current elapsed time for adjustments next time. + m_data->mPrevElapsedTime = elapsedTime; + + return msecTicks; +#else + +#ifdef __CELLOS_LV2__ + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq) / 1000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + SYS_TIMEBASE_GET( newTime ); + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + + (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000; +#endif //__CELLOS_LV2__ +#endif +} + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. +unsigned long int btClock::getTimeMicroseconds() +{ +#ifdef BT_USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + m_data->mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + m_data->mClockFrequency.QuadPart / 1000, elapsedTime - + m_data->mPrevElapsedTime); + m_data->mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + } + + // Store the current elapsed time for adjustments next time. + m_data->mPrevElapsedTime = elapsedTime; + + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + m_data->mClockFrequency.QuadPart); + + return usecTicks; +#else + +#ifdef __CELLOS_LV2__ + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + + return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + + (currentTime.tv_usec - m_data->mStartTime.tv_usec); +#endif//__CELLOS_LV2__ +#endif +} + + + + + +inline void Profile_Get_Ticks(unsigned long int * ticks) +{ + *ticks = gProfileClock.getTimeMicroseconds(); +} + +inline float Profile_Get_Tick_Rate(void) +{ +// return 1000000.f; + return 1000.f; + +} + + + +/*************************************************************************************************** +** +** CProfileNode +** +***************************************************************************************************/ + +/*********************************************************************************************** + * INPUT: * + * name - pointer to a static string which is the name of this profile node * + * parent - parent pointer * + * * + * WARNINGS: * + * The name is assumed to be a static pointer, only the pointer is stored and compared for * + * efficiency reasons. * + *=============================================================================================*/ +CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : + Name( name ), + TotalCalls( 0 ), + TotalTime( 0 ), + StartTime( 0 ), + RecursionCounter( 0 ), + Parent( parent ), + Child( NULL ), + Sibling( NULL ), + m_userPtr(0) +{ + Reset(); +} + + +void CProfileNode::CleanupMemory() +{ + delete ( Child); + Child = NULL; + delete ( Sibling); + Sibling = NULL; +} + +CProfileNode::~CProfileNode( void ) +{ + delete ( Child); + delete ( Sibling); +} + + +/*********************************************************************************************** + * INPUT: * + * name - static string pointer to the name of the node we are searching for * + * * + * WARNINGS: * + * All profile names are assumed to be static strings so this function uses pointer compares * + * to find the named node. * + *=============================================================================================*/ +CProfileNode * CProfileNode::Get_Sub_Node( const char * name ) +{ + // Try to find this sub node + CProfileNode * child = Child; + while ( child ) { + if ( child->Name == name ) { + return child; + } + child = child->Sibling; + } + + // We didn't find it, so add it + + CProfileNode * node = new CProfileNode( name, this ); + node->Sibling = Child; + Child = node; + return node; +} + + +void CProfileNode::Reset( void ) +{ + TotalCalls = 0; + TotalTime = 0.0f; + + + if ( Child ) { + Child->Reset(); + } + if ( Sibling ) { + Sibling->Reset(); + } +} + + +void CProfileNode::Call( void ) +{ + TotalCalls++; + if (RecursionCounter++ == 0) { + Profile_Get_Ticks(&StartTime); + } +} + + +bool CProfileNode::Return( void ) +{ + if ( --RecursionCounter == 0 && TotalCalls != 0 ) { + unsigned long int time; + Profile_Get_Ticks(&time); + time-=StartTime; + TotalTime += (float)time / Profile_Get_Tick_Rate(); + } + return ( RecursionCounter == 0 ); +} + + +/*************************************************************************************************** +** +** CProfileIterator +** +***************************************************************************************************/ +CProfileIterator::CProfileIterator( CProfileNode * start ) +{ + CurrentParent = start; + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::First(void) +{ + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::Next(void) +{ + CurrentChild = CurrentChild->Get_Sibling(); +} + + +bool CProfileIterator::Is_Done(void) +{ + return CurrentChild == NULL; +} + + +void CProfileIterator::Enter_Child( int index ) +{ + CurrentChild = CurrentParent->Get_Child(); + while ( (CurrentChild != NULL) && (index != 0) ) { + index--; + CurrentChild = CurrentChild->Get_Sibling(); + } + + if ( CurrentChild != NULL ) { + CurrentParent = CurrentChild; + CurrentChild = CurrentParent->Get_Child(); + } +} + + +void CProfileIterator::Enter_Parent( void ) +{ + if ( CurrentParent->Get_Parent() != NULL ) { + CurrentParent = CurrentParent->Get_Parent(); + } + CurrentChild = CurrentParent->Get_Child(); +} + + +/*************************************************************************************************** +** +** CProfileManager +** +***************************************************************************************************/ + +CProfileNode CProfileManager::Root( "Root", NULL ); +CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; +int CProfileManager::FrameCounter = 0; +unsigned long int CProfileManager::ResetTime = 0; + + +/*********************************************************************************************** + * CProfileManager::Start_Profile -- Begin a named profile * + * * + * Steps one level deeper into the tree, if a child already exists with the specified name * + * then it accumulates the profiling; otherwise a new child node is added to the profile tree. * + * * + * INPUT: * + * name - name of this profiling record * + * * + * WARNINGS: * + * The string used is assumed to be a static string; pointer compares are used throughout * + * the profiling code for efficiency. * + *=============================================================================================*/ +void CProfileManager::Start_Profile( const char * name ) +{ + if (name != CurrentNode->Get_Name()) { + CurrentNode = CurrentNode->Get_Sub_Node( name ); + } + + CurrentNode->Call(); +} + + +/*********************************************************************************************** + * CProfileManager::Stop_Profile -- Stop timing and record the results. * + *=============================================================================================*/ +void CProfileManager::Stop_Profile( void ) +{ + // Return will indicate whether we should back up to our parent (we may + // be profiling a recursive function) + if (CurrentNode->Return()) { + CurrentNode = CurrentNode->Get_Parent(); + } +} + + +/*********************************************************************************************** + * CProfileManager::Reset -- Reset the contents of the profiling system * + * * + * This resets everything except for the tree structure. All of the timing data is reset. * + *=============================================================================================*/ +void CProfileManager::Reset( void ) +{ + gProfileClock.reset(); + Root.Reset(); + Root.Call(); + FrameCounter = 0; + Profile_Get_Ticks(&ResetTime); +} + + +/*********************************************************************************************** + * CProfileManager::Increment_Frame_Counter -- Increment the frame counter * + *=============================================================================================*/ +void CProfileManager::Increment_Frame_Counter( void ) +{ + FrameCounter++; +} + + +/*********************************************************************************************** + * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset * + *=============================================================================================*/ +float CProfileManager::Get_Time_Since_Reset( void ) +{ + unsigned long int time; + Profile_Get_Ticks(&time); + time -= ResetTime; + return (float)time / Profile_Get_Tick_Rate(); +} + +#include + +void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing) +{ + profileIterator->First(); + if (profileIterator->Is_Done()) + return; + + float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time(); + int i; + int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); + for (i=0;iGet_Current_Parent_Name(), parent_time ); + float totalTime = 0.f; + + + int numChildren = 0; + + for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next()) + { + numChildren++; + float current_total_time = profileIterator->Get_Current_Total_Time(); + accumulated_time += current_total_time; + float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; + { + int i; for (i=0;iGet_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls()); + totalTime += current_total_time; + //recurse into children + } + + if (parent_time < accumulated_time) + { + printf("what's wrong\n"); + } + for (i=0;i SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); + + for (i=0;iEnter_Child(i); + dumpRecursive(profileIterator,spacing+3); + profileIterator->Enter_Parent(); + } +} + + + +void CProfileManager::dumpAll() +{ + CProfileIterator* profileIterator = 0; + profileIterator = CProfileManager::Get_Iterator(); + + dumpRecursive(profileIterator,0); + + CProfileManager::Release_Iterator(profileIterator); +} + + + + +#endif //BT_NO_PROFILE diff --git a/Code/Physics/src/LinearMath/btQuickprof.h b/Code/Physics/src/LinearMath/btQuickprof.h new file mode 100644 index 00000000..93f3f4a6 --- /dev/null +++ b/Code/Physics/src/LinearMath/btQuickprof.h @@ -0,0 +1,203 @@ + +/*************************************************************************************************** +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ + +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + + + +#ifndef BT_QUICK_PROF_H +#define BT_QUICK_PROF_H + +//To disable built-in profiling, please comment out next line +//#define BT_NO_PROFILE 1 +#ifndef BT_NO_PROFILE +#include //@todo remove this, backwards compatibility +#include "btScalar.h" +#include "btAlignedAllocator.h" +#include + + + + + +#define USE_BT_CLOCK 1 + +#ifdef USE_BT_CLOCK + +///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. +class btClock +{ +public: + btClock(); + + btClock(const btClock& other); + btClock& operator=(const btClock& other); + + ~btClock(); + + /// Resets the initial reference time. + void reset(); + + /// Returns the time in ms since the last call to reset or since + /// the btClock was created. + unsigned long int getTimeMilliseconds(); + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds(); +private: + struct btClockData* m_data; +}; + +#endif //USE_BT_CLOCK + + + + +///A node in the Profile Hierarchy Tree +class CProfileNode { + +public: + CProfileNode( const char * name, CProfileNode * parent ); + ~CProfileNode( void ); + + CProfileNode * Get_Sub_Node( const char * name ); + + CProfileNode * Get_Parent( void ) { return Parent; } + CProfileNode * Get_Sibling( void ) { return Sibling; } + CProfileNode * Get_Child( void ) { return Child; } + + void CleanupMemory(); + void Reset( void ); + void Call( void ); + bool Return( void ); + + const char * Get_Name( void ) { return Name; } + int Get_Total_Calls( void ) { return TotalCalls; } + float Get_Total_Time( void ) { return TotalTime; } + void* GetUserPointer() const {return m_userPtr;} + void SetUserPointer(void* ptr) { m_userPtr = ptr;} +protected: + + const char * Name; + int TotalCalls; + float TotalTime; + unsigned long int StartTime; + int RecursionCounter; + + CProfileNode * Parent; + CProfileNode * Child; + CProfileNode * Sibling; + void* m_userPtr; +}; + +///An iterator to navigate through the tree +class CProfileIterator +{ +public: + // Access all the children of the current parent + void First(void); + void Next(void); + bool Is_Done(void); + bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } + + void Enter_Child( int index ); // Make the given child the new parent + void Enter_Largest_Child( void ); // Make the largest child the new parent + void Enter_Parent( void ); // Make the current parent's parent the new parent + + // Access the current child + const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } + int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } + float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } + + void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); } + void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);} + // Access the current parent + const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } + int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } + float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } + + + +protected: + + CProfileNode * CurrentParent; + CProfileNode * CurrentChild; + + + CProfileIterator( CProfileNode * start ); + friend class CProfileManager; +}; + + +///The Manager for the Profile system +class CProfileManager { +public: + static void Start_Profile( const char * name ); + static void Stop_Profile( void ); + + static void CleanupMemory(void) + { + Root.CleanupMemory(); + } + + static void Reset( void ); + static void Increment_Frame_Counter( void ); + static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } + static float Get_Time_Since_Reset( void ); + + static CProfileIterator * Get_Iterator( void ) + { + + return new CProfileIterator( &Root ); + } + static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } + + static void dumpRecursive(CProfileIterator* profileIterator, int spacing); + + static void dumpAll(); + +private: + static CProfileNode Root; + static CProfileNode * CurrentNode; + static int FrameCounter; + static unsigned long int ResetTime; +}; + + +///ProfileSampleClass is a simple way to profile a function's scope +///Use the BT_PROFILE macro at the start of scope to time +class CProfileSample { +public: + CProfileSample( const char * name ) + { + CProfileManager::Start_Profile( name ); + } + + ~CProfileSample( void ) + { + CProfileManager::Stop_Profile(); + } +}; + + +#define BT_PROFILE( name ) CProfileSample __profile( name ) + +#else + +#define BT_PROFILE( name ) + +#endif //#ifndef BT_NO_PROFILE + + + +#endif //BT_QUICK_PROF_H + + diff --git a/Code/Physics/src/LinearMath/btRandom.h b/Code/Physics/src/LinearMath/btRandom.h new file mode 100644 index 00000000..4cbfc6bf --- /dev/null +++ b/Code/Physics/src/LinearMath/btRandom.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_GEN_RANDOM_H +#define BT_GEN_RANDOM_H + +#ifdef MT19937 + +#include +#include + +#define GEN_RAND_MAX UINT_MAX + +SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); } +SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); } + +#else + +#include + +#define GEN_RAND_MAX RAND_MAX + +SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); } +SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); } + +#endif + +#endif //BT_GEN_RANDOM_H + diff --git a/Code/Physics/src/LinearMath/btScalar.h b/Code/Physics/src/LinearMath/btScalar.h new file mode 100644 index 00000000..37c6dec1 --- /dev/null +++ b/Code/Physics/src/LinearMath/btScalar.h @@ -0,0 +1,731 @@ +/* +Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.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 BT_SCALAR_H +#define BT_SCALAR_H + +#ifdef BT_MANAGED_CODE +//Aligned data types not supported in managed code +#pragma unmanaged +#endif + + +#include +#include //size_t for MSVC 6.0 +#include + +/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ +#define BT_BULLET_VERSION 282 + +inline int btGetVersion() +{ + return BT_BULLET_VERSION; +} + +#if defined(DEBUG) || defined (_DEBUG) +#define BT_DEBUG +#endif + + +#ifdef _WIN32 + + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + + #define SIMD_FORCE_INLINE inline + #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED64(a) a + #define ATTRIBUTE_ALIGNED128(a) a + #else + //#define BT_HAS_ALIGNED_ALLOCATOR + #pragma warning(disable : 4324) // disable padding warning +// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. +// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines +// #pragma warning(disable:4786) // Disable the "debug name too long" warning + + #define SIMD_FORCE_INLINE __forceinline + #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a + #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a + #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a + #ifdef _XBOX + #define BT_USE_VMX128 + + #include + #define BT_HAVE_NATIVE_FSEL + #define btFsel(a,b,c) __fsel((a),(b),(c)) + #else + +#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION)) + #if _MSC_VER>1400 + #define BT_USE_SIMD_VECTOR3 + #endif + + #define BT_USE_SSE + #ifdef BT_USE_SSE + //BT_USE_SSE_IN_API is disabled under Windows by default, because + //it makes it harder to integrate Bullet into your application under Windows + //(structured embedding Bullet structs/classes need to be 16-byte aligned) + //with relatively little performance gain + //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries + //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage) + //#define BT_USE_SSE_IN_API + #endif //BT_USE_SSE + #include +#endif + + #endif//_XBOX + + #endif //__MINGW32__ + +#ifdef BT_DEBUG + #ifdef _MSC_VER + #include + #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }} + #else//_MSC_VER + #include + #define btAssert assert + #endif//_MSC_VER +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + +#else + +#if defined (__CELLOS_LV2__) + #define SIMD_FORCE_INLINE inline __attribute__((always_inline)) + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif +#ifdef BT_DEBUG +#ifdef __SPU__ +#include +#define printf spu_printf + #define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}} +#else + #define btAssert assert +#endif + +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + +#else + +#ifdef USE_LIBSPE2 + + #define SIMD_FORCE_INLINE __inline + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif +#ifdef BT_DEBUG + #define btAssert assert +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + + #define btLikely(_c) __builtin_expect((_c), 1) + #define btUnlikely(_c) __builtin_expect((_c), 0) + + +#else + //non-windows systems + +#if (defined (__APPLE__) && (!defined (BT_USE_DOUBLE_PRECISION))) + #if defined (__i386__) || defined (__x86_64__) + #define BT_USE_SIMD_VECTOR3 + #define BT_USE_SSE + //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries + //if apps run into issues, we will disable the next line + #define BT_USE_SSE_IN_API + #ifdef BT_USE_SSE + // include appropriate SSE level + #if defined (__SSE4_1__) + #include + #elif defined (__SSSE3__) + #include + #elif defined (__SSE3__) + #include + #else + #include + #endif + #endif //BT_USE_SSE + #elif defined( __ARM_NEON__ ) + #ifdef __clang__ + #define BT_USE_NEON 1 + #define BT_USE_SIMD_VECTOR3 + + #if defined BT_USE_NEON && defined (__clang__) + #include + #endif//BT_USE_NEON + #endif //__clang__ + #endif//__arm__ + + #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline)) +///@todo: check out alignment methods for other platforms/compilers + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif + + #if defined(DEBUG) || defined (_DEBUG) + #if defined (__i386__) || defined (__x86_64__) + #include + #define btAssert(x)\ + {\ + if(!(x))\ + {\ + printf("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\ + asm volatile ("int3");\ + }\ + } + #else//defined (__i386__) || defined (__x86_64__) + #define btAssert assert + #endif//defined (__i386__) || defined (__x86_64__) + #else//defined(DEBUG) || defined (_DEBUG) + #define btAssert(x) + #endif//defined(DEBUG) || defined (_DEBUG) + + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + #define btLikely(_c) _c + #define btUnlikely(_c) _c + +#else + + #define SIMD_FORCE_INLINE inline + ///@todo: check out alignment methods for other platforms/compilers + ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) + ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED64(a) a + #define ATTRIBUTE_ALIGNED128(a) a + #ifndef assert + #include + #endif + +#if defined(DEBUG) || defined (_DEBUG) + #define btAssert assert +#else + #define btAssert(x) +#endif + + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + #define btLikely(_c) _c + #define btUnlikely(_c) _c +#endif //__APPLE__ + +#endif // LIBSPE2 + +#endif //__CELLOS_LV2__ +#endif + + +///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. +#if defined(BT_USE_DOUBLE_PRECISION) + +typedef double btScalar; +//this number could be bigger in double precision +#define BT_LARGE_FLOAT 1e30 +#else + +typedef float btScalar; +//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX +#define BT_LARGE_FLOAT 1e18f +#endif + +#ifdef BT_USE_SSE +typedef __m128 btSimdFloat4; +#endif//BT_USE_SSE + +#if defined (BT_USE_SSE) +//#if defined BT_USE_SSE_IN_API && defined (BT_USE_SSE) +#ifdef _WIN32 + +#ifndef BT_NAN +static int btNanMask = 0x7F800001; +#define BT_NAN (*(float*)&btNanMask) +#endif + +#ifndef BT_INFINITY +static int btInfinityMask = 0x7F800000; +#define BT_INFINITY (*(float*)&btInfinityMask) +#endif + +//use this, in case there are clashes (such as xnamath.h) +#ifndef BT_NO_SIMD_OPERATOR_OVERLOADS +inline __m128 operator + (const __m128 A, const __m128 B) +{ + return _mm_add_ps(A, B); +} + +inline __m128 operator - (const __m128 A, const __m128 B) +{ + return _mm_sub_ps(A, B); +} + +inline __m128 operator * (const __m128 A, const __m128 B) +{ + return _mm_mul_ps(A, B); +} +#endif //BT_NO_SIMD_OPERATOR_OVERLOADS + +#define btCastfTo128i(a) (_mm_castps_si128(a)) +#define btCastfTo128d(a) (_mm_castps_pd(a)) +#define btCastiTo128f(a) (_mm_castsi128_ps(a)) +#define btCastdTo128f(a) (_mm_castpd_ps(a)) +#define btCastdTo128i(a) (_mm_castpd_si128(a)) +#define btAssign128(r0,r1,r2,r3) _mm_setr_ps(r0,r1,r2,r3) + +#else//_WIN32 + +#define btCastfTo128i(a) ((__m128i)(a)) +#define btCastfTo128d(a) ((__m128d)(a)) +#define btCastiTo128f(a) ((__m128) (a)) +#define btCastdTo128f(a) ((__m128) (a)) +#define btCastdTo128i(a) ((__m128i)(a)) +#define btAssign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3} +#define BT_INFINITY INFINITY +#define BT_NAN NAN +#endif//_WIN32 +#else + +#ifdef BT_USE_NEON + #include + + typedef float32x4_t btSimdFloat4; + #define BT_INFINITY INFINITY + #define BT_NAN NAN + #define btAssign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3} +#else//BT_USE_NEON + + #ifndef BT_INFINITY + static int btInfinityMask = 0x7F800000; + #define BT_INFINITY (*(float*)&btInfinityMask) + #endif +#endif//BT_USE_NEON + +#endif //BT_USE_SSE + +#ifdef BT_USE_NEON +#include + +typedef float32x4_t btSimdFloat4; +#define BT_INFINITY INFINITY +#define BT_NAN NAN +#define btAssign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3} +#endif + + + + + +#define BT_DECLARE_ALIGNED_ALLOCATOR() \ + SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ + + + +#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) + +SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } +SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } +SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (xbtScalar(1)) x=btScalar(1); return acos(x); } +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (xbtScalar(1)) x=btScalar(1); return asin(x); } +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } +SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } +SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } +SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } +SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); } + +#else + +SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) +{ +#ifdef USE_APPROXIMATION + double x, z, tempf; + unsigned long *tfptr = ((unsigned long *)&tempf) + 1; + + tempf = y; + *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ + x = tempf; + z = y*btScalar(0.5); + x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + return x*y; +#else + return sqrtf(y); +#endif +} +SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } +SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { + if (xbtScalar(1)) + x=btScalar(1); + return acosf(x); +} +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { + if (xbtScalar(1)) + x=btScalar(1); + return asinf(x); +} +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } +SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } +SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } +SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } +SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); } + +#endif + +#define SIMD_PI btScalar(3.1415926535897932384626433832795029) +#define SIMD_2_PI btScalar(2.0) * SIMD_PI +#define SIMD_HALF_PI (SIMD_PI * btScalar(0.5)) +#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) +#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) +#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) + +#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ +#define btRecip(x) (btScalar(1.0)/btScalar(x)) + +#ifdef BT_USE_DOUBLE_PRECISION +#define SIMD_EPSILON DBL_EPSILON +#define SIMD_INFINITY DBL_MAX +#else +#define SIMD_EPSILON FLT_EPSILON +#define SIMD_INFINITY FLT_MAX +#endif + +SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) +{ + btScalar coeff_1 = SIMD_PI / 4.0f; + btScalar coeff_2 = 3.0f * coeff_1; + btScalar abs_y = btFabs(y); + btScalar angle; + if (x >= 0.0f) { + btScalar r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + btScalar r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; +} + +SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } + +SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { + return (((a) <= eps) && !((a) < -eps)); +} +SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { + return (!((a) <= eps)); +} + + +SIMD_FORCE_INLINE int btIsNegative(btScalar x) { + return x < btScalar(0.0) ? 1 : 0; +} + +SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } +SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } + +#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifndef btFsel +SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) +{ + return a >= 0 ? b : c; +} +#endif +#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) + + +SIMD_FORCE_INLINE bool btMachineIsLittleEndian() +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + return true; + else + return false; +} + + + +///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 +///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html +SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) +{ + // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero + // Rely on positive value or'ed with its negative having sign bit on + // and zero value or'ed with its negative (which is still zero) having sign bit off + // Use arithmetic shift right, shifting the sign bit through all 32 bits + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) +{ + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return static_cast((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) +{ +#ifdef BT_HAVE_NATIVE_FSEL + return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); +#else + return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; +#endif +} + +template SIMD_FORCE_INLINE void btSwap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +//PCK: endian swapping functions +SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) +{ + return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) +{ + return static_cast(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); +} + +SIMD_FORCE_INLINE unsigned btSwapEndian(int val) +{ + return btSwapEndian((unsigned)val); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) +{ + return btSwapEndian((unsigned short) val); +} + +///btSwapFloat uses using char pointers to swap the endianness +////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values +///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. +///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. +///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. +///so instead of returning a float/double, we return integer/long long integer +SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) +{ + unsigned int a = 0; + unsigned char *dst = (unsigned char *)&a; + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + return a; +} + +// unswap using char pointers +SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) +{ + float d = 0.0f; + unsigned char *src = (unsigned char *)&a; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + + return d; +} + + +// swap using char pointers +SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) +{ + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + +} + +// unswap using char pointers +SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) +{ + double d = 0.0; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + + return d; +} + +template +SIMD_FORCE_INLINE void btSetZero(T* a, int n) +{ + T* acurr = a; + size_t ncurr = n; + while (ncurr > 0) + { + *(acurr++) = 0; + --ncurr; + } +} + + +SIMD_FORCE_INLINE btScalar btLargeDot(const btScalar *a, const btScalar *b, int n) +{ + btScalar p0,q0,m0,p1,q1,m1,sum; + sum = 0; + n -= 2; + while (n >= 0) { + p0 = a[0]; q0 = b[0]; + m0 = p0 * q0; + p1 = a[1]; q1 = b[1]; + m1 = p1 * q1; + sum += m0; + sum += m1; + a += 2; + b += 2; + n -= 2; + } + n += 2; + while (n > 0) { + sum += (*a) * (*b); + a++; + b++; + n--; + } + return sum; +} + + +// returns normalized value in range [-SIMD_PI, SIMD_PI] +SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) +{ + angleInRadians = btFmod(angleInRadians, SIMD_2_PI); + if(angleInRadians < -SIMD_PI) + { + return angleInRadians + SIMD_2_PI; + } + else if(angleInRadians > SIMD_PI) + { + return angleInRadians - SIMD_2_PI; + } + else + { + return angleInRadians; + } +} + + + +///rudimentary class to provide type info +struct btTypedObject +{ + btTypedObject(int objectType) + :m_objectType(objectType) + { + } + int m_objectType; + inline int getObjectType() const + { + return m_objectType; + } +}; + + + +///align a pointer to the provided alignment, upwards +template T* btAlignPointer(T* unalignedPtr, size_t alignment) +{ + + struct btConvertPointerSizeT + { + union + { + T* ptr; + size_t integer; + }; + }; + btConvertPointerSizeT converter; + + + const size_t bit_mask = ~(alignment - 1); + converter.ptr = unalignedPtr; + converter.integer += alignment-1; + converter.integer &= bit_mask; + return converter.ptr; +} + +#endif //BT_SCALAR_H diff --git a/Code/Physics/src/LinearMath/btSerializer.cpp b/Code/Physics/src/LinearMath/btSerializer.cpp new file mode 100644 index 00000000..ba344939 --- /dev/null +++ b/Code/Physics/src/LinearMath/btSerializer.cpp @@ -0,0 +1,991 @@ +char sBulletDNAstr[]= { +char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(69),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109), +char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95), +char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111), +char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110), +char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115), +char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51), +char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109), +char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98), +char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100), +char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122), +char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77), +char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109), +char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97), +char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109), +char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101), +char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98), +char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77), +char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110), +char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115), +char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67), +char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109), +char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117), +char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111), +char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105), +char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116), +char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0), +char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117), +char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110), +char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97), +char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110), +char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97), +char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109), +char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112), +char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115), +char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109), +char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100), +char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108), +char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111), +char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99), +char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0), +char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118), +char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101), +char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115), +char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51), +char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101), +char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117), +char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116), +char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114), +char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104), +char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99), +char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66), +char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108), +char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111), +char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109), +char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115), +char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109), +char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104), +char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104), +char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97), +char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100), +char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86), +char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103), +char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42), +char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101), +char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80), +char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95), +char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110), +char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114), +char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68), +char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122), +char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110), +char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83), +char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117), +char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(103),char(105),char(109),char(112),char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121), +char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115), +char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100), +char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117), +char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97), +char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104), +char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105), +char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105), +char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97), +char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105), +char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105), +char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101), +char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105), +char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95), +char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0), +char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84), +char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116), +char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109), +char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114), +char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99), +char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114), +char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84), +char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116), +char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84), +char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95), +char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105), +char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67), +char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73), +char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110), +char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0), +char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97), +char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103), +char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70), +char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101), +char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105), +char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0), +char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101), +char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103), +char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103), +char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76), +char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), +char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103), +char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100), +char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117), +char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108), +char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111), +char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103), +char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110), +char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65), +char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101), +char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112), +char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100), +char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97), +char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68), +char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108), +char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100), +char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109), +char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98), +char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104), +char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100), +char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97), +char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109), +char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101), +char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102), +char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), +char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108), +char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101), +char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114), +char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105), +char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116), +char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111), +char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119), +char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110), +char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(100),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109), +char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110), +char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116), +char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109), +char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110), +char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105), +char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83), +char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103), +char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65), +char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109), +char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97), +char(120),char(69),char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111), +char(114),char(0),char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111), +char(98),char(97),char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115), +char(101),char(80),char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), +char(100),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110), +char(69),char(114),char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119), +char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95), +char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109), +char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114), +char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117), +char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114), +char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99), +char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), +char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116), +char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115), +char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0), +char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109), +char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95), +char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0), +char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109), +char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97), +char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95), +char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101), +char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110), +char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100), +char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114), +char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100), +char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101), +char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111), +char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100), +char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111), +char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95), +char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117), +char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105), +char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99), +char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100), +char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99), +char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116), +char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114), +char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100), +char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111), +char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100), +char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103), +char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105), +char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102), +char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83), +char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116), +char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73), +char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110), +char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116), +char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116), +char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97), +char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111), +char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109), +char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87), +char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102), +char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95), +char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112), +char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115), +char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97), +char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101), +char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97), +char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95), +char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109), +char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0), +char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97), +char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109), +char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108), +char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109), +char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105), +char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109), +char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100), +char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50), +char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101), +char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50), +char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121), +char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109), +char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0), +char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109), +char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97), +char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116), +char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77), +char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0), +char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114), +char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0), +char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74), +char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(0),char(84),char(89),char(80),char(69), +char(87),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116), +char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111), +char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100), +char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115), +char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98), +char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78), +char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109), +char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70), +char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100), +char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97), +char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100), +char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97), +char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105), +char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120), +char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97), +char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115), +char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105), +char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115), +char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110), +char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121), +char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108), +char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108), +char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77), +char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101), +char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108), +char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116), +char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115), +char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108), +char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108), +char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116), +char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0), +char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49), +char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), +char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100), +char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97), +char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110), +char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111), +char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116), +char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105), +char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), +char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111), +char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0), +char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), +char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119), +char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), +char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67), +char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50), +char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103), +char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110), +char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114), +char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108), +char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117), +char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114), +char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114), +char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116), +char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83), +char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116), +char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100), +char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100), +char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67), +char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111), +char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105), +char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111), +char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0), +char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0), +char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0), +char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0), +char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0), +char(16),char(0),char(64),char(0),char(68),char(0),char(-48),char(1),char(0),char(1),char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-24),char(1), +char(-96),char(3),char(8),char(0),char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1), +char(-36),char(0),char(-116),char(1),char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-52),char(0),char(108),char(1), +char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0), +char(92),char(1),char(104),char(0),char(-84),char(1),char(0),char(0),char(83),char(84),char(82),char(67),char(76),char(0),char(0),char(0),char(10),char(0),char(3),char(0), +char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0), +char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0), +char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0), +char(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0), +char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(19),char(0),char(4),char(0), +char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(20),char(0),char(6),char(0), +char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0), +char(0),char(0),char(21),char(0),char(21),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0), +char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(22),char(0),char(3),char(0),char(2),char(0),char(14),char(0), +char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(23),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0), +char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0), +char(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0), +char(24),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0), +char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0), +char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),char(25),char(0),char(3),char(0),char(0),char(0),char(35),char(0), +char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(26),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0), +char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(27),char(0),char(5),char(0),char(25),char(0),char(38),char(0), +char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(28),char(0),char(2),char(0), +char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0), +char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0), +char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0), +char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0), +char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0), +char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),char(34),char(0),char(62),char(0),char(13),char(0),char(63),char(0), +char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(36),char(0),char(7),char(0),char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0), +char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0), +char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0), +char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0), +char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0), +char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(78),char(0), +char(0),char(0),char(37),char(0),char(43),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0), +char(44),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0), +char(37),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(44),char(0),char(85),char(0),char(4),char(0),char(86),char(0), +char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0), +char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0), +char(45),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0), +char(4),char(0),char(96),char(0),char(46),char(0),char(5),char(0),char(27),char(0),char(47),char(0),char(13),char(0),char(97),char(0),char(14),char(0),char(98),char(0), +char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0), +char(25),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(18),char(0),char(104),char(0),char(18),char(0),char(105),char(0),char(14),char(0),char(106),char(0), +char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0), +char(8),char(0),char(112),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0), +char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0), +char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(25),char(0),char(9),char(0),char(101),char(0), +char(9),char(0),char(102),char(0),char(25),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(17),char(0),char(104),char(0),char(17),char(0),char(105),char(0), +char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0),char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0), +char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0), +char(7),char(0),char(116),char(0),char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0), +char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(49),char(0),char(2),char(0), +char(50),char(0),char(124),char(0),char(14),char(0),char(125),char(0),char(51),char(0),char(2),char(0),char(52),char(0),char(124),char(0),char(13),char(0),char(125),char(0), +char(53),char(0),char(21),char(0),char(48),char(0),char(126),char(0),char(15),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0), +char(13),char(0),char(-126),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0), +char(13),char(0),char(-122),char(0),char(13),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0), +char(7),char(0),char(-117),char(0),char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0), +char(7),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(54),char(0),char(22),char(0),char(47),char(0),char(126),char(0),char(16),char(0),char(127),char(0), +char(14),char(0),char(-128),char(0),char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(125),char(0), +char(14),char(0),char(-124),char(0),char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0), +char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0), +char(8),char(0),char(-114),char(0),char(8),char(0),char(-113),char(0),char(8),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(0),char(0),char(37),char(0), +char(55),char(0),char(2),char(0),char(4),char(0),char(-110),char(0),char(4),char(0),char(-109),char(0),char(56),char(0),char(13),char(0),char(53),char(0),char(-108),char(0), +char(53),char(0),char(-107),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0), +char(4),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0), +char(7),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(57),char(0),char(13),char(0),char(58),char(0),char(-108),char(0),char(58),char(0),char(-107),char(0), +char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0), +char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0), +char(4),char(0),char(-97),char(0),char(59),char(0),char(14),char(0),char(54),char(0),char(-108),char(0),char(54),char(0),char(-107),char(0),char(0),char(0),char(35),char(0), +char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0), +char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0), +char(0),char(0),char(-96),char(0),char(60),char(0),char(3),char(0),char(57),char(0),char(-95),char(0),char(13),char(0),char(-94),char(0),char(13),char(0),char(-93),char(0), +char(61),char(0),char(3),char(0),char(59),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(62),char(0),char(3),char(0), +char(57),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(63),char(0),char(13),char(0),char(57),char(0),char(-95),char(0), +char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0), +char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0), +char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(64),char(0),char(13),char(0),char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0), +char(17),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0), +char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0), +char(7),char(0),char(-81),char(0),char(65),char(0),char(14),char(0),char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0), +char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0), +char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0), +char(0),char(0),char(-80),char(0),char(66),char(0),char(10),char(0),char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0), +char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0), +char(8),char(0),char(-81),char(0),char(8),char(0),char(-76),char(0),char(67),char(0),char(11),char(0),char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0), +char(17),char(0),char(-91),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(7),char(0),char(-83),char(0), +char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-76),char(0),char(0),char(0),char(21),char(0),char(68),char(0),char(9),char(0), +char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0),char(17),char(0),char(-91),char(0),char(13),char(0),char(-75),char(0),char(13),char(0),char(-74),char(0), +char(13),char(0),char(-73),char(0),char(13),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(69),char(0),char(9),char(0), +char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0),char(14),char(0),char(-75),char(0),char(14),char(0),char(-74),char(0), +char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(70),char(0),char(5),char(0), +char(68),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0), +char(71),char(0),char(5),char(0),char(69),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(8),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0), +char(8),char(0),char(-65),char(0),char(72),char(0),char(9),char(0),char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0),char(17),char(0),char(-91),char(0), +char(7),char(0),char(-75),char(0),char(7),char(0),char(-74),char(0),char(7),char(0),char(-73),char(0),char(7),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0), +char(4),char(0),char(-70),char(0),char(73),char(0),char(9),char(0),char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0), +char(8),char(0),char(-75),char(0),char(8),char(0),char(-74),char(0),char(8),char(0),char(-73),char(0),char(8),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0), +char(4),char(0),char(-70),char(0),char(74),char(0),char(5),char(0),char(56),char(0),char(-95),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0), +char(7),char(0),char(-62),char(0),char(0),char(0),char(37),char(0),char(75),char(0),char(4),char(0),char(59),char(0),char(-95),char(0),char(14),char(0),char(-64),char(0), +char(14),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(50),char(0),char(22),char(0),char(8),char(0),char(-61),char(0),char(8),char(0),char(-76),char(0), +char(8),char(0),char(111),char(0),char(8),char(0),char(-60),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0), +char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0), +char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),char(8),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0), +char(4),char(0),char(-47),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(0),char(0),char(37),char(0), +char(52),char(0),char(22),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-76),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(-60),char(0), +char(7),char(0),char(113),char(0),char(7),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0), +char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0), +char(7),char(0),char(-50),char(0),char(7),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),char(4),char(0),char(-46),char(0), +char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(0),char(0),char(37),char(0),char(76),char(0),char(4),char(0),char(7),char(0),char(-43),char(0), +char(7),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(4),char(0),char(79),char(0),char(77),char(0),char(10),char(0),char(76),char(0),char(-40),char(0), +char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0),char(13),char(0),char(-37),char(0),char(13),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0), +char(7),char(0),char(-120),char(0),char(7),char(0),char(-34),char(0),char(4),char(0),char(-33),char(0),char(4),char(0),char(53),char(0),char(78),char(0),char(4),char(0), +char(76),char(0),char(-40),char(0),char(4),char(0),char(-32),char(0),char(7),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(79),char(0),char(4),char(0), +char(13),char(0),char(-35),char(0),char(76),char(0),char(-40),char(0),char(4),char(0),char(-29),char(0),char(7),char(0),char(-28),char(0),char(80),char(0),char(7),char(0), +char(13),char(0),char(-27),char(0),char(76),char(0),char(-40),char(0),char(4),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0), +char(7),char(0),char(-23),char(0),char(4),char(0),char(53),char(0),char(81),char(0),char(6),char(0),char(15),char(0),char(-22),char(0),char(13),char(0),char(-24),char(0), +char(13),char(0),char(-21),char(0),char(58),char(0),char(-20),char(0),char(4),char(0),char(-19),char(0),char(7),char(0),char(-23),char(0),char(82),char(0),char(26),char(0), +char(4),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),char(7),char(0),char(-76),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0), +char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),char(7),char(0),char(-11),char(0),char(7),char(0),char(-10),char(0), +char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0), +char(7),char(0),char(-4),char(0),char(7),char(0),char(-3),char(0),char(7),char(0),char(-2),char(0),char(7),char(0),char(-1),char(0),char(7),char(0),char(0),char(1), +char(7),char(0),char(1),char(1),char(4),char(0),char(2),char(1),char(4),char(0),char(3),char(1),char(4),char(0),char(4),char(1),char(4),char(0),char(5),char(1), +char(4),char(0),char(118),char(0),char(83),char(0),char(12),char(0),char(15),char(0),char(6),char(1),char(15),char(0),char(7),char(1),char(15),char(0),char(8),char(1), +char(13),char(0),char(9),char(1),char(13),char(0),char(10),char(1),char(7),char(0),char(11),char(1),char(4),char(0),char(12),char(1),char(4),char(0),char(13),char(1), +char(4),char(0),char(14),char(1),char(4),char(0),char(15),char(1),char(7),char(0),char(-25),char(0),char(4),char(0),char(53),char(0),char(84),char(0),char(27),char(0), +char(17),char(0),char(16),char(1),char(15),char(0),char(17),char(1),char(15),char(0),char(18),char(1),char(13),char(0),char(9),char(1),char(13),char(0),char(19),char(1), +char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(13),char(0),char(23),char(1),char(4),char(0),char(24),char(1), +char(7),char(0),char(25),char(1),char(4),char(0),char(26),char(1),char(4),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(7),char(0),char(29),char(1), +char(7),char(0),char(30),char(1),char(4),char(0),char(31),char(1),char(4),char(0),char(32),char(1),char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1), +char(7),char(0),char(35),char(1),char(7),char(0),char(36),char(1),char(7),char(0),char(37),char(1),char(7),char(0),char(38),char(1),char(4),char(0),char(39),char(1), +char(4),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(85),char(0),char(12),char(0),char(9),char(0),char(42),char(1),char(9),char(0),char(43),char(1), +char(13),char(0),char(44),char(1),char(7),char(0),char(45),char(1),char(7),char(0),char(-57),char(0),char(7),char(0),char(46),char(1),char(4),char(0),char(47),char(1), +char(13),char(0),char(48),char(1),char(4),char(0),char(49),char(1),char(4),char(0),char(50),char(1),char(4),char(0),char(51),char(1),char(4),char(0),char(53),char(0), +char(86),char(0),char(19),char(0),char(48),char(0),char(126),char(0),char(83),char(0),char(52),char(1),char(76),char(0),char(53),char(1),char(77),char(0),char(54),char(1), +char(78),char(0),char(55),char(1),char(79),char(0),char(56),char(1),char(80),char(0),char(57),char(1),char(81),char(0),char(58),char(1),char(84),char(0),char(59),char(1), +char(85),char(0),char(60),char(1),char(4),char(0),char(61),char(1),char(4),char(0),char(27),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(63),char(1), +char(4),char(0),char(64),char(1),char(4),char(0),char(65),char(1),char(4),char(0),char(66),char(1),char(4),char(0),char(67),char(1),char(82),char(0),char(68),char(1), +}; +int sBulletDNAlen= sizeof(sBulletDNAstr); + +char sBulletDNAstr64[]= { +char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(69),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109), +char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95), +char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111), +char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110), +char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115), +char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51), +char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109), +char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98), +char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100), +char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122), +char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77), +char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109), +char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97), +char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109), +char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101), +char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98), +char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77), +char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110), +char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115), +char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67), +char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109), +char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117), +char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111), +char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105), +char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116), +char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0), +char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117), +char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110), +char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97), +char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110), +char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97), +char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109), +char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112), +char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115), +char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109), +char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100), +char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108), +char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111), +char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99), +char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0), +char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118), +char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101), +char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115), +char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51), +char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101), +char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117), +char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116), +char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114), +char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104), +char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99), +char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66), +char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108), +char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111), +char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109), +char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115), +char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109), +char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104), +char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104), +char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97), +char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100), +char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86), +char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103), +char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42), +char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101), +char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80), +char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95), +char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110), +char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114), +char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68), +char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122), +char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110), +char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83), +char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117), +char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(103),char(105),char(109),char(112),char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121), +char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115), +char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100), +char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117), +char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97), +char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104), +char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105), +char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105), +char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97), +char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105), +char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105), +char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101), +char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105), +char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95), +char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0), +char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84), +char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116), +char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109), +char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114), +char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99), +char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114), +char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84), +char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116), +char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84), +char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95), +char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105), +char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67), +char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73), +char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110), +char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0), +char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97), +char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103), +char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70), +char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101), +char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105), +char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0), +char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101), +char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103), +char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103), +char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76), +char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), +char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103), +char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100), +char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117), +char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108), +char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111), +char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103), +char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110), +char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65), +char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101), +char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112), +char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100), +char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97), +char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68), +char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108), +char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100), +char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109), +char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98), +char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104), +char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),char(97),char(100),char(100), +char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97), +char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109), +char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101), +char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102), +char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108), +char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108), +char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101), +char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114), +char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116), +char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105), +char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116), +char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111), +char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(115),char(119), +char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110), +char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(100),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109), +char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105), +char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110), +char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116), +char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109), +char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110), +char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105), +char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83), +char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103), +char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(65), +char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(97),char(116),char(105),char(111),char(0),char(109), +char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97), +char(120),char(69),char(114),char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111), +char(114),char(0),char(109),char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111), +char(98),char(97),char(108),char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115), +char(101),char(80),char(101),char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), +char(100),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110), +char(69),char(114),char(112),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119), +char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95), +char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109), +char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114), +char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117), +char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114), +char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99), +char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108), +char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116), +char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115), +char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0), +char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109), +char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95), +char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0), +char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109), +char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97), +char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95), +char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101), +char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110), +char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100), +char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114), +char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100), +char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101), +char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111), +char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100), +char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111), +char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95), +char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117), +char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105), +char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99), +char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100), +char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99), +char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116), +char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114), +char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100), +char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111), +char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100), +char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103), +char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105), +char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102), +char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83), +char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116), +char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73), +char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110), +char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116), +char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116), +char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97), +char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111), +char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109), +char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87), +char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102), +char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95), +char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112), +char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115), +char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97), +char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101), +char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97), +char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95), +char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109), +char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0), +char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112), +char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97), +char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109), +char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108), +char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109), +char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105), +char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109), +char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100), +char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50), +char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101), +char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50), +char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121), +char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109), +char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0), +char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109), +char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97), +char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116), +char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77), +char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0), +char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114), +char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0), +char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74), +char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(0),char(84),char(89),char(80),char(69), +char(87),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116), +char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111), +char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100), +char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115), +char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98), +char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78), +char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109), +char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101), +char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70), +char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100), +char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108), +char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97), +char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100), +char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97), +char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116), +char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105), +char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120), +char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97), +char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115), +char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105), +char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115), +char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110), +char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121), +char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108), +char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108), +char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77), +char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101), +char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108), +char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116), +char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115), +char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111), +char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108), +char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108), +char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116), +char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0), +char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97), +char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97), +char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49), +char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108), +char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100), +char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97), +char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110), +char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111), +char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116), +char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116), +char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105), +char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68), +char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), +char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111), +char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0), +char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), +char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119), +char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116), +char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110), +char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67), +char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50), +char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103), +char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110), +char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114), +char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(83),char(108), +char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98), +char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117), +char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114), +char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),char(114), +char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97), +char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116), +char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83), +char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116), +char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100), +char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100), +char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67), +char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111), +char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116), +char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105), +char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111), +char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0), +char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0), +char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0), +char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0), +char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0), +char(16),char(0),char(72),char(0),char(80),char(0),char(-32),char(1),char(16),char(1),char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-8),char(1), +char(-80),char(3),char(8),char(0),char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1), +char(-24),char(0),char(-104),char(1),char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-40),char(0),char(120),char(1), +char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0), +char(104),char(1),char(112),char(0),char(-32),char(1),char(0),char(0),char(83),char(84),char(82),char(67),char(76),char(0),char(0),char(0),char(10),char(0),char(3),char(0), +char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0), +char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0), +char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0), +char(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0), +char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),char(14),char(0),char(11),char(0),char(19),char(0),char(4),char(0), +char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(20),char(0),char(6),char(0), +char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0), +char(0),char(0),char(21),char(0),char(21),char(0),char(6),char(0),char(14),char(0),char(16),char(0),char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0), +char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(22),char(0),char(3),char(0),char(2),char(0),char(14),char(0), +char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(23),char(0),char(12),char(0),char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0), +char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0), +char(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0), +char(24),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0), +char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0), +char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),char(25),char(0),char(3),char(0),char(0),char(0),char(35),char(0), +char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(26),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0), +char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),char(27),char(0),char(5),char(0),char(25),char(0),char(38),char(0), +char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(44),char(0),char(28),char(0),char(2),char(0), +char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0), +char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0), +char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0), +char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0), +char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0), +char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),char(34),char(0),char(62),char(0),char(13),char(0),char(63),char(0), +char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(36),char(0),char(7),char(0),char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0), +char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0), +char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0), +char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0), +char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0), +char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(78),char(0), +char(0),char(0),char(37),char(0),char(43),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0), +char(44),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0), +char(37),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),char(44),char(0),char(85),char(0),char(4),char(0),char(86),char(0), +char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0), +char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0), +char(45),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0), +char(4),char(0),char(96),char(0),char(46),char(0),char(5),char(0),char(27),char(0),char(47),char(0),char(13),char(0),char(97),char(0),char(14),char(0),char(98),char(0), +char(4),char(0),char(99),char(0),char(0),char(0),char(100),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(101),char(0),char(9),char(0),char(102),char(0), +char(25),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(18),char(0),char(104),char(0),char(18),char(0),char(105),char(0),char(14),char(0),char(106),char(0), +char(14),char(0),char(107),char(0),char(14),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0), +char(8),char(0),char(112),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0), +char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0), +char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(25),char(0),char(9),char(0),char(101),char(0), +char(9),char(0),char(102),char(0),char(25),char(0),char(103),char(0),char(0),char(0),char(35),char(0),char(17),char(0),char(104),char(0),char(17),char(0),char(105),char(0), +char(13),char(0),char(106),char(0),char(13),char(0),char(107),char(0),char(13),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0), +char(7),char(0),char(111),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0), +char(7),char(0),char(116),char(0),char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0), +char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),char(4),char(0),char(123),char(0),char(0),char(0),char(37),char(0),char(49),char(0),char(2),char(0), +char(50),char(0),char(124),char(0),char(14),char(0),char(125),char(0),char(51),char(0),char(2),char(0),char(52),char(0),char(124),char(0),char(13),char(0),char(125),char(0), +char(53),char(0),char(21),char(0),char(48),char(0),char(126),char(0),char(15),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0), +char(13),char(0),char(-126),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0), +char(13),char(0),char(-122),char(0),char(13),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0), +char(7),char(0),char(-117),char(0),char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0), +char(7),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(54),char(0),char(22),char(0),char(47),char(0),char(126),char(0),char(16),char(0),char(127),char(0), +char(14),char(0),char(-128),char(0),char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(125),char(0), +char(14),char(0),char(-124),char(0),char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(14),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0), +char(8),char(0),char(-119),char(0),char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0), +char(8),char(0),char(-114),char(0),char(8),char(0),char(-113),char(0),char(8),char(0),char(-112),char(0),char(4),char(0),char(-111),char(0),char(0),char(0),char(37),char(0), +char(55),char(0),char(2),char(0),char(4),char(0),char(-110),char(0),char(4),char(0),char(-109),char(0),char(56),char(0),char(13),char(0),char(53),char(0),char(-108),char(0), +char(53),char(0),char(-107),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0), +char(4),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0), +char(7),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(57),char(0),char(13),char(0),char(58),char(0),char(-108),char(0),char(58),char(0),char(-107),char(0), +char(0),char(0),char(35),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0), +char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(7),char(0),char(-98),char(0), +char(4),char(0),char(-97),char(0),char(59),char(0),char(14),char(0),char(54),char(0),char(-108),char(0),char(54),char(0),char(-107),char(0),char(0),char(0),char(35),char(0), +char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(4),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0), +char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(4),char(0),char(-99),char(0),char(8),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0), +char(0),char(0),char(-96),char(0),char(60),char(0),char(3),char(0),char(57),char(0),char(-95),char(0),char(13),char(0),char(-94),char(0),char(13),char(0),char(-93),char(0), +char(61),char(0),char(3),char(0),char(59),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(62),char(0),char(3),char(0), +char(57),char(0),char(-95),char(0),char(14),char(0),char(-94),char(0),char(14),char(0),char(-93),char(0),char(63),char(0),char(13),char(0),char(57),char(0),char(-95),char(0), +char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0), +char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0), +char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(64),char(0),char(13),char(0),char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0), +char(17),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0), +char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0), +char(7),char(0),char(-81),char(0),char(65),char(0),char(14),char(0),char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0), +char(4),char(0),char(-90),char(0),char(4),char(0),char(-89),char(0),char(4),char(0),char(-88),char(0),char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0), +char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0), +char(0),char(0),char(-80),char(0),char(66),char(0),char(10),char(0),char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0), +char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),char(8),char(0),char(-77),char(0),char(8),char(0),char(-83),char(0),char(8),char(0),char(-82),char(0), +char(8),char(0),char(-81),char(0),char(8),char(0),char(-76),char(0),char(67),char(0),char(11),char(0),char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0), +char(17),char(0),char(-91),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),char(7),char(0),char(-83),char(0), +char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-76),char(0),char(0),char(0),char(21),char(0),char(68),char(0),char(9),char(0), +char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0),char(17),char(0),char(-91),char(0),char(13),char(0),char(-75),char(0),char(13),char(0),char(-74),char(0), +char(13),char(0),char(-73),char(0),char(13),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(69),char(0),char(9),char(0), +char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0),char(14),char(0),char(-75),char(0),char(14),char(0),char(-74),char(0), +char(14),char(0),char(-73),char(0),char(14),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(4),char(0),char(-70),char(0),char(70),char(0),char(5),char(0), +char(68),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(-65),char(0), +char(71),char(0),char(5),char(0),char(69),char(0),char(-69),char(0),char(4),char(0),char(-68),char(0),char(8),char(0),char(-67),char(0),char(8),char(0),char(-66),char(0), +char(8),char(0),char(-65),char(0),char(72),char(0),char(9),char(0),char(57),char(0),char(-95),char(0),char(17),char(0),char(-92),char(0),char(17),char(0),char(-91),char(0), +char(7),char(0),char(-75),char(0),char(7),char(0),char(-74),char(0),char(7),char(0),char(-73),char(0),char(7),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0), +char(4),char(0),char(-70),char(0),char(73),char(0),char(9),char(0),char(59),char(0),char(-95),char(0),char(18),char(0),char(-92),char(0),char(18),char(0),char(-91),char(0), +char(8),char(0),char(-75),char(0),char(8),char(0),char(-74),char(0),char(8),char(0),char(-73),char(0),char(8),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0), +char(4),char(0),char(-70),char(0),char(74),char(0),char(5),char(0),char(56),char(0),char(-95),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0), +char(7),char(0),char(-62),char(0),char(0),char(0),char(37),char(0),char(75),char(0),char(4),char(0),char(59),char(0),char(-95),char(0),char(14),char(0),char(-64),char(0), +char(14),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(50),char(0),char(22),char(0),char(8),char(0),char(-61),char(0),char(8),char(0),char(-76),char(0), +char(8),char(0),char(111),char(0),char(8),char(0),char(-60),char(0),char(8),char(0),char(113),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0), +char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0), +char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),char(8),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0), +char(4),char(0),char(-47),char(0),char(4),char(0),char(-46),char(0),char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(0),char(0),char(37),char(0), +char(52),char(0),char(22),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-76),char(0),char(7),char(0),char(111),char(0),char(7),char(0),char(-60),char(0), +char(7),char(0),char(113),char(0),char(7),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0), +char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0), +char(7),char(0),char(-50),char(0),char(7),char(0),char(-49),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),char(4),char(0),char(-46),char(0), +char(4),char(0),char(-45),char(0),char(4),char(0),char(-44),char(0),char(0),char(0),char(37),char(0),char(76),char(0),char(4),char(0),char(7),char(0),char(-43),char(0), +char(7),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(4),char(0),char(79),char(0),char(77),char(0),char(10),char(0),char(76),char(0),char(-40),char(0), +char(13),char(0),char(-39),char(0),char(13),char(0),char(-38),char(0),char(13),char(0),char(-37),char(0),char(13),char(0),char(-36),char(0),char(13),char(0),char(-35),char(0), +char(7),char(0),char(-120),char(0),char(7),char(0),char(-34),char(0),char(4),char(0),char(-33),char(0),char(4),char(0),char(53),char(0),char(78),char(0),char(4),char(0), +char(76),char(0),char(-40),char(0),char(4),char(0),char(-32),char(0),char(7),char(0),char(-31),char(0),char(4),char(0),char(-30),char(0),char(79),char(0),char(4),char(0), +char(13),char(0),char(-35),char(0),char(76),char(0),char(-40),char(0),char(4),char(0),char(-29),char(0),char(7),char(0),char(-28),char(0),char(80),char(0),char(7),char(0), +char(13),char(0),char(-27),char(0),char(76),char(0),char(-40),char(0),char(4),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0), +char(7),char(0),char(-23),char(0),char(4),char(0),char(53),char(0),char(81),char(0),char(6),char(0),char(15),char(0),char(-22),char(0),char(13),char(0),char(-24),char(0), +char(13),char(0),char(-21),char(0),char(58),char(0),char(-20),char(0),char(4),char(0),char(-19),char(0),char(7),char(0),char(-23),char(0),char(82),char(0),char(26),char(0), +char(4),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),char(7),char(0),char(-76),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0), +char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),char(7),char(0),char(-11),char(0),char(7),char(0),char(-10),char(0), +char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0), +char(7),char(0),char(-4),char(0),char(7),char(0),char(-3),char(0),char(7),char(0),char(-2),char(0),char(7),char(0),char(-1),char(0),char(7),char(0),char(0),char(1), +char(7),char(0),char(1),char(1),char(4),char(0),char(2),char(1),char(4),char(0),char(3),char(1),char(4),char(0),char(4),char(1),char(4),char(0),char(5),char(1), +char(4),char(0),char(118),char(0),char(83),char(0),char(12),char(0),char(15),char(0),char(6),char(1),char(15),char(0),char(7),char(1),char(15),char(0),char(8),char(1), +char(13),char(0),char(9),char(1),char(13),char(0),char(10),char(1),char(7),char(0),char(11),char(1),char(4),char(0),char(12),char(1),char(4),char(0),char(13),char(1), +char(4),char(0),char(14),char(1),char(4),char(0),char(15),char(1),char(7),char(0),char(-25),char(0),char(4),char(0),char(53),char(0),char(84),char(0),char(27),char(0), +char(17),char(0),char(16),char(1),char(15),char(0),char(17),char(1),char(15),char(0),char(18),char(1),char(13),char(0),char(9),char(1),char(13),char(0),char(19),char(1), +char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(13),char(0),char(23),char(1),char(4),char(0),char(24),char(1), +char(7),char(0),char(25),char(1),char(4),char(0),char(26),char(1),char(4),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(7),char(0),char(29),char(1), +char(7),char(0),char(30),char(1),char(4),char(0),char(31),char(1),char(4),char(0),char(32),char(1),char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1), +char(7),char(0),char(35),char(1),char(7),char(0),char(36),char(1),char(7),char(0),char(37),char(1),char(7),char(0),char(38),char(1),char(4),char(0),char(39),char(1), +char(4),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(85),char(0),char(12),char(0),char(9),char(0),char(42),char(1),char(9),char(0),char(43),char(1), +char(13),char(0),char(44),char(1),char(7),char(0),char(45),char(1),char(7),char(0),char(-57),char(0),char(7),char(0),char(46),char(1),char(4),char(0),char(47),char(1), +char(13),char(0),char(48),char(1),char(4),char(0),char(49),char(1),char(4),char(0),char(50),char(1),char(4),char(0),char(51),char(1),char(4),char(0),char(53),char(0), +char(86),char(0),char(19),char(0),char(48),char(0),char(126),char(0),char(83),char(0),char(52),char(1),char(76),char(0),char(53),char(1),char(77),char(0),char(54),char(1), +char(78),char(0),char(55),char(1),char(79),char(0),char(56),char(1),char(80),char(0),char(57),char(1),char(81),char(0),char(58),char(1),char(84),char(0),char(59),char(1), +char(85),char(0),char(60),char(1),char(4),char(0),char(61),char(1),char(4),char(0),char(27),char(1),char(4),char(0),char(62),char(1),char(4),char(0),char(63),char(1), +char(4),char(0),char(64),char(1),char(4),char(0),char(65),char(1),char(4),char(0),char(66),char(1),char(4),char(0),char(67),char(1),char(82),char(0),char(68),char(1), +}; +int sBulletDNAlen64= sizeof(sBulletDNAstr64); diff --git a/Code/Physics/src/LinearMath/btSerializer.h b/Code/Physics/src/LinearMath/btSerializer.h new file mode 100644 index 00000000..ff1dc574 --- /dev/null +++ b/Code/Physics/src/LinearMath/btSerializer.h @@ -0,0 +1,639 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SERIALIZER_H +#define BT_SERIALIZER_H + +#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE +#include "btHashMap.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include + + + +///only the 32bit versions for now +extern char sBulletDNAstr[]; +extern int sBulletDNAlen; +extern char sBulletDNAstr64[]; +extern int sBulletDNAlen64; + +SIMD_FORCE_INLINE int btStrLen(const char* str) +{ + if (!str) + return(0); + int len = 0; + + while (*str != 0) + { + str++; + len++; + } + + return len; +} + + +class btChunk +{ +public: + int m_chunkCode; + int m_length; + void *m_oldPtr; + int m_dna_nr; + int m_number; +}; + +enum btSerializationFlags +{ + BT_SERIALIZE_NO_BVH = 1, + BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2, + BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4 +}; + +class btSerializer +{ + +public: + + virtual ~btSerializer() {} + + virtual const unsigned char* getBufferPointer() const = 0; + + virtual int getCurrentBufferSize() const = 0; + + virtual btChunk* allocate(size_t size, int numElements) = 0; + + virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0; + + virtual void* findPointer(void* oldPtr) = 0; + + virtual void* getUniquePointer(void*oldPtr) = 0; + + virtual void startSerialization() = 0; + + virtual void finishSerialization() = 0; + + virtual const char* findNameForPointer(const void* ptr) const = 0; + + virtual void registerNameForPointer(const void* ptr, const char* name) = 0; + + virtual void serializeName(const char* ptr) = 0; + + virtual int getSerializationFlags() const = 0; + + virtual void setSerializationFlags(int flags) = 0; + + +}; + + + +#define BT_HEADER_LENGTH 12 +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +# define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + +#define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y') +#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J') +#define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y') +#define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S') +#define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S') +#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H') +#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P') +#define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P') +#define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y') +#define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T') +#define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D') +#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D') +#define BT_DNA_CODE BT_MAKE_ID('D','N','A','1') + + +struct btPointerUid +{ + union + { + void* m_ptr; + int m_uniqueIds[2]; + }; +}; + +///The btDefaultSerializer is the main Bullet serialization class. +///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero. +class btDefaultSerializer : public btSerializer +{ + + + btAlignedObjectArray mTypes; + btAlignedObjectArray mStructs; + btAlignedObjectArray mTlens; + btHashMap mStructReverse; + btHashMap mTypeLookup; + + + btHashMap m_chunkP; + + btHashMap m_nameMap; + + btHashMap m_uniquePointers; + int m_uniqueIdGenerator; + + int m_totalSize; + unsigned char* m_buffer; + int m_currentSize; + void* m_dna; + int m_dnaLength; + + int m_serializationFlags; + + + btAlignedObjectArray m_chunkPtrs; + +protected: + + virtual void* findPointer(void* oldPtr) + { + void** ptr = m_chunkP.find(oldPtr); + if (ptr && *ptr) + return *ptr; + return 0; + } + + + + + + void writeDNA() + { + btChunk* dnaChunk = allocate(m_dnaLength,1); + memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength); + finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna); + } + + int getReverseType(const char *type) const + { + + btHashString key(type); + const int* valuePtr = mTypeLookup.find(key); + if (valuePtr) + return *valuePtr; + + return -1; + } + + void initDNA(const char* bdnaOrg,int dnalen) + { + ///was already initialized + if (m_dna) + return; + + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + + m_dna = btAlignedAlloc(dnalen,16); + memcpy(m_dna,bdnaOrg,dnalen); + m_dnaLength = dnalen; + + int *intPtr=0; + short *shtPtr=0; + char *cp = 0;int dataLen =0; + intPtr = (int*)m_dna; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + (4 bytes) amount of names (int) + + + */ + + if (strncmp((const char*)m_dna, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; intPtr++; + } + + // Parse names + if (!littleEndian) + *intPtr = btSwapEndian(*intPtr); + + dataLen = *intPtr; + + intPtr++; + + cp = (char*)intPtr; + int i; + for ( i=0; i amount of types (int) + + + */ + + intPtr = (int*)cp; + btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (!littleEndian) + *intPtr = btSwapEndian(*intPtr); + + dataLen = *intPtr; + intPtr++; + + + cp = (char*)intPtr; + for (i=0; i (short) the lengths of types + + */ + + // Parse type lens + intPtr = (int*)cp; + btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + dataLen = (int)mTypes.size(); + + shtPtr = (short*)intPtr; + for (i=0; i amount of structs (int) + + + + + + + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + btAssert(strncmp(cp, "STRC", 4)==0); intPtr++; + + if (!littleEndian) + *intPtr = btSwapEndian(*intPtr); + dataLen = *intPtr ; + intPtr++; + + + shtPtr = (short*)intPtr; + for (i=0; im_length; + memcpy(currentPtr,m_chunkPtrs[i], curLength); + btAlignedFree(m_chunkPtrs[i]); + currentPtr+=curLength; + mysize+=curLength; + } + } + + mTypes.clear(); + mStructs.clear(); + mTlens.clear(); + mStructReverse.clear(); + mTypeLookup.clear(); + m_chunkP.clear(); + m_nameMap.clear(); + m_uniquePointers.clear(); + m_chunkPtrs.clear(); + } + + virtual void* getUniquePointer(void*oldPtr) + { + if (!oldPtr) + return 0; + + btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr); + if (uptr) + { + return uptr->m_ptr; + } + m_uniqueIdGenerator++; + + btPointerUid uid; + uid.m_uniqueIds[0] = m_uniqueIdGenerator; + uid.m_uniqueIds[1] = m_uniqueIdGenerator; + m_uniquePointers.insert(oldPtr,uid); + return uid.m_ptr; + + } + + virtual const unsigned char* getBufferPointer() const + { + return m_buffer; + } + + virtual int getCurrentBufferSize() const + { + return m_currentSize; + } + + virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr) + { + if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT)) + { + btAssert(!findPointer(oldPtr)); + } + + chunk->m_dna_nr = getReverseType(structType); + + chunk->m_chunkCode = chunkCode; + + void* uniquePtr = getUniquePointer(oldPtr); + + m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr); + chunk->m_oldPtr = uniquePtr;//oldPtr; + + } + + + virtual unsigned char* internalAlloc(size_t size) + { + unsigned char* ptr = 0; + + if (m_totalSize) + { + ptr = m_buffer+m_currentSize; + m_currentSize += int(size); + btAssert(m_currentSizem_chunkCode = 0; + chunk->m_oldPtr = data; + chunk->m_length = int(size)*numElements; + chunk->m_number = numElements; + + m_chunkPtrs.push_back(chunk); + + + return chunk; + } + + virtual const char* findNameForPointer(const void* ptr) const + { + const char*const * namePtr = m_nameMap.find(ptr); + if (namePtr && *namePtr) + return *namePtr; + return 0; + + } + + virtual void registerNameForPointer(const void* ptr, const char* name) + { + m_nameMap.insert(ptr,name); + } + + virtual void serializeName(const char* name) + { + if (name) + { + //don't serialize name twice + if (findPointer((void*)name)) + return; + + int len = btStrLen(name); + if (len) + { + + int newLen = len+1; + int padding = ((newLen+3)&~3)-newLen; + newLen += padding; + + //serialize name string now + btChunk* chunk = allocate(sizeof(char),newLen); + char* destinationName = (char*)chunk->m_oldPtr; + for (int i=0;i(totalsize - usedsize); + } + + unsigned char* allocate(unsigned int size) + { + const unsigned int nus(usedsize+size); + if(nusprevious = current; + pb->address = data+usedsize; + current = pb; + return(pb); + } + SIMD_FORCE_INLINE void endBlock(btBlock* block) + { + btAssert(block==current); + //Raise(L"Unmatched blocks"); + if(block==current) + { + current = block->previous; + usedsize = (unsigned int)((block->address-data)-sizeof(btBlock)); + } + } + +private: + void ctor() + { + data = 0; + totalsize = 0; + usedsize = 0; + current = 0; + ischild = false; + } + unsigned char* data; + unsigned int totalsize; + unsigned int usedsize; + btBlock* current; + bool ischild; +}; + +#endif //BT_STACK_ALLOC diff --git a/Code/Physics/src/LinearMath/btTransform.h b/Code/Physics/src/LinearMath/btTransform.h new file mode 100644 index 00000000..90762737 --- /dev/null +++ b/Code/Physics/src/LinearMath/btTransform.h @@ -0,0 +1,305 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_TRANSFORM_H +#define BT_TRANSFORM_H + + +#include "btMatrix3x3.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btTransformData btTransformDoubleData +#else +#define btTransformData btTransformFloatData +#endif + + + + +/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear. + *It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */ +ATTRIBUTE_ALIGNED16(class) btTransform { + + ///Storage for the rotation + btMatrix3x3 m_basis; + ///Storage for the translation + btVector3 m_origin; + +public: + + /**@brief No initialization constructor */ + btTransform() {} + /**@brief Constructor from btQuaternion (optional btVector3 ) + * @param q Rotation from quaternion + * @param c Translation from Vector (default 0,0,0) */ + explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, + const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) + : m_basis(q), + m_origin(c) + {} + + /**@brief Constructor from btMatrix3x3 (optional btVector3) + * @param b Rotation from Matrix + * @param c Translation from Vector default (0,0,0)*/ + explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, + const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) + : m_basis(b), + m_origin(c) + {} + /**@brief Copy constructor */ + SIMD_FORCE_INLINE btTransform (const btTransform& other) + : m_basis(other.m_basis), + m_origin(other.m_origin) + { + } + /**@brief Assignment Operator */ + SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other) + { + m_basis = other.m_basis; + m_origin = other.m_origin; + return *this; + } + + + /**@brief Set the current transform as the value of the product of two transforms + * @param t1 Transform 1 + * @param t2 Transform 2 + * This = Transform1 * Transform2 */ + SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) { + m_basis = t1.m_basis * t2.m_basis; + m_origin = t1(t2.m_origin); + } + +/* void multInverseLeft(const btTransform& t1, const btTransform& t2) { + btVector3 v = t2.m_origin - t1.m_origin; + m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis); + m_origin = v * t1.m_basis; + } + */ + +/**@brief Return the transform of the vector */ + SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const + { + return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin; + } + + /**@brief Return the transform of the vector */ + SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const + { + return (*this)(x); + } + + /**@brief Return the transform of the btQuaternion */ + SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const + { + return getRotation() * q; + } + + /**@brief Return the basis matrix for the rotation */ + SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; } + /**@brief Return the basis matrix for the rotation */ + SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; } + + /**@brief Return the origin vector translation */ + SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; } + /**@brief Return the origin vector translation */ + SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; } + + /**@brief Return a quaternion representing the rotation */ + btQuaternion getRotation() const { + btQuaternion q; + m_basis.getRotation(q); + return q; + } + + + /**@brief Set from an array + * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ + void setFromOpenGLMatrix(const btScalar *m) + { + m_basis.setFromOpenGLSubMatrix(m); + m_origin.setValue(m[12],m[13],m[14]); + } + + /**@brief Fill an array representation + * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */ + void getOpenGLMatrix(btScalar *m) const + { + m_basis.getOpenGLSubMatrix(m); + m[12] = m_origin.x(); + m[13] = m_origin.y(); + m[14] = m_origin.z(); + m[15] = btScalar(1.0); + } + + /**@brief Set the translational element + * @param origin The vector to set the translation to */ + SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) + { + m_origin = origin; + } + + SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const; + + + /**@brief Set the rotational element by btMatrix3x3 */ + SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis) + { + m_basis = basis; + } + + /**@brief Set the rotational element by btQuaternion */ + SIMD_FORCE_INLINE void setRotation(const btQuaternion& q) + { + m_basis.setRotation(q); + } + + + /**@brief Set this transformation to the identity */ + void setIdentity() + { + m_basis.setIdentity(); + m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + } + + /**@brief Multiply this Transform by another(this = this * another) + * @param t The other transform */ + btTransform& operator*=(const btTransform& t) + { + m_origin += m_basis * t.m_origin; + m_basis *= t.m_basis; + return *this; + } + + /**@brief Return the inverse of this transform */ + btTransform inverse() const + { + btMatrix3x3 inv = m_basis.transpose(); + return btTransform(inv, inv * -m_origin); + } + + /**@brief Return the inverse of this transform times the other transform + * @param t The other transform + * return this.inverse() * the other */ + btTransform inverseTimes(const btTransform& t) const; + + /**@brief Return the product of this transform and the other */ + btTransform operator*(const btTransform& t) const; + + /**@brief Return an identity transform */ + static const btTransform& getIdentity() + { + static const btTransform identityTransform(btMatrix3x3::getIdentity()); + return identityTransform; + } + + void serialize(struct btTransformData& dataOut) const; + + void serializeFloat(struct btTransformFloatData& dataOut) const; + + void deSerialize(const struct btTransformData& dataIn); + + void deSerializeDouble(const struct btTransformDoubleData& dataIn); + + void deSerializeFloat(const struct btTransformFloatData& dataIn); + +}; + + +SIMD_FORCE_INLINE btVector3 +btTransform::invXform(const btVector3& inVec) const +{ + btVector3 v = inVec - m_origin; + return (m_basis.transpose() * v); +} + +SIMD_FORCE_INLINE btTransform +btTransform::inverseTimes(const btTransform& t) const +{ + btVector3 v = t.getOrigin() - m_origin; + return btTransform(m_basis.transposeTimes(t.m_basis), + v * m_basis); +} + +SIMD_FORCE_INLINE btTransform +btTransform::operator*(const btTransform& t) const +{ + return btTransform(m_basis * t.m_basis, + (*this)(t.m_origin)); +} + +/**@brief Test if two transforms have all elements equal */ +SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) +{ + return ( t1.getBasis() == t2.getBasis() && + t1.getOrigin() == t2.getOrigin() ); +} + + +///for serialization +struct btTransformFloatData +{ + btMatrix3x3FloatData m_basis; + btVector3FloatData m_origin; +}; + +struct btTransformDoubleData +{ + btMatrix3x3DoubleData m_basis; + btVector3DoubleData m_origin; +}; + + + +SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const +{ + m_basis.serialize(dataOut.m_basis); + m_origin.serialize(dataOut.m_origin); +} + +SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const +{ + m_basis.serializeFloat(dataOut.m_basis); + m_origin.serializeFloat(dataOut.m_origin); +} + + +SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn) +{ + m_basis.deSerialize(dataIn.m_basis); + m_origin.deSerialize(dataIn.m_origin); +} + +SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn) +{ + m_basis.deSerializeFloat(dataIn.m_basis); + m_origin.deSerializeFloat(dataIn.m_origin); +} + +SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn) +{ + m_basis.deSerializeDouble(dataIn.m_basis); + m_origin.deSerializeDouble(dataIn.m_origin); +} + + +#endif //BT_TRANSFORM_H + + + + + + diff --git a/Code/Physics/src/LinearMath/btTransformUtil.h b/Code/Physics/src/LinearMath/btTransformUtil.h new file mode 100644 index 00000000..2303c274 --- /dev/null +++ b/Code/Physics/src/LinearMath/btTransformUtil.h @@ -0,0 +1,228 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef BT_TRANSFORM_UTIL_H +#define BT_TRANSFORM_UTIL_H + +#include "btTransform.h" +#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI + + + + +SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +{ + return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); +} + + + + + + +/// Utils related to temporal transforms +class btTransformUtil +{ + +public: + + static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform) + { + predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep); +// #define QUATERNION_DERIVATIVE + #ifdef QUATERNION_DERIVATIVE + btQuaternion predictedOrn = curTrans.getRotation(); + predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); + predictedOrn.normalize(); + #else + //Exponential map + //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia + + btVector3 axis; + btScalar fAngle = angvel.length(); + //limit the angular motion + if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD) + { + fAngle = ANGULAR_MOTION_THRESHOLD / timeStep; + } + + if ( fAngle < btScalar(0.001) ) + { + // use Taylor's expansions of sync function + axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle ); + } + else + { + // sync(fAngle) = sin(c*fAngle)/t + axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle ); + } + btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) )); + btQuaternion orn0 = curTrans.getRotation(); + + btQuaternion predictedOrn = dorn * orn0; + predictedOrn.normalize(); + #endif + predictedTransform.setRotation(predictedOrn); + } + + static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel) + { + linVel = (pos1 - pos0) / timeStep; + btVector3 axis; + btScalar angle; + if (orn0 != orn1) + { + calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle); + angVel = axis * angle / timeStep; + } else + { + angVel.setValue(0,0,0); + } + } + + static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle) + { + btQuaternion orn1 = orn0.nearest(orn1a); + btQuaternion dorn = orn1 * orn0.inverse(); + angle = dorn.getAngle(); + axis = btVector3(dorn.x(),dorn.y(),dorn.z()); + axis[3] = btScalar(0.); + //check for axis length + btScalar len = axis.length2(); + if (len < SIMD_EPSILON*SIMD_EPSILON) + axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); + else + axis /= btSqrt(len); + } + + static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel) + { + linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep; + btVector3 axis; + btScalar angle; + calculateDiffAxisAngle(transform0,transform1,axis,angle); + angVel = axis * angle / timeStep; + } + + static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle) + { + btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse(); + btQuaternion dorn; + dmat.getRotation(dorn); + + ///floating point inaccuracy can lead to w component > 1..., which breaks + dorn.normalize(); + + angle = dorn.getAngle(); + axis = btVector3(dorn.x(),dorn.y(),dorn.z()); + axis[3] = btScalar(0.); + //check for axis length + btScalar len = axis.length2(); + if (len < SIMD_EPSILON*SIMD_EPSILON) + axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); + else + axis /= btSqrt(len); + } + +}; + + +///The btConvexSeparatingDistanceUtil can help speed up convex collision detection +///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance +class btConvexSeparatingDistanceUtil +{ + btQuaternion m_ornA; + btQuaternion m_ornB; + btVector3 m_posA; + btVector3 m_posB; + + btVector3 m_separatingNormal; + + btScalar m_boundingRadiusA; + btScalar m_boundingRadiusB; + btScalar m_separatingDistance; + +public: + + btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB) + :m_boundingRadiusA(boundingRadiusA), + m_boundingRadiusB(boundingRadiusB), + m_separatingDistance(0.f) + { + } + + btScalar getConservativeSeparatingDistance() + { + return m_separatingDistance; + } + + void updateSeparatingDistance(const btTransform& transA,const btTransform& transB) + { + const btVector3& toPosA = transA.getOrigin(); + const btVector3& toPosB = transB.getOrigin(); + btQuaternion toOrnA = transA.getRotation(); + btQuaternion toOrnB = transB.getRotation(); + + if (m_separatingDistance>0.f) + { + + + btVector3 linVelA,angVelA,linVelB,angVelB; + btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA); + btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB); + btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal); + if (relLinVelocLength<0.f) + { + relLinVelocLength = 0.f; + } + + btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength; + m_separatingDistance -= projectedMotion; + } + + m_posA = toPosA; + m_posB = toPosB; + m_ornA = toOrnA; + m_ornB = toOrnB; + } + + void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB) + { + m_separatingDistance = separatingDistance; + + if (m_separatingDistance>0.f) + { + m_separatingNormal = separatingVector; + + const btVector3& toPosA = transA.getOrigin(); + const btVector3& toPosB = transB.getOrigin(); + btQuaternion toOrnA = transA.getRotation(); + btQuaternion toOrnB = transB.getRotation(); + m_posA = toPosA; + m_posB = toPosB; + m_ornA = toOrnA; + m_ornB = toOrnB; + } + } + +}; + + +#endif //BT_TRANSFORM_UTIL_H + diff --git a/Code/Physics/src/LinearMath/btVector3.cpp b/Code/Physics/src/LinearMath/btVector3.cpp new file mode 100644 index 00000000..9389a25c --- /dev/null +++ b/Code/Physics/src/LinearMath/btVector3.cpp @@ -0,0 +1,1664 @@ +/* + Copyright (c) 2011 Apple Inc. + http://continuousphysics.com/Bullet/ + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it freely, + subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + This source version has been altered. + */ + +#if defined (_WIN32) || defined (__i386__) +#define BT_USE_SSE_IN_API +#endif + + +#include "btVector3.h" + + + +#if defined BT_USE_SIMD_VECTOR3 + +#if DEBUG +#include //for memset +#endif + + +#ifdef __APPLE__ +#include +typedef float float4 __attribute__ ((vector_size(16))); +#else +#define float4 __m128 +#endif +//typedef uint32_t uint4 __attribute__ ((vector_size(16))); + + +#if defined BT_USE_SSE || defined _WIN32 + +#define LOG2_ARRAY_SIZE 6 +#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE) + +#include + +long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult ); +long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + const float4 *vertices = (const float4*) vv; + static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 }; + float4 dotMax = btAssign128( -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY ); + float4 vvec = _mm_loadu_ps( vec ); + float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz + float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy + + long maxIndex = -1L; + + size_t segment = 0; + float4 stack_array[ STACK_ARRAY_COUNT ]; + +#if DEBUG + memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) ); +#endif + + size_t index; + float4 max; + // Faster loop without cleanup code for full tiles + for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 ) + { + max = dotMax; + + for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 ) + { // do four dot products at a time. Carefully avoid touching the w element. + float4 v0 = vertices[0]; + float4 v1 = vertices[1]; + float4 v2 = vertices[2]; + float4 v3 = vertices[3]; vertices += 4; + + float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + float4 z = _mm_shuffle_ps(hi0, hi1, 0x88); + float4 x = _mm_shuffle_ps(lo0, lo1, 0x88); + float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+1] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+2] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+3] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way. + } + + // If we found a new max + if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax))) + { + // copy the new max across all lanes of our max accumulator + max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e)); + max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1)); + + dotMax = max; + + // find first occurrence of that max + size_t test; + for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4 + {} + // record where it is. + maxIndex = 4*index + segment + indexTable[test]; + } + } + + // account for work we've already done + count -= segment; + + // Deal with the last < STACK_ARRAY_COUNT vectors + max = dotMax; + index = 0; + + + if( btUnlikely( count > 16) ) + { + for( ; index + 4 <= count / 4; index+=4 ) + { // do four dot products at a time. Carefully avoid touching the w element. + float4 v0 = vertices[0]; + float4 v1 = vertices[1]; + float4 v2 = vertices[2]; + float4 v3 = vertices[3]; vertices += 4; + + float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + float4 z = _mm_shuffle_ps(hi0, hi1, 0x88); + float4 x = _mm_shuffle_ps(lo0, lo1, 0x88); + float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+1] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+2] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+3] = x; + max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan + + // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way. + } + } + + size_t localCount = (count & -4L) - 4*index; + if( localCount ) + { +#ifdef __APPLE__ + float4 t0, t1, t2, t3, t4; + float4 * sap = &stack_array[index + localCount / 4]; + vertices += localCount; // counter the offset + size_t byteIndex = -(localCount) * sizeof(float); + //AT&T Code style assembly + asm volatile + ( ".align 4 \n\ + 0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\ + movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\ + movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\ + movaps %[t0], %[max] // vertices[0] \n\ + movlhps %[t1], %[max] // x0y0x1y1 \n\ + movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\ + movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\ + mulps %[vLo], %[max] // x0y0x1y1 * vLo \n\ + movhlps %[t0], %[t1] // z0w0z1w1 \n\ + movaps %[t3], %[t0] // vertices[2] \n\ + movlhps %[t4], %[t0] // x2y2x3y3 \n\ + mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\ + movhlps %[t3], %[t4] // z2w2z3w3 \n\ + shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\ + mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\ + movaps %[max], %[t3] // x0y0x1y1 * vLo \n\ + shufps $0x88, %[t0], %[max] // x0x1x2x3 * vLo.x \n\ + shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\ + addps %[t3], %[max] // x + y \n\ + addps %[t1], %[max] // x + y + z \n\ + movaps %[max], (%[sap], %[byteIndex]) // record result for later scrutiny \n\ + maxps %[t2], %[max] // record max, restore max \n\ + add $16, %[byteIndex] // advance loop counter\n\ + jnz 0b \n\ + " + : [max] "+x" (max), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex) + : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap) + : "memory", "cc" + ); + index += localCount/4; +#else + { + for( unsigned int i=0; i 16) ) + { + for( ; index + 4 <= count / 4; index+=4 ) + { // do four dot products at a time. Carefully avoid touching the w element. + float4 v0 = vertices[0]; + float4 v1 = vertices[1]; + float4 v2 = vertices[2]; + float4 v3 = vertices[3]; vertices += 4; + + float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + float4 z = _mm_shuffle_ps(hi0, hi1, 0x88); + float4 x = _mm_shuffle_ps(lo0, lo1, 0x88); + float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index] = x; + min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+1] = x; + min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+2] = x; + min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan + + v0 = vertices[0]; + v1 = vertices[1]; + v2 = vertices[2]; + v3 = vertices[3]; vertices += 4; + + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 + hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 + lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 + hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 + + lo0 = lo0*vLo; + lo1 = lo1*vLo; + z = _mm_shuffle_ps(hi0, hi1, 0x88); + x = _mm_shuffle_ps(lo0, lo1, 0x88); + y = _mm_shuffle_ps(lo0, lo1, 0xdd); + z = z*vHi; + x = x+y; + x = x+z; + stack_array[index+3] = x; + min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan + + // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way. + } + } + + size_t localCount = (count & -4L) - 4*index; + if( localCount ) + { + + +#ifdef __APPLE__ + vertices += localCount; // counter the offset + float4 t0, t1, t2, t3, t4; + size_t byteIndex = -(localCount) * sizeof(float); + float4 * sap = &stack_array[index + localCount / 4]; + + asm volatile + ( ".align 4 \n\ + 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\ + movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\ + movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\ + movaps %[t0], %[min] // vertices[0] \n\ + movlhps %[t1], %[min] // x0y0x1y1 \n\ + movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\ + movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\ + mulps %[vLo], %[min] // x0y0x1y1 * vLo \n\ + movhlps %[t0], %[t1] // z0w0z1w1 \n\ + movaps %[t3], %[t0] // vertices[2] \n\ + movlhps %[t4], %[t0] // x2y2x3y3 \n\ + movhlps %[t3], %[t4] // z2w2z3w3 \n\ + mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\ + shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\ + mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\ + movaps %[min], %[t3] // x0y0x1y1 * vLo \n\ + shufps $0x88, %[t0], %[min] // x0x1x2x3 * vLo.x \n\ + shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\ + addps %[t3], %[min] // x + y \n\ + addps %[t1], %[min] // x + y + z \n\ + movaps %[min], (%[sap], %[byteIndex]) // record result for later scrutiny \n\ + minps %[t2], %[min] // record min, restore min \n\ + add $16, %[byteIndex] // advance loop counter\n\ + jnz 0b \n\ + " + : [min] "+x" (min), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex) + : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap) + : "memory", "cc" + ); + index += localCount/4; +#else + { + for( unsigned int i=0; i +#include +#include //for sysctlbyname + +static long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult ); +static long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult ); +static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult ); +static long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult ); +static long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult ); +static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult ); + +long (*_maxdot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _maxdot_large_sel; +long (*_mindot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _mindot_large_sel; + + +static inline uint32_t btGetCpuCapabilities( void ) +{ + static uint32_t capabilities = 0; + static bool testedCapabilities = false; + + if( 0 == testedCapabilities) + { + uint32_t hasFeature = 0; + size_t featureSize = sizeof( hasFeature ); + int err = sysctlbyname( "hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0 ); + + if( 0 == err && hasFeature) + capabilities |= 0x2000; + + testedCapabilities = true; + } + + return capabilities; +} + + + + +static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + + if( btGetCpuCapabilities() & 0x2000 ) + _maxdot_large = _maxdot_large_v1; + else + _maxdot_large = _maxdot_large_v0; + + return _maxdot_large(vv, vec, count, dotResult); +} + +static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + + if( btGetCpuCapabilities() & 0x2000 ) + _mindot_large = _mindot_large_v1; + else + _mindot_large = _mindot_large_v0; + + return _mindot_large(vv, vec, count, dotResult); +} + + + +#define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; }) + + +long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + unsigned long i = 0; + float32x4_t vvec = vld1q_f32_aligned_postincrement( vec ); + float32x2_t vLo = vget_low_f32(vvec); + float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0); + float32x2_t dotMaxLo = (float32x2_t) { -BT_INFINITY, -BT_INFINITY }; + float32x2_t dotMaxHi = (float32x2_t) { -BT_INFINITY, -BT_INFINITY }; + uint32x2_t indexLo = (uint32x2_t) {0, 1}; + uint32x2_t indexHi = (uint32x2_t) {2, 3}; + uint32x2_t iLo = (uint32x2_t) {static_cast(-1), static_cast(-1)}; + uint32x2_t iHi = (uint32x2_t) {static_cast(-1), static_cast(-1)}; + const uint32x2_t four = (uint32x2_t) {4,4}; + + for( ; i+8 <= count; i+= 8 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo); + float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + float32x2_t zHi = vmul_f32( z1.val[0], vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + float32x2_t rHi = vpadd_f32( xy2, xy3); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo ); + uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi ); + dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo); + dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + indexLo = vadd_u32(indexLo, four); + indexHi = vadd_u32(indexHi, four); + + v0 = vld1q_f32_aligned_postincrement( vv ); + v1 = vld1q_f32_aligned_postincrement( vv ); + v2 = vld1q_f32_aligned_postincrement( vv ); + v3 = vld1q_f32_aligned_postincrement( vv ); + + xy0 = vmul_f32( vget_low_f32(v0), vLo); + xy1 = vmul_f32( vget_low_f32(v1), vLo); + xy2 = vmul_f32( vget_low_f32(v2), vLo); + xy3 = vmul_f32( vget_low_f32(v3), vLo); + + z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3)); + zLo = vmul_f32( z0.val[0], vHi); + zHi = vmul_f32( z1.val[0], vHi); + + rLo = vpadd_f32( xy0, xy1); + rHi = vpadd_f32( xy2, xy3); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + maskLo = vcgt_f32( rLo, dotMaxLo ); + maskHi = vcgt_f32( rHi, dotMaxHi ); + dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo); + dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + indexLo = vadd_u32(indexLo, four); + indexHi = vadd_u32(indexHi, four); + } + + for( ; i+4 <= count; i+= 4 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo); + float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + float32x2_t zHi = vmul_f32( z1.val[0], vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + float32x2_t rHi = vpadd_f32( xy2, xy3); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo ); + uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi ); + dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo); + dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + indexLo = vadd_u32(indexLo, four); + indexHi = vadd_u32(indexHi, four); + } + + switch( count & 3 ) + { + case 3: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + float32x2_t rHi = vpadd_f32( xy2, xy2); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo ); + uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi ); + dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo); + dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + } + break; + case 2: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + rLo = vadd_f32(rLo, zLo); + + uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo ); + dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo); + iLo = vbsl_u32(maskLo, indexLo, iLo); + } + break; + case 1: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0); + float32x2_t zLo = vmul_f32( z0, vHi); + float32x2_t rLo = vpadd_f32( xy0, xy0); + rLo = vadd_f32(rLo, zLo); + uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo ); + dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo); + iLo = vbsl_u32(maskLo, indexLo, iLo); + } + break; + + default: + break; + } + + // select best answer between hi and lo results + uint32x2_t mask = vcgt_f32( dotMaxHi, dotMaxLo ); + dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo); + iLo = vbsl_u32(mask, iHi, iLo); + + // select best answer between even and odd results + dotMaxHi = vdup_lane_f32(dotMaxLo, 1); + iHi = vdup_lane_u32(iLo, 1); + mask = vcgt_f32( dotMaxHi, dotMaxLo ); + dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo); + iLo = vbsl_u32(mask, iHi, iLo); + + *dotResult = vget_lane_f32( dotMaxLo, 0); + return vget_lane_u32(iLo, 0); +} + + +long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + float32x4_t vvec = vld1q_f32_aligned_postincrement( vec ); + float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec)); + float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0); + const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 }; + uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3}; + uint32x4_t index = (uint32x4_t) { static_cast(-1), static_cast(-1), static_cast(-1), static_cast(-1) }; + float32x4_t maxDot = (float32x4_t) { -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY }; + + unsigned long i = 0; + for( ; i + 8 <= count; i += 8 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z1); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy1); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcgtq_f32(x, maxDot); + maxDot = vbslq_f32( mask, x, maxDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + + v0 = vld1q_f32_aligned_postincrement( vv ); + v1 = vld1q_f32_aligned_postincrement( vv ); + v2 = vld1q_f32_aligned_postincrement( vv ); + v3 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3)); + // the next two lines should resolve to a single vswp d, d + z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + zb = vuzpq_f32( z0, z1); + z = vmulq_f32( zb.val[0], vHi); + xy = vuzpq_f32( xy0, xy1); + x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + mask = vcgtq_f32(x, maxDot); + maxDot = vbslq_f32( mask, x, maxDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + + for( ; i + 4 <= count; i += 4 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z1); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy1); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcgtq_f32(x, maxDot); + maxDot = vbslq_f32( mask, x, maxDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + + switch (count & 3) { + case 3: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z1); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy1); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcgtq_f32(x, maxDot); + maxDot = vbslq_f32( mask, x, maxDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + break; + + case 2: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + + xy0 = vmulq_f32(xy0, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z0); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy0); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcgtq_f32(x, maxDot); + maxDot = vbslq_f32( mask, x, maxDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + break; + + case 1: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0); + + xy0 = vmulq_f32(xy0, vLo); + + z = vmulq_f32( z, vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy0); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcgtq_f32(x, maxDot); + maxDot = vbslq_f32( mask, x, maxDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + break; + + default: + break; + } + + + // select best answer between hi and lo results + uint32x2_t mask = vcgt_f32( vget_high_f32(maxDot), vget_low_f32(maxDot)); + float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot)); + uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index)); + + // select best answer between even and odd results + float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1); + uint32x2_t indexHi = vdup_lane_u32(index2, 1); + mask = vcgt_f32( maxDotO, maxDot2 ); + maxDot2 = vbsl_f32(mask, maxDotO, maxDot2); + index2 = vbsl_u32(mask, indexHi, index2); + + *dotResult = vget_lane_f32( maxDot2, 0); + return vget_lane_u32(index2, 0); + +} + +long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + unsigned long i = 0; + float32x4_t vvec = vld1q_f32_aligned_postincrement( vec ); + float32x2_t vLo = vget_low_f32(vvec); + float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0); + float32x2_t dotMinLo = (float32x2_t) { BT_INFINITY, BT_INFINITY }; + float32x2_t dotMinHi = (float32x2_t) { BT_INFINITY, BT_INFINITY }; + uint32x2_t indexLo = (uint32x2_t) {0, 1}; + uint32x2_t indexHi = (uint32x2_t) {2, 3}; + uint32x2_t iLo = (uint32x2_t) {static_cast(-1), static_cast(-1)}; + uint32x2_t iHi = (uint32x2_t) {static_cast(-1), static_cast(-1)}; + const uint32x2_t four = (uint32x2_t) {4,4}; + + for( ; i+8 <= count; i+= 8 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo); + float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + float32x2_t zHi = vmul_f32( z1.val[0], vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + float32x2_t rHi = vpadd_f32( xy2, xy3); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + uint32x2_t maskLo = vclt_f32( rLo, dotMinLo ); + uint32x2_t maskHi = vclt_f32( rHi, dotMinHi ); + dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo); + dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + indexLo = vadd_u32(indexLo, four); + indexHi = vadd_u32(indexHi, four); + + v0 = vld1q_f32_aligned_postincrement( vv ); + v1 = vld1q_f32_aligned_postincrement( vv ); + v2 = vld1q_f32_aligned_postincrement( vv ); + v3 = vld1q_f32_aligned_postincrement( vv ); + + xy0 = vmul_f32( vget_low_f32(v0), vLo); + xy1 = vmul_f32( vget_low_f32(v1), vLo); + xy2 = vmul_f32( vget_low_f32(v2), vLo); + xy3 = vmul_f32( vget_low_f32(v3), vLo); + + z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3)); + zLo = vmul_f32( z0.val[0], vHi); + zHi = vmul_f32( z1.val[0], vHi); + + rLo = vpadd_f32( xy0, xy1); + rHi = vpadd_f32( xy2, xy3); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + maskLo = vclt_f32( rLo, dotMinLo ); + maskHi = vclt_f32( rHi, dotMinHi ); + dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo); + dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + indexLo = vadd_u32(indexLo, four); + indexHi = vadd_u32(indexHi, four); + } + + for( ; i+4 <= count; i+= 4 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo); + float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + float32x2_t zHi = vmul_f32( z1.val[0], vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + float32x2_t rHi = vpadd_f32( xy2, xy3); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + uint32x2_t maskLo = vclt_f32( rLo, dotMinLo ); + uint32x2_t maskHi = vclt_f32( rHi, dotMinHi ); + dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo); + dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + indexLo = vadd_u32(indexLo, four); + indexHi = vadd_u32(indexHi, four); + } + switch( count & 3 ) + { + case 3: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + float32x2_t rHi = vpadd_f32( xy2, xy2); + rLo = vadd_f32(rLo, zLo); + rHi = vadd_f32(rHi, zHi); + + uint32x2_t maskLo = vclt_f32( rLo, dotMinLo ); + uint32x2_t maskHi = vclt_f32( rHi, dotMinHi ); + dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo); + dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi); + iLo = vbsl_u32(maskLo, indexLo, iLo); + iHi = vbsl_u32(maskHi, indexHi, iHi); + } + break; + case 2: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo); + + float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x2_t zLo = vmul_f32( z0.val[0], vHi); + + float32x2_t rLo = vpadd_f32( xy0, xy1); + rLo = vadd_f32(rLo, zLo); + + uint32x2_t maskLo = vclt_f32( rLo, dotMinLo ); + dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo); + iLo = vbsl_u32(maskLo, indexLo, iLo); + } + break; + case 1: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo); + float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0); + float32x2_t zLo = vmul_f32( z0, vHi); + float32x2_t rLo = vpadd_f32( xy0, xy0); + rLo = vadd_f32(rLo, zLo); + uint32x2_t maskLo = vclt_f32( rLo, dotMinLo ); + dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo); + iLo = vbsl_u32(maskLo, indexLo, iLo); + } + break; + + default: + break; + } + + // select best answer between hi and lo results + uint32x2_t mask = vclt_f32( dotMinHi, dotMinLo ); + dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo); + iLo = vbsl_u32(mask, iHi, iLo); + + // select best answer between even and odd results + dotMinHi = vdup_lane_f32(dotMinLo, 1); + iHi = vdup_lane_u32(iLo, 1); + mask = vclt_f32( dotMinHi, dotMinLo ); + dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo); + iLo = vbsl_u32(mask, iHi, iLo); + + *dotResult = vget_lane_f32( dotMinLo, 0); + return vget_lane_u32(iLo, 0); +} + +long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult ) +{ + float32x4_t vvec = vld1q_f32_aligned_postincrement( vec ); + float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec)); + float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0); + const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 }; + uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3}; + uint32x4_t index = (uint32x4_t) { static_cast(-1), static_cast(-1), static_cast(-1), static_cast(-1) }; + float32x4_t minDot = (float32x4_t) { BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY }; + + unsigned long i = 0; + for( ; i + 8 <= count; i += 8 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z1); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy1); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcltq_f32(x, minDot); + minDot = vbslq_f32( mask, x, minDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + + v0 = vld1q_f32_aligned_postincrement( vv ); + v1 = vld1q_f32_aligned_postincrement( vv ); + v2 = vld1q_f32_aligned_postincrement( vv ); + v3 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3)); + // the next two lines should resolve to a single vswp d, d + z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + zb = vuzpq_f32( z0, z1); + z = vmulq_f32( zb.val[0], vHi); + xy = vuzpq_f32( xy0, xy1); + x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + mask = vcltq_f32(x, minDot); + minDot = vbslq_f32( mask, x, minDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + + for( ; i + 4 <= count; i += 4 ) + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v3 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z1); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy1); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcltq_f32(x, minDot); + minDot = vbslq_f32( mask, x, minDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + + switch (count & 3) { + case 3: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v2 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2)); + + xy0 = vmulq_f32(xy0, vLo); + xy1 = vmulq_f32(xy1, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z1); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy1); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcltq_f32(x, minDot); + minDot = vbslq_f32( mask, x, minDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + break; + + case 2: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + float32x4_t v1 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1)); + + xy0 = vmulq_f32(xy0, vLo); + + float32x4x2_t zb = vuzpq_f32( z0, z0); + float32x4_t z = vmulq_f32( zb.val[0], vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy0); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcltq_f32(x, minDot); + minDot = vbslq_f32( mask, x, minDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + break; + + case 1: + { + float32x4_t v0 = vld1q_f32_aligned_postincrement( vv ); + + // the next two lines should resolve to a single vswp d, d + float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0)); + // the next two lines should resolve to a single vswp d, d + float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0); + + xy0 = vmulq_f32(xy0, vLo); + + z = vmulq_f32( z, vHi); + float32x4x2_t xy = vuzpq_f32( xy0, xy0); + float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]); + x = vaddq_f32(x, z); + + uint32x4_t mask = vcltq_f32(x, minDot); + minDot = vbslq_f32( mask, x, minDot); + index = vbslq_u32(mask, local_index, index); + local_index = vaddq_u32(local_index, four); + } + break; + + default: + break; + } + + + // select best answer between hi and lo results + uint32x2_t mask = vclt_f32( vget_high_f32(minDot), vget_low_f32(minDot)); + float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot)); + uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index)); + + // select best answer between even and odd results + float32x2_t minDotO = vdup_lane_f32(minDot2, 1); + uint32x2_t indexHi = vdup_lane_u32(index2, 1); + mask = vclt_f32( minDotO, minDot2 ); + minDot2 = vbsl_f32(mask, minDotO, minDot2); + index2 = vbsl_u32(mask, indexHi, index2); + + *dotResult = vget_lane_f32( minDot2, 0); + return vget_lane_u32(index2, 0); + +} + +#else + #error Unhandled __APPLE__ arch +#endif + +#endif /* __APPLE__ */ + + diff --git a/Code/Physics/src/LinearMath/btVector3.h b/Code/Physics/src/LinearMath/btVector3.h new file mode 100644 index 00000000..89685929 --- /dev/null +++ b/Code/Physics/src/LinearMath/btVector3.h @@ -0,0 +1,1352 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#ifndef BT_VECTOR3_H +#define BT_VECTOR3_H + +//#include +#include "btScalar.h" +#include "btMinMax.h" +#include "btAlignedAllocator.h" + +#ifdef BT_USE_DOUBLE_PRECISION +#define btVector3Data btVector3DoubleData +#define btVector3DataName "btVector3DoubleData" +#else +#define btVector3Data btVector3FloatData +#define btVector3DataName "btVector3FloatData" +#endif //BT_USE_DOUBLE_PRECISION + +#if defined BT_USE_SSE + +//typedef uint32_t __m128i __attribute__ ((vector_size(16))); + +#ifdef _MSC_VER +#pragma warning(disable: 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255' +#endif + + +#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x)) +//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) ) +#define bt_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) ) +#define bt_splat3_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i, 3) ) +#define bt_splat_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i,_i) ) + +#define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF)) +#define btvAbsMask (_mm_set_epi32( 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF)) +#define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF)) +#define btv3AbsfMask btCastiTo128f(btv3AbsiMask) +#define btvFFF0fMask btCastiTo128f(btvFFF0Mask) +#define btvxyzMaskf btvFFF0fMask +#define btvAbsfMask btCastiTo128f(btvAbsMask) + +//there is an issue with XCode 3.2 (LCx errors) +#define btvMzeroMask (_mm_set_ps(-0.0f, -0.0f, -0.0f, -0.0f)) +#define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f)) +#define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f)) +#define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f)) + +//const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f}; +//const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f}; +//const __m128 ATTRIBUTE_ALIGNED16(vHalf) = {0.5f, 0.5f, 0.5f, 0.5f}; +//const __m128 ATTRIBUTE_ALIGNED16(v1_5) = {1.5f, 1.5f, 1.5f, 1.5f}; + +#endif + +#ifdef BT_USE_NEON + +const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f}; +const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){static_cast(0xFFFFFFFF), + static_cast(0xFFFFFFFF), static_cast(0xFFFFFFFF), 0x0}; +const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; +const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0}; + +#endif + +/**@brief btVector3 can be used to represent 3D points and vectors. + * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user + * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers + */ +ATTRIBUTE_ALIGNED16(class) btVector3 +{ +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + +#if defined (__SPU__) && defined (__CELLOS_LV2__) + btScalar m_floats[4]; +public: + SIMD_FORCE_INLINE const vec_float4& get128() const + { + return *((const vec_float4*)&m_floats[0]); + } +public: +#else //__CELLOS_LV2__ __SPU__ + #if defined (BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM + union { + btSimdFloat4 mVec128; + btScalar m_floats[4]; + }; + SIMD_FORCE_INLINE btSimdFloat4 get128() const + { + return mVec128; + } + SIMD_FORCE_INLINE void set128(btSimdFloat4 v128) + { + mVec128 = v128; + } + #else + btScalar m_floats[4]; + #endif +#endif //__CELLOS_LV2__ __SPU__ + + public: + + /**@brief No initialization constructor */ + SIMD_FORCE_INLINE btVector3() + { + + } + + + + /**@brief Constructor from scalars + * @param x X value + * @param y Y value + * @param z Z value + */ + SIMD_FORCE_INLINE btVector3(const btScalar& _x, const btScalar& _y, const btScalar& _z) + { + m_floats[0] = _x; + m_floats[1] = _y; + m_floats[2] = _z; + m_floats[3] = btScalar(0.f); + } + +#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) )|| defined (BT_USE_NEON) + // Set Vector + SIMD_FORCE_INLINE btVector3( btSimdFloat4 v) + { + mVec128 = v; + } + + // Copy constructor + SIMD_FORCE_INLINE btVector3(const btVector3& rhs) + { + mVec128 = rhs.mVec128; + } + + // Assignment Operator + SIMD_FORCE_INLINE btVector3& + operator=(const btVector3& v) + { + mVec128 = v.mVec128; + + return *this; + } +#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON) + +/**@brief Add a vector to this one + * @param The vector to add to this one */ + SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_add_ps(mVec128, v.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vaddq_f32(mVec128, v.mVec128); +#else + m_floats[0] += v.m_floats[0]; + m_floats[1] += v.m_floats[1]; + m_floats[2] += v.m_floats[2]; +#endif + return *this; + } + + + /**@brief Subtract a vector from this one + * @param The vector to subtract */ + SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_sub_ps(mVec128, v.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vsubq_f32(mVec128, v.mVec128); +#else + m_floats[0] -= v.m_floats[0]; + m_floats[1] -= v.m_floats[1]; + m_floats[2] -= v.m_floats[2]; +#endif + return *this; + } + + /**@brief Scale the vector + * @param s Scale factor */ + SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vs = _mm_load_ss(&s); // (S 0 0 0) + vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0) + mVec128 = _mm_mul_ps(mVec128, vs); +#elif defined(BT_USE_NEON) + mVec128 = vmulq_n_f32(mVec128, s); +#else + m_floats[0] *= s; + m_floats[1] *= s; + m_floats[2] *= s; +#endif + return *this; + } + + /**@brief Inversely scale the vector + * @param s Scale factor to divide by */ + SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) + { + btFullAssert(s != btScalar(0.0)); + +#if 0 //defined(BT_USE_SSE_IN_API) +// this code is not faster ! + __m128 vs = _mm_load_ss(&s); + vs = _mm_div_ss(v1110, vs); + vs = bt_pshufd_ps(vs, 0x00); // (S S S S) + + mVec128 = _mm_mul_ps(mVec128, vs); + + return *this; +#else + return *this *= btScalar(1.0) / s; +#endif + } + + /**@brief Return the dot product + * @param v The other vector in the dot product */ + SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const + { +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vd = _mm_mul_ps(mVec128, v.mVec128); + __m128 z = _mm_movehl_ps(vd, vd); + __m128 y = _mm_shuffle_ps(vd, vd, 0x55); + vd = _mm_add_ss(vd, y); + vd = _mm_add_ss(vd, z); + return _mm_cvtss_f32(vd); +#elif defined(BT_USE_NEON) + float32x4_t vd = vmulq_f32(mVec128, v.mVec128); + float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd)); + x = vadd_f32(x, vget_high_f32(vd)); + return vget_lane_f32(x, 0); +#else + return m_floats[0] * v.m_floats[0] + + m_floats[1] * v.m_floats[1] + + m_floats[2] * v.m_floats[2]; +#endif + } + + /**@brief Return the length of the vector squared */ + SIMD_FORCE_INLINE btScalar length2() const + { + return dot(*this); + } + + /**@brief Return the length of the vector */ + SIMD_FORCE_INLINE btScalar length() const + { + return btSqrt(length2()); + } + + /**@brief Return the norm (length) of the vector */ + SIMD_FORCE_INLINE btScalar norm() const + { + return length(); + } + + /**@brief Return the distance squared between the ends of this and another vector + * This is symantically treating the vector like a point */ + SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; + + /**@brief Return the distance between the ends of this and another vector + * This is symantically treating the vector like a point */ + SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const; + + SIMD_FORCE_INLINE btVector3& safeNormalize() + { + btVector3 absVec = this->absolute(); + int maxIndex = absVec.maxAxis(); + if (absVec[maxIndex]>0) + { + *this /= absVec[maxIndex]; + return *this /= length(); + } + setValue(1,0,0); + return *this; + } + + /**@brief Normalize this vector + * x^2 + y^2 + z^2 = 1 */ + SIMD_FORCE_INLINE btVector3& normalize() + { + + btAssert(length() != btScalar(0)); + +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + // dot product first + __m128 vd = _mm_mul_ps(mVec128, mVec128); + __m128 z = _mm_movehl_ps(vd, vd); + __m128 y = _mm_shuffle_ps(vd, vd, 0x55); + vd = _mm_add_ss(vd, y); + vd = _mm_add_ss(vd, z); + + #if 0 + vd = _mm_sqrt_ss(vd); + vd = _mm_div_ss(v1110, vd); + vd = bt_splat_ps(vd, 0x80); + mVec128 = _mm_mul_ps(mVec128, vd); + #else + + // NR step 1/sqrt(x) - vd is x, y is output + y = _mm_rsqrt_ss(vd); // estimate + + // one step NR + z = v1_5; + vd = _mm_mul_ss(vd, vHalf); // vd * 0.5 + //x2 = vd; + vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 + vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0 + z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0 + + y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0) + + y = bt_splat_ps(y, 0x80); + mVec128 = _mm_mul_ps(mVec128, y); + + #endif + + + return *this; +#else + return *this /= length(); +#endif + } + + /**@brief Return a normalized version of this vector */ + SIMD_FORCE_INLINE btVector3 normalized() const; + + /**@brief Return a rotated version of this vector + * @param wAxis The axis to rotate about + * @param angle The angle to rotate by */ + SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const; + + /**@brief Return the angle between this and another vector + * @param v The other vector */ + SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const + { + btScalar s = btSqrt(length2() * v.length2()); + btFullAssert(s != btScalar(0.0)); + return btAcos(dot(v) / s); + } + + /**@brief Return a vector will the absolute values of each element */ + SIMD_FORCE_INLINE btVector3 absolute() const + { + +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btVector3(_mm_and_ps(mVec128, btv3AbsfMask)); +#elif defined(BT_USE_NEON) + return btVector3(vabsq_f32(mVec128)); +#else + return btVector3( + btFabs(m_floats[0]), + btFabs(m_floats[1]), + btFabs(m_floats[2])); +#endif + } + + /**@brief Return the cross product between this and another vector + * @param v The other vector */ + SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 T, V; + + T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0) + V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0) + + V = _mm_mul_ps(V, mVec128); + T = _mm_mul_ps(T, v.mVec128); + V = _mm_sub_ps(V, T); + + V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3)); + return btVector3(V); +#elif defined(BT_USE_NEON) + float32x4_t T, V; + // form (Y, Z, X, _) of mVec128 and v.mVec128 + float32x2_t Tlow = vget_low_f32(mVec128); + float32x2_t Vlow = vget_low_f32(v.mVec128); + T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow); + V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow); + + V = vmulq_f32(V, mVec128); + T = vmulq_f32(T, v.mVec128); + V = vsubq_f32(V, T); + Vlow = vget_low_f32(V); + // form (Y, Z, X, _); + V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow); + V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask); + + return btVector3(V); +#else + return btVector3( + m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1], + m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2], + m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]); +#endif + } + + SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const + { +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + // cross: + __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0) + __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0) + + V = _mm_mul_ps(V, v1.mVec128); + T = _mm_mul_ps(T, v2.mVec128); + V = _mm_sub_ps(V, T); + + V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3)); + + // dot: + V = _mm_mul_ps(V, mVec128); + __m128 z = _mm_movehl_ps(V, V); + __m128 y = _mm_shuffle_ps(V, V, 0x55); + V = _mm_add_ss(V, y); + V = _mm_add_ss(V, z); + return _mm_cvtss_f32(V); + +#elif defined(BT_USE_NEON) + // cross: + float32x4_t T, V; + // form (Y, Z, X, _) of mVec128 and v.mVec128 + float32x2_t Tlow = vget_low_f32(v1.mVec128); + float32x2_t Vlow = vget_low_f32(v2.mVec128); + T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow); + V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow); + + V = vmulq_f32(V, v1.mVec128); + T = vmulq_f32(T, v2.mVec128); + V = vsubq_f32(V, T); + Vlow = vget_low_f32(V); + // form (Y, Z, X, _); + V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow); + + // dot: + V = vmulq_f32(mVec128, V); + float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V)); + x = vadd_f32(x, vget_high_f32(V)); + return vget_lane_f32(x, 0); +#else + return + m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + + m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + + m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]); +#endif + } + + /**@brief Return the axis with the smallest value + * Note return values are 0,1,2 for x, y, or z */ + SIMD_FORCE_INLINE int minAxis() const + { + return m_floats[0] < m_floats[1] ? (m_floats[0] return this, t=1 => return other) */ + SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vt = _mm_load_ss(&t); // (t 0 0 0) + vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0) + __m128 vl = _mm_sub_ps(v.mVec128, mVec128); + vl = _mm_mul_ps(vl, vt); + vl = _mm_add_ps(vl, mVec128); + + return btVector3(vl); +#elif defined(BT_USE_NEON) + float32x4_t vl = vsubq_f32(v.mVec128, mVec128); + vl = vmulq_n_f32(vl, t); + vl = vaddq_f32(vl, mVec128); + + return btVector3(vl); +#else + return + btVector3( m_floats[0] + (v.m_floats[0] - m_floats[0]) * t, + m_floats[1] + (v.m_floats[1] - m_floats[1]) * t, + m_floats[2] + (v.m_floats[2] - m_floats[2]) * t); +#endif + } + + /**@brief Elementwise multiply this vector by the other + * @param v The other vector */ + SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_mul_ps(mVec128, v.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vmulq_f32(mVec128, v.mVec128); +#else + m_floats[0] *= v.m_floats[0]; + m_floats[1] *= v.m_floats[1]; + m_floats[2] *= v.m_floats[2]; +#endif + return *this; + } + + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } + /**@brief Set the x value */ + SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;}; + /**@brief Set the y value */ + SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;}; + /**@brief Set the z value */ + SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;}; + /**@brief Set the w value */ + SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;}; + /**@brief Return the x value */ + SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } + /**@brief Return the y value */ + SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } + /**@brief Return the z value */ + SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } + /**@brief Return the w value */ + SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } + + //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } + //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } + ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. + SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } + + SIMD_FORCE_INLINE bool operator==(const btVector3& other) const + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128))); +#else + return ((m_floats[3]==other.m_floats[3]) && + (m_floats[2]==other.m_floats[2]) && + (m_floats[1]==other.m_floats[1]) && + (m_floats[0]==other.m_floats[0])); +#endif + } + + SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const + { + return !(*this == other); + } + + /**@brief Set each element to the max of the current values and the values of another btVector3 + * @param other The other btVector3 to compare with + */ + SIMD_FORCE_INLINE void setMax(const btVector3& other) + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_max_ps(mVec128, other.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vmaxq_f32(mVec128, other.mVec128); +#else + btSetMax(m_floats[0], other.m_floats[0]); + btSetMax(m_floats[1], other.m_floats[1]); + btSetMax(m_floats[2], other.m_floats[2]); + btSetMax(m_floats[3], other.w()); +#endif + } + + /**@brief Set each element to the min of the current values and the values of another btVector3 + * @param other The other btVector3 to compare with + */ + SIMD_FORCE_INLINE void setMin(const btVector3& other) + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = _mm_min_ps(mVec128, other.mVec128); +#elif defined(BT_USE_NEON) + mVec128 = vminq_f32(mVec128, other.mVec128); +#else + btSetMin(m_floats[0], other.m_floats[0]); + btSetMin(m_floats[1], other.m_floats[1]); + btSetMin(m_floats[2], other.m_floats[2]); + btSetMin(m_floats[3], other.w()); +#endif + } + + SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z) + { + m_floats[0]=_x; + m_floats[1]=_y; + m_floats[2]=_z; + m_floats[3] = btScalar(0.f); + } + + void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const + { +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + + __m128 V = _mm_and_ps(mVec128, btvFFF0fMask); + __m128 V0 = _mm_xor_ps(btvMzeroMask, V); + __m128 V2 = _mm_movelh_ps(V0, V); + + __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE); + + V0 = _mm_shuffle_ps(V0, V, 0xDB); + V2 = _mm_shuffle_ps(V2, V, 0xF9); + + v0->mVec128 = V0; + v1->mVec128 = V1; + v2->mVec128 = V2; +#else + v0->setValue(0. ,-z() ,y()); + v1->setValue(z() ,0. ,-x()); + v2->setValue(-y() ,x() ,0.); +#endif + } + + void setZero() + { +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128); +#elif defined(BT_USE_NEON) + int32x4_t vi = vdupq_n_s32(0); + mVec128 = vreinterpretq_f32_s32(vi); +#else + setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +#endif + } + + SIMD_FORCE_INLINE bool isZero() const + { + return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0); + } + + SIMD_FORCE_INLINE bool fuzzyZero() const + { + return length2() < SIMD_EPSILON; + } + + SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const; + + SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn); + + SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const; + + SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn); + + SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const; + + SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn); + + /**@brief returns index of maximum dot product between this and vectors in array[] + * @param array The other vectors + * @param array_count The number of other vectors + * @param dotOut The maximum dot product */ + SIMD_FORCE_INLINE long maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const; + + /**@brief returns index of minimum dot product between this and vectors in array[] + * @param array The other vectors + * @param array_count The number of other vectors + * @param dotOut The minimum dot product */ + SIMD_FORCE_INLINE long minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const; + + /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */ + SIMD_FORCE_INLINE btVector3 dot3( const btVector3 &v0, const btVector3 &v1, const btVector3 &v2 ) const + { +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + + __m128 a0 = _mm_mul_ps( v0.mVec128, this->mVec128 ); + __m128 a1 = _mm_mul_ps( v1.mVec128, this->mVec128 ); + __m128 a2 = _mm_mul_ps( v2.mVec128, this->mVec128 ); + __m128 b0 = _mm_unpacklo_ps( a0, a1 ); + __m128 b1 = _mm_unpackhi_ps( a0, a1 ); + __m128 b2 = _mm_unpacklo_ps( a2, _mm_setzero_ps() ); + __m128 r = _mm_movelh_ps( b0, b2 ); + r = _mm_add_ps( r, _mm_movehl_ps( b2, b0 )); + a2 = _mm_and_ps( a2, btvxyzMaskf); + r = _mm_add_ps( r, btCastdTo128f (_mm_move_sd( btCastfTo128d(a2), btCastfTo128d(b1) ))); + return btVector3(r); + +#elif defined(BT_USE_NEON) + static const uint32x4_t xyzMask = (const uint32x4_t){ static_cast(-1), static_cast(-1), static_cast(-1), 0 }; + float32x4_t a0 = vmulq_f32( v0.mVec128, this->mVec128); + float32x4_t a1 = vmulq_f32( v1.mVec128, this->mVec128); + float32x4_t a2 = vmulq_f32( v2.mVec128, this->mVec128); + float32x2x2_t zLo = vtrn_f32( vget_high_f32(a0), vget_high_f32(a1)); + a2 = (float32x4_t) vandq_u32((uint32x4_t) a2, xyzMask ); + float32x2_t b0 = vadd_f32( vpadd_f32( vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0] ); + float32x2_t b1 = vpadd_f32( vpadd_f32( vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f)); + return btVector3( vcombine_f32(b0, b1) ); +#else + return btVector3( dot(v0), dot(v1), dot(v2)); +#endif + } +}; + +/**@brief Return the sum of two vectors (Point symantics)*/ +SIMD_FORCE_INLINE btVector3 +operator+(const btVector3& v1, const btVector3& v2) +{ +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128)); +#elif defined(BT_USE_NEON) + return btVector3(vaddq_f32(v1.mVec128, v2.mVec128)); +#else + return btVector3( + v1.m_floats[0] + v2.m_floats[0], + v1.m_floats[1] + v2.m_floats[1], + v1.m_floats[2] + v2.m_floats[2]); +#endif +} + +/**@brief Return the elementwise product of two vectors */ +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v1, const btVector3& v2) +{ +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128)); +#elif defined(BT_USE_NEON) + return btVector3(vmulq_f32(v1.mVec128, v2.mVec128)); +#else + return btVector3( + v1.m_floats[0] * v2.m_floats[0], + v1.m_floats[1] * v2.m_floats[1], + v1.m_floats[2] * v2.m_floats[2]); +#endif +} + +/**@brief Return the difference between two vectors */ +SIMD_FORCE_INLINE btVector3 +operator-(const btVector3& v1, const btVector3& v2) +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) + + // without _mm_and_ps this code causes slowdown in Concave moving + __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128); + return btVector3(_mm_and_ps(r, btvFFF0fMask)); +#elif defined(BT_USE_NEON) + float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128); + return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask)); +#else + return btVector3( + v1.m_floats[0] - v2.m_floats[0], + v1.m_floats[1] - v2.m_floats[1], + v1.m_floats[2] - v2.m_floats[2]); +#endif +} + +/**@brief Return the negative of the vector */ +SIMD_FORCE_INLINE btVector3 +operator-(const btVector3& v) +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)) + __m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask); + return btVector3(_mm_and_ps(r, btvFFF0fMask)); +#elif defined(BT_USE_NEON) + return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask)); +#else + return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]); +#endif +} + +/**@brief Return the vector scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v, const btScalar& s) +{ +#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + __m128 vs = _mm_load_ss(&s); // (S 0 0 0) + vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0) + return btVector3(_mm_mul_ps(v.mVec128, vs)); +#elif defined(BT_USE_NEON) + float32x4_t r = vmulq_n_f32(v.mVec128, s); + return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask)); +#else + return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s); +#endif +} + +/**@brief Return the vector scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator*(const btScalar& s, const btVector3& v) +{ + return v * s; +} + +/**@brief Return the vector inversely scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator/(const btVector3& v, const btScalar& s) +{ + btFullAssert(s != btScalar(0.0)); +#if 0 //defined(BT_USE_SSE_IN_API) +// this code is not faster ! + __m128 vs = _mm_load_ss(&s); + vs = _mm_div_ss(v1110, vs); + vs = bt_pshufd_ps(vs, 0x00); // (S S S S) + + return btVector3(_mm_mul_ps(v.mVec128, vs)); +#else + return v * (btScalar(1.0) / s); +#endif +} + +/**@brief Return the vector inversely scaled by s */ +SIMD_FORCE_INLINE btVector3 +operator/(const btVector3& v1, const btVector3& v2) +{ +#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) + __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128); + vec = _mm_and_ps(vec, btvFFF0fMask); + return btVector3(vec); +#elif defined(BT_USE_NEON) + float32x4_t x, y, v, m; + + x = v1.mVec128; + y = v2.mVec128; + + v = vrecpeq_f32(y); // v ~ 1/y + m = vrecpsq_f32(y, v); // m = (2-v*y) + v = vmulq_f32(v, m); // vv = v*m ~~ 1/y + m = vrecpsq_f32(y, v); // mm = (2-vv*y) + v = vmulq_f32(v, x); // x*vv + v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y + + return btVector3(v); +#else + return btVector3( + v1.m_floats[0] / v2.m_floats[0], + v1.m_floats[1] / v2.m_floats[1], + v1.m_floats[2] / v2.m_floats[2]); +#endif +} + +/**@brief Return the dot product between two vectors */ +SIMD_FORCE_INLINE btScalar +btDot(const btVector3& v1, const btVector3& v2) +{ + return v1.dot(v2); +} + + +/**@brief Return the distance squared between two vectors */ +SIMD_FORCE_INLINE btScalar +btDistance2(const btVector3& v1, const btVector3& v2) +{ + return v1.distance2(v2); +} + + +/**@brief Return the distance between two vectors */ +SIMD_FORCE_INLINE btScalar +btDistance(const btVector3& v1, const btVector3& v2) +{ + return v1.distance(v2); +} + +/**@brief Return the angle between two vectors */ +SIMD_FORCE_INLINE btScalar +btAngle(const btVector3& v1, const btVector3& v2) +{ + return v1.angle(v2); +} + +/**@brief Return the cross product of two vectors */ +SIMD_FORCE_INLINE btVector3 +btCross(const btVector3& v1, const btVector3& v2) +{ + return v1.cross(v2); +} + +SIMD_FORCE_INLINE btScalar +btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3) +{ + return v1.triple(v2, v3); +} + +/**@brief Return the linear interpolation between two vectors + * @param v1 One vector + * @param v2 The other vector + * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */ +SIMD_FORCE_INLINE btVector3 +lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) +{ + return v1.lerp(v2, t); +} + + + +SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const +{ + return (v - *this).length2(); +} + +SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const +{ + return (v - *this).length(); +} + +SIMD_FORCE_INLINE btVector3 btVector3::normalized() const +{ + btVector3 norm = *this; + + return norm.normalize(); +} + +SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar _angle ) const +{ + // wAxis must be a unit lenght vector + +#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + + __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128); + btScalar ssin = btSin( _angle ); + __m128 C = wAxis.cross( mVec128 ).mVec128; + O = _mm_and_ps(O, btvFFF0fMask); + btScalar scos = btCos( _angle ); + + __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0) + __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0) + + __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0) + __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0) + O = _mm_add_ps(O, Y); + vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0) + O = _mm_add_ps(O, Z); + vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0) + + vsin = vsin * C; + O = O * wAxis.mVec128; + __m128 X = mVec128 - O; + + O = O + vsin; + vcos = vcos * X; + O = O + vcos; + + return btVector3(O); +#else + btVector3 o = wAxis * wAxis.dot( *this ); + btVector3 _x = *this - o; + btVector3 _y; + + _y = wAxis.cross( *this ); + + return ( o + _x * btCos( _angle ) + _y * btSin( _angle ) ); +#endif +} + +SIMD_FORCE_INLINE long btVector3::maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const +{ +#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON) + #if defined _WIN32 || defined (BT_USE_SSE) + const long scalar_cutoff = 10; + long _maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut ); + #elif defined BT_USE_NEON + const long scalar_cutoff = 4; + extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut ); + #endif + if( array_count < scalar_cutoff ) +#endif + { + btScalar maxDot = -SIMD_INFINITY; + int i = 0; + int ptIndex = -1; + for( i = 0; i < array_count; i++ ) + { + btScalar dot = array[i].dot(*this); + + if( dot > maxDot ) + { + maxDot = dot; + ptIndex = i; + } + } + + dotOut = maxDot; + return ptIndex; + } +#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON) + return _maxdot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut ); +#endif +} + +SIMD_FORCE_INLINE long btVector3::minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const +{ +#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON) + #if defined BT_USE_SSE + const long scalar_cutoff = 10; + long _mindot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut ); + #elif defined BT_USE_NEON + const long scalar_cutoff = 4; + extern long (*_mindot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut ); + #else + #error unhandled arch! + #endif + + if( array_count < scalar_cutoff ) +#endif + { + btScalar minDot = SIMD_INFINITY; + int i = 0; + int ptIndex = -1; + + for( i = 0; i < array_count; i++ ) + { + btScalar dot = array[i].dot(*this); + + if( dot < minDot ) + { + minDot = dot; + ptIndex = i; + } + } + + dotOut = minDot; + + return ptIndex; + } +#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON) + return _mindot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut ); +#endif//BT_USE_SIMD_VECTOR3 +} + + +class btVector4 : public btVector3 +{ +public: + + SIMD_FORCE_INLINE btVector4() {} + + + SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w) + : btVector3(_x,_y,_z) + { + m_floats[3] = _w; + } + +#if (defined (BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined (BT_USE_NEON) + SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec) + { + mVec128 = vec; + } + + SIMD_FORCE_INLINE btVector4(const btVector3& rhs) + { + mVec128 = rhs.mVec128; + } + + SIMD_FORCE_INLINE btVector4& + operator=(const btVector4& v) + { + mVec128 = v.mVec128; + return *this; + } +#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON) + + SIMD_FORCE_INLINE btVector4 absolute4() const + { +#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE) + return btVector4(_mm_and_ps(mVec128, btvAbsfMask)); +#elif defined(BT_USE_NEON) + return btVector4(vabsq_f32(mVec128)); +#else + return btVector4( + btFabs(m_floats[0]), + btFabs(m_floats[1]), + btFabs(m_floats[2]), + btFabs(m_floats[3])); +#endif + } + + + btScalar getW() const { return m_floats[3];} + + + SIMD_FORCE_INLINE int maxAxis4() const + { + int maxIndex = -1; + btScalar maxVal = btScalar(-BT_LARGE_FLOAT); + if (m_floats[0] > maxVal) + { + maxIndex = 0; + maxVal = m_floats[0]; + } + if (m_floats[1] > maxVal) + { + maxIndex = 1; + maxVal = m_floats[1]; + } + if (m_floats[2] > maxVal) + { + maxIndex = 2; + maxVal =m_floats[2]; + } + if (m_floats[3] > maxVal) + { + maxIndex = 3; + maxVal = m_floats[3]; + } + + return maxIndex; + } + + + SIMD_FORCE_INLINE int minAxis4() const + { + int minIndex = -1; + btScalar minVal = btScalar(BT_LARGE_FLOAT); + if (m_floats[0] < minVal) + { + minIndex = 0; + minVal = m_floats[0]; + } + if (m_floats[1] < minVal) + { + minIndex = 1; + minVal = m_floats[1]; + } + if (m_floats[2] < minVal) + { + minIndex = 2; + minVal =m_floats[2]; + } + if (m_floats[3] < minVal) + { + minIndex = 3; + minVal = m_floats[3]; + } + + return minIndex; + } + + + SIMD_FORCE_INLINE int closestAxis4() const + { + return absolute4().maxAxis4(); + } + + + + + /**@brief Set x,y,z and zero w + * @param x Value of x + * @param y Value of y + * @param z Value of z + */ + + +/* void getValue(btScalar *m) const + { + m[0] = m_floats[0]; + m[1] = m_floats[1]; + m[2] =m_floats[2]; + } +*/ +/**@brief Set the values + * @param x Value of x + * @param y Value of y + * @param z Value of z + * @param w Value of w + */ + SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w) + { + m_floats[0]=_x; + m_floats[1]=_y; + m_floats[2]=_z; + m_floats[3]=_w; + } + + +}; + + +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) +{ + #ifdef BT_USE_DOUBLE_PRECISION + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[7]; + dest[1] = src[6]; + dest[2] = src[5]; + dest[3] = src[4]; + dest[4] = src[3]; + dest[5] = src[2]; + dest[6] = src[1]; + dest[7] = src[0]; +#else + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[3]; + dest[1] = src[2]; + dest[2] = src[1]; + dest[3] = src[0]; +#endif //BT_USE_DOUBLE_PRECISION +} +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) +{ + for (int i=0;i<4;i++) + { + btSwapScalarEndian(sourceVec[i],destVec[i]); + } + +} + +///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) +{ + + btVector3 swappedVec; + for (int i=0;i<4;i++) + { + btSwapScalarEndian(vector[i],swappedVec[i]); + } + vector = swappedVec; +} + +template +SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q) +{ + if (btFabs(n[2]) > SIMDSQRT12) { + // choose p in y-z plane + btScalar a = n[1]*n[1] + n[2]*n[2]; + btScalar k = btRecipSqrt (a); + p[0] = 0; + p[1] = -n[2]*k; + p[2] = n[1]*k; + // set q = n x p + q[0] = a*k; + q[1] = -n[0]*p[2]; + q[2] = n[0]*p[1]; + } + else { + // choose p in x-y plane + btScalar a = n[0]*n[0] + n[1]*n[1]; + btScalar k = btRecipSqrt (a); + p[0] = -n[1]*k; + p[1] = n[0]*k; + p[2] = 0; + // set q = n x p + q[0] = -n[2]*p[1]; + q[1] = n[2]*p[0]; + q[2] = a*k; + } +} + + +struct btVector3FloatData +{ + float m_floats[4]; +}; + +struct btVector3DoubleData +{ + double m_floats[4]; + +}; + +SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const +{ + ///could also do a memcpy, check if it is worth it + for (int i=0;i<4;i++) + dataOut.m_floats[i] = float(m_floats[i]); +} + +SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn) +{ + for (int i=0;i<4;i++) + m_floats[i] = btScalar(dataIn.m_floats[i]); +} + + +SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const +{ + ///could also do a memcpy, check if it is worth it + for (int i=0;i<4;i++) + dataOut.m_floats[i] = double(m_floats[i]); +} + +SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn) +{ + for (int i=0;i<4;i++) + m_floats[i] = btScalar(dataIn.m_floats[i]); +} + + +SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const +{ + ///could also do a memcpy, check if it is worth it + for (int i=0;i<4;i++) + dataOut.m_floats[i] = m_floats[i]; +} + +SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn) +{ + for (int i=0;i<4;i++) + m_floats[i] = dataIn.m_floats[i]; +} + +#endif //BT_VECTOR3_H diff --git a/Code/Physics/src/LinearMath/premake4.lua b/Code/Physics/src/LinearMath/premake4.lua new file mode 100644 index 00000000..0f0a88a4 --- /dev/null +++ b/Code/Physics/src/LinearMath/premake4.lua @@ -0,0 +1,11 @@ + project "LinearMath" + + kind "StaticLib" + targetdir "../../lib" + includedirs { + "..", + } + files { + "**.cpp", + "**.h" + } \ No newline at end of file diff --git a/Code/Physics/src/Makefile.am b/Code/Physics/src/Makefile.am new file mode 100644 index 00000000..0ecb5c9f --- /dev/null +++ b/Code/Physics/src/Makefile.am @@ -0,0 +1,612 @@ +bullet_includedir = $(includedir)/bullet +nobase_bullet_include_HEADERS = \ + btBulletDynamicsCommon.h \ + Bullet-C-Api.h \ + btBulletCollisionCommon.h + +if CONDITIONAL_BUILD_MULTITHREADED +nobase_bullet_include_HEADERS += \ + BulletMultiThreaded/PosixThreadSupport.h \ + BulletMultiThreaded/vectormath/scalar/cpp/mat_aos.h \ + BulletMultiThreaded/vectormath/scalar/cpp/vec_aos.h \ + BulletMultiThreaded/vectormath/scalar/cpp/quat_aos.h \ + BulletMultiThreaded/vectormath/scalar/cpp/vectormath_aos.h \ + BulletMultiThreaded/PpuAddressSpace.h \ + BulletMultiThreaded/SpuCollisionTaskProcess.h \ + BulletMultiThreaded/PlatformDefinitions.h \ + BulletMultiThreaded/vectormath2bullet.h \ + BulletMultiThreaded/SpuGatheringCollisionDispatcher.h \ + BulletMultiThreaded/SpuCollisionObjectWrapper.h \ + BulletMultiThreaded/SpuSampleTaskProcess.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h \ + BulletMultiThreaded/SpuSync.h \ + BulletMultiThreaded/btThreadSupportInterface.h \ + BulletMultiThreaded/SpuLibspe2Support.h \ + BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h \ + BulletMultiThreaded/SpuFakeDma.h \ + BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h \ + BulletMultiThreaded/SpuDoubleBuffer.h \ + BulletMultiThreaded/Win32ThreadSupport.h \ + BulletMultiThreaded/SequentialThreadSupport.h + +lib_LTLIBRARIES = libLinearMath.la libBulletCollision.la libBulletDynamics.la libBulletSoftBody.la libBulletMultiThreaded.la + +libBulletMultiThreaded_la_CXXFLAGS = ${CXXFLAGS} -I./BulletMultiThreaded/vectormath/scalar/cpp +libBulletMultiThreaded_la_SOURCES =\ + BulletMultiThreaded/SpuCollisionObjectWrapper.cpp \ + BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp \ + BulletMultiThreaded/SpuLibspe2Support.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp \ + BulletMultiThreaded/btThreadSupportInterface.cpp \ + BulletMultiThreaded/SequentialThreadSupport.cpp \ + BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp \ + BulletMultiThreaded/Win32ThreadSupport.cpp \ + BulletMultiThreaded/SpuFakeDma.cpp \ + BulletMultiThreaded/PosixThreadSupport.cpp \ + BulletMultiThreaded/SpuCollisionTaskProcess.cpp \ + BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp \ + BulletMultiThreaded/SpuSampleTaskProcess.cpp \ + BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h \ + BulletMultiThreaded/PpuAddressSpace.h \ + BulletMultiThreaded/SpuSampleTaskProcess.h \ + BulletMultiThreaded/SequentialThreadSupport.h \ + BulletMultiThreaded/PlatformDefinitions.h \ + BulletMultiThreaded/Win32ThreadSupport.h \ + BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h \ + BulletMultiThreaded/btThreadSupportInterface.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h \ + BulletMultiThreaded/SpuGatheringCollisionDispatcher.h \ + BulletMultiThreaded/SpuFakeDma.h \ + BulletMultiThreaded/SpuSync.h \ + BulletMultiThreaded/SpuCollisionObjectWrapper.h \ + BulletMultiThreaded/SpuDoubleBuffer.h \ + BulletMultiThreaded/SpuCollisionTaskProcess.h \ + BulletMultiThreaded/PosixThreadSupport.h \ + BulletMultiThreaded/SpuLibspe2Support.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h \ + BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h + +else +lib_LTLIBRARIES = libLinearMath.la libBulletCollision.la libBulletDynamics.la libBulletSoftBody.la +endif + + +libLinearMath_la_SOURCES = \ + LinearMath/btQuickprof.cpp \ + LinearMath/btGeometryUtil.cpp \ + LinearMath/btAlignedAllocator.cpp \ + LinearMath/btSerializer.cpp \ + LinearMath/btConvexHull.cpp \ + LinearMath/btPolarDecomposition.cpp \ + LinearMath/btVector3.cpp \ + LinearMath/btConvexHullComputer.cpp \ + LinearMath/btHashMap.h \ + LinearMath/btConvexHull.h \ + LinearMath/btAabbUtil2.h \ + LinearMath/btGeometryUtil.h \ + LinearMath/btQuadWord.h \ + LinearMath/btPoolAllocator.h \ + LinearMath/btPolarDecomposition.h \ + LinearMath/btScalar.h \ + LinearMath/btMinMax.h \ + LinearMath/btVector3.h \ + LinearMath/btList.h \ + LinearMath/btStackAlloc.h \ + LinearMath/btMatrix3x3.h \ + LinearMath/btMotionState.h \ + LinearMath/btAlignedAllocator.h \ + LinearMath/btQuaternion.h \ + LinearMath/btAlignedObjectArray.h \ + LinearMath/btQuickprof.h \ + LinearMath/btSerializer.h \ + LinearMath/btTransformUtil.h \ + LinearMath/btTransform.h \ + LinearMath/btDefaultMotionState.h \ + LinearMath/btIDebugDraw.h \ + LinearMath/btRandom.h + + +libBulletCollision_la_SOURCES = \ + BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp \ + BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp \ + BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp \ + BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp \ + BulletCollision/NarrowPhaseCollision/btConvexCast.cpp \ + BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp \ + BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp \ + BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp \ + BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btCollisionObject.cpp \ + BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btGhostObject.cpp \ + BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp \ + BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp \ + BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp \ + BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp \ + BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp \ + BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp \ + BulletCollision/CollisionDispatch/btManifoldResult.cpp \ + BulletCollision/CollisionDispatch/btCollisionWorld.cpp \ + BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btUnionFind.cpp \ + BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp \ + BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp \ + BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp \ + BulletCollision/CollisionShapes/btTetrahedronShape.cpp \ + BulletCollision/CollisionShapes/btShapeHull.cpp \ + BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp \ + BulletCollision/CollisionShapes/btCompoundShape.cpp \ + BulletCollision/CollisionShapes/btConeShape.cpp \ + BulletCollision/CollisionShapes/btConvexPolyhedron.cpp \ + BulletCollision/CollisionShapes/btMultiSphereShape.cpp \ + BulletCollision/CollisionShapes/btUniformScalingShape.cpp \ + BulletCollision/CollisionShapes/btSphereShape.cpp \ + BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp \ + BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btTriangleBuffer.cpp \ + BulletCollision/CollisionShapes/btStaticPlaneShape.cpp \ + BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp \ + BulletCollision/CollisionShapes/btEmptyShape.cpp \ + BulletCollision/CollisionShapes/btCollisionShape.cpp \ + BulletCollision/CollisionShapes/btConvexShape.cpp \ + BulletCollision/CollisionShapes/btConvex2dShape.cpp \ + BulletCollision/CollisionShapes/btConvexInternalShape.cpp \ + BulletCollision/CollisionShapes/btConvexHullShape.cpp \ + BulletCollision/CollisionShapes/btTriangleCallback.cpp \ + BulletCollision/CollisionShapes/btCapsuleShape.cpp \ + BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btConcaveShape.cpp \ + BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp \ + BulletCollision/CollisionShapes/btBoxShape.cpp \ + BulletCollision/CollisionShapes/btBox2dShape.cpp \ + BulletCollision/CollisionShapes/btOptimizedBvh.cpp \ + BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp \ + BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btCylinderShape.cpp \ + BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp \ + BulletCollision/CollisionShapes/btStridingMeshInterface.cpp \ + BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp \ + BulletCollision/CollisionShapes/btTriangleMesh.cpp \ + BulletCollision/BroadphaseCollision/btAxisSweep3.cpp \ + BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp \ + BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp \ + BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp \ + BulletCollision/BroadphaseCollision/btDispatcher.cpp \ + BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp \ + BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp \ + BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp \ + BulletCollision/BroadphaseCollision/btDbvt.cpp \ + BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp \ + BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \ + BulletCollision/NarrowPhaseCollision/btConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \ + BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \ + BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btPointCollector.h \ + BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \ + BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \ + BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \ + BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \ + BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \ + BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \ + BulletCollision/CollisionDispatch/btCollisionObject.h \ + BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h \ + BulletCollision/CollisionDispatch/btGhostObject.h \ + BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \ + BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxDetector.h \ + BulletCollision/CollisionDispatch/btCollisionDispatcher.h \ + BulletCollision/CollisionDispatch/SphereTriangleDetector.h \ + BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btUnionFind.h \ + BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btHashedSimplePairCache.h \ + BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btSimulationIslandManager.h \ + BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \ + BulletCollision/CollisionDispatch/btCollisionWorld.h \ + BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \ + BulletCollision/CollisionDispatch/btManifoldResult.h \ + BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionConfiguration.h \ + BulletCollision/CollisionShapes/btConvexShape.h \ + BulletCollision/CollisionShapes/btConvex2dShape.h \ + BulletCollision/CollisionShapes/btTriangleCallback.h \ + BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \ + BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btCompoundShape.h \ + BulletCollision/CollisionShapes/btBoxShape.h \ + BulletCollision/CollisionShapes/btBox2dShape.h \ + BulletCollision/CollisionShapes/btMultiSphereShape.h \ + BulletCollision/CollisionShapes/btCollisionMargin.h \ + BulletCollision/CollisionShapes/btConcaveShape.h \ + BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btEmptyShape.h \ + BulletCollision/CollisionShapes/btUniformScalingShape.h \ + BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btMaterial.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \ + BulletCollision/CollisionShapes/btTriangleInfoMap.h \ + BulletCollision/CollisionShapes/btSphereShape.h \ + BulletCollision/CollisionShapes/btConvexPointCloudShape.h \ + BulletCollision/CollisionShapes/btCapsuleShape.h \ + BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \ + BulletCollision/CollisionShapes/btCollisionShape.h \ + BulletCollision/CollisionShapes/btStaticPlaneShape.h \ + BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btStridingMeshInterface.h \ + BulletCollision/CollisionShapes/btTriangleMesh.h \ + BulletCollision/CollisionShapes/btTriangleBuffer.h \ + BulletCollision/CollisionShapes/btShapeHull.h \ + BulletCollision/CollisionShapes/btMinkowskiSumShape.h \ + BulletCollision/CollisionShapes/btOptimizedBvh.h \ + BulletCollision/CollisionShapes/btTriangleShape.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \ + BulletCollision/CollisionShapes/btCylinderShape.h \ + BulletCollision/CollisionShapes/btTetrahedronShape.h \ + BulletCollision/CollisionShapes/btConvexInternalShape.h \ + BulletCollision/CollisionShapes/btConeShape.h \ + BulletCollision/CollisionShapes/btConvexHullShape.h \ + BulletCollision/BroadphaseCollision/btAxisSweep3.h \ + BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \ + BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \ + BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \ + BulletCollision/BroadphaseCollision/btDbvt.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \ + BulletCollision/BroadphaseCollision/btDispatcher.h \ + BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \ + BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \ + BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \ + BulletCollision/BroadphaseCollision/btQuantizedBvh.h \ + BulletCollision/Gimpact/btGImpactBvh.cpp\ + BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp\ + BulletCollision/Gimpact/btTriangleShapeEx.cpp\ + BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp\ + BulletCollision/Gimpact/btGImpactShape.cpp\ + BulletCollision/Gimpact/gim_box_set.cpp\ + BulletCollision/Gimpact/gim_contact.cpp\ + BulletCollision/Gimpact/gim_memory.cpp\ + BulletCollision/Gimpact/gim_tri_collision.cpp + +libBulletDynamics_la_SOURCES = \ + BulletDynamics/Dynamics/btRigidBody.cpp \ + BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp \ + BulletDynamics/Dynamics/Bullet-C-API.cpp \ + BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp \ + BulletDynamics/ConstraintSolver/btFixedConstraint.cpp \ + BulletDynamics/ConstraintSolver/btGearConstraint.cpp \ + BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp \ + BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp \ + BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp \ + BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp \ + BulletDynamics/ConstraintSolver/btTypedConstraint.cpp \ + BulletDynamics/ConstraintSolver/btContactConstraint.cpp \ + BulletDynamics/ConstraintSolver/btSliderConstraint.cpp \ + BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp \ + BulletDynamics/ConstraintSolver/btHingeConstraint.cpp \ + BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp \ + BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp \ + BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp \ + BulletDynamics/Vehicle/btWheelInfo.cpp \ + BulletDynamics/Vehicle/btRaycastVehicle.cpp \ + BulletDynamics/Character/btKinematicCharacterController.cpp \ + BulletDynamics/Character/btKinematicCharacterController.h \ + BulletDynamics/Character/btCharacterControllerInterface.h \ + BulletDynamics/Dynamics/btActionInterface.h \ + BulletDynamics/Dynamics/btSimpleDynamicsWorld.h \ + BulletDynamics/Dynamics/btRigidBody.h \ + BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h \ + BulletDynamics/Dynamics/btDynamicsWorld.h \ + BulletDynamics/ConstraintSolver/btSolverBody.h \ + BulletDynamics/ConstraintSolver/btConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btConeTwistConstraint.h \ + BulletDynamics/ConstraintSolver/btTypedConstraint.h \ + BulletDynamics/ConstraintSolver/btContactSolverInfo.h \ + BulletDynamics/ConstraintSolver/btContactConstraint.h \ + BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h \ + BulletDynamics/ConstraintSolver/btJacobianEntry.h \ + BulletDynamics/ConstraintSolver/btSolverConstraint.h \ + BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btGearConstraint.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h \ + BulletDynamics/ConstraintSolver/btSliderConstraint.h \ + BulletDynamics/ConstraintSolver/btHingeConstraint.h \ + BulletDynamics/ConstraintSolver/btHinge2Constraint.h \ + BulletDynamics/ConstraintSolver/btUniversalConstraint.h \ + BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h \ + BulletDynamics/Vehicle/btVehicleRaycaster.h \ + BulletDynamics/Vehicle/btRaycastVehicle.h \ + BulletDynamics/Vehicle/btWheelInfo.h \ + BulletDynamics/Featherstone/btMultiBody.cpp \ + BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp \ + BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp \ + BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp \ + BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp \ + BulletDynamics/Featherstone/btMultiBodyJointMotor.h \ + BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h \ + BulletDynamics/Featherstone/btMultiBody.h \ + BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h \ + BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h \ + BulletDynamics/Featherstone/btMultiBodyLink.h \ + BulletDynamics/Featherstone/btMultiBodyLinkCollider.h \ + BulletDynamics/Featherstone/btMultiBodySolverConstraint.h \ + BulletDynamics/Featherstone/btMultiBodyConstraint.h \ + BulletDynamics/Featherstone/btMultiBodyPoint2Point.h \ + BulletDynamics/Featherstone/btMultiBodyConstraint.cpp \ + BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp \ + BulletDynamics/MLCPSolvers/btDantzigLCP.cpp \ + BulletDynamics/MLCPSolvers/btMLCPSolver.cpp \ + BulletDynamics/MLCPSolvers/btDantzigLCP.h \ + BulletDynamics/MLCPSolvers/btDantzigSolver.h \ + BulletDynamics/MLCPSolvers/btMLCPSolver.h \ + BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h \ + BulletDynamics/MLCPSolvers/btPATHSolver.h \ + BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h + + + + +libBulletSoftBody_la_SOURCES = \ + BulletSoftBody/btDefaultSoftBodySolver.cpp \ + BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp \ + BulletSoftBody/btSoftBody.cpp \ + BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp \ + BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp \ + BulletSoftBody/btSoftRigidDynamicsWorld.cpp \ + BulletSoftBody/btSoftBodyHelpers.cpp \ + BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp \ + BulletSoftBody/btSparseSDF.h \ + BulletSoftBody/btSoftRigidCollisionAlgorithm.h \ + BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h \ + BulletSoftBody/btSoftBody.h \ + BulletSoftBody/btSoftSoftCollisionAlgorithm.h \ + BulletSoftBody/btSoftBodyInternals.h \ + BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h \ + BulletSoftBody/btSoftRigidDynamicsWorld.h \ + BulletSoftBody/btSoftBodyHelpers.h + + + +nobase_bullet_include_HEADERS += \ + BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h \ + BulletSoftBody/btSoftBodyInternals.h \ + BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h \ + BulletSoftBody/btSoftSoftCollisionAlgorithm.h \ + BulletSoftBody/btSoftBody.h \ + BulletSoftBody/btSoftBodyHelpers.h \ + BulletSoftBody/btSparseSDF.h \ + BulletSoftBody/btSoftRigidCollisionAlgorithm.h \ + BulletSoftBody/btSoftRigidDynamicsWorld.h \ + BulletDynamics/Vehicle/btRaycastVehicle.h \ + BulletDynamics/Vehicle/btWheelInfo.h \ + BulletDynamics/Vehicle/btVehicleRaycaster.h \ + BulletDynamics/Dynamics/btActionInterface.h \ + BulletDynamics/Dynamics/btRigidBody.h \ + BulletDynamics/Dynamics/btDynamicsWorld.h \ + BulletDynamics/Dynamics/btSimpleDynamicsWorld.h \ + BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h \ + BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btSolverConstraint.h \ + BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h \ + BulletDynamics/ConstraintSolver/btTypedConstraint.h \ + BulletDynamics/ConstraintSolver/btSliderConstraint.h \ + BulletDynamics/ConstraintSolver/btConstraintSolver.h \ + BulletDynamics/ConstraintSolver/btContactConstraint.h \ + BulletDynamics/ConstraintSolver/btContactSolverInfo.h \ + BulletDynamics/ConstraintSolver/btGearConstraint.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h \ + BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h \ + BulletDynamics/ConstraintSolver/btJacobianEntry.h \ + BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h \ + BulletDynamics/ConstraintSolver/btConeTwistConstraint.h \ + BulletDynamics/ConstraintSolver/btHingeConstraint.h \ + BulletDynamics/ConstraintSolver/btHinge2Constraint.h \ + BulletDynamics/ConstraintSolver/btUniversalConstraint.h \ + BulletDynamics/ConstraintSolver/btSolverBody.h \ + BulletDynamics/Character/btCharacterControllerInterface.h \ + BulletDynamics/Character/btKinematicCharacterController.h \ + BulletDynamics/Featherstone/btMultiBody.h \ + BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h \ + BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h \ + BulletDynamics/Featherstone/btMultiBodyLink.h \ + BulletDynamics/Featherstone/btMultiBodyLinkCollider.h \ + BulletDynamics/Featherstone/btMultiBodySolverConstraint.h \ + BulletDynamics/Featherstone/btMultiBodyConstraint.h \ + BulletDynamics/Featherstone/btMultiBodyPoint2Point.h \ + BulletDynamics/MLCPSolvers/btDantzigLCP.h \ + BulletDynamics/MLCPSolvers/btDantzigSolver.h \ + BulletDynamics/MLCPSolvers/btMLCPSolver.h \ + BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h \ + BulletDynamics/MLCPSolvers/btPATHSolver.h \ + BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h \ + BulletCollision/CollisionShapes/btShapeHull.h \ + BulletCollision/CollisionShapes/btConcaveShape.h \ + BulletCollision/CollisionShapes/btCollisionMargin.h \ + BulletCollision/CollisionShapes/btCompoundShape.h \ + BulletCollision/CollisionShapes/btConvexHullShape.h \ + BulletCollision/CollisionShapes/btCylinderShape.h \ + BulletCollision/CollisionShapes/btTriangleMesh.h \ + BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \ + BulletCollision/CollisionShapes/btUniformScalingShape.h \ + BulletCollision/CollisionShapes/btConvexPointCloudShape.h \ + BulletCollision/CollisionShapes/btTetrahedronShape.h \ + BulletCollision/CollisionShapes/btCapsuleShape.h \ + BulletCollision/CollisionShapes/btSphereShape.h \ + BulletCollision/CollisionShapes/btMultiSphereShape.h \ + BulletCollision/CollisionShapes/btConvexInternalShape.h \ + BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btStridingMeshInterface.h \ + BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btEmptyShape.h \ + BulletCollision/CollisionShapes/btOptimizedBvh.h \ + BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btTriangleCallback.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \ + BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \ + BulletCollision/CollisionShapes/btTriangleInfoMap.h \ + BulletCollision/CollisionShapes/btTriangleBuffer.h \ + BulletCollision/CollisionShapes/btConvexShape.h \ + BulletCollision/CollisionShapes/btConvex2dShape.h \ + BulletCollision/CollisionShapes/btStaticPlaneShape.h \ + BulletCollision/CollisionShapes/btConeShape.h \ + BulletCollision/CollisionShapes/btCollisionShape.h \ + BulletCollision/CollisionShapes/btTriangleShape.h \ + BulletCollision/CollisionShapes/btBoxShape.h \ + BulletCollision/CollisionShapes/btBox2dShape.h \ + BulletCollision/CollisionShapes/btMinkowskiSumShape.h \ + BulletCollision/CollisionShapes/btTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btMaterial.h \ + BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \ + BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \ + BulletCollision/NarrowPhaseCollision/btConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \ + BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \ + BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \ + BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \ + BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \ + BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \ + BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \ + BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \ + BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \ + BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \ + BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \ + BulletCollision/NarrowPhaseCollision/btPointCollector.h \ + BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \ + BulletCollision/BroadphaseCollision/btDbvt.h \ + BulletCollision/BroadphaseCollision/btDispatcher.h \ + BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \ + BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \ + BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \ + BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \ + BulletCollision/BroadphaseCollision/btQuantizedBvh.h \ + BulletCollision/BroadphaseCollision/btAxisSweep3.h \ + BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \ + BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \ + BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \ + BulletCollision/CollisionDispatch/btUnionFind.h \ + BulletCollision/CollisionDispatch/btCollisionConfiguration.h \ + BulletCollision/CollisionDispatch/btCollisionDispatcher.h \ + BulletCollision/CollisionDispatch/SphereTriangleDetector.h \ + BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionWorld.h \ + BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \ + BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \ + BulletCollision/CollisionDispatch/btCollisionObject.h \ + BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h \ + BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \ + BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btHashedSimplePairCache.h \ + BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btGhostObject.h \ + BulletCollision/CollisionDispatch/btSimulationIslandManager.h \ + BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btBoxBoxDetector.h \ + BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \ + BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \ + BulletCollision/CollisionDispatch/btManifoldResult.h \ + BulletCollision/Gimpact/gim_memory.h \ + BulletCollision/Gimpact/gim_clip_polygon.h \ + BulletCollision/Gimpact/gim_bitset.h \ + BulletCollision/Gimpact/gim_linear_math.h \ + BulletCollision/Gimpact/btGeometryOperations.h \ + BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h \ + BulletCollision/Gimpact/btGImpactBvh.h \ + BulletCollision/Gimpact/gim_box_set.h \ + BulletCollision/Gimpact/gim_array.h \ + BulletCollision/Gimpact/btGImpactShape.h \ + BulletCollision/Gimpact/btTriangleShapeEx.h \ + BulletCollision/Gimpact/btClipPolygon.h \ + BulletCollision/Gimpact/gim_box_collision.h \ + BulletCollision/Gimpact/gim_tri_collision.h \ + BulletCollision/Gimpact/gim_geometry.h \ + BulletCollision/Gimpact/gim_math.h \ + BulletCollision/Gimpact/btQuantization.h \ + BulletCollision/Gimpact/btGImpactQuantizedBvh.h \ + BulletCollision/Gimpact/gim_geom_types.h \ + BulletCollision/Gimpact/gim_basic_geometry_operations.h \ + BulletCollision/Gimpact/gim_contact.h \ + BulletCollision/Gimpact/gim_hash_table.h \ + BulletCollision/Gimpact/gim_radixsort.h \ + BulletCollision/Gimpact/btGImpactMassUtil.h \ + BulletCollision/Gimpact/btGenericPoolAllocator.h \ + BulletCollision/Gimpact/btBoxCollision.h \ + BulletCollision/Gimpact/btContactProcessing.h \ + LinearMath/btGeometryUtil.h \ + LinearMath/btConvexHull.h \ + LinearMath/btList.h \ + LinearMath/btMatrix3x3.h \ + LinearMath/btVector3.h \ + LinearMath/btPoolAllocator.h \ + LinearMath/btPolarDecomposition.h \ + LinearMath/btScalar.h \ + LinearMath/btDefaultMotionState.h \ + LinearMath/btTransform.h \ + LinearMath/btQuadWord.h \ + LinearMath/btAabbUtil2.h \ + LinearMath/btTransformUtil.h \ + LinearMath/btRandom.h \ + LinearMath/btQuaternion.h \ + LinearMath/btMinMax.h \ + LinearMath/btMotionState.h \ + LinearMath/btIDebugDraw.h \ + LinearMath/btAlignedAllocator.h \ + LinearMath/btStackAlloc.h \ + LinearMath/btAlignedObjectArray.h \ + LinearMath/btHashMap.h \ + LinearMath/btQuickprof.h\ + LinearMath/btSerializer.h diff --git a/Code/Physics/src/MiniCL/CMakeLists.txt b/Code/Physics/src/MiniCL/CMakeLists.txt new file mode 100644 index 00000000..f351b1ce --- /dev/null +++ b/Code/Physics/src/MiniCL/CMakeLists.txt @@ -0,0 +1,69 @@ +#MiniCL provides a small subset of OpenCL + +INCLUDE_DIRECTORIES( + ${BULLET_PHYSICS_SOURCE_DIR}/src + ${VECTOR_MATH_INCLUDE} +) + +SET(MiniCL_SRCS + MiniCL.cpp + MiniCLTaskScheduler.cpp + MiniCLTask/MiniCLTask.cpp +) + +SET(Root_HDRS + MiniCLTaskScheduler.h + cl.h + cl_gl.h + cl_platform.h + cl_MiniCL_Defs.h +) + +SET(MiniCLTask_HDRS + MiniCLTask/MiniCLTask.h +) + +SET(MiniCL_HDRS + ${Root_HDRS} + ${MiniCLTask_HDRS} +) + +ADD_LIBRARY(MiniCL ${MiniCL_SRCS} ${MiniCL_HDRS} ) +SET_TARGET_PROPERTIES(MiniCL PROPERTIES VERSION ${BULLET_VERSION}) +SET_TARGET_PROPERTIES(MiniCL PROPERTIES SOVERSION ${BULLET_VERSION}) + + +IF (BUILD_SHARED_LIBS) + TARGET_LINK_LIBRARIES(MiniCL BulletMultiThreaded BulletDynamics BulletCollision) +ENDIF (BUILD_SHARED_LIBS) + +IF (INSTALL_LIBS) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + #INSTALL of other files requires CMake 2.6 + IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) +# IF(INSTALL_EXTRA_LIBS) + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS MiniCL DESTINATION .) + ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + INSTALL(TARGETS MiniCL + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib${LIB_SUFFIX} + ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(DIRECTORY +${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING +PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) +# ENDIF (INSTALL_EXTRA_LIBS) + ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + + IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + SET_TARGET_PROPERTIES(MiniCL PROPERTIES FRAMEWORK true) + + SET_TARGET_PROPERTIES(MiniCL PROPERTIES PUBLIC_HEADER "${Root_HDRS}") + # Have to list out sub-directories manually: + SET_PROPERTY(SOURCE ${MiniCLTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MiniCLTask) + + ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) + ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) +ENDIF (INSTALL_LIBS) + diff --git a/Code/Physics/src/MiniCL/MiniCL.cpp b/Code/Physics/src/MiniCL/MiniCL.cpp new file mode 100644 index 00000000..ba0865aa --- /dev/null +++ b/Code/Physics/src/MiniCL/MiniCL.cpp @@ -0,0 +1,788 @@ +/* + Copyright (C) 2010 Sony Computer Entertainment Inc. + All rights reserved. + +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 "MiniCL/cl.h" +#define __PHYSICS_COMMON_H__ 1 +#ifdef _WIN32 +#include "BulletMultiThreaded/Win32ThreadSupport.h" +#endif + +#include "BulletMultiThreaded/PlatformDefinitions.h" +#ifdef USE_PTHREADS +#include "BulletMultiThreaded/PosixThreadSupport.h" +#endif + + +#include "BulletMultiThreaded/SequentialThreadSupport.h" +#include "MiniCLTaskScheduler.h" +#include "MiniCLTask/MiniCLTask.h" +#include "LinearMath/btMinMax.h" +#include +#include + +//#define DEBUG_MINICL_KERNELS 1 + +static const char* spPlatformID = "MiniCL, SCEA"; +static const char* spDriverVersion= "1.0"; + +CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs( + cl_uint num_entries, + cl_platform_id * platforms, + cl_uint * num_platforms ) CL_API_SUFFIX__VERSION_1_0 +{ + if(platforms != NULL) + { + if(num_entries <= 0) + { + return CL_INVALID_VALUE; + } + *((const char**)platforms) = spPlatformID; + } + if(num_platforms != NULL) + { + *num_platforms = 1; + } + return CL_SUCCESS; +} + + +CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo( + cl_platform_id platform, + cl_platform_info param_name, + size_t param_value_size, + void * param_value, + size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 +{ + char* pId = (char*)platform; + if(strcmp(pId, spPlatformID)) + { + return CL_INVALID_PLATFORM; + } + switch(param_name) + { + case CL_PLATFORM_VERSION: + { + if(param_value_size < (strlen(spDriverVersion) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spDriverVersion); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spDriverVersion) + 1; + } + break; + } + case CL_PLATFORM_NAME: + case CL_PLATFORM_VENDOR : + if(param_value_size < (strlen(spPlatformID) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spPlatformID); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spPlatformID) + 1; + } + break; + default : + return CL_INVALID_VALUE; + } + return CL_SUCCESS; +} + + + + +CL_API_ENTRY cl_int CL_API_CALL clGetDeviceInfo( + cl_device_id device , + cl_device_info param_name , + size_t param_value_size , + void * param_value , + size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 +{ + + switch (param_name) + { + case CL_DEVICE_NAME: + { + char deviceName[] = "MiniCL CPU"; + unsigned int nameLen = (unsigned int)strlen(deviceName)+1; + btAssert(param_value_size>strlen(deviceName)); + if (nameLen < param_value_size) + { + const char* cpuName = "MiniCL CPU"; + sprintf((char*)param_value,"%s",cpuName); + } else + { + printf("error: param_value_size should be at least %d, but it is %zu\n",nameLen,param_value_size); + return CL_INVALID_VALUE; + } + break; + } + case CL_DEVICE_TYPE: + { + if (param_value_size>=sizeof(cl_device_type)) + { + cl_device_type* deviceType = (cl_device_type*)param_value; + *deviceType = CL_DEVICE_TYPE_CPU; + } else + { + printf("error: param_value_size should be at least %zu\n",sizeof(cl_device_type)); + return CL_INVALID_VALUE; + } + break; + } + case CL_DEVICE_MAX_COMPUTE_UNITS: + { + if (param_value_size>=sizeof(cl_uint)) + { + cl_uint* numUnits = (cl_uint*)param_value; + *numUnits= 4; + } else + { + printf("error: param_value_size should be at least %zu\n",sizeof(cl_uint)); + return CL_INVALID_VALUE; + } + + break; + } + case CL_DEVICE_MAX_WORK_ITEM_SIZES: + { + size_t workitem_size[3]; + + if (param_value_size>=sizeof(workitem_size)) + { + size_t* workItemSize = (size_t*)param_value; + workItemSize[0] = 64; + workItemSize[1] = 24; + workItemSize[2] = 16; + } else + { + printf("error: param_value_size should be at least %zu\n",sizeof(cl_uint)); + return CL_INVALID_VALUE; + } + break; + } + case CL_DEVICE_MAX_CLOCK_FREQUENCY: + { + cl_uint* clock_frequency = (cl_uint*)param_value; + *clock_frequency = 3*1024; + break; + } + + case CL_DEVICE_VENDOR : + { + if(param_value_size < (strlen(spPlatformID) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spPlatformID); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spPlatformID) + 1; + } + break; + } + case CL_DRIVER_VERSION: + { + if(param_value_size < (strlen(spDriverVersion) + 1)) + { + return CL_INVALID_VALUE; + } + strcpy((char*)param_value, spDriverVersion); + if(param_value_size_ret != NULL) + { + *param_value_size_ret = strlen(spDriverVersion) + 1; + } + + break; + } + case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: + { + cl_uint* maxDimensions = (cl_uint*)param_value; + *maxDimensions = 1; + break; + } + case CL_DEVICE_MAX_WORK_GROUP_SIZE: + { + cl_uint* maxWorkGroupSize = (cl_uint*)param_value; + *maxWorkGroupSize = 128;//1; + break; + } + case CL_DEVICE_ADDRESS_BITS: + { + cl_uint* addressBits = (cl_uint*)param_value; + *addressBits= 32; //@todo: should this be 64 for 64bit builds? + break; + } + case CL_DEVICE_MAX_MEM_ALLOC_SIZE: + { + cl_ulong* maxMemAlloc = (cl_ulong*)param_value; + *maxMemAlloc= 512*1024*1024; //this "should be enough for everyone" ? + break; + } + case CL_DEVICE_GLOBAL_MEM_SIZE: + { + cl_ulong* maxMemAlloc = (cl_ulong*)param_value; + *maxMemAlloc= 1024*1024*1024; //this "should be enough for everyone" ? + break; + } + + case CL_DEVICE_ERROR_CORRECTION_SUPPORT: + { + cl_bool* error_correction_support = (cl_bool*)param_value; + *error_correction_support = CL_FALSE; + break; + } + + case CL_DEVICE_LOCAL_MEM_TYPE: + { + cl_device_local_mem_type* local_mem_type = (cl_device_local_mem_type*)param_value; + *local_mem_type = CL_GLOBAL; + break; + } + case CL_DEVICE_LOCAL_MEM_SIZE: + { + cl_ulong* localmem = (cl_ulong*) param_value; + *localmem = 32*1024; + break; + } + + case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: + { + cl_ulong* localmem = (cl_ulong*) param_value; + *localmem = 64*1024; + break; + } + case CL_DEVICE_QUEUE_PROPERTIES: + { + cl_command_queue_properties* queueProp = (cl_command_queue_properties*) param_value; + memset(queueProp,0,param_value_size); + + break; + } + case CL_DEVICE_IMAGE_SUPPORT: + { + cl_bool* imageSupport = (cl_bool*) param_value; + *imageSupport = CL_FALSE; + break; + } + + case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: + case CL_DEVICE_MAX_READ_IMAGE_ARGS: + { + cl_uint* imageArgs = (cl_uint*) param_value; + *imageArgs = 0; + break; + } + case CL_DEVICE_IMAGE3D_MAX_DEPTH: + case CL_DEVICE_IMAGE3D_MAX_HEIGHT: + case CL_DEVICE_IMAGE2D_MAX_HEIGHT: + case CL_DEVICE_IMAGE3D_MAX_WIDTH: + case CL_DEVICE_IMAGE2D_MAX_WIDTH: + { + size_t* maxSize = (size_t*) param_value; + *maxSize = 0; + break; + } + + case CL_DEVICE_EXTENSIONS: + { + char* extensions = (char*) param_value; + *extensions = 0; + break; + } + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: + { + cl_uint* width = (cl_uint*) param_value; + *width = 1; + break; + } + + default: + { + printf("error: unsupported param_name:%d\n",param_name); + } + } + + + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + + + +CL_API_ENTRY cl_int CL_API_CALL clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + + +// Enqueued Commands APIs +CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadBuffer(cl_command_queue command_queue , + cl_mem buffer , + cl_bool /* blocking_read */, + size_t offset , + size_t cb , + void * ptr , + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + + ///wait for all work items to be completed + scheduler->flush(); + + memcpy(ptr,(char*)buffer + offset,cb); + return 0; +} + + +CL_API_ENTRY cl_int clGetProgramBuildInfo(cl_program /* program */, + cl_device_id /* device */, + cl_program_build_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + + return 0; +} + + +// Program Object APIs +CL_API_ENTRY cl_program +clCreateProgramWithSource(cl_context context , + cl_uint /* count */, + const char ** /* strings */, + const size_t * /* lengths */, + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + *errcode_ret = CL_SUCCESS; + return (cl_program)context; +} + +CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue command_queue , + cl_mem buffer , + cl_bool /* blocking_read */, + size_t offset, + size_t cb , + const void * ptr , + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + + ///wait for all work items to be completed + scheduler->flush(); + + memcpy((char*)buffer + offset, ptr,cb); + return 0; +} + +CL_API_ENTRY cl_int CL_API_CALL clFlush(cl_command_queue command_queue) +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + ///wait for all work items to be completed + scheduler->flush(); + return 0; +} + + +CL_API_ENTRY cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, + cl_kernel clKernel , + cl_uint work_dim , + const size_t * /* global_work_offset */, + const size_t * global_work_size , + const size_t * /* local_work_size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 +{ + + + MiniCLKernel* kernel = (MiniCLKernel*) clKernel; + for (unsigned int ii=0;iim_scheduler->getMaxNumOutstandingTasks(); + int numWorkItems = global_work_size[ii]; + +// //at minimum 64 work items per task +// int numWorkItemsPerTask = btMax(64,numWorkItems / maxTask); + int numWorkItemsPerTask = numWorkItems / maxTask; + if (!numWorkItemsPerTask) numWorkItemsPerTask = 1; + + for (int t=0;tm_scheduler->issueTask(t, endIndex, kernel); + t = endIndex; + } + } +/* + + void* bla = 0; + + scheduler->issueTask(bla,2,3); + scheduler->flush(); + + */ + + return 0; +} + +#define LOCAL_BUF_SIZE 32768 +static int sLocalMemBuf[LOCAL_BUF_SIZE * 4 + 16]; +static int* spLocalBufCurr = NULL; +static int sLocalBufUsed = LOCAL_BUF_SIZE; // so it will be reset at the first call +static void* localBufMalloc(int size) +{ + int size16 = (size + 15) >> 4; // in 16-byte units + if((sLocalBufUsed + size16) > LOCAL_BUF_SIZE) + { // reset + spLocalBufCurr = sLocalMemBuf; + while((size_t)spLocalBufCurr & 0x0F) spLocalBufCurr++; // align to 16 bytes + sLocalBufUsed = 0; + } + void* ret = spLocalBufCurr; + spLocalBufCurr += size16 * 4; + sLocalBufUsed += size; + return ret; +} + + + +CL_API_ENTRY cl_int CL_API_CALL clSetKernelArg(cl_kernel clKernel , + cl_uint arg_index , + size_t arg_size , + const void * arg_value ) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLKernel* kernel = (MiniCLKernel* ) clKernel; + btAssert(arg_size <= MINICL_MAX_ARGLENGTH); + if (arg_index>MINI_CL_MAX_ARG) + { + printf("error: clSetKernelArg arg_index (%u) exceeds %u\n",arg_index,MINI_CL_MAX_ARG); + } else + { + if (arg_size>MINICL_MAX_ARGLENGTH) + //if (arg_size != MINICL_MAX_ARGLENGTH) + { + printf("error: clSetKernelArg argdata too large: %zu (maximum is %zu)\n",arg_size,MINICL_MAX_ARGLENGTH); + } + else + { + if(arg_value == NULL) + { // this is only for __local memory qualifier + void* ptr = localBufMalloc(arg_size); + kernel->m_argData[arg_index] = ptr; + } + else + { + memcpy(&(kernel->m_argData[arg_index]), arg_value, arg_size); + } + kernel->m_argSizes[arg_index] = arg_size; + if(arg_index >= kernel->m_numArgs) + { + kernel->m_numArgs = arg_index + 1; + kernel->updateLauncher(); + } + } + } + return 0; +} + +// Kernel Object APIs +CL_API_ENTRY cl_kernel CL_API_CALL clCreateKernel(cl_program program , + const char * kernel_name , + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) program; + int nameLen = strlen(kernel_name); + if(nameLen >= MINI_CL_MAX_KERNEL_NAME) + { + *errcode_ret = CL_INVALID_KERNEL_NAME; + return NULL; + } + + MiniCLKernel* kernel = new MiniCLKernel(); + + strcpy(kernel->m_name, kernel_name); + kernel->m_numArgs = 0; + + //kernel->m_kernelProgramCommandId = scheduler->findProgramCommandIdByName(kernel_name); + //if (kernel->m_kernelProgramCommandId>=0) + //{ + // *errcode_ret = CL_SUCCESS; + //} else + //{ + // *errcode_ret = CL_INVALID_KERNEL_NAME; + //} + kernel->m_scheduler = scheduler; + if(kernel->registerSelf() == NULL) + { + *errcode_ret = CL_INVALID_KERNEL_NAME; + delete kernel; + return NULL; + } + else + { + *errcode_ret = CL_SUCCESS; + } + + return (cl_kernel)kernel; + +} + + +CL_API_ENTRY cl_int CL_API_CALL clBuildProgram(cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + void (*pfn_notify)(cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_0 +{ + return CL_SUCCESS; +} + +CL_API_ENTRY cl_program CL_API_CALL clCreateProgramWithBinary(cl_context context , + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const size_t * /* lengths */, + const unsigned char ** /* binaries */, + cl_int * /* binary_status */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + return (cl_program)context; +} + + +// Memory Object APIs +CL_API_ENTRY cl_mem CL_API_CALL clCreateBuffer(cl_context /* context */, + cl_mem_flags flags , + size_t size, + void * host_ptr , + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + cl_mem buf = (cl_mem)malloc(size); + if ((flags&CL_MEM_COPY_HOST_PTR) && host_ptr) + { + memcpy(buf,host_ptr,size); + } + *errcode_ret = 0; + return buf; +} + +// Command Queue APIs +CL_API_ENTRY cl_command_queue CL_API_CALL clCreateCommandQueue(cl_context context , + cl_device_id /* device */, + cl_command_queue_properties /* properties */, + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + *errcode_ret = 0; + return (cl_command_queue) context; +} + +extern CL_API_ENTRY cl_int CL_API_CALL clGetContextInfo(cl_context /* context */, + cl_context_info param_name , + size_t param_value_size , + void * param_value, + size_t * param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + + switch (param_name) + { + case CL_CONTEXT_DEVICES: + { + if (!param_value_size) + { + *param_value_size_ret = 13; + } else + { + const char* testName = "MiniCL_Test."; + sprintf((char*)param_value,"%s",testName); + } + break; + }; + default: + { + printf("unsupported\n"); + } + } + + return 0; +} + + + +CL_API_ENTRY cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties * /* properties */, + cl_device_type device_type , + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + int maxNumOutstandingTasks = 4; +// int maxNumOutstandingTasks = 2; +// int maxNumOutstandingTasks = 1; + gMiniCLNumOutstandingTasks = maxNumOutstandingTasks; + const int maxNumOfThreadSupports = 8; + static int sUniqueThreadSupportIndex = 0; + static const char* sUniqueThreadSupportName[maxNumOfThreadSupports] = + { + "MiniCL_0", "MiniCL_1", "MiniCL_2", "MiniCL_3", "MiniCL_4", "MiniCL_5", "MiniCL_6", "MiniCL_7" + }; + + btThreadSupportInterface* threadSupport = 0; + + if (device_type==CL_DEVICE_TYPE_DEBUG) + { + SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory); + threadSupport = new SequentialThreadSupport(stc); + } else + { + +#if _WIN32 + btAssert(sUniqueThreadSupportIndex < maxNumOfThreadSupports); + const char* bla = "MiniCL"; + threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( +// bla, + sUniqueThreadSupportName[sUniqueThreadSupportIndex++], + processMiniCLTask, //processCollisionTask, + createMiniCLLocalStoreMemory,//createCollisionLocalStoreMemory, + maxNumOutstandingTasks)); +#else + +#ifdef USE_PTHREADS + PosixThreadSupport::ThreadConstructionInfo constructionInfo("PosixThreads", + processMiniCLTask, + createMiniCLLocalStoreMemory, + maxNumOutstandingTasks); + threadSupport = new PosixThreadSupport(constructionInfo); + +#else + ///todo: add posix thread support for other platforms + SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory); + threadSupport = new SequentialThreadSupport(stc); +#endif //USE_PTHREADS +#endif + + } + + + MiniCLTaskScheduler* scheduler = new MiniCLTaskScheduler(threadSupport,maxNumOutstandingTasks); + + *errcode_ret = 0; + return (cl_context)scheduler; +} + +CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceIDs(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +CL_API_ENTRY cl_context CL_API_CALL +clCreateContext(const cl_context_properties * properties , + cl_uint num_devices , + const cl_device_id * devices , + void (*pfn_notify)(const char *, const void *, size_t, void *), + void * user_data , + cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 +{ + + return clCreateContextFromType(properties,CL_DEVICE_TYPE_ALL,pfn_notify,user_data,errcode_ret); +} + +CL_API_ENTRY cl_int CL_API_CALL clReleaseContext(cl_context context ) CL_API_SUFFIX__VERSION_1_0 +{ + + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) context; + + btThreadSupportInterface* threadSupport = scheduler->getThreadSupportInterface(); + delete scheduler; + delete threadSupport; + + return 0; +} +extern CL_API_ENTRY cl_int CL_API_CALL +clFinish(cl_command_queue command_queue ) CL_API_SUFFIX__VERSION_1_0 +{ + MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; + ///wait for all work items to be completed + scheduler->flush(); + return CL_SUCCESS; +} + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetProgramInfo(cl_program /* program */, + cl_program_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + return 0; +} + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelWorkGroupInfo(cl_kernel kernel , + cl_device_id /* device */, + cl_kernel_work_group_info wgi/* param_name */, + size_t sz /* param_value_size */, + void * ptr /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 +{ + if((wgi == CL_KERNEL_WORK_GROUP_SIZE) + &&(sz == sizeof(size_t)) + &&(ptr != NULL)) + { + MiniCLKernel* miniCLKernel = (MiniCLKernel*)kernel; + MiniCLTaskScheduler* scheduler = miniCLKernel->m_scheduler; + *((size_t*)ptr) = scheduler->getMaxNumOutstandingTasks(); + return CL_SUCCESS; + } + else + { + return CL_INVALID_VALUE; + } +} diff --git a/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.cpp b/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.cpp new file mode 100644 index 00000000..a56e96a0 --- /dev/null +++ b/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.cpp @@ -0,0 +1,74 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 "MiniCLTask.h" +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "BulletMultiThreaded/SpuFakeDma.h" +#include "LinearMath/btMinMax.h" +#include "MiniCLTask.h" +#include "MiniCL/MiniCLTaskScheduler.h" + + +#ifdef __SPU__ +#include +#else +#include +#define spu_printf printf +#endif + +int gMiniCLNumOutstandingTasks = 0; + +struct MiniCLTask_LocalStoreMemory +{ + +}; + + +//-- MAIN METHOD +void processMiniCLTask(void* userPtr, void* lsMemory) +{ + // BT_PROFILE("processSampleTask"); + + MiniCLTask_LocalStoreMemory* localMemory = (MiniCLTask_LocalStoreMemory*)lsMemory; + + MiniCLTaskDesc* taskDescPtr = (MiniCLTaskDesc*)userPtr; + MiniCLTaskDesc& taskDesc = *taskDescPtr; + + for (unsigned int i=taskDesc.m_firstWorkUnit;im_launcher(&taskDesc, i); + } + +// printf("Compute Unit[%d] executed kernel %d work items [%d..%d)\n",taskDesc.m_taskId,taskDesc.m_kernelProgramId,taskDesc.m_firstWorkUnit,taskDesc.m_lastWorkUnit); + +} + + +#if defined(__CELLOS_LV2__) || defined (LIBSPE2) + +ATTRIBUTE_ALIGNED16(MiniCLTask_LocalStoreMemory gLocalStoreMemory); + +void* createMiniCLLocalStoreMemory() +{ + return &gLocalStoreMemory; +} +#else +void* createMiniCLLocalStoreMemory() +{ + return new MiniCLTask_LocalStoreMemory; +}; + +#endif diff --git a/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.h b/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.h new file mode 100644 index 00000000..7e78be08 --- /dev/null +++ b/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 MINICL__TASK_H +#define MINICL__TASK_H + +#include "BulletMultiThreaded/PlatformDefinitions.h" +#include "LinearMath/btScalar.h" + +#include "LinearMath/btAlignedAllocator.h" + + +#define MINICL_MAX_ARGLENGTH (sizeof(void*)) +#define MINI_CL_MAX_ARG 16 +#define MINI_CL_MAX_KERNEL_NAME 256 + +struct MiniCLKernel; + +ATTRIBUTE_ALIGNED16(struct) MiniCLTaskDesc +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + MiniCLTaskDesc() + { + for (int i=0;i + +#ifdef __SPU__ + + + +void SampleThreadFunc(void* userPtr,void* lsMemory) +{ + //do nothing + printf("hello world\n"); +} + + +void* SamplelsMemoryFunc() +{ + //don't create local store memory, just return 0 + return 0; +} + + +#else + + +#include "BulletMultiThreaded/btThreadSupportInterface.h" + +//# include "SPUAssert.h" +#include + +#include "MiniCL/cl_platform.h" + +extern "C" { + extern char SPU_SAMPLE_ELF_SYMBOL[]; +} + + +MiniCLTaskScheduler::MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks); + + m_kernels.resize(0); + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + + m_initialized = false; + + m_threadInterface->startSPU(); + + +} + +MiniCLTaskScheduler::~MiniCLTaskScheduler() +{ + m_threadInterface->stopSPU(); + +} + + + +void MiniCLTaskScheduler::initialize() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("MiniCLTaskScheduler::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_initialized = true; + +} + + +void MiniCLTaskScheduler::issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel) +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("MiniCLTaskScheduler::issueTask (m_currentTask= %d\)n", m_currentTask); +#endif //DEBUG_SPU_TASK_SCHEDULING + + m_taskBusy[m_currentTask] = true; + m_numBusyTasks++; + + MiniCLTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask]; + { + // send task description in event message + taskDesc.m_firstWorkUnit = firstWorkUnit; + taskDesc.m_lastWorkUnit = lastWorkUnit; + taskDesc.m_kernel = kernel; + //some bookkeeping to recognize finished tasks + taskDesc.m_taskId = m_currentTask; + +// for (int i=0;im_numArgs; i++) + { + taskDesc.m_argSizes[i] = kernel->m_argSizes[i]; + if (taskDesc.m_argSizes[i]) + { + taskDesc.m_argData[i] = kernel->m_argData[i]; +// memcpy(&taskDesc.m_argData[i],&argData[MINICL_MAX_ARGLENGTH*i],taskDesc.m_argSizes[i]); + } + } + } + + + m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc, m_currentTask); + + // if all tasks busy, wait for spu event to clear the task. + + if (m_numBusyTasks >= m_maxNumOutstandingTasks) + { + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + + //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + // find new task buffer + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + if (!m_taskBusy[i]) + { + m_currentTask = i; + break; + } + } +} + + +///Optional PPU-size post processing for each task +void MiniCLTaskScheduler::postProcess(int taskId, int outputSize) +{ + +} + + +void MiniCLTaskScheduler::flush() +{ +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("\nSpuCollisionTaskProcess::flush()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + + + // all tasks are issued, wait for all tasks to be complete + while(m_numBusyTasks > 0) + { +// Consolidating SPU code + unsigned int taskId; + unsigned int outputSize; + + for (int i=0;iwaitForResponse(&taskId, &outputSize); + } + + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} + + + +typedef void (*MiniCLKernelLauncher0)(int); +typedef void (*MiniCLKernelLauncher1)(void*, int); +typedef void (*MiniCLKernelLauncher2)(void*, void*, int); +typedef void (*MiniCLKernelLauncher3)(void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher4)(void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher5)(void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher6)(void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher7)(void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher8)(void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher9)(void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher10)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher11)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher12)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher13)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher14)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher15)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); +typedef void (*MiniCLKernelLauncher16)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); + + +static void kernelLauncher0(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher0)(taskDesc->m_kernel->m_launcher))(guid); +} +static void kernelLauncher1(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher1)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + guid); +} +static void kernelLauncher2(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher2)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + guid); +} +static void kernelLauncher3(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher3)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + guid); +} +static void kernelLauncher4(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher4)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + guid); +} +static void kernelLauncher5(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher5)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + guid); +} +static void kernelLauncher6(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher6)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + guid); +} +static void kernelLauncher7(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher7)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + guid); +} +static void kernelLauncher8(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher8)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + guid); +} +static void kernelLauncher9(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher9)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + guid); +} +static void kernelLauncher10(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher10)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + guid); +} +static void kernelLauncher11(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher11)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + guid); +} +static void kernelLauncher12(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher12)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + guid); +} +static void kernelLauncher13(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher13)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + guid); +} +static void kernelLauncher14(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher14)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + taskDesc->m_argData[13], + guid); +} +static void kernelLauncher15(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher15)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + taskDesc->m_argData[13], + taskDesc->m_argData[14], + guid); +} +static void kernelLauncher16(MiniCLTaskDesc* taskDesc, int guid) +{ + ((MiniCLKernelLauncher16)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], + taskDesc->m_argData[1], + taskDesc->m_argData[2], + taskDesc->m_argData[3], + taskDesc->m_argData[4], + taskDesc->m_argData[5], + taskDesc->m_argData[6], + taskDesc->m_argData[7], + taskDesc->m_argData[8], + taskDesc->m_argData[9], + taskDesc->m_argData[10], + taskDesc->m_argData[11], + taskDesc->m_argData[12], + taskDesc->m_argData[13], + taskDesc->m_argData[14], + taskDesc->m_argData[15], + guid); +} + +static kernelLauncherCB spLauncherList[MINI_CL_MAX_ARG+1] = +{ + kernelLauncher0, + kernelLauncher1, + kernelLauncher2, + kernelLauncher3, + kernelLauncher4, + kernelLauncher5, + kernelLauncher6, + kernelLauncher7, + kernelLauncher8, + kernelLauncher9, + kernelLauncher10, + kernelLauncher11, + kernelLauncher12, + kernelLauncher13, + kernelLauncher14, + kernelLauncher15, + kernelLauncher16 +}; + +void MiniCLKernel::updateLauncher() +{ + m_launcher = spLauncherList[m_numArgs]; +} + +struct MiniCLKernelDescEntry +{ + void* pCode; + const char* pName; +}; +static MiniCLKernelDescEntry spKernelDesc[256]; +static int sNumKernelDesc = 0; + +MiniCLKernelDesc::MiniCLKernelDesc(void* pCode, const char* pName) +{ + for(int i = 0; i < sNumKernelDesc; i++) + { + if(!strcmp(pName, spKernelDesc[i].pName)) + { // already registered + btAssert(spKernelDesc[i].pCode == pCode); + return; + } + } + spKernelDesc[sNumKernelDesc].pCode = pCode; + spKernelDesc[sNumKernelDesc].pName = pName; + sNumKernelDesc++; +} + + +MiniCLKernel* MiniCLKernel::registerSelf() +{ + m_scheduler->registerKernel(this); + for(int i = 0; i < sNumKernelDesc; i++) + { + if(!strcmp(m_name, spKernelDesc[i].pName)) + { + m_pCode = spKernelDesc[i].pCode; + return this; + } + } + return NULL; +} + +#endif + + +#endif //USE_SAMPLE_PROCESS diff --git a/Code/Physics/src/MiniCL/MiniCLTaskScheduler.h b/Code/Physics/src/MiniCL/MiniCLTaskScheduler.h new file mode 100644 index 00000000..3061a713 --- /dev/null +++ b/Code/Physics/src/MiniCL/MiniCLTaskScheduler.h @@ -0,0 +1,194 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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 MINICL_TASK_SCHEDULER_H +#define MINICL_TASK_SCHEDULER_H + +#include + + +#include "BulletMultiThreaded/PlatformDefinitions.h" + +#include + +#include "LinearMath/btAlignedObjectArray.h" + + +#include "MiniCLTask/MiniCLTask.h" + +//just add your commands here, try to keep them globally unique for debugging purposes +#define CMD_SAMPLE_TASK_COMMAND 10 + +struct MiniCLKernel; + +/// MiniCLTaskScheduler handles SPU processing of collision pairs. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class MiniCLTaskScheduler +{ + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArray m_spuSampleTaskDesc; + + + btAlignedObjectArray m_kernels; + + + int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + int m_currentTask; + + bool m_initialized; + + void postProcess(int taskId, int outputSize); + + class btThreadSupportInterface* m_threadInterface; + + int m_maxNumOutstandingTasks; + + + +public: + MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks); + + ~MiniCLTaskScheduler(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize(); + + void issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush(); + + class btThreadSupportInterface* getThreadSupportInterface() + { + return m_threadInterface; + } + + int findProgramCommandIdByName(const char* programName) const; + + int getMaxNumOutstandingTasks() const + { + return m_maxNumOutstandingTasks; + } + + void registerKernel(MiniCLKernel* kernel) + { + m_kernels.push_back(kernel); + } +}; + +typedef void (*kernelLauncherCB)(MiniCLTaskDesc* taskDesc, int guid); + +struct MiniCLKernel +{ + MiniCLTaskScheduler* m_scheduler; + +// int m_kernelProgramCommandId; + + char m_name[MINI_CL_MAX_KERNEL_NAME]; + unsigned int m_numArgs; + kernelLauncherCB m_launcher; + void* m_pCode; + void updateLauncher(); + MiniCLKernel* registerSelf(); + + void* m_argData[MINI_CL_MAX_ARG]; + int m_argSizes[MINI_CL_MAX_ARG]; +}; + + +#if defined(USE_LIBSPE2) && defined(__SPU__) +////////////////////MAIN///////////////////////////// +#include "../SpuLibspe2Support.h" +#include +#include +#include + +void * SamplelsMemoryFunc(); +void SampleThreadFunc(void* userPtr,void* lsMemory); + +//#define DEBUG_LIBSPE2_MAINLOOP + +int main(unsigned long long speid, addr64 argp, addr64 envp) +{ + printf("SPU is up \n"); + + ATTRIBUTE_ALIGNED128(btSpuStatus status); + ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ; + unsigned int received_message = Spu_Mailbox_Event_Nothing; + bool shutdown = false; + + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + status.m_status = Spu_Status_Free; + status.m_lsMemory.p = SamplelsMemoryFunc(); + + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + while (!shutdown) + { + received_message = spu_read_in_mbox(); + + + + switch(received_message) + { + case Spu_Mailbox_Event_Shutdown: + shutdown = true; + break; + case Spu_Mailbox_Event_Task: + // refresh the status +#ifdef DEBUG_LIBSPE2_MAINLOOP + printf("SPU recieved Task \n"); +#endif //DEBUG_LIBSPE2_MAINLOOP + cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + btAssert(status.m_status==Spu_Status_Occupied); + + cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + SampleThreadFunc((void*)&taskDesc, reinterpret_cast (taskDesc.m_mainMemoryPtr) ); + break; + case Spu_Mailbox_Event_Nothing: + default: + break; + } + + // set to status free and wait for next task + status.m_status = Spu_Status_Free; + cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); + cellDmaWaitTagStatusAll(DMA_MASK(3)); + + + } + return 0; +} +////////////////////////////////////////////////////// +#endif + + + +#endif // MINICL_TASK_SCHEDULER_H + diff --git a/Code/Physics/src/MiniCL/cl.h b/Code/Physics/src/MiniCL/cl.h new file mode 100644 index 00000000..35282988 --- /dev/null +++ b/Code/Physics/src/MiniCL/cl.h @@ -0,0 +1,867 @@ +/******************************************************************************* + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ + +#ifndef __OPENCL_CL_H +#define __OPENCL_CL_H + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ + +typedef struct _cl_platform_id * cl_platform_id; +typedef struct _cl_device_id * cl_device_id; +typedef struct _cl_context * cl_context; +typedef struct _cl_command_queue * cl_command_queue; +typedef struct _cl_mem * cl_mem; +typedef struct _cl_program * cl_program; +typedef struct _cl_kernel * cl_kernel; +typedef struct _cl_event * cl_event; +typedef struct _cl_sampler * cl_sampler; + +typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */ +typedef cl_ulong cl_bitfield; +typedef cl_bitfield cl_device_type; +typedef cl_uint cl_platform_info; +typedef cl_uint cl_device_info; +typedef cl_bitfield cl_device_address_info; +typedef cl_bitfield cl_device_fp_config; +typedef cl_uint cl_device_mem_cache_type; +typedef cl_uint cl_device_local_mem_type; +typedef cl_bitfield cl_device_exec_capabilities; +typedef cl_bitfield cl_command_queue_properties; + +typedef intptr_t cl_context_properties; +typedef cl_uint cl_context_info; +typedef cl_uint cl_command_queue_info; +typedef cl_uint cl_channel_order; +typedef cl_uint cl_channel_type; +typedef cl_bitfield cl_mem_flags; +typedef cl_uint cl_mem_object_type; +typedef cl_uint cl_mem_info; +typedef cl_uint cl_image_info; +typedef cl_uint cl_addressing_mode; +typedef cl_uint cl_filter_mode; +typedef cl_uint cl_sampler_info; +typedef cl_bitfield cl_map_flags; +typedef cl_uint cl_program_info; +typedef cl_uint cl_program_build_info; +typedef cl_int cl_build_status; +typedef cl_uint cl_kernel_info; +typedef cl_uint cl_kernel_work_group_info; +typedef cl_uint cl_event_info; +typedef cl_uint cl_command_type; +typedef cl_uint cl_profiling_info; + +typedef struct _cl_image_format { + cl_channel_order image_channel_order; + cl_channel_type image_channel_data_type; +} cl_image_format; + +/******************************************************************************/ + +// Error Codes +#define CL_SUCCESS 0 +#define CL_DEVICE_NOT_FOUND -1 +#define CL_DEVICE_NOT_AVAILABLE -2 +#define CL_DEVICE_COMPILER_NOT_AVAILABLE -3 +#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4 +#define CL_OUT_OF_RESOURCES -5 +#define CL_OUT_OF_HOST_MEMORY -6 +#define CL_PROFILING_INFO_NOT_AVAILABLE -7 +#define CL_MEM_COPY_OVERLAP -8 +#define CL_IMAGE_FORMAT_MISMATCH -9 +#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10 +#define CL_BUILD_PROGRAM_FAILURE -11 +#define CL_MAP_FAILURE -12 + +#define CL_INVALID_VALUE -30 +#define CL_INVALID_DEVICE_TYPE -31 +#define CL_INVALID_PLATFORM -32 +#define CL_INVALID_DEVICE -33 +#define CL_INVALID_CONTEXT -34 +#define CL_INVALID_QUEUE_PROPERTIES -35 +#define CL_INVALID_COMMAND_QUEUE -36 +#define CL_INVALID_HOST_PTR -37 +#define CL_INVALID_MEM_OBJECT -38 +#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39 +#define CL_INVALID_IMAGE_SIZE -40 +#define CL_INVALID_SAMPLER -41 +#define CL_INVALID_BINARY -42 +#define CL_INVALID_BUILD_OPTIONS -43 +#define CL_INVALID_PROGRAM -44 +#define CL_INVALID_PROGRAM_EXECUTABLE -45 +#define CL_INVALID_KERNEL_NAME -46 +#define CL_INVALID_KERNEL_DEFINITION -47 +#define CL_INVALID_KERNEL -48 +#define CL_INVALID_ARG_INDEX -49 +#define CL_INVALID_ARG_VALUE -50 +#define CL_INVALID_ARG_SIZE -51 +#define CL_INVALID_KERNEL_ARGS -52 +#define CL_INVALID_WORK_DIMENSION -53 +#define CL_INVALID_WORK_GROUP_SIZE -54 +#define CL_INVALID_WORK_ITEM_SIZE -55 +#define CL_INVALID_GLOBAL_OFFSET -56 +#define CL_INVALID_EVENT_WAIT_LIST -57 +#define CL_INVALID_EVENT -58 +#define CL_INVALID_OPERATION -59 +#define CL_INVALID_GL_OBJECT -60 +#define CL_INVALID_BUFFER_SIZE -61 +#define CL_INVALID_MIP_LEVEL -62 + +// OpenCL Version +#define CL_VERSION_1_0 1 + +// cl_bool +#define CL_FALSE 0 +#define CL_TRUE 1 + +// cl_platform_info +#define CL_PLATFORM_PROFILE 0x0900 +#define CL_PLATFORM_VERSION 0x0901 +#define CL_PLATFORM_NAME 0x0902 +#define CL_PLATFORM_VENDOR 0x0903 +#define CL_PLATFORM_EXTENSIONS 0x0904 + +// cl_device_type - bitfield +#define CL_DEVICE_TYPE_DEFAULT (1 << 0) +#define CL_DEVICE_TYPE_CPU (1 << 1) +#define CL_DEVICE_TYPE_GPU (1 << 2) +#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3) +#define CL_DEVICE_TYPE_DEBUG (1 << 4) +#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF + + +// cl_device_info +#define CL_DEVICE_TYPE 0x1000 +#define CL_DEVICE_VENDOR_ID 0x1001 +#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002 +#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003 +#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004 +#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009 +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B +#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C +#define CL_DEVICE_ADDRESS_BITS 0x100D +#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E +#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F +#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010 +#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011 +#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012 +#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013 +#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014 +#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015 +#define CL_DEVICE_IMAGE_SUPPORT 0x1016 +#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017 +#define CL_DEVICE_MAX_SAMPLERS 0x1018 +#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019 +#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A +#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B +#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C +#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D +#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E +#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F +#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020 +#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021 +#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022 +#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023 +#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024 +#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025 +#define CL_DEVICE_ENDIAN_LITTLE 0x1026 +#define CL_DEVICE_AVAILABLE 0x1027 +#define CL_DEVICE_COMPILER_AVAILABLE 0x1028 +#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029 +#define CL_DEVICE_QUEUE_PROPERTIES 0x102A +#define CL_DEVICE_NAME 0x102B +#define CL_DEVICE_VENDOR 0x102C +#define CL_DRIVER_VERSION 0x102D +#define CL_DEVICE_PROFILE 0x102E +#define CL_DEVICE_VERSION 0x102F +#define CL_DEVICE_EXTENSIONS 0x1030 +#define CL_DEVICE_PLATFORM 0x1031 + +// cl_device_address_info - bitfield +#define CL_DEVICE_ADDRESS_32_BITS (1 << 0) +#define CL_DEVICE_ADDRESS_64_BITS (1 << 1) + +// cl_device_fp_config - bitfield +#define CL_FP_DENORM (1 << 0) +#define CL_FP_INF_NAN (1 << 1) +#define CL_FP_ROUND_TO_NEAREST (1 << 2) +#define CL_FP_ROUND_TO_ZERO (1 << 3) +#define CL_FP_ROUND_TO_INF (1 << 4) +#define CL_FP_FMA (1 << 5) + +// cl_device_mem_cache_type +#define CL_NONE 0x0 +#define CL_READ_ONLY_CACHE 0x1 +#define CL_READ_WRITE_CACHE 0x2 + +// cl_device_local_mem_type +#define CL_LOCAL 0x1 +#define CL_GLOBAL 0x2 + +// cl_device_exec_capabilities - bitfield +#define CL_EXEC_KERNEL (1 << 0) +#define CL_EXEC_NATIVE_KERNEL (1 << 1) + +// cl_command_queue_properties - bitfield +#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0) +#define CL_QUEUE_PROFILING_ENABLE (1 << 1) + +// cl_context_info +#define CL_CONTEXT_REFERENCE_COUNT 0x1080 +#define CL_CONTEXT_NUM_DEVICES 0x1081 +#define CL_CONTEXT_DEVICES 0x1082 +#define CL_CONTEXT_PROPERTIES 0x1083 +#define CL_CONTEXT_PLATFORM 0x1084 + +// cl_command_queue_info +#define CL_QUEUE_CONTEXT 0x1090 +#define CL_QUEUE_DEVICE 0x1091 +#define CL_QUEUE_REFERENCE_COUNT 0x1092 +#define CL_QUEUE_PROPERTIES 0x1093 + +// cl_mem_flags - bitfield +#define CL_MEM_READ_WRITE (1 << 0) +#define CL_MEM_WRITE_ONLY (1 << 1) +#define CL_MEM_READ_ONLY (1 << 2) +#define CL_MEM_USE_HOST_PTR (1 << 3) +#define CL_MEM_ALLOC_HOST_PTR (1 << 4) +#define CL_MEM_COPY_HOST_PTR (1 << 5) + +// cl_channel_order +#define CL_R 0x10B0 +#define CL_A 0x10B1 +#define CL_RG 0x10B2 +#define CL_RA 0x10B3 +#define CL_RGB 0x10B4 +#define CL_RGBA 0x10B5 +#define CL_BGRA 0x10B6 +#define CL_ARGB 0x10B7 +#define CL_INTENSITY 0x10B8 +#define CL_LUMINANCE 0x10B9 + +// cl_channel_type +#define CL_SNORM_INT8 0x10D0 +#define CL_SNORM_INT16 0x10D1 +#define CL_UNORM_INT8 0x10D2 +#define CL_UNORM_INT16 0x10D3 +#define CL_UNORM_SHORT_565 0x10D4 +#define CL_UNORM_SHORT_555 0x10D5 +#define CL_UNORM_INT_101010 0x10D6 +#define CL_SIGNED_INT8 0x10D7 +#define CL_SIGNED_INT16 0x10D8 +#define CL_SIGNED_INT32 0x10D9 +#define CL_UNSIGNED_INT8 0x10DA +#define CL_UNSIGNED_INT16 0x10DB +#define CL_UNSIGNED_INT32 0x10DC +#define CL_HALF_FLOAT 0x10DD +#define CL_FLOAT 0x10DE + +// cl_mem_object_type +#define CL_MEM_OBJECT_BUFFER 0x10F0 +#define CL_MEM_OBJECT_IMAGE2D 0x10F1 +#define CL_MEM_OBJECT_IMAGE3D 0x10F2 + +// cl_mem_info +#define CL_MEM_TYPE 0x1100 +#define CL_MEM_FLAGS 0x1101 +#define CL_MEM_SIZE 0x1102 +#define CL_MEM_HOST_PTR 0x1103 +#define CL_MEM_MAP_COUNT 0x1104 +#define CL_MEM_REFERENCE_COUNT 0x1105 +#define CL_MEM_CONTEXT 0x1106 + +// cl_image_info +#define CL_IMAGE_FORMAT 0x1110 +#define CL_IMAGE_ELEMENT_SIZE 0x1111 +#define CL_IMAGE_ROW_PITCH 0x1112 +#define CL_IMAGE_SLICE_PITCH 0x1113 +#define CL_IMAGE_WIDTH 0x1114 +#define CL_IMAGE_HEIGHT 0x1115 +#define CL_IMAGE_DEPTH 0x1116 + +// cl_addressing_mode +#define CL_ADDRESS_NONE 0x1130 +#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131 +#define CL_ADDRESS_CLAMP 0x1132 +#define CL_ADDRESS_REPEAT 0x1133 + +// cl_filter_mode +#define CL_FILTER_NEAREST 0x1140 +#define CL_FILTER_LINEAR 0x1141 + +// cl_sampler_info +#define CL_SAMPLER_REFERENCE_COUNT 0x1150 +#define CL_SAMPLER_CONTEXT 0x1151 +#define CL_SAMPLER_NORMALIZED_COORDS 0x1152 +#define CL_SAMPLER_ADDRESSING_MODE 0x1153 +#define CL_SAMPLER_FILTER_MODE 0x1154 + +// cl_map_flags - bitfield +#define CL_MAP_READ (1 << 0) +#define CL_MAP_WRITE (1 << 1) + +// cl_program_info +#define CL_PROGRAM_REFERENCE_COUNT 0x1160 +#define CL_PROGRAM_CONTEXT 0x1161 +#define CL_PROGRAM_NUM_DEVICES 0x1162 +#define CL_PROGRAM_DEVICES 0x1163 +#define CL_PROGRAM_SOURCE 0x1164 +#define CL_PROGRAM_BINARY_SIZES 0x1165 +#define CL_PROGRAM_BINARIES 0x1166 + +// cl_program_build_info +#define CL_PROGRAM_BUILD_STATUS 0x1181 +#define CL_PROGRAM_BUILD_OPTIONS 0x1182 +#define CL_PROGRAM_BUILD_LOG 0x1183 + +// cl_build_status +#define CL_BUILD_SUCCESS 0 +#define CL_BUILD_NONE -1 +#define CL_BUILD_ERROR -2 +#define CL_BUILD_IN_PROGRESS -3 + +// cl_kernel_info +#define CL_KERNEL_FUNCTION_NAME 0x1190 +#define CL_KERNEL_NUM_ARGS 0x1191 +#define CL_KERNEL_REFERENCE_COUNT 0x1192 +#define CL_KERNEL_CONTEXT 0x1193 +#define CL_KERNEL_PROGRAM 0x1194 + +// cl_kernel_work_group_info +#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0 +#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1 +#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2 + +// cl_event_info +#define CL_EVENT_COMMAND_QUEUE 0x11D0 +#define CL_EVENT_COMMAND_TYPE 0x11D1 +#define CL_EVENT_REFERENCE_COUNT 0x11D2 +#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3 + +// cl_command_type +#define CL_COMMAND_NDRANGE_KERNEL 0x11F0 +#define CL_COMMAND_TASK 0x11F1 +#define CL_COMMAND_NATIVE_KERNEL 0x11F2 +#define CL_COMMAND_READ_BUFFER 0x11F3 +#define CL_COMMAND_WRITE_BUFFER 0x11F4 +#define CL_COMMAND_COPY_BUFFER 0x11F5 +#define CL_COMMAND_READ_IMAGE 0x11F6 +#define CL_COMMAND_WRITE_IMAGE 0x11F7 +#define CL_COMMAND_COPY_IMAGE 0x11F8 +#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9 +#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA +#define CL_COMMAND_MAP_BUFFER 0x11FB +#define CL_COMMAND_MAP_IMAGE 0x11FC +#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD +#define CL_COMMAND_MARKER 0x11FE +#define CL_COMMAND_WAIT_FOR_EVENTS 0x11FF +#define CL_COMMAND_BARRIER 0x1200 +#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x1201 +#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1202 + +// command execution status +#define CL_COMPLETE 0x0 +#define CL_RUNNING 0x1 +#define CL_SUBMITTED 0x2 +#define CL_QUEUED 0x3 + +// cl_profiling_info +#define CL_PROFILING_COMMAND_QUEUED 0x1280 +#define CL_PROFILING_COMMAND_SUBMIT 0x1281 +#define CL_PROFILING_COMMAND_START 0x1282 +#define CL_PROFILING_COMMAND_END 0x1283 + +/********************************************************************************************************/ + +// Platform API +extern CL_API_ENTRY cl_int CL_API_CALL +clGetPlatformIDs(cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetPlatformInfo(cl_platform_id /* platform */, + cl_platform_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Device APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceIDs(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetDeviceInfo(cl_device_id /* device */, + cl_device_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Context APIs +extern CL_API_ENTRY cl_context CL_API_CALL +clCreateContext(const cl_context_properties * /* properties */, + cl_uint /* num_devices */, + const cl_device_id * /* devices */, + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_context CL_API_CALL +clCreateContextFromType(const cl_context_properties * /* properties */, + cl_device_type /* device_type */, + void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetContextInfo(cl_context /* context */, + cl_context_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Command Queue APIs +extern CL_API_ENTRY cl_command_queue CL_API_CALL +clCreateCommandQueue(cl_context /* context */, + cl_device_id /* device */, + cl_command_queue_properties /* properties */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetCommandQueueInfo(cl_command_queue /* command_queue */, + cl_command_queue_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetCommandQueueProperty(cl_command_queue /* command_queue */, + cl_command_queue_properties /* properties */, + cl_bool /* enable */, + cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0; + +// Memory Object APIs +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateBuffer(cl_context /* context */, + cl_mem_flags /* flags */, + size_t /* size */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateImage2D(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_row_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateImage3D(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_depth */, + size_t /* image_row_pitch */, + size_t /* image_slice_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetSupportedImageFormats(cl_context /* context */, + cl_mem_flags /* flags */, + cl_mem_object_type /* image_type */, + cl_uint /* num_entries */, + cl_image_format * /* image_formats */, + cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetMemObjectInfo(cl_mem /* memobj */, + cl_mem_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetImageInfo(cl_mem /* image */, + cl_image_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Sampler APIs +extern CL_API_ENTRY cl_sampler CL_API_CALL +clCreateSampler(cl_context /* context */, + cl_bool /* normalized_coords */, + cl_addressing_mode /* addressing_mode */, + cl_filter_mode /* filter_mode */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainSampler(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseSampler(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetSamplerInfo(cl_sampler /* sampler */, + cl_sampler_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Program Object APIs +extern CL_API_ENTRY cl_program CL_API_CALL +clCreateProgramWithSource(cl_context /* context */, + cl_uint /* count */, + const char ** /* strings */, + const size_t * /* lengths */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_program CL_API_CALL +clCreateProgramWithBinary(cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const size_t * /* lengths */, + const unsigned char ** /* binaries */, + cl_int * /* binary_status */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clBuildProgram(cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + void (*pfn_notify)(cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clUnloadCompiler(void) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetProgramInfo(cl_program /* program */, + cl_program_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetProgramBuildInfo(cl_program /* program */, + cl_device_id /* device */, + cl_program_build_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Kernel Object APIs +extern CL_API_ENTRY cl_kernel CL_API_CALL +clCreateKernel(cl_program /* program */, + const char * /* kernel_name */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clCreateKernelsInProgram(cl_program /* program */, + cl_uint /* num_kernels */, + cl_kernel * /* kernels */, + cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetKernelArg(cl_kernel /* kernel */, + cl_uint /* arg_index */, + size_t /* arg_size */, + const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelInfo(cl_kernel /* kernel */, + cl_kernel_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelWorkGroupInfo(cl_kernel /* kernel */, + cl_device_id /* device */, + cl_kernel_work_group_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Event Object APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clWaitForEvents(cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetEventInfo(cl_event /* event */, + cl_event_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; + +// Profiling APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clGetEventProfilingInfo(cl_event /* event */, + cl_profiling_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +// Flush and Finish APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clFlush(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clFinish(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +// Enqueued Commands APIs +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReadBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_read */, + size_t /* offset */, + size_t /* cb */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWriteBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_write */, + size_t /* offset */, + size_t /* cb */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyBuffer(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_buffer */, + size_t /* src_offset */, + size_t /* dst_offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReadImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_read */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* row_pitch */, + size_t /* slice_pitch */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWriteImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_write */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t /* input_row_pitch */, + size_t /* input_slice_pitch */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyImage(cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_image */, + const size_t * /* src_origin[3] */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyImageToBuffer(cl_command_queue /* command_queue */, + cl_mem /* src_image */, + cl_mem /* dst_buffer */, + const size_t * /* src_origin[3] */, + const size_t * /* region[3] */, + size_t /* dst_offset */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyBufferToImage(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_image */, + size_t /* src_offset */, + const size_t * /* dst_origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY void * CL_API_CALL +clEnqueueMapBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + size_t /* offset */, + size_t /* cb */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY void * CL_API_CALL +clEnqueueMapImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + cl_bool /* blocking_map */, + cl_map_flags /* map_flags */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + size_t * /* image_row_pitch */, + size_t * /* image_slice_pitch */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueUnmapMemObject(cl_command_queue /* command_queue */, + cl_mem /* memobj */, + void * /* mapped_ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* work_dim */, + const size_t * /* global_work_offset */, + const size_t * /* global_work_size */, + const size_t * /* local_work_size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueTask(cl_command_queue /* command_queue */, + cl_kernel /* kernel */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueNativeKernel(cl_command_queue /* command_queue */, + void (*user_func)(void *), + void * /* args */, + size_t /* cb_args */, + cl_uint /* num_mem_objects */, + const cl_mem * /* mem_list */, + const void ** /* args_mem_loc */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueMarker(cl_command_queue /* command_queue */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWaitForEvents(cl_command_queue /* command_queue */, + cl_uint /* num_events */, + const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueBarrier(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_H + diff --git a/Code/Physics/src/MiniCL/cl_MiniCL_Defs.h b/Code/Physics/src/MiniCL/cl_MiniCL_Defs.h new file mode 100644 index 00000000..0773c857 --- /dev/null +++ b/Code/Physics/src/MiniCL/cl_MiniCL_Defs.h @@ -0,0 +1,439 @@ +/* +Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans + +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 +#include +#include "LinearMath/btScalar.h" + +#include "MiniCL/cl.h" + + +#define __kernel +#define __global +#define __local +#define get_global_id(a) __guid_arg +#define get_local_id(a) ((__guid_arg) % gMiniCLNumOutstandingTasks) +#define get_local_size(a) (gMiniCLNumOutstandingTasks) +#define get_group_id(a) ((__guid_arg) / gMiniCLNumOutstandingTasks) + +//static unsigned int as_uint(float val) { return *((unsigned int*)&val); } + + +#define CLK_LOCAL_MEM_FENCE 0x01 +#define CLK_GLOBAL_MEM_FENCE 0x02 + +static void barrier(unsigned int a) +{ + // TODO : implement +} + +//ATTRIBUTE_ALIGNED16(struct) float8 +struct float8 +{ + float s0; + float s1; + float s2; + float s3; + float s4; + float s5; + float s6; + float s7; + + float8(float scalar) + { + s0=s1=s2=s3=s4=s5=s6=s7=scalar; + } +}; + + +float select( float arg0, float arg1, bool select) +{ + if (select) + return arg0; + return arg1; +} + +#define __constant + + +struct float3 +{ + float x,y,z; + + float3& operator+=(const float3& other) + { + x += other.x; + y += other.y; + z += other.z; + return *this; + } + + float3& operator-=(const float3& other) + { + x -= other.x; + y -= other.y; + z -= other.z; + return *this; + } + +}; + +static float dot(const float3&a ,const float3& b) +{ + float3 tmp; + tmp.x = a.x*b.x; + tmp.y = a.y*b.y; + tmp.z = a.z*b.z; + return tmp.x+tmp.y+tmp.z; +} + +static float3 operator-(const float3& a,const float3& b) +{ + float3 tmp; + tmp.x = a.x - b.x; + tmp.y = a.y - b.y; + tmp.z = a.z - b.z; + return tmp; +} + +static float3 operator*(const float& scalar,const float3& b) +{ + float3 tmp; + tmp.x = scalar * b.x; + tmp.y = scalar * b.y; + tmp.z = scalar * b.z; + return tmp; +} + +static float3 operator*(const float3& a,const float& scalar) +{ + float3 tmp; + tmp.x = a.x * scalar; + tmp.y = a.y * scalar; + tmp.z = a.z * scalar; + return tmp; +} + + +static float3 operator*(const float3& a,const float3& b) +{ + float3 tmp; + tmp.x = a.x * b.x; + tmp.y = a.y * b.y; + tmp.z = a.z * b.z; + return tmp; +} + + +//ATTRIBUTE_ALIGNED16(struct) float4 +struct float4 +{ + union + { + struct { + float x; + float y; + float z; + }; + float3 xyz; + }; + float w; + + float4() {} + + float4(float v0, float v1, float v2, float v3) + { + x=v0; + y=v1; + z=v2; + w=v3; + + } + float4(float3 xyz, float scalarW) + { + x = xyz.x; + y = xyz.y; + z = xyz.z; + w = scalarW; + } + + float4(float v) + { + x = y = z = w = v; + } + float4 operator*(const float4& other) + { + float4 tmp; + tmp.x = x*other.x; + tmp.y = y*other.y; + tmp.z = z*other.z; + tmp.w = w*other.w; + return tmp; + } + + + + float4 operator*(const float& other) + { + float4 tmp; + tmp.x = x*other; + tmp.y = y*other; + tmp.z = z*other; + tmp.w = w*other; + return tmp; + } + + + + float4& operator+=(const float4& other) + { + x += other.x; + y += other.y; + z += other.z; + w += other.w; + return *this; + } + + float4& operator-=(const float4& other) + { + x -= other.x; + y -= other.y; + z -= other.z; + w -= other.w; + return *this; + } + + float4& operator *=(float scalar) + { + x *= scalar; + y *= scalar; + z *= scalar; + w *= scalar; + return (*this); + } + + + + + +}; + +static float4 fabs(const float4& a) +{ + float4 tmp; + tmp.x = a.x < 0.f ? 0.f : a.x; + tmp.y = a.y < 0.f ? 0.f : a.y; + tmp.z = a.z < 0.f ? 0.f : a.z; + tmp.w = a.w < 0.f ? 0.f : a.w; + return tmp; +} +static float4 operator+(const float4& a,const float4& b) +{ + float4 tmp; + tmp.x = a.x + b.x; + tmp.y = a.y + b.y; + tmp.z = a.z + b.z; + tmp.w = a.w + b.w; + return tmp; +} + + +static float8 operator+(const float8& a,const float8& b) +{ + float8 tmp(0); + tmp.s0 = a.s0 + b.s0; + tmp.s1 = a.s1 + b.s1; + tmp.s2 = a.s2 + b.s2; + tmp.s3 = a.s3 + b.s3; + tmp.s4 = a.s4 + b.s4; + tmp.s5 = a.s5 + b.s5; + tmp.s6 = a.s6 + b.s6; + tmp.s7 = a.s7 + b.s7; + return tmp; +} + + +static float4 operator-(const float4& a,const float4& b) +{ + float4 tmp; + tmp.x = a.x - b.x; + tmp.y = a.y - b.y; + tmp.z = a.z - b.z; + tmp.w = a.w - b.w; + return tmp; +} + +static float8 operator-(const float8& a,const float8& b) +{ + float8 tmp(0); + tmp.s0 = a.s0 - b.s0; + tmp.s1 = a.s1 - b.s1; + tmp.s2 = a.s2 - b.s2; + tmp.s3 = a.s3 - b.s3; + tmp.s4 = a.s4 - b.s4; + tmp.s5 = a.s5 - b.s5; + tmp.s6 = a.s6 - b.s6; + tmp.s7 = a.s7 - b.s7; + return tmp; +} + +static float4 operator*(float a,const float4& b) +{ + float4 tmp; + tmp.x = a * b.x; + tmp.y = a * b.y; + tmp.z = a * b.z; + tmp.w = a * b.w; + return tmp; +} + +static float4 operator/(const float4& b,float a) +{ + float4 tmp; + tmp.x = b.x/a; + tmp.y = b.y/a; + tmp.z = b.z/a; + tmp.w = b.w/a; + return tmp; +} + + + + + +static float dot(const float4&a ,const float4& b) +{ + float4 tmp; + tmp.x = a.x*b.x; + tmp.y = a.y*b.y; + tmp.z = a.z*b.z; + tmp.w = a.w*b.w; + return tmp.x+tmp.y+tmp.z+tmp.w; +} + +static float length(const float4&a) +{ + float l = sqrtf(a.x*a.x+a.y*a.y+a.z*a.z); + return l; +} + +static float4 normalize(const float4&a) +{ + float4 tmp; + float l = length(a); + tmp = 1.f/l*a; + return tmp; +} + + + +static float4 cross(const float4&a ,const float4& b) +{ + float4 tmp; + tmp.x = a.y*b.z - a.z*b.y; + tmp.y = -a.x*b.z + a.z*b.x; + tmp.z = a.x*b.y - a.y*b.x; + tmp.w = 0.f; + return tmp; +} + +static float max(float a, float b) +{ + return (a >= b) ? a : b; +} + + +static float min(float a, float b) +{ + return (a <= b) ? a : b; +} + +static float fmax(float a, float b) +{ + return (a >= b) ? a : b; +} + +static float fmin(float a, float b) +{ + return (a <= b) ? a : b; +} + +struct int2 +{ + int x,y; +}; + +struct uint2 +{ + unsigned int x,y; +}; + +//typedef int2 uint2; + +typedef unsigned int uint; + +struct int4 +{ + int x,y,z,w; +}; + +struct uint4 +{ + unsigned int x,y,z,w; + uint4() {} + uint4(uint val) { x = y = z = w = val; } + uint4& operator+=(const uint4& other) + { + x += other.x; + y += other.y; + z += other.z; + w += other.w; + return *this; + } +}; +static uint4 operator+(const uint4& a,const uint4& b) +{ + uint4 tmp; + tmp.x = a.x + b.x; + tmp.y = a.y + b.y; + tmp.z = a.z + b.z; + tmp.w = a.w + b.w; + return tmp; +} +static uint4 operator-(const uint4& a,const uint4& b) +{ + uint4 tmp; + tmp.x = a.x - b.x; + tmp.y = a.y - b.y; + tmp.z = a.z - b.z; + tmp.w = a.w - b.w; + return tmp; +} + +#define native_sqrt sqrtf +#define native_sin sinf +#define native_cos cosf +#define native_powr powf + +#define GUID_ARG ,int __guid_arg +#define GUID_ARG_VAL ,__guid_arg + + +#define as_int(a) (*((int*)&(a))) + +extern "C" int gMiniCLNumOutstandingTasks; +// extern "C" void __kernel_func(); + + diff --git a/Code/Physics/src/MiniCL/cl_gl.h b/Code/Physics/src/MiniCL/cl_gl.h new file mode 100644 index 00000000..0a69d6ec --- /dev/null +++ b/Code/Physics/src/MiniCL/cl_gl.h @@ -0,0 +1,113 @@ +/********************************************************************************** + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +#ifndef __OPENCL_CL_GL_H +#define __OPENCL_CL_GL_H + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// NOTE: Make sure that appropriate GL header file is included separately + +typedef cl_uint cl_gl_object_type; +typedef cl_uint cl_gl_texture_info; +typedef cl_uint cl_gl_platform_info; + +// cl_gl_object_type +#define CL_GL_OBJECT_BUFFER 0x2000 +#define CL_GL_OBJECT_TEXTURE2D 0x2001 +#define CL_GL_OBJECT_TEXTURE3D 0x2002 +#define CL_GL_OBJECT_RENDERBUFFER 0x2003 + +// cl_gl_texture_info +#define CL_GL_TEXTURE_TARGET 0x2004 +#define CL_GL_MIPMAP_LEVEL 0x2005 + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLBuffer(cl_context /* context */, + cl_mem_flags /* flags */, + GLuint /* bufobj */, + int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLTexture2D(cl_context /* context */, + cl_mem_flags /* flags */, + GLenum /* target */, + GLint /* miplevel */, + GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLTexture3D(cl_context /* context */, + cl_mem_flags /* flags */, + GLenum /* target */, + GLint /* miplevel */, + GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_mem CL_API_CALL +clCreateFromGLRenderbuffer(cl_context /* context */, + cl_mem_flags /* flags */, + GLuint /* renderbuffer */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetGLObjectInfo(cl_mem /* memobj */, + cl_gl_object_type * /* gl_object_type */, + GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clGetGLTextureInfo(cl_mem /* memobj */, + cl_gl_texture_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueAcquireGLObjects(cl_command_queue /* command_queue */, + cl_uint /* num_objects */, + const cl_mem * /* mem_objects */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */, + cl_uint /* num_objects */, + const cl_mem * /* mem_objects */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_GL_H diff --git a/Code/Physics/src/MiniCL/cl_platform.h b/Code/Physics/src/MiniCL/cl_platform.h new file mode 100644 index 00000000..43219e14 --- /dev/null +++ b/Code/Physics/src/MiniCL/cl_platform.h @@ -0,0 +1,254 @@ +/********************************************************************************** + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +#ifndef __CL_PLATFORM_H +#define __CL_PLATFORM_H + +#define CL_PLATFORM_MINI_CL 0x12345 + +struct MiniCLKernelDesc +{ + MiniCLKernelDesc(void* pCode, const char* pName); +}; + +#define MINICL_REGISTER(__kernel_func) static MiniCLKernelDesc __kernel_func##Desc((void*)__kernel_func, #__kernel_func); + + +#ifdef __APPLE__ + /* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */ + #include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define CL_API_ENTRY +#define CL_API_CALL +#ifdef __APPLE__ +#define CL_API_SUFFIX__VERSION_1_0 // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER +#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import)) +#else +#define CL_API_SUFFIX__VERSION_1_0 +#define CL_EXTENSION_WEAK_LINK +#endif + +#if defined (_WIN32) && ! defined (__MINGW32__) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + +typedef int8_t cl_char; +typedef uint8_t cl_uchar; +typedef int16_t cl_short ; +typedef uint16_t cl_ushort ; +typedef int32_t cl_int ; +typedef uint32_t cl_uint ; +typedef int64_t cl_long ; +typedef uint64_t cl_ulong ; + +typedef uint16_t cl_half ; +typedef float cl_float ; +typedef double cl_double ; + + +typedef int8_t cl_char2[2] ; +typedef int8_t cl_char4[4] ; +typedef int8_t cl_char8[8] ; +typedef int8_t cl_char16[16] ; +typedef uint8_t cl_uchar2[2] ; +typedef uint8_t cl_uchar4[4] ; +typedef uint8_t cl_uchar8[8] ; +typedef uint8_t cl_uchar16[16] ; + +typedef int16_t cl_short2[2] ; +typedef int16_t cl_short4[4] ; +typedef int16_t cl_short8[8] ; +typedef int16_t cl_short16[16] ; +typedef uint16_t cl_ushort2[2] ; +typedef uint16_t cl_ushort4[4] ; +typedef uint16_t cl_ushort8[8] ; +typedef uint16_t cl_ushort16[16] ; + +typedef int32_t cl_int2[2] ; +typedef int32_t cl_int4[4] ; +typedef int32_t cl_int8[8] ; +typedef int32_t cl_int16[16] ; +typedef uint32_t cl_uint2[2] ; +typedef uint32_t cl_uint4[4] ; +typedef uint32_t cl_uint8[8] ; +typedef uint32_t cl_uint16[16] ; + +typedef int64_t cl_long2[2] ; +typedef int64_t cl_long4[4] ; +typedef int64_t cl_long8[8] ; +typedef int64_t cl_long16[16] ; +typedef uint64_t cl_ulong2[2] ; +typedef uint64_t cl_ulong4[4] ; +typedef uint64_t cl_ulong8[8] ; +typedef uint64_t cl_ulong16[16] ; + +typedef float cl_float2[2] ; +typedef float cl_float4[4] ; +typedef float cl_float8[8] ; +typedef float cl_float16[16] ; + +typedef double cl_double2[2] ; +typedef double cl_double4[4] ; +typedef double cl_double8[8] ; +typedef double cl_double16[16] ; + + +#else +#include + +/* scalar types */ +typedef int8_t cl_char; +typedef uint8_t cl_uchar; +typedef int16_t cl_short __attribute__((aligned(2))); +typedef uint16_t cl_ushort __attribute__((aligned(2))); +typedef int32_t cl_int __attribute__((aligned(4))); +typedef uint32_t cl_uint __attribute__((aligned(4))); +typedef int64_t cl_long __attribute__((aligned(8))); +typedef uint64_t cl_ulong __attribute__((aligned(8))); + +typedef uint16_t cl_half __attribute__((aligned(2))); +typedef float cl_float __attribute__((aligned(4))); +typedef double cl_double __attribute__((aligned(8))); + + +/* + * Vector types + * + * Note: OpenCL requires that all types be naturally aligned. + * This means that vector types must be naturally aligned. + * For example, a vector of four floats must be aligned to + * a 16 byte boundary (calculated as 4 * the natural 4-byte + * alignment of the float). The alignment qualifiers here + * will only function properly if your compiler supports them + * and if you don't actively work to defeat them. For example, + * in order for a cl_float4 to be 16 byte aligned in a struct, + * the start of the struct must itself be 16-byte aligned. + * + * Maintaining proper alignment is the user's responsibility. + */ +typedef int8_t cl_char2[2] __attribute__((aligned(2))); +typedef int8_t cl_char4[4] __attribute__((aligned(4))); +typedef int8_t cl_char8[8] __attribute__((aligned(8))); +typedef int8_t cl_char16[16] __attribute__((aligned(16))); +typedef uint8_t cl_uchar2[2] __attribute__((aligned(2))); +typedef uint8_t cl_uchar4[4] __attribute__((aligned(4))); +typedef uint8_t cl_uchar8[8] __attribute__((aligned(8))); +typedef uint8_t cl_uchar16[16] __attribute__((aligned(16))); + +typedef int16_t cl_short2[2] __attribute__((aligned(4))); +typedef int16_t cl_short4[4] __attribute__((aligned(8))); +typedef int16_t cl_short8[8] __attribute__((aligned(16))); +typedef int16_t cl_short16[16] __attribute__((aligned(32))); +typedef uint16_t cl_ushort2[2] __attribute__((aligned(4))); +typedef uint16_t cl_ushort4[4] __attribute__((aligned(8))); +typedef uint16_t cl_ushort8[8] __attribute__((aligned(16))); +typedef uint16_t cl_ushort16[16] __attribute__((aligned(32))); + +typedef int32_t cl_int2[2] __attribute__((aligned(8))); +typedef int32_t cl_int4[4] __attribute__((aligned(16))); +typedef int32_t cl_int8[8] __attribute__((aligned(32))); +typedef int32_t cl_int16[16] __attribute__((aligned(64))); +typedef uint32_t cl_uint2[2] __attribute__((aligned(8))); +typedef uint32_t cl_uint4[4] __attribute__((aligned(16))); +typedef uint32_t cl_uint8[8] __attribute__((aligned(32))); +typedef uint32_t cl_uint16[16] __attribute__((aligned(64))); + +typedef int64_t cl_long2[2] __attribute__((aligned(16))); +typedef int64_t cl_long4[4] __attribute__((aligned(32))); +typedef int64_t cl_long8[8] __attribute__((aligned(64))); +typedef int64_t cl_long16[16] __attribute__((aligned(128))); +typedef uint64_t cl_ulong2[2] __attribute__((aligned(16))); +typedef uint64_t cl_ulong4[4] __attribute__((aligned(32))); +typedef uint64_t cl_ulong8[8] __attribute__((aligned(64))); +typedef uint64_t cl_ulong16[16] __attribute__((aligned(128))); + +typedef float cl_float2[2] __attribute__((aligned(8))); +typedef float cl_float4[4] __attribute__((aligned(16))); +typedef float cl_float8[8] __attribute__((aligned(32))); +typedef float cl_float16[16] __attribute__((aligned(64))); + +typedef double cl_double2[2] __attribute__((aligned(16))); +typedef double cl_double4[4] __attribute__((aligned(32))); +typedef double cl_double8[8] __attribute__((aligned(64))); +typedef double cl_double16[16] __attribute__((aligned(128))); +#endif + +#include + +/* and a few goodies to go with them */ +#define CL_CHAR_BIT 8 +#define CL_SCHAR_MAX 127 +#define CL_SCHAR_MIN (-127-1) +#define CL_CHAR_MAX CL_SCHAR_MAX +#define CL_CHAR_MIN CL_SCHAR_MIN +#define CL_UCHAR_MAX 255 +#define CL_SHRT_MAX 32767 +#define CL_SHRT_MIN (-32767-1) +#define CL_USHRT_MAX 65535 +#define CL_INT_MAX 2147483647 +#define CL_INT_MIN (-2147483647-1) +#define CL_UINT_MAX 0xffffffffU +#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL) +#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL) +#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL) + +#define CL_FLT_DIG 6 +#define CL_FLT_MANT_DIG 24 +#define CL_FLT_MAX_10_EXP +38 +#define CL_FLT_MAX_EXP +128 +#define CL_FLT_MIN_10_EXP -37 +#define CL_FLT_MIN_EXP -125 +#define CL_FLT_RADIX 2 +#define CL_FLT_MAX 0x1.fffffep127f +#define CL_FLT_MIN 0x1.0p-126f +#define CL_FLT_EPSILON 0x1.0p-23f + +#define CL_DBL_DIG 15 +#define CL_DBL_MANT_DIG 53 +#define CL_DBL_MAX_10_EXP +308 +#define CL_DBL_MAX_EXP +1024 +#define CL_DBL_MIN_10_EXP -307 +#define CL_DBL_MIN_EXP -1021 +#define CL_DBL_RADIX 2 +#define CL_DBL_MAX 0x1.fffffffffffffp1023 +#define CL_DBL_MIN 0x1.0p-1022 +#define CL_DBL_EPSILON 0x1.0p-52 + +/* There are no vector types for half */ + +#ifdef __cplusplus +} +#endif + +#endif // __CL_PLATFORM_H diff --git a/Code/Physics/src/btBulletCollisionCommon.h b/Code/Physics/src/btBulletCollisionCommon.h new file mode 100644 index 00000000..af981b5d --- /dev/null +++ b/Code/Physics/src/btBulletCollisionCommon.h @@ -0,0 +1,68 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BULLET_COLLISION_COMMON_H +#define BULLET_COLLISION_COMMON_H + +///Common headerfile includes for Bullet Collision Detection + +///Bullet's btCollisionWorld and btCollisionObject definitions +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +///Collision Shapes +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMesh.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btEmptyShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" + +///Narrowphase Collision Detector +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" + +//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +///Dispatching and generation of collision pairs (broadphase) +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" +#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" + +///Math library & Utils +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btSerializer.h" + + +#endif //BULLET_COLLISION_COMMON_H + diff --git a/Code/Physics/src/btBulletDynamicsCommon.h b/Code/Physics/src/btBulletDynamicsCommon.h new file mode 100644 index 00000000..50282bf2 --- /dev/null +++ b/Code/Physics/src/btBulletDynamicsCommon.h @@ -0,0 +1,51 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BULLET_DYNAMICS_COMMON_H +#define BULLET_DYNAMICS_COMMON_H + +///Common headerfile includes for Bullet Dynamics, including Collision Detection +#include "btBulletCollisionCommon.h" + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h" +#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h" +#include "BulletDynamics/ConstraintSolver/btGearConstraint.h" +#include "BulletDynamics/ConstraintSolver/btFixedConstraint.h" + + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + +///Vehicle simulation, with wheel contact simulated by raycasts +#include "BulletDynamics/Vehicle/btRaycastVehicle.h" + + + + + + +#endif //BULLET_DYNAMICS_COMMON_H + diff --git a/Code/Physics/src/vectormath/neon/boolInVec.h b/Code/Physics/src/vectormath/neon/boolInVec.h new file mode 100644 index 00000000..ba16838c --- /dev/null +++ b/Code/Physics/src/vectormath/neon/boolInVec.h @@ -0,0 +1,226 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _BOOLINVEC_H +#define _BOOLINVEC_H + +#include +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ +private: + unsigned int mData; + +public: + // Default constructor; does no initialization + // + inline boolInVec( ) { }; + + // Construct from a value converted from float + // + inline boolInVec(floatInVec vec); + + // Explicit cast from bool + // + explicit inline boolInVec(bool scalar); + + // Explicit cast to bool + // + inline bool getAsBool() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to bool + // + inline operator bool() const; +#endif + + // Boolean negation operator + // + inline const boolInVec operator ! () const; + + // Assignment operator + // + inline boolInVec& operator = (boolInVec vec); + + // Boolean and assignment operator + // + inline boolInVec& operator &= (boolInVec vec); + + // Boolean exclusive or assignment operator + // + inline boolInVec& operator ^= (boolInVec vec); + + // Boolean or assignment operator + // + inline boolInVec& operator |= (boolInVec vec); + +}; + +// Equal operator +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + +// And operator +// +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + +// Exclusive or operator +// +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + +// Or operator +// +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// Conditionally select between two values +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = -(int)scalar; +} + +inline +bool +boolInVec::getAsBool() const +{ + return (mData > 0); +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +boolInVec::operator bool() const +{ + return getAsBool(); +} +#endif + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(!mData); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() == vec1.getAsBool()); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() & vec1.getAsBool()); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() | vec1.getAsBool()); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // boolInVec_h + diff --git a/Code/Physics/src/vectormath/neon/floatInVec.h b/Code/Physics/src/vectormath/neon/floatInVec.h new file mode 100644 index 00000000..26147d22 --- /dev/null +++ b/Code/Physics/src/vectormath/neon/floatInVec.h @@ -0,0 +1,344 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +// A class representing a scalar float value contained in a vector register +// This class does not support fastmath +class floatInVec +{ +private: + float mData; + +public: + // Default constructor; does no initialization + // + inline floatInVec( ) { }; + + // Construct from a value converted from bool + // + inline floatInVec(boolInVec vec); + + // Explicit cast from float + // + explicit inline floatInVec(float scalar); + + // Explicit cast to float + // + inline float getAsFloat() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to float + // + inline operator float() const; +#endif + + // Post increment (add 1.0f) + // + inline const floatInVec operator ++ (int); + + // Post decrement (subtract 1.0f) + // + inline const floatInVec operator -- (int); + + // Pre increment (add 1.0f) + // + inline floatInVec& operator ++ (); + + // Pre decrement (subtract 1.0f) + // + inline floatInVec& operator -- (); + + // Negation operator + // + inline const floatInVec operator - () const; + + // Assignment operator + // + inline floatInVec& operator = (floatInVec vec); + + // Multiplication assignment operator + // + inline floatInVec& operator *= (floatInVec vec); + + // Division assignment operator + // + inline floatInVec& operator /= (floatInVec vec); + + // Addition assignment operator + // + inline floatInVec& operator += (floatInVec vec); + + // Subtraction assignment operator + // + inline floatInVec& operator -= (floatInVec vec); + +}; + +// Multiplication operator +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + +// Division operator +// +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + +// Addition operator +// +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + +// Subtraction operator +// +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + +// Less than operator +// +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + +// Less than or equal operator +// +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + +// Greater than operator +// +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + +// Greater than or equal operator +// +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + +// Equal operator +// +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// Conditionally select between two values +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = float(vec.getAsBool()); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = scalar; +} + +inline +float +floatInVec::getAsFloat() const +{ + return mData; +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +floatInVec::operator float() const +{ + return getAsFloat(); +} +#endif + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + float olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + float olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(-mData); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(num.getAsFloat() / den.getAsFloat()); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // floatInVec_h + diff --git a/Code/Physics/src/vectormath/neon/mat_aos.h b/Code/Physics/src/vectormath/neon/mat_aos.h new file mode 100644 index 00000000..e61f601c --- /dev/null +++ b/Code/Physics/src/vectormath/neon/mat_aos.h @@ -0,0 +1,1631 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + float detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), + Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), + Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix3( + Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), + Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), + Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); + res1.setX( ( mI * tmp1 ) ); + res1.setY( ( mM * tmp0 ) ); + res1.setZ( ( mA * tmp1 ) ); + res1.setW( ( mE * tmp0 ) ); + res3.setX( ( mI * tmp3 ) ); + res3.setY( ( mM * tmp2 ) ); + res3.setZ( ( mA * tmp3 ) ); + res3.setW( ( mE * tmp2 ) ); + res2.setX( ( mI * tmp5 ) ); + res2.setY( ( mM * tmp4 ) ); + res2.setZ( ( mA * tmp5 ) ); + res2.setW( ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); + res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); + res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); + res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); + res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); + res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); + res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); + res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); + res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); + res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); + res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); + res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), + ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), + ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), + ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), + ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), + ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4::xAxis( ), + Vector4( 0.0f, c, s, 0.0f ), + Vector4( 0.0f, -s, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, 0.0f, -s, 0.0f ), + Vector4::yAxis( ), + Vector4( s, 0.0f, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, s, 0.0f, 0.0f ), + Vector4( -s, c, 0.0f, 0.0f ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix4( + Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), + Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), + Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix4( + Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), + Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), + Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, f, 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + return Matrix4( + Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), + Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), + Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + float detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); + inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); + inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Transform3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + mXYZW[0] = qx; + mXYZW[1] = qy; + mXYZW[2] = qz; + mXYZW[3] = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), + ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), + ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( 0.0f, vec.getZ(), -vec.getY() ), + Vector3( -vec.getZ(), 0.0f, vec.getX() ), + Vector3( vec.getY(), -vec.getX(), 0.0f ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif + diff --git a/Code/Physics/src/vectormath/neon/quat_aos.h b/Code/Physics/src/vectormath/neon/quat_aos.h new file mode 100644 index 00000000..d0618460 --- /dev/null +++ b/Code/Physics/src/vectormath/neon/quat_aos.h @@ -0,0 +1,413 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + + inline Quat::Quat( const Quat & quat ) + { + vXYZW = quat.vXYZW; + } + + inline Quat::Quat( float _x, float _y, float _z, float _w ) + { + mXYZW[0] = _x; + mXYZW[1] = _y; + mXYZW[2] = _z; + mXYZW[3] = _w; + } + + inline Quat::Quat( float32x4_t fXYZW ) + { + vXYZW = fXYZW; + } + + inline Quat::Quat( const Vector3 & xyz, float _w ) + { + this->setXYZ( xyz ); + this->setW( _w ); + } + + inline Quat::Quat( const Vector4 & vec ) + { + mXYZW[0] = vec.getX(); + mXYZW[1] = vec.getY(); + mXYZW[2] = vec.getZ(); + mXYZW[3] = vec.getW(); + } + + inline Quat::Quat( float scalar ) + { + vXYZW = vdupq_n_f32(scalar); + } + + inline const Quat Quat::identity( ) + { + return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); + } + + inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) + { + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); + } + + inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) + { + Quat start; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + start = ( -unitQuat0 ); + } else { + start = unitQuat0; + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); + } + + inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) + { + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); + } + + inline void loadXYZW( Quat & quat, const float * fptr ) + { + quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); + } + + inline void storeXYZW( const Quat & quat, float * fptr ) + { + vst1q_f32(fptr, quat.getvXYZW()); + } + + inline Quat & Quat::operator =( const Quat & quat ) + { + vXYZW = quat.getvXYZW(); + return *this; + } + + inline Quat & Quat::setXYZ( const Vector3 & vec ) + { + mXYZW[0] = vec.getX(); + mXYZW[1] = vec.getY(); + mXYZW[2] = vec.getZ(); + return *this; + } + + inline const Vector3 Quat::getXYZ( ) const + { + return Vector3( mXYZW[0], mXYZW[1], mXYZW[2] ); + } + + inline float32x4_t Quat::getvXYZW( ) const + { + return vXYZW; + } + + inline Quat & Quat::setX( float _x ) + { + mXYZW[0] = _x; + return *this; + } + + inline float Quat::getX( ) const + { + return mXYZW[0]; + } + + inline Quat & Quat::setY( float _y ) + { + mXYZW[1] = _y; + return *this; + } + + inline float Quat::getY( ) const + { + return mXYZW[1]; + } + + inline Quat & Quat::setZ( float _z ) + { + mXYZW[2] = _z; + return *this; + } + + inline float Quat::getZ( ) const + { + return mXYZW[2]; + } + + inline Quat & Quat::setW( float _w ) + { + mXYZW[3] = _w; + return *this; + } + + inline float Quat::getW( ) const + { + return mXYZW[3]; + } + + inline Quat & Quat::setElem( int idx, float value ) + { + *(&mXYZW[0] + idx) = value; + return *this; + } + + inline float Quat::getElem( int idx ) const + { + return *(&mXYZW[0] + idx); + } + + inline float & Quat::operator []( int idx ) + { + return *(&mXYZW[0] + idx); + } + + inline float Quat::operator []( int idx ) const + { + return *(&mXYZW[0] + idx); + } + + inline const Quat Quat::operator +( const Quat & quat ) const + { + return Quat( vaddq_f32(vXYZW, quat.vXYZW) ); + } + + inline const Quat Quat::operator -( const Quat & quat ) const + { + return Quat( vsubq_f32(vXYZW, quat.vXYZW) ); + } + + inline const Quat Quat::operator *( float scalar ) const + { + float32x4_t v_scalar = vdupq_n_f32(scalar); + return Quat( vmulq_f32(vXYZW, v_scalar) ); + } + + inline Quat & Quat::operator +=( const Quat & quat ) + { + *this = *this + quat; + return *this; + } + + inline Quat & Quat::operator -=( const Quat & quat ) + { + *this = *this - quat; + return *this; + } + + inline Quat & Quat::operator *=( float scalar ) + { + *this = *this * scalar; + return *this; + } + + inline const Quat Quat::operator /( float scalar ) const + { + return Quat( + ( mXYZW[0] / scalar ), + ( mXYZW[1] / scalar ), + ( mXYZW[2] / scalar ), + ( mXYZW[3] / scalar ) + ); + } + + inline Quat & Quat::operator /=( float scalar ) + { + *this = *this / scalar; + return *this; + } + + inline const Quat Quat::operator -( ) const + { + return Quat( vnegq_f32(vXYZW) ); + } + + inline const Quat operator *( float scalar, const Quat & quat ) + { + return quat * scalar; + } + + inline float dot( const Quat & quat0, const Quat & quat1 ) + { + float result; + result = ( quat0.getX() * quat1.getX() ); + result = ( result + ( quat0.getY() * quat1.getY() ) ); + result = ( result + ( quat0.getZ() * quat1.getZ() ) ); + result = ( result + ( quat0.getW() * quat1.getW() ) ); + return result; + } + + inline float norm( const Quat & quat ) + { + float result; + result = ( quat.getX() * quat.getX() ); + result = ( result + ( quat.getY() * quat.getY() ) ); + result = ( result + ( quat.getZ() * quat.getZ() ) ); + result = ( result + ( quat.getW() * quat.getW() ) ); + return result; + } + + inline float length( const Quat & quat ) + { + return ::sqrtf( norm( quat ) ); + } + + inline const Quat normalize( const Quat & quat ) + { + float lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Quat( + ( quat.getX() * lenInv ), + ( quat.getY() * lenInv ), + ( quat.getZ() * lenInv ), + ( quat.getW() * lenInv ) + ); + } + + inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) + { + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); + } + + inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) + { + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( ( unitVec * s ), c ); + } + + inline const Quat Quat::rotationX( float radians ) + { + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( s, 0.0f, 0.0f, c ); + } + + inline const Quat Quat::rotationY( float radians ) + { + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, s, 0.0f, c ); + } + + inline const Quat Quat::rotationZ( float radians ) + { + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, 0.0f, s, c ); + } + + inline const Quat Quat::operator *( const Quat & quat ) const + { + return Quat( + ( ( ( ( mXYZW[3] * quat.mXYZW[0] ) + ( mXYZW[0] * quat.mXYZW[3] ) ) + ( mXYZW[1] * quat.mXYZW[2] ) ) - ( mXYZW[2] * quat.mXYZW[1] ) ), + ( ( ( ( mXYZW[3] * quat.mXYZW[1] ) + ( mXYZW[1] * quat.mXYZW[3] ) ) + ( mXYZW[2] * quat.mXYZW[0] ) ) - ( mXYZW[0] * quat.mXYZW[2] ) ), + ( ( ( ( mXYZW[3] * quat.mXYZW[2] ) + ( mXYZW[2] * quat.mXYZW[3] ) ) + ( mXYZW[0] * quat.mXYZW[1] ) ) - ( mXYZW[1] * quat.mXYZW[0] ) ), + ( ( ( ( mXYZW[3] * quat.mXYZW[3] ) - ( mXYZW[0] * quat.mXYZW[0] ) ) - ( mXYZW[1] * quat.mXYZW[1] ) ) - ( mXYZW[2] * quat.mXYZW[2] ) ) + ); + } + + inline Quat & Quat::operator *=( const Quat & quat ) + { + *this = *this * quat; + return *this; + } + + inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) + { + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return Vector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); + } + + inline const Quat conj( const Quat & quat ) + { + return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); + } + + inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) + { + return Quat( + ( select1 )? quat1.getX() : quat0.getX(), + ( select1 )? quat1.getY() : quat0.getY(), + ( select1 )? quat1.getZ() : quat0.getZ(), + ( select1 )? quat1.getW() : quat0.getW() + ); + } + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +inline void print( const Quat & quat, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif + diff --git a/Code/Physics/src/vectormath/neon/vec_aos.h b/Code/Physics/src/vectormath/neon/vec_aos.h new file mode 100644 index 00000000..7bcf8dbe --- /dev/null +++ b/Code/Physics/src/vectormath/neon/vec_aos.h @@ -0,0 +1,1427 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( 1.0f, 0.0f, 0.0f ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( 0.0f, 1.0f, 0.0f ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( 0.0f, 0.0f, 1.0f ); +} + +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZ( Vector3 & vec, const float * fptr ) +{ + vec = Vector3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Vector3 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + ( mX + pnt.getX() ), + ( mY + pnt.getY() ), + ( mZ + pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + -mX, + -mY, + -mZ + ); +} + +inline const Vector3 operator *( float scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float maxElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float minElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + return result; +} + +inline float sum( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + return result; +} + +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + return result; +} + +inline float lengthSqr( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + return result; +} + +inline float length( const Vector3 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector3( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), + ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), + ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) +{ + return Vector3( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = 0.0f; +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = 1.0f; +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZW( Vector4 & vec, const float * fptr ) +{ + vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Vector4 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); + fptr[3] = vec.getW(); +} + +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ), + ( mW + vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ), + ( mW - vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Vector4 operator *( float scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ), + ( vec0.getW() * vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ), + ( vec0.getW() / vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ), + ( 1.0f / vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ), + sqrtf( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ), + ( 1.0f / sqrtf( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ), + fabsf( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), + ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float maxElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + result = (vec.getW() > result)? vec.getW() : result; + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float minElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + result = (vec.getW() < result)? vec.getW() : result; + return result; +} + +inline float sum( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + result = ( result + vec.getW() ); + return result; +} + +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + result = ( result + ( vec0.getW() * vec1.getW() ) ); + return result; +} + +inline float lengthSqr( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + result = ( result + ( vec.getW() * vec.getW() ) ); + return result; +} + +inline float length( const Vector4 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector4( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ), + ( vec.getW() * lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) +{ + return Vector4( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ(), + ( select1 )? vec1.getW() : vec0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void loadXYZ( Point3 & pnt, const float * fptr ) +{ + pnt = Point3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Point3 & pnt, float * fptr ) +{ + fptr[0] = pnt.getX(); + fptr[1] = pnt.getY(); + fptr[2] = pnt.getZ(); +} + +inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + ( mX - pnt.mX ), + ( mY - pnt.mY ), + ( mZ - pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + ( mX + vec.getX() ), + ( mY + vec.getY() ), + ( mZ + vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + ( mX - vec.getX() ), + ( mY - vec.getY() ), + ( mZ - vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() * pnt1.getX() ), + ( pnt0.getY() * pnt1.getY() ), + ( pnt0.getZ() * pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() / pnt1.getX() ), + ( pnt0.getY() / pnt1.getY() ), + ( pnt0.getZ() / pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / pnt.getX() ), + ( 1.0f / pnt.getY() ), + ( 1.0f / pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf( pnt.getX() ), + sqrtf( pnt.getY() ), + sqrtf( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / sqrtf( pnt.getX() ) ), + ( 1.0f / sqrtf( pnt.getY() ) ), + ( 1.0f / sqrtf( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf( pnt.getX() ), + fabsf( pnt.getY() ), + fabsf( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), + ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), + ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float maxElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() > result)? pnt.getZ() : result; + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float minElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() < result)? pnt.getZ() : result; + return result; +} + +inline float sum( const Point3 & pnt ) +{ + float result; + result = ( pnt.getX() + pnt.getY() ); + result = ( result + pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + float result; + result = ( pnt.getX() * unitVec.getX() ); + result = ( result + ( pnt.getY() * unitVec.getY() ) ); + result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); + return result; +} + +inline float distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) +{ + return Point3( + ( select1 )? pnt1.getX() : pnt0.getX(), + ( select1 )? pnt1.getY() : pnt0.getY(), + ( select1 )? pnt1.getZ() : pnt0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif + diff --git a/Code/Physics/src/vectormath/neon/vectormath_aos.h b/Code/Physics/src/vectormath/neon/vectormath_aos.h new file mode 100644 index 00000000..97bdc278 --- /dev/null +++ b/Code/Physics/src/vectormath/neon/vectormath_aos.h @@ -0,0 +1,1890 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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. + +This source version has been altered. + +*/ + +#ifndef _VECTORMATH_AOS_CPP_H +#define _VECTORMATH_AOS_CPP_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline float length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Vector3 & vec, const float * fptr ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Vector3 & vec, float * fptr ); + +// Load three-half-floats as a 3-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); + +// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline float length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Vector4 & vec, const float * fptr ); + +// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Vector4 & vec, float * fptr ); + +// Load four-half-floats as a 4-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); + +// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Point3 & pnt, const float * fptr ); + +// Store x, y, and z elements of a 3-D point in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Point3 & pnt, float * fptr ); + +// Load three-half-floats as a 3-D point +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); + +// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ +#if defined( __APPLE__ ) && defined( BT_USE_NEON ) + union{ + float32x4_t vXYZW; + float mXYZW[4]; + }; +#else + float mX; + float mY; + float mZ; + float mW; +#endif + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from vector of x, y, z, and w elements + // + inline Quat( float32x4_t fXYZW ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + +#if defined( __APPLE__ ) && defined( BT_USE_NEON ) + inline float32x4_t getvXYZW( ) const; +#endif + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline float dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline float length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Quat & quat, const float * fptr ); + +// Store x, y, z, and w elements of a quaternion in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Quat & quat, float * fptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif + diff --git a/Code/Physics/src/vectormath/scalar/boolInVec.h b/Code/Physics/src/vectormath/scalar/boolInVec.h new file mode 100644 index 00000000..c5eeeebd --- /dev/null +++ b/Code/Physics/src/vectormath/scalar/boolInVec.h @@ -0,0 +1,225 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _BOOLINVEC_H +#define _BOOLINVEC_H + +#include +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ +private: + unsigned int mData; + +public: + // Default constructor; does no initialization + // + inline boolInVec( ) { }; + + // Construct from a value converted from float + // + inline boolInVec(floatInVec vec); + + // Explicit cast from bool + // + explicit inline boolInVec(bool scalar); + + // Explicit cast to bool + // + inline bool getAsBool() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to bool + // + inline operator bool() const; +#endif + + // Boolean negation operator + // + inline const boolInVec operator ! () const; + + // Assignment operator + // + inline boolInVec& operator = (boolInVec vec); + + // Boolean and assignment operator + // + inline boolInVec& operator &= (boolInVec vec); + + // Boolean exclusive or assignment operator + // + inline boolInVec& operator ^= (boolInVec vec); + + // Boolean or assignment operator + // + inline boolInVec& operator |= (boolInVec vec); + +}; + +// Equal operator +// +inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); + +// And operator +// +inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); + +// Exclusive or operator +// +inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); + +// Or operator +// +inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); + +// Conditionally select between two values +// +inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(floatInVec vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + mData = -(int)scalar; +} + +inline +bool +boolInVec::getAsBool() const +{ + return (mData > 0); +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +boolInVec::operator bool() const +{ + return getAsBool(); +} +#endif + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(!mData); +} + +inline +boolInVec& +boolInVec::operator = (boolInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (boolInVec vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (boolInVec vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (boolInVec vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() == vec1.getAsBool()); +} + +inline +const boolInVec +operator != (boolInVec vec0, boolInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const boolInVec +operator & (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() & vec1.getAsBool()); +} + +inline +const boolInVec +operator | (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() | vec1.getAsBool()); +} + +inline +const boolInVec +operator ^ (boolInVec vec0, boolInVec vec1) +{ + return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); +} + +inline +const boolInVec +select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Code/Physics/src/vectormath/scalar/floatInVec.h b/Code/Physics/src/vectormath/scalar/floatInVec.h new file mode 100644 index 00000000..12d89e43 --- /dev/null +++ b/Code/Physics/src/vectormath/scalar/floatInVec.h @@ -0,0 +1,343 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +// A class representing a scalar float value contained in a vector register +// This class does not support fastmath +class floatInVec +{ +private: + float mData; + +public: + // Default constructor; does no initialization + // + inline floatInVec( ) { }; + + // Construct from a value converted from bool + // + inline floatInVec(boolInVec vec); + + // Explicit cast from float + // + explicit inline floatInVec(float scalar); + + // Explicit cast to float + // + inline float getAsFloat() const; + +#ifndef _VECTORMATH_NO_SCALAR_CAST + // Implicit cast to float + // + inline operator float() const; +#endif + + // Post increment (add 1.0f) + // + inline const floatInVec operator ++ (int); + + // Post decrement (subtract 1.0f) + // + inline const floatInVec operator -- (int); + + // Pre increment (add 1.0f) + // + inline floatInVec& operator ++ (); + + // Pre decrement (subtract 1.0f) + // + inline floatInVec& operator -- (); + + // Negation operator + // + inline const floatInVec operator - () const; + + // Assignment operator + // + inline floatInVec& operator = (floatInVec vec); + + // Multiplication assignment operator + // + inline floatInVec& operator *= (floatInVec vec); + + // Division assignment operator + // + inline floatInVec& operator /= (floatInVec vec); + + // Addition assignment operator + // + inline floatInVec& operator += (floatInVec vec); + + // Subtraction assignment operator + // + inline floatInVec& operator -= (floatInVec vec); + +}; + +// Multiplication operator +// +inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); + +// Division operator +// +inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); + +// Addition operator +// +inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); + +// Subtraction operator +// +inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); + +// Less than operator +// +inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); + +// Less than or equal operator +// +inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); + +// Greater than operator +// +inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); + +// Greater than or equal operator +// +inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); + +// Equal operator +// +inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); + +// Not equal operator +// +inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); + +// Conditionally select between two values +// +inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); + + +} // namespace Vectormath + + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(boolInVec vec) +{ + mData = float(vec.getAsBool()); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = scalar; +} + +inline +float +floatInVec::getAsFloat() const +{ + return mData; +} + +#ifndef _VECTORMATH_NO_SCALAR_CAST +inline +floatInVec::operator float() const +{ + return getAsFloat(); +} +#endif + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + float olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + float olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(1.0f); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(1.0f); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(-mData); +} + +inline +floatInVec& +floatInVec::operator = (floatInVec vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (floatInVec vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (floatInVec vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (floatInVec vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (floatInVec vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); +} + +inline +const floatInVec +operator / (floatInVec num, floatInVec den) +{ + return floatInVec(num.getAsFloat() / den.getAsFloat()); +} + +inline +const floatInVec +operator + (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); +} + +inline +const floatInVec +operator - (floatInVec vec0, floatInVec vec1) +{ + return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); +} + +inline +const boolInVec +operator < (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); +} + +inline +const boolInVec +operator <= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 > vec1); +} + +inline +const boolInVec +operator > (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); +} + +inline +const boolInVec +operator >= (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 < vec1); +} + +inline +const boolInVec +operator == (floatInVec vec0, floatInVec vec1) +{ + return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); +} + +inline +const boolInVec +operator != (floatInVec vec0, floatInVec vec1) +{ + return !(vec0 == vec1); +} + +inline +const floatInVec +select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) +{ + return (select_vec1.getAsBool() == 0) ? vec0 : vec1; +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Code/Physics/src/vectormath/scalar/mat_aos.h b/Code/Physics/src/vectormath/scalar/mat_aos.h new file mode 100644 index 00000000..e103243d --- /dev/null +++ b/Code/Physics/src/vectormath/scalar/mat_aos.h @@ -0,0 +1,1630 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +inline Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +inline Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +inline Matrix3::Matrix3( const Quat & unitQuat ) +{ + float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; + qx = unitQuat.getX(); + qy = unitQuat.getY(); + qz = unitQuat.getZ(); + qw = unitQuat.getW(); + qx2 = ( qx + qx ); + qy2 = ( qy + qy ); + qz2 = ( qz + qz ); + qxqx2 = ( qx * qx2 ); + qxqy2 = ( qx * qy2 ); + qxqz2 = ( qx * qz2 ); + qxqw2 = ( qw * qx2 ); + qyqy2 = ( qy * qy2 ); + qyqz2 = ( qy * qz2 ); + qyqw2 = ( qw * qy2 ); + qzqz2 = ( qz * qz2 ); + qzqw2 = ( qw * qz2 ); + mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); + mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); + mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); +} + +inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +inline Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +inline Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +inline const Matrix3 transpose( const Matrix3 & mat ) +{ + return Matrix3( + Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), + Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), + Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) + ); +} + +inline const Matrix3 inverse( const Matrix3 & mat ) +{ + Vector3 tmp0, tmp1, tmp2; + float detinv; + tmp0 = cross( mat.getCol1(), mat.getCol2() ); + tmp1 = cross( mat.getCol2(), mat.getCol0() ); + tmp2 = cross( mat.getCol0(), mat.getCol1() ); + detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); + return Matrix3( + Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), + Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), + Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) + ); +} + +inline float determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +inline const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::operator *( float scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +inline Matrix3 & Matrix3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +inline const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ) + ); +} + +inline const Matrix3 Matrix3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ) + ); +} + +inline const Matrix3 Matrix3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ) + ); +} + +inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix3( + Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), + Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), + Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) + ); +} + +inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) +{ + return Matrix3( unitQuat ); +} + +inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) +{ + return Matrix3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ) + ); +} + +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +inline void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +inline Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +inline Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +inline const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +inline const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +inline const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +inline const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +inline const Matrix4 transpose( const Matrix4 & mat ) +{ + return Matrix4( + Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), + Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), + Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), + Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) + ); +} + +inline const Matrix4 inverse( const Matrix4 & mat ) +{ + Vector4 res0, res1, res2, res3; + float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); + res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); + res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); + res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); + detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); + res1.setX( ( mI * tmp1 ) ); + res1.setY( ( mM * tmp0 ) ); + res1.setZ( ( mA * tmp1 ) ); + res1.setW( ( mE * tmp0 ) ); + res3.setX( ( mI * tmp3 ) ); + res3.setY( ( mM * tmp2 ) ); + res3.setZ( ( mA * tmp3 ) ); + res3.setW( ( mE * tmp2 ) ); + res2.setX( ( mI * tmp5 ) ); + res2.setY( ( mM * tmp4 ) ); + res2.setZ( ( mA * tmp5 ) ); + res2.setW( ( mE * tmp4 ) ); + tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); + tmp1 = ( ( mM * mF ) - ( mE * mN ) ); + tmp2 = ( ( mI * mD ) - ( mA * mL ) ); + tmp3 = ( ( mM * mH ) - ( mE * mP ) ); + tmp4 = ( ( mI * mC ) - ( mA * mK ) ); + tmp5 = ( ( mM * mG ) - ( mE * mO ) ); + res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); + res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); + res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); + res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); + res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); + res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); + res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); + res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); + res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); + res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); + res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); + res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); + return Matrix4( + ( res0 * detInv ), + ( res1 * detInv ), + ( res2 * detInv ), + ( res3 * detInv ) + ); +} + +inline const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +inline const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +inline float determinant( const Matrix4 & mat ) +{ + float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + mA = mat.getCol0().getX(); + mB = mat.getCol0().getY(); + mC = mat.getCol0().getZ(); + mD = mat.getCol0().getW(); + mE = mat.getCol1().getX(); + mF = mat.getCol1().getY(); + mG = mat.getCol1().getZ(); + mH = mat.getCol1().getW(); + mI = mat.getCol2().getX(); + mJ = mat.getCol2().getY(); + mK = mat.getCol2().getZ(); + mL = mat.getCol2().getW(); + mM = mat.getCol3().getX(); + mN = mat.getCol3().getY(); + mO = mat.getCol3().getZ(); + mP = mat.getCol3().getW(); + tmp0 = ( ( mK * mD ) - ( mC * mL ) ); + tmp1 = ( ( mO * mH ) - ( mG * mP ) ); + tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); + tmp3 = ( ( mF * mO ) - ( mN * mG ) ); + tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); + tmp5 = ( ( mN * mH ) - ( mF * mP ) ); + dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); + dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); + dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); + dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); + return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); +} + +inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +inline const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +inline const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::operator *( float scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +inline Matrix4 & Matrix4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), + ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), + ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), + ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const +{ + return Vector4( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), + ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ); +} + +inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const +{ + return Vector4( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), + ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) + ); +} + +inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +inline const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +inline const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +inline const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +inline const Matrix4 Matrix4::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4::xAxis( ), + Vector4( 0.0f, c, s, 0.0f ), + Vector4( 0.0f, -s, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, 0.0f, -s, 0.0f ), + Vector4::yAxis( ), + Vector4( s, 0.0f, c, 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Matrix4( + Vector4( c, s, 0.0f, 0.0f ), + Vector4( -s, c, 0.0f, 0.0f ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Matrix4( + Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), + Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), + Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) +{ + float x, y, z, s, c, oneMinusC, xy, yz, zx; + s = sinf( radians ); + c = cosf( radians ); + x = unitVec.getX(); + y = unitVec.getY(); + z = unitVec.getZ(); + xy = ( x * y ); + yz = ( y * z ); + zx = ( z * x ); + oneMinusC = ( 1.0f - c ); + return Matrix4( + Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), + Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), + Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) +{ + return Matrix4( + Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), + Vector4::wAxis( ) + ); +} + +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); + rangeInv = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, f, 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + n2 = ( zNear + zNear ); + return Matrix4( + Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), + Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), + Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) + ); +} + +inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; + sum_rl = ( right + left ); + sum_tb = ( top + bottom ); + sum_nf = ( zNear + zFar ); + inv_rl = ( 1.0f / ( right - left ) ); + inv_tb = ( 1.0f / ( top - bottom ) ); + inv_nf = ( 1.0f / ( zNear - zFar ) ); + return Matrix4( + Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), + Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), + Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), + Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) + ); +} + +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +inline void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +inline Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +inline Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) +{ + mCol0 = _col0; + return *this; +} + +inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) +{ + mCol1 = _col1; + return *this; +} + +inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) +{ + mCol2 = _col2; + return *this; +} + +inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) +{ + mCol3 = _col3; + return *this; +} + +inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +inline Transform3 & Transform3::setElem( int col, int row, float val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +inline float Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +inline const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +inline const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +inline const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +inline const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +inline const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +inline const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +inline Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +inline const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +inline const Transform3 inverse( const Transform3 & tfrm ) +{ + Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; + float detinv; + tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); + tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); + tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); + detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); + inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); + inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); + inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + Vector3 inv0, inv1, inv2; + inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); + inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); + inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); + return Transform3( + inv0, + inv1, + inv2, + Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) + ); +} + +inline const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +inline const Vector3 Transform3::operator *( const Vector3 & vec ) const +{ + return Vector3( + ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), + ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), + ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ); +} + +inline const Point3 Transform3::operator *( const Point3 & pnt ) const +{ + return Point3( + ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), + ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), + ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) + ); +} + +inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +inline const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +inline const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +inline const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +inline const Transform3 Transform3::rotationX( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3::xAxis( ), + Vector3( 0.0f, c, s ), + Vector3( 0.0f, -s, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationY( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, 0.0f, -s ), + Vector3::yAxis( ), + Vector3( s, 0.0f, c ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZ( float radians ) +{ + float s, c; + s = sinf( radians ); + c = cosf( radians ); + return Transform3( + Vector3( c, s, 0.0f ), + Vector3( -s, c, 0.0f ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) +{ + float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; + sX = sinf( radiansXYZ.getX() ); + cX = cosf( radiansXYZ.getX() ); + sY = sinf( radiansXYZ.getY() ); + cY = cosf( radiansXYZ.getY() ); + sZ = sinf( radiansXYZ.getZ() ); + cZ = cosf( radiansXYZ.getZ() ); + tmp0 = ( cZ * sY ); + tmp1 = ( sZ * sY ); + return Transform3( + Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), + Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), + Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::rotation( const Quat & unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) +{ + return Transform3( + Vector3( scaleVec.getX(), 0.0f, 0.0f ), + Vector3( 0.0f, scaleVec.getY(), 0.0f ), + Vector3( 0.0f, 0.0f, scaleVec.getZ() ), + Vector3( 0.0f ) + ); +} + +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +inline const Transform3 Transform3::translation( const Vector3 & translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +inline void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +inline Quat::Quat( const Matrix3 & tfrm ) +{ + float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; + int negTrace, ZgtX, ZgtY, YgtX; + int largestXorY, largestYorZ, largestZorX; + + xx = tfrm.getCol0().getX(); + yx = tfrm.getCol0().getY(); + zx = tfrm.getCol0().getZ(); + xy = tfrm.getCol1().getX(); + yy = tfrm.getCol1().getY(); + zy = tfrm.getCol1().getZ(); + xz = tfrm.getCol2().getX(); + yz = tfrm.getCol2().getY(); + zz = tfrm.getCol2().getZ(); + + trace = ( ( xx + yy ) + zz ); + + negTrace = ( trace < 0.0f ); + ZgtX = zz > xx; + ZgtY = zz > yy; + YgtX = yy > xx; + largestXorY = ( !ZgtX || !ZgtY ) && negTrace; + largestYorZ = ( YgtX || ZgtX ) && negTrace; + largestZorX = ( ZgtY || !YgtX ) && negTrace; + + if ( largestXorY ) + { + zz = -zz; + xy = -xy; + } + if ( largestYorZ ) + { + xx = -xx; + yz = -yz; + } + if ( largestZorX ) + { + yy = -yy; + zx = -zx; + } + + radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); + scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); + + tmpx = ( ( zy - yz ) * scale ); + tmpy = ( ( xz - zx ) * scale ); + tmpz = ( ( yx - xy ) * scale ); + tmpw = ( radicand * scale ); + qx = tmpx; + qy = tmpy; + qz = tmpz; + qw = tmpw; + + if ( largestXorY ) + { + qx = tmpw; + qy = tmpz; + qz = tmpy; + qw = tmpx; + } + if ( largestYorZ ) + { + tmpx = qx; + tmpz = qz; + qx = qy; + qy = tmpx; + qz = qw; + qw = tmpz; + } + + mX = qx; + mY = qy; + mZ = qz; + mW = qw; +} + +inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Vector3( + ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), + ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), + ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) + ); +} + +inline const Matrix3 crossMatrix( const Vector3 & vec ) +{ + return Matrix3( + Vector3( 0.0f, vec.getZ(), -vec.getY() ), + Vector3( -vec.getZ(), 0.0f, vec.getX() ), + Vector3( vec.getY(), -vec.getX(), 0.0f ) + ); +} + +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/scalar/quat_aos.h b/Code/Physics/src/vectormath/scalar/quat_aos.h new file mode 100644 index 00000000..764e0170 --- /dev/null +++ b/Code/Physics/src/vectormath/scalar/quat_aos.h @@ -0,0 +1,433 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Quat::Quat( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; +} + +inline Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Quat::Quat( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Quat::Quat( const Vector4 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = vec.getW(); +} + +inline Quat::Quat( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Quat Quat::identity( ) +{ + return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) +{ + Quat start; + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitQuat0, unitQuat1 ); + if ( cosAngle < 0.0f ) { + cosAngle = -cosAngle; + start = ( -unitQuat0 ); + } else { + start = unitQuat0; + } + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); +} + +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) +{ + Quat tmp0, tmp1; + tmp0 = slerp( t, unitQuat0, unitQuat3 ); + tmp1 = slerp( t, unitQuat1, unitQuat2 ); + return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); +} + +inline void loadXYZW( Quat & quat, const float * fptr ) +{ + quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Quat & quat, float * fptr ) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +} + +inline Quat & Quat::operator =( const Quat & quat ) +{ + mX = quat.mX; + mY = quat.mY; + mZ = quat.mZ; + mW = quat.mW; + return *this; +} + +inline Quat & Quat::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Quat & Quat::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Quat::getX( ) const +{ + return mX; +} + +inline Quat & Quat::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Quat::getY( ) const +{ + return mY; +} + +inline Quat & Quat::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Quat::getZ( ) const +{ + return mZ; +} + +inline Quat & Quat::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Quat::getW( ) const +{ + return mW; +} + +inline Quat & Quat::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Quat::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Quat::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Quat::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Quat Quat::operator +( const Quat & quat ) const +{ + return Quat( + ( mX + quat.mX ), + ( mY + quat.mY ), + ( mZ + quat.mZ ), + ( mW + quat.mW ) + ); +} + +inline const Quat Quat::operator -( const Quat & quat ) const +{ + return Quat( + ( mX - quat.mX ), + ( mY - quat.mY ), + ( mZ - quat.mZ ), + ( mW - quat.mW ) + ); +} + +inline const Quat Quat::operator *( float scalar ) const +{ + return Quat( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Quat & Quat::operator +=( const Quat & quat ) +{ + *this = *this + quat; + return *this; +} + +inline Quat & Quat::operator -=( const Quat & quat ) +{ + *this = *this - quat; + return *this; +} + +inline Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Quat Quat::operator /( float scalar ) const +{ + return Quat( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Quat Quat::operator -( ) const +{ + return Quat( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Quat operator *( float scalar, const Quat & quat ) +{ + return quat * scalar; +} + +inline float dot( const Quat & quat0, const Quat & quat1 ) +{ + float result; + result = ( quat0.getX() * quat1.getX() ); + result = ( result + ( quat0.getY() * quat1.getY() ) ); + result = ( result + ( quat0.getZ() * quat1.getZ() ) ); + result = ( result + ( quat0.getW() * quat1.getW() ) ); + return result; +} + +inline float norm( const Quat & quat ) +{ + float result; + result = ( quat.getX() * quat.getX() ); + result = ( result + ( quat.getY() * quat.getY() ) ); + result = ( result + ( quat.getZ() * quat.getZ() ) ); + result = ( result + ( quat.getW() * quat.getW() ) ); + return result; +} + +inline float length( const Quat & quat ) +{ + return ::sqrtf( norm( quat ) ); +} + +inline const Quat normalize( const Quat & quat ) +{ + float lenSqr, lenInv; + lenSqr = norm( quat ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Quat( + ( quat.getX() * lenInv ), + ( quat.getY() * lenInv ), + ( quat.getZ() * lenInv ), + ( quat.getW() * lenInv ) + ); +} + +inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float cosHalfAngleX2, recipCosHalfAngleX2; + cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); + recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); + return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); +} + +inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( ( unitVec * s ), c ); +} + +inline const Quat Quat::rotationX( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( s, 0.0f, 0.0f, c ); +} + +inline const Quat Quat::rotationY( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, s, 0.0f, c ); +} + +inline const Quat Quat::rotationZ( float radians ) +{ + float s, c, angle; + angle = ( radians * 0.5f ); + s = sinf( angle ); + c = cosf( angle ); + return Quat( 0.0f, 0.0f, s, c ); +} + +inline const Quat Quat::operator *( const Quat & quat ) const +{ + return Quat( + ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), + ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), + ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), + ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) + ); +} + +inline Quat & Quat::operator *=( const Quat & quat ) +{ + *this = *this * quat; + return *this; +} + +inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) +{ + float tmpX, tmpY, tmpZ, tmpW; + tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); + tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); + tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); + tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); + return Vector3( + ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), + ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), + ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) + ); +} + +inline const Quat conj( const Quat & quat ) +{ + return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); +} + +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) +{ + return Quat( + ( select1 )? quat1.getX() : quat0.getX(), + ( select1 )? quat1.getY() : quat0.getY(), + ( select1 )? quat1.getZ() : quat0.getZ(), + ( select1 )? quat1.getW() : quat0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Quat & quat ) +{ + printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +inline void print( const Quat & quat, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/scalar/vec_aos.h b/Code/Physics/src/vectormath/scalar/vec_aos.h new file mode 100644 index 00000000..46d4d6b3 --- /dev/null +++ b/Code/Physics/src/vectormath/scalar/vec_aos.h @@ -0,0 +1,1426 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants + +#define _VECTORMATH_SLERP_TOL 0.999f + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +inline Vector3::Vector3( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; +} + +inline Vector3::Vector3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Vector3::Vector3( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); +} + +inline Vector3::Vector3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Vector3 Vector3::xAxis( ) +{ + return Vector3( 1.0f, 0.0f, 0.0f ); +} + +inline const Vector3 Vector3::yAxis( ) +{ + return Vector3( 0.0f, 1.0f, 0.0f ); +} + +inline const Vector3 Vector3::zAxis( ) +{ + return Vector3( 0.0f, 0.0f, 1.0f ); +} + +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZ( Vector3 & vec, const float * fptr ) +{ + vec = Vector3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Vector3 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector3 & Vector3::operator =( const Vector3 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + return *this; +} + +inline Vector3 & Vector3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector3::getX( ) const +{ + return mX; +} + +inline Vector3 & Vector3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector3::getY( ) const +{ + return mY; +} + +inline Vector3 & Vector3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector3::getZ( ) const +{ + return mZ; +} + +inline Vector3 & Vector3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Vector3::operator +( const Vector3 & vec ) const +{ + return Vector3( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ) + ); +} + +inline const Vector3 Vector3::operator -( const Vector3 & vec ) const +{ + return Vector3( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ) + ); +} + +inline const Point3 Vector3::operator +( const Point3 & pnt ) const +{ + return Point3( + ( mX + pnt.getX() ), + ( mY + pnt.getY() ), + ( mZ + pnt.getZ() ) + ); +} + +inline const Vector3 Vector3::operator *( float scalar ) const +{ + return Vector3( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ) + ); +} + +inline Vector3 & Vector3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector3 & Vector3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector3 Vector3::operator /( float scalar ) const +{ + return Vector3( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ) + ); +} + +inline Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector3 Vector3::operator -( ) const +{ + return Vector3( + -mX, + -mY, + -mZ + ); +} + +inline const Vector3 operator *( float scalar, const Vector3 & vec ) +{ + return vec * scalar; +} + +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ) + ); +} + +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ) + ); +} + +inline const Vector3 recipPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ) + ); +} + +inline const Vector3 sqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ) + ); +} + +inline const Vector3 rsqrtPerElem( const Vector3 & vec ) +{ + return Vector3( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ) + ); +} + +inline const Vector3 absPerElem( const Vector3 & vec ) +{ + return Vector3( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ) + ); +} + +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) + ); +} + +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float maxElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + return result; +} + +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() + ); +} + +inline float minElem( const Vector3 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + return result; +} + +inline float sum( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + return result; +} + +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + return result; +} + +inline float lengthSqr( const Vector3 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + return result; +} + +inline float length( const Vector3 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector3 normalize( const Vector3 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector3( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ) + ); +} + +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) +{ + return Vector3( + ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), + ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), + ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) + ); +} + +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) +{ + return Vector3( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector3 & vec ) +{ + printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); +} + +inline void print( const Vector3 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); +} + +#endif + +inline Vector4::Vector4( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; +} + +inline Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mX = _x; + mY = _y; + mZ = _z; + mW = _w; +} + +inline Vector4::Vector4( const Vector3 & xyz, float _w ) +{ + this->setXYZ( xyz ); + this->setW( _w ); +} + +inline Vector4::Vector4( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + mW = 0.0f; +} + +inline Vector4::Vector4( const Point3 & pnt ) +{ + mX = pnt.getX(); + mY = pnt.getY(); + mZ = pnt.getZ(); + mW = 1.0f; +} + +inline Vector4::Vector4( const Quat & quat ) +{ + mX = quat.getX(); + mY = quat.getY(); + mZ = quat.getZ(); + mW = quat.getW(); +} + +inline Vector4::Vector4( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; + mW = scalar; +} + +inline const Vector4 Vector4::xAxis( ) +{ + return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::yAxis( ) +{ + return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); +} + +inline const Vector4 Vector4::zAxis( ) +{ + return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); +} + +inline const Vector4 Vector4::wAxis( ) +{ + return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); +} + +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) +{ + float recipSinAngle, scale0, scale1, cosAngle, angle; + cosAngle = dot( unitVec0, unitVec1 ); + if ( cosAngle < _VECTORMATH_SLERP_TOL ) { + angle = acosf( cosAngle ); + recipSinAngle = ( 1.0f / sinf( angle ) ); + scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); + scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); + } else { + scale0 = ( 1.0f - t ); + scale1 = t; + } + return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); +} + +inline void loadXYZW( Vector4 & vec, const float * fptr ) +{ + vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); +} + +inline void storeXYZW( const Vector4 & vec, float * fptr ) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); + fptr[3] = vec.getW(); +} + +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 4; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Vector4 & Vector4::operator =( const Vector4 & vec ) +{ + mX = vec.mX; + mY = vec.mY; + mZ = vec.mZ; + mW = vec.mW; + return *this; +} + +inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); + return *this; +} + +inline const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mX, mY, mZ ); +} + +inline Vector4 & Vector4::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Vector4::getX( ) const +{ + return mX; +} + +inline Vector4 & Vector4::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Vector4::getY( ) const +{ + return mY; +} + +inline Vector4 & Vector4::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Vector4::getZ( ) const +{ + return mZ; +} + +inline Vector4 & Vector4::setW( float _w ) +{ + mW = _w; + return *this; +} + +inline float Vector4::getW( ) const +{ + return mW; +} + +inline Vector4 & Vector4::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Vector4::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Vector4::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Vector4::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector4 Vector4::operator +( const Vector4 & vec ) const +{ + return Vector4( + ( mX + vec.mX ), + ( mY + vec.mY ), + ( mZ + vec.mZ ), + ( mW + vec.mW ) + ); +} + +inline const Vector4 Vector4::operator -( const Vector4 & vec ) const +{ + return Vector4( + ( mX - vec.mX ), + ( mY - vec.mY ), + ( mZ - vec.mZ ), + ( mW - vec.mW ) + ); +} + +inline const Vector4 Vector4::operator *( float scalar ) const +{ + return Vector4( + ( mX * scalar ), + ( mY * scalar ), + ( mZ * scalar ), + ( mW * scalar ) + ); +} + +inline Vector4 & Vector4::operator +=( const Vector4 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Vector4 & Vector4::operator -=( const Vector4 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +inline const Vector4 Vector4::operator /( float scalar ) const +{ + return Vector4( + ( mX / scalar ), + ( mY / scalar ), + ( mZ / scalar ), + ( mW / scalar ) + ); +} + +inline Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +inline const Vector4 Vector4::operator -( ) const +{ + return Vector4( + -mX, + -mY, + -mZ, + -mW + ); +} + +inline const Vector4 operator *( float scalar, const Vector4 & vec ) +{ + return vec * scalar; +} + +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() * vec1.getX() ), + ( vec0.getY() * vec1.getY() ), + ( vec0.getZ() * vec1.getZ() ), + ( vec0.getW() * vec1.getW() ) + ); +} + +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec0.getX() / vec1.getX() ), + ( vec0.getY() / vec1.getY() ), + ( vec0.getZ() / vec1.getZ() ), + ( vec0.getW() / vec1.getW() ) + ); +} + +inline const Vector4 recipPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / vec.getX() ), + ( 1.0f / vec.getY() ), + ( 1.0f / vec.getZ() ), + ( 1.0f / vec.getW() ) + ); +} + +inline const Vector4 sqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + sqrtf( vec.getX() ), + sqrtf( vec.getY() ), + sqrtf( vec.getZ() ), + sqrtf( vec.getW() ) + ); +} + +inline const Vector4 rsqrtPerElem( const Vector4 & vec ) +{ + return Vector4( + ( 1.0f / sqrtf( vec.getX() ) ), + ( 1.0f / sqrtf( vec.getY() ) ), + ( 1.0f / sqrtf( vec.getZ() ) ), + ( 1.0f / sqrtf( vec.getW() ) ) + ); +} + +inline const Vector4 absPerElem( const Vector4 & vec ) +{ + return Vector4( + fabsf( vec.getX() ), + fabsf( vec.getY() ), + fabsf( vec.getZ() ), + fabsf( vec.getW() ) + ); +} + +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), + ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), + ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), + ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) + ); +} + +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float maxElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() > result)? vec.getZ() : result; + result = (vec.getW() > result)? vec.getW() : result; + return result; +} + +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) +{ + return Vector4( + (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), + (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), + (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), + (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() + ); +} + +inline float minElem( const Vector4 & vec ) +{ + float result; + result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); + result = (vec.getZ() < result)? vec.getZ() : result; + result = (vec.getW() < result)? vec.getW() : result; + return result; +} + +inline float sum( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() + vec.getY() ); + result = ( result + vec.getZ() ); + result = ( result + vec.getW() ); + return result; +} + +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) +{ + float result; + result = ( vec0.getX() * vec1.getX() ); + result = ( result + ( vec0.getY() * vec1.getY() ) ); + result = ( result + ( vec0.getZ() * vec1.getZ() ) ); + result = ( result + ( vec0.getW() * vec1.getW() ) ); + return result; +} + +inline float lengthSqr( const Vector4 & vec ) +{ + float result; + result = ( vec.getX() * vec.getX() ); + result = ( result + ( vec.getY() * vec.getY() ) ); + result = ( result + ( vec.getZ() * vec.getZ() ) ); + result = ( result + ( vec.getW() * vec.getW() ) ); + return result; +} + +inline float length( const Vector4 & vec ) +{ + return ::sqrtf( lengthSqr( vec ) ); +} + +inline const Vector4 normalize( const Vector4 & vec ) +{ + float lenSqr, lenInv; + lenSqr = lengthSqr( vec ); + lenInv = ( 1.0f / sqrtf( lenSqr ) ); + return Vector4( + ( vec.getX() * lenInv ), + ( vec.getY() * lenInv ), + ( vec.getZ() * lenInv ), + ( vec.getW() * lenInv ) + ); +} + +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) +{ + return Vector4( + ( select1 )? vec1.getX() : vec0.getX(), + ( select1 )? vec1.getY() : vec0.getY(), + ( select1 )? vec1.getZ() : vec0.getZ(), + ( select1 )? vec1.getW() : vec0.getW() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Vector4 & vec ) +{ + printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +inline void print( const Vector4 & vec, const char * name ) +{ + printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); +} + +#endif + +inline Point3::Point3( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; +} + +inline Point3::Point3( float _x, float _y, float _z ) +{ + mX = _x; + mY = _y; + mZ = _z; +} + +inline Point3::Point3( const Vector3 & vec ) +{ + mX = vec.getX(); + mY = vec.getY(); + mZ = vec.getZ(); +} + +inline Point3::Point3( float scalar ) +{ + mX = scalar; + mY = scalar; + mZ = scalar; +} + +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +inline void loadXYZ( Point3 & pnt, const float * fptr ) +{ + pnt = Point3( fptr[0], fptr[1], fptr[2] ); +} + +inline void storeXYZ( const Point3 & pnt, float * fptr ) +{ + fptr[0] = pnt.getX(); + fptr[1] = pnt.getY(); + fptr[2] = pnt.getZ(); +} + +inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + unsigned short fp16 = hfptr[i]; + unsigned int sign = fp16 >> 15; + unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); + unsigned int mantissa = fp16 & ((1 << 10) - 1); + + if (exponent == 0) { + // zero + mantissa = 0; + + } else if (exponent == 31) { + // infinity or nan -> infinity + exponent = 255; + mantissa = 0; + + } else { + exponent += 127 - 15; + mantissa <<= 13; + } + + Data32 d; + d.u32 = (sign << 31) | (exponent << 23) | mantissa; + vec[i] = d.f32; + } +} + +inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) +{ + union Data32 { + unsigned int u32; + float f32; + }; + + for (int i = 0; i < 3; i++) { + Data32 d; + d.f32 = vec[i]; + + unsigned int sign = d.u32 >> 31; + unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); + unsigned int mantissa = d.u32 & ((1 << 23) - 1);; + + if (exponent == 0) { + // zero or denorm -> zero + mantissa = 0; + + } else if (exponent == 255 && mantissa != 0) { + // nan -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent >= 127 - 15 + 31) { + // overflow or infinity -> infinity + exponent = 31; + mantissa = 0; + + } else if (exponent <= 127 - 15) { + // underflow -> zero + exponent = 0; + mantissa = 0; + + } else { + exponent -= 127 - 15; + mantissa >>= 13; + } + + hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); + } +} + +inline Point3 & Point3::operator =( const Point3 & pnt ) +{ + mX = pnt.mX; + mY = pnt.mY; + mZ = pnt.mZ; + return *this; +} + +inline Point3 & Point3::setX( float _x ) +{ + mX = _x; + return *this; +} + +inline float Point3::getX( ) const +{ + return mX; +} + +inline Point3 & Point3::setY( float _y ) +{ + mY = _y; + return *this; +} + +inline float Point3::getY( ) const +{ + return mY; +} + +inline Point3 & Point3::setZ( float _z ) +{ + mZ = _z; + return *this; +} + +inline float Point3::getZ( ) const +{ + return mZ; +} + +inline Point3 & Point3::setElem( int idx, float value ) +{ + *(&mX + idx) = value; + return *this; +} + +inline float Point3::getElem( int idx ) const +{ + return *(&mX + idx); +} + +inline float & Point3::operator []( int idx ) +{ + return *(&mX + idx); +} + +inline float Point3::operator []( int idx ) const +{ + return *(&mX + idx); +} + +inline const Vector3 Point3::operator -( const Point3 & pnt ) const +{ + return Vector3( + ( mX - pnt.mX ), + ( mY - pnt.mY ), + ( mZ - pnt.mZ ) + ); +} + +inline const Point3 Point3::operator +( const Vector3 & vec ) const +{ + return Point3( + ( mX + vec.getX() ), + ( mY + vec.getY() ), + ( mZ + vec.getZ() ) + ); +} + +inline const Point3 Point3::operator -( const Vector3 & vec ) const +{ + return Point3( + ( mX - vec.getX() ), + ( mY - vec.getY() ), + ( mZ - vec.getZ() ) + ); +} + +inline Point3 & Point3::operator +=( const Vector3 & vec ) +{ + *this = *this + vec; + return *this; +} + +inline Point3 & Point3::operator -=( const Vector3 & vec ) +{ + *this = *this - vec; + return *this; +} + +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() * pnt1.getX() ), + ( pnt0.getY() * pnt1.getY() ), + ( pnt0.getZ() * pnt1.getZ() ) + ); +} + +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt0.getX() / pnt1.getX() ), + ( pnt0.getY() / pnt1.getY() ), + ( pnt0.getZ() / pnt1.getZ() ) + ); +} + +inline const Point3 recipPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / pnt.getX() ), + ( 1.0f / pnt.getY() ), + ( 1.0f / pnt.getZ() ) + ); +} + +inline const Point3 sqrtPerElem( const Point3 & pnt ) +{ + return Point3( + sqrtf( pnt.getX() ), + sqrtf( pnt.getY() ), + sqrtf( pnt.getZ() ) + ); +} + +inline const Point3 rsqrtPerElem( const Point3 & pnt ) +{ + return Point3( + ( 1.0f / sqrtf( pnt.getX() ) ), + ( 1.0f / sqrtf( pnt.getY() ) ), + ( 1.0f / sqrtf( pnt.getZ() ) ) + ); +} + +inline const Point3 absPerElem( const Point3 & pnt ) +{ + return Point3( + fabsf( pnt.getX() ), + fabsf( pnt.getY() ), + fabsf( pnt.getZ() ) + ); +} + +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), + ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), + ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) + ); +} + +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float maxElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() > result)? pnt.getZ() : result; + return result; +} + +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return Point3( + (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), + (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), + (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() + ); +} + +inline float minElem( const Point3 & pnt ) +{ + float result; + result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); + result = (pnt.getZ() < result)? pnt.getZ() : result; + return result; +} + +inline float sum( const Point3 & pnt ) +{ + float result; + result = ( pnt.getX() + pnt.getY() ); + result = ( result + pnt.getZ() ); + return result; +} + +inline const Point3 scale( const Point3 & pnt, float scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +inline float projection( const Point3 & pnt, const Vector3 & unitVec ) +{ + float result; + result = ( pnt.getX() * unitVec.getX() ); + result = ( result + ( pnt.getY() * unitVec.getY() ) ); + result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); + return result; +} + +inline float distSqrFromOrigin( const Point3 & pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +inline float distFromOrigin( const Point3 & pnt ) +{ + return length( Vector3( pnt ) ); +} + +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) +{ + return Point3( + ( select1 )? pnt1.getX() : pnt0.getX(), + ( select1 )? pnt1.getY() : pnt0.getY(), + ( select1 )? pnt1.getZ() : pnt0.getZ() + ); +} + +#ifdef _VECTORMATH_DEBUG + +inline void print( const Point3 & pnt ) +{ + printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +inline void print( const Point3 & pnt, const char * name ) +{ + printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/scalar/vectormath_aos.h b/Code/Physics/src/vectormath/scalar/vectormath_aos.h new file mode 100644 index 00000000..d00456df --- /dev/null +++ b/Code/Physics/src/vectormath/scalar/vectormath_aos.h @@ -0,0 +1,1872 @@ +/* + Copyright (C) 2009 Sony Computer Entertainment Inc. + All rights reserved. + +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 _VECTORMATH_AOS_CPP_H +#define _VECTORMATH_AOS_CPP_H + +#include + +#ifdef _VECTORMATH_DEBUG +#include +#endif + +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Vector3( ) { }; + + // Copy a 3-D vector + // + inline Vector3( const Vector3 & vec ); + + // Construct a 3-D vector from x, y, and z elements + // + inline Vector3( float x, float y, float z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit inline Vector3( const Point3 & pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit inline Vector3( float scalar ); + + // Assign one 3-D vector to another + // + inline Vector3 & operator =( const Vector3 & vec ); + + // Set the x element of a 3-D vector + // + inline Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + inline Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + inline Vector3 & setZ( float z ); + + // Get the x element of a 3-D vector + // + inline float getX( ) const; + + // Get the y element of a 3-D vector + // + inline float getY( ) const; + + // Get the z element of a 3-D vector + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + inline Vector3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 3-D vectors + // + inline const Vector3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + inline const Vector3 operator -( const Vector3 & vec ) const; + + // Add a 3-D vector to a 3-D point + // + inline const Point3 operator +( const Point3 & pnt ) const; + + // Multiply a 3-D vector by a scalar + // + inline const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + inline const Vector3 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Vector3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Vector3 & operator -=( const Vector3 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector3 & operator /=( float scalar ); + + // Negate all elements of a 3-D vector + // + inline const Vector3 operator -( ) const; + + // Construct x axis + // + static inline const Vector3 xAxis( ); + + // Construct y axis + // + static inline const Vector3 yAxis( ); + + // Construct z axis + // + static inline const Vector3 zAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 3-D vector by a scalar +// +inline const Vector3 operator *( float scalar, const Vector3 & vec ); + +// Multiply two 3-D vectors per element +// +inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector3 recipPerElem( const Vector3 & vec ); + +// Compute the square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector3 sqrtPerElem( const Vector3 & vec ); + +// Compute the reciprocal square root of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector3 rsqrtPerElem( const Vector3 & vec ); + +// Compute the absolute value of a 3-D vector per element +// +inline const Vector3 absPerElem( const Vector3 & vec ); + +// Copy sign from one 3-D vector to another, per element +// +inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum of two 3-D vectors per element +// +inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Minimum of two 3-D vectors per element +// +inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); + +// Maximum element of a 3-D vector +// +inline float maxElem( const Vector3 & vec ); + +// Minimum element of a 3-D vector +// +inline float minElem( const Vector3 & vec ); + +// Compute the sum of all elements of a 3-D vector +// +inline float sum( const Vector3 & vec ); + +// Compute the dot product of two 3-D vectors +// +inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); + +// Compute the square of the length of a 3-D vector +// +inline float lengthSqr( const Vector3 & vec ); + +// Compute the length of a 3-D vector +// +inline float length( const Vector3 & vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector3 normalize( const Vector3 & vec ); + +// Compute cross product of two 3-D vectors +// +inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); + +// Outer product of two 3-D vectors +// +inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// +inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +inline const Matrix3 crossMatrix( const Vector3 & vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); + +// Conditionally select between two 3-D vectors +// +inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Vector3 & vec, const float * fptr ); + +// Store x, y, and z elements of a 3-D vector in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Vector3 & vec, float * fptr ); + +// Load three-half-floats as a 3-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); + +// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector3 & vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Vector4( ) { }; + + // Copy a 4-D vector + // + inline Vector4( const Vector4 & vec ); + + // Construct a 4-D vector from x, y, z, and w elements + // + inline Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + inline Vector4( const Vector3 & xyz, float w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit inline Vector4( const Vector3 & vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit inline Vector4( const Point3 & pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit inline Vector4( const Quat & quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit inline Vector4( float scalar ); + + // Assign one 4-D vector to another + // + inline Vector4 & operator =( const Vector4 & vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + inline Vector4 & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a 4-D vector + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + inline Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + inline Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + inline Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + inline Vector4 & setW( float w ); + + // Get the x element of a 4-D vector + // + inline float getX( ) const; + + // Get the y element of a 4-D vector + // + inline float getY( ) const; + + // Get the z element of a 4-D vector + // + inline float getZ( ) const; + + // Get the w element of a 4-D vector + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + inline Vector4 & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two 4-D vectors + // + inline const Vector4 operator +( const Vector4 & vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + inline const Vector4 operator -( const Vector4 & vec ) const; + + // Multiply a 4-D vector by a scalar + // + inline const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + inline const Vector4 operator /( float scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + inline Vector4 & operator +=( const Vector4 & vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + inline Vector4 & operator -=( const Vector4 & vec ); + + // Perform compound assignment and multiplication by a scalar + // + inline Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Vector4 & operator /=( float scalar ); + + // Negate all elements of a 4-D vector + // + inline const Vector4 operator -( ) const; + + // Construct x axis + // + static inline const Vector4 xAxis( ); + + // Construct y axis + // + static inline const Vector4 yAxis( ); + + // Construct z axis + // + static inline const Vector4 zAxis( ); + + // Construct w axis + // + static inline const Vector4 wAxis( ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a 4-D vector by a scalar +// +inline const Vector4 operator *( float scalar, const Vector4 & vec ); + +// Multiply two 4-D vectors per element +// +inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Vector4 recipPerElem( const Vector4 & vec ); + +// Compute the square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Vector4 sqrtPerElem( const Vector4 & vec ); + +// Compute the reciprocal square root of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Vector4 rsqrtPerElem( const Vector4 & vec ); + +// Compute the absolute value of a 4-D vector per element +// +inline const Vector4 absPerElem( const Vector4 & vec ); + +// Copy sign from one 4-D vector to another, per element +// +inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum of two 4-D vectors per element +// +inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Minimum of two 4-D vectors per element +// +inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); + +// Maximum element of a 4-D vector +// +inline float maxElem( const Vector4 & vec ); + +// Minimum element of a 4-D vector +// +inline float minElem( const Vector4 & vec ); + +// Compute the sum of all elements of a 4-D vector +// +inline float sum( const Vector4 & vec ); + +// Compute the dot product of two 4-D vectors +// +inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); + +// Compute the square of the length of a 4-D vector +// +inline float lengthSqr( const Vector4 & vec ); + +// Compute the length of a 4-D vector +// +inline float length( const Vector4 & vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +inline const Vector4 normalize( const Vector4 & vec ); + +// Outer product of two 4-D vectors +// +inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); + +// Conditionally select between two 4-D vectors +// +inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Vector4 & vec, const float * fptr ); + +// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Vector4 & vec, float * fptr ); + +// Load four-half-floats as a 4-D vector +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); + +// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Vector4 & vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + float mX; + float mY; + float mZ; +#ifndef __GNUC__ + float d; +#endif + +public: + // Default constructor; does no initialization + // + inline Point3( ) { }; + + // Copy a 3-D point + // + inline Point3( const Point3 & pnt ); + + // Construct a 3-D point from x, y, and z elements + // + inline Point3( float x, float y, float z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit inline Point3( const Vector3 & vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit inline Point3( float scalar ); + + // Assign one 3-D point to another + // + inline Point3 & operator =( const Point3 & pnt ); + + // Set the x element of a 3-D point + // + inline Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + inline Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + inline Point3 & setZ( float z ); + + // Get the x element of a 3-D point + // + inline float getX( ) const; + + // Get the y element of a 3-D point + // + inline float getY( ) const; + + // Get the z element of a 3-D point + // + inline float getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + inline Point3 & setElem( int idx, float value ); + + // Get an x, y, or z element of a 3-D point by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + inline const Vector3 operator -( const Point3 & pnt ) const; + + // Add a 3-D point to a 3-D vector + // + inline const Point3 operator +( const Vector3 & vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + inline const Point3 operator -( const Vector3 & vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + inline Point3 & operator +=( const Vector3 & vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + inline Point3 & operator -=( const Vector3 & vec ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply two 3-D points per element +// +inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +inline const Point3 recipPerElem( const Point3 & pnt ); + +// Compute the square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function sqrtf4. +// +inline const Point3 sqrtPerElem( const Point3 & pnt ); + +// Compute the reciprocal square root of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function rsqrtf4. +// +inline const Point3 rsqrtPerElem( const Point3 & pnt ); + +// Compute the absolute value of a 3-D point per element +// +inline const Point3 absPerElem( const Point3 & pnt ); + +// Copy sign from one 3-D point to another, per element +// +inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum of two 3-D points per element +// +inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Minimum of two 3-D points per element +// +inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); + +// Maximum element of a 3-D point +// +inline float maxElem( const Point3 & pnt ); + +// Minimum element of a 3-D point +// +inline float minElem( const Point3 & pnt ); + +// Compute the sum of all elements of a 3-D point +// +inline float sum( const Point3 & pnt ); + +// Apply uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, float scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +inline float projection( const Point3 & pnt, const Vector3 & unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +inline float distSqrFromOrigin( const Point3 & pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +inline float distFromOrigin( const Point3 & pnt ); + +// Compute the square of the distance between two 3-D points +// +inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); + +// Compute the distance between two 3-D points +// +inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); + +// Conditionally select between two 3-D points +// +inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); + +// Load x, y, and z elements from the first three words of a float array. +// +// +inline void loadXYZ( Point3 & pnt, const float * fptr ); + +// Store x, y, and z elements of a 3-D point in the first three words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZ( const Point3 & pnt, float * fptr ); + +// Load three-half-floats as a 3-D point +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. +// +inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); + +// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// NOTE: +// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. +// +inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Point3 & pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + float mX; + float mY; + float mZ; + float mW; + +public: + // Default constructor; does no initialization + // + inline Quat( ) { }; + + // Copy a quaternion + // + inline Quat( const Quat & quat ); + + // Construct a quaternion from x, y, z, and w elements + // + inline Quat( float x, float y, float z, float w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + inline Quat( const Vector3 & xyz, float w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit inline Quat( const Vector4 & vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit inline Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit inline Quat( float scalar ); + + // Assign one quaternion to another + // + inline Quat & operator =( const Quat & quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + inline Quat & setXYZ( const Vector3 & vec ); + + // Get the x, y, and z elements of a quaternion + // + inline const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + inline Quat & setX( float x ); + + // Set the y element of a quaternion + // + inline Quat & setY( float y ); + + // Set the z element of a quaternion + // + inline Quat & setZ( float z ); + + // Set the w element of a quaternion + // + inline Quat & setW( float w ); + + // Get the x element of a quaternion + // + inline float getX( ) const; + + // Get the y element of a quaternion + // + inline float getY( ) const; + + // Get the z element of a quaternion + // + inline float getZ( ) const; + + // Get the w element of a quaternion + // + inline float getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + inline Quat & setElem( int idx, float value ); + + // Get an x, y, z, or w element of a quaternion by index + // + inline float getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + inline float & operator []( int idx ); + + // Subscripting operator to get an element + // + inline float operator []( int idx ) const; + + // Add two quaternions + // + inline const Quat operator +( const Quat & quat ) const; + + // Subtract a quaternion from another quaternion + // + inline const Quat operator -( const Quat & quat ) const; + + // Multiply two quaternions + // + inline const Quat operator *( const Quat & quat ) const; + + // Multiply a quaternion by a scalar + // + inline const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + inline const Quat operator /( float scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + inline Quat & operator +=( const Quat & quat ); + + // Perform compound assignment and subtraction by a quaternion + // + inline Quat & operator -=( const Quat & quat ); + + // Perform compound assignment and multiplication by a quaternion + // + inline Quat & operator *=( const Quat & quat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + inline Quat & operator /=( float scalar ); + + // Negate all elements of a quaternion + // + inline const Quat operator -( ) const; + + // Construct an identity quaternion + // + static inline const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static inline const Quat rotation( float radians, const Vector3 & unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static inline const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static inline const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static inline const Quat rotationZ( float radians ); + +} +#ifdef __GNUC__ +__attribute__ ((aligned(16))) +#endif +; + +// Multiply a quaternion by a scalar +// +inline const Quat operator *( float scalar, const Quat & quat ); + +// Compute the conjugate of a quaternion +// +inline const Quat conj( const Quat & quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); + +// Compute the dot product of two quaternions +// +inline float dot( const Quat & quat0, const Quat & quat1 ); + +// Compute the norm of a quaternion +// +inline float norm( const Quat & quat ); + +// Compute the length of a quaternion +// +inline float length( const Quat & quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +inline const Quat normalize( const Quat & quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); + +// Spherical quadrangle interpolation +// +inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); + +// Conditionally select between two quaternions +// +inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); + +// Load x, y, z, and w elements from the first four words of a float array. +// +// +inline void loadXYZW( Quat & quat, const float * fptr ); + +// Store x, y, z, and w elements of a quaternion in the first four words of a float array. +// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed +// +inline void storeXYZW( const Quat & quat, float * fptr ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Quat & quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + inline Matrix3( ) { }; + + // Copy a 3x3 matrix + // + inline Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit inline Matrix3( const Quat & unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit inline Matrix3( float scalar ); + + // Assign one 3x3 matrix to another + // + inline Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + inline Matrix3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x3 matrix + // + inline Matrix3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x3 matrix + // + inline Matrix3 & setCol2( const Vector3 & col2 ); + + // Get column 0 of a 3x3 matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + inline const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + inline Matrix3 & setRow( int row, const Vector3 & vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + inline const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + inline Matrix3 & setElem( int col, int row, float val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + inline const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + inline const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + inline const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + inline const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply two 3x3 matrices + // + inline const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + inline Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + inline Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + inline Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static inline const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static inline const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static inline const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static inline const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix3 rotation( const Quat & unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static inline const Matrix3 scale( const Vector3 & scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +inline const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +inline const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +inline float determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// +inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + inline Matrix4( ) { }; + + // Copy a 4x4 matrix + // + inline Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit inline Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit inline Matrix4( float scalar ); + + // Assign one 4x4 matrix to another + // + inline Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + inline Matrix4 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 4x4 matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + inline Matrix4 & setCol0( const Vector4 & col0 ); + + // Set column 1 of a 4x4 matrix + // + inline Matrix4 & setCol1( const Vector4 & col1 ); + + // Set column 2 of a 4x4 matrix + // + inline Matrix4 & setCol2( const Vector4 & col2 ); + + // Set column 3 of a 4x4 matrix + // + inline Matrix4 & setCol3( const Vector4 & col3 ); + + // Get column 0 of a 4x4 matrix + // + inline const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + inline const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + inline const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + inline const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setCol( int col, const Vector4 & vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + inline Matrix4 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + inline Matrix4 & setElem( int col, int row, float val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + inline const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + inline const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + inline const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + inline const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + inline const Vector4 operator *( const Vector4 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + inline const Vector4 operator *( const Vector3 & vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + inline const Vector4 operator *( const Point3 & pnt ) const; + + // Multiply two 4x4 matrices + // + inline const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + inline const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + inline Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + inline Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + inline Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + inline Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static inline const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static inline const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static inline const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static inline const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Matrix4 rotation( const Quat & unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static inline const Matrix4 scale( const Vector3 & scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static inline const Matrix4 translation( const Vector3 & translateVec ); + + // Construct viewing matrix based on eye position, position looked at, and up direction + // + static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); + + // Construct a perspective projection matrix + // + static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +inline const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +inline const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +inline const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +inline const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +inline float determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// +inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + inline Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + inline Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit inline Transform3( float scalar ); + + // Assign one 3x4 transformation matrix to another + // + inline Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + inline const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + inline Transform3 & setTranslation( const Vector3 & translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + inline const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + inline Transform3 & setCol0( const Vector3 & col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + inline Transform3 & setCol1( const Vector3 & col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + inline Transform3 & setCol2( const Vector3 & col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + inline Transform3 & setCol3( const Vector3 & col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + inline const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + inline const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + inline const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + inline const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setCol( int col, const Vector3 & vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + inline Transform3 & setRow( int row, const Vector4 & vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + inline const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + inline Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + inline const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + inline Transform3 & setElem( int col, int row, float val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + inline float getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + inline const Vector3 operator *( const Vector3 & vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + inline const Point3 operator *( const Point3 & pnt ) const; + + // Multiply two 3x4 transformation matrices + // + inline const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + inline Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static inline const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static inline const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static inline const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static inline const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static inline const Transform3 rotation( const Quat & unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static inline const Transform3 scale( const Vector3 & scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static inline const Transform3 translation( const Vector3 & translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +inline const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +inline const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +inline const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// +inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +inline void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Code/Physics/src/vectormath/sse/boolInVec.h b/Code/Physics/src/vectormath/sse/boolInVec.h new file mode 100644 index 00000000..d21d25cb --- /dev/null +++ b/Code/Physics/src/vectormath/sse/boolInVec.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BOOLINVEC_H +#define _BOOLINVEC_H + +#include + +namespace Vectormath { + +class floatInVec; + +//-------------------------------------------------------------------------------------------------- +// boolInVec class +// + +class boolInVec +{ + private: + __m128 mData; + + inline boolInVec(__m128 vec); + public: + inline boolInVec() {} + + // matches standard type conversions + // + inline boolInVec(const floatInVec &vec); + + // explicit cast from bool + // + explicit inline boolInVec(bool scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to bool + // + inline bool getAsBool() const; +#else + // implicit cast to bool + // + inline operator bool() const; +#endif + + // get vector data + // bool value is splatted across all word slots of vector as 0 (false) or -1 (true) + // + inline __m128 get128() const; + + // operators + // + inline const boolInVec operator ! () const; + inline boolInVec& operator = (const boolInVec &vec); + inline boolInVec& operator &= (const boolInVec &vec); + inline boolInVec& operator ^= (const boolInVec &vec); + inline boolInVec& operator |= (const boolInVec &vec); + + // friend functions + // + friend inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + friend inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + friend inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// boolInVec functions +// + +// operators +// +inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); +inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// boolInVec implementation +// + +#include "floatInVec.h" + +namespace Vectormath { + +inline +boolInVec::boolInVec(__m128 vec) +{ + mData = vec; +} + +inline +boolInVec::boolInVec(const floatInVec &vec) +{ + *this = (vec != floatInVec(0.0f)); +} + +inline +boolInVec::boolInVec(bool scalar) +{ + unsigned int mask = -(int)scalar; + mData = _mm_set1_ps(*(float *)&mask); // TODO: Union +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +bool +boolInVec::getAsBool() const +#else +inline +boolInVec::operator bool() const +#endif +{ + return *(bool *)&mData; +} + +inline +__m128 +boolInVec::get128() const +{ + return mData; +} + +inline +const boolInVec +boolInVec::operator ! () const +{ + return boolInVec(_mm_andnot_ps(mData, _mm_cmpneq_ps(_mm_setzero_ps(),_mm_setzero_ps()))); +} + +inline +boolInVec& +boolInVec::operator = (const boolInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +boolInVec& +boolInVec::operator &= (const boolInVec &vec) +{ + *this = *this & vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator ^= (const boolInVec &vec) +{ + *this = *this ^ vec; + return *this; +} + +inline +boolInVec& +boolInVec::operator |= (const boolInVec &vec) +{ + *this = *this | vec; + return *this; +} + +inline +const boolInVec +operator == (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator & (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_and_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator | (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_or_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator ^ (const boolInVec &vec0, const boolInVec &vec1) +{ + return boolInVec(_mm_xor_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1) +{ + return boolInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // boolInVec_h diff --git a/Code/Physics/src/vectormath/sse/floatInVec.h b/Code/Physics/src/vectormath/sse/floatInVec.h new file mode 100644 index 00000000..e8ac5959 --- /dev/null +++ b/Code/Physics/src/vectormath/sse/floatInVec.h @@ -0,0 +1,340 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FLOATINVEC_H +#define _FLOATINVEC_H + +#include +#include + +namespace Vectormath { + +class boolInVec; + +//-------------------------------------------------------------------------------------------------- +// floatInVec class +// + +class floatInVec +{ + private: + __m128 mData; + + public: + inline floatInVec(__m128 vec); + + inline floatInVec() {} + + // matches standard type conversions + // + inline floatInVec(const boolInVec &vec); + + // construct from a slot of __m128 + // + inline floatInVec(__m128 vec, int slot); + + // explicit cast from float + // + explicit inline floatInVec(float scalar); + +#ifdef _VECTORMATH_NO_SCALAR_CAST + // explicit cast to float + // + inline float getAsFloat() const; +#else + // implicit cast to float + // + inline operator float() const; +#endif + + // get vector data + // float value is splatted across all word slots of vector + // + inline __m128 get128() const; + + // operators + // + inline const floatInVec operator ++ (int); + inline const floatInVec operator -- (int); + inline floatInVec& operator ++ (); + inline floatInVec& operator -- (); + inline const floatInVec operator - () const; + inline floatInVec& operator = (const floatInVec &vec); + inline floatInVec& operator *= (const floatInVec &vec); + inline floatInVec& operator /= (const floatInVec &vec); + inline floatInVec& operator += (const floatInVec &vec); + inline floatInVec& operator -= (const floatInVec &vec); + + // friend functions + // + friend inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); + friend inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, boolInVec select_vec1); +}; + +//-------------------------------------------------------------------------------------------------- +// floatInVec functions +// + +// operators +// +inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); +inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); +inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); + +// select between vec0 and vec1 using boolInVec. +// false selects vec0, true selects vec1 +// +inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1); + +} // namespace Vectormath + +//-------------------------------------------------------------------------------------------------- +// floatInVec implementation +// + +#include "boolInVec.h" + +namespace Vectormath { + +inline +floatInVec::floatInVec(__m128 vec) +{ + mData = vec; +} + +inline +floatInVec::floatInVec(const boolInVec &vec) +{ + mData = vec_sel(_mm_setzero_ps(), _mm_set1_ps(1.0f), vec.get128()); +} + +inline +floatInVec::floatInVec(__m128 vec, int slot) +{ + SSEFloat v; + v.m128 = vec; + mData = _mm_set1_ps(v.f[slot]); +} + +inline +floatInVec::floatInVec(float scalar) +{ + mData = _mm_set1_ps(scalar); +} + +#ifdef _VECTORMATH_NO_SCALAR_CAST +inline +float +floatInVec::getAsFloat() const +#else +inline +floatInVec::operator float() const +#endif +{ + return *((float *)&mData); +} + +inline +__m128 +floatInVec::get128() const +{ + return mData; +} + +inline +const floatInVec +floatInVec::operator ++ (int) +{ + __m128 olddata = mData; + operator ++(); + return floatInVec(olddata); +} + +inline +const floatInVec +floatInVec::operator -- (int) +{ + __m128 olddata = mData; + operator --(); + return floatInVec(olddata); +} + +inline +floatInVec& +floatInVec::operator ++ () +{ + *this += floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +floatInVec& +floatInVec::operator -- () +{ + *this -= floatInVec(_mm_set1_ps(1.0f)); + return *this; +} + +inline +const floatInVec +floatInVec::operator - () const +{ + return floatInVec(_mm_sub_ps(_mm_setzero_ps(), mData)); +} + +inline +floatInVec& +floatInVec::operator = (const floatInVec &vec) +{ + mData = vec.mData; + return *this; +} + +inline +floatInVec& +floatInVec::operator *= (const floatInVec &vec) +{ + *this = *this * vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator /= (const floatInVec &vec) +{ + *this = *this / vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator += (const floatInVec &vec) +{ + *this = *this + vec; + return *this; +} + +inline +floatInVec& +floatInVec::operator -= (const floatInVec &vec) +{ + *this = *this - vec; + return *this; +} + +inline +const floatInVec +operator * (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_mul_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator / (const floatInVec &num, const floatInVec &den) +{ + return floatInVec(_mm_div_ps(num.get128(), den.get128())); +} + +inline +const floatInVec +operator + (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_add_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +operator - (const floatInVec &vec0, const floatInVec &vec1) +{ + return floatInVec(_mm_sub_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator < (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator <= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec1.get128(), vec0.get128())); +} + +inline +const boolInVec +operator > (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpgt_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator >= (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpge_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator == (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); +} + +inline +const boolInVec +operator != (const floatInVec &vec0, const floatInVec &vec1) +{ + return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); +} + +inline +const floatInVec +select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1) +{ + return floatInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); +} + +} // namespace Vectormath + +#endif // floatInVec_h diff --git a/Code/Physics/src/vectormath/sse/mat_aos.h b/Code/Physics/src/vectormath/sse/mat_aos.h new file mode 100644 index 00000000..a2c66cc5 --- /dev/null +++ b/Code/Physics/src/vectormath/sse/mat_aos.h @@ -0,0 +1,2190 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_MAT_AOS_CPP_H +#define _VECTORMATH_MAT_AOS_CPP_H + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// Constants +// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) +#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) +#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) +#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) +#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) +#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) +#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) +#define _VECTORMATH_PI_OVER_2 1.570796327f + +//----------------------------------------------------------------------------- +// Definitions + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Quat &unitQuat ) +{ + __m128 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + VM_ATTRIBUTE_ALIGN16 unsigned int sx[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int sz[4] = {0, 0, 0xffffffff, 0}; + __m128 select_x = _mm_load_ps((float *)sx); + __m128 select_z = _mm_load_ps((float *)sz); + + xyzw_2 = _mm_add_ps( unitQuat.get128(), unitQuat.get128() ); + wwww = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,3,3,3) ); + yzxw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,0,2,1) ); + zxyw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,1,0,2) ); + yzxw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,0,2,1) ); + zxyw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,1,0,2) ); + + tmp0 = _mm_mul_ps( yzxw_2, wwww ); // tmp0 = 2yw, 2zw, 2xw, 2w2 + tmp1 = _mm_sub_ps( _mm_set1_ps(1.0f), _mm_mul_ps(yzxw, yzxw_2) ); // tmp1 = 1 - 2y2, 1 - 2z2, 1 - 2x2, 1 - 2w2 + tmp2 = _mm_mul_ps( yzxw, xyzw_2 ); // tmp2 = 2xy, 2yz, 2xz, 2w2 + tmp0 = _mm_add_ps( _mm_mul_ps(zxyw, xyzw_2), tmp0 ); // tmp0 = 2yw + 2zx, 2zw + 2xy, 2xw + 2yz, 2w2 + 2w2 + tmp1 = _mm_sub_ps( tmp1, _mm_mul_ps(zxyw, zxyw_2) ); // tmp1 = 1 - 2y2 - 2z2, 1 - 2z2 - 2x2, 1 - 2x2 - 2y2, 1 - 2w2 - 2w2 + tmp2 = _mm_sub_ps( tmp2, _mm_mul_ps(zxyw_2, wwww) ); // tmp2 = 2xy - 2zw, 2yz - 2xw, 2xz - 2yw, 2w2 -2w2 + + tmp3 = vec_sel( tmp0, tmp1, select_x ); + tmp4 = vec_sel( tmp1, tmp2, select_x ); + tmp5 = vec_sel( tmp2, tmp0, select_x ); + mCol0 = Vector3( vec_sel( tmp3, tmp2, select_z ) ); + mCol1 = Vector3( vec_sel( tmp4, tmp0, select_z ) ); + mCol2 = Vector3( vec_sel( tmp5, tmp1, select_z ) ); +} + +VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setRow( int row, const Vector3 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Matrix3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getRow( int row ) const +{ + return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Matrix3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator =( const Matrix3 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, res0, res1, res2; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + res0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //res1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + res1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + res1 = vec_sel(res1, mat.getCol1().get128(), select_y); + //res2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + res2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + res2 = vec_sel(res2, vec_splat(mat.getCol1().get128(), 2), select_y); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; + tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); + tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); + tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); + dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + return Matrix3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ) + ); +} + +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ) +{ + return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const +{ + return Matrix3( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) +{ + *this = *this + mat; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) +{ + *this = *this - mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( ) const +{ + return Matrix3( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ) +{ + return Matrix3( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const floatInVec &scalar ) const +{ + return Matrix3( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ) +{ + return floatInVec(scalar) * mat; +} + +VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ) +{ + return mat * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const +{ + return Matrix3( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) +{ + *this = *this * mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) +{ + return Matrix3( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::identity( ) +{ + return Matrix3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + return Matrix3( + Vector3( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector3( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector3( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const Quat &unitQuat ) +{ + return Matrix3( unitQuat ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ) +{ + return Matrix3( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ) +{ + return Matrix3( + mulPerElem( mat.getCol0(), scaleVec ), + mulPerElem( mat.getCol1(), scaleVec ), + mulPerElem( mat.getCol2(), scaleVec ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ) +{ + return Matrix3( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( float scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const floatInVec &scalar ) +{ + mCol0 = Vector4( scalar ); + mCol1 = Vector4( scalar ); + mCol2 = Vector4( scalar ); + mCol3 = Vector4( scalar ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Transform3 & mat ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( mat.getCol3(), 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Vector4 &_col0, const Vector4 &_col1, const Vector4 &_col2, const Vector4 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix3 & mat, const Vector3 &translateVec ) +{ + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Quat &unitQuat, const Vector3 &translateVec ) +{ + Matrix3 mat; + mat = Matrix3( unitQuat ); + mCol0 = Vector4( mat.getCol0(), 0.0f ); + mCol1 = Vector4( mat.getCol1(), 0.0f ); + mCol2 = Vector4( mat.getCol2(), 0.0f ); + mCol3 = Vector4( translateVec, 1.0f ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol0( const Vector4 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol1( const Vector4 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol2( const Vector4 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol3( const Vector4 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol( int col, const Vector4 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, const floatInVec &val ) +{ + Vector4 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Matrix4::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol3( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Matrix4::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator =( const Matrix4 & mat ) +{ + mCol0 = mat.mCol0; + mCol1 = mat.mCol1; + mCol2 = mat.mCol2; + mCol3 = mat.mCol3; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergeh( mat.getCol1().get128(), mat.getCol3().get128() ); + tmp2 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp3 = vec_mergel( mat.getCol1().get128(), mat.getCol3().get128() ); + res0 = vec_mergeh( tmp0, tmp1 ); + res1 = vec_mergel( tmp0, tmp1 ); + res2 = vec_mergeh( tmp2, tmp3 ); + res3 = vec_mergel( tmp2, tmp3 ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4( res2 ), + Vector4( res3 ) + ); +} + +// TODO: Tidy +static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathPNPN[4] = {0x00000000, 0x80000000, 0x00000000, 0x80000000}; +static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathNPNP[4] = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; +static VM_ATTRIBUTE_ALIGN16 const float _vmathZERONE[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + +VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det,RDet; + __m128 trns0,trns1,trns2,trns3; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3'dot V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3'dot V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + const __m128 Sign_PNPN = _mm_load_ps((float *)_vmathPNPN); + const __m128 Sign_NPNP = _mm_load_ps((float *)_vmathNPNP); + + __m128 mtL1 = _mm_xor_ps(sum,Sign_PNPN); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL2 = _mm_xor_ps(sum,Sign_NPNP); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + + // Calculating the minterms of the third line. + tt = _mm_ror_ps(_L1,1); + Va = _mm_mul_ps(tt,Vb); // V1' dot V2" + Vb = _mm_mul_ps(tt,Vc); // V1' dot V2^ + Vc = _mm_mul_ps(tt,_L2); // V1' dot V2 + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V1" dot V2^ - V1^ dot V2" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V1^ dot V2' - V1' dot V2^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V1' dot V2" - V1" dot V2' + + tt = _mm_ror_ps(_L4,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL3 = _mm_xor_ps(sum,Sign_PNPN); + + // Dividing is FASTER than rcp_nr! (Because rcp_nr causes many register-memory RWs). + RDet = _mm_div_ss(_mm_load_ss((float *)&_vmathZERONE), Det); // TODO: just 1.0f? + RDet = _mm_shuffle_ps(RDet,RDet,0x00); + + // Devide the first 12 minterms with the determinant. + mtL1 = _mm_mul_ps(mtL1, RDet); + mtL2 = _mm_mul_ps(mtL2, RDet); + mtL3 = _mm_mul_ps(mtL3, RDet); + + // Calculate the minterms of the forth line and devide by the determinant. + tt = _mm_ror_ps(_L3,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + __m128 mtL4 = _mm_xor_ps(sum,Sign_NPNP); + mtL4 = _mm_mul_ps(mtL4, RDet); + + // Now we just have to transpose the minterms matrix. + trns0 = _mm_unpacklo_ps(mtL1,mtL2); + trns1 = _mm_unpacklo_ps(mtL3,mtL4); + trns2 = _mm_unpackhi_ps(mtL1,mtL2); + trns3 = _mm_unpackhi_ps(mtL3,mtL4); + _L1 = _mm_movelh_ps(trns0,trns1); + _L2 = _mm_movehl_ps(trns1,trns0); + _L3 = _mm_movelh_ps(trns2,trns3); + _L4 = _mm_movehl_ps(trns3,trns2); + + return Matrix4( + Vector4( _L1 ), + Vector4( _L2 ), + Vector4( _L3 ), + Vector4( _L4 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( inverse( affineMat ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ) +{ + Transform3 affineMat; + affineMat.setCol0( mat.getCol0().getXYZ( ) ); + affineMat.setCol1( mat.getCol1().getXYZ( ) ); + affineMat.setCol2( mat.getCol2().getXYZ( ) ); + affineMat.setCol3( mat.getCol3().getXYZ( ) ); + return Matrix4( orthoInverse( affineMat ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ) +{ + __m128 Va,Vb,Vc; + __m128 r1,r2,r3,tt,tt2; + __m128 sum,Det; + + __m128 _L1 = mat.getCol0().get128(); + __m128 _L2 = mat.getCol1().get128(); + __m128 _L3 = mat.getCol2().get128(); + __m128 _L4 = mat.getCol3().get128(); + // Calculating the minterms for the first line. + + // _mm_ror_ps is just a macro using _mm_shuffle_ps(). + tt = _L4; tt2 = _mm_ror_ps(_L3,1); + Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3' dot V4 + Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3' dot V4" + Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ + + r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" + r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ + r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' + + tt = _L2; + Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); + Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); + Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); + + // Calculating the determinant. + Det = _mm_mul_ps(sum,_L1); + Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); + + // Calculating the minterms of the second line (using previous results). + tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); + tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); + + // Testing the determinant. + Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); + return floatInVec(Det, 0); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 + mat.mCol0 ), + ( mCol1 + mat.mCol1 ), + ( mCol2 + mat.mCol2 ), + ( mCol3 + mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const +{ + return Matrix4( + ( mCol0 - mat.mCol0 ), + ( mCol1 - mat.mCol1 ), + ( mCol2 - mat.mCol2 ), + ( mCol3 - mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) +{ + *this = *this + mat; + return *this; +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) +{ + *this = *this - mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( ) const +{ + return Matrix4( + ( -mCol0 ), + ( -mCol1 ), + ( -mCol2 ), + ( -mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ) +{ + return Matrix4( + absPerElem( mat.getCol0() ), + absPerElem( mat.getCol1() ), + absPerElem( mat.getCol2() ), + absPerElem( mat.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const floatInVec &scalar ) const +{ + return Matrix4( + ( mCol0 * scalar ), + ( mCol1 * scalar ), + ( mCol2 * scalar ), + ( mCol3 * scalar ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ) +{ + return floatInVec(scalar) * mat; +} + +VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ) +{ + return mat * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector4 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2))), _mm_mul_ps(mCol3.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(3,3,3,3))))) + ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector3 &vec ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2)))) + ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Point3 &pnt ) const +{ + return Vector4( + _mm_add_ps( + _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(1,1,1,1)))), + _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(2,2,2,2))), mCol3.get128())) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const +{ + return Matrix4( + ( *this * mat.mCol0 ), + ( *this * mat.mCol1 ), + ( *this * mat.mCol2 ), + ( *this * mat.mCol3 ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) +{ + *this = *this * mat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const +{ + return Matrix4( + ( *this * tfrm.getCol0() ), + ( *this * tfrm.getCol1() ), + ( *this * tfrm.getCol2() ), + ( *this * Point3( tfrm.getCol3() ) ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) +{ + return Matrix4( + mulPerElem( mat0.getCol0(), mat1.getCol0() ), + mulPerElem( mat0.getCol1(), mat1.getCol1() ), + mulPerElem( mat0.getCol2(), mat1.getCol2() ), + mulPerElem( mat0.getCol3(), mat1.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::identity( ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) +{ + mCol0.setXYZ( mat3.getCol0() ); + mCol1.setXYZ( mat3.getCol1() ); + mCol2.setXYZ( mat3.getCol2() ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Matrix4::getUpper3x3( ) const +{ + return Matrix3( + mCol0.getXYZ( ), + mCol1.getXYZ( ), + mCol2.getXYZ( ) + ); +} + +VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setTranslation( const Vector3 &translateVec ) +{ + mCol3.setXYZ( translateVec ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Matrix4::getTranslation( ) const +{ + return mCol3.getXYZ( ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4::xAxis( ), + Vector4( res1 ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Matrix4( + Vector4( res0 ), + Vector4::yAxis( ), + Vector4( res2 ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Matrix4( + Vector4( res0 ), + Vector4( res1 ), + Vector4::zAxis( ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Matrix4( + Vector4( vec_mul( Z0, Y0 ) ), + Vector4( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector4( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; + axis = unitVec.get128(); + sincosf4( radians.get128(), &s, &c ); + xxxx = vec_splat( axis, 0 ); + yyyy = vec_splat( axis, 1 ); + zzzz = vec_splat( axis, 2 ); + oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); + axisS = vec_mul( axis, s ); + negAxisS = negatef4( axisS ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); + tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); + tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); + //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); + tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); + //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); + tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); + tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); + tmp0 = vec_sel( tmp0, c, select_x ); + tmp1 = vec_sel( tmp1, c, select_y ); + tmp2 = vec_sel( tmp2, c, select_z ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + axis = vec_and( axis, _mm_load_ps( (float *)select_xyz ) ); + tmp0 = vec_and( tmp0, _mm_load_ps( (float *)select_xyz ) ); + tmp1 = vec_and( tmp1, _mm_load_ps( (float *)select_xyz ) ); + tmp2 = vec_and( tmp2, _mm_load_ps( (float *)select_xyz ) ); + return Matrix4( + Vector4( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), + Vector4( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), + Vector4( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const Quat &unitQuat ) +{ + return Matrix4( Transform3::rotation( unitQuat ) ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Matrix4( + Vector4( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector4( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector4::wAxis( ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ) +{ + return Matrix4( + ( mat.getCol0() * scaleVec.getX( ) ), + ( mat.getCol1() * scaleVec.getY( ) ), + ( mat.getCol2() * scaleVec.getZ( ) ), + mat.getCol3() + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ) +{ + Vector4 scale4; + scale4 = Vector4( scaleVec, 1.0f ); + return Matrix4( + mulPerElem( mat.getCol0(), scale4 ), + mulPerElem( mat.getCol1(), scale4 ), + mulPerElem( mat.getCol2(), scale4 ), + mulPerElem( mat.getCol3(), scale4 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::translation( const Vector3 &translateVec ) +{ + return Matrix4( + Vector4::xAxis( ), + Vector4::yAxis( ), + Vector4::zAxis( ), + Vector4( translateVec, 1.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ) +{ + Matrix4 m4EyeFrame; + Vector3 v3X, v3Y, v3Z; + v3Y = normalize( upVec ); + v3Z = normalize( ( eyePos - lookAtPos ) ); + v3X = normalize( cross( v3Y, v3Z ) ); + v3Y = cross( v3Z, v3X ); + m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); + return orthoInverse( m4EyeFrame ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) +{ + float f, rangeInv; + __m128 zero, col0, col1, col2, col3; + union { __m128 v; float s[4]; } tmp; + f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); + rangeInv = 1.0f / ( zNear - zFar ); + zero = _mm_setzero_ps(); + tmp.v = zero; + tmp.s[0] = f / aspect; + col0 = tmp.v; + tmp.v = zero; + tmp.s[1] = f; + col1 = tmp.v; + tmp.v = zero; + tmp.s[2] = ( zNear + zFar ) * rangeInv; + tmp.s[3] = -1.0f; + col2 = tmp.v; + tmp.v = zero; + tmp.s[2] = zNear * zFar * rangeInv * 2.0f; + col3 = tmp.v; + return Matrix4( + Vector4( col0 ), + Vector4( col1 ), + Vector4( col2 ), + Vector4( col3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff; + __m128 diagonal, column, near2; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; // TODO: Union? + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + near2 = vec_splat( n.v, 0 ); + near2 = vec_add( near2, near2 ); + diagonal = vec_mul( near2, inv_diff ); + column = vec_mul( sum, inv_diff ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( column, _mm_set1_ps(-1.0f), select_w ) ), + Vector4( vec_sel( zero, vec_mul( diagonal, vec_splat( f.v, 0 ) ), select_z ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) +{ + /* function implementation based on code from STIDC SDK: */ + /* -------------------------------------------------------------- */ + /* PLEASE DO NOT MODIFY THIS SECTION */ + /* This prolog section is automatically generated. */ + /* */ + /* (C)Copyright */ + /* Sony Computer Entertainment, Inc., */ + /* Toshiba Corporation, */ + /* International Business Machines Corporation, */ + /* 2001,2002. */ + /* S/T/I Confidential Information */ + /* -------------------------------------------------------------- */ + __m128 lbf, rtn; + __m128 diff, sum, inv_diff, neg_inv_diff; + __m128 diagonal, column; + __m128 zero = _mm_setzero_ps(); + union { __m128 v; float s[4]; } l, f, r, n, b, t; + l.s[0] = left; + f.s[0] = zFar; + r.s[0] = right; + n.s[0] = zNear; + b.s[0] = bottom; + t.s[0] = top; + lbf = vec_mergeh( l.v, f.v ); + rtn = vec_mergeh( r.v, n.v ); + lbf = vec_mergeh( lbf, b.v ); + rtn = vec_mergeh( rtn, t.v ); + diff = vec_sub( rtn, lbf ); + sum = vec_add( rtn, lbf ); + inv_diff = recipf4( diff ); + neg_inv_diff = negatef4( inv_diff ); + diagonal = vec_add( inv_diff, inv_diff ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + column = vec_mul( sum, vec_sel( neg_inv_diff, inv_diff, select_z ) ); // TODO: no madds with zero + return Matrix4( + Vector4( vec_sel( zero, diagonal, select_x ) ), + Vector4( vec_sel( zero, diagonal, select_y ) ), + Vector4( vec_sel( zero, diagonal, select_z ) ), + Vector4( vec_sel( column, _mm_set1_ps(1.0f), select_w ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ) +{ + return Matrix4( + select( mat0.getCol0(), mat1.getCol0(), select1 ), + select( mat0.getCol1(), mat1.getCol1(), select1 ), + select( mat0.getCol2(), mat1.getCol2(), select1 ), + select( mat0.getCol3(), mat1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ) +{ + print( mat.getRow( 0 ) ); + print( mat.getRow( 1 ) ); + print( mat.getRow( 2 ) ); + print( mat.getRow( 3 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ) +{ + printf("%s:\n", name); + print( mat ); +} + +#endif + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( float scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const floatInVec &scalar ) +{ + mCol0 = Vector3( scalar ); + mCol1 = Vector3( scalar ); + mCol2 = Vector3( scalar ); + mCol3 = Vector3( scalar ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2, const Vector3 &_col3 ) +{ + mCol0 = _col0; + mCol1 = _col1; + mCol2 = _col2; + mCol3 = _col3; +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ) +{ + this->setUpper3x3( tfrm ); + this->setTranslation( translateVec ); +} + +VECTORMATH_FORCE_INLINE Transform3::Transform3( const Quat &unitQuat, const Vector3 &translateVec ) +{ + this->setUpper3x3( Matrix3( unitQuat ) ); + this->setTranslation( translateVec ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol0( const Vector3 &_col0 ) +{ + mCol0 = _col0; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol1( const Vector3 &_col1 ) +{ + mCol1 = _col1; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol2( const Vector3 &_col2 ) +{ + mCol2 = _col2; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol3( const Vector3 &_col3 ) +{ + mCol3 = _col3; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol( int col, const Vector3 &vec ) +{ + *(&mCol0 + col) = vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setRow( int row, const Vector4 &vec ) +{ + mCol0.setElem( row, vec.getElem( 0 ) ); + mCol1.setElem( row, vec.getElem( 1 ) ); + mCol2.setElem( row, vec.getElem( 2 ) ); + mCol3.setElem( row, vec.getElem( 3 ) ); + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, float val ) +{ + (*this)[col].setElem(row, val); + return *this; +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, const floatInVec &val ) +{ + Vector3 tmpV3_0; + tmpV3_0 = this->getCol( col ); + tmpV3_0.setElem( row, val ); + this->setCol( col, tmpV3_0 ); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Transform3::getElem( int col, int row ) const +{ + return this->getCol( col ).getElem( row ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol0( ) const +{ + return mCol0; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol1( ) const +{ + return mCol1; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol2( ) const +{ + return mCol2; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol3( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector4 Transform3::getRow( int row ) const +{ + return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Transform3::operator []( int col ) +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator []( int col ) const +{ + return *(&mCol0 + col); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator =( const Transform3 & tfrm ) +{ + mCol0 = tfrm.mCol0; + mCol1 = tfrm.mCol1; + mCol2 = tfrm.mCol2; + mCol3 = tfrm.mCol3; + return *this; +} + +VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; + __m128 xxxx, yyyy, zzzz; + tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); + tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); + tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); + dot = vec_splat( dot, 0 ); + invdet = recipf4( dot ); + tmp3 = vec_mergeh( tmp0, tmp2 ); + tmp4 = vec_mergel( tmp0, tmp2 ); + inv0 = vec_mergeh( tmp3, tmp1 ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tmp1, select_y); + //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + inv0 = vec_mul( inv0, invdet ); + inv1 = vec_mul( inv1, invdet ); + inv2 = vec_mul( inv2, invdet ); + inv3 = vec_mul( inv3, invdet ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ) +{ + __m128 inv0, inv1, inv2, inv3; + __m128 tmp0, tmp1; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + tmp1 = vec_mergel( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); + inv3 = negatef4( tfrm.getCol3().get128() ); + inv0 = vec_mergeh( tmp0, tfrm.getCol1().get128() ); + xxxx = vec_splat( inv3, 0 ); + //inv1 = vec_perm( tmp0, tfrm.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + inv1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + inv1 = vec_sel(inv1, tfrm.getCol1().get128(), select_y); + //inv2 = vec_perm( tmp1, tfrm.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + inv2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + inv2 = vec_sel(inv2, vec_splat(tfrm.getCol1().get128(), 2), select_y); + yyyy = vec_splat( inv3, 1 ); + zzzz = vec_splat( inv3, 2 ); + inv3 = vec_mul( inv0, xxxx ); + inv3 = vec_madd( inv1, yyyy, inv3 ); + inv3 = vec_madd( inv2, zzzz, inv3 ); + return Transform3( + Vector3( inv0 ), + Vector3( inv1 ), + Vector3( inv2 ), + Vector3( inv3 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ) +{ + return Transform3( + absPerElem( tfrm.getCol0() ), + absPerElem( tfrm.getCol1() ), + absPerElem( tfrm.getCol2() ), + absPerElem( tfrm.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator *( const Vector3 &vec ) const +{ + __m128 res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( vec.get128(), 0 ); + yyyy = vec_splat( vec.get128(), 1 ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_mul( mCol0.get128(), xxxx ); + res = vec_madd( mCol1.get128(), yyyy, res ); + res = vec_madd( mCol2.get128(), zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Point3 Transform3::operator *( const Point3 &pnt ) const +{ + __m128 tmp0, tmp1, res; + __m128 xxxx, yyyy, zzzz; + xxxx = vec_splat( pnt.get128(), 0 ); + yyyy = vec_splat( pnt.get128(), 1 ); + zzzz = vec_splat( pnt.get128(), 2 ); + tmp0 = vec_mul( mCol0.get128(), xxxx ); + tmp1 = vec_mul( mCol1.get128(), yyyy ); + tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); + tmp1 = vec_add( mCol3.get128(), tmp1 ); + res = vec_add( tmp0, tmp1 ); + return Point3( res ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::operator *( const Transform3 & tfrm ) const +{ + return Transform3( + ( *this * tfrm.mCol0 ), + ( *this * tfrm.mCol1 ), + ( *this * tfrm.mCol2 ), + Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) + ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator *=( const Transform3 & tfrm ) +{ + *this = *this * tfrm; + return *this; +} + +VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) +{ + return Transform3( + mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), + mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), + mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), + mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::identity( ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) +{ + mCol0 = tfrm.getCol0(); + mCol1 = tfrm.getCol1(); + mCol2 = tfrm.getCol2(); + return *this; +} + +VECTORMATH_FORCE_INLINE const Matrix3 Transform3::getUpper3x3( ) const +{ + return Matrix3( mCol0, mCol1, mCol2 ); +} + +VECTORMATH_FORCE_INLINE Transform3 & Transform3::setTranslation( const Vector3 &translateVec ) +{ + mCol3 = translateVec; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Transform3::getTranslation( ) const +{ + return mCol3; +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( const floatInVec &radians ) +{ + __m128 s, c, res1, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res1 = vec_sel( zero, c, select_y ); + res1 = vec_sel( res1, s, select_z ); + res2 = vec_sel( zero, negatef4(s), select_y ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3::xAxis( ), + Vector3( res1 ), + Vector3( res2 ), + Vector3( _mm_setzero_ps() ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( const floatInVec &radians ) +{ + __m128 s, c, res0, res2; + __m128 zero; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, negatef4(s), select_z ); + res2 = vec_sel( zero, s, select_x ); + res2 = vec_sel( res2, c, select_z ); + return Transform3( + Vector3( res0 ), + Vector3::yAxis( ), + Vector3( res2 ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, res0, res1; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + __m128 zero = _mm_setzero_ps(); + sincosf4( radians.get128(), &s, &c ); + res0 = vec_sel( zero, c, select_x ); + res0 = vec_sel( res0, s, select_y ); + res1 = vec_sel( zero, negatef4(s), select_x ); + res1 = vec_sel( res1, c, select_y ); + return Transform3( + Vector3( res0 ), + Vector3( res1 ), + Vector3::zAxis( ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZYX( const Vector3 &radiansXYZ ) +{ + __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; + angles = Vector4( radiansXYZ, 0.0f ).get128(); + sincosf4( angles, &s, &c ); + negS = negatef4( s ); + Z0 = vec_mergel( c, s ); + Z1 = vec_mergel( negS, c ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; + Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); + Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); + Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); + X0 = vec_splat( s, 0 ); + X1 = vec_splat( c, 0 ); + tmp = vec_mul( Z0, Y1 ); + return Transform3( + Vector3( vec_mul( Z0, Y0 ) ), + Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), + Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const Quat &unitQuat ) +{ + return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::scale( const Vector3 &scaleVec ) +{ + __m128 zero = _mm_setzero_ps(); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + return Transform3( + Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), + Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ), + Vector3( 0.0f ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ) +{ + return Transform3( + ( tfrm.getCol0() * scaleVec.getX( ) ), + ( tfrm.getCol1() * scaleVec.getY( ) ), + ( tfrm.getCol2() * scaleVec.getZ( ) ), + tfrm.getCol3() + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ) +{ + return Transform3( + mulPerElem( tfrm.getCol0(), scaleVec ), + mulPerElem( tfrm.getCol1(), scaleVec ), + mulPerElem( tfrm.getCol2(), scaleVec ), + mulPerElem( tfrm.getCol3(), scaleVec ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 Transform3::translation( const Vector3 &translateVec ) +{ + return Transform3( + Vector3::xAxis( ), + Vector3::yAxis( ), + Vector3::zAxis( ), + translateVec + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ) +{ + return Transform3( + select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), + select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), + select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), + select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) + ); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ) +{ + print( tfrm.getRow( 0 ) ); + print( tfrm.getRow( 1 ) ); + print( tfrm.getRow( 2 ) ); +} + +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ) +{ + printf("%s:\n", name); + print( tfrm ); +} + +#endif + +VECTORMATH_FORCE_INLINE Quat::Quat( const Matrix3 & tfrm ) +{ + __m128 res; + __m128 col0, col1, col2; + __m128 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; + __m128 zy_xz_yx, yz_zx_xy, sum, diff; + __m128 radicand, invSqrt, scale; + __m128 res0, res1, res2, res3; + __m128 xx, yy, zz; + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; + + col0 = tfrm.getCol0().get128(); + col1 = tfrm.getCol1().get128(); + col2 = tfrm.getCol2().get128(); + + /* four cases: */ + /* trace > 0 */ + /* else */ + /* xx largest diagonal element */ + /* yy largest diagonal element */ + /* zz largest diagonal element */ + + /* compute quaternion for each case */ + + xx_yy = vec_sel( col0, col1, select_y ); + //xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); + //yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); + //zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); + xx_yy_zz_xx = _mm_shuffle_ps( xx_yy, xx_yy, _MM_SHUFFLE(0,0,1,0) ); + xx_yy_zz_xx = vec_sel( xx_yy_zz_xx, col2, select_z ); // TODO: Ck + yy_zz_xx_yy = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(1,0,2,1) ); + zz_xx_yy_zz = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(2,1,0,2) ); + + diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); + radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), _mm_set1_ps(1.0f) ); + // invSqrt = rsqrtf4( radicand ); + invSqrt = newtonrapson_rsqrt4( radicand ); + + + + zy_xz_yx = vec_sel( col0, col1, select_z ); // zy_xz_yx = 00 01 12 03 + //zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); + zy_xz_yx = _mm_shuffle_ps( zy_xz_yx, zy_xz_yx, _MM_SHUFFLE(0,1,2,2) ); // zy_xz_yx = 12 12 01 00 + zy_xz_yx = vec_sel( zy_xz_yx, vec_splat(col2, 0), select_y ); // zy_xz_yx = 12 20 01 00 + yz_zx_xy = vec_sel( col0, col1, select_x ); // yz_zx_xy = 10 01 02 03 + //yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); + yz_zx_xy = _mm_shuffle_ps( yz_zx_xy, yz_zx_xy, _MM_SHUFFLE(0,0,2,0) ); // yz_zx_xy = 10 02 10 10 + yz_zx_xy = vec_sel( yz_zx_xy, vec_splat(col2, 1), select_x ); // yz_zx_xy = 21 02 10 10 + + sum = vec_add( zy_xz_yx, yz_zx_xy ); + diff = vec_sub( zy_xz_yx, yz_zx_xy ); + + scale = vec_mul( invSqrt, _mm_set1_ps(0.5f) ); + + //res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); + res0 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,1,2,0) ); + res0 = vec_sel( res0, vec_splat(diff, 0), select_w ); // TODO: Ck + //res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); + res1 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,2) ); + res1 = vec_sel( res1, vec_splat(diff, 1), select_w ); // TODO: Ck + //res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); + res2 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,1) ); + res2 = vec_sel( res2, vec_splat(diff, 2), select_w ); // TODO: Ck + res3 = diff; + res0 = vec_sel( res0, radicand, select_x ); + res1 = vec_sel( res1, radicand, select_y ); + res2 = vec_sel( res2, radicand, select_z ); + res3 = vec_sel( res3, radicand, select_w ); + res0 = vec_mul( res0, vec_splat( scale, 0 ) ); + res1 = vec_mul( res1, vec_splat( scale, 1 ) ); + res2 = vec_mul( res2, vec_splat( scale, 2 ) ); + res3 = vec_mul( res3, vec_splat( scale, 3 ) ); + + /* determine case and select answer */ + + xx = vec_splat( col0, 0 ); + yy = vec_splat( col1, 1 ); + zz = vec_splat( col2, 2 ); + res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); + res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); + res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), _mm_setzero_ps() ) ); + mVec128 = res; +} + +VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &tfrm0, const Vector3 &tfrm1 ) +{ + return Matrix3( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &tfrm0, const Vector4 &tfrm1 ) +{ + return Matrix4( + ( tfrm0 * tfrm1.getX( ) ), + ( tfrm0 * tfrm1.getY( ) ), + ( tfrm0 * tfrm1.getZ( ) ), + ( tfrm0 * tfrm1.getW( ) ) + ); +} + +VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ) +{ + __m128 tmp0, tmp1, mcol0, mcol1, mcol2, res; + __m128 xxxx, yyyy, zzzz; + tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); + tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); + xxxx = vec_splat( vec.get128(), 0 ); + mcol0 = vec_mergeh( tmp0, mat.getCol1().get128() ); + //mcol1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + mcol1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); + mcol1 = vec_sel(mcol1, mat.getCol1().get128(), select_y); + //mcol2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); + mcol2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); + mcol2 = vec_sel(mcol2, vec_splat(mat.getCol1().get128(), 2), select_y); + yyyy = vec_splat( vec.get128(), 1 ); + res = vec_mul( mcol0, xxxx ); + zzzz = vec_splat( vec.get128(), 2 ); + res = vec_madd( mcol1, yyyy, res ); + res = vec_madd( mcol2, zzzz, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ) +{ + __m128 neg, res0, res1, res2; + neg = negatef4( vec.get128() ); + VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; + //res0 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_XZBX ); + res0 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,2,2,0) ); + res0 = vec_sel(res0, vec_splat(neg, 1), select_z); + //res1 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_CXXX ); + res1 = vec_sel(vec_splat(vec.get128(), 0), vec_splat(neg, 2), select_x); + //res2 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_YAXX ); + res2 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,1,1) ); + res2 = vec_sel(res2, vec_splat(neg, 0), select_y); + VM_ATTRIBUTE_ALIGN16 unsigned int filter_x[4] = {0, 0xffffffff, 0xffffffff, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int filter_y[4] = {0xffffffff, 0, 0xffffffff, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int filter_z[4] = {0xffffffff, 0xffffffff, 0, 0xffffffff}; + res0 = vec_and( res0, _mm_load_ps((float *)filter_x ) ); + res1 = vec_and( res1, _mm_load_ps((float *)filter_y ) ); + res2 = vec_and( res2, _mm_load_ps((float *)filter_z ) ); // TODO: Use selects? + return Matrix3( + Vector3( res0 ), + Vector3( res1 ), + Vector3( res2 ) + ); +} + +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ) +{ + return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); +} + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/sse/quat_aos.h b/Code/Physics/src/vectormath/sse/quat_aos.h new file mode 100644 index 00000000..7eac59fe --- /dev/null +++ b/Code/Physics/src/vectormath/sse/quat_aos.h @@ -0,0 +1,579 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_QUAT_AOS_CPP_H +#define _VECTORMATH_QUAT_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#endif + +namespace Vectormath { +namespace Aos { + +VECTORMATH_FORCE_INLINE void Quat::set128(vec_float4 vec) +{ + mVec128 = vec; +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + + + +VECTORMATH_FORCE_INLINE Quat::Quat(const Quat& quat) +{ + mVec128 = quat.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); +} + + + + + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const Vector4 &vec ) +{ + mVec128 = vec.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Quat::Quat( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::identity( ) +{ + return Quat( _VECTORMATH_UNIT_0001 ); +} + +VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ) +{ + return lerp( floatInVec(t), quat0, quat1 ); +} + +VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ) +{ + return ( quat0 + ( ( quat1 - quat0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + return slerp( floatInVec(t), unitQuat0, unitQuat1 ); +} + +VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ) +{ + Quat start; + vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + __m128 selectMask; + cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); + selectMask = (__m128)vec_cmpgt( _mm_setzero_ps(), cosAngle ); + cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); + start = Quat( vec_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); + selectMask = (__m128)vec_cmpgt( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = vec_sub( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( _mm_set1_ps(1.0f), tttt ); + angles = vec_mergeh( angles, oneMinusT ); + angles = vec_madd( angles, angle, _mm_setzero_ps() ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Quat( vec_madd( start.get128(), scale0, vec_mul( unitQuat1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return squad( floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3 ); +} + +VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) +{ + return slerp( ( ( floatInVec(2.0f) * t ) * ( floatInVec(1.0f) - t ) ), slerp( t, unitQuat0, unitQuat3 ), slerp( t, unitQuat1, unitQuat2 ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Quat::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator =( const Quat &quat ) +{ + mVec128 = quat.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setXYZ( const Vector3 &vec ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Quat::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Quat::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Quat::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator +( const Quat &quat ) const +{ + return Quat( _mm_add_ps( mVec128, quat.mVec128 ) ); +} + + +VECTORMATH_FORCE_INLINE const Quat Quat::operator -( const Quat &quat ) const +{ + return Quat( _mm_sub_ps( mVec128, quat.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const floatInVec &scalar ) const +{ + return Quat( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator +=( const Quat &quat ) +{ + *this = *this + quat; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator -=( const Quat &quat ) +{ + *this = *this - quat; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator /( const floatInVec &scalar ) const +{ + return Quat( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator -( ) const +{ + return Quat(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ) +{ + return floatInVec(scalar) * quat; +} + +VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ) +{ + return quat * scalar; +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ) +{ + return floatInVec( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ) +{ + return floatInVec( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( quat.get128(), quat.get128() )), 0 ); +} + +VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ) +{ + vec_float4 dot =_vmathVfDot4( quat.get128(), quat.get128()); + return Quat( _mm_mul_ps( quat.get128(), newtonrapson_rsqrt4( dot ) ) ); +} + + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + Vector3 crossVec; + __m128 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + cosAngleX2Plus2 = vec_madd( cosAngle, _mm_set1_ps(2.0f), _mm_set1_ps(2.0f) ); + recipCosHalfAngleX2 = _mm_rsqrt_ps( cosAngleX2Plus2 ); + cosHalfAngleX2 = vec_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); + crossVec = cross( unitVec0, unitVec1 ); + res = vec_mul( crossVec.get128(), recipCosHalfAngleX2 ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( res, vec_mul( cosHalfAngleX2, _mm_set1_ps(0.5f) ), sw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( float radians, const Vector3 &unitVec ) +{ + return rotation( floatInVec(radians), unitVec ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const floatInVec &radians, const Vector3 &unitVec ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( vec_mul( unitVec.get128(), s ), c, sw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( float radians ) +{ + return rotationX( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0xffffffff, 0, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, xsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( float radians ) +{ + return rotationY( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int ysw[4] = {0, 0xffffffff, 0, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, ysw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( float radians ) +{ + return rotationZ( floatInVec(radians) ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( const floatInVec &radians ) +{ + __m128 s, c, angle, res; + angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); + sincosf4( angle, &s, &c ); + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0, 0, 0xffffffff, 0}; + VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; + res = vec_sel( _mm_setzero_ps(), s, zsw ); + res = vec_sel( res, c, wsw ); + return Quat( res ); +} + +VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const Quat &quat ) const +{ + __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; + __m128 product, l_wxyz, r_wxyz, xy, qw; + ldata = mVec128; + rdata = quat.mVec128; + tmp0 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,0,2,1) ); + qv = vec_mul( vec_splat( ldata, 3 ), rdata ); + qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( ldata, rdata ); + l_wxyz = vec_sld( ldata, ldata, 12 ); + r_wxyz = vec_sld( rdata, rdata, 12 ); + qw = vec_nmsub( l_wxyz, r_wxyz, product ); + xy = vec_madd( l_wxyz, r_wxyz, product ); + qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + return Quat( vec_sel( qv, qw, sw ) ); +} + +VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const Quat &quat ) +{ + *this = *this * quat; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &quat, const Vector3 &vec ) +{ __m128 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; + qdata = quat.get128(); + vdata = vec.get128(); + tmp0 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,0,2,1) ); + wwww = vec_splat( qdata, 3 ); + qv = vec_mul( wwww, vdata ); + qv = vec_madd( tmp0, tmp1, qv ); + qv = vec_nmsub( tmp2, tmp3, qv ); + product = vec_mul( qdata, vdata ); + qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); + qw = vec_add( vec_sld( product, product, 8 ), qw ); + tmp1 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,0,2,1) ); + res = vec_mul( vec_splat( qw, 0 ), qdata ); + res = vec_madd( wwww, qv, res ); + res = vec_madd( tmp0, tmp1, res ); + res = vec_nmsub( tmp2, tmp3, res ); + return Vector3( res ); +} + +VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0x80000000,0x80000000,0x80000000,0}; + return Quat( vec_xor( quat.get128(), _mm_load_ps((float *)sw) ) ); +} + +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ) +{ + return select( quat0, quat1, boolInVec(select1) ); +} + +//VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ) +//{ +// return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) ); +//} + +VECTORMATH_FORCE_INLINE void loadXYZW(Quat& quat, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + quat = Quat( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + quat = Quat( fl.m128); +#endif + + +} + +VECTORMATH_FORCE_INLINE void storeXYZW(const Quat& quat, float* fptr) +{ + fptr[0] = quat.getX(); + fptr[1] = quat.getY(); + fptr[2] = quat.getZ(); + fptr[3] = quat.getW(); +// _mm_storeu_ps((float*)quat.get128(),fptr); +} + + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Quat &quat ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = quat.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/sse/vec_aos.h b/Code/Physics/src/vectormath/sse/vec_aos.h new file mode 100644 index 00000000..35aeeaf1 --- /dev/null +++ b/Code/Physics/src/vectormath/sse/vec_aos.h @@ -0,0 +1,1455 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VEC_AOS_CPP_H +#define _VECTORMATH_VEC_AOS_CPP_H + +//----------------------------------------------------------------------------- +// Constants +// for permutes words are labeled [x,y,z,w] [a,b,c,d] + +#define _VECTORMATH_PERM_X 0x00010203 +#define _VECTORMATH_PERM_Y 0x04050607 +#define _VECTORMATH_PERM_Z 0x08090a0b +#define _VECTORMATH_PERM_W 0x0c0d0e0f +#define _VECTORMATH_PERM_A 0x10111213 +#define _VECTORMATH_PERM_B 0x14151617 +#define _VECTORMATH_PERM_C 0x18191a1b +#define _VECTORMATH_PERM_D 0x1c1d1e1f +#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } +#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } +#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } +#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } +#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } +#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } +#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } +#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } +#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } +#define _VECTORMATH_UNIT_1000 _mm_setr_ps(1.0f,0.0f,0.0f,0.0f) // (__m128){ 1.0f, 0.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0100 _mm_setr_ps(0.0f,1.0f,0.0f,0.0f) // (__m128){ 0.0f, 1.0f, 0.0f, 0.0f } +#define _VECTORMATH_UNIT_0010 _mm_setr_ps(0.0f,0.0f,1.0f,0.0f) // (__m128){ 0.0f, 0.0f, 1.0f, 0.0f } +#define _VECTORMATH_UNIT_0001 _mm_setr_ps(0.0f,0.0f,0.0f,1.0f) // (__m128){ 0.0f, 0.0f, 0.0f, 1.0f } +#define _VECTORMATH_SLERP_TOL 0.999f +//_VECTORMATH_SLERP_TOLF + +//----------------------------------------------------------------------------- +// Definitions + +#ifndef _VECTORMATH_INTERNAL_FUNCTIONS +#define _VECTORMATH_INTERNAL_FUNCTIONS + +#define _vmath_shufps(a, b, immx, immy, immz, immw) _mm_shuffle_ps(a, b, _MM_SHUFFLE(immw, immz, immy, immx)) +static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps( vec0, vec1); + return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); +} + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot4( __m128 vec0, __m128 vec1 ) +{ + __m128 result = _mm_mul_ps(vec0, vec1); + return _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(0,0,0,0)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(1,1,1,1)), + _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(result, result, _MM_SHUFFLE(3,3,3,3))))); +} + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfCross( __m128 vec0, __m128 vec1 ) +{ + __m128 tmp0, tmp1, tmp2, tmp3, result; + tmp0 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,0,2,1) ); + tmp1 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,1,0,2) ); + tmp2 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,1,0,2) ); + tmp3 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,0,2,1) ); + result = vec_mul( tmp0, tmp1 ); + result = vec_nmsub( tmp2, tmp3, result ); + return result; +} +/* +static VECTORMATH_FORCE_INLINE vec_uint4 _vmathVfToHalfFloatsUnpacked(__m128 v) +{ +#if 0 + vec_int4 bexp; + vec_uint4 mant, sign, hfloat; + vec_uint4 notZero, isInf; + const vec_uint4 hfloatInf = (vec_uint4)(0x00007c00u); + const vec_uint4 mergeMant = (vec_uint4)(0x000003ffu); + const vec_uint4 mergeSign = (vec_uint4)(0x00008000u); + + sign = vec_sr((vec_uint4)v, (vec_uint4)16); + mant = vec_sr((vec_uint4)v, (vec_uint4)13); + bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4)23), (vec_int4)0xff); + + notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4)112); + isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4)142); + + bexp = _mm_add_ps(bexp, (vec_int4)-112); + bexp = vec_sl(bexp, (vec_uint4)10); + + hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); + hfloat = vec_sel((vec_uint4)(0), hfloat, notZero); + hfloat = vec_sel(hfloat, hfloatInf, isInf); + hfloat = vec_sel(hfloat, sign, mergeSign); + + return hfloat; +#else + assert(0); + return _mm_setzero_ps(); +#endif +} + +static VECTORMATH_FORCE_INLINE vec_ushort8 _vmath2VfToHalfFloats(__m128 u, __m128 v) +{ +#if 0 + vec_uint4 hfloat_u, hfloat_v; + const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; + hfloat_u = _vmathVfToHalfFloatsUnpacked(u); + hfloat_v = _vmathVfToHalfFloatsUnpacked(v); + return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); +#else + assert(0); + return _mm_setzero_si128(); +#endif +} +*/ + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfInsert(__m128 dst, __m128 src, int slot) +{ + SSEFloat s; + s.m128 = src; + SSEFloat d; + d.m128 = dst; + d.f[slot] = s.f[slot]; + return d.m128; +} + +#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar + +static VECTORMATH_FORCE_INLINE __m128 _vmathVfSplatScalar(float scalar) +{ + return _mm_set1_ps(scalar); +} + +#endif + +namespace Vectormath { +namespace Aos { + + +#ifdef _VECTORMATH_NO_SCALAR_CAST +VECTORMATH_FORCE_INLINE VecIdx::operator floatInVec() const +{ + return floatInVec(ref, i); +} + +VECTORMATH_FORCE_INLINE float VecIdx::getAsFloat() const +#else +VECTORMATH_FORCE_INLINE VecIdx::operator float() const +#endif +{ + return ((float *)&ref)[i]; +} + +VECTORMATH_FORCE_INLINE float VecIdx::operator =( float scalar ) +{ + _vmathVfSetElement(ref, scalar, i); + return scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const floatInVec &scalar ) +{ + ref = _vmathVfInsert(ref, scalar.get128(), i); + return scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const VecIdx& scalar ) +{ + return *this = floatInVec(scalar.ref, scalar.i); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( float scalar ) +{ + return *this *= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) * scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator /=( float scalar ) +{ + return *this /= floatInVec(scalar); +} + +inline floatInVec VecIdx::operator /=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) / scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( float scalar ) +{ + return *this += floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) + scalar; +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( float scalar ) +{ + return *this -= floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( const floatInVec &scalar ) +{ + return *this = floatInVec(ref, i) - scalar; +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3(const Vector3& vec) +{ + set128(vec.get128()); +} + +VECTORMATH_FORCE_INLINE void Vector3::set128(vec_float4 vec) +{ + mVec128 = vec; +} + + +VECTORMATH_FORCE_INLINE Vector3::Vector3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + __m128 xz = _mm_unpacklo_ps( _x.get128(), _z.get128() ); + mVec128 = _mm_unpacklo_ps( xz, _y.get128() ); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Vector3::Vector3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::xAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_1000 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::yAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0100 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::zAxis( ) +{ + return Vector3( _VECTORMATH_UNIT_0010 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector3( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Vector3::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE void loadXYZ(Point3& vec, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + vec = Point3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Point3( fl.m128); +#endif //USE_SSE3_LDDQU + +} + + + +VECTORMATH_FORCE_INLINE void loadXYZ(Vector3& vec, const float* fptr) +{ +#ifdef USE_SSE3_LDDQU + vec = Vector3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); +#else + SSEFloat fl; + fl.f[0] = fptr[0]; + fl.f[1] = fptr[1]; + fl.f[2] = fptr[2]; + fl.f[3] = fptr[3]; + vec = Vector3( fl.m128); +#endif //USE_SSE3_LDDQU + +} + +VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ) +{ + __m128 dstVec = *quad; + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(vec.get128(), dstVec, sw); + *quad = dstVec; +} + +VECTORMATH_FORCE_INLINE void storeXYZ(const Point3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + +VECTORMATH_FORCE_INLINE void storeXYZ(const Vector3& vec, float* fptr) +{ + fptr[0] = vec.getX(); + fptr[1] = vec.getY(); + fptr[2] = vec.getZ(); +} + + +VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + vec0 = Vector3( _mm_load_ps(quads) ); + vec1 = Vector3( _mm_loadu_ps(quads + 3) ); + vec2 = Vector3( _mm_loadu_ps(quads + 6) ); + vec3 = Vector3( _mm_loadu_ps(quads + 9) ); +} + +VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( vec1.get128(), vec1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( vec2.get128(), vec2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( vec0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( vec1.get128(), vec2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( vec3.get128(), vec3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ) +{ + assert(0); +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); + storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#endif +} +*/ +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator =( const Vector3 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Vector3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator +( const Vector3 &vec ) const +{ + return Vector3( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( const Vector3 &vec ) const +{ + return Vector3( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Vector3::operator +( const Point3 &pnt ) const +{ + return Point3( _mm_add_ps( mVec128, pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( const floatInVec &scalar ) const +{ + return Vector3( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( const floatInVec &scalar ) const +{ + return Vector3( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( ) const +{ + //return Vector3(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); + + VM_ATTRIBUTE_ALIGN16 static const int array[] = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; + __m128 NEG_MASK = SSEFloat(*(const vec_float4*)array).vf; + return Vector3(_mm_xor_ps(get128(),NEG_MASK)); +} + +VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ) +{ + return floatInVec(scalar) * vec; +} + +VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ) +{ + return vec * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ) +{ + return Vector3( _mm_rcp_ps( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ) +{ + return Vector3( fabsf4( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector3( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ) +{ + return floatInVec( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot3( vec.get128(), vec.get128() )), 0 ); +} + + +VECTORMATH_FORCE_INLINE const Vector3 normalizeApprox( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ) +{ + return Vector3( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ) +{ + return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +VECTORMATH_FORCE_INLINE const Vector4 select(const Vector4& vec0, const Vector4& vec1, const boolInVec& select1) +{ + return Vector4(vec_sel(vec0.get128(), vec1.get128(), select1.get128())); +} + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +VECTORMATH_FORCE_INLINE Vector4::Vector4( float _x, float _y, float _z, float _w ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, _w); + } + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) +{ + mVec128 = _mm_unpacklo_ps( + _mm_unpacklo_ps( _x.get128(), _z.get128() ), + _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, float _w ) +{ + mVec128 = xyz.get128(); + _vmathVfSetElement(mVec128, _w, 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, const floatInVec &_w ) +{ + mVec128 = xyz.get128(); + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &vec ) +{ + mVec128 = vec.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_setzero_ps(), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Point3 &pnt ) +{ + mVec128 = pnt.get128(); + mVec128 = _vmathVfInsert(mVec128, _mm_set1_ps(1.0f), 3); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const Quat &quat ) +{ + mVec128 = quat.get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Vector4::Vector4( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::xAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_1000 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::yAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0100 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::zAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0010 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::wAxis( ) +{ + return Vector4( _VECTORMATH_UNIT_0001 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return lerp( floatInVec(t), vec0, vec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ) +{ + return ( vec0 + ( ( vec1 - vec0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + return slerp( floatInVec(t), unitVec0, unitVec1 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) +{ + __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; + cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); + __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); + angle = acosf4( cosAngle ); + tttt = t.get128(); + oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); + angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t + angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t + angles = _mm_mul_ps( angles, angle ); + sines = sinf4( angles ); + scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); + scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); + scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); + return Vector4( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Vector4::get128( ) const +{ + return mVec128; +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ) +{ + twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); + twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); +} +*/ +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator =( const Vector4 &vec ) +{ + mVec128 = vec.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setXYZ( const Vector3 &vec ) +{ + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; + mVec128 = vec_sel( vec.get128(), mVec128, sw ); + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector3 Vector4::getXYZ( ) const +{ + return Vector3( mVec128 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( float _w ) +{ + _vmathVfSetElement(mVec128, _w, 3); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( const floatInVec &_w ) +{ + mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getW( ) const +{ + return floatInVec( mVec128, 3 ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Vector4::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Vector4::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator +( const Vector4 &vec ) const +{ + return Vector4( _mm_add_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( const Vector4 &vec ) const +{ + return Vector4( _mm_sub_ps( mVec128, vec.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( float scalar ) const +{ + return *this * floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( const floatInVec &scalar ) const +{ + return Vector4( _mm_mul_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator +=( const Vector4 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator -=( const Vector4 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( float scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( const floatInVec &scalar ) +{ + *this = *this * scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( float scalar ) const +{ + return *this / floatInVec(scalar); +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( const floatInVec &scalar ) const +{ + return Vector4( _mm_div_ps( mVec128, scalar.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( float scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( const floatInVec &scalar ) +{ + *this = *this / scalar; + return *this; +} + +VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( ) const +{ + return Vector4(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ) +{ + return floatInVec(scalar) * vec; +} + +VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ) +{ + return vec * scalar; +} + +VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_div_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ) +{ + return Vector4( _mm_rcp_ps( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ) +{ + return Vector4( fabsf4( vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Vector4( _mm_or_ps( + _mm_and_ps ( vmask, vec0.get128() ), // Value + _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_max_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ) +{ + return floatInVec( _mm_max_ps( + _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_max_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return Vector4( _mm_min_ps( vec0.get128(), vec1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ) +{ + return floatInVec( _mm_min_ps( + _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_min_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ) +{ + return floatInVec( _mm_add_ps( + _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), + _mm_add_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ) +{ + return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ) +{ + return floatInVec( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ) +{ + return floatInVec( _mm_sqrt_ps(_vmathVfDot4( vec.get128(), vec.get128() )), 0 ); +} + +VECTORMATH_FORCE_INLINE const Vector4 normalizeApprox( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ) +{ + return Vector4( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); +} + +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ) +{ + return select( vec0, vec1, boolInVec(select1) ); +} + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = vec.get128(); + printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); +} + +#endif + +VECTORMATH_FORCE_INLINE Point3::Point3( float _x, float _y, float _z ) +{ + mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) +{ + mVec128 = _mm_unpacklo_ps( _mm_unpacklo_ps( _x.get128(), _z.get128() ), _y.get128() ); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const Vector3 &vec ) +{ + mVec128 = vec.get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( float scalar ) +{ + mVec128 = floatInVec(scalar).get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &scalar ) +{ + mVec128 = scalar.get128(); +} + +VECTORMATH_FORCE_INLINE Point3::Point3( __m128 vf4 ) +{ + mVec128 = vf4; +} + +VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lerp( floatInVec(t), pnt0, pnt1 ); +} + +VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ) +{ + return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); +} + +VECTORMATH_FORCE_INLINE __m128 Point3::get128( ) const +{ + return mVec128; +} + +VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ) +{ + __m128 dstVec = *quad; + VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize + dstVec = vec_sel(pnt.get128(), dstVec, sw); + *quad = dstVec; +} + +VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ) +{ + const float *quads = (float *)threeQuads; + pnt0 = Point3( _mm_load_ps(quads) ); + pnt1 = Point3( _mm_loadu_ps(quads + 3) ); + pnt2 = Point3( _mm_loadu_ps(quads + 6) ); + pnt3 = Point3( _mm_loadu_ps(quads + 9) ); +} + +VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ) +{ + __m128 xxxx = _mm_shuffle_ps( pnt1.get128(), pnt1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); + __m128 zzzz = _mm_shuffle_ps( pnt2.get128(), pnt2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); + VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; + VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; + threeQuads[0] = vec_sel( pnt0.get128(), xxxx, xsw ); + threeQuads[1] = _mm_shuffle_ps( pnt1.get128(), pnt2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); + threeQuads[2] = vec_sel( _mm_shuffle_ps( pnt3.get128(), pnt3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); +} +/* +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ) +{ +#if 0 + __m128 xyz0[3]; + __m128 xyz1[3]; + storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); + storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); + threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); + threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); + threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); +#else + assert(0); +#endif +} +*/ +VECTORMATH_FORCE_INLINE Point3 & Point3::operator =( const Point3 &pnt ) +{ + mVec128 = pnt.mVec128; + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setX( float _x ) +{ + _vmathVfSetElement(mVec128, _x, 0); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setX( const floatInVec &_x ) +{ + mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getX( ) const +{ + return floatInVec( mVec128, 0 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setY( float _y ) +{ + _vmathVfSetElement(mVec128, _y, 1); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setY( const floatInVec &_y ) +{ + mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getY( ) const +{ + return floatInVec( mVec128, 1 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( float _z ) +{ + _vmathVfSetElement(mVec128, _z, 2); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( const floatInVec &_z ) +{ + mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getZ( ) const +{ + return floatInVec( mVec128, 2 ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, float value ) +{ + _vmathVfSetElement(mVec128, value, idx); + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, const floatInVec &value ) +{ + mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); + return *this; +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::getElem( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE VecIdx Point3::operator []( int idx ) +{ + return VecIdx( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const floatInVec Point3::operator []( int idx ) const +{ + return floatInVec( mVec128, idx ); +} + +VECTORMATH_FORCE_INLINE const Vector3 Point3::operator -( const Point3 &pnt ) const +{ + return Vector3( _mm_sub_ps( mVec128, pnt.mVec128 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Point3::operator +( const Vector3 &vec ) const +{ + return Point3( _mm_add_ps( mVec128, vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 Point3::operator -( const Vector3 &vec ) const +{ + return Point3( _mm_sub_ps( mVec128, vec.get128() ) ); +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::operator +=( const Vector3 &vec ) +{ + *this = *this + vec; + return *this; +} + +VECTORMATH_FORCE_INLINE Point3 & Point3::operator -=( const Vector3 &vec ) +{ + *this = *this - vec; + return *this; +} + +VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_mul_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_div_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ) +{ + return Point3( _mm_rcp_ps( pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ) +{ + return Point3( fabsf4( pnt.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + __m128 vmask = toM128(0x7fffffff); + return Point3( _mm_or_ps( + _mm_and_ps ( vmask, pnt0.get128() ), // Value + _mm_andnot_ps( vmask, pnt1.get128() ) ) ); // Signs +} + +VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_max_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ) +{ + return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return Point3( _mm_min_ps( pnt0.get128(), pnt1.get128() ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ) +{ + return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ) +{ + return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ) +{ + return scale( pnt, floatInVec( scaleVal ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ) +{ + return mulPerElem( pnt, Point3( scaleVal ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ) +{ + return mulPerElem( pnt, Point3( scaleVec ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ) +{ + return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ) +{ + return lengthSqr( Vector3( pnt ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ) +{ + return length( Vector3( pnt ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return lengthSqr( ( pnt1 - pnt0 ) ); +} + +VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ) +{ + return length( ( pnt1 - pnt0 ) ); +} + +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ) +{ + return select( pnt0, pnt1, boolInVec(select1) ); +} + +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ) +{ + return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) ); +} + + + +#ifdef _VECTORMATH_DEBUG + +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ) +{ + union { __m128 v; float s[4]; } tmp; + tmp.v = pnt.get128(); + printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); +} + +#endif + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/sse/vecidx_aos.h b/Code/Physics/src/vectormath/sse/vecidx_aos.h new file mode 100644 index 00000000..8ba4b1d7 --- /dev/null +++ b/Code/Physics/src/vectormath/sse/vecidx_aos.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VECTORMATH_VECIDX_AOS_H +#define _VECTORMATH_VECIDX_AOS_H + + +#include "floatInVec.h" + +namespace Vectormath { +namespace Aos { + +//----------------------------------------------------------------------------- +// VecIdx +// Used in setting elements of Vector3, Vector4, Point3, or Quat with the +// subscripting operator. +// + +VM_ATTRIBUTE_ALIGNED_CLASS16 (class) VecIdx +{ +private: + __m128 &ref; + int i; +public: + inline VecIdx( __m128& vec, int idx ): ref(vec) { i = idx; } + + // implicitly casts to float unless _VECTORMATH_NO_SCALAR_CAST defined + // in which case, implicitly casts to floatInVec, and one must call + // getAsFloat to convert to float. + // +#ifdef _VECTORMATH_NO_SCALAR_CAST + inline operator floatInVec() const; + inline float getAsFloat() const; +#else + inline operator float() const; +#endif + + inline float operator =( float scalar ); + inline floatInVec operator =( const floatInVec &scalar ); + inline floatInVec operator =( const VecIdx& scalar ); + inline floatInVec operator *=( float scalar ); + inline floatInVec operator *=( const floatInVec &scalar ); + inline floatInVec operator /=( float scalar ); + inline floatInVec operator /=( const floatInVec &scalar ); + inline floatInVec operator +=( float scalar ); + inline floatInVec operator +=( const floatInVec &scalar ); + inline floatInVec operator -=( float scalar ); + inline floatInVec operator -=( const floatInVec &scalar ); +}; + +} // namespace Aos +} // namespace Vectormath + +#endif diff --git a/Code/Physics/src/vectormath/sse/vectormath_aos.h b/Code/Physics/src/vectormath/sse/vectormath_aos.h new file mode 100644 index 00000000..be5ae8c6 --- /dev/null +++ b/Code/Physics/src/vectormath/sse/vectormath_aos.h @@ -0,0 +1,2547 @@ +/* + Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that the + following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Sony Computer Entertainment Inc nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _VECTORMATH_AOS_CPP_SSE_H +#define _VECTORMATH_AOS_CPP_SSE_H + +#include +#include +#include +#include + +#define Vector3Ref Vector3& +#define QuatRef Quat& +#define Matrix3Ref Matrix3& + +#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) + #define USE_SSE3_LDDQU + + #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) __declspec(align(16)) a + #define VM_ATTRIBUTE_ALIGN16 __declspec(align(16)) + #define VECTORMATH_FORCE_INLINE __forceinline +#else + #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) a __attribute__ ((aligned (16))) + #define VM_ATTRIBUTE_ALIGN16 __attribute__ ((aligned (16))) + #define VECTORMATH_FORCE_INLINE inline __attribute__ ((always_inline)) + #ifdef __SSE3__ + #define USE_SSE3_LDDQU + #endif //__SSE3__ +#endif//_WIN32 + + +#ifdef USE_SSE3_LDDQU +#include //_mm_lddqu_si128 +#endif //USE_SSE3_LDDQU + + +// TODO: Tidy +typedef __m128 vec_float4; +typedef __m128 vec_uint4; +typedef __m128 vec_int4; +typedef __m128i vec_uchar16; +typedef __m128i vec_ushort8; + +#define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) + +#define _mm_ror_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec)) +#define _mm_rol_ps(vec,i) \ + (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(7-i)%4,(unsigned char)(6-i)%4,(unsigned char)(5-i)%4,(unsigned char)(4-i)%4))) : (vec)) + +#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4)) + +#define _mm_abs_ps(vec) _mm_andnot_ps(_MASKSIGN_,vec) +#define _mm_neg_ps(vec) _mm_xor_ps(_MASKSIGN_,vec) + +#define vec_madd(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b) ) + +union SSEFloat +{ + __m128i vi; + __m128 m128; + __m128 vf; + unsigned int ui[4]; + unsigned short s[8]; + float f[4]; + SSEFloat(__m128 v) : m128(v) {} + SSEFloat(__m128i v) : vi(v) {} + SSEFloat() {}//uninitialized +}; + +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, __m128 mask) +{ + return _mm_or_ps(_mm_and_ps(mask, b), _mm_andnot_ps(mask, a)); +} +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, const unsigned int *_mask) +{ + return vec_sel(a, b, _mm_load_ps((float *)_mask)); +} +static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, unsigned int _mask) +{ + return vec_sel(a, b, _mm_set1_ps(*(float *)&_mask)); +} + +static VECTORMATH_FORCE_INLINE __m128 toM128(unsigned int x) +{ + return _mm_set1_ps( *(float *)&x ); +} + +static VECTORMATH_FORCE_INLINE __m128 fabsf4(__m128 x) +{ + return _mm_and_ps( x, toM128( 0x7fffffff ) ); +} +/* +union SSE64 +{ + __m128 m128; + struct + { + __m64 m01; + __m64 m23; + } m64; +}; + +static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m64.m01 = _mm_cvttps_pi32(x); + sse64.m64.m23 = _mm_cvttps_pi32(_mm_ror_ps(x,2)); + _mm_empty(); + return sse64.m128; +} + +static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + SSE64 sse64; + sse64.m128 = x; + __m128 result =_mm_movelh_ps( + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m01), + _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m23)); + _mm_empty(); + return result; +} +*/ +static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + __m128i result = _mm_cvtps_epi32(x); + return (__m128 &)result; +} + +static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) +{ + assert(a == 0); // Only 2^0 supported + (void)a; + return _mm_cvtepi32_ps((__m128i &)x); +} + +#define vec_nmsub(a,b,c) _mm_sub_ps( c, _mm_mul_ps( a, b ) ) +#define vec_sub(a,b) _mm_sub_ps( a, b ) +#define vec_add(a,b) _mm_add_ps( a, b ) +#define vec_mul(a,b) _mm_mul_ps( a, b ) +#define vec_xor(a,b) _mm_xor_ps( a, b ) +#define vec_and(a,b) _mm_and_ps( a, b ) +#define vec_cmpeq(a,b) _mm_cmpeq_ps( a, b ) +#define vec_cmpgt(a,b) _mm_cmpgt_ps( a, b ) + +#define vec_mergeh(a,b) _mm_unpacklo_ps( a, b ) +#define vec_mergel(a,b) _mm_unpackhi_ps( a, b ) + +#define vec_andc(a,b) _mm_andnot_ps( b, a ) + +#define sqrtf4(x) _mm_sqrt_ps( x ) +#define rsqrtf4(x) _mm_rsqrt_ps( x ) +#define recipf4(x) _mm_rcp_ps( x ) +#define negatef4(x) _mm_sub_ps( _mm_setzero_ps(), x ) + +static VECTORMATH_FORCE_INLINE __m128 newtonrapson_rsqrt4( const __m128 v ) +{ +#define _half4 _mm_setr_ps(.5f,.5f,.5f,.5f) +#define _three _mm_setr_ps(3.f,3.f,3.f,3.f) +const __m128 approx = _mm_rsqrt_ps( v ); +const __m128 muls = _mm_mul_ps(_mm_mul_ps(v, approx), approx); +return _mm_mul_ps(_mm_mul_ps(_half4, approx), _mm_sub_ps(_three, muls) ); +} + +static VECTORMATH_FORCE_INLINE __m128 acosf4(__m128 x) +{ + __m128 xabs = fabsf4(x); + __m128 select = _mm_cmplt_ps( x, _mm_setzero_ps() ); + __m128 t1 = sqrtf4(vec_sub(_mm_set1_ps(1.0f), xabs)); + + /* Instruction counts can be reduced if the polynomial was + * computed entirely from nested (dependent) fma's. However, + * to reduce the number of pipeline stalls, the polygon is evaluated + * in two halves (hi amd lo). + */ + __m128 xabs2 = _mm_mul_ps(xabs, xabs); + __m128 xabs4 = _mm_mul_ps(xabs2, xabs2); + __m128 hi = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0012624911f), + xabs, _mm_set1_ps(0.0066700901f)), + xabs, _mm_set1_ps(-0.0170881256f)), + xabs, _mm_set1_ps( 0.0308918810f)); + __m128 lo = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0501743046f), + xabs, _mm_set1_ps(0.0889789874f)), + xabs, _mm_set1_ps(-0.2145988016f)), + xabs, _mm_set1_ps( 1.5707963050f)); + + __m128 result = vec_madd(hi, xabs4, lo); + + // Adjust the result if x is negactive. + return vec_sel( + vec_mul(t1, result), // Positive + vec_nmsub(t1, result, _mm_set1_ps(3.1415926535898f)), // Negative + select); +} + +static VECTORMATH_FORCE_INLINE __m128 sinf4(vec_float4 x) +{ + +// +// Common constants used to evaluate sinf4/cosf4/tanf4 +// +#define _SINCOS_CC0 -0.0013602249f +#define _SINCOS_CC1 0.0416566950f +#define _SINCOS_CC2 -0.4999990225f +#define _SINCOS_SC0 -0.0001950727f +#define _SINCOS_SC1 0.0083320758f +#define _SINCOS_SC2 -0.1666665247f + +#define _SINCOS_KC1 1.57079625129f +#define _SINCOS_KC2 7.54978995489e-8f + + vec_float4 xl,xl2,xl3,res; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + vec_int4 q = vec_cts(xl,0); + + // Compute an offset based on the quadrant that the angle falls in + // + vec_int4 offset = _mm_and_ps(q,toM128(0x3)); + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + res = vec_sel(cx,sx,vec_cmpeq(vec_and(offset, + toM128(0x1)), + _mm_setzero_ps())); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + return vec_sel( + vec_xor(toM128(0x80000000U), res), // Negative + res, // Positive + vec_cmpeq(vec_and(offset,toM128(0x2)),_mm_setzero_ps())); +} + +static VECTORMATH_FORCE_INLINE void sincosf4(vec_float4 x, vec_float4* s, vec_float4* c) +{ + vec_float4 xl,xl2,xl3; + vec_int4 offsetSin, offsetCos; + + // Range reduction using : xl = angle * TwoOverPi; + // + xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); + + // Find the quadrant the angle falls in + // using: q = (int) (ceil(abs(xl))*sign(xl)) + // + //vec_int4 q = vec_cts(vec_add(xl,vec_sel(_mm_set1_ps(0.5f),xl,(0x80000000))),0); + vec_int4 q = vec_cts(xl,0); + + // Compute the offset based on the quadrant that the angle falls in. + // Add 1 to the offset for the cosine. + // + offsetSin = vec_and(q,toM128((int)0x3)); + __m128i temp = _mm_add_epi32(_mm_set1_epi32(1),(__m128i &)offsetSin); + offsetCos = (__m128 &)temp; + + // Remainder in range [-pi/4..pi/4] + // + vec_float4 qf = vec_ctf(q,0); + xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); + + // Compute x^2 and x^3 + // + xl2 = vec_mul(xl,xl); + xl3 = vec_mul(xl2,xl); + + // Compute both the sin and cos of the angles + // using a polynomial expression: + // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and + // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) + // + vec_float4 cx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); + vec_float4 sx = + vec_madd( + vec_madd( + vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); + + // Use the cosine when the offset is odd and the sin + // when the offset is even + // + vec_uint4 sinMask = (vec_uint4)vec_cmpeq(vec_and(offsetSin,toM128(0x1)),_mm_setzero_ps()); + vec_uint4 cosMask = (vec_uint4)vec_cmpeq(vec_and(offsetCos,toM128(0x1)),_mm_setzero_ps()); + *s = vec_sel(cx,sx,sinMask); + *c = vec_sel(cx,sx,cosMask); + + // Flip the sign of the result when (offset mod 4) = 1 or 2 + // + sinMask = vec_cmpeq(vec_and(offsetSin,toM128(0x2)),_mm_setzero_ps()); + cosMask = vec_cmpeq(vec_and(offsetCos,toM128(0x2)),_mm_setzero_ps()); + + *s = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*s),*s,sinMask); + *c = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*c),*c,cosMask); +} + +#include "vecidx_aos.h" +#include "floatInVec.h" +#include "boolInVec.h" + +#ifdef _VECTORMATH_DEBUG +#include +#endif +namespace Vectormath { + +namespace Aos { + +//----------------------------------------------------------------------------- +// Forward Declarations +// + +class Vector3; +class Vector4; +class Point3; +class Quat; +class Matrix3; +class Matrix4; +class Transform3; + +// A 3-D vector in array-of-structures format +// +class Vector3 +{ + __m128 mVec128; + + VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); + + VECTORMATH_FORCE_INLINE vec_float4& get128Ref(); + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Vector3( ) { }; + + // Default copy constructor + // + VECTORMATH_FORCE_INLINE Vector3(const Vector3& vec); + + // Construct a 3-D vector from x, y, and z elements + // + VECTORMATH_FORCE_INLINE Vector3( float x, float y, float z ); + + // Construct a 3-D vector from x, y, and z elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D point into a 3-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector3( const Point3 &pnt ); + + // Set all elements of a 3-D vector to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Vector3( float scalar ); + + // Set all elements of a 3-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Vector3( const floatInVec &scalar ); + + // Set vector float data in a 3-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector3( __m128 vf4 ); + + // Get vector float data from a 3-D vector + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 3-D vector to another + // + VECTORMATH_FORCE_INLINE Vector3 & operator =( const Vector3 &vec ); + + // Set the x element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setX( float x ); + + // Set the y element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setY( float y ); + + // Set the z element of a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & setZ( float z ); + + // Set the x element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 3-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D vector by index + // + VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D vector by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D vector by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two 3-D vectors + // + VECTORMATH_FORCE_INLINE const Vector3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from another 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( const Vector3 &vec ) const; + + // Add a 3-D vector to a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator +( const Point3 &pnt ) const; + + // Multiply a 3-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar ) const; + + // Divide a 3-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector3 operator /( float scalar ) const; + + // Multiply a 3-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar ) const; + + // Divide a 3-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector3 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + VECTORMATH_FORCE_INLINE Vector3 & operator -=( const Vector3 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Vector3 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Vector3 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector3 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( ) const; + + // Construct x axis + // + static VECTORMATH_FORCE_INLINE const Vector3 xAxis( ); + + // Construct y axis + // + static VECTORMATH_FORCE_INLINE const Vector3 yAxis( ); + + // Construct z axis + // + static VECTORMATH_FORCE_INLINE const Vector3 zAxis( ); + +}; + +// Multiply a 3-D vector by a scalar +// +VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ); + +// Multiply a 3-D vector by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ); + +// Multiply two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Divide two 3-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the reciprocal of a 3-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ); + +// Compute the absolute value of a 3-D vector per element +// +VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ); + +// Copy sign from one 3-D vector to another, per element +// +VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum of two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Minimum of two 3-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ); + +// Maximum element of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ); + +// Minimum element of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ); + +// Compute the sum of all elements of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ); + +// Compute the dot product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ); + +// Compute the square of the length of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ); + +// Compute the length of a 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ); + +// Normalize a 3-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ); + +// Compute cross product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ); + +// Outer product of two 3-D vectors +// +VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &vec0, const Vector3 &vec1 ); + +// Pre-multiply a row vector by a 3x3 matrix +// NOTE: +// Slower than column post-multiply. +// +VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ); + +// Cross-product matrix of a 3-D vector +// +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ); + +// Create cross-product matrix and multiply +// NOTE: +// Faster than separately creating a cross-product matrix and multiplying. +// +VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ); + +// Linear interpolation between two 3-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ); + +// Spherical linear interpolation between two 3-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Spherical linear interpolation between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); + +// Conditionally select between two 3-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ); + +// Conditionally select between two 3-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D vector in first three words of a quadword, preserving fourth word +// +VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ); + +// Load four three-float 3-D vectors, stored in three quadwords +// +VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ); + +// Store four 3-D vectors in three quadwords +// +VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ); + +// Store eight 3-D vectors as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ); + +// Print a 3-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ); + +#endif + +// A 4-D vector in array-of-structures format +// +class Vector4 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Vector4( ) { }; + + // Construct a 4-D vector from x, y, z, and w elements + // + VECTORMATH_FORCE_INLINE Vector4( float x, float y, float z, float w ); + + // Construct a 4-D vector from x, y, z, and w elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a 4-D vector from a 3-D vector and a scalar + // + VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, float w ); + + // Construct a 4-D vector from a 3-D vector and a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, const floatInVec &w ); + + // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Vector3 &vec ); + + // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Point3 &pnt ); + + // Copy elements from a quaternion into a 4-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector4( const Quat &quat ); + + // Set all elements of a 4-D vector to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Vector4( float scalar ); + + // Set all elements of a 4-D vector to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Vector4( const floatInVec &scalar ); + + // Set vector float data in a 4-D vector + // + explicit VECTORMATH_FORCE_INLINE Vector4( __m128 vf4 ); + + // Get vector float data from a 4-D vector + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 4-D vector to another + // + VECTORMATH_FORCE_INLINE Vector4 & operator =( const Vector4 &vec ); + + // Set the x, y, and z elements of a 4-D vector + // NOTE: + // This function does not change the w element. + // + VECTORMATH_FORCE_INLINE Vector4 & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; + + // Set the x element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setX( float x ); + + // Set the y element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setY( float y ); + + // Set the z element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setZ( float z ); + + // Set the w element of a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & setW( float w ); + + // Set the x element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setX( const floatInVec &x ); + + // Set the y element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setY( const floatInVec &y ); + + // Set the z element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setZ( const floatInVec &z ); + + // Set the w element of a 4-D vector (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setW( const floatInVec &w ); + + // Get the x element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Get the w element of a 4-D vector + // + VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a 4-D vector by index + // + VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a 4-D vector by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a 4-D vector by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two 4-D vectors + // + VECTORMATH_FORCE_INLINE const Vector4 operator +( const Vector4 &vec ) const; + + // Subtract a 4-D vector from another 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator -( const Vector4 &vec ) const; + + // Multiply a 4-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar ) const; + + // Divide a 4-D vector by a scalar + // + VECTORMATH_FORCE_INLINE const Vector4 operator /( float scalar ) const; + + // Multiply a 4-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar ) const; + + // Divide a 4-D vector by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Vector4 operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & operator +=( const Vector4 &vec ); + + // Perform compound assignment and subtraction by a 4-D vector + // + VECTORMATH_FORCE_INLINE Vector4 & operator -=( const Vector4 &vec ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Vector4 & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Vector4 & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Vector4 & operator /=( const floatInVec &scalar ); + + // Negate all elements of a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator -( ) const; + + // Construct x axis + // + static VECTORMATH_FORCE_INLINE const Vector4 xAxis( ); + + // Construct y axis + // + static VECTORMATH_FORCE_INLINE const Vector4 yAxis( ); + + // Construct z axis + // + static VECTORMATH_FORCE_INLINE const Vector4 zAxis( ); + + // Construct w axis + // + static VECTORMATH_FORCE_INLINE const Vector4 wAxis( ); + +}; + +// Multiply a 4-D vector by a scalar +// +VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ); + +// Multiply a 4-D vector by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ); + +// Multiply two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Divide two 4-D vectors per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the reciprocal of a 4-D vector per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ); + +// Compute the absolute value of a 4-D vector per element +// +VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ); + +// Copy sign from one 4-D vector to another, per element +// +VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum of two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Minimum of two 4-D vectors per element +// +VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ); + +// Maximum element of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ); + +// Minimum element of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ); + +// Compute the sum of all elements of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ); + +// Compute the dot product of two 4-D vectors +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ); + +// Compute the square of the length of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ); + +// Compute the length of a 4-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ); + +// Normalize a 4-D vector +// NOTE: +// The result is unpredictable when all elements of vec are at or near zero. +// +VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ); + +// Outer product of two 4-D vectors +// +VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ); + +// Spherical linear interpolation between two 4-D vectors +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Spherical linear interpolation between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// The result is unpredictable if the vectors point in opposite directions. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); + +// Conditionally select between two 4-D vectors +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ); + +// Conditionally select between two 4-D vectors (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, const boolInVec &select1 ); + +// Store four 4-D vectors as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4-D vector +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ); + +// Print a 4-D vector and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ); + +#endif + +// A 3-D point in array-of-structures format +// +class Point3 +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Point3( ) { }; + + // Construct a 3-D point from x, y, and z elements + // + VECTORMATH_FORCE_INLINE Point3( float x, float y, float z ); + + // Construct a 3-D point from x, y, and z elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); + + // Copy elements from a 3-D vector into a 3-D point + // + explicit VECTORMATH_FORCE_INLINE Point3( const Vector3 &vec ); + + // Set all elements of a 3-D point to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Point3( float scalar ); + + // Set all elements of a 3-D point to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Point3( const floatInVec &scalar ); + + // Set vector float data in a 3-D point + // + explicit VECTORMATH_FORCE_INLINE Point3( __m128 vf4 ); + + // Get vector float data from a 3-D point + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Assign one 3-D point to another + // + VECTORMATH_FORCE_INLINE Point3 & operator =( const Point3 &pnt ); + + // Set the x element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setX( float x ); + + // Set the y element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setY( float y ); + + // Set the z element of a 3-D point + // + VECTORMATH_FORCE_INLINE Point3 & setZ( float z ); + + // Set the x element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setX( const floatInVec &x ); + + // Set the y element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setY( const floatInVec &y ); + + // Set the z element of a 3-D point (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setZ( const floatInVec &z ); + + // Get the x element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a 3-D point + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Set an x, y, or z element of a 3-D point by index + // + VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, float value ); + + // Set an x, y, or z element of a 3-D point by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, const floatInVec &value ); + + // Get an x, y, or z element of a 3-D point by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Subtract a 3-D point from another 3-D point + // + VECTORMATH_FORCE_INLINE const Vector3 operator -( const Point3 &pnt ) const; + + // Add a 3-D point to a 3-D vector + // + VECTORMATH_FORCE_INLINE const Point3 operator +( const Vector3 &vec ) const; + + // Subtract a 3-D vector from a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator -( const Vector3 &vec ) const; + + // Perform compound assignment and addition with a 3-D vector + // + VECTORMATH_FORCE_INLINE Point3 & operator +=( const Vector3 &vec ); + + // Perform compound assignment and subtraction by a 3-D vector + // + VECTORMATH_FORCE_INLINE Point3 & operator -=( const Vector3 &vec ); + +}; + +// Multiply two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Divide two 3-D points per element +// NOTE: +// Floating-point behavior matches standard library function divf4. +// +VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the reciprocal of a 3-D point per element +// NOTE: +// Floating-point behavior matches standard library function recipf4. +// +VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ); + +// Compute the absolute value of a 3-D point per element +// +VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ); + +// Copy sign from one 3-D point to another, per element +// +VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum of two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Minimum of two 3-D points per element +// +VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ); + +// Maximum element of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ); + +// Minimum element of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ); + +// Compute the sum of all elements of a 3-D point +// +VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ); + +// Apply uniform scale to a 3-D point +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ); + +// Apply uniform scale to a 3-D point (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ); + +// Apply non-uniform scale to a 3-D point +// +VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ); + +// Scalar projection of a 3-D point on a unit-length 3-D vector +// +VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ); + +// Compute the square of the distance of a 3-D point from the coordinate-system origin +// +VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ); + +// Compute the distance of a 3-D point from the coordinate-system origin +// +VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ); + +// Compute the square of the distance between two 3-D points +// +VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ); + +// Compute the distance between two 3-D points +// +VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Linear interpolation between two 3-D points (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ); + +// Conditionally select between two 3-D points +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ); + +// Conditionally select between two 3-D points (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ); + +// Store x, y, and z elements of 3-D point in first three words of a quadword, preserving fourth word +// +VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ); + +// Load four three-float 3-D points, stored in three quadwords +// +VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ); + +// Store four 3-D points in three quadwords +// +VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ); + +// Store eight 3-D points as half-floats +// +VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3-D point +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ); + +// Print a 3-D point and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ); + +#endif + +// A quaternion in array-of-structures format +// +class Quat +{ + __m128 mVec128; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Quat( ) { }; + + VECTORMATH_FORCE_INLINE Quat(const Quat& quat); + + // Construct a quaternion from x, y, z, and w elements + // + VECTORMATH_FORCE_INLINE Quat( float x, float y, float z, float w ); + + // Construct a quaternion from x, y, z, and w elements (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); + + // Construct a quaternion from a 3-D vector and a scalar + // + VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, float w ); + + // Construct a quaternion from a 3-D vector and a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, const floatInVec &w ); + + // Copy elements from a 4-D vector into a quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( const Vector4 &vec ); + + // Convert a rotation matrix to a unit-length quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( const Matrix3 & rotMat ); + + // Set all elements of a quaternion to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Quat( float scalar ); + + // Set all elements of a quaternion to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Quat( const floatInVec &scalar ); + + // Set vector float data in a quaternion + // + explicit VECTORMATH_FORCE_INLINE Quat( __m128 vf4 ); + + // Get vector float data from a quaternion + // + VECTORMATH_FORCE_INLINE __m128 get128( ) const; + + // Set a quaterion from vector float data + // + VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); + + // Assign one quaternion to another + // + VECTORMATH_FORCE_INLINE Quat & operator =( const Quat &quat ); + + // Set the x, y, and z elements of a quaternion + // NOTE: + // This function does not change the w element. + // + VECTORMATH_FORCE_INLINE Quat & setXYZ( const Vector3 &vec ); + + // Get the x, y, and z elements of a quaternion + // + VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; + + // Set the x element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setX( float x ); + + // Set the y element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setY( float y ); + + // Set the z element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setZ( float z ); + + // Set the w element of a quaternion + // + VECTORMATH_FORCE_INLINE Quat & setW( float w ); + + // Set the x element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setX( const floatInVec &x ); + + // Set the y element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setY( const floatInVec &y ); + + // Set the z element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setZ( const floatInVec &z ); + + // Set the w element of a quaternion (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setW( const floatInVec &w ); + + // Get the x element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; + + // Get the y element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; + + // Get the z element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; + + // Get the w element of a quaternion + // + VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; + + // Set an x, y, z, or w element of a quaternion by index + // + VECTORMATH_FORCE_INLINE Quat & setElem( int idx, float value ); + + // Set an x, y, z, or w element of a quaternion by index (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & setElem( int idx, const floatInVec &value ); + + // Get an x, y, z, or w element of a quaternion by index + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; + + // Subscripting operator to set or get an element + // + VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); + + // Subscripting operator to get an element + // + VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; + + // Add two quaternions + // + VECTORMATH_FORCE_INLINE const Quat operator +( const Quat &quat ) const; + + // Subtract a quaternion from another quaternion + // + VECTORMATH_FORCE_INLINE const Quat operator -( const Quat &quat ) const; + + // Multiply two quaternions + // + VECTORMATH_FORCE_INLINE const Quat operator *( const Quat &quat ) const; + + // Multiply a quaternion by a scalar + // + VECTORMATH_FORCE_INLINE const Quat operator *( float scalar ) const; + + // Divide a quaternion by a scalar + // + VECTORMATH_FORCE_INLINE const Quat operator /( float scalar ) const; + + // Multiply a quaternion by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar ) const; + + // Divide a quaternion by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Quat operator /( const floatInVec &scalar ) const; + + // Perform compound assignment and addition with a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator +=( const Quat &quat ); + + // Perform compound assignment and subtraction by a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator -=( const Quat &quat ); + + // Perform compound assignment and multiplication by a quaternion + // + VECTORMATH_FORCE_INLINE Quat & operator *=( const Quat &quat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Quat & operator *=( float scalar ); + + // Perform compound assignment and division by a scalar + // + VECTORMATH_FORCE_INLINE Quat & operator /=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and division by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Quat & operator /=( const floatInVec &scalar ); + + // Negate all elements of a quaternion + // + VECTORMATH_FORCE_INLINE const Quat operator -( ) const; + + // Construct an identity quaternion + // + static VECTORMATH_FORCE_INLINE const Quat identity( ); + + // Construct a quaternion to rotate between two unit-length 3-D vectors + // NOTE: + // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. + // + static VECTORMATH_FORCE_INLINE const Quat rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ); + + // Construct a quaternion to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Quat rotation( float radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a quaternion to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationX( float radians ); + + // Construct a quaternion to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationY( float radians ); + + // Construct a quaternion to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Quat rotationZ( float radians ); + + // Construct a quaternion to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationX( const floatInVec &radians ); + + // Construct a quaternion to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationY( const floatInVec &radians ); + + // Construct a quaternion to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Quat rotationZ( const floatInVec &radians ); + +}; + +// Multiply a quaternion by a scalar +// +VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ); + +// Multiply a quaternion by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ); + +// Compute the conjugate of a quaternion +// +VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ); + +// Use a unit-length quaternion to rotate a 3-D vector +// +VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &unitQuat, const Vector3 &vec ); + +// Compute the dot product of two quaternions +// +VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ); + +// Compute the norm of a quaternion +// +VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ); + +// Compute the length of a quaternion +// +VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ); + +// Normalize a quaternion +// NOTE: +// The result is unpredictable when all elements of quat are at or near zero. +// +VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ); + +// Linear interpolation between two quaternions +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ); + +// Linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ); + +// Spherical linear interpolation between two quaternions +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical linear interpolation between two quaternions (scalar data contained in vector data type) +// NOTE: +// Interpolates along the shortest path between orientations. +// Does not clamp t between 0 and 1. +// +VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ); + +// Spherical quadrangle interpolation +// +VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Spherical quadrangle interpolation (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); + +// Conditionally select between two quaternions +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ); + +// Conditionally select between two quaternions (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a quaternion +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Quat &quat ); + +// Print a quaternion and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ); + +#endif + +// A 3x3 matrix in array-of-structures format +// +class Matrix3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Matrix3( ) { }; + + // Copy a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3( const Matrix3 & mat ); + + // Construct a 3x3 matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Matrix3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2 ); + + // Construct a 3x3 rotation matrix from a unit-length quaternion + // + explicit VECTORMATH_FORCE_INLINE Matrix3( const Quat &unitQuat ); + + // Set all elements of a 3x3 matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Matrix3( float scalar ); + + // Set all elements of a 3x3 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Matrix3( const floatInVec &scalar ); + + // Assign one 3x3 matrix to another + // + VECTORMATH_FORCE_INLINE Matrix3 & operator =( const Matrix3 & mat ); + + // Set column 0 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol2( const Vector3 &col2 ); + + // Get column 0 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; + + // Get column 1 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; + + // Get column 2 of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; + + // Set the column of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix3 & setRow( int row, const Vector3 &vec ); + + // Get the column of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; + + // Get the row of a 3x3 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; + + // Set the element of a 3x3 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, float val ); + + // Set the element of a 3x3 matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x3 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Add two 3x3 matrices + // + VECTORMATH_FORCE_INLINE const Matrix3 operator +( const Matrix3 & mat ) const; + + // Subtract a 3x3 matrix from another 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 operator -( const Matrix3 & mat ) const; + + // Negate all elements of a 3x3 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 operator -( ) const; + + // Multiply a 3x3 matrix by a scalar + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar ) const; + + // Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar ) const; + + // Multiply a 3x3 matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply two 3x3 matrices + // + VECTORMATH_FORCE_INLINE const Matrix3 operator *( const Matrix3 & mat ) const; + + // Perform compound assignment and addition with a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator +=( const Matrix3 & mat ); + + // Perform compound assignment and subtraction by a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator -=( const Matrix3 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 3x3 matrix + // + VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const Matrix3 & mat ); + + // Construct an identity 3x3 matrix + // + static VECTORMATH_FORCE_INLINE const Matrix3 identity( ); + + // Construct a 3x3 matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( float radians ); + + // Construct a 3x3 matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( float radians ); + + // Construct a 3x3 matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( float radians ); + + // Construct a 3x3 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( const floatInVec &radians ); + + // Construct a 3x3 matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x3 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const Quat &unitQuat ); + + // Construct a 3x3 matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Matrix3 scale( const Vector3 &scaleVec ); + +}; +// Multiply a 3x3 matrix by a scalar +// +VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ); + +// Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ); + +// Append (post-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x3 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ); + +// Multiply two 3x3 matrices per element +// +VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); + +// Compute the absolute value of a 3x3 matrix per element +// +VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ); + +// Transpose of a 3x3 matrix +// +VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ); + +// Compute the inverse of a 3x3 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ); + +// Determinant of a 3x3 matrix +// +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ); + +// Conditionally select between two 3x3 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); + +// Conditionally select between two 3x3 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x3 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ); + +// Print a 3x3 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ); + +#endif + +// A 4x4 matrix in array-of-structures format +// +class Matrix4 +{ + Vector4 mCol0; + Vector4 mCol1; + Vector4 mCol2; + Vector4 mCol3; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Matrix4( ) { }; + + // Copy a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4( const Matrix4 & mat ); + + // Construct a 4x4 matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Matrix4( const Vector4 &col0, const Vector4 &col1, const Vector4 &col2, const Vector4 &col3 ); + + // Construct a 4x4 matrix from a 3x4 transformation matrix + // + explicit VECTORMATH_FORCE_INLINE Matrix4( const Transform3 & mat ); + + // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector + // + VECTORMATH_FORCE_INLINE Matrix4( const Matrix3 & mat, const Vector3 &translateVec ); + + // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector + // + VECTORMATH_FORCE_INLINE Matrix4( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 4x4 matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Matrix4( float scalar ); + + // Set all elements of a 4x4 matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Matrix4( const floatInVec &scalar ); + + // Assign one 4x4 matrix to another + // + VECTORMATH_FORCE_INLINE Matrix4 & operator =( const Matrix4 & mat ); + + // Set the upper-left 3x3 submatrix + // NOTE: + // This function does not change the bottom row elements. + // + VECTORMATH_FORCE_INLINE Matrix4 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; + + // Set translation component + // NOTE: + // This function does not change the bottom row elements. + // + VECTORMATH_FORCE_INLINE Matrix4 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; + + // Set column 0 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol0( const Vector4 &col0 ); + + // Set column 1 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol1( const Vector4 &col1 ); + + // Set column 2 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol2( const Vector4 &col2 ); + + // Set column 3 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol3( const Vector4 &col3 ); + + // Get column 0 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol0( ) const; + + // Get column 1 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol1( ) const; + + // Get column 2 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol2( ) const; + + // Get column 3 of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Vector4 getCol3( ) const; + + // Set the column of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix4 & setCol( int col, const Vector4 &vec ); + + // Set the row of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Matrix4 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getCol( int col ) const; + + // Get the row of a 4x4 matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector4 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector4 operator []( int col ) const; + + // Set the element of a 4x4 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, float val ); + + // Set the element of a 4x4 matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 4x4 matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Add two 4x4 matrices + // + VECTORMATH_FORCE_INLINE const Matrix4 operator +( const Matrix4 & mat ) const; + + // Subtract a 4x4 matrix from another 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator -( const Matrix4 & mat ) const; + + // Negate all elements of a 4x4 matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator -( ) const; + + // Multiply a 4x4 matrix by a scalar + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar ) const; + + // Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar ) const; + + // Multiply a 4x4 matrix by a 4-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector4 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector3 &vec ) const; + + // Multiply a 4x4 matrix by a 3-D point + // + VECTORMATH_FORCE_INLINE const Vector4 operator *( const Point3 &pnt ) const; + + // Multiply two 4x4 matrices + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Matrix4 & mat ) const; + + // Multiply a 4x4 matrix by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and addition with a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator +=( const Matrix4 & mat ); + + // Perform compound assignment and subtraction by a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator -=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a scalar + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( float scalar ); + + // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const floatInVec &scalar ); + + // Perform compound assignment and multiplication by a 4x4 matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Matrix4 & mat ); + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 4x4 matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 identity( ); + + // Construct a 4x4 matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( float radians ); + + // Construct a 4x4 matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( float radians ); + + // Construct a 4x4 matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( float radians ); + + // Construct a 4x4 matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( const floatInVec &radians ); + + // Construct a 4x4 matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 4x4 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const Quat &unitQuat ); + + // Construct a 4x4 matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Matrix4 scale( const Vector3 &scaleVec ); + + // Construct a 4x4 matrix to perform translation + // + static VECTORMATH_FORCE_INLINE const Matrix4 translation( const Vector3 &translateVec ); + + // Construct viewing matrix based on eye, position looked at, and up direction + // + static VECTORMATH_FORCE_INLINE const Matrix4 lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ); + + // Construct a perspective projection matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); + + // Construct a perspective projection matrix based on frustum + // + static VECTORMATH_FORCE_INLINE const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); + + // Construct an orthographic projection matrix + // + static VECTORMATH_FORCE_INLINE const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); + +}; +// Multiply a 4x4 matrix by a scalar +// +VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ); + +// Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) +// +VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ); + +// Append (post-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 4x4 matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ); + +// Multiply two 4x4 matrices per element +// +VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); + +// Compute the absolute value of a 4x4 matrix per element +// +VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ); + +// Transpose of a 4x4 matrix +// +VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix +// NOTE: +// Result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ); + +// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. +// +VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ); + +// Determinant of a 4x4 matrix +// +VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ); + +// Conditionally select between two 4x4 matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); + +// Conditionally select between two 4x4 matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 4x4 matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ); + +// Print a 4x4 matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ); + +#endif + +// A 3x4 transformation matrix in array-of-structures format +// +class Transform3 +{ + Vector3 mCol0; + Vector3 mCol1; + Vector3 mCol2; + Vector3 mCol3; + +public: + // Default constructor; does no initialization + // + VECTORMATH_FORCE_INLINE Transform3( ) { }; + + // Copy a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3( const Transform3 & tfrm ); + + // Construct a 3x4 transformation matrix containing the specified columns + // + VECTORMATH_FORCE_INLINE Transform3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2, const Vector3 &col3 ); + + // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector + // + VECTORMATH_FORCE_INLINE Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ); + + // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector + // + VECTORMATH_FORCE_INLINE Transform3( const Quat &unitQuat, const Vector3 &translateVec ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value + // + explicit VECTORMATH_FORCE_INLINE Transform3( float scalar ); + + // Set all elements of a 3x4 transformation matrix to the same scalar value (scalar data contained in vector data type) + // + explicit VECTORMATH_FORCE_INLINE Transform3( const floatInVec &scalar ); + + // Assign one 3x4 transformation matrix to another + // + VECTORMATH_FORCE_INLINE Transform3 & operator =( const Transform3 & tfrm ); + + // Set the upper-left 3x3 submatrix + // + VECTORMATH_FORCE_INLINE Transform3 & setUpper3x3( const Matrix3 & mat3 ); + + // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; + + // Set translation component + // + VECTORMATH_FORCE_INLINE Transform3 & setTranslation( const Vector3 &translateVec ); + + // Get the translation component of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; + + // Set column 0 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol0( const Vector3 &col0 ); + + // Set column 1 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol1( const Vector3 &col1 ); + + // Set column 2 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol2( const Vector3 &col2 ); + + // Set column 3 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & setCol3( const Vector3 &col3 ); + + // Get column 0 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; + + // Get column 1 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; + + // Get column 2 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; + + // Get column 3 of a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE const Vector3 getCol3( ) const; + + // Set the column of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Transform3 & setCol( int col, const Vector3 &vec ); + + // Set the row of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE Transform3 & setRow( int row, const Vector4 &vec ); + + // Get the column of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; + + // Get the row of a 3x4 transformation matrix referred to by the specified index + // + VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; + + // Subscripting operator to set or get a column + // + VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); + + // Subscripting operator to get a column + // + VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; + + // Set the element of a 3x4 transformation matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, float val ); + + // Set the element of a 3x4 transformation matrix referred to by column and row indices (scalar data contained in vector data type) + // + VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, const floatInVec &val ); + + // Get the element of a 3x4 transformation matrix referred to by column and row indices + // + VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; + + // Multiply a 3x4 transformation matrix by a 3-D vector + // + VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; + + // Multiply a 3x4 transformation matrix by a 3-D point + // + VECTORMATH_FORCE_INLINE const Point3 operator *( const Point3 &pnt ) const; + + // Multiply two 3x4 transformation matrices + // + VECTORMATH_FORCE_INLINE const Transform3 operator *( const Transform3 & tfrm ) const; + + // Perform compound assignment and multiplication by a 3x4 transformation matrix + // + VECTORMATH_FORCE_INLINE Transform3 & operator *=( const Transform3 & tfrm ); + + // Construct an identity 3x4 transformation matrix + // + static VECTORMATH_FORCE_INLINE const Transform3 identity( ); + + // Construct a 3x4 transformation matrix to rotate around the x axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationX( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationY( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( float radians ); + + // Construct a 3x4 transformation matrix to rotate around the x axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationX( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the y axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationY( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the z axis (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( const floatInVec &radians ); + + // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes + // + static VECTORMATH_FORCE_INLINE const Transform3 rotationZYX( const Vector3 &radiansXYZ ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( float radians, const Vector3 &unitVec ); + + // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( const floatInVec &radians, const Vector3 &unitVec ); + + // Construct a rotation matrix from a unit-length quaternion + // + static VECTORMATH_FORCE_INLINE const Transform3 rotation( const Quat &unitQuat ); + + // Construct a 3x4 transformation matrix to perform scaling + // + static VECTORMATH_FORCE_INLINE const Transform3 scale( const Vector3 &scaleVec ); + + // Construct a 3x4 transformation matrix to perform translation + // + static VECTORMATH_FORCE_INLINE const Transform3 translation( const Vector3 &translateVec ); + +}; +// Append (post-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ); + +// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix +// NOTE: +// Faster than creating and multiplying a scale transformation matrix. +// +VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ); + +// Multiply two 3x4 transformation matrices per element +// +VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); + +// Compute the absolute value of a 3x4 transformation matrix per element +// +VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ); + +// Inverse of a 3x4 transformation matrix +// NOTE: +// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. +// +VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ); + +// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix +// NOTE: +// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. +// +VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ); + +// Conditionally select between two 3x4 transformation matrices +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// However, the transfer of select1 to a VMX register may use more processing time than a branch. +// Use the boolInVec version for better performance. +// +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); + +// Conditionally select between two 3x4 transformation matrices (scalar data contained in vector data type) +// NOTE: +// This function uses a conditional select instruction to avoid a branch. +// +VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ); + +#ifdef _VECTORMATH_DEBUG + +// Print a 3x4 transformation matrix +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ); + +// Print a 3x4 transformation matrix and an associated string identifier +// NOTE: +// Function is only defined when _VECTORMATH_DEBUG is defined. +// +VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ); + +#endif + +} // namespace Aos +} // namespace Vectormath + +#include "vec_aos.h" +#include "quat_aos.h" +#include "mat_aos.h" + +#endif diff --git a/Code/Physics/src/vectormath/vmInclude.h b/Code/Physics/src/vectormath/vmInclude.h new file mode 100644 index 00000000..656514e4 --- /dev/null +++ b/Code/Physics/src/vectormath/vmInclude.h @@ -0,0 +1,31 @@ + +#ifndef __VM_INCLUDE_H +#define __VM_INCLUDE_H + +#include "LinearMath/btScalar.h" + +#if defined (USE_SYSTEM_VECTORMATH) || defined (__CELLOS_LV2__) + #include +#else //(USE_SYSTEM_VECTORMATH) + #if defined (BT_USE_SSE) + #include "sse/vectormath_aos.h" + #else //all other platforms + #if defined (BT_USE_NEON) + #include "neon/vectormath_aos.h" + #else + #include "scalar/vectormath_aos.h" + #endif + #endif //(BT_USE_SSE) && defined (_WIN32) +#endif //(USE_SYSTEM_VECTORMATH) + + + +typedef Vectormath::Aos::Vector3 vmVector3; +typedef Vectormath::Aos::Quat vmQuat; +typedef Vectormath::Aos::Matrix3 vmMatrix3; +typedef Vectormath::Aos::Transform3 vmTransform3; +typedef Vectormath::Aos::Point3 vmPoint3; + +#endif //__VM_INCLUDE_H + + From 427ec3b7160240df753a3a8b988b2ca775fbe20d Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 10:52:08 +0100 Subject: [PATCH 18/35] Major overhaul fix --- Code/DanBias.sln | 158 +- .../DanBiasGame/GameClientState/GameState.cpp | 5 +- Code/GamePhysics/GamePhysics.vcxproj | 4 +- .../Implementation/SimpleRigidBody.cpp | 2 +- Code/Physics/ALL_BUILD.vcxproj | 244 + Code/Physics/BULLET_PHYSICS.sln | 162 + Code/Physics/Bullet Source/AUTHORS | 22 + Code/Physics/Bullet Source/BspDemo.bsp | Bin 0 -> 105100 bytes .../Bullet Source/BulletConfig.cmake.in | 25 + Code/Physics/Bullet Source/BulletLicense.txt | 18 + Code/Physics/Bullet Source/CMakeLists.txt | 439 ++ Code/Physics/Bullet Source/COPYING | 17 + Code/Physics/Bullet Source/ChangeLog | 795 +++ Code/Physics/Bullet Source/Doxyfile | 780 +++ .../Glut/EmptyGL/GL/egl_cpx.h | 0 .../Glut/EmptyGL/GL/egl_defs.h | 0 .../Glut/EmptyGL/GL/egl_logged.h | 0 .../Glut/EmptyGL/GL/egl_tokens.h | 0 .../Glut/EmptyGL/GL/egl_void.h | 0 .../{ => Bullet Source}/Glut/EmptyGL/GL/gl.h | 0 .../{ => Bullet Source}/Glut/EmptyGL/GL/glu.h | 0 .../Glut/EmptyGL/GL/glut.h | 0 .../{ => Bullet Source}/Glut/GL/glew.h | 0 .../{ => Bullet Source}/Glut/GL/glext.h | 0 .../{ => Bullet Source}/Glut/GL/glut.h | 0 .../{ => Bullet Source}/Glut/GL/glxew.h | 0 .../{ => Bullet Source}/Glut/GL/glxext.h | 0 .../{ => Bullet Source}/Glut/GL/wglew.h | 0 .../{ => Bullet Source}/Glut/GL/wglext.h | 0 .../{ => Bullet Source}/Glut/btGlutInclude.h | 0 Code/Physics/Bullet Source/INSTALL | 111 + Code/Physics/Bullet Source/Makefile.am | 7 + Code/Physics/Bullet Source/NEWS | 5 + Code/Physics/Bullet Source/README | 6 + Code/Physics/Bullet Source/RELEASING.TXT | 36 + Code/Physics/Bullet Source/UseBullet.cmake | 10 + Code/Physics/Bullet Source/VERSION | 1 + Code/Physics/Bullet Source/acinclude.m4 | 3054 +++++++++ Code/Physics/Bullet Source/autogen.sh | 61 + Code/Physics/Bullet Source/bullet.pc.cmake | 6 + Code/Physics/Bullet Source/bullet.pc.in | 11 + Code/Physics/Bullet Source/bullet_logo.png | Bin 0 -> 3380 bytes Code/Physics/Bullet Source/config.h.in | 113 + Code/Physics/Bullet Source/configure.ac | 172 + Code/Physics/Bullet Source/convex0.bin | Bin 0 -> 548 bytes Code/Physics/Bullet Source/file.obj | 3578 +++++++++++ .../Bullet Source/heightfield128x128.raw | 37 + Code/Physics/Bullet Source/install-sh | 322 + Code/Physics/Bullet Source/jenga.dae | 5632 +++++++++++++++++ .../{ => Bullet Source}/src/Bullet-C-Api.h | 0 .../BroadphaseCollision/btAxisSweep3.cpp | 0 .../BroadphaseCollision/btAxisSweep3.h | 0 .../btBroadphaseInterface.h | 0 .../BroadphaseCollision/btBroadphaseProxy.cpp | 0 .../BroadphaseCollision/btBroadphaseProxy.h | 0 .../btCollisionAlgorithm.cpp | 0 .../btCollisionAlgorithm.h | 0 .../BroadphaseCollision/btDbvt.cpp | 0 .../BroadphaseCollision/btDbvt.h | 0 .../BroadphaseCollision/btDbvtBroadphase.cpp | 0 .../BroadphaseCollision/btDbvtBroadphase.h | 0 .../BroadphaseCollision/btDispatcher.cpp | 0 .../BroadphaseCollision/btDispatcher.h | 0 .../btMultiSapBroadphase.cpp | 0 .../btMultiSapBroadphase.h | 0 .../btOverlappingPairCache.cpp | 0 .../btOverlappingPairCache.h | 0 .../btOverlappingPairCallback.h | 0 .../BroadphaseCollision/btQuantizedBvh.cpp | 0 .../BroadphaseCollision/btQuantizedBvh.h | 0 .../btSimpleBroadphase.cpp | 0 .../BroadphaseCollision/btSimpleBroadphase.h | 0 .../src/BulletCollision/CMakeLists.txt | 0 .../SphereTriangleDetector.cpp | 0 .../SphereTriangleDetector.h | 0 .../btActivatingCollisionAlgorithm.cpp | 0 .../btActivatingCollisionAlgorithm.h | 0 .../btBox2dBox2dCollisionAlgorithm.cpp | 0 .../btBox2dBox2dCollisionAlgorithm.h | 0 .../btBoxBoxCollisionAlgorithm.cpp | 0 .../btBoxBoxCollisionAlgorithm.h | 0 .../CollisionDispatch/btBoxBoxDetector.cpp | 0 .../CollisionDispatch/btBoxBoxDetector.h | 0 .../btCollisionConfiguration.h | 0 .../CollisionDispatch/btCollisionCreateFunc.h | 0 .../btCollisionDispatcher.cpp | 0 .../CollisionDispatch/btCollisionDispatcher.h | 0 .../CollisionDispatch/btCollisionObject.cpp | 0 .../CollisionDispatch/btCollisionObject.h | 0 .../btCollisionObjectWrapper.h | 0 .../CollisionDispatch/btCollisionWorld.cpp | 0 .../CollisionDispatch/btCollisionWorld.h | 0 .../btCompoundCollisionAlgorithm.cpp | 0 .../btCompoundCollisionAlgorithm.h | 0 .../btCompoundCompoundCollisionAlgorithm.cpp | 0 .../btCompoundCompoundCollisionAlgorithm.h | 0 .../btConvex2dConvex2dAlgorithm.cpp | 0 .../btConvex2dConvex2dAlgorithm.h | 0 .../btConvexConcaveCollisionAlgorithm.cpp | 0 .../btConvexConcaveCollisionAlgorithm.h | 0 .../btConvexConvexAlgorithm.cpp | 0 .../btConvexConvexAlgorithm.h | 0 .../btConvexPlaneCollisionAlgorithm.cpp | 0 .../btConvexPlaneCollisionAlgorithm.h | 0 .../btDefaultCollisionConfiguration.cpp | 0 .../btDefaultCollisionConfiguration.h | 0 .../btEmptyCollisionAlgorithm.cpp | 0 .../btEmptyCollisionAlgorithm.h | 0 .../CollisionDispatch/btGhostObject.cpp | 0 .../CollisionDispatch/btGhostObject.h | 0 .../btHashedSimplePairCache.cpp | 0 .../btHashedSimplePairCache.h | 0 .../btInternalEdgeUtility.cpp | 0 .../CollisionDispatch/btInternalEdgeUtility.h | 0 .../CollisionDispatch/btManifoldResult.cpp | 0 .../CollisionDispatch/btManifoldResult.h | 0 .../btSimulationIslandManager.cpp | 0 .../btSimulationIslandManager.h | 0 .../btSphereBoxCollisionAlgorithm.cpp | 0 .../btSphereBoxCollisionAlgorithm.h | 0 .../btSphereSphereCollisionAlgorithm.cpp | 0 .../btSphereSphereCollisionAlgorithm.h | 0 .../btSphereTriangleCollisionAlgorithm.cpp | 0 .../btSphereTriangleCollisionAlgorithm.h | 0 .../CollisionDispatch/btUnionFind.cpp | 0 .../CollisionDispatch/btUnionFind.h | 0 .../CollisionShapes/btBox2dShape.cpp | 0 .../CollisionShapes/btBox2dShape.h | 0 .../CollisionShapes/btBoxShape.cpp | 0 .../CollisionShapes/btBoxShape.h | 0 .../btBvhTriangleMeshShape.cpp | 0 .../CollisionShapes/btBvhTriangleMeshShape.h | 0 .../CollisionShapes/btCapsuleShape.cpp | 0 .../CollisionShapes/btCapsuleShape.h | 0 .../CollisionShapes/btCollisionMargin.h | 0 .../CollisionShapes/btCollisionShape.cpp | 0 .../CollisionShapes/btCollisionShape.h | 0 .../CollisionShapes/btCompoundShape.cpp | 0 .../CollisionShapes/btCompoundShape.h | 0 .../CollisionShapes/btConcaveShape.cpp | 0 .../CollisionShapes/btConcaveShape.h | 0 .../CollisionShapes/btConeShape.cpp | 0 .../CollisionShapes/btConeShape.h | 0 .../CollisionShapes/btConvex2dShape.cpp | 0 .../CollisionShapes/btConvex2dShape.h | 0 .../CollisionShapes/btConvexHullShape.cpp | 0 .../CollisionShapes/btConvexHullShape.h | 0 .../CollisionShapes/btConvexInternalShape.cpp | 0 .../CollisionShapes/btConvexInternalShape.h | 0 .../btConvexPointCloudShape.cpp | 0 .../CollisionShapes/btConvexPointCloudShape.h | 0 .../CollisionShapes/btConvexPolyhedron.cpp | 0 .../CollisionShapes/btConvexPolyhedron.h | 0 .../CollisionShapes/btConvexShape.cpp | 0 .../CollisionShapes/btConvexShape.h | 0 .../btConvexTriangleMeshShape.cpp | 0 .../btConvexTriangleMeshShape.h | 0 .../CollisionShapes/btCylinderShape.cpp | 0 .../CollisionShapes/btCylinderShape.h | 0 .../CollisionShapes/btEmptyShape.cpp | 0 .../CollisionShapes/btEmptyShape.h | 0 .../btHeightfieldTerrainShape.cpp | 0 .../btHeightfieldTerrainShape.h | 0 .../CollisionShapes/btMaterial.h | 0 .../CollisionShapes/btMinkowskiSumShape.cpp | 0 .../CollisionShapes/btMinkowskiSumShape.h | 0 .../CollisionShapes/btMultiSphereShape.cpp | 0 .../CollisionShapes/btMultiSphereShape.h | 0 .../btMultimaterialTriangleMeshShape.cpp | 0 .../btMultimaterialTriangleMeshShape.h | 0 .../CollisionShapes/btOptimizedBvh.cpp | 0 .../CollisionShapes/btOptimizedBvh.h | 0 .../btPolyhedralConvexShape.cpp | 0 .../CollisionShapes/btPolyhedralConvexShape.h | 0 .../btScaledBvhTriangleMeshShape.cpp | 0 .../btScaledBvhTriangleMeshShape.h | 0 .../CollisionShapes/btShapeHull.cpp | 0 .../CollisionShapes/btShapeHull.h | 0 .../CollisionShapes/btSphereShape.cpp | 0 .../CollisionShapes/btSphereShape.h | 0 .../CollisionShapes/btStaticPlaneShape.cpp | 0 .../CollisionShapes/btStaticPlaneShape.h | 0 .../btStridingMeshInterface.cpp | 0 .../CollisionShapes/btStridingMeshInterface.h | 0 .../CollisionShapes/btTetrahedronShape.cpp | 0 .../CollisionShapes/btTetrahedronShape.h | 0 .../CollisionShapes/btTriangleBuffer.cpp | 0 .../CollisionShapes/btTriangleBuffer.h | 0 .../CollisionShapes/btTriangleCallback.cpp | 0 .../CollisionShapes/btTriangleCallback.h | 0 .../btTriangleIndexVertexArray.cpp | 0 .../btTriangleIndexVertexArray.h | 0 .../btTriangleIndexVertexMaterialArray.cpp | 0 .../btTriangleIndexVertexMaterialArray.h | 0 .../CollisionShapes/btTriangleInfoMap.h | 0 .../CollisionShapes/btTriangleMesh.cpp | 0 .../CollisionShapes/btTriangleMesh.h | 0 .../CollisionShapes/btTriangleMeshShape.cpp | 0 .../CollisionShapes/btTriangleMeshShape.h | 0 .../CollisionShapes/btTriangleShape.h | 0 .../CollisionShapes/btUniformScalingShape.cpp | 0 .../CollisionShapes/btUniformScalingShape.h | 0 .../src/BulletCollision/Doxyfile | 0 .../BulletCollision/Gimpact/btBoxCollision.h | 0 .../BulletCollision/Gimpact/btClipPolygon.h | 0 .../Gimpact/btCompoundFromGimpact.h | 0 .../Gimpact/btContactProcessing.cpp | 0 .../Gimpact/btContactProcessing.h | 0 .../BulletCollision/Gimpact/btGImpactBvh.cpp | 0 .../BulletCollision/Gimpact/btGImpactBvh.h | 0 .../Gimpact/btGImpactCollisionAlgorithm.cpp | 0 .../Gimpact/btGImpactCollisionAlgorithm.h | 0 .../Gimpact/btGImpactMassUtil.h | 0 .../Gimpact/btGImpactQuantizedBvh.cpp | 0 .../Gimpact/btGImpactQuantizedBvh.h | 0 .../Gimpact/btGImpactShape.cpp | 0 .../BulletCollision/Gimpact/btGImpactShape.h | 0 .../Gimpact/btGenericPoolAllocator.cpp | 0 .../Gimpact/btGenericPoolAllocator.h | 0 .../Gimpact/btGeometryOperations.h | 0 .../BulletCollision/Gimpact/btQuantization.h | 0 .../Gimpact/btTriangleShapeEx.cpp | 0 .../Gimpact/btTriangleShapeEx.h | 0 .../src/BulletCollision/Gimpact/gim_array.h | 0 .../Gimpact/gim_basic_geometry_operations.h | 0 .../src/BulletCollision/Gimpact/gim_bitset.h | 0 .../Gimpact/gim_box_collision.h | 0 .../BulletCollision/Gimpact/gim_box_set.cpp | 0 .../src/BulletCollision/Gimpact/gim_box_set.h | 0 .../Gimpact/gim_clip_polygon.h | 0 .../BulletCollision/Gimpact/gim_contact.cpp | 0 .../src/BulletCollision/Gimpact/gim_contact.h | 0 .../BulletCollision/Gimpact/gim_geom_types.h | 0 .../BulletCollision/Gimpact/gim_geometry.h | 0 .../BulletCollision/Gimpact/gim_hash_table.h | 0 .../BulletCollision/Gimpact/gim_linear_math.h | 0 .../src/BulletCollision/Gimpact/gim_math.h | 0 .../BulletCollision/Gimpact/gim_memory.cpp | 0 .../src/BulletCollision/Gimpact/gim_memory.h | 0 .../BulletCollision/Gimpact/gim_radixsort.h | 0 .../Gimpact/gim_tri_collision.cpp | 0 .../Gimpact/gim_tri_collision.h | 0 .../btContinuousConvexCollision.cpp | 0 .../btContinuousConvexCollision.h | 0 .../NarrowPhaseCollision/btConvexCast.cpp | 0 .../NarrowPhaseCollision/btConvexCast.h | 0 .../btConvexPenetrationDepthSolver.h | 0 .../btDiscreteCollisionDetectorInterface.h | 0 .../NarrowPhaseCollision/btGjkConvexCast.cpp | 0 .../NarrowPhaseCollision/btGjkConvexCast.h | 0 .../NarrowPhaseCollision/btGjkEpa2.cpp | 0 .../NarrowPhaseCollision/btGjkEpa2.h | 0 .../btGjkEpaPenetrationDepthSolver.cpp | 0 .../btGjkEpaPenetrationDepthSolver.h | 0 .../btGjkPairDetector.cpp | 0 .../NarrowPhaseCollision/btGjkPairDetector.h | 0 .../NarrowPhaseCollision/btManifoldPoint.h | 0 .../btMinkowskiPenetrationDepthSolver.cpp | 0 .../btMinkowskiPenetrationDepthSolver.h | 0 .../btPersistentManifold.cpp | 0 .../btPersistentManifold.h | 0 .../NarrowPhaseCollision/btPointCollector.h | 0 .../btPolyhedralContactClipping.cpp | 0 .../btPolyhedralContactClipping.h | 0 .../btRaycastCallback.cpp | 0 .../NarrowPhaseCollision/btRaycastCallback.h | 0 .../btSimplexSolverInterface.h | 0 .../btSubSimplexConvexCast.cpp | 0 .../btSubSimplexConvexCast.h | 0 .../btVoronoiSimplexSolver.cpp | 0 .../btVoronoiSimplexSolver.h | 0 .../src/BulletCollision/premake4.lua | 0 .../src/BulletDynamics/CMakeLists.txt | 0 .../btCharacterControllerInterface.h | 0 .../btKinematicCharacterController.cpp | 0 .../btKinematicCharacterController.h | 0 .../btConeTwistConstraint.cpp | 0 .../ConstraintSolver/btConeTwistConstraint.h | 0 .../ConstraintSolver/btConstraintSolver.h | 0 .../ConstraintSolver/btContactConstraint.cpp | 0 .../ConstraintSolver/btContactConstraint.h | 0 .../ConstraintSolver/btContactSolverInfo.h | 0 .../ConstraintSolver/btFixedConstraint.cpp | 0 .../ConstraintSolver/btFixedConstraint.h | 0 .../ConstraintSolver/btGearConstraint.cpp | 0 .../ConstraintSolver/btGearConstraint.h | 0 .../btGeneric6DofConstraint.cpp | 0 .../btGeneric6DofConstraint.h | 0 .../btGeneric6DofSpringConstraint.cpp | 0 .../btGeneric6DofSpringConstraint.h | 0 .../ConstraintSolver/btHinge2Constraint.cpp | 0 .../ConstraintSolver/btHinge2Constraint.h | 0 .../ConstraintSolver/btHingeConstraint.cpp | 0 .../ConstraintSolver/btHingeConstraint.h | 0 .../ConstraintSolver/btJacobianEntry.h | 0 .../btPoint2PointConstraint.cpp | 0 .../btPoint2PointConstraint.h | 0 .../btSequentialImpulseConstraintSolver.cpp | 0 .../btSequentialImpulseConstraintSolver.h | 0 .../ConstraintSolver/btSliderConstraint.cpp | 0 .../ConstraintSolver/btSliderConstraint.h | 0 .../btSolve2LinearConstraint.cpp | 0 .../btSolve2LinearConstraint.h | 0 .../ConstraintSolver/btSolverBody.h | 0 .../ConstraintSolver/btSolverConstraint.h | 0 .../ConstraintSolver/btTypedConstraint.cpp | 0 .../ConstraintSolver/btTypedConstraint.h | 0 .../btUniversalConstraint.cpp | 0 .../ConstraintSolver/btUniversalConstraint.h | 0 .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 0 .../Dynamics/btActionInterface.h | 0 .../Dynamics/btDiscreteDynamicsWorld.cpp | 4 - .../Dynamics/btDiscreteDynamicsWorld.h | 0 .../BulletDynamics/Dynamics/btDynamicsWorld.h | 0 .../BulletDynamics/Dynamics/btRigidBody.cpp | 0 .../src/BulletDynamics/Dynamics/btRigidBody.h | 0 .../Dynamics/btSimpleDynamicsWorld.cpp | 0 .../Dynamics/btSimpleDynamicsWorld.h | 0 .../Featherstone/btMultiBody.cpp | 0 .../BulletDynamics/Featherstone/btMultiBody.h | 0 .../Featherstone/btMultiBodyConstraint.cpp | 0 .../Featherstone/btMultiBodyConstraint.h | 0 .../btMultiBodyConstraintSolver.cpp | 0 .../btMultiBodyConstraintSolver.h | 0 .../Featherstone/btMultiBodyDynamicsWorld.cpp | 0 .../Featherstone/btMultiBodyDynamicsWorld.h | 0 .../btMultiBodyJointLimitConstraint.cpp | 0 .../btMultiBodyJointLimitConstraint.h | 0 .../Featherstone/btMultiBodyJointMotor.cpp | 0 .../Featherstone/btMultiBodyJointMotor.h | 0 .../Featherstone/btMultiBodyLink.h | 0 .../Featherstone/btMultiBodyLinkCollider.h | 0 .../Featherstone/btMultiBodyPoint2Point.cpp | 0 .../Featherstone/btMultiBodyPoint2Point.h | 0 .../btMultiBodySolverConstraint.h | 0 .../MLCPSolvers/btDantzigLCP.cpp | 0 .../BulletDynamics/MLCPSolvers/btDantzigLCP.h | 0 .../MLCPSolvers/btDantzigSolver.h | 0 .../MLCPSolvers/btMLCPSolver.cpp | 0 .../BulletDynamics/MLCPSolvers/btMLCPSolver.h | 0 .../MLCPSolvers/btMLCPSolverInterface.h | 0 .../BulletDynamics/MLCPSolvers/btPATHSolver.h | 0 .../MLCPSolvers/btSolveProjectedGaussSeidel.h | 0 .../Vehicle/btRaycastVehicle.cpp | 0 .../BulletDynamics/Vehicle/btRaycastVehicle.h | 0 .../Vehicle/btVehicleRaycaster.h | 0 .../BulletDynamics/Vehicle/btWheelInfo.cpp | 0 .../src/BulletDynamics/Vehicle/btWheelInfo.h | 0 .../src/BulletDynamics/premake4.lua | 0 .../src/BulletMultiThreaded/CMakeLists.txt | 0 .../GpuSoftBodySolvers/CMakeLists.txt | 0 .../GpuSoftBodySolvers/DX11/CMakeLists.txt | 0 .../DX11/HLSL/ApplyForces.hlsl | 0 .../DX11/HLSL/ComputeBounds.hlsl | 0 .../DX11/HLSL/Integrate.hlsl | 0 .../DX11/HLSL/OutputToVertexArray.hlsl | 0 .../DX11/HLSL/PrepareLinks.hlsl | 0 .../DX11/HLSL/SolvePositions.hlsl | 0 .../DX11/HLSL/SolvePositionsSIMDBatched.hlsl | 0 .../DX11/HLSL/UpdateConstants.hlsl | 0 .../DX11/HLSL/UpdateNodes.hlsl | 0 .../DX11/HLSL/UpdateNormals.hlsl | 0 .../DX11/HLSL/UpdatePositions.hlsl | 0 .../HLSL/UpdatePositionsFromVelocities.hlsl | 0 .../DX11/HLSL/VSolveLinks.hlsl | 0 .../solveCollisionsAndUpdateVelocities.hlsl | 0 ...lisionsAndUpdateVelocitiesSIMDBatched.hlsl | 0 .../DX11/btSoftBodySolverBuffer_DX11.h | 0 .../DX11/btSoftBodySolverLinkData_DX11.h | 0 .../btSoftBodySolverLinkData_DX11SIMDAware.h | 0 .../DX11/btSoftBodySolverTriangleData_DX11.h | 0 .../DX11/btSoftBodySolverVertexBuffer_DX11.h | 0 .../DX11/btSoftBodySolverVertexData_DX11.h | 0 .../DX11/btSoftBodySolver_DX11.cpp | 0 .../DX11/btSoftBodySolver_DX11.h | 0 .../DX11/btSoftBodySolver_DX11SIMDAware.cpp | 0 .../DX11/btSoftBodySolver_DX11SIMDAware.h | 0 .../GpuSoftBodySolvers/DX11/premake4.lua | 0 .../OpenCL/AMD/CMakeLists.txt | 0 .../OpenCL/AMD/premake4.lua | 0 .../OpenCL/Apple/CMakeLists.txt | 0 .../GpuSoftBodySolvers/OpenCL/CMakeLists.txt | 0 .../OpenCL/Intel/CMakeLists.txt | 0 .../OpenCL/Intel/premake4.lua | 0 .../OpenCL/MiniCL/CMakeLists.txt | 0 .../OpenCL/MiniCL/MiniCLTaskWrap.cpp | 0 .../OpenCL/NVidia/CMakeLists.txt | 0 .../OpenCL/NVidia/premake4.lua | 0 .../OpenCL/OpenCLC10/ApplyForces.cl | 0 .../OpenCL/OpenCLC10/ComputeBounds.cl | 0 .../OpenCL/OpenCLC10/Integrate.cl | 0 .../OpenCL/OpenCLC10/OutputToVertexArray.cl | 0 .../OpenCL/OpenCLC10/PrepareLinks.cl | 0 .../SolveCollisionsAndUpdateVelocities.cl | 0 ...ollisionsAndUpdateVelocitiesSIMDBatched.cl | 0 .../OpenCL/OpenCLC10/SolvePositions.cl | 0 .../OpenCLC10/SolvePositionsSIMDBatched.cl | 0 .../OpenCL/OpenCLC10/UpdateConstants.cl | 0 .../OpenCLC10/UpdateFixedVertexPositions.cl | 0 .../OpenCL/OpenCLC10/UpdateNodes.cl | 0 .../OpenCL/OpenCLC10/UpdateNormals.cl | 0 .../OpenCL/OpenCLC10/UpdatePositions.cl | 0 .../UpdatePositionsFromVelocities.cl | 0 .../OpenCL/OpenCLC10/VSolveLinks.cl | 0 .../OpenCL/btSoftBodySolverBuffer_OpenCL.h | 0 .../OpenCL/btSoftBodySolverLinkData_OpenCL.h | 0 ...btSoftBodySolverLinkData_OpenCLSIMDAware.h | 0 .../OpenCL/btSoftBodySolverOutputCLtoGL.cpp | 0 .../OpenCL/btSoftBodySolverOutputCLtoGL.h | 0 .../btSoftBodySolverTriangleData_OpenCL.h | 0 .../btSoftBodySolverVertexBuffer_OpenGL.h | 0 .../btSoftBodySolverVertexData_OpenCL.h | 0 .../OpenCL/btSoftBodySolver_OpenCL.cpp | 0 .../OpenCL/btSoftBodySolver_OpenCL.h | 0 .../btSoftBodySolver_OpenCLSIMDAware.cpp | 0 .../OpenCL/btSoftBodySolver_OpenCLSIMDAware.h | 0 .../Shared/btSoftBodySolverData.h | 0 .../src/BulletMultiThreaded/HeapManager.h | 0 .../BulletMultiThreaded/PlatformDefinitions.h | 0 .../PosixThreadSupport.cpp | 0 .../BulletMultiThreaded/PosixThreadSupport.h | 0 .../src/BulletMultiThreaded/PpuAddressSpace.h | 0 .../SequentialThreadSupport.cpp | 0 .../SequentialThreadSupport.h | 0 .../SpuCollisionObjectWrapper.cpp | 0 .../SpuCollisionObjectWrapper.h | 0 .../SpuCollisionTaskProcess.cpp | 0 .../SpuCollisionTaskProcess.h | 0 .../SpuContactManifoldCollisionAlgorithm.cpp | 0 .../SpuContactManifoldCollisionAlgorithm.h | 0 .../src/BulletMultiThreaded/SpuDoubleBuffer.h | 0 .../src/BulletMultiThreaded/SpuFakeDma.cpp | 0 .../src/BulletMultiThreaded/SpuFakeDma.h | 0 .../SpuGatheringCollisionDispatcher.cpp | 0 .../SpuGatheringCollisionDispatcher.h | 0 .../BulletMultiThreaded/SpuLibspe2Support.cpp | 0 .../BulletMultiThreaded/SpuLibspe2Support.h | 0 .../SpuNarrowPhaseCollisionTask/Box.h | 0 .../SpuCollisionShapes.cpp | 0 .../SpuCollisionShapes.h | 0 .../SpuContactResult.cpp | 0 .../SpuContactResult.h | 0 .../SpuConvexPenetrationDepthSolver.h | 0 .../SpuGatheringCollisionTask.cpp | 0 .../SpuGatheringCollisionTask.h | 0 .../SpuLocalSupport.h | 0 .../SpuMinkowskiPenetrationDepthSolver.cpp | 0 .../SpuMinkowskiPenetrationDepthSolver.h | 0 .../SpuPreferredPenetrationDirections.h | 0 .../boxBoxDistance.cpp | 0 .../boxBoxDistance.h | 0 .../SpuNarrowPhaseCollisionTask/readme.txt | 0 .../SpuSampleTask/SpuSampleTask.cpp | 0 .../SpuSampleTask/SpuSampleTask.h | 0 .../SpuSampleTask/readme.txt | 0 .../SpuSampleTaskProcess.cpp | 0 .../SpuSampleTaskProcess.h | 0 .../src/BulletMultiThreaded/SpuSync.h | 0 .../src/BulletMultiThreaded/TrbDynBody.h | 0 .../src/BulletMultiThreaded/TrbStateVec.h | 0 .../Win32ThreadSupport.cpp | 0 .../BulletMultiThreaded/Win32ThreadSupport.h | 0 .../btGpu3DGridBroadphase.cpp | 0 .../btGpu3DGridBroadphase.h | 0 .../btGpu3DGridBroadphaseSharedCode.h | 0 .../btGpu3DGridBroadphaseSharedDefs.h | 0 .../btGpu3DGridBroadphaseSharedTypes.h | 0 .../src/BulletMultiThreaded/btGpuDefines.h | 0 .../btGpuUtilsSharedCode.h | 0 .../btGpuUtilsSharedDefs.h | 0 .../btParallelConstraintSolver.cpp | 0 .../btParallelConstraintSolver.h | 0 .../btThreadSupportInterface.cpp | 0 .../btThreadSupportInterface.h | 0 .../BulletMultiThreaded/vectormath2bullet.h | 0 .../src/BulletSoftBody/CMakeLists.txt | 0 .../btDefaultSoftBodySolver.cpp | 0 .../BulletSoftBody/btDefaultSoftBodySolver.h | 0 .../src/BulletSoftBody/btSoftBody.cpp | 0 .../src/BulletSoftBody/btSoftBody.h | 0 .../btSoftBodyConcaveCollisionAlgorithm.cpp | 0 .../btSoftBodyConcaveCollisionAlgorithm.h | 0 .../src/BulletSoftBody/btSoftBodyData.h | 0 .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 0 .../src/BulletSoftBody/btSoftBodyHelpers.h | 0 .../src/BulletSoftBody/btSoftBodyInternals.h | 0 ...oftBodyRigidBodyCollisionConfiguration.cpp | 0 ...tSoftBodyRigidBodyCollisionConfiguration.h | 0 .../btSoftBodySolverVertexBuffer.h | 0 .../src/BulletSoftBody/btSoftBodySolvers.h | 0 .../btSoftRigidCollisionAlgorithm.cpp | 0 .../btSoftRigidCollisionAlgorithm.h | 0 .../btSoftRigidDynamicsWorld.cpp | 0 .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 0 .../btSoftSoftCollisionAlgorithm.cpp | 0 .../btSoftSoftCollisionAlgorithm.h | 0 .../src/BulletSoftBody/btSparseSDF.h | 0 .../src/BulletSoftBody/premake4.lua | 0 .../{ => Bullet Source}/src/CMakeLists.txt | 0 .../src/LinearMath/CMakeLists.txt | 0 .../src/LinearMath/btAabbUtil2.h | 0 .../src/LinearMath/btAlignedAllocator.cpp | 0 .../src/LinearMath/btAlignedAllocator.h | 0 .../src/LinearMath/btAlignedObjectArray.h | 0 .../src/LinearMath/btConvexHull.cpp | 0 .../src/LinearMath/btConvexHull.h | 0 .../src/LinearMath/btConvexHullComputer.cpp | 0 .../src/LinearMath/btConvexHullComputer.h | 0 .../src/LinearMath/btDefaultMotionState.h | 0 .../src/LinearMath/btGeometryUtil.cpp | 0 .../src/LinearMath/btGeometryUtil.h | 0 .../src/LinearMath/btGrahamScan2dConvexHull.h | 0 .../src/LinearMath/btHashMap.h | 0 .../src/LinearMath/btIDebugDraw.h | 0 .../src/LinearMath/btList.h | 0 .../src/LinearMath/btMatrix3x3.h | 0 .../src/LinearMath/btMatrixX.h | 0 .../src/LinearMath/btMinMax.h | 0 .../src/LinearMath/btMotionState.h | 0 .../src/LinearMath/btPolarDecomposition.cpp | 0 .../src/LinearMath/btPolarDecomposition.h | 0 .../src/LinearMath/btPoolAllocator.h | 0 .../src/LinearMath/btQuadWord.h | 0 .../src/LinearMath/btQuaternion.h | 0 .../src/LinearMath/btQuickprof.cpp | 0 .../src/LinearMath/btQuickprof.h | 0 .../src/LinearMath/btRandom.h | 0 .../src/LinearMath/btScalar.h | 0 .../src/LinearMath/btSerializer.cpp | 0 .../src/LinearMath/btSerializer.h | 0 .../src/LinearMath/btStackAlloc.h | 0 .../src/LinearMath/btTransform.h | 0 .../src/LinearMath/btTransformUtil.h | 0 .../src/LinearMath/btVector3.cpp | 0 .../src/LinearMath/btVector3.h | 0 .../src/LinearMath/premake4.lua | 0 .../{ => Bullet Source}/src/Makefile.am | 0 .../src/MiniCL/CMakeLists.txt | 0 .../{ => Bullet Source}/src/MiniCL/MiniCL.cpp | 0 .../src/MiniCL/MiniCLTask/MiniCLTask.cpp | 0 .../src/MiniCL/MiniCLTask/MiniCLTask.h | 0 .../src/MiniCL/MiniCLTaskScheduler.cpp | 0 .../src/MiniCL/MiniCLTaskScheduler.h | 0 .../{ => Bullet Source}/src/MiniCL/cl.h | 0 .../src/MiniCL/cl_MiniCL_Defs.h | 0 .../{ => Bullet Source}/src/MiniCL/cl_gl.h | 0 .../src/MiniCL/cl_platform.h | 0 .../src/btBulletCollisionCommon.h | 0 .../src/btBulletDynamicsCommon.h | 0 .../src/vectormath/neon/boolInVec.h | 0 .../src/vectormath/neon/floatInVec.h | 0 .../src/vectormath/neon/mat_aos.h | 0 .../src/vectormath/neon/quat_aos.h | 0 .../src/vectormath/neon/vec_aos.h | 0 .../src/vectormath/neon/vectormath_aos.h | 0 .../src/vectormath/scalar/boolInVec.h | 0 .../src/vectormath/scalar/floatInVec.h | 0 .../src/vectormath/scalar/mat_aos.h | 0 .../src/vectormath/scalar/quat_aos.h | 0 .../src/vectormath/scalar/vec_aos.h | 0 .../src/vectormath/scalar/vectormath_aos.h | 0 .../src/vectormath/sse/boolInVec.h | 0 .../src/vectormath/sse/floatInVec.h | 0 .../src/vectormath/sse/mat_aos.h | 0 .../src/vectormath/sse/quat_aos.h | 0 .../src/vectormath/sse/vec_aos.h | 0 .../src/vectormath/sse/vecidx_aos.h | 0 .../src/vectormath/sse/vectormath_aos.h | 0 .../src/vectormath/vmInclude.h | 0 Code/Physics/Bullet Source/test1.oec | 227 + .../BulletCollision/BulletCollision.vcxproj | 487 -- .../BulletCollision.vcxproj.user | 4 - .../CMakeFiles/generate.stamp.depend | 2 - Code/Physics/BulletConfig.cmake | 25 + .../BulletDynamics/BulletDynamics.vcxproj | 343 - .../BulletDynamics.vcxproj.user | 4 - .../CMakeFiles/generate.stamp.depend | 2 - Code/Physics/CMakeCache.txt | 471 ++ .../CMakeFiles/2.8.12.2/CMakeCCompiler.cmake | 56 + .../2.8.12.2/CMakeCXXCompiler.cmake | 57 + .../2.8.12.2/CMakeDetermineCompilerABI_C.bin | Bin 0 -> 30208 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 30208 bytes .../CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake | 6 + .../CMakeFiles/2.8.12.2/CMakeSystem.cmake | 15 + .../2.8.12.2/CompilerIdC/CMakeCCompilerId.c | 389 ++ .../2.8.12.2/CompilerIdC/CompilerIdC.vcxproj | 52 + .../CompilerIdC/Debug/CMakeCCompilerId.obj | Bin 0 -> 1497 bytes .../Debug/CompilerIdC.lastbuildstate | 2 + .../CompilerIdC/Debug/CompilerIdC.log | 17 + .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 377 ++ .../CompilerIdCXX/CompilerIdCXX.vcxproj | 52 + .../Debug/CMakeCXXCompilerId.obj | Bin 0 -> 1495 bytes .../Debug/CompilerIdCXX.lastbuildstate | 2 + .../CompilerIdCXX/Debug/CompilerIdCXX.log | 17 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + Code/Physics/CMakeFiles/CMakeOutput.log | 119 + Code/Physics/CMakeFiles/TargetDirectories.txt | 10 + .../ALL_BUILD.rule | 1 + .../INSTALL_force.rule | 1 + .../ZERO_CHECK.rule | 1 + .../generate.stamp.rule | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + Code/Physics/CMakeFiles/cmake.check_cache | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + .../INSTALL_force.rule | 1 + .../CMakeFiles/generate.stamp | 0 Code/Physics/CMakeFiles/generate.stamp.depend | 33 + Code/Physics/CMakeFiles/generate.stamp.list | 12 + Code/Physics/{LinearMath => }/INSTALL.vcxproj | 32 +- .../CMakeFiles/generate.stamp.depend | 2 - .../LinearMath/LinearMath.vcxproj.user | 4 - Code/Physics/ZERO_CHECK.vcxproj | 217 + Code/Physics/cmake_install.cmake | 52 + .../BulletCollision/BulletCollision.vcxproj | 485 ++ .../CMakeFiles/generate.stamp | 0 .../CMakeFiles/generate.stamp.depend | 2 + .../src/BulletCollision/INSTALL.vcxproj | 217 + .../src/BulletCollision/cmake_install.cmake | 29 + .../src/BulletDynamics/BulletDynamics.vcxproj | 343 + .../BulletDynamics}/CMakeFiles/generate.stamp | 0 .../CMakeFiles/generate.stamp.depend | 2 + .../src/BulletDynamics/INSTALL.vcxproj | 217 + .../BulletDynamics/cmake_install.cmake | 2 +- .../BulletMultiThreaded.vcxproj | 316 + .../CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + .../CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + .../DX11/BulletSoftBodySolvers_DX11.vcxproj | 293 + .../DX11/CMakeFiles/generate.stamp | 1 + .../DX11/CMakeFiles/generate.stamp.depend | 2 + .../GpuSoftBodySolvers/DX11/INSTALL.vcxproj | 217 + .../DX11/cmake_install.cmake | 29 + .../GpuSoftBodySolvers/INSTALL.vcxproj | 217 + .../OpenCL/CMakeFiles/generate.stamp | 1 + .../OpenCL/CMakeFiles/generate.stamp.depend | 2 + .../GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj | 217 + .../BulletSoftBodySolvers_OpenCL_Mini.vcxproj | 284 + .../OpenCL/MiniCL/CMakeFiles/generate.stamp | 1 + .../MiniCL/CMakeFiles/generate.stamp.depend | 2 + .../OpenCL/MiniCL/INSTALL.vcxproj | 217 + .../OpenCL/MiniCL/cmake_install.cmake | 29 + .../OpenCL/cmake_install.cmake | 35 + .../GpuSoftBodySolvers/cmake_install.cmake | 36 + .../src/BulletMultiThreaded/INSTALL.vcxproj | 217 + .../BulletMultiThreaded/cmake_install.cmake | 35 + .../src/BulletSoftBody/BulletSoftBody.vcxproj | 288 + .../BulletSoftBody/CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + .../src/BulletSoftBody/INSTALL.vcxproj | 217 + .../src/BulletSoftBody/cmake_install.cmake | 29 + Code/Physics/src/CMakeFiles/generate.stamp | 1 + .../src/CMakeFiles/generate.stamp.depend | 2 + .../{BulletDynamics => src}/INSTALL.vcxproj | 32 +- .../src/LinearMath/CMakeFiles/generate.stamp | 1 + .../CMakeFiles/generate.stamp.depend | 2 + Code/Physics/src/LinearMath/INSTALL.vcxproj | 217 + .../{ => src}/LinearMath/LinearMath.vcxproj | 147 +- .../LinearMath}/cmake_install.cmake | 2 +- .../src/MiniCL/CMakeFiles/generate.stamp | 1 + .../MiniCL/CMakeFiles/generate.stamp.depend | 2 + .../MiniCL}/INSTALL.vcxproj | 32 +- Code/Physics/src/MiniCL/MiniCL.vcxproj | 277 + .../MiniCL}/cmake_install.cmake | 2 +- Code/Physics/src/cmake_install.cmake | 40 + Code/suo6F49.tmp | Bin 0 -> 1536 bytes Code/suoBC7E.tmp | Bin 0 -> 1536 bytes Code/suoC9A6.tmp | Bin 0 -> 1536 bytes Code/suoDD74.tmp | Bin 0 -> 1536 bytes Code/suoE071.tmp | Bin 0 -> 1536 bytes Code/suoE544.tmp | Bin 0 -> 1536 bytes 678 files changed, 22618 insertions(+), 1072 deletions(-) create mode 100644 Code/Physics/ALL_BUILD.vcxproj create mode 100644 Code/Physics/BULLET_PHYSICS.sln create mode 100644 Code/Physics/Bullet Source/AUTHORS create mode 100644 Code/Physics/Bullet Source/BspDemo.bsp create mode 100644 Code/Physics/Bullet Source/BulletConfig.cmake.in create mode 100644 Code/Physics/Bullet Source/BulletLicense.txt create mode 100644 Code/Physics/Bullet Source/CMakeLists.txt create mode 100644 Code/Physics/Bullet Source/COPYING create mode 100644 Code/Physics/Bullet Source/ChangeLog create mode 100644 Code/Physics/Bullet Source/Doxyfile rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/egl_cpx.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/egl_defs.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/egl_logged.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/egl_tokens.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/egl_void.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/gl.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/glu.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/EmptyGL/GL/glut.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/glew.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/glext.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/glut.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/glxew.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/glxext.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/wglew.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/GL/wglext.h (100%) rename Code/Physics/{ => Bullet Source}/Glut/btGlutInclude.h (100%) create mode 100644 Code/Physics/Bullet Source/INSTALL create mode 100644 Code/Physics/Bullet Source/Makefile.am create mode 100644 Code/Physics/Bullet Source/NEWS create mode 100644 Code/Physics/Bullet Source/README create mode 100644 Code/Physics/Bullet Source/RELEASING.TXT create mode 100644 Code/Physics/Bullet Source/UseBullet.cmake create mode 100644 Code/Physics/Bullet Source/VERSION create mode 100644 Code/Physics/Bullet Source/acinclude.m4 create mode 100644 Code/Physics/Bullet Source/autogen.sh create mode 100644 Code/Physics/Bullet Source/bullet.pc.cmake create mode 100644 Code/Physics/Bullet Source/bullet.pc.in create mode 100644 Code/Physics/Bullet Source/bullet_logo.png create mode 100644 Code/Physics/Bullet Source/config.h.in create mode 100644 Code/Physics/Bullet Source/configure.ac create mode 100644 Code/Physics/Bullet Source/convex0.bin create mode 100644 Code/Physics/Bullet Source/file.obj create mode 100644 Code/Physics/Bullet Source/heightfield128x128.raw create mode 100644 Code/Physics/Bullet Source/install-sh create mode 100644 Code/Physics/Bullet Source/jenga.dae rename Code/Physics/{ => Bullet Source}/src/Bullet-C-Api.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btDbvt.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btDbvt.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btDispatcher.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionObject.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCollisionWorld.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btGhostObject.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btGhostObject.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btManifoldResult.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btUnionFind.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionDispatch/btUnionFind.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btBox2dShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btBox2dShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btBoxShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btBoxShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCapsuleShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCollisionMargin.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCollisionShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCollisionShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCompoundShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCompoundShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConcaveShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConcaveShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConeShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConeShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvex2dShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexHullShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexInternalShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCylinderShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btCylinderShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btEmptyShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btEmptyShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMaterial.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMultiSphereShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btOptimizedBvh.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btShapeHull.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btShapeHull.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btSphereShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btSphereShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTetrahedronShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleBuffer.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleCallback.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleMesh.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btTriangleShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/CollisionShapes/btUniformScalingShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Doxyfile (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btBoxCollision.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btClipPolygon.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btCompoundFromGimpact.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btContactProcessing.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btContactProcessing.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactBvh.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactBvh.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactMassUtil.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactShape.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGImpactShape.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGenericPoolAllocator.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btGeometryOperations.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btQuantization.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/btTriangleShapeEx.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_array.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_bitset.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_box_collision.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_box_set.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_box_set.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_clip_polygon.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_contact.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_contact.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_geom_types.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_geometry.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_hash_table.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_linear_math.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_math.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_memory.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_memory.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_radixsort.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_tri_collision.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/Gimpact/gim_tri_collision.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletCollision/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Character/btCharacterControllerInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Character/btKinematicCharacterController.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Character/btKinematicCharacterController.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btContactConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btGearConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSolverBody.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/Bullet-C-API.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btActionInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp (99%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btDynamicsWorld.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btRigidBody.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btRigidBody.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBody.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBody.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyLink.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btPATHSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Vehicle/btRaycastVehicle.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Vehicle/btVehicleRaycaster.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Vehicle/btWheelInfo.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/Vehicle/btWheelInfo.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletDynamics/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/HeapManager.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/PlatformDefinitions.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/PosixThreadSupport.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/PosixThreadSupport.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/PpuAddressSpace.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SequentialThreadSupport.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SequentialThreadSupport.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuCollisionTaskProcess.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuDoubleBuffer.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuFakeDma.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuFakeDma.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuLibspe2Support.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuLibspe2Support.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuSampleTask/readme.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuSampleTaskProcess.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/SpuSync.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/TrbDynBody.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/TrbStateVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/Win32ThreadSupport.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/Win32ThreadSupport.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpu3DGridBroadphase.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpuDefines.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpuUtilsSharedCode.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btParallelConstraintSolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btParallelConstraintSolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btThreadSupportInterface.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/btThreadSupportInterface.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletMultiThreaded/vectormath2bullet.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btDefaultSoftBodySolver.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btDefaultSoftBodySolver.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBody.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBody.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyData.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyHelpers.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyHelpers.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyInternals.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftBodySolvers.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftRigidDynamicsWorld.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/btSparseSDF.h (100%) rename Code/Physics/{ => Bullet Source}/src/BulletSoftBody/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btAabbUtil2.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btAlignedAllocator.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btAlignedAllocator.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btAlignedObjectArray.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btConvexHull.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btConvexHull.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btConvexHullComputer.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btConvexHullComputer.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btDefaultMotionState.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btGeometryUtil.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btGeometryUtil.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btGrahamScan2dConvexHull.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btHashMap.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btIDebugDraw.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btList.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btMatrix3x3.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btMatrixX.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btMinMax.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btMotionState.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btPolarDecomposition.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btPolarDecomposition.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btPoolAllocator.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btQuadWord.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btQuaternion.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btQuickprof.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btQuickprof.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btRandom.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btScalar.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btSerializer.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btSerializer.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btStackAlloc.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btTransform.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btTransformUtil.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btVector3.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/btVector3.h (100%) rename Code/Physics/{ => Bullet Source}/src/LinearMath/premake4.lua (100%) rename Code/Physics/{ => Bullet Source}/src/Makefile.am (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/CMakeLists.txt (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/MiniCL.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/MiniCLTask/MiniCLTask.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/MiniCLTask/MiniCLTask.h (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/MiniCLTaskScheduler.cpp (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/MiniCLTaskScheduler.h (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/cl.h (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/cl_MiniCL_Defs.h (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/cl_gl.h (100%) rename Code/Physics/{ => Bullet Source}/src/MiniCL/cl_platform.h (100%) rename Code/Physics/{ => Bullet Source}/src/btBulletCollisionCommon.h (100%) rename Code/Physics/{ => Bullet Source}/src/btBulletDynamicsCommon.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/neon/boolInVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/neon/floatInVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/neon/mat_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/neon/quat_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/neon/vec_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/neon/vectormath_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/scalar/boolInVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/scalar/floatInVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/scalar/mat_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/scalar/quat_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/scalar/vec_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/scalar/vectormath_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/boolInVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/floatInVec.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/mat_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/quat_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/vec_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/vecidx_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/sse/vectormath_aos.h (100%) rename Code/Physics/{ => Bullet Source}/src/vectormath/vmInclude.h (100%) create mode 100644 Code/Physics/Bullet Source/test1.oec delete mode 100644 Code/Physics/BulletCollision/BulletCollision.vcxproj delete mode 100644 Code/Physics/BulletCollision/BulletCollision.vcxproj.user delete mode 100644 Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/BulletConfig.cmake delete mode 100644 Code/Physics/BulletDynamics/BulletDynamics.vcxproj delete mode 100644 Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user delete mode 100644 Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/CMakeCache.txt create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CMakeCCompilerId.obj create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CompilerIdCXX.lastbuildstate create mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CompilerIdCXX.log create mode 100644 Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/CMakeOutput.log create mode 100644 Code/Physics/CMakeFiles/TargetDirectories.txt create mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule create mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule create mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule create mode 100644 Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/cmake.check_cache create mode 100644 Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule create mode 100644 Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule rename Code/Physics/{BulletCollision => }/CMakeFiles/generate.stamp (100%) create mode 100644 Code/Physics/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/CMakeFiles/generate.stamp.list rename Code/Physics/{LinearMath => }/INSTALL.vcxproj (79%) delete mode 100644 Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/LinearMath/LinearMath.vcxproj.user create mode 100644 Code/Physics/ZERO_CHECK.vcxproj create mode 100644 Code/Physics/cmake_install.cmake create mode 100644 Code/Physics/src/BulletCollision/BulletCollision.vcxproj rename Code/Physics/{BulletDynamics => src/BulletCollision}/CMakeFiles/generate.stamp (100%) create mode 100644 Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletCollision/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletCollision/cmake_install.cmake create mode 100644 Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj rename Code/Physics/{LinearMath => src/BulletDynamics}/CMakeFiles/generate.stamp (100%) create mode 100644 Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletDynamics/INSTALL.vcxproj rename Code/Physics/{ => src}/BulletDynamics/cmake_install.cmake (89%) create mode 100644 Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake create mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake create mode 100644 Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletMultiThreaded/cmake_install.cmake create mode 100644 Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj create mode 100644 Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/BulletSoftBody/INSTALL.vcxproj create mode 100644 Code/Physics/src/BulletSoftBody/cmake_install.cmake create mode 100644 Code/Physics/src/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/CMakeFiles/generate.stamp.depend rename Code/Physics/{BulletDynamics => src}/INSTALL.vcxproj (79%) create mode 100644 Code/Physics/src/LinearMath/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend create mode 100644 Code/Physics/src/LinearMath/INSTALL.vcxproj rename Code/Physics/{ => src}/LinearMath/LinearMath.vcxproj (58%) rename Code/Physics/{BulletCollision => src/LinearMath}/cmake_install.cmake (89%) create mode 100644 Code/Physics/src/MiniCL/CMakeFiles/generate.stamp create mode 100644 Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend rename Code/Physics/{BulletCollision => src/MiniCL}/INSTALL.vcxproj (79%) create mode 100644 Code/Physics/src/MiniCL/MiniCL.vcxproj rename Code/Physics/{LinearMath => src/MiniCL}/cmake_install.cmake (90%) create mode 100644 Code/Physics/src/cmake_install.cmake create mode 100644 Code/suo6F49.tmp create mode 100644 Code/suoBC7E.tmp create mode 100644 Code/suoC9A6.tmp create mode 100644 Code/suoDD74.tmp create mode 100644 Code/suoE071.tmp create mode 100644 Code/suoE544.tmp diff --git a/Code/DanBias.sln b/Code/DanBias.sln index b02fd49b..68ed1d24 100644 --- a/Code/DanBias.sln +++ b/Code/DanBias.sln @@ -25,9 +25,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetworkDependencies", "Netw EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamePhysics", "GamePhysics\GamePhysics.vcxproj", "{104FA3E9-94D9-4E1D-A941-28A03BC8A095}" ProjectSection(ProjectDependencies) = postProject - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} = {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} = {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} - {22C0C4D8-6C43-406A-9CDB-76A4F800971A} = {22C0C4D8-6C43-406A-9CDB-76A4F800971A} + {D4985405-3286-4026-BD61-E9E53DC5027E} = {D4985405-3286-4026-BD61-E9E53DC5027E} + {C933A737-D7BA-4136-95AF-D12310BD6BA8} = {C933A737-D7BA-4136-95AF-D12310BD6BA8} + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} = {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasGame", "Game\DanBiasGame\DanBiasGame.vcxproj", "{2A1BC987-AF42-4500-802D-89CD32FC1309}" @@ -44,19 +44,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameProtocols", "Game\GameP EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasServerLauncher", "Game\DanBiasServerLauncher\DanBiasServerLauncher.vcxproj", "{060B1890-CBF3-4808-BA99-A4776222093B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Physics lab", "Physics lab\Physics lab.vcxproj", "{5128BD77-6472-4C4A-BE6F-724AD0E589C2}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameServer", "Game\GameServer\GameServer.vcxproj", "{143BD516-20A1-4890-A3E4-F8BFD02220E7}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aDanBiasGameLauncher", "Game\aDanBiasGameLauncher\aDanBiasGameLauncher.vcxproj", "{666FEA52-975F-41CD-B224-B19AF3C0ABBA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Physics", "Physics", "{0D86E569-9C74-47F0-BDB2-390C0C9A084B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "Physics\BulletCollision\BulletCollision.vcxproj", "{B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "Physics\src\BulletCollision\BulletCollision.vcxproj", "{C933A737-D7BA-4136-95AF-D12310BD6BA8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletDynamics", "Physics\BulletDynamics\BulletDynamics.vcxproj", "{6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "Physics\src\LinearMath\LinearMath.vcxproj", "{D4985405-3286-4026-BD61-E9E53DC5027E}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "Physics\LinearMath\LinearMath.vcxproj", "{22C0C4D8-6C43-406A-9CDB-76A4F800971A}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletDynamics", "Physics\src\BulletDynamics\BulletDynamics.vcxproj", "{74EDC06C-85E5-47BC-B42D-F55CE6E9928B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -464,24 +462,6 @@ Global {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Win32.Build.0 = Release|Win32 {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|x64.Build.0 = Release|x64 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Win32.ActiveCfg = Debug|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|Win32.Build.0 = Debug|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|x64.ActiveCfg = Debug|x64 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Debug|x64.Build.0 = Debug|x64 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.MinSizeRel|Win32.ActiveCfg = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.MinSizeRel|x64.ActiveCfg = Release|x64 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Mixed Platforms.Build.0 = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Win32.ActiveCfg = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|Win32.Build.0 = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|x64.ActiveCfg = Release|x64 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.Release|x64.Build.0 = Release|x64 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32 - {5128BD77-6472-4C4A-BE6F-724AD0E589C2}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -530,66 +510,66 @@ Global {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Win32.Build.0 = Release|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.Build.0 = Release|x64 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Win32.ActiveCfg = Debug|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|Win32.Build.0 = Debug|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Debug|x64.ActiveCfg = Debug|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Win32.ActiveCfg = Release|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|Win32.Build.0 = Release|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.Release|x64.ActiveCfg = Release|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Win32.ActiveCfg = Debug|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|Win32.Build.0 = Debug|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Debug|x64.ActiveCfg = Debug|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Win32.ActiveCfg = Release|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|Win32.Build.0 = Release|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.Release|x64.ActiveCfg = Release|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Win32.ActiveCfg = Debug|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|Win32.Build.0 = Debug|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Debug|x64.ActiveCfg = Debug|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Mixed Platforms.Build.0 = Release|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Win32.ActiveCfg = Release|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|Win32.Build.0 = Release|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.Release|x64.ActiveCfg = Release|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {22C0C4D8-6C43-406A-9CDB-76A4F800971A}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.Build.0 = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|x64.ActiveCfg = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.ActiveCfg = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.Build.0 = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|x64.ActiveCfg = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.ActiveCfg = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.Build.0 = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|x64.ActiveCfg = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Mixed Platforms.Build.0 = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.ActiveCfg = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.Build.0 = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|x64.ActiveCfg = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.ActiveCfg = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.Build.0 = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|x64.ActiveCfg = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Mixed Platforms.Build.0 = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.ActiveCfg = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.Build.0 = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|x64.ActiveCfg = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -606,8 +586,8 @@ Global {060B1890-CBF3-4808-BA99-A4776222093B} = {20720CA7-795C-45AD-A302-9383A6DD503A} {143BD516-20A1-4890-A3E4-F8BFD02220E7} = {20720CA7-795C-45AD-A302-9383A6DD503A} {666FEA52-975F-41CD-B224-B19AF3C0ABBA} = {20720CA7-795C-45AD-A302-9383A6DD503A} - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} - {22C0C4D8-6C43-406A-9CDB-76A4F800971A} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} + {C933A737-D7BA-4136-95AF-D12310BD6BA8} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} + {D4985405-3286-4026-BD61-E9E53DC5027E} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} EndGlobalSection EndGlobal diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index a7d04f86..fb4b8479 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -465,13 +465,13 @@ void GameState::Protocol( ObjPos* pos ) if(privData->object[i]->GetId() == pos->object_ID) { privData->object[i]->setPos(world); - + Oyster::Math::Float3 pos = Oyster::Math::Float3(0, 600, 15); if(i == myId) // playerobj { Oyster::Math::Float3 right = Oyster::Math::Float3(world[0], world[1], world[2]); Oyster::Math::Float3 up = Oyster::Math::Float3(world[4], world[5], world[6]); Oyster::Math::Float3 objForward = (Oyster::Math::Float3(world[8], world[9], world[10])); - Oyster::Math::Float3 pos = Oyster::Math::Float3(world[12], world[13], world[14]); + Oyster::Math::Float3 cameraLook = camera->GetLook(); @@ -496,6 +496,7 @@ void GameState::Protocol( ObjPos* pos ) camera->UpdateViewMatrix(); } + camera->SetPosition(pos); } } } diff --git a/Code/GamePhysics/GamePhysics.vcxproj b/Code/GamePhysics/GamePhysics.vcxproj index 813d87c6..a9746245 100644 --- a/Code/GamePhysics/GamePhysics.vcxproj +++ b/Code/GamePhysics/GamePhysics.vcxproj @@ -89,7 +89,7 @@ Level3 Disabled - $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\src;%(AdditionalIncludeDirectories) _WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions) false @@ -97,7 +97,7 @@ true - $(SolutionDir)Physics/Debug/BulletCollision_Debug.lib;$(SolutionDir)Physics/Debug/BulletDynamics_Debug.lib;$(SolutionDir)Physics/Debug/LinearMath_Debug.lib;%(AdditionalDependencies) + $(SolutionDir)Physics/lib/debug/BulletCollision_Debug.lib;$(SolutionDir)Physics/lib/debug/BulletDynamics_Debug.lib;$(SolutionDir)Physics/lib/debug/LinearMath_Debug.lib;%(AdditionalDependencies) diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index ca18dc1c..10a2e336 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -67,7 +67,7 @@ void SimpleRigidBody::SetSubscription(EventAction_AfterCollisionResponse functio void SimpleRigidBody::CallSubsciptMessage(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) { - this->CallSubsciptMessage(bodyA, bodyB, kineticEnergyLoss); + return; } btDefaultMotionState* SimpleRigidBody::GetMotionState() const diff --git a/Code/Physics/ALL_BUILD.vcxproj b/Code/Physics/ALL_BUILD.vcxproj new file mode 100644 index 00000000..545f3181 --- /dev/null +++ b/Code/Physics/ALL_BUILD.vcxproj @@ -0,0 +1,244 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {14E546AD-2393-41B9-BAA2-134241286A4E} + Win32Proj + Win32 + ALL_BUILD + + + + Utility + false + MultiByte + v110 + + + Utility + false + MultiByte + v110 + + + Utility + false + MultiByte + v110 + + + Utility + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp + false + + + + + Build all projects + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD + false + Build all projects + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD + false + Build all projects + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD + false + Build all projects + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD + false + + + + + + + + C933A737-D7BA-4136-95AF-D12310BD6BA8 + + + 74EDC06C-85E5-47BC-B42D-F55CE6E9928B + + + 83B388D3-BE71-476A-AA6A-CC7082E3866D + + + 14DC504E-697F-4178-8E05-87173957FE59 + + + 2CF89262-94E6-4A9F-A29A-1BE6D73DDA85 + + + 80FC7669-D649-4212-8B6F-C0167CE9CB59 + + + D4985405-3286-4026-BD61-E9E53DC5027E + + + FA9E3157-5228-4CA4-8327-BD0AF11BD390 + + + 53399ED8-C4B0-4F84-9CA8-623049125822 + + + + + + \ No newline at end of file diff --git a/Code/Physics/BULLET_PHYSICS.sln b/Code/Physics/BULLET_PHYSICS.sln new file mode 100644 index 00000000..b7c18743 --- /dev/null +++ b/Code/Physics/BULLET_PHYSICS.sln @@ -0,0 +1,162 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{14E546AD-2393-41B9-BAA2-134241286A4E}" + ProjectSection(ProjectDependencies) = postProject + {C933A737-D7BA-4136-95AF-D12310BD6BA8} = {C933A737-D7BA-4136-95AF-D12310BD6BA8} + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} = {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} + {83B388D3-BE71-476A-AA6A-CC7082E3866D} = {83B388D3-BE71-476A-AA6A-CC7082E3866D} + {14DC504E-697F-4178-8E05-87173957FE59} = {14DC504E-697F-4178-8E05-87173957FE59} + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85} = {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85} + {80FC7669-D649-4212-8B6F-C0167CE9CB59} = {80FC7669-D649-4212-8B6F-C0167CE9CB59} + {D4985405-3286-4026-BD61-E9E53DC5027E} = {D4985405-3286-4026-BD61-E9E53DC5027E} + {FA9E3157-5228-4CA4-8327-BD0AF11BD390} = {FA9E3157-5228-4CA4-8327-BD0AF11BD390} + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "src\BulletCollision\BulletCollision.vcxproj", "{C933A737-D7BA-4136-95AF-D12310BD6BA8}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletDynamics", "src\BulletDynamics\BulletDynamics.vcxproj", "{74EDC06C-85E5-47BC-B42D-F55CE6E9928B}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletMultiThreaded", "src\BulletMultiThreaded\BulletMultiThreaded.vcxproj", "{83B388D3-BE71-476A-AA6A-CC7082E3866D}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletSoftBody", "src\BulletSoftBody\BulletSoftBody.vcxproj", "{14DC504E-697F-4178-8E05-87173957FE59}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletSoftBodySolvers_DX11", "src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\BulletSoftBodySolvers_DX11.vcxproj", "{2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletSoftBodySolvers_OpenCL_Mini", "src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\BulletSoftBodySolvers_OpenCL_Mini.vcxproj", "{80FC7669-D649-4212-8B6F-C0167CE9CB59}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INSTALL", "INSTALL.vcxproj", "{71641E56-5E9E-462B-844F-A9F8A6D82120}" + ProjectSection(ProjectDependencies) = postProject + {14E546AD-2393-41B9-BAA2-134241286A4E} = {14E546AD-2393-41B9-BAA2-134241286A4E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "src\LinearMath\LinearMath.vcxproj", "{D4985405-3286-4026-BD61-E9E53DC5027E}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MiniCL", "src\MiniCL\MiniCL.vcxproj", "{FA9E3157-5228-4CA4-8327-BD0AF11BD390}" + ProjectSection(ProjectDependencies) = postProject + {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{53399ED8-C4B0-4F84-9CA8-623049125822}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + MinSizeRel|Win32 = MinSizeRel|Win32 + RelWithDebInfo|Win32 = RelWithDebInfo|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {14E546AD-2393-41B9-BAA2-134241286A4E}.Debug|Win32.ActiveCfg = Debug|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.Debug|Win32.Build.0 = Debug|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.Release|Win32.ActiveCfg = Release|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.Release|Win32.Build.0 = Release|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {14E546AD-2393-41B9-BAA2-134241286A4E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.Build.0 = Debug|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.ActiveCfg = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.Build.0 = Release|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.ActiveCfg = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.Build.0 = Debug|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.ActiveCfg = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.Build.0 = Release|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Debug|Win32.ActiveCfg = Debug|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Debug|Win32.Build.0 = Debug|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Release|Win32.ActiveCfg = Release|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Release|Win32.Build.0 = Release|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {83B388D3-BE71-476A-AA6A-CC7082E3866D}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.Debug|Win32.ActiveCfg = Debug|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.Debug|Win32.Build.0 = Debug|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.Release|Win32.ActiveCfg = Release|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.Release|Win32.Build.0 = Release|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {14DC504E-697F-4178-8E05-87173957FE59}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Debug|Win32.ActiveCfg = Debug|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Debug|Win32.Build.0 = Debug|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Release|Win32.ActiveCfg = Release|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Release|Win32.Build.0 = Release|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Debug|Win32.ActiveCfg = Debug|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Debug|Win32.Build.0 = Debug|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Release|Win32.ActiveCfg = Release|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Release|Win32.Build.0 = Release|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {80FC7669-D649-4212-8B6F-C0167CE9CB59}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {71641E56-5E9E-462B-844F-A9F8A6D82120}.Debug|Win32.ActiveCfg = Debug|Win32 + {71641E56-5E9E-462B-844F-A9F8A6D82120}.Release|Win32.ActiveCfg = Release|Win32 + {71641E56-5E9E-462B-844F-A9F8A6D82120}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {71641E56-5E9E-462B-844F-A9F8A6D82120}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.ActiveCfg = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.Build.0 = Debug|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.ActiveCfg = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.Build.0 = Release|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Debug|Win32.ActiveCfg = Debug|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Debug|Win32.Build.0 = Debug|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Release|Win32.ActiveCfg = Release|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Release|Win32.Build.0 = Release|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.Debug|Win32.ActiveCfg = Debug|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.Debug|Win32.Build.0 = Debug|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.Release|Win32.ActiveCfg = Release|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.Release|Win32.Build.0 = Release|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 + {53399ED8-C4B0-4F84-9CA8-623049125822}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Code/Physics/Bullet Source/AUTHORS b/Code/Physics/Bullet Source/AUTHORS new file mode 100644 index 00000000..f2cc86dd --- /dev/null +++ b/Code/Physics/Bullet Source/AUTHORS @@ -0,0 +1,22 @@ + +Bullet Physics Library is an open source project with help from the community at the Physics Forum +See the forum at http://bulletphysics.com + +The project was started by Erwin Coumans + +Following people contributed to Bullet +(random order, please let us know on the forum if your name should be in this list) + +Gino van den Bergen: LinearMath classes +Christer Ericson: parts of the voronoi simplex solver +Simon Hobbs: 3d axis sweep and prune, Extras/SATCollision, separating axis theorem + SIMD code +Dirk Gregorius: generic D6 constraint +Erin Catto: accumulated impulse in sequential impulse +Nathanael Presson: EPA penetration depth calculation +Francisco Leon: GIMPACT Concave Concave collision +Joerg Henrichs: make buildsystem (work in progress) +Eric Sunshine: jam + msvcgen buildsystem +Steve Baker: GPU physics and general implementation improvements +Jay Lee: Double precision support +KleMiX, aka Vsevolod Klementjev, managed version, rewritten in C# for XNA +Erwin Coumans: most other source code diff --git a/Code/Physics/Bullet Source/BspDemo.bsp b/Code/Physics/Bullet Source/BspDemo.bsp new file mode 100644 index 0000000000000000000000000000000000000000..4ed414d75b92d4d94b05589c46bc8f66bee34686 GIT binary patch literal 105100 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 HQ-1y*qN~We literal 0 HcmV?d00001 diff --git a/Code/Physics/Bullet Source/BulletConfig.cmake.in b/Code/Physics/Bullet Source/BulletConfig.cmake.in new file mode 100644 index 00000000..f5dc7bdb --- /dev/null +++ b/Code/Physics/Bullet Source/BulletConfig.cmake.in @@ -0,0 +1,25 @@ +# -*- cmake -*- +# +# BulletConfig.cmake(.in) +# + +# Use the following variables to compile and link against Bullet: +# BULLET_FOUND - True if Bullet was found on your system +# BULLET_USE_FILE - The file making Bullet usable +# BULLET_DEFINITIONS - Definitions needed to build with Bullet +# BULLET_INCLUDE_DIR - Directory where Bullet-C-Api.h can be found +# BULLET_INCLUDE_DIRS - List of directories of Bullet and it's dependencies +# BULLET_LIBRARIES - List of libraries to link against Bullet library +# BULLET_LIBRARY_DIRS - List of directories containing Bullet' libraries +# BULLET_ROOT_DIR - The base directory of Bullet +# BULLET_VERSION_STRING - A human-readable string containing the version + +set ( BULLET_FOUND 1 ) +set ( BULLET_USE_FILE "@BULLET_USE_FILE@" ) +set ( BULLET_DEFINITIONS "@BULLET_DEFINITIONS@" ) +set ( BULLET_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@" ) +set ( BULLET_INCLUDE_DIRS "@INCLUDE_INSTALL_DIR@" ) +set ( BULLET_LIBRARIES "@BULLET_LIBRARIES@" ) +set ( BULLET_LIBRARY_DIRS "@LIB_DESTINATION@" ) +set ( BULLET_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" ) +set ( BULLET_VERSION_STRING "@BULLET_VERSION@" ) \ No newline at end of file diff --git a/Code/Physics/Bullet Source/BulletLicense.txt b/Code/Physics/Bullet Source/BulletLicense.txt new file mode 100644 index 00000000..2e5680a8 --- /dev/null +++ b/Code/Physics/Bullet Source/BulletLicense.txt @@ -0,0 +1,18 @@ +/* +Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +Free for commercial use, please report projects in the forum at http://www.bulletphysics.org + +In case you want to display a Bullet logo in your software: you can download the Bullet logo in various vector formats and high resolution at the download section in http://bullet.googlecode.com diff --git a/Code/Physics/Bullet Source/CMakeLists.txt b/Code/Physics/Bullet Source/CMakeLists.txt new file mode 100644 index 00000000..18a089a9 --- /dev/null +++ b/Code/Physics/Bullet Source/CMakeLists.txt @@ -0,0 +1,439 @@ +cmake_minimum_required(VERSION 2.4.3) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) + +#this line has to appear before 'PROJECT' in order to be able to disable incremental linking +SET(MSVC_INCREMENTAL_DEFAULT ON) + +PROJECT(BULLET_PHYSICS) +SET(BULLET_VERSION 2.82) + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +IF (NOT CMAKE_BUILD_TYPE) +# SET(CMAKE_BUILD_TYPE "Debug") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF (NOT CMAKE_BUILD_TYPE) + +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") +#MESSAGE("CMAKE_CXX_FLAGS_DEBUG="+${CMAKE_CXX_FLAGS_DEBUG}) + +OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF) +OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON) + + +OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" OFF) +OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) + +OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF) + +IF (USE_CUSTOM_VECTOR_MATH) + ADD_DEFINITIONS(-DUSE_SYSTEM_VECTORMATH) + IF(WIN32) + SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/sse CACHE PATH "Vector Math library include path.") + ELSE(WIN32) + SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/scalar CACHE PATH "Vector Math library include path.") + ENDIF(WIN32) +ENDIF(USE_CUSTOM_VECTOR_MATH) + + +IF (APPLE OR MSVC) + OPTION(BUILD_MULTITHREADING "Use BulletMultiThreading" ON) +ELSE() + OPTION(BUILD_MULTITHREADING "Use BulletMultiThreading" OFF) +ENDIF() + +IF (BUILD_MULTITHREADING) + OPTION(USE_MULTITHREADED_BENCHMARK "Use Multithreaded Benchmark" OFF) + IF (USE_MULTITHREADED_BENCHMARK) + ADD_DEFINITIONS(-DUSE_PARALLEL_SOLVER_BENCHMARK -DUSE_PARALLEL_DISPATCHER_BENCHMARK) + ENDIF(USE_MULTITHREADED_BENCHMARK) + + IF (MSVC OR APPLE) + OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" ON) + ELSE() + OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" OFF) + ENDIF(MSVC OR APPLE) + + IF(MSVC) + FIND_PATH(DIRECTX_SDK_BASE_DIR Include/D3D11.h PATH $ENV{DXSDK_DIR} ) + IF(DIRECTX_SDK_BASE_DIR) + OPTION(USE_DX11 "Use DirectX 11" ON) + ELSE() + OPTION(USE_DX11 "Use DirectX 11" OFF) + ENDIF() + + FIND_PATH(AMD_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{ATISTREAMSDKROOT} $ENV{AMDAPPSDKROOT} ) + IF(AMD_OPENCL_BASE_DIR) + #AMD adds an extras slash at the end of the ATISTREAMSDKROOT variable + SET(AMD_OPENCL_INCLUDES ${AMD_OPENCL_BASE_DIR}/include ) + MESSAGE("AMD OPENCL SDK FOUND") + IF (CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86_64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86 ) + ENDIF(CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBRARY ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib ) + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" ON) + IF (CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY + ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) + ELSE(CMAKE_CL_64) + SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) + ENDIF(CMAKE_CL_64) + ELSE() + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" OFF) + ENDIF() + + FIND_PATH(INTEL_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{INTELOCLSDKROOT} ) + IF(INTEL_OPENCL_BASE_DIR) + SET(INTEL_OPENCL_INCLUDES ${INTEL_OPENCL_BASE_DIR}/include ) + MESSAGE("INTEL OPENCL SDK FOUND") + MESSAGE(${INTEL_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_INTELOCLSDK_LIBPATH ${INTEL_OPENCL_BASE_DIR}/lib/x64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_INTELOCLSDK_LIBPATH ${INTEL_OPENCL_BASE_DIR}/lib/x86 ) + ENDIF(CMAKE_CL_64) + SET(INTEL_OPENCL_LIBRARIES ${CMAKE_INTELOCLSDK_LIBPATH}/OpenCL.lib) + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" ON) + ELSE() + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" OFF) + ENDIF() + + FIND_PATH(NVIDIA_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{CUDA_PATH} ) + IF(NVIDIA_OPENCL_BASE_DIR) + SET(NVIDIA_OPENCL_INCLUDES ${NVIDIA_OPENCL_BASE_DIR}/include ) + MESSAGE("NVIDIA OPENCL SDK FOUND") + MESSAGE(${NVIDIA_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/lib/x64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/lib/Win32 ) + ENDIF(CMAKE_CL_64) + SET(NVIDIA_OPENCL_LIBRARIES ${CMAKE_NVSDKCOMPUTE_LIBPATH}/OpenCL.lib) + + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) + ELSE() + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) + ENDIF() + ELSE(MSVC) + FIND_PATH(AMD_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{ATISTREAMSDKROOT} $ENV{AMDAPPSDKROOT} ) + IF(AMD_OPENCL_BASE_DIR) + #AMD adds an extras slash at the end of the ATISTREAMSDKROOT variable + SET(AMD_OPENCL_INCLUDES ${AMD_OPENCL_BASE_DIR}/include ) + MESSAGE("AMD OPENCL SDK FOUND") + MESSAGE(${AMD_OPENCL_INCLUDES}) + IF (CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86_64 ) + ELSE(CMAKE_CL_64) + SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86 ) + ENDIF(CMAKE_CL_64) + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" ON) + SET(CMAKE_ATISTREAMSDK_LIBRARY OpenCL ) + ELSE() + OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" OFF) + ENDIF(AMD_OPENCL_BASE_DIR) + + FIND_PATH(INTEL_OPENCL_INCLUDES CL/cl.h) + FIND_PATH(INTEL_OPENCL_ICD_CFG intelocl64.icd /etc/OpenCL/vendors) + FIND_LIBRARY(INTEL_OPENCL_LIBRARIES OpenCL PATH /usr/lib64) + IF (INTEL_OPENCL_INCLUDES AND INTEL_OPENCL_LIBRARIES AND INTEL_OPENCL_ICD_CFG) + MESSAGE("INTEL OPENCL SDK FOUND") + MESSAGE(${INTEL_OPENCL_LIBRARIES}) + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" ON) + ELSE () + MESSAGE("INTEL OPENCL NOT FOUND") + OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" OFF) + ENDIF () + + + FIND_PATH(NVIDIA_OPENCL_INCLUDES CL/cl.h) + FIND_PATH(NVIDIA_OPENCL_ICD_CFG nvidia.icd /etc/OpenCL/vendors) + FIND_LIBRARY(NVIDIA_OPENCL_LIBRARIES OpenCL PATH /usr/lib64 /usr/local/lib) + IF (NVIDIA_OPENCL_INCLUDES AND NVIDIA_OPENCL_LIBRARIES AND NVIDIA_OPENCL_ICD_CFG) + MESSAGE("NVidia OPENCL FOUND") + MESSAGE(${NVIDIA_OPENCL_LIBRARIES}) + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) + ELSE () + MESSAGE("NVidia OPENCL NOT FOUND") + OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) + ENDIF () + ENDIF(MSVC) + +ELSE(BUILD_MULTITHREADING) +# SET(BUILD_NVIDIA_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for NVidia" FORCE) +# SET(BUILD_AMD_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for AMD" FORCE) +# SET(BUILD_INTEL_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for Intel (CPU)" FORCE) +# SET(BUILD_MINICL_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for MiniCL (Generic CPU)" FORCE) +# SET(USE_DX11 OFF CACHE BOOL "Use DirectX 11" FORCE) +# SET(USE_MULTITHREADED_BENCHMARK OFF CACHE BOOL "Use Multithreaded Benchmark" FORCE) +ENDIF(BUILD_MULTITHREADING) + + + + +#SET(CMAKE_EXE_LINKER_FLAGS_INIT "/STACK:10000000 /INCREMENTAL:NO") +#SET(CMAKE_EXE_LINKER_FLAGS "/STACK:10000000 /INCREMENTAL:NO") + +#MESSAGE("MSVC_INCREMENTAL_YES_FLAG"+${MSVC_INCREMENTAL_YES_FLAG}) + + +IF(MSVC) + IF (NOT USE_MSVC_INCREMENTAL_LINKING) + #MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT}) + SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO") + + STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) + SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/INCREMENTAL:NO ${replacementFlags}" ) + MESSAGE("CMAKE_EXE_LINKER_FLAGS_DEBUG=${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + +# STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags2 ${CMAKE_EXE_LINKER_FLAGS}) +# SET(CMAKE_EXE_LINKER_FLAGS ${replacementFlag2}) +# STRING(REPLACE "INCREMENTAL:YES" "" replacementFlags3 ${CMAKE_EXTRA_LINK_FLAGS}) +# SET(CMAKE_EXTRA_LINK_FLAGS ${replacementFlag3}) + + + STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags3 ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}) + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacementFlags3}) + SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/INCREMENTAL:NO ${replacementFlags3}" ) + + ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING) + + IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) + #We statically link to reduce dependancies + FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + IF(${flag_var} MATCHES "/MD") + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MD") + IF(${flag_var} MATCHES "/MDd") + STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") + ENDIF(${flag_var} MATCHES "/MDd") + ENDFOREACH(flag_var) + ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) + + IF (CMAKE_CL_64) + ADD_DEFINITIONS(-D_WIN64) + ELSE() + OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" ON) + IF (USE_MSVC_SSE) + ADD_DEFINITIONS(/arch:SSE) + ENDIF() + ENDIF() + OPTION(USE_MSVC_FAST_FLOATINGPOINT "Use MSVC /fp:fast option" ON) + IF (USE_MSVC_FAST_FLOATINGPOINT) + ADD_DEFINITIONS(/fp:fast) + ENDIF() +ENDIF(MSVC) + + + +IF (WIN32) +OPTION(INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES "Create MSVC projectfiles that can be distributed" OFF) + +IF (INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + SET (LIBRARY_OUTPUT_PATH ${BULLET_PHYSICS_SOURCE_DIR}/lib CACHE PATH "Single output directory for building all libraries.") + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${BULLET_PHYSICS_SOURCE_DIR}) + SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${BULLET_PHYSICS_SOURCE_DIR}) +ELSE() + SET (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib CACHE PATH "Single output directory for building all libraries.") +ENDIF() + + + +OPTION(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES "Create MSVC projectfiles with relative paths" OFF) +OPTION(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES "Add MSVC postfix for executable names (_Debug)" OFF) + +SET(CMAKE_DEBUG_POSTFIX "_Debug" CACHE STRING "Adds a postfix for debug-built libraries.") +SET(CMAKE_MINSIZEREL_POSTFIX "_MinsizeRel" CACHE STRING "Adds a postfix for MinsizeRelease-built libraries.") +SET(CMAKE_RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo" CACHE STRING "Adds a postfix for ReleaseWithDebug-built libraries.") + + + + + +IF (INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) +SET(CMAKE_SUPPRESS_REGENERATION 1) +SET(CMAKE_USE_RELATIVE_PATHS 1) +ENDIF(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) + +ENDIF (WIN32) + + +OPTION(BUILD_CPU_DEMOS "Build original Bullet CPU demos" ON) + + + +OPTION(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES "Internal update serialization structures" OFF) +IF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) +ADD_DEFINITIONS( -DBT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) +ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) + +IF (USE_DOUBLE_PRECISION) +ADD_DEFINITIONS( -DBT_USE_DOUBLE_PRECISION) +SET( BULLET_DOUBLE_DEF "-DBT_USE_DOUBLE_PRECISION") +ENDIF (USE_DOUBLE_PRECISION) + +IF(USE_GRAPHICAL_BENCHMARK) +ADD_DEFINITIONS( -DUSE_GRAPHICAL_BENCHMARK) +ENDIF (USE_GRAPHICAL_BENCHMARK) + +IF (WIN32) +OPTION(USE_GLUT "Use Glut" ON) +ADD_DEFINITIONS( -D_IRR_STATIC_LIB_ ) +ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE ) +ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + +IF (USE_GLUT AND MSVC) + string (REPLACE "/D_WINDOWS" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + remove_definitions(-D_WINDOWS ) +ENDIF() + + + +ELSE(WIN32) +OPTION(USE_GLUT "Use Glut" ON) +ENDIF(WIN32) + + +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + + +# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system +# This should be the case. + +FIND_PACKAGE(OpenGL) +IF (OPENGL_FOUND) + MESSAGE("OPENGL FOUND") + MESSAGE(${OPENGL_LIBRARIES}) +ELSE (OPENGL_FOUND) + MESSAGE("OPENGL NOT FOUND") + SET(OPENGL_gl_LIBRARY opengl32) + SET(OPENGL_glu_LIBRARY glu32) +ENDIF (OPENGL_FOUND) + +# ADD_DEFINITIONS(-DBT_USE_FREEGLUT) + +FIND_PACKAGE(GLU) + +IF (USE_GLUT) + FIND_PACKAGE(GLUT) + IF (GLUT_FOUND) + MESSAGE("GLUT FOUND") + MESSAGE(${GLUT_glut_LIBRARY}) + ELSE (GLUT_FOUND) + IF (MINGW) + MESSAGE ("GLUT NOT FOUND not found, trying to use MINGW glut32") + SET(GLUT_glut_LIBRARY glut32) + #TODO add better GLUT detection for MinGW + SET(GLUT_FOUND TRUE) + ENDIF (MINGW) + IF (MSVC) + SET(GLUT_FOUND TRUE) + IF (CMAKE_CL_64) + message("Win64 using Glut/glut64.lib") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut64.lib) + ELSE(CMAKE_CL_64) + message("Win32 using Glut/glut32.lib") + SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib) + ENDIF (CMAKE_CL_64) + INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/Glut) + ELSE() + MESSAGE("GLUT NOT FOUND") + ENDIF (MSVC) + ENDIF (GLUT_FOUND) + + IF(NOT WIN32) + # This is added for linux. This should always work if everything is installed and working fine. + INCLUDE_DIRECTORIES(/usr/include /usr/local/include) + ENDIF() +ENDIF(USE_GLUT) + + +OPTION(BUILD_DEMOS "Set when you want to build the demos" ON) +IF(BUILD_DEMOS) + IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/Demos AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/Demos) + SUBDIRS(Demos) + ENDIF() +ENDIF(BUILD_DEMOS) + +# "Demos_ps3") +IF (MSVC) + IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) + IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/Demos_ps3 AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/Demos_ps3) + MESSAGE("Demos_ps3 found") + SUBDIRS(Demos_ps3) + ENDIF() + ENDIF() +ENDIF(MSVC) + + +OPTION(BUILD_EXTRAS "Set when you want to build the extras" ON) +IF(BUILD_EXTRAS) + SUBDIRS(Extras) +ENDIF(BUILD_EXTRAS) + +#Maya Dynamica plugin is moved to http://dynamica.googlecode.com + +SUBDIRS(src) + +IF("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") + OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) +ELSE() + IF(APPLE AND FRAMEWORK) + OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) + ELSE() +#by default, don't enable the 'INSTALL' option for Xcode and MSVC projectfiles + OPTION(INSTALL_LIBS "Set when you want to install libraries" OFF) + ENDIF() +ENDIF() + +IF(INSTALL_LIBS) + SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) + SET (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") + ## the following are directories where stuff will be installed to + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/bullet/" CACHE PATH "The subdirectory to the header prefix") + SET(PKGCONFIG_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files") + IF(NOT WIN32) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bullet.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc @ONLY) + INSTALL( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc + DESTINATION + ${PKGCONFIG_INSTALL_PREFIX}) + ENDIF(NOT WIN32) +ENDIF(INSTALL_LIBS) + +#INSTALL of other files requires CMake 2.6 +IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + OPTION(INSTALL_EXTRA_LIBS "Set when you want extra libraries installed" OFF) +ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) + +OPTION(BUILD_UNIT_TESTS "Build Unit Tests" OFF) + +IF (BUILD_UNIT_TESTS) + SUBDIRS(UnitTests) +ENDIF() + +set (BULLET_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/bullet ) +list (APPEND BULLET_LIBRARIES LinearMath) +list (APPEND BULLET_LIBRARIES BulletCollisions) +list (APPEND BULLET_LIBRARIES BulletDynamics) +list (APPEND BULLET_LIBRARIES BulletSoftBody) +set (BULLET_USE_FILE ${CMAKE_INSTALL_PREFIX}/${BULLET_CONFIG_CMAKE_PATH}/UseBullet.cmake) +configure_file ( ${CMAKE_SOURCE_DIR}/BulletConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/BulletConfig.cmake + @ONLY ESCAPE_QUOTES + ) +install ( FILES ${CMAKE_SOURCE_DIR}/UseBullet.cmake + ${CMAKE_CURRENT_BINARY_DIR}/BulletConfig.cmake + DESTINATION ${BULLET_CONFIG_CMAKE_PATH} + ) diff --git a/Code/Physics/Bullet Source/COPYING b/Code/Physics/Bullet Source/COPYING new file mode 100644 index 00000000..794842d9 --- /dev/null +++ b/Code/Physics/Bullet Source/COPYING @@ -0,0 +1,17 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2011 Erwin Coumans http://bulletphysics.org + +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. +*/ + +All files in the Bullet/src folder are under this Zlib license. +Files in the Extras and Demos folder may have a different license, see the respective files. diff --git a/Code/Physics/Bullet Source/ChangeLog b/Code/Physics/Bullet Source/ChangeLog new file mode 100644 index 00000000..f5c85c80 --- /dev/null +++ b/Code/Physics/Bullet Source/ChangeLog @@ -0,0 +1,795 @@ +Bullet Continuous Collision Detection and Physics Library +Primary author and maintainer: Erwin Coumans + +This ChangeLog is incomplete, for an up-to-date list of all fixed issues see http://bullet.googlecode.com +using http://tinyurl.com/yabmjjj + +2013 October 23 + - Bullet 2.82 release + - See docs/BulletQuickstart.pdf or issue tracked for details. + +2012 September 10 + - Bullet 2.81 release preparation + +2011 September 15 + - Bullet 2.79 release, revision 2433 (mainly a bugfix release) + - Revert a change in 2.78 related to speculative contacts (it has undesired side effects) + - Use HACD Hierachical Approximate Convex Decomposition (thanks to Khaled Mammou and Sujeon Kim) + - Add Intel cmake-build support for OpenCL accelerated cloth/particle + - add premake4 build system support to autogenerate visual studio project files that can be shipped (see msvc folder) + - preliminary build support for Google NativeClient, using premake4 (see msvc folder) + + +2011 April 8 + - Bullet 2.78 release 2383 + - Added FractureDemo + - Added Separatinx Axis Test and Polyhedral Clipping support (See InternalEdgeDemo) + - Added speculative contacts as CCD response method (See CcdPhysicsDemo) + - OpenCL and DirectCompute cloth as basic support for capsule collision + +2010 September 7 + - autotools now uses CamelCase naming for libraries just like cmake: + libbulletdynamics -> libBulletDynamics, libbulletmath -> libLinearMath + +2010 July 21 + - Preparing for Bullet 2.77 release, around revision r2135 + - Added an OpenCL particle demo, running on NVidia, AMD and MiniCL + Thanks to NVidia for the original particle demo from their OpenCL SDK + - Added GPU deformable object solvers for OpenCL and DirectCompute, and a DirectX 11 cloth demo + Thanks to AMD + - Create a separate library for MiniCL, + MiniCL is a rudimentary OpenCL wrapper that allows to compile OpenCL kernels for multi-core CPU, using Win32 Threads or Posix + - Moved vectormath into Bullet/src, and added a SSE implementation + - Added a btParallelConstraintSolver, mainly for PlayStation 3 Cell SPUs (although it runs fine on CPU too) + +2010 March 6 + - Dynamica Maya plugin (and COLLADA support) is moved to http://dynamica.googlecode.com + +2010 February + - Bullet 2.76 release, revision 2010 + - support for the .bullet binary file format + - btInternalEdgeUtility to adjust unwanted collisions against internal triangle edges + - Improved Maya Dynamica plugin with better constraint authoring and .bullet file export + + +2009 September 17 + - Minor update to Bullet 2.75 release, revision 1776 + - Support for btConvex2dShape, check out Bullet/Demos/Box2dDemo + - Fixes in build systems + - Minor fix in btGjkPairDetector + - Initialize world transform for btCollisionShape in constructor + + +2009 September 6 + - Bullet 2.75 release + - Added SPH fluid simulation in Extras, not integrated with rigid body / soft body yet + Thanks to Rama Hoetzlein to make this contribution available under the ZLib license + - add special capsule-capsule collider code in btConvexConvexCollisionAlgorithm, to speed up capsule-ragdolls + - soft body improvement: faster building of bending constraints + - soft body improvement: allow to disable/enable cluster self-collision + - soft body fix: 'exploding' soft bodies when using cluster collision + - fix some degenerate cases in continuous convex cast, could impact ray cast/convex cast + Thanks to Jacob Langford for the report and reproduction cases, see http://code.google.com/p/bullet/issues/detail?id=250&can=1&start=200 + - re-enabled split impulse + - added btHinge2Constraint, btUniversalConstraint, btGeneric6DofSpringConstraint + - demonstrate 2D physics with 2D/3D object interaction + + +2008 December 2 + - Fix contact refresh issues with btCompoundShape, introduced with btDbvt acceleration structure in btCompoundCollisionAlgorithm + - Made btSequentialImpulseConstraintSolver 100% compatible with ODE quickstep + constraints can use 'solveConstraint' method or 'getInfo/getInfo2' + +2008 November 30 + - Add highly optimized SIMD branchless PGS/SI solver innerloop + +2008 November 12 + - Add compound shape export to BulletColladaConverter + Thanks to JamesH for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=12&t=2840 + - Fix compiler build for Visual Studio 6 + Thanks to JoF for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2841 + +2008 November 11 + - Add CProfileManager::dumpAll() to dump performance statistics to console using printf. + - Add support for interaction between btSoftBody and btCollisionObject/btGhostObject + +2008 November 8 + - Fix PosixThreadSupport + - Add improved btHeightfieldTerrainShape support and new Demos/TerrainDemo + Thanks to tomva, http://code.google.com/p/bullet/issues/detail?id=63&can=1 + - Moved kinematic character controller from Demos/CharacterDemo into src/BulletDynamics/Character/btKinematicCharacterController.cpp + +2008 November 6 + - reduced default memory pool allocation from 40Mb to 3Mb. This should be more suitable for all platforms, including iPhone + - improved CUDA broadphase + - IBM Cell SDK 3.x support, fix ibmsdk Makefiles + - improved CMake support with 'install' and 'framework option + +2008 November 4 + - add btAxisSweep::resetPool to avoid non-determinism due to shuffled linked list + Thanks to Ole for the contribution, + +2008 October 30 + - disabled btTriangleMesh duplicate search by default, it is extremely slow + - added Extras/IFF binary chunk serialization library as preparation for in-game native platform serialization (planned COLLADA DOM -> IFF converter) + +2008 October 20 + - added SCE Physics Effects box-box collision detection for SPU/BulletMultiThreaded version + See Bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp + Thanks to Sony Computer Entertainment Japan, SCEI for the contribution + +2008 October 17 + - Added btGhostObject support, this helps character controller, explosions, triggers and other local spatial queries + +2008 October 10 + - Moved aabb to btBroadphaseProxy, improves rayTest dramatically. Further raytest improvements using the broadphase acceleration structures are planned + - Moved BulletMultiThreaded from Extras to /src/BulletMultiThreaded for better integration + + +2008 October 3 + - Add support for autoconf automake + ./autogen.sh and ./configure will create both Makefile and Jamfile. CMake and autogenerated Visual Studio projectfiles remain supported too. + - Improved ColladaConverter: plane shape export, and callback for shape construction to allow deletion of memory + +2008 Sept 30 + - Improved Soft Body support, fixed issues related to soft body colliding against concave triangle meshes + - Shared more code between regular version and SPU/BulletMultiThreaded, in particular GJK/EPA + +2008 Sept 28 + - Fixed rotation issues in Dynamic Maya Plugin + +2008 Sept 11 + - Enable CCD motion clamping for btDiscreteDynamicsWorld, to avoid tunneling. A more advanced solution will be implemented in btContinuousDynamicsWorld. + +2008 Sept 7 + - Add btScaledBvhTriangleMeshShape, to allow re-use of btBvhTriangleMeshShape of different sizes, without copying of the BVH data. + +2008 Sept 5 + - Enabled Demos/ForkLiftDemo + Thanks Roman Ponomarev. + +2008 Sept 4 + - Added btCudaBroadphase in Extras/CUDA: some research into accelerating Bullet using CUDA. + Thanks to the particle demo from the NVidia CUDA SDK. + +2008 Sept 3 + - Several bug fixes and contributions related to inertia tensor, memory leaks etc. + Thanks to Ole K. + +2008 Sept 1 + - Updated CDTestFramework, with latest version of OPCODE Array SAP. See Extras/CDTestFramework + Thanks to Pierre Terdiman for the update + +2008 August 25 + - Walt Disney Studios contributes their in-house Maya Plugin for simulating Bullet physics, with options for other engines such as PhysBam or PhysX. + Thanks to Nicola Candussi and Arthur Shek + +2008 August 14 + - Improved performance for btDbvtBroadphase, based on dual dynamic AABB trees (one for static, one for dynamic objects, where objects can move from one to the other tree) + Thanks to Nathanael Presson again, for all his work. + +2008 July 31 + - Added Havok .hkx to COLLADA Physics .dae converter patch+information + - Fix btSubsimplexConvexCast + Thanks to Nacho, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2422) + - Fix in rendering, GL_STENCIL + - btTriangleIndexVertexArray indices should be unsigned int/unsigned short int, + - Made InternalProcessAllTriangles virtual, thanks to + Both thank to Fullmetalcoder, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2401 + - clamp impulse for btPoint2PointConstraint + Thanks to Martijn Reuvers, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2418 + - Free memory of bvh, pass in scaling factor (optional) + Thanks to Roy Eltham, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2375 + +2008 July 27 + +btDbvtBroadphase: + - Fixed a performance issues reported by 'reltham' + - Added btDbvtBroadphase::optimize() for people who want good performances right +away or don't do dynamics. + - fixed compilation issues when DBVT_BP_PROFILE was set. +btSoftBody: + - Fixed singular matrix issues related to polar decomposition (flat meshes). +DemoApplication: + - Shadows (enable/disable through 'g' or DemoApplication::setShadows(bool)). + - Texture can be enable/disable through 'u' +CDFramework: + - fixed compilation issues. + All thanks to Nathanael Presson + +2008 July 10 + - Added btMultimaterialTriangleMeshShape and MultiMaterialDemo + Thanks to Alex Silverman for the contribution + +2008 June 30 + - Added initial support for kinematic character controller + Thanks to John McCutchan + +2008 April 14 + - Added ray cast support for Soft Bodies + Thanks to Nathanael Presson for the contribution + +2008 April 9 + - Cleanup of Stan Melax ConvexHull, removed Extras/ConvexHull, moved sources into LinearMath/BulletCollision + +2008 April 4 + - Added btSliderConstraint and demo + Thanks Roman Ponomarev + +2008 April 3 + - Fixed btMinkowskiSumShape, and added hitpoint to btSubsimplexConvexCast + +2008 April 2 + - Added Extras/CdTestFrameWork + Thanks Pierre Terdiman + +2008 April 1 + - Added posix thread (pthread) support + Thanks Enrico + +2008 March 30 + - Added Soft Body, cloth, rope and deformable volumes, including demos and interaction + Thanks Nathanael Presson for this great contribution + + 2008 March 17 + - Improved BulletColladaConverter + Thanks John McCutchan + +2008 March 15 + - btMultiSapBroadphase in a working state. Needs more optimizations to be fully useable. + - Allow btOptimizedBvh to be used for arbitrary objects, not just triangles + - added quicksort to btAlignedObjectArray + - removed btTypedUserInfo, added btHashMap + +2008 March 30 + - Moved quickstep solver and boxbox into Bullet/src folder + Thanks Russell L. Smith for permission to redistribute Open Dynamics Engine quickstep and box-box under the ZLib license + +2008 Feb 27 + - Added initial version for Character Control Demo + - Applied fixes to IBM Cell SDK 3.0 build makefiles + Thanks Jochen and mojo for reporting/providing patch: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1922 + +2008 Feb 8 + - Bugfixes in ConvexCast support against the world. + Thanks to Isgmasa for reporting/providing fix: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1823 + +2008 Feb 6 + - Added btCapsuleShapeX and btCapsuleShapeZ for capsules around X and Z axis (default capsule is around Y) + +2008 Feb 3 + - Added btTypedUserInfo, useful for serialization + +2008 Jan 31 + - Add support for 16 and 32-bit indices for SPU / BulletMultiThreaded version. + +2008 Jan 29 + - Added COLLADA Physics export/serialization/snapshot from any Bullet btDynamicsWorld. Saving the physics world into a text .xml file is useful for debugging etc. + +2008 Jan 23 + - Added Stan Melax Convex Hull utility library in Extras/ConvexHull. This is useful to render non-polyhedral convex objects, and to simplify convex polyhedra. + +2008 Jan 14 + - Add support for batch raycasting on SPU / BulletMultiThreaded + +2007 Dec 16 + - Added btRigidBodyConstructionInfo, to make it easier to set individual setting (and leave other untouched) during rigid body construction. + Thanks Vangelis Kokkevis for pointing this out. + - Fixed memoryleak in the ConstraintDemo and Raytracer demo. + - Fixed issue with clearing forces/gravity at the end of the stepSimulation, instead of during internalSingleStepSimulation. + Thanks chunky for pointing this out: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1780 + - Disabled additional damping in rigid body by default, but enable it in most demos. Set btRigidBodyConstructionInfo m_additionalDamping to true to enable this. + - Removed obsolete QUICKPROF BEGIN/END_PROFILE, and enabled BT_PROFILE. Profiling is enabled by default (see Bullet/Demos/OpenGL/DemoApplication.cpp how to use this). + User can switch off profiling by enabling define BT_NO_PROFILE in Bullet/src/btQuickprof.h. + +2007 Dec 14 + - Added Hello World and BulletMultiThreaded demos + - Add portable version of BulletMultiThreaded, through SequentialThreadSupport (non-parallel but sharing the same code-path) + - Add Cmake support for AllBulletDemos + + +2007 Dec 11 + - Moved the 'btRigidBody::clearForce' to the end of the stepSimulation, instead of in each substep. + See discussion http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1601 + - Added btConvexPlaneCollisionAlgorithm, makes planes perform better, and prevents tunneling + Thanks Andy O'Neil for reporting the performance/functionality issue + - Fixes for IBM Cell SDK 3.0 + Thanks to Jochen Roth for the patch. + +2007 Dec 10 + - Fixes in btHeightfieldTerrainShape + Thanks to Jay Lee for the patch. + +2007 Dec 9 + - Only update aabb of active objects + Thanks Peter Tchernev for reporting (http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1764 ) + - Added workaround to compile libxml under Visual Studio 2008 Beta 2 + - Make glui compile under MSVC 9.0 beta (vsnprintf is already defined) + +2007 Dec 6 + - Added DynamicControlDemo, showing dynamic control through constraint motors + Thanks to Eddy Boxerman + - Add support for generic concave shapes for convex cast. + - Added convex cast query to collision world. + - Added workaround for OpenGL bug in Mac OS X 10.5.0 (Leopard) + - Added concave raycast demo + All above thanks to John McCutchan (JMC) + - Fixed issues that prevent Linux version to compile. + Thanks to Enrico for reporting and patch, see + - Fixed misleading name 'numTriangleIndices' into 'numTriangles' + Thanks Sean Tasker for reporting: + +2007 Nov 28: + - Added raycast against trianglemesh. Will be extended to object cast soon. + Thanks John McCutchan (JMC) + - make getNumPoints const correct, add const getPoints(). + Thanks Dirk Gregorius + - Bugfix: allow btCollisionObjects (non-btRigidBody) to interact properly with btRigidBody for cache-friendly btSequentialImpulseConstraintSolver. + Thanks Andy O'Neil for pointing this out. + - Bugfix: don't fail if spheres have identical center, use arbitrary separating normal (1,0,0) + Thanks Sean Tasker for reporting! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1681 + + +2007, November 20 + - Added hierarchical profiling + - Fixed memory leak in btMultiSapBroadphase, + - Fixed hash function (typo, should use 2 proxies) + Thanks to Stephen (shatcher) for reporting and fixes! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1696 + +2007 Nov 11 + - Fixed parallel solver (BulletMultiThreaded) friction issue + - Terminate Win32 Threads when closing the CcdPhysicsDemo (when USE_PARALLEL_SOLVER/USE_PARALLEL_DISPATCHER is defined) + +2007 Nov 6 + - Added support for 16-bit indices for triangle meshes + - Added support for multiple mesh parts using btBvhTriangleMeshShape. + Thanks to Tim Johansson + +2007 Oct 22 + - All memory allocations go through btAlignedAlloc/btAlignedFree. User can override this to verify memory leaks + - added a few more demos to AllBulletDemos + - fix for one of the constructors of btHingeConstraint + Thanks Marcus Hennix + +2007 Oct 20 + - included glui, a GLUT/OpenGL based toolkit for some graphical user elements + Removed dynamic_cast from glui, to allow linkage without rtti + - added Box2D framework using glui, allowing all demos to run within one executable + Thanks Erin Catto for the FrameWork skeleton (http://www.box2d.org) + +2007 Ocy 17 + - Allow user to pass in their own memory (stack and pool) allocators, through collisionConfiguration. See demos how to use this + +2007 Oct 14 + - Included working version of Cell SPU parallel optimized version for Libspe2 SPU task scheduler. + This version compiles and runs on Playstation 3 Linux and IBM CellBlade, see BulletSpuOptimized.pdf for build instructions + (Official Playstation 3 developers can request a SPURS version through Sony PS3 Devnet.) + Thanks to IBM 'Extreme Blue' project for the contribution + http://www-913.ibm.com/employment/us/extremeblue/ + Thanks Minh Cuong Tran, Benjamin Hoeferlin, Frederick Roth and Martina Huellmann + for various contributions to get this initial Libspe2 parallel version up and running. + +2007 Oct 13 + - made 'btCollisionShape::calculateLocalInertia' const + Thanks to cgripeos, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1514 + - applied a large patch to remove warnings + Thanks to Enrico, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1568 + - removed SSE includes, added #incude for memset in Extras/quickstep, thanks Eternl Knight + +2007 Oct 11 + - added Hashed Overlapping Pair Cache, recommended by Pierre Terdiman. It works like a charm, thanks Pierre and Erin Catto (code from Box2D) + - modified some margins inside btBoxShape, btCylinderShape and btSphereShape + - added cone debug rendering (for cones with x, y and z up-axis) + - added improvements for optional Extra/quickstep, thanks to Remotion + - some performance improvements for Bullet constraint solver + +2007 Sept 28 + - upgraded GIMPACT to version 0.3 + Thanks to Francisco Leon + +2007 Sept 27 + - added contribution from IBM Extreme Blue project for Libspe2 support. This allow to execute BulletMultiThreaded on Cell SPU under PS3 Linux and Cell Blade. See http://www-913.ibm.com/employment/us/extremeblue + Thanks to Minh Cuong Tran, Frederick Roth, Martina Heullmann and Benjamin Hoeferlin. + +2007 Sept 13 + - Improved btGenericD6Constraint. It can be used to create ragdolls (similar to the new btConeTwistConstraint). See GenericJointDemo + - Added support for Bullet constraints in the optional Extras/quickstep ODE solver. See CcdPhysicsDemo, enable #COMPARE_WITH_QUICKSTEP and add libquickstep to the dependencies. + For both patches/improvements thanks Francisco Leon/projectileman + +2007 Sept 10 + - removed union from btQuadWordStorage, it caused issues under certain version of gcc/Linux + +2007 Sept 10 + - Reverted constraint solver, due to some issues. Need to review the recent memory allocation changes. + - Fixed issue with kinematic objects rotating at low speed: quaternion was de-normalized, passing value > 1 into acosf returns #IND00 invalid values + - 16 byte memory alignment for BVH serialization + - memory cleanup for btPoolAllocator + +2007 Sept 9 + - Added serialization for BVH/btBvhTriangleMeshShape, including endian swapping. See ConcaveDemo for an example. + Thanks to Phil Knight for the contribution. + - Fixed issues related to stack allocator/compound collision algorithm + Thanks Proctoid, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=18&t=1460 + - Increase some default memory pool settings, and added a fallback for the constraints solver to use heap memory + - Removed accidential testing code in btScalar.h related to operator new. + - Enable btAxis3Sweep and bt32BitAxis3Sweep to be linked in at the same time, using template + +2007 Sept 7 + - Replaced several dynamic memory allocations by stack allocation and pool allocations + - Added branch-free quantized aabb bounding box overlap check, works better on Playstation 3 and XBox 360 + Thanks to Phil Knight. Also see www.cellperformance.com for related articles + - Collision algorithms and settings for the memory/stack allocator can be done using btDefaultCollisionConfiguration + This is an API change. See demos how to modify existing implementations with a one-liner. + - Register several collision algorithms by default (sphere-sphere, sphere-box, sphere-triangle) + - Use other traveral method for BVH by default, this improves triangle mesh collision performance. + +2007 Aug 31 + - fixed MSVC 6 build + Thanks Proctoid, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1375 + - fixed double precision build issues + Thanks Alex Silverman, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1434 + +2007 Aug 24 + - fixed bug in btMatrix3x3::transposeTimes(const btMatrix3x3& m) const. Luckily it wasn't used in core parts of the library (yet). + Thanks to Jay Lee + +2007 Aug 15 + - fixed bug in Extras/GIMPACT 0.2 related to moving triangle meshes + Thanks Thomas, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1368 + +2007 Aug 14 + - added parallel constraint solver. Works on Playstation 3 Cell SPU and multi core (Win Threads on PC and XBox 360). + See Extras/BulletMultiThreaded for SpuSolverTask subfolder and SpuParallelSolver.cpp + Thanks Marten Svanfeldt (Starbreeze Studios) + - fixed some bugs related to parallel collision detection (Extras/BulletMultiThreaded) + Thanks Marten Svanfeldt (Starbreeze Studios) + +2007 Aug 2 + - added compound and concave-convex (swapped) case for BulletMultiThreaded collision detection, thanks to Marten Svanfeldt + - refactored broadphase and overlapping pair cache. This allows performance improvement by combining multiple broadphases. This helps add/remove of large batches of objects and large worlds. See also Pierre Terdiman forum topic: + http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 + + +2007 July 27 + - added Ragdoll Demo + Thanks to Marten Svanfeldt (Starbreeze Studios) + + - added Vector Math library for SIMD 3D graphics linear algebra (vector, matrix, quaternion) + See Bullet/Extras/vectormathlibrary + Supports SIMD SSE, PowerPC PPU and Cell SPU (including PS3 Linux and CellBlade), as well as generic portable scalar version + Will be used to improve BulletMultiThreaded performance + Open Sourced by Sony Computer Entertainment Inc. under the new BSD license + - added SIMD math library + 4-way SIMD for common math functions like atan2f4, cosf4, floorf4, fabsf4, rsqrtf4 etc. Used by Vector Math library under PPU and SPU. + Supports PowerPC (PPU) and Cell SPU, including PS3 Linux and CellBlade. + See Bullet/Extras/simdmathlibrary + Open sourced by Sony Computer Entertainment Inc. under the new BSD license + + +2007 July 25 + - added several patches: per-rigidbody sleeping threshold. added Assert to prevent deletion of rigidbody while constraints are still pointing at it + Thanks to Marten Svanfeldt (Starbreeze Studios) + +2007 July 13 + - fixed relative #include paths again. We can't use "../" relative paths: some compilers choke on it (it causes extreme long paths) + Within the libraries, we always need to start with "BulletCollision/" or "BulletDynamics/ or "LinearMath/" + +2007 July 10 + - Updated Bullet User Manual + +2007 July 5 + - added btConeTwistConstraint, especially useful for ragdolls. See Demos/RagdollDemo + Thanks to Marten Svanfeldt (Starbreeze Studios) + +2007 June 29 + - btHeightfieldTerrainShape: Added heightfield support, with customizations + - Upgraded to GIMPACT 0.2, see Extras/GIMPACT and MovingConcaveDemo + - Several patches from Marten Svanfeldt (Starbreeze Studios) + Improved collision filtering (in broadphase and rigidbody) + Improved debug rendering + Allow to set collision filter group/mask in addRigidBody + + +2007 June 15 + - Changed btAlignedObjectArray to call copy constructor/replacement new for duplication, rather then assignment operator (operator=). + +2007 June 11 + - Added multi-threading. Originally for Playstation 3 Cell SPU, but the same code can run using Win32 Threads using fake DMA transfers (memcpy) + Libspe2 support for Cell Blade / PS3 Linux is upcoming + See Extras/BulletMultiThreaded. Usage: replace btCollisionDispatcher by btSpuGatheringCollisionDispatcher + + - Added managed Bullet library, entirely rewritten in C# for Windows and XBox 360 XNA + See Extras/BulletX + Thanks to KleMiX, aka Vsevolod Klementjev + +2007 May 31 + - sign-bit went wrong in case of 32-bit broadphase, causing quantization problems. + Thanks DevO for reporting. + +2007 May 23 + - Fixed quantization problem for planar triangle meshes in btOptimizedBvh + Thanks Phil Knight for reporting and helping to fix this bug. + +2007 May 20 + - btAxisSweep3: Fixed a bug in btAxisSweep3 (sweep and prune) related to object removal. Only showed up when at least one btStaticPlaneShape was inserted. + Thanks tbp for more details on reproducing case. + - btAxisSweep3: Fixed issue with full 32bit precision btAxisSweep3 (define BP_USE_FIXEDPOINT_INT_32), it used only 0xffff/65536 for quantization instead of full integer space (0xffffffff) + - btRaycastVehicle: Added 'getForwardVector' and getCurrentSpeedKmHour utility functions + - Fixed local scaling issues (btConvexTriangleMeshShape, btBvhTriangleMeshShape, removed scaling from btMatrix3x3). + Thanks Volker for reporting! + - Added second filename search, so that starting BspDemo and ConvexDecompositionDemo from within Visual Studio (without setting the starting path) still works + +2007 April 22 + - Added braking functionality to btRaycastVehicle + - Removed tons of warnings, under MSVC 2005 compilation in -W4 + +2007 March 21 + - Fixed issues: comma at end of enum causes errors for some compilers + - Fixed initialization bug in LocalRayResult ( m_localShapeInfo(localShapeInfo) ) + +2007 March 20 + - Added refit tree to quantized stackless tree, and updated ConcaveDemo as example. + +2007 March 17 + - Added constraint solver optimizations, avoiding cross products during iterations, and gather rigidbody/constraint info in contiguous memory (btSolverBody/btSolverConstraint) + - These optimizations don't give large benefit yet, but it has good potential. Turned on by default. Can be switched off using solver->setSolverMode(SOLVER_RANDMIZE_ORDER). + - Enabled anti-jitter for rigid bodies. This is experimental, and can be switched off by setting a global (it is experimental so no proper interface) gJitterVelocityDampingFactor = 1.0; + - Fixed bug in islandmanifold.heapSort(btPersistentManifoldSortPredicate()); , thanks Noehrgel for reporting this (affected Sun Solaris) + +2007 March 12 + - Added compile-time toggle between on 16-bit and 32-bit fixed-point SAP broadphase. + This allows the number of bodies to exceed 32767 + - Enable useQuantizedAabbCompression on btTriangleMesh, see ColladaDemo + +2007 March 8 + - Fixed bug in constraint/island sorting (caused by replacing STL by dedicated btAlignedObjectArray with heapSort) + Thanks Clemens Unterkofler for pointing this out! + +2007 March 6 + - removed STL from the Bullet library: replace std::vector by btAlignedObjectArray. Also removed the std::set for overlapping pair set, and turned it into an overlapping pair array. The SAP only adds objects, never removed. Removal is postponed for during traversal of overlapping pairs (duplicates and non-overlapping pairs are removed during that traversal). + - added heap sort and binary search/linear search to btAlignedObjectArray + - fixed wrong cast, thanks Hamstray, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1015 + + +2007 Feb 25 + - Improved performance of convex collision shapes, cache local AABB instead of recomputation. This fixes issue with very slow performance in larger .bsp levels + +2007 Feb 24 + - Added compressed/quantized AABB tree, 16 bytes per node, while supporting 32-bit (triangle) indices. + Should be faster and smaller then original version (quantized aabb check is done in integer space) + Original aabb tree nodes are still supported. They are 44 bytes, with full floating point precision and additional subPart index. + - added meter-unit scaling support in ColladaConverter.cpp + +2007 Feb 21 + - Build system: updated bullet.pc.in library names + - Updated EPA comparison integration (missing parameter) + +2007 Jan 04 + - fixed optimized AABB tree building: in some cases the tree building fails due to unbalanced trees, which generated stack overflow + +2006 Dec 15 + - added contribution to allow double precision collision detection/dynamics. Define BT_USE_DOUBLE_PRECISION in your project and libraries that include Bullet + +2006 Dec 14 + - merged contact and non-contact constraint solving into one loop, will improve stability of jointed bodies during collisions + - added first draft for hingeConstraint motor + +2006 Dec 8, Erwin Coumans + - preparation for SIMD: added btAlignedAllocator and btAlignedObjectArray, to replace stl std::vector, same interface, but compatible with 16 byte alignment + - cleaned up dependencies in autogenerated msvc projectfiles + - aligned btVector3 on 16 bytes boundary, under win32. see if developers will come up with problems + +2006 Dec 04, Erwin Coumans + Added btNearCallback. This is similar to Open Dynamics Engine (ODE) dNearCallback, but important differences: + - contact points are persistent (lifetime more then one frame, for warmstarting/incremental contact point management) + - continuous collision detection, time of impact + Added btRigidBody::isInWorld(), returns true if btRigidBody is inside a btCollisionWorld/btDynamicsWorld derived class + Added angularFactor to btRigidbody, this helps some character control (no angular impulse applied) + + +2006 Nov 28 + Moved StackAlloc from EPA into LinearMath/btStackAlloc + renamed internal class ConcaveShape into btConcaveShape + added btHeightfieldTerrainShape (not completed yet) + +2006 Nov 15 Nathanael Presson + Added EPA penetration depth algorithm, Expanding Polytope Algorithm + Added Pierre Terdiman penetration depth comparison/test DEMO + Fixed Bullet's Minkowski sampling penetration depth solver + Contributed by Nathanael Presson + +2006 Nov 11 Francisco León Nájera + Added GIMPACT trimesh collision detection: concave versus concave, + Contributed by Francisco León Nájera + +2006 Nov 2 + Minor refactoring: btCollisionObject changes from struct into class, added accessor methods + Force use of btMotionState to synchronize graphics transform, disabled old btRigidBody constructor that accepts btTransform + Renamed treshold into threshold throughout the code + +2006 Oct 30 + Enable decoupling of physics and graphics framerate using interpolation and internal fixed timestep, based on btMotionState + Enabled raycast vehicle demo (still needs tuning) + Refresh contact points, even when they are already persistent. + Fixed debugDraw colors (thanks pc0de for reporting) + Use Dispatcher in ConcaveConvexCollisionAlgorithm (so it uses the registered collision algorithm, not hardcoded convexconcave) + Improved performance of constraint solver by precalculating the cross product/impulse arm + Added collision comparison code: ODE box-box, also sphere-triangle + Added safety check into GJK, and an assert for AABB's that are very large + Fixed kinematic support (deriving velocities for animated objects) + Updated comparison/optional quickstep solver in Extras + UserCollisionAlgorithm demonstrates btTriangleMesh usage (easier trimesh compared to index array version) + Removed scaling from btTransform (we only want to deal with rigid transforms) + +2006 Oct 4 + Fixed minor leak in btOptimizeBVH + Cleanup of btRigidBody construction + added getW() in btQuaternion + assert when setLinearVelocity is called on btRigidBody + renamed projectfile library from collada-dom to colladadom (to make VC6 happy) + +2006 Sept 27 + Big Refactoring: renamed and moved files, create a replacement for CcdPhysicsEnvironment/CcdPhysicsController. + All Bullet classes in LinearMath, BulletCollision and BulletDynamics start with bt, and methods start with lowercase. + Moved classes into src folder, which is the only include folder needed. + Added 2 headerfiles in src: btBulletCollisionCommon.h and btBulletDynamicsCommon.h + +2006 Sept 23 + Fixed 2 bugs, causing crashes when removing objects. Should do better unit-testing. UnionFind and 3D SAP were involved. + +2006 Sept 19 + Allow programmable friction and contact solver model. User can register their own functions for several interaction types. + Improved performance, and removed hardcoded maximum overlaps (switched from C-array to stl::set) + +2006 Sept 16 + Added Bullet 2.0 User Manual + Allow registration of custom user collision algorithms + +2006 Sept 10 + Started cleaning up demos + +2006 Sept 4 + Fixed concave collision bug (caused instability/missing collisions in meshes/compounds) + Fixed memoryleak in OptimizedBvh, added RayTestSingle to CollisionWorld + Prepared for VehicleDemo + Increased Performance (island generation for sleeping objects took too much time) + Better COLLADA 1.4.1 physics conformance in ColladaDemo + +2006 August 11 + Added Quake BspDemo + Improved CCD for compound and non-convex objects + +2006 August 10 + Added per-triangle material (friction/restitution) support for non-convex meshes. See ConcaveDemo for usage. + +2006 August 9 + Added CMake support (see http://cmake.org) + This can autogenerate makefiles, projectfiles cross platform (including MacOS X Xcode ) + Just run cmake . in the root folder and it will autogenerate build files + +2006 July 26 Erwin Coumans + Upgraded to COLLADA-DOM 1.4.1, latest SVN version + ColladaDemo can export snapshots to .dae + +2006 July 24 Erwin Coumans + Added Compound CollisionShape support + (this is still low performance -> requires stackless tree-versus-tree traversal for better performance) + +2006 July 15 Erwin Coumans + Added initial support for Parallel execution (collision detection, constraint solving) + See ParallelPhysicsEnvironment in Extras\PhysicsInterface\CcdPhysics + +2006 July 10 Erwin Coumans + Added MacOS X support (some build issues mainly) + +2006 July 5 Erwin Coumans + Improved COLLADA 1.4 physics import, both COLLADA-DOM and FCollada + +2006 June 29 Erwin Coumans + Refactoring of the broadphase + Moved some optional files to Extras: Algebraic ccd and EPA, quickstep + Moved the limits on bodies/overlap to 32k and 65k + +2006 June 25 Erwin Coumans + Added basic Collision Filtering, during broadphase + Allow adding meshes to the TriangleIndexVertexArray, + (input for TriangleMeshShape) + Preparation for CompoundShape + +2006 June 19 Erwin Coumans + Added support for COLLADA Physics Import. + Both jam and Visual Studio can compile ColladaDemo + +2006 June 18 Dirk Gregorius + Started implementing Generic6DOF joint and setup basic interface + + +2006 June 17 Frank Richter + Bumped version in configure.ac to 1.5.6 (assuming that "1.5f" is + the next version released). + Updated files in mk/autoconf and mk/jam with copies from CS; fixes a + GLU detection issue on MinGW. + Set msvc/bullet_ico.ico as the default application icon. + Disabled exceptions for gcc builds. + Applied a patch from Michael D. Adams to fix a warning with gcc. +2006 jUNE 16 Erwin Coumans + Constraints now merge simulation islands. + +2006 May 24 + Improved GJK accuracy, fixed GjkConvexCast issue, thanks to ~MyXa~ for reporting + +2006 May 19 + Added restitution support + Moved out Friction and Dynamics info from ManifoldPoint (removed logical dependency) + Added a void* m_userPersistentData in ManifoldPoint. + Added a ContactDestroyedCallback, to allow user to handle destruction of m_userPersistentData + +2006 May 13 + Fixed some bugs in friction / jacobian calculations. Reported by Dirk Gregorius. Thanks! + +2006 May 9 + Fixed raycasting filtering + Moved repository to SVN at https://svn.sourceforge.net/svnroot/bullet + +2006 April 27 + Moved raycasting to CollisionWorld, to make it more generic + Added basic CCD option in the CcdCollisionDemo + Fixed 'noResponse' mode, for triggering rigidbodies (useful for Artificial Intelligence queries) + Improved Bullet/ODE sample (in Extras) + +2006 April 10 + Separating Axis Test (SAT) convex hull collision detector, contribution by Simon Hobbs + Added SIMD SSE Math classes (for above SAT) + Added Mouse picking in CcdPhysicsDemo + Improved penetration depth estimation in MinkowskiPenetrationDepthSolver, both accuracy and performance + Added Hinge constraint + Added quickprof profiling (see http://sourceforge.net/projects/quickprof ) + +2006 March 21 Frank Richter + Removed VC manifest files. + Removed superfluous "grpplugins" projects. + +2006 March 20 Erwin Coumans + Clamped the acculumated impulse rather then intermediate impulse (within the iteration) + Use the persistent contacts for reusing the impulse + Separated friction and normal solving for better stability + Decreased the default number of iterations of the constraint solver from 10 to 4 + +2006 March 19 Frank Richter + Removed a couple of CSisms from the VC projects. + Fixed VC include & lib paths to go to the Addtional* options + instead the command line arguments. + Added pkgconfig support. + +2006 March 14 Frank Richter + Added support for shipped GLUT on MinGW. + Fixed GLUT support on MinGW. + +2006 March 13 Frank Richter + Bolted on Jam-based build system. + Generated VC project files. + Fixed GCC warnings. + Fixed Linux build issues. + +2006 March 13 +Added 3D Sweep and Prune Broadphase Collision Detection, Contribution from Simon Hobbs. + +2006 March 2 + Minor change in license to ZLib/LibPNG + This makes it legally a bit easier to deploy on Playstation 3 + Prepared for more generic constraints, added ConstraintsDemo + +2006 Feb 23 + Rearranged files and dependencies to allow for easier standalone Collision Detection without Bullet Dynamics. + See Demos/CollisionInterfaceDemo and Extras/ode/ode/test/test_BulletGjk.cpp for examples how to use. + +2005 August 6 + Bullet 0.2 release with demos, sources, doxygen, draft manual + +2005 June 1 + First public release of Bullet + + +... todo: add history + +2003 Initial version (continuous collision detection) diff --git a/Code/Physics/Bullet Source/Doxyfile b/Code/Physics/Bullet Source/Doxyfile new file mode 100644 index 00000000..d483fe4b --- /dev/null +++ b/Code/Physics/Bullet Source/Doxyfile @@ -0,0 +1,780 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + + + + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = "Bullet Collision Detection & Physics Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = src + + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.h *.cpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = YES + +# HHC_LOCATION = "C:\Program Files\HTML Help Workshop\hhc.exe" +HHC_LOCATION = "C:\Program Files (x86)\HTML Help Workshop\hhc.exe" + + +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +#HTML_STYLESHEET = "\\server\exchange\Software Development\Documentation\DoxyGen\doxygen.css" + +CHM_FILE = BulletDocs.chm +HHC_LOCATION = "c:\program files\HTML Help Workshop\hhc.exe" +GENERATE_CHI = YES +BINARY_TOC = YES + +TOC_EXPAND = YES + +SHOW_DIRECTORIES = YES + + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 1 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = src + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = "ATTRIBUTE_ALIGNED128(x)=x" \ + "ATTRIBUTE_ALIGNED16(x)=x" \ + "SIMD_FORCE_INLINE=inline" \ + "VECTORMATH_FORCE_INLINE=inline" \ + "USE_WIN32_THREADING=1"\ + "USE_PTHREADS=1"\ + "_WIN32=1" + + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + + +# delete intermediate dot files? + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_cpx.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_cpx.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/egl_cpx.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_cpx.h diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_defs.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_defs.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/egl_defs.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_defs.h diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_logged.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_logged.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/egl_logged.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_logged.h diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_tokens.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_tokens.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/egl_tokens.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_tokens.h diff --git a/Code/Physics/Glut/EmptyGL/GL/egl_void.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_void.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/egl_void.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_void.h diff --git a/Code/Physics/Glut/EmptyGL/GL/gl.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/gl.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/gl.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/gl.h diff --git a/Code/Physics/Glut/EmptyGL/GL/glu.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glu.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/glu.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/glu.h diff --git a/Code/Physics/Glut/EmptyGL/GL/glut.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glut.h similarity index 100% rename from Code/Physics/Glut/EmptyGL/GL/glut.h rename to Code/Physics/Bullet Source/Glut/EmptyGL/GL/glut.h diff --git a/Code/Physics/Glut/GL/glew.h b/Code/Physics/Bullet Source/Glut/GL/glew.h similarity index 100% rename from Code/Physics/Glut/GL/glew.h rename to Code/Physics/Bullet Source/Glut/GL/glew.h diff --git a/Code/Physics/Glut/GL/glext.h b/Code/Physics/Bullet Source/Glut/GL/glext.h similarity index 100% rename from Code/Physics/Glut/GL/glext.h rename to Code/Physics/Bullet Source/Glut/GL/glext.h diff --git a/Code/Physics/Glut/GL/glut.h b/Code/Physics/Bullet Source/Glut/GL/glut.h similarity index 100% rename from Code/Physics/Glut/GL/glut.h rename to Code/Physics/Bullet Source/Glut/GL/glut.h diff --git a/Code/Physics/Glut/GL/glxew.h b/Code/Physics/Bullet Source/Glut/GL/glxew.h similarity index 100% rename from Code/Physics/Glut/GL/glxew.h rename to Code/Physics/Bullet Source/Glut/GL/glxew.h diff --git a/Code/Physics/Glut/GL/glxext.h b/Code/Physics/Bullet Source/Glut/GL/glxext.h similarity index 100% rename from Code/Physics/Glut/GL/glxext.h rename to Code/Physics/Bullet Source/Glut/GL/glxext.h diff --git a/Code/Physics/Glut/GL/wglew.h b/Code/Physics/Bullet Source/Glut/GL/wglew.h similarity index 100% rename from Code/Physics/Glut/GL/wglew.h rename to Code/Physics/Bullet Source/Glut/GL/wglew.h diff --git a/Code/Physics/Glut/GL/wglext.h b/Code/Physics/Bullet Source/Glut/GL/wglext.h similarity index 100% rename from Code/Physics/Glut/GL/wglext.h rename to Code/Physics/Bullet Source/Glut/GL/wglext.h diff --git a/Code/Physics/Glut/btGlutInclude.h b/Code/Physics/Bullet Source/Glut/btGlutInclude.h similarity index 100% rename from Code/Physics/Glut/btGlutInclude.h rename to Code/Physics/Bullet Source/Glut/btGlutInclude.h diff --git a/Code/Physics/Bullet Source/INSTALL b/Code/Physics/Bullet Source/INSTALL new file mode 100644 index 00000000..0f42fb52 --- /dev/null +++ b/Code/Physics/Bullet Source/INSTALL @@ -0,0 +1,111 @@ +Bullet Collision Detection and Physics Library + +See also http://bulletphysics.org/mediawiki-1.5.8/index.php/Creating_a_project_from_scratch + +** Windows Compilation ** + + Open the Microsoft Visual Studio solution in msvc/20xx/BULLET_PHYSICS.sln + +Alternatively, use CMake to autogenerate a build system for Windows: + + - Download/install CMake from www.cmake.org or package manager + - Use cmake-gui or + - List available build systems by running 'cmake' in the Bullet root folder + - Use cmake-gui + - Create a build system using the -G option for example: + + cmake . -G "Visual Studio 9 2008" or + cmake . -G "Visual Studio 9 2008 Win64" + + +** Linux Compilation ** + + - Download/install CMake from www.cmake.org or package manager + CMake is like autoconf in that it will create build scripts which are then + used for the actual compilation + + - List available build systems by running 'cmake' in the Bullet root folder + - Create a build system using the -G option for example: + + cmake . -G "Unix Makefiles" + + - There are some options for cmake builds: + BUILD_SHARED_LIBS: default 'OFF', set to 'ON' to build .so libraries + BUILD_EXTRAS: default 'ON', compiles additional libraries in 'Extras' + BUILD_DEMOS: default 'ON', compiles applications found in 'Demos' + CMAKE_INSTALL_PREFIX: default '/usr/local', the installation path. + CMAKE_INSTALL_RPATH: if you install outside a standard ld search path, + then you should set this to the installation lib path. + CMAKE_BUILD_TYPE: default 'Release', can include debug symbols with + either 'Debug' or 'RelWithDebInfo'. + Other options may be discovered by 'cmake --help-variable-list' and + 'cmake --help-variable OPTION' + + - Run 'cmake' with desired options of the form -DOPTION=VALUE + By default this will create the usual Makefile build system, but CMake can + also produce Eclipse or KDevelop project files. See 'cmake --help' to see + what "generators" are available in your environment, selected via '-G'. + For example: + cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RelWithDebugInfo + + - Assuming using the default Makefile output from cmake, run 'make' to + build, and then 'make install' if you wish to install. + + +** Mac OS X Compilation ** + + - Download/install CMake from www.cmake.org or package manager + CMake is like autoconf in that it will create build scripts which are then + used for the actual compilation + + - List available build systems by running 'cmake' in the Bullet root folder + - Create a build system using the -G option for example: + + cmake . -G Xcode + cmake . -G "Unix Makefiles" + + - There are some options for cmake builds: + BUILD_SHARED_LIBS: default 'OFF', set to 'ON' to build .dylib libraries + BUILD_EXTRAS: default 'ON', compiles additional libraries in 'Extras' + BUILD_DEMOS: default 'ON', compiles applications found in 'Demos' + CMAKE_INSTALL_PREFIX: default '/usr/local', the installation path. + CMAKE_INSTALL_NAME_DIR: if you install outside a standard ld search + path, then you should set this to the installation lib/framework path. + CMAKE_OSX_ARCHITECTURES: defaults to the native architecture, but can be + set to a semicolon separated list for fat binaries, e.g. ppc;i386;x86_64 + CMAKE_BUILD_TYPE: default 'Release', can include debug symbols with + either 'Debug' or 'RelWithDebInfo'. + + To build framework bundles: + FRAMEWORK: default 'OFF', also requires 'BUILD_SHARED_LIBS' set ON + If both FRAMEWORK and BUILD_SHARED_LIBS are set, will create + OS X style Framework Bundles which can be placed in + linked via the -framework gcc argument or drag into Xcode projects. + (If not framework, then UNIX style 'include' and 'lib' will be produced) + + Other options may be discovered by 'cmake --help-variable-list' and + 'cmake --help-variable OPTION' + + - Run 'cmake' with desired options of the form -DOPTION=VALUE + By default this will create the usual Makefile build system, but CMake can + also produce Eclipse or KDevelop project files. See 'cmake --help' to see + what "generators" are available in your environment, selected via '-G'. + For example: + cmake -DBUILD_SHARED_LIBS=ON -DFRAMEWORK=ON \ + -DCMAKE_INSTALL_PREFIX=/Library/Frameworks \ + -DCMAKE_INSTALL_NAME_DIR=/Library/Frameworks \ + -DCMAKE_OSX_ARCHITECTURES='ppc;i386;x86_64' \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo + + - Assuming using the default Makefile output from cmake, run 'make' to build + and then 'make install'. + + +** Alternative Mac OS X and Linux via autoconf/make ** + - at the command line: + ./autogen.sh + ./configure + make + + +** For more help, visit http://www.bulletphysics.org ** diff --git a/Code/Physics/Bullet Source/Makefile.am b/Code/Physics/Bullet Source/Makefile.am new file mode 100644 index 00000000..a9b97a8e --- /dev/null +++ b/Code/Physics/Bullet Source/Makefile.am @@ -0,0 +1,7 @@ +if CONDITIONAL_BUILD_DEMOS +SUBDIRS=src Extras Demos +else +SUBDIRS=src +endif +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = bullet.pc diff --git a/Code/Physics/Bullet Source/NEWS b/Code/Physics/Bullet Source/NEWS new file mode 100644 index 00000000..dec9f0fd --- /dev/null +++ b/Code/Physics/Bullet Source/NEWS @@ -0,0 +1,5 @@ + +For news, visit the Bullet Physics forums at +http://www.bulletphysics.org and http://bullet.googlecode.com + + diff --git a/Code/Physics/Bullet Source/README b/Code/Physics/Bullet Source/README new file mode 100644 index 00000000..1eda762c --- /dev/null +++ b/Code/Physics/Bullet Source/README @@ -0,0 +1,6 @@ + +Bullet is a 3D Collision Detection and Rigid Body Dynamics Library for games and animation. +Free for commercial use, including Playstation 3, open source under the ZLib License. + +See the Bullet_User_Manual.pdf for more info and visit the Bullet Physics Forum at +http://bulletphysics.org diff --git a/Code/Physics/Bullet Source/RELEASING.TXT b/Code/Physics/Bullet Source/RELEASING.TXT new file mode 100644 index 00000000..49d6ba40 --- /dev/null +++ b/Code/Physics/Bullet Source/RELEASING.TXT @@ -0,0 +1,36 @@ +This document details the steps necessary to package a release of Bullet. + +1) Preparing for release: + +update VERSION in several places (/VERSION file, /CMakeLists.txt, /configure.ac, /src/LinearMath/btScalar.h, /src/LinearMath/btSerializer.h around line 441) +re-generate serialization structures, if they changed (/src/LinearMath/btSerializer.cpp using makesdna) +update ChangeLog with larger/important changes +regenerate MSVC project files using build/vs_all.bat +create a Subversion tag revision in bullet.googlecode.com/svn/tags/bullet- + +2) Generating the release .zip: +Do an SVN export on a Windows machine into the directory: bullet-X.YY +prepare a zip file containing the directory + +3) Generating the release .tar.gz: +Do an SVN export on a Unix machine into the directory: bullet-X.YY +prepare a .tar.gz file containing the directory + +4) Uploading release to google code: + +Google Code Bullet downloads URL: http://code.google.com/p/bullet/downloads/list + +Title of release should follow this guide line: Bullet Physics SDK (revision) + +It is better to upload the .tar.gz before the .zip so that the .zip appears first in the list + +If the release is an Alpha/Beta or RC the tags should be: Type-Source, OpSys-ALL +If the release is a final release the tags should be: Type-Source, OpSys-ALL, Featured + +5) Obsoleting old releases + +Edit the tags on old releases and add the 'Deprecated' tag + +6) Announcing final releases: + +Final release announcements are done here: http://bulletphysics.com/Bullet/phpBB3/viewforum.php?f=18 diff --git a/Code/Physics/Bullet Source/UseBullet.cmake b/Code/Physics/Bullet Source/UseBullet.cmake new file mode 100644 index 00000000..5ed94874 --- /dev/null +++ b/Code/Physics/Bullet Source/UseBullet.cmake @@ -0,0 +1,10 @@ +# -*- cmake -*- +# +# UseBullet.cmake +# + + +add_definitions ( ${BULLET_DEFINITIONS} ) +include_directories ( ${BULLET_INCLUDE_DIRS} ) +link_directories ( ${BULLET_LIBRARY_DIRS} ) + diff --git a/Code/Physics/Bullet Source/VERSION b/Code/Physics/Bullet Source/VERSION new file mode 100644 index 00000000..90c00fa3 --- /dev/null +++ b/Code/Physics/Bullet Source/VERSION @@ -0,0 +1 @@ +2.82 diff --git a/Code/Physics/Bullet Source/acinclude.m4 b/Code/Physics/Bullet Source/acinclude.m4 new file mode 100644 index 00000000..0505895c --- /dev/null +++ b/Code/Physics/Bullet Source/acinclude.m4 @@ -0,0 +1,3054 @@ +# checkbuild.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_SPLIT_TUPLE(TUPLE, OUTPUT-VARIABLES) +# Split a build-tuple into its component parts. A build tuple is +# constructed by CS_CREATE_TUPLE() and is comprised of compiler flags, +# linker flags, and library references. OUTPUT-VARIABLES is a +# comma-delimited list of shell variables which should receive the +# extracted compiler flags, linker flags, and library references, +# respectively. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SPLIT_TUPLE], + [CS_SPLIT([$1], [cs_dummy,$2], [@]) + m4_map([_CS_SPLIT_TUPLE], [$2])]) + +AC_DEFUN([_CS_SPLIT_TUPLE], + [$1=`echo $$1 | sed 'y%@%:@% %'` + ]) + + + +#------------------------------------------------------------------------------ +# CS_CREATE_TUPLE([CFLAGS], [LFLAGS], [LIBS]) +# Construct a build-tuple which is comprised of compiler flags, linker +# flags, and library references. Build tuples are encoded so as to +# preserve whitespace in each component. This makes it possible for +# macros (such as CS_BUILD_IFELSE) which employ build tuples to accept +# whitespace-delimited lists of tuples, and for shell "for" statements to +# iterate over tuple lists without compromising whitespace embedded +# within individual flags or library references. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CREATE_TUPLE], [`echo @$1@$2@$3 | sed 'y% %@%:@%'`]) + + + +#------------------------------------------------------------------------------ +# CS_LANG_CFLAGS +# Return the literal string CFLAGS if the current language is C. Return +# the literal string CXXFLAGS if the current language is C++. Generic +# compiler test macros which need to modify or save the compiler flags +# can invoke this macro to get the name of the compiler flags environment +# variable (either CFLAGS or CXXFLAGS) depending upon the current +# language. For example: +# CS_LANG_CFLAGS="$CS_LANG_CFLAGS -Wall" +# With C, this expands to: +# CFLAGS="$CFLAGS -Wall" +# With C++, it expands to: +# CXXFLAGS="$CXXFLAGS -Wall" +#------------------------------------------------------------------------------ +AC_DEFUN([CS_LANG_CFLAGS], [AC_LANG_CASE([C], [CFLAGS], [C++], [CXXFLAGS])]) + + + +#------------------------------------------------------------------------------ +# CS_BUILD_IFELSE([PROGRAM], [FLAGS], [LANGUAGE], [ACTION-IF-BUILT], +# [ACTION-IF-NOT-BUILT], [OTHER-CFLAGS], [OTHER-LFLAGS], +# [OTHER-LIBS], [INHIBIT-OTHER-FLAGS], [ERROR-REGEX]) +# Try building a program using the supplied compiler flags, linker flags, +# and library references. PROGRAM is typically a program composed via +# AC_LANG_PROGRAM(). PROGRAM may be omitted if you are interested only +# in learning if the compiler or linker respects certain flags. LANGUAGE +# is typically either C or C++ and specifies which compiler to use for +# the test. If LANGUAGE is omitted, C is used. FLAGS is a whitespace +# delimited list of build tuples. Tuples are created with +# CS_CREATE_TUPLE() and are composed of up to three elements each. The +# first element represents compiler flags, the second linker flags, and +# the third libraries used when linking the program. Each tuple from +# FLAGS is attempted in order. If you want a build attempted with no +# special flags prior to builds with specialized flags, create an empty +# tuple with CS_CREATE_TUPLE() at the start of the FLAGS list. If the +# build is successful, then the shell variables cs_build_ok is set to +# "yes", cs_build_cflags, cs_build_lflags, and cs_build_libs are set to +# the tuple elements which resulted in the successful build, and +# ACTION-IF-BUILT is invoked. Upon successful build, no further tuples +# are consulted. If no tuple results in a successful build, then +# cs_build_ok is set to "no" and ACTION-IF-NOT-BUILT is invoked. +# OTHER-CFLAGS, OTHER-LFLAGS, and OTHER-LIBS specify additional compiler +# flags, linker flags, and libraries which should be used with each tuple +# build attempt. Upon successful build, these additional flags are also +# reflected in the variables cs_build_cflags, cs_build_lflags, and +# cs_build_libs unless INHIBIT-OTHER-FLAGS is a non-empty string. The +# optional ERROR-REGEX places an additional constraint upon the build +# check. If specified, ERROR-REGEX, which is a standard `grep' regular +# expression, is applied to output captured from the compiler and linker. +# If ERROR-REGEX matches, then the build is deemed a failure, and +# cs_build_ok is set to "no". This facility is useful for broken build +# tools which emit an error message yet still return success as a result. +# In such cases, it should be possible to detect the failure by scanning +# the tools' output. +# +# IMPLEMENTATION NOTES +# +# In Autoconf 2.57 and earlier, AC_LINK_IFELSE() invokes AC_TRY_EVAL(), +# which does not provide access to the captured output. To work around +# this limitation, we temporarily re-define AC_TRY_EVAL() as +# _AC_EVAL_STDERR(), which leaves the captured output in conftest.err +# (which we must also delete). In Autoconf 2.58, however, +# AC_LINK_IFELSE() instead already invokes _AC_EVAL_STDERR() on our +# behalf, however we must be careful to apply ERROR-REGEX within the +# invocation AC_LINK_IFELSE(), since AC_LINK_IFELSE() deletes +# conftest.err before it returns. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_BUILD_IFELSE], + [AC_LANG_PUSH(m4_default([$3],[C])) + cs_cflags_save="$CS_LANG_CFLAGS" + cs_lflags_save="$LDFLAGS" + cs_libs_save="$LIBS" + cs_build_ok=no + m4_ifval([$10], [m4_pushdef([AC_TRY_EVAL], [_AC_EVAL_STDERR]($$[1]))]) + + for cs_build_item in m4_default([$2],[CS_CREATE_TUPLE()]) + do + CS_SPLIT_TUPLE( + [$cs_build_item],[cs_cflags_test,cs_lflags_test,cs_libs_test]) + CS_LANG_CFLAGS="$cs_cflags_test $6 $cs_cflags_save" + LDFLAGS="$cs_lflags_test $7 $cs_lflags_save" + LIBS="$cs_libs_test $8 $cs_libs_save" + AC_LINK_IFELSE(m4_default([$1], [AC_LANG_PROGRAM([],[])]), + [m4_ifval([$10], + [AS_IF([AC_TRY_COMMAND( + [grep "AS_ESCAPE([$10])" conftest.err >/dev/null 2>&1])], + [cs_build_ok=no], [cs_build_ok=yes])], + [cs_build_ok=yes])]) + AS_IF([test $cs_build_ok = yes], [break]) + done + + m4_ifval([$10], [m4_popdef([AC_TRY_EVAL]) rm -f conftest.err]) + CS_LANG_CFLAGS=$cs_cflags_save + LDFLAGS=$cs_lflags_save + LIBS=$cs_libs_save + AC_LANG_POP(m4_default([$3],[C])) + + AS_IF([test $cs_build_ok = yes], + [cs_build_cflags=CS_TRIM([$cs_cflags_test[]m4_ifval([$9],[],[ $6])]) + cs_build_lflags=CS_TRIM([$cs_lflags_test[]m4_ifval([$9],[],[ $7])]) + cs_build_libs=CS_TRIM([$cs_libs_test[]m4_ifval([$9],[],[ $8])]) + $4], + [$5])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_BUILD(MESSAGE, CACHE-VAR, [PROGRAM], [FLAGS], [LANGUAGE], +# [ACTION-IF-BUILT], [ACTION-IF-NOT-BUILT], [IGNORE-CACHE], +# [OTHER-CFLAGS], [OTHER-LFLAGS], [OTHER-LIBS], +# [INHIBIT-OTHER-FLAGS], [ERROR-REGEX]) +# Like CS_BUILD_IFELSE() but also prints "checking" and result messages, +# and optionally respects the cache. Sets CACHE-VAR to "yes" upon +# success, else "no" upon failure. Additionally, sets CACHE-VAR_cflags, +# CACHE-VAR_lflags, and CACHE-VAR_libs to the values which resulted in a +# successful build. If IGNORE-CACHE is "yes", then the cache variables +# are ignored upon entry to this macro, however they are still set to +# appropriate values upon exit. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_BUILD], + [AS_IF([test "$8" != yes], + [AC_CACHE_CHECK([$1], [$2], + [CS_BUILD_IFELSE([$3], [$4], [$5], + [$2=yes + $2_cflags=$cs_build_cflags + $2_lflags=$cs_build_lflags + $2_libs=$cs_build_libs], + [$2=no], [$9], [$10], [$11], [$12], [$13])])], + [AC_MSG_CHECKING([$1]) + CS_BUILD_IFELSE([$3], [$4], [$5], + [$2=yes + $2_cflags=$cs_build_cflags + $2_lflags=$cs_build_lflags + $2_libs=$cs_build_libs], + [$2=no], [$9], [$10], [$11], [$12], [$13]) + AC_MSG_RESULT([$$2])]) + AS_IF([test $$2 = yes], [$6], + [$2_cflags='' + $2_lflags='' + $2_libs='' + $7])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_BUILD_FLAGS(MESSAGE, CACHE-VAR, FLAGS, [LANGUAGE], +# [ACTION-IF-RECOGNIZED], [ACTION-IF-NOT-RECOGNIZED], +# [OTHER-CFLAGS], [OTHER-LFLAGS], [OTHER-LIBS], +# [ERROR-REGEX]) +# Like CS_CHECK_BUILD(), but checks only if the compiler or linker +# recognizes a command-line option or options. MESSAGE is the "checking" +# message. CACHE-VAR is the shell cache variable which receives the flag +# or flags recognized by the compiler or linker. FLAGS is a +# whitespace-delimited list of build tuples created with +# CS_CREATE_TUPLE(). Each tuple from FLAGS is attempted in order until +# one is found which is recognized by the compiler. After that, no +# further flags are checked. LANGUAGE is typically either C or C++ and +# specifies which compiler to use for the test. If LANGUAGE is omitted, +# C is used. If a command-line option is recognized, then CACHE-VAR is +# set to the composite value of $cs_build_cflags, $cs_build_lflags, and +# $cs_build_libs of the FLAGS element which succeeded (not including the +# "other" flags) and ACTION-IF-RECOGNIZED is invoked. If no options are +# recognized, then CACHE-VAR is set to the empty string, and +# ACTION-IF-NOT-RECOGNIZED is invoked. As a convenience, in case +# comparing CACHE-VAR against the empty string to test for failure is +# undesirable, a second variable named CACHE-VAR_ok is set to the literal +# "no" upon failure, and to the same value as CACHE-VAR upon success. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_BUILD_FLAGS], + [AC_CACHE_CHECK([$1], [$2_ok], + [CS_BUILD_IFELSE([], [$3], [$4], + [$2=CS_TRIM([$cs_build_cflags $cs_build_lflags $cs_build_libs]) + $2_ok="$$2"], + [$2='' + $2_ok=no], [$7], [$8], [$9], [Y], [$10])]) + AS_IF([test "$$2_ok" != no], [$5], [$6])]) +#============================================================================== +# Copyright (C)2003-2006 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_LINK +# Checks for common tools related to linking. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_LINK], + [ + # The default RANLIB in Jambase is wrong on some platforms, and is also + # unsuitable during cross-compilation, so we set the value unconditionally + # (sixth argument of CS_EMIT_BUILD_PROPERTY). + AC_PROG_RANLIB + CS_EMIT_BUILD_PROPERTY([RANLIB], [$RANLIB], [], [], [], [Y]) + + CS_CHECK_TOOLS([DLLTOOL], [dlltool]) + CS_EMIT_BUILD_PROPERTY([CMD.DLLTOOL], [$DLLTOOL]) + + CS_CHECK_TOOLS([DLLWRAP], [dllwrap]) + CS_EMIT_BUILD_PROPERTY([CMD.DLLWRAP], [$DLLWRAP]) + + CS_CHECK_TOOLS([WINDRES], [windres]) + CS_EMIT_BUILD_PROPERTY([CMD.WINDRES], [$WINDRES]) + + CS_CHECK_TOOLS([STRINGS], [strings]) + CS_EMIT_BUILD_PROPERTY([CMD.STRINGS], [$STRINGS]) + + CS_CHECK_TOOLS([OBJCOPY], [objcopy]) + CS_EMIT_BUILD_PROPERTY([CMD.OBJCOPY], [$OBJCOPY]) + + CS_CHECK_LIBTOOL + CS_EMIT_BUILD_PROPERTY([LIBTOOL], [$LIBTOOL]) + CS_EMIT_BUILD_PROPERTY([APPLE_LIBTOOL], [$APPLE_LIBTOOL]) + ]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_BASIC +# Checks for basic tools for building things. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_BASIC], + [CS_CHECK_MKDIR + CS_EMIT_BUILD_PROPERTY([CMD.MKDIR], [$MKDIR]) + CS_EMIT_BUILD_PROPERTY([CMD.MKDIRS], [$MKDIRS]) + + CS_CHECK_PROGS([INSTALL], [install]) + CS_EMIT_BUILD_PROPERTY([INSTALL], [$INSTALL])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_DOC_TEXINFO +# Checks for tools to generate documentation from texinfo files. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_DOC_TEXINFO], + [CS_CHECK_PROGS([TEXI2DVI], [texi2dvi]) + CS_EMIT_BUILD_PROPERTY([CMD.TEXI2DVI], [$TEXI2DVI]) + + CS_CHECK_PROGS([TEXI2PDF], [texi2pdf]) + CS_EMIT_BUILD_PROPERTY([CMD.TEXI2PDF], [$TEXI2PDF]) + + CS_CHECK_PROGS([DVIPS], [dvips]) + CS_EMIT_BUILD_PROPERTY([CMD.DVIPS], [$DVIPS]) + + CS_CHECK_PROGS([DVIPDF], [dvipdf]) + CS_EMIT_BUILD_PROPERTY([CMD.DVIPDF], [$DVIPDF]) + + CS_CHECK_PROGS([MAKEINFO], [makeinfo]) + CS_EMIT_BUILD_PROPERTY([CMD.MAKEINFO], [$MAKEINFO])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_TOOLS_DOC_DOXYGEN +# Checks for tools to generate source documentation via doxygen. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_TOOLS_DOC_DOXYGEN], + [CS_CHECK_PROGS([DOXYGEN], [doxygen]) + CS_EMIT_BUILD_PROPERTY([CMD.DOXYGEN], [$DOXYGEN]) + + CS_CHECK_TOOLS([DOT], [dot]) + CS_EMIT_BUILD_PROPERTY([CMD.DOT], [$DOT])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_COMMON_LIBS +# Check for typical required libraries (libm, libmx, libdl, libnsl). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_COMMON_LIBS], + [AC_LANG_PUSH([C]) + AC_CHECK_LIB([m], [pow], [cs_cv_libm_libs=-lm], [cs_cv_libm_libs=]) + AC_CHECK_LIB([m], [cosf], [cs_cv_libm_libs=-lm]) + AC_CHECK_LIB([mx], [cosf]) + AC_CHECK_LIB([dl], [dlopen], [cs_cv_libdl_libs=-ldl], [cs_cv_libdl_libs=]) + AC_CHECK_LIB([nsl], [gethostbyname]) + AC_LANG_POP([C])]) +# checkcppunit.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_CPPUNIT([EMITTER]) +# Check if CppUnit (http://cppunit.sourceforge.net/), the unit-testing +# framework is available. The shell variable cs_cv_libcppunit is set to +# "yes" if CppUnit is discovered, else "no". If available, then the +# variables cs_cv_libcppunit_cflags, cs_cv_libcppunit_lflags, and +# cs_cv_libcppunit_libs are set. If EMITTER is provided, then +# CS_EMIT_BUILD_RESULT() is invoked with EMITTER in order to record the +# results in an output file. As a convenience, if EMITTER is the literal +# value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s default emitter +# will be used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_CPPUNIT], + [CS_CHECK_LIB_WITH([cppunit], + [AC_LANG_PROGRAM([[#include ]], + [CppUnit::TextUi::TestRunner r; r.run();])], + [], [C++]) + + AS_IF([test $cs_cv_libcppunit = yes], + [CS_CHECK_BUILD([if cppunit is sufficiently recent], + [cs_cv_libcppunit_recent], + [AC_LANG_PROGRAM( + [[#include ]], + [CppUnit::BriefTestProgressListener b; b.startTest(0);])], + [], [C++], + [CS_EMIT_BUILD_RESULT([cs_cv_libcppunit], [CPPUNIT], + CS_EMITTER_OPTIONAL([$1]))], [], [], + [$cs_cv_libcppunit_cflags], + [$cs_cv_libcppunit_lflags], + [$cs_cv_libcppunit_libs])])]) +# checklib.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003-2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# cs_lib_paths_default +# Whitespace delimited list of directory tuples in which to search, by +# default, for external libraries. Each list item can specify an +# include|library directory tuple (for example, "/usr/include|/usr/lib"), +# or a single directory (for example, "/usr"). If the second form is +# used, then "include" and "lib" subdirectories of the directory are +# searched. If the library resources are not found, then the directory +# itself is searched. Thus, "/proj" is shorthand for +# "/proj/include|/proj/lib /proj|/proj". +# +# Present Cases: +# /usr/local -- Not all compilers search here by default, so we specify +# it manually. +# /sw -- Fink, the MacOS/X manager of Unix packages, installs here by +# default. +# /opt/local -- DarwinPorts installs here by default. +#------------------------------------------------------------------------------ +m4_define([cs_lib_paths_default], + [/usr/local/include|/usr/local/lib \ + /sw/include|/sw/lib \ + /opt/local/include|/opt/local/lib \ + /opt/include|/opt/lib]) + + + +#------------------------------------------------------------------------------ +# cs_pkg_paths_default +# Comma delimited list of additional directories in which the +# `pkg-config' command should search for its `.pc' files. +# +# Present Cases: +# /usr/local/lib/pkgconfig -- Although a common location for .pc files +# installed by "make install", many `pkg-config' commands neglect +# to search here automatically. +# /sw/lib/pkgconfig -- Fink, the MacOS/X manager of Unix packages, +# installs .pc files here by default. +# /opt/local/lib/pkgconfig -- DarwinPorts installs .pc files here by +# default. +#------------------------------------------------------------------------------ +m4_define([cs_pkg_paths_default], + [/usr/local/lib/pkgconfig, + /sw/lib/pkgconfig, + /opt/local/lib/pkgconfig, + /opt/lib/pkgconfig]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_LIB_WITH(LIBRARY, PROGRAM, [SEARCH-LIST], [LANGUAGE], +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], [OTHER-CFLAGS], +# [OTHER-LFLAGS], [OTHER-LIBS], [ALIASES]) +# Very roughly similar in concept to AC_CHECK_LIB(), but allows caller to +# to provide list of directories in which to search for LIBRARY; allows +# user to override library location via --with-LIBRARY=dir; and consults +# `pkg-config' (if present) and `LIBRARY-config' (if present, i.e. +# `sdl-config') in order to obtain compiler and linker flags. LIBRARY is +# the name of the library or MacOS/X framework which is to be located +# (for example, "readline" for `libreadline.a' or `readline.framework'). +# PROGRAM, which is typically composed with AC_LANG_PROGRAM(), is a +# program which references at least one function or symbol in LIBRARY. +# SEARCH-LIST is a whitespace-delimited list of paths in which to search +# for the library and its header files, in addition to those searched by +# the compiler and linker by default, and those referenced by the +# cs_lib_paths_default macro. Each list item can specify an +# `include|library' directory tuple (for example, +# "/usr/include|/usr/lib"), or a single directory (for example, "/usr"). +# If the second form is used, then "include" and "lib" subdirectories of +# the directory are searched. If the library resources are not found, +# then the directory itself is searched. Thus, "/proj" is shorthand for +# "/proj/include|/proj/lib /proj|/proj". Items in the search list can +# include wildcards. SEARCH-LIST can be overridden by the user with the +# --with-LIBRARY=dir option, in which case only "dir/include|dir/lib" and +# "dir|dir" are searched. If SEARCH-LIST is omitted and the user did not +# override the search list via --with-LIBRARY=dir, then only the +# directories normally searched by the compiler and the directories +# mentioned via cs_lib_paths_default are searched. LANGUAGE is typically +# either C or C++ and specifies which compiler to use for the test. If +# LANGUAGE is omitted, C is used. OTHER-CFLAGS, OTHER-LFLAGS, and +# OTHER-LIBS can specify additional compiler flags, linker flags, and +# libraries needed to successfully link with LIBRARY. The optional +# ALIASES is a comma-delimited list of library names for which to search +# in case LIBRARY is not located (for example "[sdl1.2, sdl12]" for +# libsdl1.2.a, sdl1.2.framework, libsdl12.a, and sdl12.framework). If +# the library or one of its aliases is found and can be successfully +# linked into a program, then the shell cache variable cs_cv_libLIBRARY +# is set to "yes"; cs_cv_libLIBRARY_cflags, cs_cv_libLIBRARY_lflags, and +# cs_cv_libLIBRARY_libs are set, respectively, to the compiler flags +# (including OTHER-CFLAGS), linker flags (including OTHER-LFLAGS), and +# library references (including OTHER-LIBS) which resulted in a +# successful build; and ACTION-IF-FOUND is invoked. If the library was +# not found or was unlinkable, or if the user disabled the library via +# --without-LIBRARY, then cs_cv_libLIBRARY is set to "no" and +# ACTION-IF-NOT-FOUND is invoked. Note that the exported shell variable +# names are always composed from LIBRARY regardless of whether the test +# succeeded because the primary library was discovered or one of the +# aliases. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_LIB_WITH], + [AC_ARG_WITH([$1], [AC_HELP_STRING([--with-$1=dir], + [specify location of lib$1 if not detected automatically; searches + dir/include, dir/lib, and dir])]) + + # Backward compatibility: Recognize --with-lib$1 as alias for --with-$1. + AS_IF([test -n "$with_lib$1" && test -z "$with_$1"], + [with_$1="$with_lib$1"]) + + AS_IF([test -z "$with_$1"], [with_$1=yes]) + AS_IF([test "$with_$1" != no], + [# If --with-$1 value is same as cached value, then assume other + # cached values are also valid; otherwise, ignore all cached values. + AS_IF([test "$with_$1" != "$cs_cv_with_$1"], + [cs_ignore_cache=yes], [cs_ignore_cache=no]) + + cs_check_lib_flags='' + AS_IF([test $with_$1 = yes], + [m4_foreach([cs_check_lib_alias], [$1, $10], + [_CS_CHECK_LIB_PKG_CONFIG_FLAGS([cs_check_lib_flags], + cs_check_lib_alias) + _CS_CHECK_LIB_CONFIG_FLAGS([cs_check_lib_flags], + cs_check_lib_alias) + ])]) + + AS_IF([test $with_$1 != yes], + [cs_check_lib_paths=$with_$1], + [cs_check_lib_paths="| cs_lib_paths_default $3"]) + m4_foreach([cs_check_lib_alias], [$1, $10], + [_CS_CHECK_LIB_CREATE_FLAGS([cs_check_lib_flags], + cs_check_lib_alias, [$cs_check_lib_paths]) + ]) + + CS_CHECK_BUILD([for lib$1], [cs_cv_lib$1], [$2], [$cs_check_lib_flags], + [$4], [], [], [$cs_ignore_cache], [$7], [$8], [$9])], + [cs_cv_lib$1=no]) + + cs_cv_with_$1="$with_$1" + AS_IF([test "$cs_cv_lib$1" = yes], [$5], [$6])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_PKG_CONFIG +# Check if the `pkg-config' command is available and reasonably recent. +# This program acts as a central repository of build flags for various +# packages. For example, to determine the compiler flags for FreeType2 +# use, "pkg-config --cflags freetype2"; and "pkg-config --libs freetype2" +# to determine the linker flags. If `pkg-config' is found and is +# sufficiently recent, PKG_CONFIG is set and AC_SUBST() invoked. +#------------------------------------------------------------------------------ +m4_define([CS_PKG_CONFIG_MIN], [0.9.0]) +AC_DEFUN([CS_CHECK_PKG_CONFIG], + [AS_IF([test "$cs_prog_pkg_config_checked" != yes], + [CS_CHECK_TOOLS([PKG_CONFIG], [pkg-config]) + _CS_CHECK_PKG_CONFIG_PREPARE_PATH + cs_prog_pkg_config_checked=yes]) + AS_IF([test -z "$cs_cv_prog_pkg_config_ok"], + [AS_IF([test -n "$PKG_CONFIG"], + [AS_IF([$PKG_CONFIG --atleast-pkgconfig-version=CS_PKG_CONFIG_MIN], + [cs_cv_prog_pkg_config_ok=yes], + [cs_cv_prog_pkg_config_ok=no])], + [cs_cv_prog_pkg_config_ok=no])])]) + +AC_DEFUN([_CS_CHECK_PKG_CONFIG_PREPARE_PATH], + [PKG_CONFIG_PATH="m4_foreach([cs_pkg_path], [cs_pkg_paths_default], + [cs_pkg_path$PATH_SEPARATOR])$PKG_CONFIG_PATH" + export PKG_CONFIG_PATH]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_PKG_CONFIG_FLAGS(VARIABLE, LIBRARY) +# Helper macro for CS_CHECK_LIB_WITH(). Checks if `pkg-config' knows +# about LIBRARY and, if so, appends a build tuple consisting of the +# compiler and linker flags reported by `pkg-config' to the list of +# tuples stored in the shell variable VARIABLE. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_PKG_CONFIG_FLAGS], + [CS_CHECK_PKG_CONFIG + AS_IF([test $cs_cv_prog_pkg_config_ok = yes], + [AC_CACHE_CHECK([if $PKG_CONFIG recognizes $2], [_CS_CLPCF_CVAR([$2])], + [AS_IF([$PKG_CONFIG --exists $2], + [_CS_CLPCF_CVAR([$2])=yes], [_CS_CLPCF_CVAR([$2])=no])]) + AS_IF([test $_CS_CLPCF_CVAR([$2]) = yes], + [_CS_CHECK_LIB_CONFIG_PROG_FLAGS([$1], [pkg_config_$2], + [$PKG_CONFIG], [$2])])])]) + +AC_DEFUN([_CS_CLPCF_CVAR], [AS_TR_SH([cs_cv_prog_pkg_config_$1])]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CONFIG_FLAGS(VARIABLE, LIBRARY) +# Helper macro for CS_CHECK_LIB_WITH(). Checks if `LIBRARY-config' +# (i.e. `sdl-config') exists and, if so, appends a build tuple consisting +# of the compiler and linker flags reported by `LIBRARY-config' to the +# list of tuples stored in the shell variable VARIABLE. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CONFIG_FLAGS], + [CS_CHECK_TOOLS(_CS_CLCF_SHVAR([$2]), [$2-config]) + AS_IF([test -n "$_CS_CLCF_SHVAR([$2])"], + [AS_IF([test -z "$_CS_CLCF_CVAR([$2])"], + [AS_IF([$_CS_CLCF_SHVAR([$2]) --cflags --libs >/dev/null 2>&1], + [_CS_CLCF_CVAR([$2])=yes], [_CS_CLCF_CVAR([$2])=no])]) + AS_IF([test $_CS_CLCF_CVAR([$2]) = yes], + [_CS_CHECK_LIB_CONFIG_PROG_FLAGS([$1], [config_$2], + [$_CS_CLCF_SHVAR([$2])])])])]) + +AC_DEFUN([_CS_CLCF_CVAR], [AS_TR_SH([cs_cv_prog_config_$1_ok])]) +AC_DEFUN([_CS_CLCF_SHVAR], [m4_toupper(AS_TR_SH([CONFIG_$1]))]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CONFIG_PROG_FLAGS(VARIABLE, TAG, CONFIG-PROGRAM, [ARGS]) +# Helper macro for _CS_CHECK_LIB_PKG_CONFIG_FLAGS() and +# _CS_CHECK_LIB_CONFIG_FLAGS(). CONFIG-PROGRAM is a command which +# responds to the --cflags and --libs options and returns suitable +# compiler and linker flags for some package. ARGS, if supplied, is +# passed to CONFIG-PROGRAM after the --cflags or --libs argument. The +# results of the --cflags and --libs options are packed into a build +# tuple and appended to the list of tuples stored in the shell variable +# VARIABLE. TAG is used to compose the name of the cache variable. A good +# choice for TAG is some unique combination of the library name and +# configuration program. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CONFIG_PROG_FLAGS], + [AS_IF([test -z "$_CS_CLCPF_CVAR([$2])"], + [cs_check_lib_cflag=CS_RUN_PATH_NORMALIZE([$3 --cflags $4]) + cs_check_lib_lflag='' + cs_check_lib_libs=CS_RUN_PATH_NORMALIZE([$3 --libs $4]) + _CS_CLCPF_CVAR([$2])=CS_CREATE_TUPLE( + [$cs_check_lib_cflag], + [$cs_check_lib_lflag], + [$cs_check_lib_libs])]) + $1="$$1 $_CS_CLCPF_CVAR([$2])"]) + +AC_DEFUN([_CS_CLCPF_CVAR], [AS_TR_SH([cs_cv_prog_$1_flags])]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CREATE_FLAGS(VARIABLE, LIBRARY, PATHS) +# Helper macro for CS_CHECK_LIB_WITH(). Constructs a list of build +# tuples suitable for CS_CHECK_BUILD() and appends the tuple list to the +# shell variable VARIABLE. LIBRARY and PATHS have the same meanings as +# the like-named arguments of CS_CHECK_LIB_WITH(). +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CREATE_FLAGS], + [for cs_lib_item in $3 + do + case $cs_lib_item in + *\|*) CS_SPLIT( + [$cs_lib_item], [cs_check_incdir,cs_check_libdir], [|]) + _CS_CHECK_LIB_CREATE_FLAG([$1], + [$cs_check_incdir], [$cs_check_libdir], [$2]) + ;; + *) _CS_CHECK_LIB_CREATE_FLAG([$1], + [$cs_lib_item/include], [$cs_lib_item/lib], [$2]) + _CS_CHECK_LIB_CREATE_FLAG( + [$1], [$cs_lib_item], [$cs_lib_item], [$2]) + ;; + esac + done]) + + + +#------------------------------------------------------------------------------ +# _CS_CHECK_LIB_CREATE_FLAG(VARIABLE, HEADER-DIR, LIBRARY-DIR, LIBRARY) +# Helper macro for _CS_CHECK_LIB_CREATE_FLAGS(). Constructs build tuples +# suitable for CS_CHECK_BUILD() for given header and library directories, +# and appends the tuples to the shell variable VARIABLE. Synthesizes +# tuples which check for LIBRARY as a MacOS/X framework, and a standard +# link library. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_CHECK_LIB_CREATE_FLAG], + [AS_IF([test -n "$2"], [cs_check_lib_cflag="-I$2"], [cs_check_lib_cflag='']) + AS_IF([test -n "$3"], [cs_check_lib_lflag="-L$3"], [cs_check_lib_lflag='']) + AS_IF([test -n "$4"], + [cs_check_lib_libs="-l$4" + cs_check_lib_framework="-framework $4"], + [cs_check_lib_libs='' + cs_check_lib_framework='']) + $1="$$1 + CS_CREATE_TUPLE( + [$cs_check_lib_cflag], + [$cs_check_lib_lflag], + [$cs_check_lib_framework]) + CS_CREATE_TUPLE( + [$cs_check_lib_cflag], + [$cs_check_lib_lflag], + [$cs_check_lib_libs])"]) +# checklibtool.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_LIBTOOL +# Find and identify the various implementations of libtool. In +# particular, this macro is aware of GNU libtool and Apple's libtool +# (which serves a completely different purpose). On MacOS/X, GNU libtool +# is typically named glibtool, however a user might also use Fink to +# install the unadorned libtool; and the Fink-installed version might +# shadow Apple's own libtool if it appears in the PATH before the Apple +# tool. This macro jumps through the necessary hoops to distinguish and +# locate the various implementations. Sets the shell variable LIBTOOL to +# the located GNU libtool (if any), and APPLE_LIBTOOL to the located +# Apple libtool. Invokes AC_SUBST() for LIBTOOL and APPLE_LIBTOOL. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_LIBTOOL], +[# GNU: Search for libtool before glibtool since Fink version is likely newer. +m4_define([cs_lt_path_gnu], + [/sw/bin$PATH_SEPARATOR/usr/local/bin$PATH_SEPARATOR$PATH]) +AS_IF([test -z "$LIBTOOL"], + [CS_CHECK_TOOLS([LIBTOOL_TEST], [libtool glibtool gnulibtool], [], + [cs_lt_path_gnu]) + AS_IF([test -n "$LIBTOOL_TEST"], + [CS_PATH_PROG([LIBTOOL_PATH], [$LIBTOOL_TEST], [], [cs_lt_path_gnu]) + CS_LIBTOOL_CLASSIFY([$LIBTOOL_PATH], + [LIBTOOL="$LIBTOOL_PATH"], + [AS_IF([test -z "$APPLE_LIBTOOL"], [APPLE_LIBTOOL="$LIBTOOL_PATH"]) + CS_CHECK_TOOLS([LIBTOOL], [glibtool gnulibtool])])])]) +AC_SUBST([LIBTOOL]) + +# Apple: Ensure that Apple libtool will be found before GNU libtool from Fink. +m4_define([cs_lt_path_apple],[/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH]) +AS_IF([test -z "$APPLE_LIBTOOL"], + [CS_PATH_PROG([CS_LT_APPLE], [libtool], [], [cs_lt_path_apple]) + CS_LIBTOOL_CLASSIFY([$CS_LT_APPLE], [], + [APPLE_LIBTOOL="$CS_LT_APPLE"])]) +AC_SUBST([APPLE_LIBTOOL])]) + +AC_DEFUN([CS_LIBTOOL_CLASSIFY], + [AS_IF([test -n "$1"], + [AC_MSG_CHECKING([classification of $1]) + CS_LIBTOOL_GNU_IFELSE([$1], + [AC_MSG_RESULT([gnu]) + $2], + [AC_MSG_RESULT([apple]) + $3])])]) + +AC_DEFUN([CS_LIBTOOL_GNU_IFELSE], + [AS_IF([AC_RUN_LOG([$1 --version 1>&2])], [$2], [$3])]) +#============================================================================== +# Copyright (C)2003-2006 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_OPENGL +# Check for OpenGL. +# +# IMPLEMENTATION NOTES +# +# Some Mesa installations require pthread, so pthread flags are employed if +# available. +# +# The check for opengl32 needs to precede other checks because Cygwin users +# often have Mesa installed, and Mesa's OpenGL library is compiled without the +# __stdcall flags which results in link errors, whereas Microsoft's native +# opengl32 works fine. Conversely, some Unix implementations have Wine +# installed (Windows emulation layer) which includes an opengl32.so library. +# We need to avoid detection of this library on Unix since it would cause an +# undesirable dependence upon Wine. +# +# Many OpenGL libraries on Unix already contain GLX, so there is no separate +# GLX library, thus we first check for GLX using the discovered OpenGL library +# before attempting to locate a separate GLX-specific library. +# +# On MacOS/X, some users have XFree86 installed which creates a link from +# /usr/include/GL to /usr/X11R6/include/GL. We want to ignore this directory +# and instead check for Apple's OpenGL.framework, if we are not cross-building +# for Darwin. We accomplish this by placing the OpenGL.framework test ahead of +# the other tests. +# +# At least one user (Jorrit) has a strange installation in which inclusion of +# fails if an int32 is not present, thus we must take this into +# account. +#------------------------------------------------------------------------------ +m4_define([cs_define_int32], + [[#if !HAVE_TYPE_INT32 + typedef long int32; + #endif + ]]) + +# CS_GL_INCLUDE(CPP-MACRO,FALLBACK,HEADER) +AC_DEFUN([CS_GL_INCLUDE], + [[#if HAVE_WINDOWS_H + #if !HAVE_TYPE_INT32 + typedef long int32; + #endif + #include + #endif + #ifndef CS_HEADER_GLOBAL + #define CS_HEADER_GLOBAL(X,Y) CS_HEADER_GLOBAL_COMPOSE(X,Y) + #define CS_HEADER_GLOBAL_COMPOSE(X,Y) + #endif + #ifdef $1 + #include CS_HEADER_GLOBAL($1,$3) + #else + #include <$2/$3> + #endif]]) + +AC_DEFUN([CS_CHECK_OPENGL], + [AC_REQUIRE([CS_CHECK_HOST]) + AC_REQUIRE([CS_CHECK_COMMON_LIBS]) + AC_REQUIRE([CS_CHECK_PTHREAD]) + AC_REQUIRE([AC_PATH_X]) + AC_REQUIRE([AC_PATH_XTRA]) + AC_CHECK_TYPE([int32], [AC_DEFINE([HAVE_TYPE_INT32], [], + [Whether the int32 type is available])], []) + AC_CHECK_HEADERS([windows.h], [], [], [cs_define_int32]) + + # Apply plaform-specific flags if necessary. + cs_gl_plat_cflags='' + cs_gl_plat_lflags='' + cs_gl_plat_libs='' + AS_IF([test -n "$cs_cv_libm_cflags$cs_cv_libm_lflags$cs_cv_libm_libs"], + [cs_gl_plat_cflags="$cs_cv_libm_cflags $cs_gl_plat_cflags" + cs_gl_plat_lflags="$cs_cv_libm_lflags $cs_gl_plat_lflags" + cs_gl_plat_libs="$cs_cv_libm_libs $cs_gl_plat_libs"]) + AS_IF([test $cs_cv_sys_pthread = yes], + [cs_gl_plat_cflags="$cs_cv_sys_pthread_cflags $cs_gl_plat_cflags" + cs_gl_plat_lflags="$cs_cv_sys_pthread_lflags $cs_gl_plat_lflags" + cs_gl_plat_libs="$cs_cv_sys_pthread_libs $cs_gl_plat_libs"]) + AS_IF([test "$no_x" != yes], + [cs_gl_plat_cflags="$X_CFLAGS $cs_gl_plat_cflags" + cs_gl_plat_lflags="$cs_gl_plat_lflags" + cs_gl_plat_libs=" + $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS $cs_gl_plat_libs"]) + + # Mesa requested? + AC_ARG_WITH([mesa], [AC_HELP_STRING([--with-mesa], + [use Mesa OpenGL library if available (default YES)])], + [], [with_mesa=yes]) + + AS_IF([test $with_mesa != no], + [cs_mesa_gl=CS_CREATE_TUPLE([],[],[-lMesaGL])]) + + # MacOS/X or Darwin? + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_osx_gl=CS_CREATE_TUPLE([-DCS_OPENGL_PATH=OpenGL],[],[-framework OpenGL])]) + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_gl_plat_lflags="$cs_plat_lflags -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"]) + + # Windows? + AS_IF([test $cs_host_family = windows], + [cs_win32_gl=CS_CREATE_TUPLE([],[],[-lopengl32])]) + + # Check for OpenGL. + CS_CHECK_BUILD([for OpenGL], [cs_cv_libgl], + [AC_LANG_PROGRAM([CS_GL_INCLUDE([CS_OPENGL_PATH],[GL],[gl.h])],[glEnd()])], + [$cs_win32_gl \ + $cs_osx_gl \ + CS_CREATE_TUPLE([],[],[-lGL]) \ + CS_CREATE_TUPLE([],[],[-lgl]) \ + $cs_mesa_gl], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libgl], [GL])], [], [], + [$cs_gl_plat_cflags], [$cs_gl_plat_lflags], [$cs_gl_plat_libs])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLU +# Check for GLU. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLU], + [AC_REQUIRE([CS_CHECK_OPENGL]) + AS_IF([test $cs_cv_libgl = yes], + [AS_IF([test $with_mesa != no], + [cs_mesa_glu=CS_CREATE_TUPLE([],[],[-lMesaGLU])]) + + # MacOS/X or Darwin? + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_osx_glu=CS_CREATE_TUPLE([-DCS_GLU_PATH=OpenGL],[],[-framework OpenGL])]) + + # Windows? + AS_IF([test $cs_host_family = windows], + [cs_win32_glu=CS_CREATE_TUPLE([],[],[-lglu32])]) + + # Check for GLU. + CS_CHECK_BUILD([for GLU], [cs_cv_libglu], + [AC_LANG_PROGRAM( + [CS_GL_INCLUDE([CS_GLU_PATH],[GL],[glu.h])], [gluNewQuadric()])], + [$cs_osx_glu \ + CS_CREATE_TUPLE() \ + $cs_win32_glu \ + CS_CREATE_TUPLE([],[],[-lGLU]) \ + CS_CREATE_TUPLE([],[],[-lglu]) \ + $cs_mesa_glu], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libglu], [GLU])], [], [], + [$cs_cv_libgl_cflags], [$cs_cv_libgl_lflags], [$cs_cv_libgl_libs])])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLX +# Check for GLX. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLX], + [AC_REQUIRE([CS_CHECK_OPENGL]) + AS_IF([test $cs_cv_libgl = yes], + [AS_IF([test $with_mesa != no], + [cs_mesa_glx=CS_CREATE_TUPLE([],[],[-lMesaGLX])]) + + # Check for GLX. + AS_IF([test "$no_x" != yes], + [CS_CHECK_BUILD([for GLX], [cs_cv_libglx], + [AC_LANG_PROGRAM([[#include ]], [glXWaitGL()])], + [CS_CREATE_TUPLE() \ + CS_CREATE_TUPLE([],[],[-lGLX]) \ + CS_CREATE_TUPLE([],[],[-lglx]) \ + $cs_mesa_glx], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libglx], [GLX])], [], [], + [$cs_cv_libgl_cflags], [$cs_cv_libgl_lflags], [$cs_cv_libgl_libs])])])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLXEXT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# Check for GLX extensions. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLXEXT], + [AC_REQUIRE([CS_CHECK_GLX]) + AS_IF([test x$cs_cv_libglx = "xyes"], + [# Check for GLX extensions. + CS_CHECK_BUILD([for GLX extensions], [cs_cv_libglx_extensions], + [AC_LANG_PROGRAM( + [[#define GLX_GLXEXT_PROTOTYPES + #include ]], + [glXGetProcAddressARB(0)])], + [CS_CREATE_TUPLE( + [$cs_cv_libglx_cflags], + [$cs_cv_libglx_lflags], + [$cs_cv_libglx_libs])], + [], [$1], [$2])])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_GLUT +# Check for GLUT. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_GLUT], + [AC_REQUIRE([CS_CHECK_GLU]) + AS_IF([test x$cs_cv_libglu = "xyes"], + [# MacOS/X or Darwin? + AS_IF([test "x$cs_host_macosx" = "xyes"], + [cs_osx_glut=CS_CREATE_TUPLE([-DCS_GLUT_PATH=GLUT],[],[-framework GLUT])]) + + # Windows? + AS_IF([test $cs_host_family = windows], + [cs_win32_glut=CS_CREATE_TUPLE([],[],[-lglut32])]) + + # Check for GLUT. + CS_CHECK_BUILD([for GLUT], [cs_cv_libglut], + [AC_LANG_PROGRAM( + [CS_GL_INCLUDE([CS_GLUT_PATH],[GL],[glut.h])], [glutSwapBuffers()])], + [$cs_osx_glut \ + CS_CREATE_TUPLE() \ + $cs_win32_glut \ + CS_CREATE_TUPLE([],[],[-lGLUT]) \ + CS_CREATE_TUPLE([],[],[-lglut])], [], + [CS_EMIT_BUILD_RESULT([cs_cv_libglut], [GLUT])], [], [], + [$cs_cv_libgl_cflags $cs_cv_libglu_cflags], + [$cs_cv_libgl_lflags $cs_cv_libglu_lflags], + [$cs_cv_libgl_libs $cs_cv_libglu_libs])])]) + +# checkpic.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_COMPILER_PIC([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check if compiler can be instructed to produce +# position-independent-code (PIC). This feature is required by some +# platforms when building plugin modules and shared libraries. If +# LANGUAGE is not provided, then `C' is assumed (other options include +# `C++'). If CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_pic". If a PIC-enabling option (such as `-fPIC') +# is discovered, then it is assigned to CACHE-VAR and ACTION-IF-FOUND is +# invoked; otherwise the empty string is assigned to CACHE-VAR and +# ACTION-IF-NOT-FOUND is invoked. +# +# IMPLEMENTATION NOTES +# +# On some platforms (such as Windows), the -fPIC option is superfluous +# and emits a warning "-fPIC ignored for target (all code is position +# independent)", despite the fact that the compiler accepts the option +# and returns a success code. We want to re-interpret the warning as a +# failure in order to avoid unnecessary compiler diagnostics in case the +# client inserts the result of this check into CFLAGS, for instance. We +# do so by attempting to promote warnings to errors using the result of +# CS_COMPILER_ERRORS(). As an extra safe-guard, we also scan the compiler +# output for an appropriate diagnostic because some gcc warnings fail to +# promote to error status despite use of -Werror. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_PIC], + [CS_COMPILER_ERRORS([$1], + [m4_default([$2_werror],[cs_cv_prog_compiler_pic_werror])]) + CS_CHECK_BUILD_FLAGS( + [how to enable m4_default([$1],[C]) PIC generation], + [m4_default([$2],[cs_cv_prog_compiler_pic])], + [CS_CREATE_TUPLE([-fPIC])], [$1], [$3], [$4], + [m4_default([$$2_werror],[$cs_cv_prog_compiler_pic_werror])], [], [], + [fPIC])]) + +# Backward-compatiblity alias. +AC_DEFUN([CS_CHECK_COMPILER_PIC], [CS_COMPILER_PIC([$1],[$2],[$3],[$4])]) +# checkprog.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# cs_bin_paths_default +# Comma delimited list of additional directories in which tools and +# commands might be found. +# +# Present Cases: +# /usr/local/bin -- Although a common location for executables, it is +# now-and-then absent from the default PATH setting. +# /sw/bin -- Fink, the MacOS/X manager of Unix packages, installs +# executables here. +#------------------------------------------------------------------------------ +m4_define([cs_bin_paths_default], [/usr/local/bin, /sw/bin]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_PROG(VARIABLE, PROGRAM, VALUE-IF-FOUND, [VALUE-IF-NOT-FOUND], +# [PATH], [REJECT]) +# Simple wrapper for AC_CHECK_PROG() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PROG], + [_CS_PROG_PATH_PREPARE + AC_CHECK_PROG([$1], [$2], [$3], [$4], + m4_ifval([$5], [_CS_PROG_CLIENT_PATH([$5])]), [$6])]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_PROGS(VARIABLE, PROGRAMS, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_CHECK_PROGS() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PROGS], + [_CS_PROG_PATH_PREPARE + AC_CHECK_PROGS([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_TOOL(VARIABLE, TOOL, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_CHECK_TOOL() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_TOOL], + [_CS_PROG_PATH_PREPARE + AC_CHECK_TOOL([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_TOOLS(VARIABLE, TOOLS, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_CHECK_TOOLS() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_TOOLS], + [_CS_PROG_PATH_PREPARE + AC_CHECK_TOOLS([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_PATH_PROG(VARIABLE, PROGRAM, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_PATH_PROG() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_PROG], + [_CS_PROG_PATH_PREPARE + AC_PATH_PROG([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_PATH_PROGS(VARIABLE, PROGRAMS, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_PATH_PROGS() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_PROGS], + [_CS_PROG_PATH_PREPARE + AC_PATH_PROGS([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# CS_PATH_TOOL(VARIABLE, TOOL, [VALUE-IF-NOT-FOUND], [PATH]) +# Simple wrapper for AC_PATH_TOOL() which ensures that the search path +# is augmented by the directories mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_TOOL], + [_CS_PROG_PATH_PREPARE + AC_PATH_TOOL([$1], [$2], [$3], + m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) + + +#------------------------------------------------------------------------------ +# _CS_PROG_PATH_PREPARE +# Ensure that the PATH environment variable mentions the set of +# directories listed in cs_bin_paths_default. These directories may not +# appear by default in the typical PATH, yet they might be common +# locations for tools and commands. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_PROG_PATH_PREPARE], + [AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE]) + AS_IF([test "$cs_prog_path_prepared" != yes], + [cs_prog_path_prepared=yes + PATH="$PATH[]m4_foreach([cs_bin_path], [cs_bin_paths_default], + [$PATH_SEPARATOR[]cs_bin_path])" + export PATH])]) + + +#------------------------------------------------------------------------------ +# _CS_PROG_CLIENT_PATH(CLIENT-PATH) +# Given a client-supplied replacement for PATH, augment the list by +# appending the locations mentioned in cs_bin_paths_default. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_PROG_CLIENT_PATH], + [AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE])dnl + $1[]m4_foreach([cs_bin_path], [cs_bin_paths_default], + [$PATH_SEPARATOR[]cs_bin_path])]) +# checkpthread.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003-2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_PTHREAD([REJECT-MASK]) +# Check for pthread. Also check if the pthread implementation supports +# the recursive and timed mutex extensions. (Timed mutexes are needed for +# the NPTL: New Posix Thread Library on GNU/Linux if the mutex is going +# to be used with any of the timed condition-wait functions.) The shell +# variable cs_cv_sys_pthread is set to "yes" if pthread is available, +# else "no". If available, then the variables cs_cv_sys_pthread_cflags, +# cs_cv_sys_pthread_lflags, and cs_cv_sys_pthread_libs are set. (As a +# convenience, these variables can be emitted to an output file with +# CS_EMIT_BUILD_RESULT() by passing "cs_cv_sys_pthread" as its CACHE-VAR +# argument.) If the recursive mutex extension is supported, then +# cs_cv_sys_pthread_mutex_recursive will be set with the literal name of +# the constant which must be passed to pthread_mutexattr_settype() to +# enable this feature. The constant name will be typically +# PTHREAD_MUTEX_RECURSIVE or PTHREAD_MUTEX_RECURSIVE_NP. If the recursive +# mutex extension is not available, then +# cs_cv_sys_pthread_mutex_recursive will be set to "no". If the timed +# mutex extension is supported, then cs_cv_sys_pthread_mutex_timed will +# be set with the literal name of the constant which must be passed to +# pthread_mutexattr_settype() to enable this feature. The constant name +# will be typically PTHREAD_MUTEX_TIMED or PTHREAD_MUTEX_TIMED_NP. If the +# timed mutex extension is not available, then +# cs_cv_sys_pthread_mutex_timed will be set to "no". REJECT-MASK can be +# used to limit the platforms on which the pthread test is performed. It +# is compared against $host_os; matches are rejected. If omitted, then +# the test is performed on all platforms. Examples: To avoid testing on +# Cygwin, use "cygwin*"; to avoid testing on Cygwin and AIX, use +# "cygwin*|aix*". +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PTHREAD], + [AC_REQUIRE([AC_CANONICAL_HOST]) + case $host_os in + m4_ifval([$1], + [$1) + cs_cv_sys_pthread=no + ;; + ]) + *) + CS_CHECK_BUILD([for pthread], [cs_cv_sys_pthread], + [AC_LANG_PROGRAM( + [[#include + #include + void* worker(void* p) { (void)p; return p; }]], + [pthread_t tid; + sem_t sem; + pthread_create(&tid, 0, worker, 0); + sem_init(&sem, 0, 0); + sem_destroy(&sem);])], + [cs_pthread_flags]) + ;; + esac + _CS_CHECK_MUTEX_FEATURE([PTHREAD_MUTEX_RECURSIVE], + [cs_cv_sys_pthread_mutex_recursive], [for pthread recursive mutexes])]) + +# _CS_CHECK_MUTEX_FEATURE(FEATURE, CACHE-VAR, MESSAGE) +AC_DEFUN([_CS_CHECK_MUTEX_FEATURE], + [AS_IF([test $cs_cv_sys_pthread = yes], + [AC_CACHE_CHECK([$3], [$2], + [CS_BUILD_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [pthread_mutexattr_t attr; + pthread_mutexattr_settype(&attr, CS_MUTEX_FEATURE);])], + [CS_CREATE_TUPLE([-DCS_MUTEX_FEATURE=$1]) \ + CS_CREATE_TUPLE([-DCS_MUTEX_FEATURE=$1_NP])], + [], + [$2=`echo $cs_build_cflags | sed 's/.*\($1_*N*P*\).*/\1/'`], + [$2=no], + [$cs_cv_sys_pthread_cflags -D_GNU_SOURCE], + [$cs_cv_sys_pthread_lflags], + [$cs_cv_sys_pthread_libs])])], + [$2=no])]) + +#------------------------------------------------------------------------------ +# CS_CHECK_PTHREAD_ATFORK(CACHE-VAR) +# Checks whether the pthread library contains pthread_atfork(). Sets +# CACHE-VAR to "yes" or "no", according to the test result. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_PTHREAD_ATFORK], + [AS_IF([test $cs_cv_sys_pthread = yes], + [AC_CACHE_CHECK([for pthread_atfork support], [$1], + [CS_BUILD_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [pthread_atfork (0, 0, 0);])], + [], [], + [$1=yes], [$1=no], + [$cs_cv_sys_pthread_cflags -D_GNU_SOURCE], + [$cs_cv_sys_pthread_lflags], + [$cs_cv_sys_pthread_libs])])], + [$1=no])]) + +m4_define([cs_pthread_flags], + [CS_CREATE_TUPLE() \ + CS_CREATE_TUPLE([], [], [-lpthread]) \ + CS_CREATE_TUPLE([], [], [-lpthread -lrt]) \ + CS_CREATE_TUPLE([-pthread], [-pthread], []) \ + CS_CREATE_TUPLE([-pthread], [-pthread], [-lpthread]) \ + CS_CREATE_TUPLE([-pthread], [-pthread], [-lc_r])]) +# checktt2.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004,2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_TEMPLATE_TOOLKIT2([EMITTER]) +# Check if Template Toolkit 2 (http://www.tt2.org/) is available. The +# shell variable cs_cv_perl_tt2 is set to "yes" if the package is +# discovered, else "no". Also sets the shell variable TTREE to the name +# path of the 'ttree' utility program and invokes AC_SUBST(). If EMITTER +# is provided and the package was discovered, then +# CS_EMIT_BUILD_PROPERTY() is invoked with EMITTER in order to record the +# value of the TTREE variable in an output file. As a convenience, if +# EMITTER is the literal value "emit" or "yes", then +# CS_EMIT_BUILD_RESULT()'s default emitter will be used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_TEMPLATE_TOOLKIT2], + [CS_CHECK_PROGS([PERL], [perl5 perl]) + AS_IF([test -n "$PERL"], + [AC_CACHE_CHECK([for TemplateToolkit], [cs_cv_perl_tt2], + [AS_IF([AC_RUN_LOG( + [$PERL -M'Template 2.11' -MTemplate::Plugin -e 0 1>&2])], + [cs_cv_perl_tt2=yes], + [cs_cv_perl_tt2=no])]) + CS_PATH_PROGS([TTREE], [ttree]) + AS_IF([test $cs_cv_perl_tt2 = yes && test -n "$TTREE"], + [CS_EMIT_BUILD_PROPERTY([TTREE], [$TTREE], [], [], + CS_EMITTER_OPTIONAL([$1]))])])]) +# compiler.m4 -*- Autoconf -*- +#============================================================================= +# Copyright (C)2003 by Matze Braun +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================= + +#----------------------------------------------------------------------------- +# Detection of C and C++ compilers and setting flags +# +# CS_PROG_CC +# Detects the C compiler. Also takes care of the CFLAGS, CPPFLAGS and CC +# environment variables. This will filter out all -g and -O from the +# CFLAGS variable because Autoconf's -g and -O defaults are not always +# desired. This will also set the CMD.CC and COMPILER.CFLAGS variables +# in Jamconfig +# CS_PROG_CXX +# Detects the C++ compiler. Also takes care of the CXXFLAGS, CPPFLAGS +# and CXX environment variables. This will filter out all -g and -O from +# the CXXFLAGS variable because Autoconf's -g and -O defaults are not +# always desired. This will also set the CMD.C++ and COMPILER.C++FLAGS +# variables in Jamconfig +# CS_PROG_LINK +# Tries to determine a linker. This is done by checking if a C++ or +# Objecctive-C++ compiler is available in which case it is used for +# linking; otherwise the C or Objective-C compiler is used. This also +# sets the CMD.LINK and COMPILER.LFLAGS variables in Jamconfig and +# respects the LDFLAGS environment variable. Finally, checks if linker +# recognizes -shared and sets PLUGIN.LFLAGS; and checks if linker +# recognizes -soname and sets PLUGIN.LFLAGS.USE_SONAME to "yes". +#----------------------------------------------------------------------------- +AC_DEFUN([CS_PROG_CC],[ + CFLAGS="$CFLAGS" # Filter undesired flags + AS_IF([test -n "$CC"],[ + CS_EMIT_BUILD_PROPERTY([CMD.CC], [$CC]) + CS_EMIT_BUILD_PROPERTY([COMPILER.CFLAGS], [$CPPFLAGS $CFLAGS], [+]) + + # Check if compiler recognizes -pipe directive. + CS_EMIT_BUILD_FLAGS([if $CC accepts -pipe], [cs_cv_prog_cc_pipe], + [CS_CREATE_TUPLE([-pipe])], [C], [COMPILER.CFLAGS], [+]) + ]) +]) + +AC_DEFUN([CS_PROG_CXX],[ + CXXFLAGS="$CXXFLAGS" # Filter undesired flags + AS_IF([test -n "$CXX"],[ + CS_EMIT_BUILD_PROPERTY([CMD.C++], [$CXX]) + + CS_EMIT_BUILD_PROPERTY([COMPILER.C++FLAGS], [$CPPFLAGS $CXXFLAGS], [+]) + + # Check if compiler can be instructed to produce position-independent-code + # (PIC). This feature is required by some platforms when building plugin + # modules and shared libraries. + CS_COMPILER_PIC([C++], [cs_cv_prog_cxx_pic], + [CS_EMIT_BUILD_PROPERTY([COMPILER.C++FLAGS.PIC], + [$cs_cv_prog_cxx_pic])]) + ]) +]) + +AC_DEFUN([CS_PROG_LINK],[ + AC_REQUIRE([CS_PROG_CXX]) + AS_IF([test -n "$CXX"], + [CS_EMIT_BUILD_PROPERTY([CMD.LINK], [AS_ESCAPE([$(CMD.C++)])])], + [CS_EMIT_BUILD_PROPERTY([CMD.LINK], [AS_ESCAPE([$(CMD.CC)])])]) + + CS_EMIT_BUILD_PROPERTY([COMPILER.LFLAGS], [$LDFLAGS], [+]) + + # Check if compiler/linker recognizes -shared directive which is needed for + # linking plugin modules. Unfortunately, the Apple compiler (and possibly + # others) requires extra effort. Even though the compiler does not recognize + # the -shared option, it nevertheless returns a "success" result after emitting + # the warning "unrecognized option `-shared'". Worse, even -Werror fails to + # promote the warning to an error, so we must instead scan the compiler's + # output for an appropriate diagnostic. + CS_CHECK_BUILD_FLAGS([if -shared is accepted], [cs_cv_prog_link_shared], + [CS_CREATE_TUPLE([-shared $cs_cv_prog_cxx_pic])], [C++], + [CS_EMIT_BUILD_PROPERTY([PLUGIN.LFLAGS], [-shared], [+])], [], + [], [], [], [shared]) + + # Check if linker recognizes -soname which is used to assign a name internally + # to plugin modules. + CS_CHECK_BUILD([if -soname is accepted], [cs_cv_prog_link_soname], [], + [CS_CREATE_TUPLE([-Wl,-soname,foobar])], [C++], + [CS_EMIT_BUILD_PROPERTY([PLUGIN.LFLAGS.USE_SONAME], [yes])]) +]) +#------------------------------------------------------------------------------ +# Determine host platform. Recognized families: Unix, Windows, MacOS/X. +# Orginial Macros Copyright (C)2003 Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Determine host CPU. +# +# CS_CHECK_HOST_CPU +# Set the shell variable cs_host_cpu to a normalized form of the CPU name +# returned by config.guess/config.sub. Typically, Crystal Space's +# conception of CPU name is the same as that returned by +# config.guess/config.sub, but there may be exceptions as seen in the +# `case' statement. Also takes the normalized name, uppercases it to +# form a name suitable for the C preprocessor. Additionally sets the +# TARGET.PROCESSOR Jamconfig property. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_HOST_CPU], + [AC_REQUIRE([AC_CANONICAL_HOST]) + case $host_cpu in + [[Ii][3-9]86*|[Xx]86*]) cs_host_cpu=x86 ;; + *) cs_host_cpu=$host_cpu ;; + esac + cs_host_cpu_normalized="AS_TR_CPP([$cs_host_cpu])" + CS_JAMCONFIG_PROPERTY([TARGET.PROCESSOR], [$cs_host_cpu_normalized]) + ]) + + +#------------------------------------------------------------------------------ +# CS_CHECK_HOST +# Sets the shell variables cs_host_target cs_host_family, +# cs_host_os_normalized, and cs_host_os_normalized_uc. Emits appropriate +# CS_PLATFORM_UNIX, CS_PLATFORM_WIN32, CS_PLATFORM_MACOSX via +# AC_DEFINE(), and TARGET.OS and TARGET.OS.NORMALIZED to Jamconfig. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_HOST], + [AC_REQUIRE([AC_CANONICAL_HOST]) + CS_CHECK_HOST_CPU + cs_host_os_normalized='' + case $host_os in + mingw*|cygwin*) + cs_host_target=win32gcc + cs_host_family=windows + ;; + darwin*) + _CS_CHECK_HOST_DARWIN + ;; + *) + # Everything else is assumed to be Unix or Unix-like. + cs_host_target=unix + cs_host_family=unix + ;; + esac + + case $cs_host_family in + windows) + AC_DEFINE([CS_PLATFORM_WIN32], [], + [Define when compiling for Win32]) + AS_IF([test -z "$cs_host_os_normalized"], + [cs_host_os_normalized='Win32']) + ;; + unix) + AC_DEFINE([CS_PLATFORM_UNIX], [], + [Define when compiling for Unix and Unix-like (i.e. MacOS/X)]) + AS_IF([test -z "$cs_host_os_normalized"], + [cs_host_os_normalized='Unix']) + ;; + esac + + cs_host_os_normalized_uc="AS_TR_CPP([$cs_host_os_normalized])" + CS_JAMCONFIG_PROPERTY([TARGET.OS], [$cs_host_os_normalized_uc]) + CS_JAMCONFIG_PROPERTY([TARGET.OS.NORMALIZED], [$cs_host_os_normalized]) +]) + +AC_DEFUN([_CS_CHECK_HOST_DARWIN], + [AC_REQUIRE([CS_PROG_CC]) + AC_REQUIRE([CS_PROG_CXX]) + + # Both MacOS/X and Darwin are identified via $host_os as "darwin". We need + # a way to distinguish between the two. If Carbon.h is present, then + # assume MacOX/S; if not, assume Darwin. If --with-x=yes was invoked, and + # Carbon.h is present, then assume that user wants to cross-build for + # Darwin even though build host is MacOS/X. + # IMPLEMENTATION NOTE *1* + # The QuickTime 7.0 installer removes , which + # causes #include to fail unconditionally. Re-installing + # the QuickTime SDK should restore the header, however not all developers + # know to do this, so we work around the problem of the missing + # CarbonSound.h by #defining __CARBONSOUND__ in the test in order to + # prevent Carbon.h from attempting to #include the missing header. + # IMPLEMENTATION NOTE *2* + # At least one MacOS/X user switches between gcc 2.95 and gcc 3.3 with a + # script which toggles the values of CC, CXX, and CPP. Unfortunately, CPP + # was being set to run the preprocessor directly ("cpp", for instance) + # rather than running it via the compiler ("gcc -E", for instance). The + # problem with running the preprocessor directly is that __APPLE__ and + # __GNUC__ are not defined, which causes the Carbon.h check to fail. We + # avoid this problem by supplying a non-empty fourth argument to + # AC_CHECK_HEADER(), which causes it to test compile the header only (which + # is a more robust test), rather than also testing it via the preprocessor. + + AC_DEFINE([__CARBONSOUND__], [], + [Avoid problem caused by missing ]) + AC_CHECK_HEADER([Carbon/Carbon.h], + [cs_host_macosx=yes], [cs_host_macosx=no], [/* force compile */]) + + AS_IF([test $cs_host_macosx = yes], + [AC_MSG_CHECKING([for --with-x]) + AS_IF([test "${with_x+set}" = set && test "$with_x" = "yes"], + [AC_MSG_RESULT([yes (assume Darwin)]) + cs_host_macosx=no], + [AC_MSG_RESULT([no])])]) + + AS_IF([test $cs_host_macosx = yes], + [cs_host_target=macosx + cs_host_family=unix + cs_host_os_normalized='MacOS/X' + AC_DEFINE([CS_PLATFORM_MACOSX], [], + [Define when compiling for MacOS/X]) + + AC_CACHE_CHECK([for Objective-C compiler], [cs_cv_prog_objc], + [cs_cv_prog_objc="$CC"]) + CS_JAMCONFIG_PROPERTY([CMD.OBJC], [$cs_cv_prog_objc]) + AC_CACHE_CHECK([for Objective-C++ compiler], [cs_cv_prog_objcxx], + [cs_cv_prog_objcxx="$CXX"]) + CS_JAMCONFIG_PROPERTY([CMD.OBJC++], [$cs_cv_prog_objcxx])], + + [cs_host_target=unix + cs_host_family=unix])]) +# diagnose.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_MSG_ERROR(ERROR-DESCRIPTION, [EXIT-STATUS]) +# A convenience wrapper for AC_MSG_ERROR() which invokes AC_CACHE_SAVE() +# before aborting the script. Saving the cache should make subsequent +# re-invocations of the configure script faster once the user has +# corrected the problem(s) which caused the failure. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_MSG_ERROR], + [AC_CACHE_SAVE + AC_MSG_ERROR([$1], [$2])]) +# embed.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003,2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_META_INFO_EMBED([EMITTER], [GPL-OKAY]) +# Determine if plugin meta-information should be embedded or if it should +# exist in a stand-alone .csplugin file, and check if necessary tools and +# libraries are present. Sets the shell variable +# enable_meta_info_embedding to "yes" if the user requested embedding or +# if it was enabled by default; otherwise sets it to "no". +# +# If EMITTER is provided, then a subset of the following variables +# (depending upon platform and availability) are recorded by invoking +# CS_EMIT_BUILD_PROPERTY() with EMITTER. As a convenience, if EMITTER is +# the literal value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s +# default emitter will be used. +# +# EMBED_META := yes or no +# EMBED_META.CFLAGS := compiler flags +# EMBED_META.LFLAGS := linker flags +# CMD.WINDRES := windres.exe +# OBJCOPY.AVAILABLE := yes or no +# CMD.OBJCOPY := objcopy.exe +# LIBBFD.AVAILABLE := yes or no +# LIBBFD.CFLAGS := libbfd compiler flags +# LIBBFD.LFLAGS := libbfd linker flags +# ELF.AVAILABLE := yes or no +# +# In general, clients need only concern themselves with the various +# EMBED_META-related variables. For building plugin modules, utilize +# EMBED_META.CFLAGS when compiling, and EMBED_META.LFLAGS when linking. +# +# On Unix, when CS' own ELF metadata reader can't be used (because the +# necessary header file elf.h was not found) embedding is accomplished +# via libbfd, which carries a GPL license. Projects which carry licenses +# not compatible with GPL should consider carefully before enabling +# embedding on Unix. If your project is GPL-compatible, then set GPL-OKAY +# to "yes". This will indicate that it is safe to use libbfd if the ELF +# reader can not be used. If your project is not GPL-compatible, then +# set it to "no" in order to disable embedding on Unix if the ELF reader +# is not usable. (The user can still manually override the setting via +# the --enable-meta-info-embedding option.) +# +# IMPLEMENTATION NOTES +# +# Recent versions of Mingw supply libbfd and libiberty. Since Crystal +# Space uses native Win32 API for meta-information embedding on Windows, +# we do not require these libraries on Windows. More importantly, users +# do not want to see these GPL-licensed libraries appear in the link +# statement for plugin modules, thus we explicitly disable the libbfd +# test on Windows. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_META_INFO_EMBED], + [AC_REQUIRE([AC_CANONICAL_HOST]) + _CS_META_INFO_EMBED_ENABLE([$1], [$2]) + AS_IF([test $enable_meta_info_embedding = yes], + [_CS_META_INFO_EMBED_TOOLS([$1]) + AS_IF([test $cs_header_elf_h = yes], + [CS_EMIT_BUILD_PROPERTY([ELF.AVAILABLE], [yes], [], [], + CS_EMITTER_OPTIONAL([$1]))], + [case $host_os in + mingw*|cygwin*) ;; + *) + CS_CHECK_LIBBFD([$1], + [CS_EMIT_BUILD_PROPERTY([EMBED_META.CFLAGS], + [$cs_cv_libbfd_ok_cflags], [+], [], + CS_EMITTER_OPTIONAL([$1])) + CS_EMIT_BUILD_PROPERTY([EMBED_META.LFLAGS], + [$cs_cv_libbfd_ok_lflags $cs_cv_libbfd_ok_libs], + [+], [], CS_EMITTER_OPTIONAL([$1]))]) + ;; + esac])])]) + + +#------------------------------------------------------------------------------ +# _CS_META_INFO_EMBED_ENABLE([EMITTER], [GPL-OKAY]) +# Helper for CS_META_INFO_EMBED which adds an +# --enable-meta-info-embedding option to the configure script allowing +# the user to control embedding. Sets the shell variable +# enable_meta_info_embedding to yes or no. +# +# IMPLEMENTATION NOTES +# +# On Unix, embedding is enabled by default if elf.h is found and disabled +# by default unless overridden via GPL-OKAY because libbfd carries a GPL +# license which may be incompatible with a project's own license (such as +# LGPL). +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_META_INFO_EMBED_ENABLE], + [AC_REQUIRE([CS_CHECK_HOST]) + AC_CHECK_HEADERS([elf.h], [cs_header_elf_h=yes], [cs_header_elf_h=no]) + AC_MSG_CHECKING([whether to embed plugin meta-information]) + case $cs_host_target in + unix) AS_IF([test $cs_header_elf_h = yes], + [cs_embed_meta_info_default=yes], + [cs_embed_meta_info_default=m4_ifval([$2],[$2],[no])]) ;; + *) cs_embed_meta_info_default=yes ;; + esac + AC_ARG_ENABLE([meta-info-embedding], + [AC_HELP_STRING([--enable-meta-info-embedding], + [store plugin meta-information directly inside plugin modules if + supported by platform; if disabled, meta-information is stored in + stand-alone .csplugin files; this option is enabled by default for + non-Unix platforms and on Unix platforms with ELF-format object + files; it is disabled by default on Unix platforms if ELF is not + available and the project uses a non-GPL-compatible license (such + as LGPL) since the non-ELF Unix embedding technology requires the + GPL-licensed libbfd library; if ELF is not available, enable this + option on Unix only if you are certain you want a GPL-licensed + library infecting your project])], + [], [enable_meta_info_embedding=$cs_embed_meta_info_default]) + AC_MSG_RESULT([$enable_meta_info_embedding]) + CS_EMIT_BUILD_PROPERTY([EMBED_META], [$enable_meta_info_embedding], + [], [], CS_EMITTER_OPTIONAL([$1]))]) + + + +#------------------------------------------------------------------------------ +# _CS_META_INFO_EMBED_TOOLS([EMITTER]) +# Helper for CS_META_INFO_EMBED() which searches for tools required for +# plugin meta-info embedding. +#------------------------------------------------------------------------------ +AC_DEFUN([_CS_META_INFO_EMBED_TOOLS], + [CS_CHECK_TOOLS([WINDRES], [windres]) + CS_EMIT_BUILD_PROPERTY([CMD.WINDRES], [$WINDRES], [], [], + CS_EMITTER_OPTIONAL([$1])) + + CS_CHECK_TOOLS([OBJCOPY], [objcopy]) + AS_IF([test -n "$OBJCOPY"], + [CS_EMIT_BUILD_PROPERTY([OBJCOPY.AVAILABLE], [yes], [], [], + CS_EMITTER_OPTIONAL([$1])) + CS_EMIT_BUILD_PROPERTY([CMD.OBJCOPY], [$OBJCOPY], [], [], + CS_EMITTER_OPTIONAL([$1]))])]) + + + +#------------------------------------------------------------------------------ +# CS_CHECK_LIBBFD([EMITTER], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# Exhaustive check for a usable GPL-licensed libbfd, the Binary File +# Descriptor library, a component of binutils, which allows low-level +# manipulation of executable and object files. If EMITTER is provided, +# then the following variables are recorded by invoking +# CS_EMIT_BUILD_PROPERTY() with EMITTER. As a convenience, if EMITTER is +# the literal value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s +# default emitter will be used. +# +# LIBBFD.AVAILABLE := yes or no +# LIBBFD.CFLAGS := libbfd compiler flags +# LIBBFD.LFLAGS := libbfd linker flags +# +# The shell variable cs_cv_libbfd_ok is set to yes if a usable libbfd was +# discovered, else no. If found, the additional shell variables +# cs_cv_libbfd_ok_cflags, cs_cv_libbfd_ok_lflags, and +# cs_cv_libbfd_ok_libs are also set. +# +# WARNING +# +# libbfd carries a GPL license which is incompatible with the LGPL +# license of Crystal Space. Do not use this library with projects under +# less restrictive licenses, such as LGPL. +# +# IMPLEMENTATION NOTES +# +# It seems that some platforms have two version of libiberty installed: +# one from binutils and one from gcc. The binutils version resides in +# /usr/lib, whereas the gcc version resides in the gcc installation +# directory. The gcc version, by default, takes precedence at link time +# over the binutils version. Unfortunately, in broken cases, the gcc +# version of libiberty is missing htab_create_alloc() which is required +# by some libbfd functions. The extensive secondary check of libbfd +# catches this anomalous case of broken gcc libiberty. It turns out that +# it is possible to make the linker prefer the binutils version by +# specifying -L/usr/lib, thus the extensive test attempts to do so in an +# effort to resolve this unfortunate issue. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_LIBBFD], + [CS_CHECK_LIB_WITH([bfd], + [AC_LANG_PROGRAM([[#include ]], [bfd_init();])], + [], [], [], [], [], [], [-liberty]) + + AS_IF([test $cs_cv_libbfd = yes], + [CS_CHECK_BUILD([if libbfd is usable], [cs_cv_libbfd_ok], + [AC_LANG_PROGRAM([[#include ]], + [bfd* p; + asection* s; + bfd_init(); + p = bfd_openr(0,0); + bfd_check_format(p,bfd_object); + bfd_get_section_by_name(p,0); + bfd_section_size(p,s); + bfd_get_section_contents(p,s,0,0,0); + bfd_close(p);])], + [CS_CREATE_TUPLE() CS_CREATE_TUPLE([],[-L/usr/lib],[])], + [], [], [], [], + [$cs_cv_libbfd_cflags], + [$cs_cv_libbfd_lflags], + [$cs_cv_libbfd_libs])], + [cs_cv_libbfd_ok=no]) + + AS_IF([test $cs_cv_libbfd_ok = yes], + [CS_EMIT_BUILD_RESULT([cs_cv_libbfd_ok], [LIBBFD], + CS_EMITTER_OPTIONAL([$1])) + $2], + [$3])]) +# emit.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003-2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_EMIT_BUILD_PROPERTY(KEY, VALUE, [APPEND], [EMPTY-OKAY], [EMITTER], +# [UNCONDITIONAL]) +# A utility function which invokes an emitter to record the KEY/VALUE +# tuple if VALUE is not the empty string (after leading and trailing +# whitespace is stripped). If EMPTY-OKAY is not an empty string, then the +# property is emitted even if VALUE is empty; that is, it is emitted +# unconditionally. If APPEND is the empty string, then the emitter sets +# the key's value directly (though it may be overridden by the +# environment), otherwise the emitter appends VALUE to the existing value +# of the key. EMITTER is a macro name, such as CS_JAMCONFIG_PROPERTY or +# CS_MAKEFILE_PROPERTY, which performs the actual task of emitting the +# KEY/VALUE tuple; it should also accept APPEND as an optional third +# argument. If EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. Some +# emitters accept an optional fourth argument, UNCONDITIONAL, which +# instructs it to set KEY's value unconditionally, even if KEY already +# had been assigned a value via some other mechanism (such as imported +# from the environment, or from Jambase, in the case of +# CS_JAMCONFIG_PROPERTY). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_BUILD_PROPERTY], + [cs_build_prop_val="$2" + cs_build_prop_val=CS_TRIM([$cs_build_prop_val]) + m4_ifval([$4], + [CS_JAMCONFIG_PROPERTY([$1], [$cs_build_prop_val], [$3])], + AS_IF([test -n "$cs_build_prop_val"], + [m4_default([$5],[CS_JAMCONFIG_PROPERTY])( + [$1], [$cs_build_prop_val], [$3], [$6])]))]) + + + +#------------------------------------------------------------------------------ +# CS_EMIT_BUILD_RESULT(CACHE-VAR, PREFIX, [EMITTER]) +# Record the results of CS_CHECK_BUILD() or CS_CHECK_LIB_WITH() via some +# emitter. If CACHE-VAR indicates that the build succeeded, then the +# following properties are emitted: +# +# PREFIX.AVAILABLE = yes +# PREFIX.CFLAGS = $CACHE-VAR_cflags +# PREFIX.LFLAGS = $CACHE-VAR_lflags $CACHE-VAR_libs +# +# EMITTER is a macro name, such as CS_JAMCONFIG_PROPERTY or +# CS_MAKEFILE_PROPERTY, which performs the actual task of emitting the +# KEY/VALUE tuple. If EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_BUILD_RESULT], + [AS_IF([test "$$1" = yes], + [CS_EMIT_BUILD_PROPERTY([$2.AVAILABLE], [yes], [], [], [$3]) + CS_EMIT_BUILD_PROPERTY([$2.CFLAGS], [$$1_cflags], [], [], [$3]) + CS_EMIT_BUILD_PROPERTY([$2.LFLAGS], [$$1_lflags $$1_libs], + [], [], [$3])])]) + + + +#------------------------------------------------------------------------------ +# CS_EMIT_BUILD_FLAGS(MESSAGE, CACHE-VAR, FLAGS, [LANGUAGE], EMITTER-KEY, +# [APPEND], [ACTION-IF-RECOGNIZED], +# [ACTION-IF-NOT-RECOGNIZED], [EMITTER]) +# A convenience wrapper for CS_CHECK_BUILD_FLAGS() which also records the +# results via CS_EMIT_BUILD_PROPERTY(). Checks if the compiler or linker +# recognizes a command-line option. MESSAGE is the "checking" message. +# CACHE-VAR is the shell cache variable which receives the flag +# recognized by the compiler or linker, or "no" if the flag was not +# recognized. FLAGS is a whitespace- delimited list of build tuples +# created with CS_CREATE_TUPLE(). Each tuple from FLAGS is attempted in +# order until one is found which is recognized by the compiler. After +# that, no further flags are checked. LANGUAGE is typically either C or +# C++ and specifies which compiler to use for the test. If LANGUAGE is +# omitted, C is used. EMITTER-KEY is the name to pass as the emitter's +# "key" argument if a usable flag is encountered. If APPEND is not the +# empty string, then the discovered flag is appended to the existing +# value of the EMITTER-KEY. If the command-line option was recognized, +# then ACTION-IF-RECOGNIZED is invoked, otherwise +# ACTION-IF-NOT-RECOGNIZED is invoked. EMITTER is a macro name, such as +# CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, which performs the +# actual task of emitting the KEY/VALUE tuple; it should also accept +# APPEND as an optional third argument. If EMITTER is omitted, +# CS_JAMCONFIG_PROPERTY is used. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_BUILD_FLAGS], + [CS_CHECK_BUILD_FLAGS([$1], [$2], [$3], [$4], + [CS_EMIT_BUILD_PROPERTY([$5], [$$2], [$6], [], [$9]) + $7], + [$8])]) + + + +#------------------------------------------------------------------------------ +# CS_EMITTER_OPTIONAL([EMITTER]) +# The CS_EMIT_FOO() macros optionally accept an emitter. If no emitter is +# supplied to those macros, then a default emitter is chosen. Other +# macros, however, which perform testing and optionally emit the results +# may wish to interpret an omitted EMITTER as a request not to emit the +# results. CS_EMITTER_OPTIONAL() is a convenience macro to help in these +# cases. It should be passed to one of the CS_EMIT_FOO() macros in place +# of the literal EMITTER argument. It functions by re-interpretating +# EMITTER as follows: +# +# - If EMITTER is omitted, then CS_NULL_EMITTER is returned, effectively +# disabling output by the CS_EMIT_FOO() macro. +# - If EMITTER is the literal string "emit" or "yes", then it returns an +# empty string, which signals to the CS_EMIT_FOO() macro that is should +# use its default emitter. +# - Any other value for EMITTER is passed along as-is to the +# CS_EMIT_FOO() macro. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMITTER_OPTIONAL], + [m4_case([$1], + [], [[CS_NULL_EMITTER]], + [emit], [], + [yes], [], + [[$1]])]) + + + +#------------------------------------------------------------------------------ +# CS_NULL_EMITTER(KEY, VALUE, [APPEND]) +# A do-nothing emitter suitable for use as the EMITTER argument of one of +# the CS_EMIT_FOO() macros. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_NULL_EMITTER], [: +]) + + + +#------------------------------------------------------------------------------ +# CS_SUBST_EMITTER(KEY, VALUE, [APPEND]) +# An emitter wrapped around AC_SUBST(). Invokes +# AC_SUBST(AS_TR_SH(KEY),VALUE). The APPEND argument is ignored. +# Suitable for use as the EMITTER argument of one of the CS_EMIT_FOO() +# macros. The call to AS_TR_SH() ensures that KEY is transformed into a +# valid shell variable. For instance, if a macro attempts to emit +# MYLIB.CFLAGS and MYLIB.LFLAGS via CS_SUBST_EMITTER(), then the names +# will be transformed to MYLIB_CFLAGS and MYLIB_LFLAGS, respectively, for +# the invocation of AC_SUBST(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SUBST_EMITTER], [AC_SUBST(AS_TR_SH([$1]),[$2])]) + + + +#------------------------------------------------------------------------------ +# CS_DEFINE_EMITTER(KEY, VALUE, [APPEND]) +# An emitter wrapped around AC_DEFINE_UNQUOTED(). Invokes +# AC_DEFINE_UNQUOTED(AS_TR_CPP(KEY),VALUE). The APPEND argument is +# ignored. Suitable for use as the EMITTER argument of one of the +# CS_EMIT_FOO() macros. The call to AS_TR_CPP() ensures that KEY is a +# well-formed token for the C-preprocessor. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_DEFINE_EMITTER], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([$1]),[$2], + [Define when feature is available])]) +# headercache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility for C-style #define properties. The cache is stored in +# the shell variable cs_header_text. +# +# CS_HEADER_APPEND(TEXT) +# Append text to the C header text cache. This is a cover for +# CS_TEXT_CACHE_APPEND(). +# +# CS_HEADER_PREPEND(TEXT) +# Prepend text to the C header text cache. This is a cover for +# CS_TEXT_CACHE_PREPEND(). +# +# CS_HEADER_PROPERTY(KEY, [VALUE]) +# Append a line of the form "#define KEY VALUE" to the C header text +# cache. If the VALUE argument is omitted, then the appended line has +# the simplified form "#define KEY". +# +# CS_HEADER_OUTPUT(FILENAME) +# Instruct config.status to write the C header text cache to the given +# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_HEADER_APPEND], [CS_TEXT_CACHE_APPEND([cs_header_text], [$1])]) +AC_DEFUN([CS_HEADER_PREPEND], [CS_TEXT_CACHE_PREPEND([cs_header_text], [$1])]) +AC_DEFUN([CS_HEADER_PROPERTY], +[CS_HEADER_APPEND([@%:@define $1[]m4_ifval([$2], [ $2], []) +])]) +AC_DEFUN([CS_HEADER_OUTPUT], [CS_TEXT_CACHE_OUTPUT([cs_header_text], [$1])]) +#----------------------------------------------------------------------------- +# installdirs.m4 (c) Matze Braun +# Macro for emitting the installation paths gathered by Autoconf. +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# CS_OUTPUT_INSTALLDIRS([EMITTER], [RAW-BACKSLASHES]) +# Emit installation directories collected by Autoconf. EMITTER is a macro +# name, such as CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, which performs +# the actual task of emitting the KEY/VALUE tuple. If EMITTER is omitted, +# CS_JAMCONFIG_PROPERTY is used. If RAW-BACKSLASHES is not provided, then +# backslashes in emitted values are each escaped with an additional +# backslash. If RAW-BACKSLASHES is not the null value, then backslashes are +# emitted raw. The following properties are emitted: +# +# prefix +# exec_prefix +# bindir +# sbindir +# libexecdir +# datadir +# sysconfdir +# sharedstatedir +# localstatedir +# libdir +# includedir +# oldincludedir +# infodir +# mandir +#----------------------------------------------------------------------------- +AC_DEFUN([CS_OUTPUT_INSTALLDIRS],[ +# Handle the case when no prefix is given, and the special case when a path +# contains more than 2 slashes, these paths seem to be correct but Jam fails +# on them. +AS_IF([test $prefix = NONE], + [cs_install_prefix="$ac_default_prefix"], + [cs_install_prefix=`echo "$prefix" | sed -e 's:///*:/:g'`]) +AS_IF([test $exec_prefix = NONE], + [cs_install_exec_prefix="AS_ESCAPE([$(prefix)])"], + [cs_install_exec_prefix=`echo "$exec_prefix" | sed -e 's:///*:/:g'`]) + +_CS_OUTPUT_INSTALL_DIRS([$1], [prefix], + [CS_PREPARE_INSTALLPATH([$cs_install_prefix], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [exec_prefix], + [CS_PREPARE_INSTALLPATH([$cs_install_exec_prefix], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [bindir], + [CS_PREPARE_INSTALLPATH([$bindir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [sbindir], + [CS_PREPARE_INSTALLPATH([$sbindir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [libexecdir], + [CS_PREPARE_INSTALLPATH([$libexecdir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [datadir], + [CS_PREPARE_INSTALLPATH([$datadir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [sysconfdir], + [CS_PREPARE_INSTALLPATH([$sysconfdir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [sharedstatedir], + [CS_PREPARE_INSTALLPATH([$sharedstatedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [localstatedir], + [CS_PREPARE_INSTALLPATH([$localstatedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [libdir], + [CS_PREPARE_INSTALLPATH([$libdir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [includedir], + [CS_PREPARE_INSTALLPATH([$includedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [oldincludedir], + [CS_PREPARE_INSTALLPATH([$oldincludedir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [infodir], + [CS_PREPARE_INSTALLPATH([$infodir], [$2])]) +_CS_OUTPUT_INSTALL_DIRS([$1], [mandir], + [CS_PREPARE_INSTALLPATH([$mandir], [$2])]) +]) + +AC_DEFUN([_CS_OUTPUT_INSTALL_DIRS], + [m4_default([$1], [CS_JAMCONFIG_PROPERTY])([$2], [$3])]) + + +#----------------------------------------------------------------------------- +# CS_PREPARE_INSTALLPATH(VALUE, [RAW-BACKSLASHES]) +# Transform variable references of the form ${bla} to $(bla) in VALUE and +# correctly quotes backslashes. This is needed if you need to emit some of +# the paths from Autoconf. RAW-BACKSLASHES has the same meaning as in +# CS_OUTPUT_INSTALLDIRS. +#----------------------------------------------------------------------------- +AC_DEFUN([CS_PREPARE_INSTALLPATH], +[`echo "$1" | sed 's/\${\([[a-zA-Z_][a-zA-Z_]]*\)}/$(\1)/g;m4_ifval([$2], + [s/\\/\\\\/g], [s/\\\\/\\\\\\\\/g])'`]) +# jamcache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility for Jam-style properties. The cache is stored in +# the shell variable cs_jamfile_text. +# +# CS_JAMCONFIG_APPEND(TEXT) +# Append text to the Jam text cache. This is a cover for +# CS_TEXT_CACHE_APPEND(). +# +# CS_JAMCONFIG_PREPEND(TEXT) +# Prepend text to the Jam text cache. This is a cover for +# CS_TEXT_CACHE_PREPEND(). +# +# CS_JAMCONFIG_PROPERTY(KEY, VALUE, [APPEND], [UNCONDITIONAL]) +# Append a line of the form "KEY ?= VALUE" to the Jam text cache. If the +# APPEND argument is not the empty string, then VALUE is appended to the +# existing value of KEY using the form "KEY += VALUE". If the +# UNCONDITIONAL argument is not empty, then the value of KEY is set +# unconditionally "KEY = VALUE", rather than via "KEY ?= VALUE". APPEND +# takes precedence over UNCONDITIONAL. Note that if VALUE references +# other Jam variables, for example $(OBJS), then be sure to protect the +# value with AS_ESCAPE(). For example: +# CS_JAMCONFIG_PROPERTY([ALLOBJS], [AS_ESCAPE([$(OBJS) $(LIBOBJS)])]) +# +# CS_JAMCONFIG_OUTPUT(FILENAME) +# Instruct config.status to write the Jam text cache to the given +# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_JAMCONFIG_APPEND], + [CS_TEXT_CACHE_APPEND([cs_jamconfig_text], [$1])]) +AC_DEFUN([CS_JAMCONFIG_PREPEND], + [CS_TEXT_CACHE_PREPEND([cs_jamconfig_text], [$1])]) +AC_DEFUN([CS_JAMCONFIG_PROPERTY], + [CS_JAMCONFIG_APPEND( + [$1 m4_ifval([$3], [+=], m4_ifval([$4], [=], [?=])) \"$2\" ; +])]) +AC_DEFUN([CS_JAMCONFIG_OUTPUT], + [CS_TEXT_CACHE_OUTPUT([cs_jamconfig_text], [$1])]) +# makecache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility for makefile-style properties. The cache is stored in +# the shell variable cs_makefile_text. +# +# CS_MAKEFILE_APPEND(TEXT) +# Append text to the makefile text cache. This is a cover for +# CS_TEXT_CACHE_APPEND(). +# +# CS_MAKEFILE_PREPEND(TEXT) +# Prepend text to the makefile text cache. This is a cover for +# CS_TEXT_CACHE_PREPEND(). +# +# CS_MAKEFILE_PROPERTY(KEY, VALUE, [APPEND]) +# Append a line of the form "KEY = VALUE" to the makefile text cache. If +# the APPEND argument is not the empty string, then VALUE is appended to +# the existing value of KEY using the form "KEY += VALUE". Note that if +# VALUE references other makefile variables, for example $(OBJS), then be +# sure to protect the value with AS_ESCAPE(). For example: +# CS_MAKEFILE_PROPERTY([ALLOBJS], [AS_ESCAPE([$(OBJS) $(LIBOBJS)])]) +# +# CS_MAKEFILE_OUTPUT(FILENAME) +# Instruct config.status to write the makefile text cache to the given +# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_MAKEFILE_APPEND], + [CS_TEXT_CACHE_APPEND([cs_makefile_text], [$1])]) +AC_DEFUN([CS_MAKEFILE_PREPEND], + [CS_TEXT_CACHE_PREPEND([cs_makefile_text], [$1])]) +AC_DEFUN([CS_MAKEFILE_PROPERTY], + [CS_MAKEFILE_APPEND([$1 m4_ifval([$3], [+=], [=]) $2 +])]) +AC_DEFUN([CS_MAKEFILE_OUTPUT],[CS_TEXT_CACHE_OUTPUT([cs_makefile_text], [$1])]) +# mkdir.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_CHECK_MKDIR +# Determine how to create a directory and a directory tree. Sets the +# shell variable MKDIR to the command which creates a directory, and +# MKDIRS to the command which creates a directory tree. Invokes +# AC_SUBST() for MKDIR and MKDIRS. +# +# IMPLEMENTATION NOTES +# We need to know the exact commands, so that we can emit them, thus the +# AS_MKDIR_P function is not what we want to use here since it does not +# provide access to the commands (and might not even discover suitable +# commands). First try "mkdir -p", then try the older "mkdirs". +# Finally, if the mkdir command failed to recognize -p, then it might +# have created a directory named "-p", so clean up that bogus directory. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_CHECK_MKDIR], + [AC_CACHE_CHECK([how to create a directory], [cs_cv_shell_mkdir], + [cs_cv_shell_mkdir='mkdir']) + AC_SUBST([MKDIR], [$cs_cv_shell_mkdir]) + + AC_CACHE_CHECK([how to create a directory tree], [cs_cv_shell_mkdir_p], + [if $cs_cv_shell_mkdir -p . 2>/dev/null; then + cs_cv_shell_mkdir_p='mkdir -p' + elif mkdirs . 2>/dev/null; then + cs_cv_shell_mkdir_p='mkdirs' + fi + test -d ./-p && rmdir ./-p]) + AS_VAR_SET_IF([cs_cv_shell_mkdir_p], + [AC_SUBST([MKDIRS], [$cs_cv_shell_mkdir_p])], + [CS_MSG_ERROR([do not know how to create a directory tree])])]) + + + +#------------------------------------------------------------------------------ +# Replacement for AS_MKDIR_P() from m4sugar/m4sh.m4 which fixes two problems +# which are present in Autoconf 2.57 and probably all earlier 2.5x versions. +# This bug, along with a patch, was submitted to the Autoconf GNATS database by +# Eric Sunshine as #227 on 17-Dec-2002. The bogus "-p" directory bug was fixed +# for Autoconf 2.58 on 26-Sep-2003. The "mkdirs" optimization was not accepted +# (since it is unnecessary; it's only an optimization). +# +# 1) Removes bogus "-p" directory which the stock AS_MKDIR_P() leaves laying +# around in the working directory if the mkdir command does not recognize +# the -p option. +# 2) Takes advantage of the older "mkdirs" program if it exists and if "mkdir +# -p" does not work. +#------------------------------------------------------------------------------ +m4_defun([_AS_MKDIR_P_PREPARE], +[if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p' +elif mkdirs . 2>/dev/null; then + as_mkdir_p='mkdirs' +else + as_mkdir_p='' +fi +test -d ./-p && rmdir ./-p +])# _AS_MKDIR_P_PREPARE + +m4_define([AS_MKDIR_P], +[AS_REQUIRE([_$0_PREPARE])dnl +{ if test -n "$as_mkdir_p"; then + $as_mkdir_p $1 + else + as_dir=$1 + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`AS_DIRNAME("$as_dir")` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || AS_ERROR([cannot create directory $1]); } +])# AS_MKDIR_P +#============================================================================== +# packageinfo.m4 +# Macros for setting general info on the package, such as name and version +# numbers and propagate them to the generated make and Jam property files. +# +# Copyright (C)2003 by Matthias Braun +# Copyright (C)2003,2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== + +#------------------------------------------------------------------------------ +# CS_PACKAGEINFO([LONGNAME], [COPYRIGHT, [HOMEPAGE]) +# Set additional information for the package. Note that the version +# number of your application should only contain numbers, because on +# Windows you can only set numerical values in some of the file +# properties (such as versioninfo .rc files). +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PACKAGEINFO], + [PACKAGE_LONGNAME="[$1]" + PACKAGE_COPYRIGHT="[$2]" + PACKAGE_HOMEPAGE="[$3]" +]) + + +#------------------------------------------------------------------------------ +# CS_EMIT_PACKAGEINFO([EMITTER]) +# Emit extended package information using the provided EMITTER. EMITTER +# is a macro name, such as CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, +# which performs the actual task of emitting the KEY/VALUE tuple. If +# EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. For backward +# compatibility, if EMITTER is the literal value "jam", then +# CS_JAMCONFIG_PROPERTY is used; if it is "make", then +# CS_MAKEFILE_PROPERTY is used; however use of these literal names is +# highly discouraged. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_EMIT_PACKAGEINFO], + [_CS_EMIT_PACKAGEINFO([$1], [PACKAGE_NAME], [$PACKAGE_NAME]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_VERSION], [$PACKAGE_VERSION]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_STRING], [$PACKAGE_STRING]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_BUGREPORT], [$PACKAGE_BUGREPORT]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_LONGNAME], [$PACKAGE_LONGNAME]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_HOMEPAGE], [$PACKAGE_HOMEPAGE]) + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_COPYRIGHT], [$PACKAGE_COPYRIGHT]) + for cs_veritem in m4_translit(AC_PACKAGE_VERSION, [.], [ ]); do + _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_VERSION_LIST], [$cs_veritem], [+]) + done + ]) + +AC_DEFUN([_CS_EMIT_PACKAGEINFO], + [m4_case([$1], + [make], [CS_MAKEFILE_PROPERTY([$2], [$3], [$4])], + [jam], [CS_JAMCONFIG_PROPERTY([$2], [$3], [$4])], + [], [CS_JAMCONFIG_PROPERTY([$2], [$3], [$4])], + [$1([$2], [$3], [$4])])]) +# path.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2004 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_PATH_NORMALIZE(STRING) +# Normalize a pathname at run-time by transliterating Windows/DOS +# backslashes to forward slashes. Also collapses whitespace. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_PATH_NORMALIZE], +[`echo "x$1" | tr '\\\\' '/' | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) + + +#------------------------------------------------------------------------------ +# CS_RUN_PATH_NORMALIZE(COMMAND) +# Normalize the pathname emitted by COMMAND by transliterating +# Windows/DOS backslashes to forward slashes. Also collapses whitespace. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_RUN_PATH_NORMALIZE], +[`AC_RUN_LOG([$1]) | tr '\\\\' '/' | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) +############################################################################### +# progver.m4 +# Written by Norman Kramer +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +############################################################################### +# +# From the input pattern we create regular expressions we send through sed +# to extract the version information from the standard input to sed. +# Then we extract from the resulting version string subparts. +# The same happens with the supplied version string. It too is split into its +# subparts according to the pattern. +# Then the subparts from the gathered version string and the supplied one are +# compared. +# +# How does the pattern look like ? +# It is a sequence of 9s and _s and separators. +# 9 denotes a non empty sequence of digits. +# _ denotes a non empty sequence of characters from the class [a-zA-Z]. +# | everything behind is optional +# Everything else is treated as a separator. +# Consecutive 9s and _s are compressed to contain only one of each type. +# For instance "99_.9.__abc9_" will become "9_.9._abc9_". +# +# How we find the parts we compare ? +# From this transformed string we yield the parts we will later compare. +# We break up the string as follows: +# Any sequence of separators represent one breakup. Additional breakups are +# placed behind every 9 and _ . +# So the example from above will give: +# +# "99_.9.__abc9_" ===compress==> "9_.9._abc9_" ===breakup==> "9" "_" "9" "_" "9" "_" +# +# How we create the regular expressions ? +# We take the compressed pattern and quote every separator. +# The we replace the 9s with [0-9][0-9]* +# and the _s with [a-zA-Z][a-zA-Z]* . +# The above example will become: +# +# "99_.9.__abc9_" ===compress==> "9_.9._abc9_" ===rexify==> +# [0-9][0-9]*[a-zA-Z][a-zA-Z]*\.[0-9][0-9]*\.[a-zA-Z][a-zA-Z]*\a\b\c[0-9][0-9]*[a-zA-Z][a-zA-Z]* +# +# Voila. +# +# To yield the subparts from the string we additionally enclose the +# 9s and _s with \( and \). +# +############################################################################### + +# **************************************************************** +# ** helper definitions ** +# **************************************************************** +m4_define([CS_VCHK_RUNTH], [m4_pushdef([i], [$1])m4_if($1,0,,[CS_VCHK_RUNTH(m4_decr($1), [$2])][$2])m4_popdef([i])]) +m4_define([CS_VCHK_PREFIX], []) +m4_define([CS_VCHK_SUFFIX], []) +m4_define([CS_VCHK_GROUPPREFIX], [\(]) +m4_define([CS_VCHK_GROUPSUFFIX], [\)]) +m4_define([CS_VCHK_CHAR], [[[[a-zA-Z]]]]) +m4_define([CS_VCHK_DIGIT], [[[0-9]]]) +m4_define([CS_VCHK_SEQUENCE], [CS_VCHK_PREFIX[]CS_VCHK_SINGLE[]CS_VCHK_SINGLE[]*CS_VCHK_SUFFIX[]]) +m4_define([CS_VCHK_OPTSEQUENCE], [CS_VCHK_PREFIX[]CS_VCHK_SINGLE[]*CS_VCHK_SUFFIX[]]) +m4_define([CS_VCHK_REXSEQ], [m4_bpatsubst($1, [$2], [[]CS_VCHK_SEQUENCE[]])]) +m4_define([CS_VCHK_GROUPINGON], [m4_pushdef([CS_VCHK_PREFIX], [CS_VCHK_GROUPPREFIX])m4_pushdef([CS_VCHK_SUFFIX], [CS_VCHK_GROUPSUFFIX])]) +m4_define([CS_VCHK_GROUPINGOFF], [m4_popdef([CS_VCHK_SUFFIX])m4_popdef([CS_VCHK_PREFIX])]) +m4_define([CS_VCHK_OPTON], [m4_pushdef([CS_VCHK_SEQUENCE], [CS_VCHK_OPTSEQUENCE])]) +m4_define([CS_VCHK_OPTOFF], [m4_popdef([CS_VCHK_SEQUENCE])]) +m4_define([CS_VCHK_RMOPT], [CS_VCHK_RMCHAR([$1], m4_index([$1], [|]))]) +m4_define([CS_VCHK_RMCHAR], [m4_if($2,-1,[$1],m4_substr([$1], 0, $2)[]m4_substr([$1], m4_incr($2)))]) +m4_define([CS_VCHK_RMALL], [m4_translit([$1], [|], [])]) +m4_define([CS_VCHK_CUTOFF], [m4_if(m4_index($1,[|]),-1, [$1], [m4_substr($1, 0, m4_index($1,[|]))])]) +m4_define([CS_VCHK_CYCLEOPT], [ +m4_if($2,-1,, [m4_pushdef([i], CS_VCHK_CUTOFF([$1])) m4_pushdef([j], CS_VCHK_DUMMY_TAIL([$1])) CS_VCHK_CYCLEOPT( CS_VCHK_RMOPT([$1]), m4_index($1, [|]), [$3])$3 m4_popdef([i]) m4_popdef([j])]) +]) +m4_define([CS_VCHK_TAIL], [m4_if(m4_index($1,[|]),-1, [], [m4_substr($1, m4_incr(m4_index($1,[|])))])]) +m4_define([CS_VCHK_DUMMY_COMPRESS], [m4_bpatsubst(m4_bpatsubst([$1], [__*], [A]), [99*], [0])]) +m4_define([CS_VCHK_DUMMY_TAIL], [CS_VCHK_DUMMY_COMPRESS(m4_translit(CS_VCHK_TAIL([$1]), [|], []))]) + +# **************************************************************** +# ** FlagsOn / FlagsOff ** +# **************************************************************** +m4_define([CS_VCHK_FLAGSON], +[m4_if($#, 0, [], + $1, [], [], + [$1], [group], [CS_VCHK_GROUPINGON[]], + [$1], [opt], [CS_VCHK_OPTON[]])dnl +m4_if($#, 0, [], $1, [], [], [CS_VCHK_FLAGSON(m4_shift($@))])]) + +m4_define([CS_VCHK_FLAGSOFF], +[m4_if($#, 0, [], + $1, [], [], + $1, [group], [CS_VCHK_GROUPINGOFF[]], + [$1], [opt], [CS_VCHK_OPTOFF[]])dnl +m4_if($#, 0, [], $1, [], [], [CS_VCHK_FLAGSOFF(m4_shift($@))])]) + +# **************************************************************** +# ** rexify / sedify ** +# **************************************************************** +m4_define([CS_VCHK_REXIFY], +[m4_pushdef([CS_VCHK_SINGLE], [$1])dnl +CS_VCHK_FLAGSON(m4_shift(m4_shift(m4_shift($@))))dnl +CS_VCHK_REXSEQ([$3], [$2])dnl +CS_VCHK_FLAGSOFF(m4_shift(m4_shift(m4_shift($@))))dnl +m4_popdef([CS_VCHK_SINGLE])]) + +m4_define([CS_VCHK_QUOTESEP], [m4_bpatsubst($1, [[^9_]], [\\\&])]) + +m4_define([CS_VCHK_REXCHAR], [CS_VCHK_REXIFY([CS_VCHK_CHAR], [__*], $@)]) +m4_define([CS_VCHK_REXDIGIT], [CS_VCHK_REXIFY([CS_VCHK_DIGIT], [99*], $@)]) +m4_define([CS_VCHK_SEDIFY], [CS_VCHK_REXDIGIT([CS_VCHK_REXCHAR([CS_VCHK_QUOTESEP([$1])], m4_shift($@))], m4_shift($@))]) +m4_define([CS_VCHK_SEDEXPRALL], [/CS_VCHK_SEDIFY([$1])/!d;s/.*\(CS_VCHK_SEDIFY([$1])\).*/\1/;q]) +m4_define([CS_VCHK_SEDEXPRNTH], [/CS_VCHK_SEDIFY([$1])/!d;s/.*CS_VCHK_SEDIFY([$1],[group]).*/\$2/]) + +# **************************************************************** +# ** Pattern splitting ** +# **************************************************************** +m4_define([CS_VCHK_SPLITSEP], [CS_VCHK_REXIFY([s], [[^9_][^9_]*], $@)]) +m4_define([CS_VCHK_SPLITDIGIT], [CS_VCHK_REXIFY([d], [99*], $@)]) +m4_define([CS_VCHK_SPLITCHAR], [CS_VCHK_REXIFY([c], [__*], $@)]) + +# **************************************************************** +# ** return a list of 's' 'd' 'c' 'e' chars denoting the kind ** +# ** pattern parts: separator, digit, char, end ** +# **************************************************************** +m4_define([CS_VCHK_PATTERNLIST], [m4_pushdef([CS_VCHK_SEQUENCE], [CS_VCHK_SINGLE ])dnl +m4_translit(CS_VCHK_SPLITDIGIT([CS_VCHK_SPLITCHAR([CS_VCHK_SPLITSEP([$1])])]), [ ], m4_if([$2],[],[ ],[$2]))e[]dnl +m4_popdef([CS_VCHK_SEQUENCE])]) + +# **************************************************************** +# ** Build the shell commands we emit to the configure script. ** +# **************************************************************** +m4_define([CS_VCHK_PATCOUNT], [m4_len(m4_bpatsubst(CS_VCHK_PATTERNLIST([$1]), [[^dc]]))]) + +# **************************************************************************************** +# ** CS_VCHK_EXTRACTVERSION(EXTRACT_CALL, MIN_VERSION, PATTERN, PRGPREFIX, COMPARISION) ** +# **************************************************************************************** +m4_define([CS_VCHK_EXTRACTVERSION], +[cs_prog_$4_is_version= +cs_prog_$4_min_version= +cs_prog_$4_is_suffix= +cs_prog_$4_min_suffix= +cs_prog_$4_is_suffix_done= +cs_prog_$4_min_suffix_done= +CS_VCHK_CYCLEOPT([$3], [], +[test -z $cs_prog_$4_is_version && cs_prog_$4_is_version=`$1 | sed 'CS_VCHK_SEDEXPRALL([i])'` +test -n "$cs_prog_$4_is_version" && test -z $cs_prog_$4_is_suffix_done && { cs_prog_$4_is_suffix_done=yes ; cs_prog_$4_is_suffix=j ; } +]) +CS_VCHK_CYCLEOPT([$3], , +[test -z $cs_prog_$4_min_version && cs_prog_$4_min_version=`echo $2 | sed 'CS_VCHK_SEDEXPRALL([i])'` +test -n "$cs_prog_$4_min_version" && test -z $cs_prog_$4_min_suffix_done && { cs_prog_$4_min_suffix_done=yes ; cs_prog_$4_min_suffix=j ; } +]) +CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], + [cs_prog_$4_is_ver_[]i=`echo ${cs_prog_$4_is_version}${cs_prog_$4_is_suffix} | sed 'CS_VCHK_SEDEXPRNTH([CS_VCHK_RMALL([$3])], [i])'` +]) +CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], + [cs_prog_$4_min_ver_[]i=`echo $cs_prog_$4_min_version${cs_prog_$4_min_suffix} | sed 'CS_VCHK_SEDEXPRNTH([CS_VCHK_RMALL([$3])], [i])'` +]) +cs_cv_prog_$4_version_ok='' +CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], +[test -z "$cs_cv_prog_$4_version_ok" && { expr "$cs_prog_$4_is_ver_[]i" "$5" "$cs_prog_$4_min_ver_[]i" >/dev/null || cs_cv_prog_$4_version_ok=no ; } +test -z "$cs_cv_prog_$4_version_ok" && { expr "$cs_prog_$4_min_ver_[]i" "$5" "$cs_prog_$4_is_ver_[]i" >/dev/null || cs_cv_prog_$4_version_ok=yes ; } +]) +AS_IF([test -z "$cs_cv_prog_$4_version_ok"], [cs_cv_prog_$4_version_ok=yes]) +cs_cv_prog_$4_version_ok_annotated="$cs_cv_prog_$4_version_ok" +AS_IF([test -n "$cs_prog_$4_is_version"], + [cs_cv_prog_$4_version_ok_annotated="$cs_cv_prog_$4_version_ok_annotated (version $cs_prog_$4_is_version)"]) +]) + +############################################################################## +# CS_CHECK_PROG_VERSION(PROG, EXTRACT_CALL, VERSION, PATTERN, +# [ACTION-IF-OKAY], [ACTION-IF-NOT-OKAY], [CMP]) +# Check the version of a program PROG. +# Version information is emitted by EXTRACT_CALL (for instance "bison -V"). +# The discovered program version is compared against VERSION. +# The pattern of the version string matches PATTERN +# The extracted version and the supplied version are compared with the CMP +# operator. i.e. EXTRACTED_VERSION CMP SUPPLIED_VERSION +# CMP defaults to >= if not specified. +# ACTION-IF-OKAY is invoked if comparision yields true, otherwise +# ACTION-IF-NOT-OKAY is invoked. +# +# PATTERN literals: 9 .. marks a non empty sequence of digits +# _ .. marks a non empty sequence of characters from [a-zA-Z] +# | .. everything behind is optional +# .. everything else is taken as separator - it is better +# to not try stuff like space, slash or comma. +# +# The test results in cs_cv_prog_PROG_version_ok being either yes or no. +############################################################################## +AC_DEFUN([CS_CHECK_PROG_VERSION], +[AC_CACHE_CHECK([if $1 version m4_default([$7],[>=]) $3], + [AS_TR_SH([cs_cv_prog_$1_version_ok_annotated])], + [CS_VCHK_EXTRACTVERSION([$2], [$3], [$4], AS_TR_SH([$1]), + m4_default([$7],[>=]))]) +AS_IF([test "$AS_TR_SH([cs_cv_prog_$1_version_ok])" = yes], [$5], [$6])]) +# qualify.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_SYMBOL_QUALIFIER(MESSAGE, CACHE-VAR, QUALIFIERS, [SYMBOL], [LANG], +# [ACTION-IF-ACCEPTED], [ACTION-IF-NOT-ACCEPTED]) +# Test if a symbol can be qualified by one of the elements of the +# comma-separated list of QUALIFIERS. Examples of qualifiers include +# __attribute__((deprecated)), __declspec(dllimport), etc. MESSAGE is the +# "checking" message. CACHE-VAR is the variable which receives the +# qualifier which succeeded, or the the literal "no" if none were +# accepted. SYMBOL is the symbol to which the qualifier should be +# applied. If omitted, then SYMBOL defaults to "void f();". LANG is the +# language of the test, typically "C" or "C++". It defaults to "C" if +# omitted. ACTION-IF-ACCEPTED is invoked after CACHE-VAR is set if one of +# the qualifiers is accepted, else ACTION-IF-NOT-ACCEPTED is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SYMBOL_QUALIFIER], + [AC_CACHE_CHECK([$1], [$2], + [$2='no' + m4_foreach([cs_symbol_qualifier], [$3], + [AS_IF([test "$$2" = no], + [CS_BUILD_IFELSE( + [AC_LANG_PROGRAM( + [cs_symbol_qualifier m4_default([$4],[void f()]);], + [])], + [], [$5], [$2='cs_symbol_qualifier'], [$2='no'])])])]) + AS_IF([test $$2 != no], [$6], [$7])]) +# split.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_SPLIT(LINE, [OUTPUT-VARIABLES], [DELIMITER], [FILLER]) +# Split LINE into individual tokens. Tokens are delimited by DELIMITER, +# which is the space character if omitted. OUTPUT-VARIABLES is a +# comma-delimited list of shell variables which should receive the +# extracted tokens. If there are too few tokens to fill the output +# variables, then the excess variables will be assigned the empty string. +# If there are too few output variables, then the excess tokens will be +# ignored. If OUTPUT-VARIABLES is omitted, then the split tokens will be +# assigned to the shell meta-variables $1, $2, $3, etc. When +# OUTPUT-VARIABLES is omitted, FILLER is assigned to meta-variables in +# cases where DELIMITER delimits a zero-length token. FILLER defaults +# to "filler". For example, if DELIMITER is "+" and OUTPUT-VARIABLES is +# omitted, given the line "one++three", $1 will be "one", $2 will be +# "filler", and $3 will be "three". +#------------------------------------------------------------------------------ +AC_DEFUN([CS_SPLIT], + [m4_define([cs_split_filler], m4_default([$4],[filler])) + set cs_split_filler `echo "$1" | awk 'BEGIN { FS="m4_default([$3],[ ])" } + { for (i=1; i <= NF; ++i) + { if ($i == "") print "cs_split_filler"; else print $i } }'` + shift + m4_map([_CS_SPLIT], [$2])]) + +AC_DEFUN([_CS_SPLIT], + [AS_IF([test $[@%:@] -eq 0], [$1=''], + [AS_IF([test "$[1]" = cs_split_filler], [$1=''], [$1=$[1]]) + shift])]) +# textcache.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# Text cache facility. These macros provide a way to incrementally store +# arbitrary text in a shell variable, and to write the saved text to a file. +# +# CS_TEXT_CACHE_APPEND(VARIABLE, TEXT) +# Append text to the contents of the named shell variable. If the text +# contains references to shell variables (such as $foo), then those +# references will be expanded. If expansion is not desired, then protect +# the text with AS_ESCAPE(). +# +# CS_TEXT_CACHE_PREPEND(VARIABLE, TEXT) +# Prepend text to the contents of the named shell variable. If the text +# contains references to shell variables (such as $foo), then those +# references will be expanded. If expansion is not desired, then protect +# the text with AS_ESCAPE(). +# +# CS_TEXT_CACHE_OUTPUT(VARIABLE, FILENAME) +# Instruct config.status to write the contents of the named shell +# variable to the given filename. If the file resides in a directory, +# the directory will be created, if necessary. If the output file +# already exists, and if the cached text is identical to the contents of +# the existing file, then the existing file is left alone, thus its time +# stamp remains unmolested. This heuristic may help to minimize rebuilds +# when the file is listed as a dependency in a makefile. +# +# *NOTE* +# There is a bug in Autoconf 2.57 and probably all earlier 2.5x versions +# which results in errors if AC_CONFIG_COMMANDS is invoked for a `tag' +# which represents a file in a directory which does not yet exist. +# Unfortunately, even invoking AS_MKDIR_P in the `cmd' portion of +# AC_CONFIG_COMMANDS does not solve the problem because the generated +# configure script attempts to access information about the directory +# before AS_MKDIR_P has a chance to create it. This forces us to invoke +# AS_MKDIR_P in the third argument to AC_CONFIG_COMMANDS (the +# `init-cmds') rather than the second (the `cmds'). This is undesirable +# because it means that the directory will be created anytime +# config.status is invoked (even for a simple --help), rather than being +# created only when requested to output the text cache. This bug was +# submitted to the Autoconf GNATS database by Eric Sunshine as #228 on +# 27-Dec-2002. It was fixed for Autoconf 2.58 on 26-Sep-2003. The +# official fix makes the assumption that `tag' always represents a file +# (as opposed to some generic target), and creates the file's directory +# is not present. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_TEXT_CACHE_APPEND], [$1="${$1}$2"]) +AC_DEFUN([CS_TEXT_CACHE_PREPEND], [$1="$2${$1}"]) +AC_DEFUN([CS_TEXT_CACHE_OUTPUT], + [AC_CONFIG_COMMANDS([$2], + [echo $ECHO_N "$$1$ECHO_C" > $tmp/tcache + AS_IF([diff $2 $tmp/tcache >/dev/null 2>&1], + [AC_MSG_NOTICE([$2 is unchanged])], + [rm -f $2 + cp $tmp/tcache $2]) + rm -f $tmp/tcache], + [$1='$$1' + cs_dir=`AS_DIRNAME([$2])` + AS_ESCAPE(AS_MKDIR_P([$cs_dir]), [$`\])])]) +# trim.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2003 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_TRIM(STRING) +# Strip leading and trailing spaces from STRING and collapse internal +# runs of multiple spaces to a single space. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_TRIM], [`echo x$1 | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) +# warnings.m4 -*- Autoconf -*- +#============================================================================== +# Copyright (C)2005 by Eric Sunshine +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; if not, write to the Free Software Foundation, +# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +#============================================================================== +AC_PREREQ([2.56]) + +#------------------------------------------------------------------------------ +# CS_COMPILER_WARNINGS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to enable compilation warnings. If LANGUAGE is not provided, +# then `C' is assumed (other options include `C++'). If CACHE-VAR is not +# provided, then it defaults to the name +# "cs_cv_prog_compiler_enable_warnings". If an option for enabling +# warnings (such as `-Wall') is discovered, then it is assigned to +# CACHE-VAR and ACTION-IF-FOUND is invoked; otherwise the empty string is +# assigned to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +# +# IMPLEMENTATION NOTES +# +# On some platforms, it is more appropriate to use -Wmost rather than +# -Wall even if the compiler understands both, thus we attempt -Wmost +# before -Wall. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_WARNINGS], + [CS_CHECK_BUILD_FLAGS( + [how to enable m4_default([$1],[C]) compilation warnings], + [m4_default([$2],[cs_cv_prog_compiler_enable_warnings])], + [CS_CREATE_TUPLE([-Wmost]) CS_CREATE_TUPLE([-Wall])], + [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_ERRORS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to promote compilation diganostics from warning to error +# status. If LANGUAGE is not provided, then `C' is assumed (other options +# include `C++'). If CACHE-VAR is not provided, then it defaults to the +# name "cs_cv_prog_compiler_enable_errors". If an option for performing +# this promotion (such as `-Werror') is discovered, then it is assigned +# to CACHE-VAR and ACTION-IF-FOUND is invoked; otherwise the empty string +# is assigned to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_ERRORS], + [CS_CHECK_BUILD_FLAGS( + [how to treat m4_default([$1],[C]) warnings as errors], + [m4_default([$2],[cs_cv_prog_compiler_enable_errors])], + [CS_CREATE_TUPLE([-Werror])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_UNUSED([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to ignore unused variables and +# arguments. This option may be useful for code generated by tools, such +# as Swig, Bison, and Flex, over which the client has no control, yet +# wishes to compile without excessive diagnostic spew. If LANGUAGE is +# not provided, then `C' is assumed (other options include `C++'). If +# CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_unused". If an option (such as +# `-Wno-unused') is discovered, then it is assigned to CACHE-VAR and +# ACTION-IF-FOUND is invoked; otherwise the empty string is assigned to +# CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_UNUSED], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) unused variable warnings], + [m4_default([$2],[cs_cv_prog_compiler_ignore_unused])], + [CS_CREATE_TUPLE([-Wno-unused])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_UNINITIALIZED([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to ignore uninitialized variables. This +# option may be useful for code generated by tools, such as Swig, Bison, +# and Flex, over which the client has no control, yet wishes to compile +# without excessive diagnostic spew. If LANGUAGE is not provided, then +# `C' is assumed (other options include `C++'). If CACHE-VAR is not +# provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_uninitialized". If an option (such as +# `-Wno-uninitialized') is discovered, then it is assigned to CACHE-VAR +# and ACTION-IF-FOUND is invoked; otherwise the empty string is assigned +# to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_UNINITIALIZED], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) uninitialized warnings], + [m4_default([$2], + [cs_cv_prog_compiler_ignore_uninitialized_variables])], + [CS_CREATE_TUPLE([-Wno-uninitialized])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_PRAGMAS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to ignore unrecognized #pragma +# directives. This option may be useful for code which contains +# unprotected #pragmas which are not understood by all compilers. If +# LANGUAGE is not provided, then `C' is assumed (other options include +# `C++'). If CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_unknown_pragmas". If an option (such as +# `-Wno-unknown-pragmas') is discovered, then it is assigned to CACHE-VAR +# and ACTION-IF-FOUND is invoked; otherwise the empty string is assigned +# to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_PRAGMAS], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) unknown [#pragma] warnings], + [m4_default([$2],[cs_cv_prog_compiler_ignore_unknown_pragmas])], + [CS_CREATE_TUPLE([-Wno-unknown-pragmas])], [$1], [$3], [$4])]) + + + +#------------------------------------------------------------------------------ +# CS_COMPILER_IGNORE_LONG_DOUBLE([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# Check how to instruct compiler to suppress warnings about `long double' +# usage. This option may be useful for code generated by tools, such as +# Swig, Bison, and Flex, over which the client has no control, yet wishes +# to compile without excessive diagnostic spew. If LANGUAGE is not +# provided, then `C' is assumed (other options include `C++'). If +# CACHE-VAR is not provided, then it defaults to the name +# "cs_cv_prog_compiler_ignore_long_double". If an option (such as +# `-Wno-long-double') is discovered, then it is assigned to CACHE-VAR and +# ACTION-IF-FOUND is invoked; otherwise the empty string is assigned to +# CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. +#------------------------------------------------------------------------------ +AC_DEFUN([CS_COMPILER_IGNORE_LONG_DOUBLE], + [CS_CHECK_BUILD_FLAGS( + [how to suppress m4_default([$1],[C]) `long double' warnings], + [m4_default([$2],[cs_cv_prog_compiler_ignore_long_double])], + [CS_CREATE_TUPLE([-Wno-long-double])], [$1], [$3], [$4])]) diff --git a/Code/Physics/Bullet Source/autogen.sh b/Code/Physics/Bullet Source/autogen.sh new file mode 100644 index 00000000..35623fac --- /dev/null +++ b/Code/Physics/Bullet Source/autogen.sh @@ -0,0 +1,61 @@ +#! /bin/sh + +if [ "$USER" = "root" ]; then + echo "*** You cannot do this as "$USER" please use a normal user account." + exit 1 +fi +if test ! -f configure.ac ; then + echo "*** Please invoke this script from directory containing configure.ac." + exit 1 +fi + +echo "running aclocal" +aclocal +rc=$? + +if test $rc -eq 0; then + echo "running libtool" + libtoolize --force --automake --copy + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +if test $rc -eq 0; then + echo "libtool worked." +else + echo "libtool not found. trying glibtool." + glibtoolize --force --automake --copy + rc=$? +fi + +if test $rc -eq 0; then + echo "running automake" + automake --add-missing --copy + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +if test $rc -eq 0; then + echo "running autoheader" + autoheader + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +if test $rc -eq 0; then + echo "running autoconf" + autoconf + rc=$? +else + echo "An error occured, autogen.sh stopping." + exit $rc +fi + +echo "autogen.sh complete" +exit $rc diff --git a/Code/Physics/Bullet Source/bullet.pc.cmake b/Code/Physics/Bullet Source/bullet.pc.cmake new file mode 100644 index 00000000..c5649d58 --- /dev/null +++ b/Code/Physics/Bullet Source/bullet.pc.cmake @@ -0,0 +1,6 @@ +Name: bullet +Description: Bullet Continuous Collision Detection and Physics Library +Requires: +Version: @BULLET_VERSION@ +Libs: -L@LIB_DESTINATION@ -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath +Cflags: @BULLET_DOUBLE_DEF@ -I@INCLUDE_INSTALL_DIR@ diff --git a/Code/Physics/Bullet Source/bullet.pc.in b/Code/Physics/Bullet Source/bullet.pc.in new file mode 100644 index 00000000..ffcd4f36 --- /dev/null +++ b/Code/Physics/Bullet Source/bullet.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: bullet +Description: Bullet Continuous Collision Detection and Physics Library +Requires: +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath +Cflags: -I${includedir}/bullet diff --git a/Code/Physics/Bullet Source/bullet_logo.png b/Code/Physics/Bullet Source/bullet_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a1b4b5588fbed303a9a15051b560a26af5dde2 GIT binary patch literal 3380 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 KMNUMnLSTZl?!Ko0 literal 0 HcmV?d00001 diff --git a/Code/Physics/Bullet Source/config.h.in b/Code/Physics/Bullet Source/config.h.in new file mode 100644 index 00000000..11b564d0 --- /dev/null +++ b/Code/Physics/Bullet Source/config.h.in @@ -0,0 +1,113 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Architecture is PowerPC */ +#undef ARCH_PPC + +/* Architecture is x86 */ +#undef ARCH_X86 + +/* Architecture is x86-64 */ +#undef ARCH_X86_64 + +/* Use the Apple OpenGL framework. */ +#undef HAVE_APPLE_OPENGL_FRAMEWORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GLEXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GLUT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GLU_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GL_GL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Platform is Apple */ +#undef PLATFORM_APPLE + +/* Platform is Linux */ +#undef PLATFORM_LINUX + +/* Platform is Win32 */ +#undef PLATFORM_WIN32 + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif diff --git a/Code/Physics/Bullet Source/configure.ac b/Code/Physics/Bullet Source/configure.ac new file mode 100644 index 00000000..3e9780b8 --- /dev/null +++ b/Code/Physics/Bullet Source/configure.ac @@ -0,0 +1,172 @@ +#---------------------------------------------------------------------------- +# Autoconf input script. Invoke the ./autogen.sh script to generate a +# configure script from this file. +#---------------------------------------------------------------------------- +AC_PREREQ([2.54]) + +#---------------------------------------------------------------------------- +# Initialize Autoconf. +#---------------------------------------------------------------------------- +AC_INIT( + [bullet], + [2.82], + [erwin.coumans@gmail.com]) +AC_CANONICAL_HOST +AC_CONFIG_SRCDIR([configure.ac]) +AM_INIT_AUTOMAKE +AM_PROG_CC_C_O +AC_PROG_CXX +AC_PROG_LIBTOOL + +case "$host" in + *-*-mingw*|*-*-cygwin*) + AC_DEFINE(PLATFORM_WIN32, 1, [Platform is Win32]) + opengl_LIBS="-lunsupported_platform" + PLATFORM_STRING="Win32" + ;; + *-*-linux*) + AC_DEFINE(PLATFORM_LINUX, 1, [Platform is Linux]) + opengl_LIBS="-lGL -lGLU -lglut" + PLATFORM_STRING="Linux" + ;; + *-*-darwin*) + AC_MSG_WARN([Hello]) + AC_DEFINE(PLATFORM_APPLE, 1, [Platform is Apple]) + opengl_LIBS="-framework AGL -framework OpenGL -framework GLUT" + PLATFORM_STRING="Apple" + ;; + *) + AC_MSG_WARN([*** Please add $host to configure.ac checks!]) + ;; +esac +AC_SUBST(opengl_LIBS) + +case "$host" in + i?86-* | k?-* | athlon-* | pentium*-) + AC_DEFINE(ARCH_X86, 1, [Architecture is x86]) + ARCH_SPECIFIC_CFLAGS="" + ARCH_STRING="X86" + ;; + x86_64-*) + AC_DEFINE(ARCH_X86_64, 1, [Architecture is x86-64]) + ARCH_SPECIFIC_CFLAGS="-DUSE_ADDR64" + ARCH_STRING="X86-64" + ;; + ppc-* | powerpc-*) + AC_MSG_WARN([HI THERE!]) + AC_DEFINE(ARCH_PPC, 1, [Architecture is PowerPC]) + ARCH_SPECIFIC_CFLAGS="" + ARCH_STRING="PowerPC" + ;; + *) + AC_MSG_ERROR([Unknown Architecture]) + ;; +esac +AC_C_BIGENDIAN + + +#---------------------------------------------------------------------------- +# Setup for the configuration header. +#---------------------------------------------------------------------------- +AC_CONFIG_HEADERS([config.h]) +#---------------------------------------------------------------------------- +# Package configuration switches. +#---------------------------------------------------------------------------- +AC_ARG_ENABLE([multithreaded], + [AC_HELP_STRING([--enable-multithreaded], + [build BulletMultiThreaded (default NO)])], + [disable_multithreaded=no], [disable_multithreaded=yes]) +AC_MSG_CHECKING([BulletMultiThreaded]) +AS_IF([test "$disable_multithreaded" = yes], [build_multithreaded=no], [build_multithreaded=yes]) +AC_MSG_RESULT([$build_multithreaded]) +AM_CONDITIONAL([CONDITIONAL_BUILD_MULTITHREADED], [test "$build_multithreaded" = yes]) + +AC_ARG_ENABLE([demos], + [AS_HELP_STRING([--disable-demos], + [disable Bullet demos])], + [], + [enable_demos=yes]) +AM_CONDITIONAL([CONDITIONAL_BUILD_DEMOS], [false]) + +dnl Check for OpenGL and GLUT + + +case "$host" in + *-*-darwin*) + AC_DEFINE([HAVE_APPLE_OPENGL_FRAMEWORK], [1], + [Use the Apple OpenGL framework.]) + GL_LIBS="-framework GLUT -framework OpenGL -framework Carbon -framework AGL" + have_glut=yes + have_glu=yes + have_gl=yes + ;; + *) + have_gl_headers=yes + AC_CHECK_HEADERS(GL/gl.h GL/glu.h GL/glext.h GL/glut.h, , + [have_gl_headers=no], + [[#ifdef WIN32 + #include + #endif + #if HAVE_GL_GL_H + #include + #endif + #if HAVE_GL_GLU_H + #include + #endif + ]]) + have_gl=no + have_glu=no + have_glut=no + TEMP_LDFLAGS="$LDFLAGS" + AC_CHECK_LIB(GL, main, [GL_LIBS="-lGL"; have_gl=yes]) + AC_CHECK_LIB(GLU, main, [GL_LIBS="-lGLU $GL_LIBS"; have_glu=yes], , -lGL) + AC_CHECK_LIB(GLUT, main, [GL_LIBS="-lGLUT -LGLU $GL_LIBS"; have_glut=yes], ,-lGLUT) + AC_CHECK_LIB(opengl32, main, [GL_LIBS="-lopengl32"; have_gl=yes]) + AC_CHECK_LIB(glu32, main, [GL_LIBS="-lglu32 $GL_LIBS"; have_glu=yes], , -lopengl32) + LDFLAGS="$TEMP_LDFLAGS" + if test $have_gl = no -o $have_glu = no -o $have_gl_headers = no; then + if test x$enable_demos = xyes; then + AC_MSG_WARN([Demos and Extras will not be built because OpenGL and GLUT doesn't seem to work. See `config.log' for details.]) + fi + enable_demos=no + else + AC_MSG_NOTICE([Found OpenGL]) + fi + ;; +esac + + + +AC_SUBST(GL_LIBS) + + +if test "x$enable_demos" != xno; then + AC_MSG_NOTICE([Building Bullet demos]) + AM_CONDITIONAL([CONDITIONAL_BUILD_DEMOS],[true]) +fi + + + +AC_ARG_ENABLE([debug], + [AC_HELP_STRING([--enable-debug], + [build with debugging information (default NO)])], + [], [enable_debug=no]) + +AC_MSG_CHECKING([build mode]) +AS_IF([test $enable_debug = yes], [build_mode=debug], [build_mode=optimize]) +AC_MSG_RESULT([$build_mode]) + + + +CFLAGS="$ARCH_SPECIFIC_CFLAGS $CFLAGS" +CXXFLAGS="$ARCH_SPECIFIC_CFLAGS $CXXFLAGS $CFLAGS" +#---------------------------------------------------------------------------- +# Emit generated files. +#---------------------------------------------------------------------------- +AC_CONFIG_FILES([bullet.pc Makefile Demos/Makefile Demos/SoftDemo/Makefile Demos/AllBulletDemos/Makefile Demos/MultiThreadedDemo/Makefile Demos/OpenGL/Makefile Demos/ForkLiftDemo/Makefile Demos/FeatherstoneMultiBodyDemo/Makefile Demos/BasicDemo/Makefile Demos/CcdPhysicsDemo/Makefile Demos/VehicleDemo/Makefile Demos/TerrainDemo/Makefile src/Makefile Extras/Makefile]) +AC_OUTPUT + +AC_MSG_NOTICE([ + +Please type 'make' to build Bullet +]) diff --git a/Code/Physics/Bullet Source/convex0.bin b/Code/Physics/Bullet Source/convex0.bin new file mode 100644 index 0000000000000000000000000000000000000000..83493fca3834f02b26c09a25e2a5d77f515bc876 GIT binary patch literal 548 zcmY+ADNhA46oor8ovoRDGZ;`95*G8!n>IKc{{TmVCt*nt!w*0}o$qIttJ4 z0D>a~6!-SEq15#B&guD1rz2_&)1NO1YPeuij(T=*&hdm62Hi)L^G^sƒ—ª±·ÁÏÞÛ˹§Žvqttsh\ZTLC;49DIRSF>52449:?Jex† ¯ÅÒàææããàØÌ»­œ–’ŠŠyt‚u²œ‹xiYOC?KORm|x€zƒ‹’ž§µ¼¾¹²®¤ŽlWJSljWB/#',162-6CVl|”¬ºÅÊÑÜÜÊ°¡˜‘‹‘€ohlocQG;8?FROD=2284**:Lgt}¤²ÅÊÕÛßÕÓÑÌÁ°©«¦™†ŠƒŠ|x‡„ȳ¢ ›‡k^UMN_km}‹‘Œ„Œ‘’–¡¬·±«©ˆjULPb`T>% %(('(,5DP\q“¯ÀÌÐÕ×Ò¼¤ž£§¡›š•‹}€qTF8.0;6,+'""(-,,0:F@>AGO]o€‘­ÂÏ×ÑÌÉÁ´¶ÇÐÉþ·¯Ÿ‹}jP;,%! +:ALLKOU^krr‡Ÿª®©žys~•¡´º¾µº¾¿ËÓÜÔÀ¢ôôôïåÚÑ××Ð×ϼ¦—„mXXdg^Q[R>6329CE6*+*+)(#"!##'-5>IONHBGQj‡ž­¼ÄÍÌÊʼ´¸ÆÎÈÊȾª‚yiM6(## +?Nfƒ™¨·ÁÊÁ·µ±­°¿ÇÀÅËÁ¯ŽzucC+#$$!%4CGFFO`kmgdduƒ—¡”‡†€…‹—«´¸»ºÁÁÏÕÚØÏ»¯ûûúüûîçäààÞ̲Ÿ“yhWRORM:76(""$!&"!# %/1389DNQTLA>AWo†™¤®¸²²²¦¡¤¯µ­°·µ¦…qiW?+$%##$).?HEFNehffebsˆ”‘ƒ…‡›˜ª·¼¹ÄÏÏÓÑÓÐ̼³üÿýýü÷öñëåÚħ™€iWMOIA.&$ &-49?>CVbZPE=AGO^aghkmpxz|rou‰“¥¬¤¢­¾ÑÜ×ÎÁ±¬°®ìõùöó÷üöìØË·¥š™“qO;20*#  + (2?GP_noi_XZ]nvrx€ž ›­ÌÖÑÉÿ»°ž–“‡rk]L9##(.:@BIU[^qsmipwz~}vot~…’Ÿ¨¨«²ÂÔÜÐǺ¯œ£ãñôñêòöôåÏŵ¦›˜…mG0*# #+6DIRciid^bgqzvx†“Ÿ¡¤¼ØäæâÚÕÏɳ–Ž‰yi]RE-#,9CJJLTVZmppt~yyxrjir}Š›¥¯§¯ÃÎÕÏÀ¨›‡…ŠÍäêæàåæßÑËÀ´¤˜“~^C2!  ##(+07ARac\^cnzŠ’”“ž¨·ÊßèéëìåßÖ½œŒƒxl`RJ6 +1@GF;7:DLT[kpnpsund]cjl~”°¶¯²®¡Ž~wtoh¢¡®°¼º°¬¬£ª¡|vqeG*  +&8;1,/;JP[jqpt•§©ªª¯¶¯«·ÅÌÕÞÞÞáÚË°šŽˆˆrWHD7&#.78;=@B>658DIJY[dqpfhd^f`_i€› ¤Ÿ‚tikopŒ‹–›Ÿ¤œ™•…Ž‡vc^ZM;#  %4:979?O]`fnq}ŽŸ°·²­®©©¯¸ÄÒÙÛÛÚÚÒ¿«š“‘…~mVLF9.-16>?CFDDLKE?7:@BNRWa`emk^bZXYpŠ‘•‰vupjgi|x…€…Š†„zmabaTJE=9#  + + + (4<7GJJJKGFQSPD9?CGAIS]`jo_URMRVat…’tpefjuxw~yxx}|vshVLNPIA?=9$    "6B=AKRY^gqx…—±ÃÊÎĪ £«ÀÎÎÌÏØÜÍ¿³¬¦‘|ptnSA8;DMTY^\TTU[[ZM=DLOKV_a^bZQECIMONZu‡whgddnplqwpqt{ypj\KFA?:59;6$ %$)39?JTYVX^en ¼ÄÌÖÒ¿²«°ÄÎÐÍÌÛàÕÁ®•…ulnoYD64AO\gkhc]cjoiYDDNTZ^__QKHF<;AJNJ\jri]cjjpjaikhemxsujRBB=5-,.8>,!#-2/*+-10$".03AKNPKOY]g‚¡»ÂÐáàÓdz¬ºÄÊÑÔÖÖϲ™“”‡qimf]O?:HWdrvumkqolkXJOUWa[U[JFC>::=IEGXeqnhqmntrfc[XTYelniPG<91*,*387+%2<;5234981)#!!,206CONE?ALQ\v—°¼ËÜàÙÒ¿®­ºÃËÕÐÌÆ»«š’„posj]QHKbszƒ„Š†~xwvm^RXZ^`ROOJG@56AEFVbmbNB:81)*146>9++.-2DD96424:9872.-398?MXP>9?BGZu‘§²½Í×ØѲ­µ¼ÈÎÄÀÅ»¯›†uorj^SVbt‹“Ž“–‡‚‚}g][\fc[YRPOE13;ENT]\Q?6;=1)-;MUO@:@IVXX]VL=4435NqŸ¬¯¹¼°±¸»º¹¼ÀÄÄƾ°­¨¡ ˆyokegyš¬®¦œ‘™œ˜››‹vwwtxƒˆ~sab^\e]bf_[ZaT\fn{xok]Q(5:FVWSRNSOMDCJSSQOWU[ZZQKGFD83@QPOJEOV]Z`\QA620.0Gi†–Ÿ¦®©›’ž´»¹··¼ÁÀ²ª°µ´²¥—ƒ}{|Ž­º¶³«¡›œ¢§¡’‹€ƒˆ™—ˆqnkh_[ffbWQ\bifhnha_ZM$+8BCMW[TSWSLEJRVQUW]akaVXURQRJAJURONNVX\Y^bT@3322;Ni}†™˜’ˆ€Ž¤®¯««µ¸±¯®±µ¸µ§–”••™¢¸ÉÊÆ»µ š£¬§œ•Œ~‚Œš¡£˜‹{~xkZ^hf^XWcwp``]YTPUQ27?EJU\[W\``ZNNV_]`ceim__gjii`_XW]^XWZ``_^YXUOEFB=KZiux}}y{‚‚‰š¥¦¢§°±®°°¬«°ª¡œ˜™£©«¯½ÑÛâÙÊ®˜“›™‡€}}Œ’›¥ œŒ„‚zmph^^fot‹‚h[PPNNUP?DIO]e`aefjjhZLO]kmoljgkty…†~xg`bfb_cec]YJGIKKPMCJ^ikilifp€ƒ…–›˜˜£««© šž¢ š›Ÿ£±¾ÄËØäêèÖÁ¤•Žv€‡Ž‹Šœ«²¹© ™|qg^grvyw]IELYRRHHS[ipfquntmncRJYjqrslfvŠŽ“–˜Ž€oefjc_bXJA866J[nqk\R[gv„‰‰‰‘’†€Ž––›Ÿ°ÉÞæåêõóòéÕÁ§Žˆ‰“Ÿ¢¦®§§¬·¼»½¸¯¦…ldXKRS]s……{u~njffkz‚‹ŒŠ–•ƒugSJRW\aklkw|Š“¢¯º±ŸwjfkhWE8,""''-3006849BR`a`[RQ_wŒ”ŠŽ™–“‡y~‰¦¬ÄÖÛÜçôøñçʸ¥„†—¥©«¬¨ª±¶¿Åľµ¦|mdSJFUm‚€}||wyx\h‡•ŠˆŒ–ž›‰ql]MAFGQX\]kt•©¸Æ½«šŠ}qjcSFC1#"" "$+1.48604CNRRQPOZrˆ•”™¤Ÿ~njvžŸ£µËÕ×ãñ÷íÝ̽©•ŒŠ™©¬¤ ©¯´¹»ÄÄÇÆ·¥m\NN^n{{|}‰T^{‰’“•–œ¡zoreUIA=FMOTgu‡š³ÂÇż¬ ’|nbRLH6" $+-475106;@?@EHWnƒ“–œ¥Ÿˆwqgp‹—™¢²ÅÓÜæïòèÒÉø¦¥¡¤´®Ÿœ«²¯³¸ÅÆÇɽª’…w\RS`r|ˆƒ~y‚–`ezš¤¯«ž›™†zynm`OFCIJJP`|—¦»ÆÉÐÍÅ´œ€scUTL<,$"#,104;;6:;9;@EC?F½±¥–ŒˆŠˆŒ†ƒ•”œŸœ¢¨§«ÃÖÕÑÏÕßÜÙÎÎÌÏÓÔȱxme\O<7119?6.+))*,.009KZ``fmvƒ†zux{}¤£¦¸¹±²´®¦¨§¤›———‡wqz†‰ƒ†Ž’•šxp_XbYI:;@@:<:;BD?<½®¨šŠ~uz„ƒ~‡”Ÿ›¤©±¶½ÓÛÚ×ÏÐÜåçÜÙØÒÕÖɬyhYJA;3/2>@6.*'&$%*.2>S`dcer{xvzwuxƒ†š­±´´½Á»¸¹²¦˜› ¢ —ŽŠ‚ƒ“Ž‹‡‰‰{gd^WZUL>?>CDEEB@AA9°¨¦”€qq{yy~˜¤§¶¾ÄÊÐÞçæáÜÛâíòêáÙÑÖ̸™…vdQ@84--8>;4,(%! '/8CTiupmq|‡~rpptz‰‘¨¿ÂÊÎÌȾ²¯¯©˜–™ž¨¤“’–¦Ÿ›‘‡‚…zkXITVXOJ?DBKMNOMC?=9ª¦¥£œƒxs}xy€œ¨´ÁÈÑÕØãçìîììñõóìâÜÔÌ»©˜…ycG9/(#(7B:1,&$#(08GVk†‚‹‚oefo~‘™³ÉÎÓÚ×ÌÁ´ª©§™•›Ÿ¦£šŸ¡¨®¨§”ƒ{xgWE:DPUQMFEEOSSXVNGCEµ´°­ ƒy|„ˆˆŠ‘¦­»ÉÏÕØáéèñ÷ôó÷óëåÝÜØÊ°¡™†zb=.*%&&2B=53/+*1:FWgz‰˜š”Œ†‚vgeu‡‘›¨½ÐÙ×ÕÎĽ¼±¦¡•‘¡¥§¯²¬«¯·­¢¤—†vk]O>92/))&2DF;;;717BOd}‘ ©®¦–†~xnm|‡‹–¨ÁØÞÖÍÁ¶¶»¸¯¨œš¦«±¼º²®¹»®›”˜ŠxbXVJCDGPZUUZPLS]^PDKNX¹Èȳ¦‰…‹”””›«¾ÍÙÚÙáñïïõôéìèÙ×ÕÛÙDz–‡sWG;63-('7LM;48>:=IVlŽ§´µ¸¾²¡—Š„yqr|ƒ‰–®ÇÔÑɶ­¯°½À»­®»¾À¼±­©°·­–”‹w^SRRMKV][TZfeZWYXLELRXª·Ãƾ°™‰‡ˆ‡‘š«¸Ç×åæéñðïñìÞÜÚÌËÈËÌ¿­“v\G=772.+-:NN=36>=>N`xš±ÀÇÈô§›•‹vlou{‚‘ªÀÅ÷­ª±¼ÄÇÂÈÏÒм¥™œ§ª¤™‡}m_QLQ[^hifbgnvhZUTQOUYZ­¯´¹µªž…€‚”¨°ºÍáðõõöõðìä×ÑÎÁ¼¼Âǹ¢ZG:5350002>OQLDABDJ^u‡œ°ÄÊÅ·©šŒ‹†|vsqrx€‚•¯ºÀÀµ°¸¿ÈËÐÒÑÕÒº¤˜Œ™£¢~l\YRKOcpmhnqr{yhYXYTY\`dú®¨¢˜‹~u|‚—«¯½Îçô÷öôöðçÚÓÎÆ¿¸ºÅÅ­’kJ<5-)'&-6=EOVWOOSY_u‹’™¬ÀĶ¨‰„}{xyunr€…™³¾½µ´¿ÀÅÅËÌÈÇõª¢Œ–“‰yeRVVPSjwnfnw||l^aZRVXjoÎö¢““‘ƒyos™©±½ÏãïòðïóêÝÊÉÅ»¼»¿Á¾žxXD0+%!+@JLT[]YY]ir‡œ¢¢ª¸Ã·§ž“‡vrtxwrr}ƒ~ˆ¢¬°³´¹·´¹»¾½¹°ª§Ÿ“ˆ€‚ƒ€o]U^XZhx~~ywz€‚}ug_PNMUqpÇ·¡Š…†}utu–©±¼ÐØáæîðìáÓÅÈÇÁ¾¾½¹´—kP>,$$.=LYbfijiqˆ—ª°¯±ºÄ­œŽxpkktvv{}‚†|Š–¥°°«¥«±²¦˜•š—•‹wnof]UZc^dv{‡‰†‰Žzn^QGIPWmp¹²­¥”€}€ƒ‹™ ©´ÂÆÐÝìóíßÏÄÇËÌÈ¿»³ª’nUE4&)29J_hgmv€Ž”—¡­´·º¿Äų–‚m]^iqmhu„{uw{‡—§¦—‹‘ž¨ª—„†‘˜˜€scRR]glhemxŠ™ƒ‡t]JDCIU_pj¢•˜¡‰Œ‰‰‰‡Ÿž£¯±´ÁÕâîëÛƾ½ÃÈÆ¿¼±¤‘vcVE/+18FU_gmw†–Ÿ¡¦ª­®±³¸¿³—~iRP]d\S_prtolpw†ŒŒ~€Š”¡˜€€Ž”’ŽŠiTXiqsne`tŠ“’ŠshmdKDJ[mwrou~†‹“ˆ}}‹Œ•Ÿ£«¸ÇÔÚÜÑƽ»±±Ã¿º²¢Š}ujY8))127?CTdjy‚ˆ”š“˜››£ª¨«¬qP<9<=91>Ykkgehec`]Y]hs~‡~~‡‹†|pkcflhjwworz}zl^QB8458DZq}|]eŽˆŒŽ}mp|…Ž’•š§¸ÊÖÒÐËù¶¸¿º³§•„}uthJ3.9<>FLSafw‡—–“–•¥´¶®¦™…a=./121.9Sbfb\ROWXPIK[jdcgqxvsutttupeYWees„wwtoi]IJFA86F_r{VWr‹‘‹†‚n\`lx„“™¬ºÂº¿Ãº¦©´°¯§›‹†„nX?6>AAJW]enŽ‘‹‹“›¬¶·°¢˜€\>005534:@NZXQFHNNGA=?@K[msx‡‘“’ŽŠ†Œ™©´·±¡‘qTF=::720/081+-.17>>843-!#)./.489@CJTSJGWksxƒ†˜ ª¯­¡“||we\TPLUYZ\dBSdo„ƒkO:=EVn}|‡Š„{ŠŠˆ…{mdcgkxqmp|…‚wbPLIGS^femzvy‚‰‡„Œ—¦¯¦vbXOCFA96240**+&$$$" *50/4BVZVUer|”™©¯®»¸¨›‰Œˆo`RIGIPZ]d?LVcy~|p\JAKXm}„„}~…ƒ„ƒ€teXQPU^ZVYcw€}m`YTV[\`]aq{vutu}}€‡Š—Ÿš‰viXMGD>9><60%#./'-?TZ]_m‡Š›©´³µ½¹ª–‹€€iVGD@@IY]`=JUanfkgdUCHRcuƒƒyƒŒ„…‚uhXODEHGKLPSas}rkjddkigc^eywmc\ivƒ|ƒ’ŽqhWKJKH@EB8/' '+$*CX\`jt’—˜¥»Ã¼¾¹´§}pjm^F?<8;DTYa;FVaaW\dcTLFMYn|Œ”ŽƒzhXLKIIB74>ISYb:AO[STU\^[YOVZo|ŒŠ‰~uobMAEPO=8@FHJHLYnyzy€€{ofgoxxpjt}~|xtssn`ZYY\\]WKH7(#!%!!'-/:BMZahvv~•£¸ÆÅ÷¬®šƒskgXWKD<7DKP]b>GGKGMMN[`aac`s‡ŽŽ}th]M>CKH?7=C=;9BPe{Š‹‡zpfgv‡ŒŠ‰ˆ‰€|tf^_c_VX^cc\TKF8'"""%%(*/-*+00=>CKZdchhcy’”œ•}zk[SJFC?>9:?64;CVk›© ”Š}umsŠœ¡Ÿ˜’pmaTSW[Z[bbdcYQG8*'.+" !(*+.320/17>@FQ]fibY^lx~œ²¸²©¨Ÿ‰yaMITYVMSQLORd~AGC?<;FSbjiidj”™šž •{vi^YMD>;713/0:I_o—¥¢œ–…yux¦­ª¡—‚siYLINZbhrqkig_SH;8;40.(,63684028DLNPbmmmjajigj€­±¦ž„zcPOPPKGKKGJPnGEC<;HV_bdmg[hwŽš›¤œ“‚uy|riXL@7,'&$'7N`l{’œ˜‰|t€–®»´¤„‚udYOKNVanz€|sppgVLOKHE=2,349?>:?AFHHSq}nnxz{tkk{¢¨•‰€qhYRNJDGGH??>GZ_aclmaR[_yŠ‘›š’€w}~ri_N=/%! 2Ofov‰Ž‡†€zŒ¡³¿· ˆ}yk\XVURYbm{„‰…}}saY_\WUN>114;HPKLFEDJ[x…}w„…zzywuˆ˜—•†wmlbPONRPMI;5Fhy;:=GVacelqdWMNPc}”š¡›…†‚vleX@8/+ -Gemn~„‚ƒ‹‡ƒ’¤·¼¯œ‘…~t_W\_Z`l{‡Ž‘Ž†yrkhge_WL?8?N][Vgyƒ†Š…z…ymZL7*" !)4IVfkls‡Ÿµ³ŸžŸ¢¶Ã¶¢£«§œ“–‰‡ƒƒ‰‘››’’…Š’“‰xl[LKRfyŠ’‡…††„ywsivuyxh\WYahoz„…Ž“”œ˜‚geffkgkoa\2-'!#)/9JYddt€ˆ†|ndcikfleVB,$ $')0=CIFET^USNC:31.--.4@JXk{||z{‚‰’•ŽŠ‹“˜‘˜–”™§®°·³©¥ž–˜¡¡¤§¦¨­³­ž˜ ««³µºÆÄ·ªŸ‰{phqkbbuynrƒ‘‘‰‚ttt}†Ž”–™†„}|ƒ~E7$""$,@IIBBD=756:AJNIJFMJG:)**%&/7>E]t€‡„€ƒ~{…‹„|‡ž¦™“š–•¦¬ªª«¦œ•‡‚Œ––™¢§°º»ª›¡«ª©²½À»°ž’vm`aeahs{y~Œ—˜˜‰qnow„ˆšŸ™ŽŒ””‡E4'*(!&6<91.30/*./6=IFC?DJJA,++''+37A]t€›™‘Œ‡‚|vxyƒ—¤§™’Š–¥©§£¥¤—€zˆ—•–¢¦­¿Å² ž¨¨§±¸¹¸¬ž|pdYV`[gr}†‡Ž’•šƒigiou€ƒ‹ž«£ž–œŸ˜‹G=73.)$#'(--&&'&'#(*/0?AA@@FF?2*+&&)08Har“œž—‘ƒvru|Š”œˆŒ“—¥§¢¡ ˜„‚—™¢¬§ª¹À´¦£¥ª¨­³¹¶£š~j\TT[\cn~Š‘•‹‰ydZZ^bp…Ž›­°µµ®¥ž“SOK=1/+#'('$#!")-/:>KXkz††……yu|€ˆ‘’Œ‚”¢š’œ¢Ÿœœ™‹’œ©´¶¨©¶¿À··»¶´¸º¾¸ž”‡ucWSMP\fp†•›ž’‚uldVTWT`vŠ“¥´ÀË»´­¦bZYE3.,*)+'&.0575=CE=?935;CM\bm{€Œƒvmrypmt‰‹„ƒ…†ŸªŸ˜¢¥ ž§© —•›¨²»º°±¹ÂÍÏËÊÃÀÀÇÇįžŽ}nd^ROXesŽ™¡£’}kbZSQTYVj€Œ—§ºÆÅ¿½¸iZZI50,*&&#!(,.*-;ORPUNLFO]gvx‚†•‡ukpqljmwyropx…“¢­¤š¢¬«¯«Ÿ”‘‘™¬·»»¿¾¿ÎØÜÔÈÄÈÄÊÉÍðš‡viddV\ev‰–£ {h_XOPQZ]mzˆ’Ÿ¸ÅÈÄËÅaMMD<3,# #%!!3R___abcmx~†‡‡‰‡–Œxozypgdilc]_i~Š•¤¥›š¤®±¦œ™›˜œ­ºÀÁÉÏÕååäÝÒÊËÆÇÐÐÌÀ®{nii`[Zf–‹n^\QKNW\ju€‰˜¢µÁÇÈÌÈQFA<9/#  .MZVWcl•“•‘‘”–Œ~y{ue[Z]^[[jx¤”¤£¡¡œŸž «¸ÀÇÓÜçñêèäÞÝÒÌÎÓÍû®•sod_SN]nv|unbTMDANZcyƒ™Ÿ§«¹À»·I;2+*#  +,GOLTj€›­§›”‘“–•¢™†‚ˆvhXQRVYiw{‡“‚‰Ÿ£•’™¤³¿ÇÍÖÚâéââåæéÝÒÐÐʺ³¦ŽulibZMEMR^a_bd[OIEN]q€Œˆ” ¤ž–ž±«¤F5.# + !(2AJQ`¢¹É¾±¨ž˜“˜Ÿ©¦ˆ‘‹wdQNMRery|†‰yz–¨Ÿ”Œ’¡³ÁÈÈÎÖÜÚ×ÙäîíàÕÌÍʽ®ž‡qg]VTJ<=HNKMM[_TPLPcs‹•œŸ¢ž–˜žŸ¢>.' "+6>FOXpš·ÈÚÛÏü¬Ÿ ¦®«›¢™Žƒr_TJGR_hnw‚ƒ~z‰Ÿš‹Šˆ¢²¼¾½½ÂÇËÑØáëçÚÍÁ¸´¯¡“}jb[OHE96=?B?=FQOQQVlw‹—¢§¤«¡––—7-"   ,4>LMZl‰¦ÃÔäæÚÏË¿´­©±·³¬¦˜ˆ}viUMHADTejmpxv€’…}„Ž£²·¹º·¶¸¿ÉÔÛÝ×Ç»®Ÿ––eSNMA=?<>657732@KNXan¦±°°³£•“•+% +!19AJQa‚¯ÄÔßàÓÓÐÇÆ¿¹ÃÉĵ ™—„wpaWPJA9AQWQQ\\dqztkvŠ ­µ´¸¸±¯²¸Æ̼µªš–Œ€xviP?><>=@@E:31.+.8CMUbwˆ“¡®³°­±©ž˜›Ÿ&  + ,7@IHUj‚¡¸ÆÉÓÜØÖÕËÊÍÓÜÛÒ»¥Ÿ’yfjcQIG>6>HE@AEFM[b]Zi„£³²°¶²£œ› ­«›–‹ƒ…~wiYH:143AJEBE?761/*1>IW_w‡‘™¦«¨¦¬­¦¥¯±' + + +  (1BQRWg}š·ÊÌÓÜãâà××ÕÜèßÔ¿¦šŒxfh`NE?:8?BA<:417?BKPZxœ²¹»¹±©›“™Ž‡pnuoieSC7,+3>EKLH><;2/++=Q[fuˆ“ž§©¦¤¬ª®²º-   "&/@Wdhl}”¸ÌÐÔÛîïìëèäçãÙÓĬ™qmeXLC:68=><4*$''&1DWo¥¶¼±§£•ŠzrodXVWUXZSH;,,55:LYQCA?520-DZbk…‘§¦ ¤««¯²°³¸6"  +  $*3IWfx{|®ÀÈÒàíïññìëéßÚÖǵ¦–‰{weO?2.2675*$7RlŸ©£”†xk[W]VNH??C@??1)'.38EVSCA93-.3G`rx‘©´º®®¯¯¼½²µ±E2&   $0;GVi}~‡“Ÿ«½ÆÛêòõóñîçáÜ×Í»¥—ŠrbPD7.,**)#+BUez‹”‹†ƒufZIAIK?407=967*!$(-9M^VI;,'$,9Tu‡‘¢§²¼Ëĵ¬ª»¸³»ºT?,$+.2?MQ^vz„’œŸªµÄÚìñôðíéàÛÔÓ̺¢”Œ‡ocVC0),*'!-9Mgv€zjdhaK?<=?6,&+145+ (09N]UH8+%%(6_{¦¯¹ÀÅÎÎƶ­¼½¾¸ÄSE1!"-:?CCGX]esŽ¢³´¸ÁÍáñîïçãåßÔÑ̸¨—ˆ„|q_LC?90+)),*#!%03<;1+++5=Qbz’¤§°¶ÇÊÑÈÁÊÓÏÌÏÙMIA75/*"$)0>SZcbcl}€ƒ…ž©©«´ÂÑâèïêÝŸ¸ÅÈ¿½Áº©—‰|aUE0)+( #$ #030+,24ALG?1('''%"#24/2/+(*=HXh‚™©¡©½ÉÅÊÌÍÎÈÊÊÎËMPK><13+#*)2>Tchinmx‰‹Š‰’¥¨›¦¹ÊØÝßÙѾ©£¨©«©®²§†j`WJ7+**"#*%&3>BGH:+# "" #/44752.19CKbwŠ£«µÀ»ÊÌËÀ¹ÄÉƹV^WKDAE=//2>N`heiokzˆŒ——š¢“‘ž®¿ÔØÐƸ´¥–”š™„h^XOB-"   $#&/69591%#)8>=54;824AXf{—­¼»½½Æ˽²­½¼±¯dpi^PSWG:8@ESdnlmwuvƒ”§¦¢œ›‘–š±ÀÄƹª¥˜ˆ||z{ˆ…yaNORI3%"  +&*0+,)%$139BLJC@67CKTRh‡ªª«³¹Àµ§¥°º²°flom`geRBHMX`jjmou~|‰¡®®œ•˜˜•‘‘™§µ¿Ä¶Ÿ•“‘‰€}|~ƒ„xgTGIJA2)#  + +  $# "!!%(# (2=BDKNH=;=MSWM[w™¢¨£±½¬¨±¶®¦iqyyvxp`[XV[gmkmuz‰…Œ¢®©Ÿ˜›¦¤ £§¨°·»¯––•‡{~‚ˆy^L=::62)    (*1,''5DLHDF?>6ANW^SXks˜˜˜¥·³­²´«žuzyy|yf^Xgkilx„†‘£«ªŸ¡£¯­¯´±±±³³ª™–’“Š‡}…‡†~kU:/10/& + +%0857;=LLFAD@A?LX_c]]i~ˆŒ…“›ž°­±´³¬¢u~wv{|Š}gb_hignq{†Š“¤«¥Ÿ¤¬¸·µ´³«©«©˜¦¨Š•“ƒkR:*+23%  &09>EPOUTL?ABHKVfkgcdnˆ‰‡†™™Ÿ±¯·¼¾º±irgkt{Šzqngs}z‚‡”•—¡§ žœ§´´·³°ª¦¤¤š¡¥²·ª›––œšŒqUE30?OY_ilqz‰”˜•––¦¬«P?:9==;>Ncx‰ž¦¢¦°¯®§ ©®­³¹¿Ä¾Â¿¼°ª§²½¼³´ÃÉÎËĶ£™Ž~whXNE4#   + %)15.-24B?>KLPNJKLOT_ndfsx~zŒ€vz}|ˆ™••QFC@A@@W[UUYk€ £¥Ÿ—’œ˜Œ˜›‘¯´¤¢¤¦¬¢¢°³®«¯½ÕãÛžºµ³¯ž‹„}tdK7-##)2?QYM<,$&% %(""&-99@S]lleedp{tkdgjeegq}Œž˜‰~rnnlrq€†~|r:=>=ETca`lr–– ¨ª ™’…€‚zr‡¢¥–›¡š˜™š˜œ¤²ÎÝØËÉÎÍÇÆ´ž–‘ƒsbM=.),3>BET^VE6(&%!',! #$$&7BR^euxru{ˆ‰ƒzumfky|‰•ž¤“Šviknlhnz{nl37:EP[jrwƒ‚Ž ¢¥¦¨¢šŠ†zgd`Ykƒ‹’š–Žz€„~™¯¿ÈÊÍÓ×Õ×ÙÊ´¦žƒw]E20&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/Code/Physics/Bullet Source/jenga.dae b/Code/Physics/Bullet Source/jenga.dae new file mode 100644 index 00000000..19c85d00 --- /dev/null +++ b/Code/Physics/Bullet Source/jenga.dae @@ -0,0 +1,5632 @@ + + + + + Illusoft Collada 1.4.0 plugin for Blender - http://colladablender.illusoft.com + Blender v:242 - Illusoft Collada Exporter v:0.2.65 + + + file:///Users/erwin/Desktop/physics_demos-2.42-preview34/jenga_physics_test.blend + + 2006-07-18T10:32:54.891550 + 2006-07-18T10:32:54.891607 + Z_UP + + + + + + + 49.13434 + 0.1 + 100.0 + + + + + + + + + + + + + + + + + + + + + + + 0.0 0.0 0.0 1.0 + + + 0.4 0.4 0.4 1.0 + + + 0.8 0.8 0.8 1.0 + + + 0.5 0.5 0.5 1.0 + + + 12.5 + + + 1.0 1.0 1.0 1.0 + + + 0.8 + + + 1 1 1 1 + + + 0.0 + + + + + + + + + + + 4.628 0.542 0.0 4.461 0.379 0.0 4.461 0.369 0.0 4.539 0.369 0.0 4.539 0.132 0.0 4.54308 0.09343 0.0 4.5553 0.05944 0.0 4.57563 0.03112 0.0 4.60404 0.00956 0.0 4.6405 -0.00418 0.0 4.685 -0.009 0.0 4.70092 -0.00796 0.0 4.719 -0.005 0.0 4.73825 -0.00038 0.0 4.75767 0.00567 0.0 4.77625 0.01288 0.0 4.793 0.021 0.0 4.793 0.104 0.0 4.77524 0.09392 0.0 4.75793 0.08567 0.0 4.741 0.07925 0.0 4.72441 0.07467 0.0 4.70809 0.07192 0.0 4.692 0.071 0.0 4.67823 0.07236 0.0 4.66385 0.07685 0.0 4.65025 0.08513 0.0 4.63882 0.09781 0.0 4.63094 0.11556 0.0 4.628 0.139 0.0 4.628 0.369 0.0 4.77 0.369 0.0 4.77 0.449 0.0 4.628 0.449 0.0 4.134 0.449 0.0 4.134 0.0 0.0 4.223 0.0 0.0 4.223 0.235 0.0 4.22684 0.27196 0.0 4.2377 0.305 0.0 4.25463 0.33288 0.0 4.27663 0.35433 0.0 4.30275 0.36813 0.0 4.332 0.373 0.0 4.34357 0.37155 0.0 4.35685 0.36737 0.0 4.37125 0.36075 0.0 4.38615 0.35196 0.0 4.40094 0.34129 0.0 4.415 0.329 0.0 4.462 0.406 0.0 4.44373 0.422 0.0 4.42582 0.43504 0.0 4.40813 0.44513 0.0 4.39052 0.4523 0.0 4.37286 0.45658 0.0 4.355 0.458 0.0 4.33391 0.45519 0.0 4.31263 0.44652 0.0 4.29113 0.43163 0.0 4.26937 0.41015 0.0 4.24734 0.38173 0.0 4.225 0.346 0.0 4.223 0.346 0.0 4.223 0.449 0.0 4.049 0.08 0.0 4.0392 0.07301 0.0 4.02993 0.06711 0.0 4.02138 0.06238 0.0 4.01374 0.05889 0.0 4.00722 0.05674 0.0 4.002 0.056 0.0 3.99692 0.05652 0.0 3.9927 0.05819 0.0 3.98938 0.06113 0.0 3.98696 0.06548 0.0 3.9855 0.07139 0.0 3.985 0.079 0.0 3.985 0.31 0.0 3.97925 0.35638 0.0 3.96296 0.3937 0.0 3.93763 0.42225 0.0 3.9047 0.4423 0.0 3.86567 0.45412 0.0 3.822 0.458 0.0 3.79082 0.45633 0.0 3.76226 0.4513 0.0 3.73625 0.44288 0.0 3.71274 0.43104 0.0 3.69168 0.41575 0.0 3.673 0.397 0.0 3.673 0.3 0.0 3.69505 0.32319 0.0 3.71804 0.34185 0.0 3.74175 0.35612 0.0 3.76596 0.36615 0.0 3.79045 0.37206 0.0 3.815 0.374 0.0 3.83975 0.37204 0.0 3.86 0.36596 0.0 3.87575 0.3555 0.0 3.887 0.34037 0.0 3.89375 0.3203 0.0 3.896 0.295 0.0 3.896 0.271 0.0 3.817 0.243 0.0 3.78067 0.22963 0.0 3.74533 0.21441 0.0 3.7135 0.19563 0.0 3.68767 0.17159 0.0 3.67033 0.14062 0.0 3.664 0.101 0.0 3.66757 0.07271 0.0 3.67785 0.0467 0.0 3.69425 0.02425 0.0 3.71615 0.00663 0.0 3.74294 -0.00488 0.0 3.774 -0.009 0.0 3.79449 -0.00775 0.0 3.81493 -0.00396 0.0 3.83525 0.00238 0.0 3.85541 0.0113 0.0 3.87534 0.02283 0.0 3.895 0.037 0.0 3.90011 0.02248 0.0 3.90752 0.01085 0.0 3.91738 0.002 0.0 3.92982 -0.00419 0.0 3.94498 -0.00781 0.0 3.963 -0.009 0.0 3.97625 -0.00828 0.0 3.98863 -0.00593 0.0 4.00113 -0.00163 0.0 4.0147 0.00493 0.0 4.03034 0.01403 0.0 4.049 0.026 0.0 3.896 0.091 0.0 3.88383 0.08027 0.0 3.87133 0.07119 0.0 3.8585 0.06387 0.0 3.84533 0.05848 0.0 3.83183 0.05514 0.0 3.818 0.054 0.0 3.80041 0.0561 0.0 3.78496 0.06211 0.0 3.77213 0.07163 0.0 3.76237 0.08422 0.0 3.75617 0.09949 0.0 3.754 0.117 0.0 3.75924 0.14138 0.0 3.77393 0.162 0.0 3.7965 0.17963 0.0 3.82541 0.195 0.0 3.85909 0.20888 0.0 3.896 0.222 0.0 3.472 0.542 0.0 3.305 0.379 0.0 3.305 0.369 0.0 3.383 0.369 0.0 3.383 0.132 0.0 3.38708 0.09343 0.0 3.3993 0.05944 0.0 3.41963 0.03112 0.0 3.44804 0.00956 0.0 3.48451 -0.00418 0.0 3.529 -0.009 0.0 3.54492 -0.00796 0.0 3.563 -0.005 0.0 3.58225 -0.00038 0.0 3.60167 0.00567 0.0 3.62025 0.01288 0.0 3.637 0.021 0.0 3.637 0.104 0.0 3.61924 0.09392 0.0 3.60193 0.08567 0.0 3.585 0.07925 0.0 3.56841 0.07467 0.0 3.55209 0.07192 0.0 3.536 0.071 0.0 3.52223 0.07236 0.0 3.50785 0.07685 0.0 3.49425 0.08513 0.0 3.48282 0.09781 0.0 3.47494 0.11556 0.0 3.472 0.139 0.0 3.472 0.369 0.0 3.614 0.369 0.0 3.614 0.449 0.0 3.472 0.449 0.0 3.244 0.421 0.0 3.22082 0.43242 0.0 3.19822 0.4417 0.0 3.17613 0.44888 0.0 3.15444 0.45396 0.0 3.1331 0.457 0.0 3.112 0.458 0.0 3.06979 0.45424 0.0 3.03363 0.44326 0.0 3.00425 0.4255 0.0 2.98237 0.40141 0.0 2.96871 0.37143 0.0 2.964 0.336 0.0 2.97956 0.28229 0.0 3.01845 0.24 0.0 3.069 0.20588 0.0 3.11956 0.17667 0.0 3.15844 0.14913 0.0 3.174 0.12 0.0 3.17161 0.10525 0.0 3.16489 0.093 0.0 3.1545 0.08325 0.0 3.14111 0.076 0.0 3.12539 0.07125 0.0 3.108 0.069 0.0 3.08864 0.07059 0.0 3.06678 0.07541 0.0 3.04275 0.0835 0.0 3.01689 0.09493 0.0 2.98953 0.10974 0.0 2.961 0.128 0.0 2.961 0.032 0.0 2.98888 0.01855 0.0 3.015 0.00804 0.0 3.04013 0.00025 0.0 3.065 -0.00504 0.0 3.09038 -0.00805 0.0 3.117 -0.009 0.0 3.15748 -0.00471 0.0 3.19315 0.00767 0.0 3.22288 0.02737 0.0 3.24552 0.05367 0.0 3.25994 0.08579 0.0 3.265 0.123 0.0 3.26266 0.1449 0.0 3.25526 0.16522 0.0 3.24225 0.18488 0.0 3.22307 0.20478 0.0 3.19718 0.22585 0.0 3.164 0.249 0.0 3.1285 0.27025 0.0 3.10063 0.28833 0.0 3.07988 0.30375 0.0 3.0657 0.317 0.0 3.05759 0.32858 0.0 3.055 0.339 0.0 3.05687 0.35037 0.0 3.0623 0.3603 0.0 3.071 0.3685 0.0 3.0827 0.3747 0.0 3.09713 0.37863 0.0 3.114 0.38 0.0 3.13162 0.37881 0.0 3.15126 0.37515 0.0 3.17263 0.36887 0.0 3.19541 0.35985 0.0 3.2193 0.34794 0.0 3.244 0.333 0.0 2.879 0.13 0.0 2.85307 0.11419 0.0 2.82719 0.10089 0.0 2.80125 0.09025 0.0 2.77515 0.08244 0.0 2.74877 0.07764 0.0 2.722 0.076 0.0 2.68193 0.07982 0.0 2.64774 0.09122 0.0 2.6195 0.11013 0.0 2.59726 0.13644 0.0 2.58107 0.1701 0.0 2.571 0.211 0.0 2.887 0.211 0.0 2.88082 0.28694 0.0 2.86289 0.34881 0.0 2.83413 0.39675 0.0 2.79544 0.43085 0.0 2.74776 0.45123 0.0 2.692 0.458 0.0 2.63339 0.45056 0.0 2.58244 0.42911 0.0 2.5405 0.395 0.0 2.50889 0.34956 0.0 2.48894 0.29411 0.0 2.482 0.23 0.0 2.48843 0.16924 0.0 2.50741 0.11293 0.0 2.5385 0.064 0.0 2.58126 0.02541 0.0 2.63524 9e-05 0.0 2.7 -0.009 0.0 2.7359 -0.00757 0.0 2.76819 -0.00326 0.0 2.79775 0.004 0.0 2.82548 0.01426 0.0 2.85227 0.02757 0.0 2.879 0.044 0.0 2.573 0.27 0.0 2.58141 0.30288 0.0 2.59459 0.33033 0.0 2.6125 0.35213 0.0 2.63507 0.368 0.0 2.66226 0.37771 0.0 2.694 0.381 0.0 2.72344 0.3775 0.0 2.74856 0.36733 0.0 2.769 0.351 0.0 2.78445 0.329 0.0 2.79456 0.30183 0.0 2.799 0.27 0.0 2.114 0.449 0.0 2.114 0.0 0.0 2.203 0.0 0.0 2.203 0.235 0.0 2.20684 0.27196 0.0 2.2177 0.305 0.0 2.23463 0.33288 0.0 2.25663 0.35433 0.0 2.28275 0.36813 0.0 2.312 0.373 0.0 2.32357 0.37155 0.0 2.33685 0.36737 0.0 2.35125 0.36075 0.0 2.36615 0.35196 0.0 2.38094 0.34129 0.0 2.395 0.329 0.0 2.442 0.406 0.0 2.42373 0.422 0.0 2.40582 0.43504 0.0 2.38813 0.44513 0.0 2.37052 0.4523 0.0 2.35286 0.45658 0.0 2.335 0.458 0.0 2.31391 0.45519 0.0 2.29263 0.44652 0.0 2.27113 0.43163 0.0 2.24937 0.41015 0.0 2.22734 0.38173 0.0 2.205 0.346 0.0 2.203 0.346 0.0 2.203 0.449 0.0 1.488 0.458 0.0 1.42392 0.45 0.0 1.367 0.4273 0.0 1.31925 0.39187 0.0 1.28267 0.3457 0.0 1.25925 0.29075 0.0 1.251 0.229 0.0 1.25897 0.16345 0.0 1.28178 0.10596 0.0 1.31775 0.05825 0.0 1.36522 0.02204 0.0 1.42253 -0.00095 0.0 1.488 -0.009 0.0 1.556 -0.00123 0.0 1.615 0.02115 0.0 1.6635 0.05675 0.0 1.7 0.10419 0.0 1.723 0.16206 0.0 1.731 0.229 0.0 1.72279 0.29214 0.0 1.69933 0.34748 0.0 1.66238 0.39338 0.0 1.61367 0.42819 0.0 1.55496 0.45027 0.0 1.487 0.378 0.0 1.52924 0.37293 0.0 1.56622 0.35844 0.0 1.59688 0.33563 0.0 1.62011 0.30556 0.0 1.63485 0.26932 0.0 1.64 0.228 0.0 1.63519 0.18269 0.0 1.62122 0.14419 0.0 1.59875 0.11313 0.0 1.56844 0.09015 0.0 1.53097 0.07589 0.0 1.487 0.071 0.0 1.4464 0.07611 0.0 1.41119 0.09085 0.0 1.38225 0.11437 0.0 1.36048 0.14581 0.0 1.34677 0.18431 0.0 1.342 0.229 0.0 1.34691 0.2699 0.0 1.36093 0.30585 0.0 1.383 0.33575 0.0 1.41207 0.35848 0.0 1.44709 0.37294 0.0 1.049 0.542 0.0 0.882 0.379 0.0 0.882 0.369 0.0 0.96 0.369 0.0 0.96 0.132 0.0 0.96408 0.09343 0.0 0.9763 0.05944 0.0 0.99663 0.03112 0.0 1.02504 0.00956 0.0 1.0615 -0.00418 0.0 1.106 -0.009 0.0 1.12192 -0.00796 0.0 1.14 -0.005 0.0 1.15925 -0.00038 0.0 1.17867 0.00567 0.0 1.19725 0.01288 0.0 1.214 0.021 0.0 1.214 0.104 0.0 1.19624 0.09392 0.0 1.17893 0.08567 0.0 1.162 0.07925 0.0 1.14541 0.07467 0.0 1.12909 0.07192 0.0 1.113 0.071 0.0 1.09923 0.07236 0.0 1.08485 0.07685 0.0 1.07125 0.08513 0.0 1.05981 0.09781 0.0 1.05194 0.11556 0.0 1.049 0.139 0.0 1.049 0.369 0.0 1.191 0.369 0.0 1.191 0.449 0.0 1.049 0.449 0.0 0.077 0.682 0.0 0.077 0.0 0.0 0.175 0.0 0.0 0.175 0.296 0.0 0.216 0.296 0.0 0.24052 0.29417 0.0 0.26515 0.28667 0.0 0.2915 0.2705 0.0 0.32119 0.24267 0.0 0.35581 0.20017 0.0 0.397 0.14 0.0 0.487 0.0 0.0 0.604 0.0 0.0 0.58281 0.02931 0.0 0.56544 0.05344 0.0 0.55075 0.07425 0.0 0.53756 0.09356 0.0 0.52469 0.11319 0.0 0.511 0.135 0.0 0.48599 0.17567 0.0 0.46226 0.21267 0.0 0.43875 0.246 0.0 0.41441 0.27567 0.0 0.38818 0.30167 0.0 0.359 0.324 0.0 0.39279 0.34095 0.0 0.421 0.36263 0.0 0.44337 0.38875 0.0 0.45967 0.41904 0.0 0.46962 0.45321 0.0 0.473 0.491 0.0 0.46599 0.54612 0.0 0.44559 0.59296 0.0 0.41275 0.63075 0.0 0.36841 0.6587 0.0 0.31351 0.67605 0.0 0.249 0.682 0.0 0.175 0.598 0.0 0.238 0.598 0.0 0.28084 0.59481 0.0 0.31474 0.58552 0.0 0.34025 0.5705 0.0 0.35793 0.55015 0.0 0.36832 0.52485 0.0 0.372 0.495 0.0 0.36971 0.46699 0.0 0.36104 0.44089 0.0 0.34475 0.41813 0.0 0.31963 0.40011 0.0 0.28445 0.38826 0.0 0.238 0.384 0.0 0.175 0.384 0.0 + + + + + + + + + + 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    1 0 0 1 33 2 1 3 33 4 32 5 1 6 32 7 31 8 2 9 1 10 31 11 3 12 2 13 31 14 4 15 3 16 30 17 30 18 3 19 31 20 4 21 30 22 29 23 4 24 29 25 28 26 5 27 4 28 28 29 5 30 28 31 27 32 18 33 17 34 16 35 5 36 27 37 26 38 19 39 18 40 16 41 6 42 5 43 26 44 20 45 19 46 16 47 6 48 26 49 25 50 21 51 20 52 16 53 6 54 25 55 24 56 22 57 21 58 16 59 6 60 24 61 23 62 23 63 22 64 16 65 6 66 23 67 16 68 7 69 6 70 16 71 8 72 7 73 16 74 8 75 16 76 15 77 8 78 15 79 14 80 9 81 8 82 14 83 9 84 14 85 13 86 9 87 13 88 12 89 10 90 9 91 12 92 10 93 12 94 11 95 57 96 56 97 55 98 57 99 55 100 54 101 58 102 57 103 54 104 58 105 54 106 53 107 35 108 34 109 64 110 35 111 64 112 63 113 59 114 58 115 53 116 59 117 53 118 52 119 59 120 52 121 51 122 60 123 59 124 51 125 60 126 51 127 50 128 61 129 60 130 50 131 61 132 50 133 43 134 43 135 50 136 44 137 44 138 50 139 45 140 45 141 50 142 46 143 46 144 50 145 47 146 47 147 50 148 48 149 48 150 50 151 49 152 62 153 61 154 42 155 42 156 61 157 43 158 62 159 42 160 41 161 62 162 41 163 40 164 35 165 63 166 62 167 35 168 62 169 39 170 39 171 62 172 40 173 35 174 39 175 38 176 35 177 38 178 37 179 35 180 37 181 36 182 85 183 84 184 83 185 86 186 85 187 83 188 86 189 83 190 82 191 87 192 86 193 82 194 88 195 87 196 82 197 88 198 82 199 81 200 89 201 88 202 81 203 89 204 81 205 80 206 90 207 89 208 80 209 91 210 90 211 92 212 92 213 90 214 93 215 93 216 90 217 94 218 94 219 90 220 95 221 95 222 90 223 96 224 96 225 90 226 97 227 97 228 90 229 80 230 97 231 80 232 98 233 98 234 80 235 79 236 99 237 98 238 79 239 100 240 99 241 79 242 100 243 79 244 78 245 101 246 100 247 78 248 102 249 101 250 78 251 103 252 102 253 78 254 103 255 78 256 77 257 104 258 103 259 77 260 105 261 104 262 154 263 154 264 104 265 77 266 106 267 105 268 154 269 107 270 106 271 154 272 107 273 154 274 153 275 136 276 154 277 77 278 108 279 107 280 153 281 108 282 153 283 152 284 109 285 108 286 152 287 109 288 152 289 151 290 109 291 151 292 150 293 110 294 109 295 150 296 110 297 150 298 149 299 110 300 149 301 148 302 111 303 110 304 148 305 111 306 148 307 147 308 112 309 111 310 147 311 112 312 147 313 146 314 137 315 136 316 77 317 112 318 146 319 145 320 138 321 137 322 77 323 66 324 65 325 135 326 138 327 77 328 76 329 67 330 66 331 135 332 113 333 112 334 145 335 113 336 145 337 144 338 138 339 76 340 75 341 139 342 138 343 75 344 68 345 67 346 135 347 139 348 75 349 74 350 140 351 139 352 74 353 69 354 68 355 135 356 113 357 144 358 143 359 140 360 74 361 73 362 70 363 69 364 135 365 141 366 140 367 73 368 141 369 73 370 72 371 71 372 70 373 135 374 141 375 72 376 71 377 113 378 143 379 142 380 141 381 71 382 135 383 142 384 141 385 135 386 113 387 142 388 123 389 123 390 142 391 135 392 114 393 113 394 123 395 114 396 123 397 122 398 124 399 123 400 135 401 124 402 135 403 134 404 115 405 114 406 122 407 115 408 122 409 121 410 125 411 124 412 134 413 125 414 134 415 133 416 115 417 121 418 120 419 126 420 125 421 133 422 116 423 115 424 120 425 126 426 133 427 132 428 116 429 120 430 119 431 127 432 126 433 132 434 127 435 132 436 131 437 116 438 119 439 118 440 128 441 127 442 131 443 117 444 116 445 118 446 128 447 131 448 130 449 129 450 128 451 130 452 156 453 155 454 188 455 156 456 188 457 187 458 156 459 187 460 186 461 157 462 156 463 186 464 158 465 157 466 186 467 159 468 158 469 185 470 185 471 158 472 186 473 159 474 185 475 184 476 159 477 184 478 183 479 160 480 159 481 183 482 160 483 183 484 182 485 173 486 172 487 171 488 160 489 182 490 181 491 174 492 173 493 171 494 161 495 160 496 181 497 175 498 174 499 171 500 161 501 181 502 180 503 176 504 175 505 171 506 161 507 180 508 179 509 177 510 176 511 171 512 161 513 179 514 178 515 178 516 177 517 171 518 161 519 178 520 171 521 162 522 161 523 171 524 163 525 162 526 171 527 163 528 171 529 170 530 163 531 170 532 169 533 164 534 163 535 169 536 164 537 169 538 168 539 164 540 168 541 167 542 165 543 164 544 167 545 165 546 167 547 166 548 196 549 195 550 194 551 196 552 194 553 193 554 197 555 196 556 193 557 197 558 193 559 192 560 197 561 192 562 191 563 198 564 197 565 191 566 198 567 191 568 190 569 198 570 190 571 189 572 199 573 198 574 189 575 199 576 189 577 250 578 250 579 189 580 251 581 251 582 189 583 252 584 252 585 189 586 253 587 253 588 189 589 254 590 254 591 189 592 255 593 255 594 189 595 256 596 200 597 199 598 250 599 200 600 250 601 249 602 200 603 249 604 248 605 200 606 248 607 247 608 201 609 200 610 247 611 201 612 247 613 246 614 201 615 246 616 245 617 201 618 245 619 244 620 201 621 244 622 243 623 202 624 201 625 243 626 202 627 243 628 242 629 202 630 242 631 241 632 202 633 241 634 240 635 202 636 240 637 239 638 203 639 202 640 239 641 203 642 239 643 238 644 203 645 238 646 237 647 204 648 203 649 237 650 204 651 237 652 236 653 205 654 204 655 236 656 205 657 236 658 235 659 205 660 235 661 234 662 206 663 205 664 234 665 206 666 234 667 233 668 207 669 206 670 233 671 207 672 233 673 232 674 220 675 219 676 218 677 207 678 232 679 231 680 208 681 207 682 231 683 220 684 218 685 217 686 209 687 208 688 231 689 220 690 217 691 216 692 210 693 209 694 231 695 210 696 231 697 230 698 220 699 216 700 215 701 211 702 210 703 230 704 212 705 211 706 230 707 220 708 215 709 214 710 213 711 212 712 230 713 220 714 214 715 213 716 220 717 213 718 230 719 220 720 230 721 229 722 221 723 220 724 229 725 221 726 229 727 228 728 222 729 221 730 228 731 223 732 222 733 228 734 223 735 228 736 227 737 224 738 223 739 227 740 224 741 227 742 226 743 225 744 224 745 226 746 277 747 276 748 275 749 277 750 275 751 274 752 278 753 277 754 274 755 278 756 274 757 273 758 279 759 278 760 273 761 279 762 273 763 301 764 301 765 273 766 302 767 302 768 273 769 272 770 280 771 279 772 300 773 300 774 279 775 301 776 280 777 300 778 299 779 303 780 302 781 272 782 280 783 299 784 298 785 304 786 303 787 272 788 280 789 298 790 297 791 305 792 304 793 272 794 281 795 280 796 297 797 305 798 272 799 271 800 281 801 297 802 296 803 306 804 305 805 271 806 281 807 296 808 295 809 307 810 306 811 271 812 282 813 281 814 295 815 307 816 271 817 270 818 282 819 295 820 307 821 282 822 307 823 270 824 283 825 282 826 269 827 269 828 282 829 270 830 283 831 269 832 268 833 283 834 268 835 267 836 284 837 283 838 267 839 284 840 267 841 266 842 258 843 257 844 294 845 259 846 258 847 294 848 285 849 284 850 266 851 285 852 266 853 265 854 260 855 259 856 294 857 285 858 265 859 264 860 261 861 260 862 294 863 262 864 261 865 294 866 285 867 264 868 263 869 263 870 262 871 294 872 285 873 263 874 294 875 286 876 285 877 294 878 286 879 294 880 293 881 286 882 293 883 292 884 287 885 286 886 292 887 287 888 292 889 291 890 287 891 291 892 290 893 288 894 287 895 290 896 288 897 290 898 289 899 331 900 330 901 329 902 331 903 329 904 328 905 332 906 331 907 328 908 332 909 328 910 327 911 309 912 308 913 338 914 309 915 338 916 337 917 333 918 332 919 327 920 333 921 327 922 326 923 333 924 326 925 325 926 334 927 333 928 325 929 334 930 325 931 324 932 335 933 334 934 324 935 335 936 324 937 317 938 317 939 324 940 318 941 318 942 324 943 319 944 319 945 324 946 320 947 320 948 324 949 321 950 321 951 324 952 322 953 322 954 324 955 323 956 336 957 335 958 316 959 316 960 335 961 317 962 336 963 316 964 315 965 336 966 315 967 314 968 309 969 337 970 336 971 309 972 336 973 313 974 313 975 336 976 314 977 309 978 313 979 312 980 309 981 312 982 311 983 309 984 311 985 310 986 340 987 339 988 362 989 340 990 362 991 361 992 341 993 340 994 361 995 341 996 361 997 360 998 342 999 341 1000 360 1001 342 1002 360 1003 363 1004 363 1005 360 1006 364 1007 364 1008 360 1009 359 1010 343 1011 342 1012 386 1013 386 1014 342 1015 363 1016 343 1017 386 1018 385 1019 365 1020 364 1021 359 1022 343 1023 385 1024 384 1025 366 1026 365 1027 359 1028 366 1029 359 1030 358 1031 344 1032 343 1033 384 1034 344 1035 384 1036 383 1037 367 1038 366 1039 358 1040 344 1041 383 1042 382 1043 368 1044 367 1045 358 1046 368 1047 358 1048 357 1049 345 1050 344 1051 382 1052 345 1053 382 1054 381 1055 369 1056 368 1057 357 1058 346 1059 345 1060 381 1061 346 1062 381 1063 380 1064 369 1065 357 1066 356 1067 370 1068 369 1069 356 1070 346 1071 380 1072 379 1073 371 1074 370 1075 356 1076 347 1077 346 1078 379 1079 371 1080 356 1081 355 1082 347 1083 379 1084 378 1085 372 1086 371 1087 355 1088 347 1089 378 1090 377 1091 373 1092 372 1093 355 1094 348 1095 347 1096 377 1097 373 1098 355 1099 354 1100 348 1101 377 1102 376 1103 374 1104 373 1105 354 1106 348 1107 376 1108 375 1109 375 1110 374 1111 354 1112 348 1113 375 1114 354 1115 349 1116 348 1117 354 1118 349 1119 354 1120 353 1121 350 1122 349 1123 353 1124 350 1125 353 1126 352 1127 351 1128 350 1129 352 1130 388 1131 387 1132 420 1133 388 1134 420 1135 419 1136 388 1137 419 1138 418 1139 389 1140 388 1141 418 1142 390 1143 389 1144 418 1145 391 1146 390 1147 417 1148 417 1149 390 1150 418 1151 391 1152 417 1153 416 1154 391 1155 416 1156 415 1157 392 1158 391 1159 415 1160 392 1161 415 1162 414 1163 405 1164 404 1165 403 1166 392 1167 414 1168 413 1169 406 1170 405 1171 403 1172 393 1173 392 1174 413 1175 407 1176 406 1177 403 1178 393 1179 413 1180 412 1181 408 1182 407 1183 403 1184 393 1185 412 1186 411 1187 409 1188 408 1189 403 1190 393 1191 411 1192 410 1193 410 1194 409 1195 403 1196 393 1197 410 1198 403 1199 394 1200 393 1201 403 1202 395 1203 394 1204 403 1205 395 1206 403 1207 402 1208 395 1209 402 1210 401 1211 396 1212 395 1213 401 1214 396 1215 401 1216 400 1217 396 1218 400 1219 399 1220 397 1221 396 1222 399 1223 397 1224 399 1225 398 1226 422 1227 421 1228 458 1229 458 1230 421 1231 457 1232 458 1233 457 1234 456 1235 458 1236 456 1237 455 1238 458 1239 455 1240 454 1241 458 1242 454 1243 459 1244 459 1245 454 1246 453 1247 422 1248 458 1249 472 1250 460 1251 459 1252 453 1253 461 1254 460 1255 453 1256 461 1257 453 1258 452 1259 462 1260 461 1261 452 1262 463 1263 462 1264 452 1265 464 1266 463 1267 452 1268 464 1269 452 1270 451 1271 465 1272 464 1273 451 1274 466 1275 465 1276 451 1277 466 1278 451 1279 450 1280 467 1281 466 1282 450 1283 467 1284 450 1285 449 1286 468 1287 467 1288 449 1289 468 1290 449 1291 448 1292 469 1293 468 1294 448 1295 470 1296 469 1297 448 1298 470 1299 448 1300 447 1301 471 1302 470 1303 447 1304 422 1305 472 1306 424 1307 424 1308 472 1309 471 1310 424 1311 471 1312 447 1313 424 1314 447 1315 446 1316 424 1317 446 1318 445 1319 424 1320 445 1321 444 1322 424 1323 444 1324 425 1325 425 1326 444 1327 426 1328 426 1329 444 1330 443 1331 422 1332 424 1333 423 1334 427 1335 426 1336 443 1337 428 1338 427 1339 443 1340 428 1341 443 1342 442 1343 429 1344 428 1345 442 1346 429 1347 442 1348 441 1349 430 1350 429 1351 441 1352 430 1353 441 1354 440 1355 431 1356 430 1357 440 1358 431 1359 440 1360 439 1361 432 1362 431 1363 439 1364 432 1365 439 1366 438 1367 432 1368 438 1369 437 1370 432 1371 437 1372 436 1373 432 1374 436 1375 435 1376 432 1377 435 1378 434 1379 432 1380 434 1381 433 1382

    + + + + + + + 9.646 -1.87 0.0 9.62007 -1.88581 0.0 9.59419 -1.89911 0.0 9.56825 -1.90975 0.0 9.54215 -1.91756 0.0 9.51577 -1.92236 0.0 9.489 -1.924 0.0 9.44893 -1.92018 0.0 9.41474 -1.90878 0.0 9.3865 -1.88988 0.0 9.36426 -1.86356 0.0 9.34807 -1.8299 0.0 9.338 -1.789 0.0 9.654 -1.789 0.0 9.64782 -1.71306 0.0 9.62989 -1.65119 0.0 9.60113 -1.60325 0.0 9.56245 -1.56915 0.0 9.51476 -1.54877 0.0 9.459 -1.542 0.0 9.40039 -1.54944 0.0 9.34945 -1.57089 0.0 9.3075 -1.605 0.0 9.27589 -1.65044 0.0 9.25595 -1.70589 0.0 9.249 -1.77 0.0 9.25543 -1.83076 0.0 9.27441 -1.88707 0.0 9.3055 -1.936 0.0 9.34826 -1.97459 0.0 9.40224 -1.99991 0.0 9.467 -2.009 0.0 9.5029 -2.00757 0.0 9.53519 -2.00326 0.0 9.56475 -1.996 0.0 9.59248 -1.98574 0.0 9.61927 -1.97243 0.0 9.646 -1.956 0.0 9.34 -1.73 0.0 9.34841 -1.69712 0.0 9.36159 -1.66967 0.0 9.3795 -1.64787 0.0 9.40208 -1.632 0.0 9.42926 -1.62229 0.0 9.461 -1.619 0.0 9.49045 -1.6225 0.0 9.51556 -1.63267 0.0 9.536 -1.649 0.0 9.55145 -1.671 0.0 9.56156 -1.69817 0.0 9.566 -1.73 0.0 9.042 -1.458 0.0 8.875 -1.621 0.0 8.875 -1.631 0.0 8.953 -1.631 0.0 8.953 -1.868 0.0 8.95708 -1.90657 0.0 8.9693 -1.94056 0.0 8.98963 -1.96888 0.0 9.01804 -1.99044 0.0 9.05451 -2.00418 0.0 9.099 -2.009 0.0 9.11492 -2.00796 0.0 9.133 -2.005 0.0 9.15225 -2.00038 0.0 9.17167 -1.99433 0.0 9.19025 -1.98713 0.0 9.207 -1.979 0.0 9.207 -1.896 0.0 9.18924 -1.90608 0.0 9.17193 -1.91433 0.0 9.155 -1.92075 0.0 9.13841 -1.92533 0.0 9.12209 -1.92808 0.0 9.106 -1.929 0.0 9.09223 -1.92764 0.0 9.07785 -1.92315 0.0 9.06425 -1.91488 0.0 9.05282 -1.90219 0.0 9.04494 -1.88444 0.0 9.042 -1.861 0.0 9.042 -1.631 0.0 9.184 -1.631 0.0 9.184 -1.551 0.0 9.042 -1.551 0.0 8.859 -1.92 0.0 8.8492 -1.92699 0.0 8.83993 -1.93289 0.0 8.83138 -1.93762 0.0 8.82374 -1.94111 0.0 8.81722 -1.94326 0.0 8.812 -1.944 0.0 8.80692 -1.94348 0.0 8.8027 -1.94181 0.0 8.79938 -1.93887 0.0 8.79696 -1.93452 0.0 8.7955 -1.92861 0.0 8.795 -1.921 0.0 8.795 -1.69 0.0 8.78925 -1.64362 0.0 8.77296 -1.6063 0.0 8.74763 -1.57775 0.0 8.7147 -1.5577 0.0 8.67567 -1.54588 0.0 8.632 -1.542 0.0 8.60083 -1.54367 0.0 8.57226 -1.5487 0.0 8.54625 -1.55712 0.0 8.52274 -1.56896 0.0 8.50168 -1.58425 0.0 8.483 -1.603 0.0 8.483 -1.7 0.0 8.50505 -1.67681 0.0 8.52804 -1.65815 0.0 8.55175 -1.64387 0.0 8.57596 -1.63385 0.0 8.60045 -1.62794 0.0 8.625 -1.626 0.0 8.64975 -1.62796 0.0 8.67 -1.63404 0.0 8.68575 -1.6445 0.0 8.697 -1.65963 0.0 8.70375 -1.6797 0.0 8.706 -1.705 0.0 8.706 -1.729 0.0 8.627 -1.757 0.0 8.59067 -1.77037 0.0 8.55533 -1.78559 0.0 8.5235 -1.80437 0.0 8.49767 -1.82841 0.0 8.48033 -1.85938 0.0 8.474 -1.899 0.0 8.47757 -1.92729 0.0 8.48785 -1.9533 0.0 8.50425 -1.97575 0.0 8.52615 -1.99337 0.0 8.55294 -2.00488 0.0 8.584 -2.009 0.0 8.60449 -2.00775 0.0 8.62493 -2.00396 0.0 8.64525 -1.99762 0.0 8.66541 -1.9887 0.0 8.68534 -1.97717 0.0 8.705 -1.963 0.0 8.71011 -1.97752 0.0 8.71752 -1.98915 0.0 8.72738 -1.998 0.0 8.73982 -2.00419 0.0 8.75498 -2.00781 0.0 8.773 -2.009 0.0 8.78625 -2.00828 0.0 8.79863 -2.00593 0.0 8.81113 -2.00162 0.0 8.8247 -1.99507 0.0 8.84034 -1.98597 0.0 8.859 -1.974 0.0 8.706 -1.909 0.0 8.69383 -1.91973 0.0 8.68133 -1.92881 0.0 8.6685 -1.93612 0.0 8.65533 -1.94152 0.0 8.64183 -1.94486 0.0 8.628 -1.946 0.0 8.61041 -1.9439 0.0 8.59496 -1.93789 0.0 8.58212 -1.92838 0.0 8.57237 -1.91578 0.0 8.56617 -1.90051 0.0 8.564 -1.883 0.0 8.56924 -1.85863 0.0 8.58393 -1.838 0.0 8.6065 -1.82038 0.0 8.63541 -1.805 0.0 8.6691 -1.79113 0.0 8.706 -1.778 0.0 8.442 -1.551 0.0 8.257 -1.551 0.0 8.20047 -1.55581 0.0 8.15241 -1.56985 0.0 8.11363 -1.5925 0.0 8.08493 -1.62315 0.0 8.06712 -1.66119 0.0 8.061 -1.706 0.0 8.06167 -1.72208 0.0 8.06367 -1.73733 0.0 8.067 -1.75175 0.0 8.07167 -1.76533 0.0 8.07767 -1.77808 0.0 8.085 -1.79 0.0 8.09417 -1.80158 0.0 8.10467 -1.81233 0.0 8.1165 -1.82225 0.0 8.12967 -1.83133 0.0 8.14417 -1.83958 0.0 8.16 -1.847 0.0 8.16 -1.849 0.0 8.13981 -1.8552 0.0 8.12248 -1.86359 0.0 8.10837 -1.87388 0.0 8.09785 -1.88574 0.0 8.09127 -1.89888 0.0 8.089 -1.913 0.0 8.09018 -1.92285 0.0 8.09378 -1.93244 0.0 8.09988 -1.94187 0.0 8.10856 -1.95122 0.0 8.1199 -1.96057 0.0 8.134 -1.97 0.0 8.09855 -1.9812 0.0 8.07004 -1.99593 0.0 8.04825 -2.01438 0.0 8.03296 -2.03674 0.0 8.02395 -2.06322 0.0 8.021 -2.094 0.0 8.02793 -2.1315 0.0 8.04778 -2.16437 0.0 8.07913 -2.19163 0.0 8.12056 -2.2123 0.0 8.17065 -2.22541 0.0 8.228 -2.23 0.0 8.28988 -2.22559 0.0 8.34207 -2.2127 0.0 8.38387 -2.19188 0.0 8.41459 -2.16363 0.0 8.43353 -2.1285 0.0 8.44 -2.087 0.0 8.43704 -2.05927 0.0 8.42763 -2.03348 0.0 8.411 -2.01025 0.0 8.38637 -1.99019 0.0 8.35296 -1.9739 0.0 8.31 -1.962 0.0 8.2686 -1.95319 0.0 8.23448 -1.94452 0.0 8.20775 -1.93563 0.0 8.18852 -1.92615 0.0 8.1769 -1.91573 0.0 8.173 -1.904 0.0 8.18232 -1.88375 0.0 8.20685 -1.87263 0.0 8.2415 -1.86563 0.0 8.28115 -1.8577 0.0 8.32069 -1.84384 0.0 8.355 -1.819 0.0 8.3654 -1.8068 0.0 8.37522 -1.7917 0.0 8.38388 -1.7745 0.0 8.39078 -1.75596 0.0 8.39535 -1.73687 0.0 8.397 -1.718 0.0 8.39595 -1.69998 0.0 8.39259 -1.68348 0.0 8.38663 -1.66787 0.0 8.37774 -1.65252 0.0 8.36563 -1.63677 0.0 8.35 -1.62 0.0 8.442 -1.62 0.0 8.317 -1.707 0.0 8.3141 -1.73024 0.0 8.30582 -1.75056 0.0 8.29275 -1.76738 0.0 8.27552 -1.78011 0.0 8.25473 -1.78818 0.0 8.231 -1.791 0.0 8.20558 -1.78833 0.0 8.18367 -1.78063 0.0 8.16575 -1.76838 0.0 8.15234 -1.75204 0.0 8.14392 -1.73209 0.0 8.141 -1.709 0.0 8.14419 -1.68772 0.0 8.15319 -1.66844 0.0 8.16713 -1.652 0.0 8.18515 -1.63922 0.0 8.20639 -1.63094 0.0 8.23 -1.628 0.0 8.25276 -1.63087 0.0 8.27345 -1.63893 0.0 8.29113 -1.65138 0.0 8.30489 -1.66741 0.0 8.31382 -1.68622 0.0 8.354 -2.094 0.0 8.35023 -2.11305 0.0 8.33919 -2.12907 0.0 8.32125 -2.14188 0.0 8.29681 -2.15126 0.0 8.26627 -2.15703 0.0 8.23 -2.159 0.0 8.19262 -2.15701 0.0 8.16159 -2.15111 0.0 8.13713 -2.14138 0.0 8.11941 -2.12789 0.0 8.10863 -2.11074 0.0 8.105 -2.09 0.0 8.10839 -2.07107 0.0 8.11811 -2.05459 0.0 8.1335 -2.041 0.0 8.15389 -2.03074 0.0 8.17861 -2.02426 0.0 8.207 -2.022 0.0 8.23699 -2.02338 0.0 8.26956 -2.028 0.0 8.30113 -2.03663 0.0 8.32811 -2.05 0.0 8.34693 -2.06888 0.0 7.956 -1.551 0.0 7.867 -1.551 0.0 7.867 -2.0 0.0 7.956 -2.0 0.0 7.965 -1.415 0.0 7.96309 -1.401 0.0 7.9577 -1.38837 0.0 7.94938 -1.37762 0.0 7.93863 -1.3693 0.0 7.926 -1.36391 0.0 7.912 -1.362 0.0 7.89801 -1.36391 0.0 7.88537 -1.3693 0.0 7.87463 -1.37762 0.0 7.8663 -1.38837 0.0 7.86091 -1.401 0.0 7.859 -1.415 0.0 7.86091 -1.429 0.0 7.8663 -1.44163 0.0 7.87463 -1.45238 0.0 7.88537 -1.4607 0.0 7.89801 -1.46609 0.0 7.912 -1.468 0.0 7.926 -1.46609 0.0 7.93863 -1.4607 0.0 7.94938 -1.45238 0.0 7.9577 -1.44163 0.0 7.96309 -1.429 0.0 7.57 -2.009 0.0 7.6 -2.009 0.0 7.798 -1.551 0.0 7.703 -1.551 0.0 7.585 -1.827 0.0 7.464 -1.551 0.0 7.367 -1.551 0.0 7.348 -1.92 0.0 7.3382 -1.92699 0.0 7.32893 -1.93289 0.0 7.32038 -1.93762 0.0 7.31274 -1.94111 0.0 7.30622 -1.94326 0.0 7.301 -1.944 0.0 7.29592 -1.94348 0.0 7.2917 -1.94181 0.0 7.28837 -1.93887 0.0 7.28596 -1.93452 0.0 7.2845 -1.92861 0.0 7.284 -1.921 0.0 7.284 -1.69 0.0 7.27825 -1.64362 0.0 7.26196 -1.6063 0.0 7.23663 -1.57775 0.0 7.2037 -1.5577 0.0 7.16467 -1.54588 0.0 7.121 -1.542 0.0 7.08982 -1.54367 0.0 7.06126 -1.5487 0.0 7.03525 -1.55712 0.0 7.01174 -1.56896 0.0 6.99068 -1.58425 0.0 6.972 -1.603 0.0 6.972 -1.7 0.0 6.99405 -1.67681 0.0 7.01704 -1.65815 0.0 7.04075 -1.64387 0.0 7.06496 -1.63385 0.0 7.08945 -1.62794 0.0 7.114 -1.626 0.0 7.13875 -1.62796 0.0 7.159 -1.63404 0.0 7.17475 -1.6445 0.0 7.186 -1.65963 0.0 7.19275 -1.6797 0.0 7.195 -1.705 0.0 7.195 -1.729 0.0 7.116 -1.757 0.0 7.07967 -1.77037 0.0 7.04433 -1.78559 0.0 7.0125 -1.80437 0.0 6.98667 -1.82841 0.0 6.96933 -1.85938 0.0 6.963 -1.899 0.0 6.96657 -1.92729 0.0 6.97685 -1.9533 0.0 6.99325 -1.97575 0.0 7.01515 -1.99337 0.0 7.04194 -2.00488 0.0 7.073 -2.009 0.0 7.09349 -2.00775 0.0 7.11393 -2.00396 0.0 7.13425 -1.99762 0.0 7.15441 -1.9887 0.0 7.17434 -1.97717 0.0 7.194 -1.963 0.0 7.19911 -1.97752 0.0 7.20652 -1.98915 0.0 7.21638 -1.998 0.0 7.22882 -2.00419 0.0 7.24398 -2.00781 0.0 7.262 -2.009 0.0 7.27525 -2.00828 0.0 7.28763 -2.00593 0.0 7.30013 -2.00162 0.0 7.3137 -1.99507 0.0 7.32934 -1.98597 0.0 7.348 -1.974 0.0 7.195 -1.909 0.0 7.18283 -1.91973 0.0 7.17033 -1.92881 0.0 7.1575 -1.93612 0.0 7.14433 -1.94152 0.0 7.13083 -1.94486 0.0 7.117 -1.946 0.0 7.09941 -1.9439 0.0 7.08396 -1.93789 0.0 7.07113 -1.92838 0.0 7.06137 -1.91578 0.0 7.05517 -1.90051 0.0 7.053 -1.883 0.0 7.05824 -1.85863 0.0 7.07293 -1.838 0.0 7.0955 -1.82038 0.0 7.12441 -1.805 0.0 7.15809 -1.79113 0.0 7.195 -1.778 0.0 6.587 -1.551 0.0 6.498 -1.551 0.0 6.498 -2.0 0.0 6.587 -2.0 0.0 6.587 -1.678 0.0 6.60717 -1.65687 0.0 6.62604 -1.64026 0.0 6.64412 -1.62787 0.0 6.66196 -1.61941 0.0 6.68008 -1.61455 0.0 6.699 -1.613 0.0 6.72427 -1.61649 0.0 6.74582 -1.62659 0.0 6.76325 -1.64275 0.0 6.77619 -1.66441 0.0 6.78423 -1.69101 0.0 6.787 -1.722 0.0 6.787 -2.0 0.0 6.876 -2.0 0.0 6.876 -1.723 0.0 6.87057 -1.66688 0.0 6.85522 -1.62141 0.0 6.83138 -1.58637 0.0 6.80044 -1.56159 0.0 6.76385 -1.54687 0.0 6.723 -1.542 0.0 6.69807 -1.54405 0.0 6.67359 -1.55007 0.0 6.65 -1.55987 0.0 6.62774 -1.57326 0.0 6.60726 -1.59003 0.0 6.589 -1.61 0.0 6.587 -1.61 0.0 5.88 -1.542 0.0 5.81592 -1.55 0.0 5.759 -1.5727 0.0 5.71125 -1.60812 0.0 5.67467 -1.6543 0.0 5.65125 -1.70925 0.0 5.643 -1.771 0.0 5.65097 -1.83655 0.0 5.67378 -1.89404 0.0 5.70975 -1.94175 0.0 5.75722 -1.97796 0.0 5.81453 -2.00095 0.0 5.88 -2.009 0.0 5.948 -2.00123 0.0 6.007 -1.97885 0.0 6.0555 -1.94325 0.0 6.092 -1.89581 0.0 6.115 -1.83794 0.0 6.123 -1.771 0.0 6.11479 -1.70786 0.0 6.09133 -1.65252 0.0 6.05438 -1.60662 0.0 6.00567 -1.57181 0.0 5.94696 -1.54973 0.0 5.879 -1.622 0.0 5.92124 -1.62707 0.0 5.95822 -1.64156 0.0 5.98888 -1.66437 0.0 6.01211 -1.69444 0.0 6.02685 -1.73068 0.0 6.032 -1.772 0.0 6.02719 -1.81731 0.0 6.01322 -1.85581 0.0 5.99075 -1.88687 0.0 5.96044 -1.90985 0.0 5.92297 -1.92411 0.0 5.879 -1.929 0.0 5.8384 -1.92389 0.0 5.80319 -1.90915 0.0 5.77425 -1.88563 0.0 5.75248 -1.85419 0.0 5.73877 -1.81569 0.0 5.734 -1.771 0.0 5.73891 -1.7301 0.0 5.75293 -1.69415 0.0 5.775 -1.66425 0.0 5.80407 -1.64152 0.0 5.83909 -1.62706 0.0 5.441 -1.458 0.0 5.274 -1.621 0.0 5.274 -1.631 0.0 5.352 -1.631 0.0 5.352 -1.868 0.0 5.35608 -1.90657 0.0 5.3683 -1.94056 0.0 5.38863 -1.96888 0.0 5.41704 -1.99044 0.0 5.4535 -2.00418 0.0 5.498 -2.009 0.0 5.51392 -2.00796 0.0 5.532 -2.005 0.0 5.55125 -2.00038 0.0 5.57067 -1.99433 0.0 5.58925 -1.98713 0.0 5.606 -1.979 0.0 5.606 -1.896 0.0 5.58824 -1.90608 0.0 5.57093 -1.91433 0.0 5.554 -1.92075 0.0 5.53741 -1.92533 0.0 5.52109 -1.92808 0.0 5.505 -1.929 0.0 5.49123 -1.92764 0.0 5.47685 -1.92315 0.0 5.46325 -1.91488 0.0 5.45182 -1.90219 0.0 5.44394 -1.88444 0.0 5.441 -1.861 0.0 5.441 -1.631 0.0 5.583 -1.631 0.0 5.583 -1.551 0.0 5.441 -1.551 0.0 4.935 -1.579 0.0 4.91182 -1.56758 0.0 4.88922 -1.5583 0.0 4.86713 -1.55112 0.0 4.84544 -1.54604 0.0 4.8241 -1.543 0.0 4.803 -1.542 0.0 4.76079 -1.54576 0.0 4.72463 -1.55674 0.0 4.69525 -1.5745 0.0 4.67337 -1.59859 0.0 4.65971 -1.62857 0.0 4.655 -1.664 0.0 4.67056 -1.71771 0.0 4.70944 -1.76 0.0 4.76 -1.79412 0.0 4.81056 -1.82333 0.0 4.84944 -1.85087 0.0 4.865 -1.88 0.0 4.86261 -1.89475 0.0 4.85589 -1.907 0.0 4.8455 -1.91675 0.0 4.83211 -1.924 0.0 4.81639 -1.92875 0.0 4.799 -1.931 0.0 4.77964 -1.92941 0.0 4.75778 -1.92459 0.0 4.73375 -1.9165 0.0 4.70789 -1.90507 0.0 4.68053 -1.89026 0.0 4.652 -1.872 0.0 4.652 -1.968 0.0 4.67987 -1.98145 0.0 4.706 -1.99196 0.0 4.73112 -1.99975 0.0 4.756 -2.00504 0.0 4.78137 -2.00805 0.0 4.808 -2.009 0.0 4.84848 -2.00471 0.0 4.88415 -1.99233 0.0 4.91388 -1.97262 0.0 4.93652 -1.94633 0.0 4.95094 -1.91421 0.0 4.956 -1.877 0.0 4.95366 -1.8551 0.0 4.94626 -1.83478 0.0 4.93325 -1.81512 0.0 4.91407 -1.79522 0.0 4.88818 -1.77415 0.0 4.855 -1.751 0.0 4.8195 -1.72975 0.0 4.79163 -1.71167 0.0 4.77087 -1.69625 0.0 4.7567 -1.683 0.0 4.74859 -1.67142 0.0 4.746 -1.661 0.0 4.74787 -1.64963 0.0 4.7533 -1.6397 0.0 4.762 -1.6315 0.0 4.7737 -1.6253 0.0 4.78813 -1.62137 0.0 4.805 -1.62 0.0 4.82262 -1.62119 0.0 4.84226 -1.62485 0.0 4.86363 -1.63112 0.0 4.88641 -1.64015 0.0 4.9103 -1.65206 0.0 4.935 -1.667 0.0 4.611 -1.551 0.0 4.511 -1.551 0.0 4.395 -1.804 0.0 4.274 -1.551 0.0 4.173 -1.551 0.0 4.347 -1.904 0.0 4.194 -2.23 0.0 4.293 -2.23 0.0 4.132 -1.87 0.0 4.10606 -1.88581 0.0 4.08018 -1.89911 0.0 4.05425 -1.90975 0.0 4.02815 -1.91756 0.0 4.00177 -1.92236 0.0 3.975 -1.924 0.0 3.93493 -1.92018 0.0 3.90074 -1.90878 0.0 3.8725 -1.88988 0.0 3.85026 -1.86356 0.0 3.83407 -1.8299 0.0 3.824 -1.789 0.0 4.14 -1.789 0.0 4.13382 -1.71306 0.0 4.11589 -1.65119 0.0 4.08712 -1.60325 0.0 4.04844 -1.56915 0.0 4.00076 -1.54877 0.0 3.945 -1.542 0.0 3.88639 -1.54944 0.0 3.83544 -1.57089 0.0 3.7935 -1.605 0.0 3.76189 -1.65044 0.0 3.74194 -1.70589 0.0 3.735 -1.77 0.0 3.74143 -1.83076 0.0 3.76041 -1.88707 0.0 3.7915 -1.936 0.0 3.83426 -1.97459 0.0 3.88824 -1.99991 0.0 3.953 -2.009 0.0 3.9889 -2.00757 0.0 4.02118 -2.00326 0.0 4.05075 -1.996 0.0 4.07848 -1.98574 0.0 4.10527 -1.97243 0.0 4.132 -1.956 0.0 3.826 -1.73 0.0 3.83441 -1.69712 0.0 3.84759 -1.66967 0.0 3.8655 -1.64787 0.0 3.88807 -1.632 0.0 3.91526 -1.62229 0.0 3.947 -1.619 0.0 3.97644 -1.6225 0.0 4.00156 -1.63267 0.0 4.022 -1.649 0.0 4.03744 -1.671 0.0 4.04756 -1.69817 0.0 4.052 -1.73 0.0 3.675 -1.551 0.0 3.569 -1.551 0.0 3.37 -1.771 0.0 3.595 -2.0 0.0 3.715 -2.0 0.0 3.483 -1.771 0.0 3.366 -1.318 0.0 3.277 -1.318 0.0 3.277 -2.0 0.0 3.366 -2.0 0.0 2.61 -1.551 0.0 2.61 -2.0 0.0 2.699 -2.0 0.0 2.699 -1.765 0.0 2.70284 -1.72804 0.0 2.7137 -1.695 0.0 2.73062 -1.66712 0.0 2.75263 -1.64567 0.0 2.77875 -1.63187 0.0 2.808 -1.627 0.0 2.81956 -1.62845 0.0 2.83285 -1.63263 0.0 2.84725 -1.63925 0.0 2.86215 -1.64804 0.0 2.87694 -1.65871 0.0 2.891 -1.671 0.0 2.938 -1.594 0.0 2.91973 -1.578 0.0 2.90181 -1.56496 0.0 2.88412 -1.55487 0.0 2.86652 -1.5477 0.0 2.84886 -1.54342 0.0 2.831 -1.542 0.0 2.80991 -1.54481 0.0 2.78863 -1.55348 0.0 2.76712 -1.56837 0.0 2.74537 -1.58985 0.0 2.72334 -1.61827 0.0 2.701 -1.654 0.0 2.699 -1.654 0.0 2.699 -1.551 0.0 2.262 -1.542 0.0 2.19792 -1.55 0.0 2.141 -1.5727 0.0 2.09325 -1.60812 0.0 2.05667 -1.6543 0.0 2.03325 -1.70925 0.0 2.025 -1.771 0.0 2.03297 -1.83655 0.0 2.05578 -1.89404 0.0 2.09175 -1.94175 0.0 2.13922 -1.97796 0.0 2.19653 -2.00095 0.0 2.262 -2.009 0.0 2.33 -2.00123 0.0 2.389 -1.97885 0.0 2.4375 -1.94325 0.0 2.474 -1.89581 0.0 2.497 -1.83794 0.0 2.505 -1.771 0.0 2.49679 -1.70786 0.0 2.47333 -1.65252 0.0 2.43637 -1.60662 0.0 2.38767 -1.57181 0.0 2.32896 -1.54973 0.0 2.261 -1.622 0.0 2.30324 -1.62707 0.0 2.34022 -1.64156 0.0 2.37087 -1.66437 0.0 2.39411 -1.69444 0.0 2.40885 -1.73068 0.0 2.414 -1.772 0.0 2.40919 -1.81731 0.0 2.39522 -1.85581 0.0 2.37275 -1.88687 0.0 2.34244 -1.90985 0.0 2.30497 -1.92411 0.0 2.261 -1.929 0.0 2.2204 -1.92389 0.0 2.18519 -1.90915 0.0 2.15625 -1.88563 0.0 2.13448 -1.85419 0.0 2.12077 -1.81569 0.0 2.116 -1.771 0.0 2.12091 -1.7301 0.0 2.13493 -1.69415 0.0 2.157 -1.66425 0.0 2.18607 -1.64152 0.0 2.22109 -1.62706 0.0 1.928 -1.579 0.0 1.90482 -1.56758 0.0 1.88222 -1.5583 0.0 1.86013 -1.55112 0.0 1.83844 -1.54604 0.0 1.8171 -1.543 0.0 1.796 -1.542 0.0 1.75379 -1.54576 0.0 1.71763 -1.55674 0.0 1.68825 -1.5745 0.0 1.66637 -1.59859 0.0 1.65271 -1.62857 0.0 1.648 -1.664 0.0 1.66356 -1.71771 0.0 1.70244 -1.76 0.0 1.753 -1.79412 0.0 1.80356 -1.82333 0.0 1.84244 -1.85087 0.0 1.858 -1.88 0.0 1.85561 -1.89475 0.0 1.84889 -1.907 0.0 1.8385 -1.91675 0.0 1.82511 -1.924 0.0 1.80939 -1.92875 0.0 1.792 -1.931 0.0 1.77264 -1.92941 0.0 1.75078 -1.92459 0.0 1.72675 -1.9165 0.0 1.70089 -1.90507 0.0 1.67353 -1.89026 0.0 1.645 -1.872 0.0 1.645 -1.968 0.0 1.67287 -1.98145 0.0 1.699 -1.99196 0.0 1.72412 -1.99975 0.0 1.749 -2.00504 0.0 1.77437 -2.00805 0.0 1.801 -2.009 0.0 1.84148 -2.00471 0.0 1.87715 -1.99233 0.0 1.90687 -1.97262 0.0 1.92952 -1.94633 0.0 1.94394 -1.91421 0.0 1.949 -1.877 0.0 1.94666 -1.8551 0.0 1.93926 -1.83478 0.0 1.92625 -1.81512 0.0 1.90707 -1.79522 0.0 1.88118 -1.77415 0.0 1.848 -1.751 0.0 1.8125 -1.72975 0.0 1.78463 -1.71167 0.0 1.76387 -1.69625 0.0 1.7497 -1.683 0.0 1.74159 -1.67142 0.0 1.739 -1.661 0.0 1.74087 -1.64963 0.0 1.7463 -1.6397 0.0 1.755 -1.6315 0.0 1.7667 -1.6253 0.0 1.78113 -1.62137 0.0 1.798 -1.62 0.0 1.81562 -1.62119 0.0 1.83526 -1.62485 0.0 1.85663 -1.63112 0.0 1.87941 -1.64015 0.0 1.9033 -1.65206 0.0 1.928 -1.667 0.0 1.277 -1.551 0.0 1.277 -2.0 0.0 1.366 -2.0 0.0 1.366 -1.765 0.0 1.36984 -1.72804 0.0 1.3807 -1.695 0.0 1.39762 -1.66712 0.0 1.41963 -1.64567 0.0 1.44575 -1.63187 0.0 1.475 -1.627 0.0 1.48656 -1.62845 0.0 1.49985 -1.63263 0.0 1.51425 -1.63925 0.0 1.52915 -1.64804 0.0 1.54394 -1.65871 0.0 1.558 -1.671 0.0 1.605 -1.594 0.0 1.58673 -1.578 0.0 1.56881 -1.56496 0.0 1.55112 -1.55487 0.0 1.53352 -1.5477 0.0 1.51586 -1.54342 0.0 1.498 -1.542 0.0 1.47691 -1.54481 0.0 1.45563 -1.55348 0.0 1.43412 -1.56837 0.0 1.41237 -1.58985 0.0 1.39034 -1.61827 0.0 1.368 -1.654 0.0 1.366 -1.654 0.0 1.366 -1.551 0.0 1.145 -2.0 0.0 1.145 -1.551 0.0 1.056 -1.551 0.0 1.056 -1.872 0.0 1.04078 -1.8909 0.0 1.02426 -1.90656 0.0 1.00662 -1.91887 0.0 0.98807 -1.92778 0.0 0.9688 -1.93318 0.0 0.949 -1.935 0.0 0.921 -1.93204 0.0 0.89804 -1.92333 0.0 0.88013 -1.90912 0.0 0.8673 -1.88967 0.0 0.85958 -1.86521 0.0 0.857 -1.836 0.0 0.857 -1.551 0.0 0.768 -1.551 0.0 0.768 -1.83 0.0 0.77316 -1.88284 0.0 0.78796 -1.92707 0.0 0.81138 -1.96225 0.0 0.84237 -1.98793 0.0 0.87992 -2.00366 0.0 0.923 -2.009 0.0 0.94556 -2.00689 0.0 0.96881 -2.00078 0.0 0.99212 -1.991 0.0 1.01485 -1.97789 0.0 1.03636 -1.96178 0.0 1.056 -1.943 0.0 1.056 -2.0 0.0 0.656 -1.365 0.0 0.61124 -1.34731 0.0 0.56956 -1.33315 0.0 0.53038 -1.32237 0.0 0.49311 -1.31485 0.0 0.45718 -1.31044 0.0 0.422 -1.309 0.0 0.31895 -1.32122 0.0 0.22859 -1.35611 0.0 0.15363 -1.411 0.0 0.09674 -1.48322 0.0 0.06063 -1.57011 0.0 0.048 -1.669 0.0 0.05748 -1.74384 0.0 0.08652 -1.8207 0.0 0.136 -1.89263 0.0 0.20681 -1.95263 0.0 0.29985 -1.99375 0.0 0.416 -2.009 0.0 0.4668 -2.00699 0.0 0.5127 -2.00122 0.0 0.5545 -1.99212 0.0 0.59296 -1.98011 0.0 0.62887 -1.9656 0.0 0.663 -1.949 0.0 0.663 -1.842 0.0 0.62398 -1.86506 0.0 0.58419 -1.88419 0.0 0.544 -1.89925 0.0 0.50381 -1.91015 0.0 0.46402 -1.91677 0.0 0.425 -1.919 0.0 0.34761 -1.91044 0.0 0.28056 -1.88585 0.0 0.2255 -1.84687 0.0 0.18411 -1.79515 0.0 0.15806 -1.73231 0.0 0.149 -1.66 0.0 0.15831 -1.58858 0.0 0.18485 -1.52567 0.0 0.2265 -1.47325 0.0 0.28115 -1.43333 0.0 0.34669 -1.40792 0.0 0.421 -1.399 0.0 0.46 -1.40086 0.0 0.49837 -1.40652 0.0 0.53663 -1.41612 0.0 0.5753 -1.42981 0.0 0.61491 -1.44773 0.0 0.656 -1.47 0.0 14.542 -0.458 0.0 14.375 -0.621 0.0 14.375 -0.631 0.0 14.453 -0.631 0.0 14.453 -0.868 0.0 14.45708 -0.90657 0.0 14.4693 -0.94056 0.0 14.48962 -0.96887 0.0 14.51804 -0.99044 0.0 14.5545 -1.00418 0.0 14.599 -1.009 0.0 14.61492 -1.00796 0.0 14.633 -1.005 0.0 14.65225 -1.00038 0.0 14.67167 -0.99433 0.0 14.69025 -0.98713 0.0 14.707 -0.979 0.0 14.707 -0.896 0.0 14.68924 -0.90608 0.0 14.67193 -0.91433 0.0 14.655 -0.92075 0.0 14.63841 -0.92533 0.0 14.62209 -0.92808 0.0 14.606 -0.929 0.0 14.59223 -0.92764 0.0 14.57785 -0.92315 0.0 14.56425 -0.91487 0.0 14.55281 -0.90219 0.0 14.54494 -0.88444 0.0 14.542 -0.861 0.0 14.542 -0.631 0.0 14.684 -0.631 0.0 14.684 -0.551 0.0 14.542 -0.551 0.0 14.096 -0.542 0.0 14.03192 -0.55 0.0 13.975 -0.5727 0.0 13.92725 -0.60812 0.0 13.89067 -0.6543 0.0 13.86725 -0.70925 0.0 13.859 -0.771 0.0 13.86697 -0.83655 0.0 13.88978 -0.89404 0.0 13.92575 -0.94175 0.0 13.97322 -0.97796 0.0 14.03053 -1.00095 0.0 14.096 -1.009 0.0 14.164 -1.00123 0.0 14.223 -0.97885 0.0 14.2715 -0.94325 0.0 14.308 -0.89581 0.0 14.331 -0.83794 0.0 14.339 -0.771 0.0 14.33079 -0.70786 0.0 14.30733 -0.65252 0.0 14.27037 -0.60662 0.0 14.22167 -0.57181 0.0 14.16296 -0.54973 0.0 14.095 -0.622 0.0 14.13724 -0.62707 0.0 14.17422 -0.64156 0.0 14.20488 -0.66438 0.0 14.22811 -0.69444 0.0 14.24285 -0.73068 0.0 14.248 -0.772 0.0 14.24319 -0.81731 0.0 14.22922 -0.85581 0.0 14.20675 -0.88688 0.0 14.17644 -0.90985 0.0 14.13897 -0.92411 0.0 14.095 -0.929 0.0 14.0544 -0.92389 0.0 14.01919 -0.90915 0.0 13.99025 -0.88563 0.0 13.96848 -0.85419 0.0 13.95477 -0.81569 0.0 13.95 -0.771 0.0 13.95491 -0.7301 0.0 13.96893 -0.69415 0.0 13.991 -0.66425 0.0 14.02007 -0.64152 0.0 14.05509 -0.62706 0.0 13.473 -0.318 0.0 13.384 -0.318 0.0 13.384 -1.0 0.0 13.473 -1.0 0.0 13.473 -0.678 0.0 13.49317 -0.65687 0.0 13.51204 -0.64026 0.0 13.53012 -0.62788 0.0 13.54796 -0.61941 0.0 13.56608 -0.61455 0.0 13.585 -0.613 0.0 13.61027 -0.61649 0.0 13.63181 -0.62659 0.0 13.64925 -0.64275 0.0 13.66219 -0.66441 0.0 13.67023 -0.69101 0.0 13.673 -0.722 0.0 13.673 -1.0 0.0 13.762 -1.0 0.0 13.762 -0.725 0.0 13.75678 -0.66874 0.0 13.74189 -0.62289 0.0 13.7185 -0.58737 0.0 13.68778 -0.56211 0.0 13.65089 -0.54701 0.0 13.609 -0.542 0.0 13.58407 -0.54405 0.0 13.55959 -0.55007 0.0 13.536 -0.55987 0.0 13.51374 -0.57326 0.0 13.49326 -0.59003 0.0 13.475 -0.61 0.0 13.473 -0.61 0.0 13.262 -0.579 0.0 13.23882 -0.56758 0.0 13.21622 -0.5583 0.0 13.19412 -0.55112 0.0 13.17244 -0.54604 0.0 13.1511 -0.543 0.0 13.13 -0.542 0.0 13.08779 -0.54576 0.0 13.05163 -0.55674 0.0 13.02225 -0.5745 0.0 13.00037 -0.59859 0.0 12.98671 -0.62857 0.0 12.982 -0.664 0.0 12.99755 -0.71771 0.0 13.03644 -0.76 0.0 13.087 -0.79412 0.0 13.13755 -0.82333 0.0 13.17644 -0.85088 0.0 13.192 -0.88 0.0 13.18961 -0.89475 0.0 13.18289 -0.907 0.0 13.1725 -0.91675 0.0 13.15911 -0.924 0.0 13.14339 -0.92875 0.0 13.126 -0.931 0.0 13.10664 -0.92941 0.0 13.08478 -0.92459 0.0 13.06075 -0.9165 0.0 13.03489 -0.90507 0.0 13.00753 -0.89026 0.0 12.979 -0.872 0.0 12.979 -0.968 0.0 13.00688 -0.98145 0.0 13.033 -0.99196 0.0 13.05812 -0.99975 0.0 13.083 -1.00504 0.0 13.10837 -1.00805 0.0 13.135 -1.009 0.0 13.17548 -1.00471 0.0 13.21115 -0.99233 0.0 13.24087 -0.97262 0.0 13.26352 -0.94633 0.0 13.27794 -0.91421 0.0 13.283 -0.877 0.0 13.28066 -0.8551 0.0 13.27326 -0.83478 0.0 13.26025 -0.81512 0.0 13.24107 -0.79522 0.0 13.21518 -0.77415 0.0 13.182 -0.751 0.0 13.1465 -0.72975 0.0 13.11863 -0.71167 0.0 13.09788 -0.69625 0.0 13.0837 -0.683 0.0 13.07559 -0.67142 0.0 13.073 -0.661 0.0 13.07487 -0.64963 0.0 13.0803 -0.6397 0.0 13.089 -0.6315 0.0 13.1007 -0.6253 0.0 13.11513 -0.62137 0.0 13.132 -0.62 0.0 13.14962 -0.62119 0.0 13.16926 -0.62485 0.0 13.19063 -0.63113 0.0 13.21341 -0.64015 0.0 13.2373 -0.65206 0.0 13.262 -0.667 0.0 12.66 -0.551 0.0 12.56 -0.551 0.0 12.444 -0.804 0.0 12.323 -0.551 0.0 12.222 -0.551 0.0 12.396 -0.904 0.0 12.243 -1.23 0.0 12.342 -1.23 0.0 12.157 -0.318 0.0 12.068 -0.318 0.0 12.068 -1.0 0.0 12.157 -1.0 0.0 11.649 -0.989 0.0 11.66546 -0.99534 0.0 11.681 -1.00041 0.0 11.69588 -1.00425 0.0 11.71033 -1.00693 0.0 11.72463 -1.00849 0.0 11.739 -1.009 0.0 11.80207 -1.00134 0.0 11.85722 -0.97937 0.0 11.90287 -0.94462 0.0 11.93744 -0.89863 0.0 11.95935 -0.84291 0.0 11.967 -0.779 0.0 11.95965 -0.71072 0.0 11.93785 -0.65411 0.0 11.902 -0.6095 0.0 11.85248 -0.57722 0.0 11.78969 -0.55761 0.0 11.714 -0.551 0.0 11.56 -0.551 0.0 11.56 -1.23 0.0 11.649 -1.23 0.0 11.649 -0.631 0.0 11.73 -0.631 0.0 11.7745 -0.63543 0.0 11.81096 -0.64844 0.0 11.83938 -0.66962 0.0 11.8597 -0.69856 0.0 11.87192 -0.73482 0.0 11.876 -0.778 0.0 11.87117 -0.81939 0.0 11.85737 -0.85581 0.0 11.83563 -0.88613 0.0 11.80696 -0.90919 0.0 11.77241 -0.92386 0.0 11.733 -0.929 0.0 11.71893 -0.92842 0.0 11.70478 -0.9267 0.0 11.69063 -0.92387 0.0 11.67656 -0.91996 0.0 11.66265 -0.915 0.0 11.649 -0.909 0.0 11.149 -0.989 0.0 11.16546 -0.99534 0.0 11.181 -1.00041 0.0 11.19588 -1.00425 0.0 11.21033 -1.00693 0.0 11.22463 -1.00849 0.0 11.239 -1.009 0.0 11.30207 -1.00134 0.0 11.35722 -0.97937 0.0 11.40287 -0.94462 0.0 11.43744 -0.89863 0.0 11.45935 -0.84291 0.0 11.467 -0.779 0.0 11.45965 -0.71072 0.0 11.43785 -0.65411 0.0 11.402 -0.6095 0.0 11.35248 -0.57722 0.0 11.28969 -0.55761 0.0 11.214 -0.551 0.0 11.06 -0.551 0.0 11.06 -1.23 0.0 11.149 -1.23 0.0 11.149 -0.631 0.0 11.23 -0.631 0.0 11.2745 -0.63543 0.0 11.31096 -0.64844 0.0 11.33938 -0.66962 0.0 11.3597 -0.69856 0.0 11.37192 -0.73482 0.0 11.376 -0.778 0.0 11.37117 -0.81939 0.0 11.35737 -0.85581 0.0 11.33563 -0.88613 0.0 11.30696 -0.90919 0.0 11.27241 -0.92386 0.0 11.233 -0.929 0.0 11.21893 -0.92842 0.0 11.20478 -0.9267 0.0 11.19063 -0.92387 0.0 11.17656 -0.91996 0.0 11.16265 -0.915 0.0 11.149 -0.909 0.0 10.987 -0.92 0.0 10.9772 -0.92699 0.0 10.96793 -0.93289 0.0 10.95938 -0.93762 0.0 10.95174 -0.94111 0.0 10.94522 -0.94326 0.0 10.94 -0.944 0.0 10.93492 -0.94348 0.0 10.9307 -0.94181 0.0 10.92737 -0.93888 0.0 10.92496 -0.93452 0.0 10.9235 -0.92861 0.0 10.923 -0.921 0.0 10.923 -0.69 0.0 10.91725 -0.64362 0.0 10.90096 -0.6063 0.0 10.87563 -0.57775 0.0 10.8427 -0.5577 0.0 10.80367 -0.54588 0.0 10.76 -0.542 0.0 10.72882 -0.54367 0.0 10.70026 -0.5487 0.0 10.67425 -0.55712 0.0 10.65074 -0.56896 0.0 10.62968 -0.58425 0.0 10.611 -0.603 0.0 10.611 -0.7 0.0 10.63305 -0.67681 0.0 10.65604 -0.65815 0.0 10.67975 -0.64387 0.0 10.70396 -0.63385 0.0 10.72845 -0.62794 0.0 10.753 -0.626 0.0 10.77775 -0.62796 0.0 10.798 -0.63404 0.0 10.81375 -0.6445 0.0 10.825 -0.65963 0.0 10.83175 -0.6797 0.0 10.834 -0.705 0.0 10.834 -0.729 0.0 10.755 -0.757 0.0 10.71867 -0.77037 0.0 10.68333 -0.78559 0.0 10.6515 -0.80437 0.0 10.62567 -0.82841 0.0 10.60833 -0.85938 0.0 10.602 -0.899 0.0 10.60557 -0.92729 0.0 10.61585 -0.9533 0.0 10.63225 -0.97575 0.0 10.65415 -0.99337 0.0 10.68094 -1.00488 0.0 10.712 -1.009 0.0 10.73249 -1.00775 0.0 10.75293 -1.00396 0.0 10.77325 -0.99762 0.0 10.79341 -0.9887 0.0 10.81334 -0.97717 0.0 10.833 -0.963 0.0 10.83811 -0.97752 0.0 10.84552 -0.98915 0.0 10.85538 -0.998 0.0 10.86782 -1.00419 0.0 10.88298 -1.00781 0.0 10.901 -1.009 0.0 10.91425 -1.00828 0.0 10.92663 -1.00593 0.0 10.93913 -1.00162 0.0 10.9527 -0.99507 0.0 10.96834 -0.98597 0.0 10.987 -0.974 0.0 10.834 -0.909 0.0 10.82183 -0.91973 0.0 10.80933 -0.92881 0.0 10.7965 -0.93613 0.0 10.78333 -0.94152 0.0 10.76983 -0.94486 0.0 10.756 -0.946 0.0 10.73841 -0.9439 0.0 10.72296 -0.93789 0.0 10.71012 -0.92838 0.0 10.70037 -0.91578 0.0 10.69417 -0.90051 0.0 10.692 -0.883 0.0 10.69724 -0.85862 0.0 10.71193 -0.838 0.0 10.7345 -0.82038 0.0 10.76341 -0.805 0.0 10.79709 -0.79112 0.0 10.834 -0.778 0.0 10.019 -0.542 0.0 9.95492 -0.55 0.0 9.898 -0.5727 0.0 9.85025 -0.60812 0.0 9.81367 -0.6543 0.0 9.79025 -0.70925 0.0 9.782 -0.771 0.0 9.78997 -0.83655 0.0 9.81278 -0.89404 0.0 9.84875 -0.94175 0.0 9.89622 -0.97796 0.0 9.95353 -1.00095 0.0 10.019 -1.009 0.0 10.087 -1.00123 0.0 10.146 -0.97885 0.0 10.1945 -0.94325 0.0 10.231 -0.89581 0.0 10.254 -0.83794 0.0 10.262 -0.771 0.0 10.25379 -0.70786 0.0 10.23033 -0.65252 0.0 10.19337 -0.60662 0.0 10.14467 -0.57181 0.0 10.08596 -0.54973 0.0 10.018 -0.622 0.0 10.06024 -0.62707 0.0 10.09722 -0.64156 0.0 10.12788 -0.66438 0.0 10.15111 -0.69444 0.0 10.16585 -0.73068 0.0 10.171 -0.772 0.0 10.16619 -0.81731 0.0 10.15222 -0.85581 0.0 10.12975 -0.88688 0.0 10.09944 -0.90985 0.0 10.06197 -0.92411 0.0 10.018 -0.929 0.0 9.9774 -0.92389 0.0 9.94219 -0.90915 0.0 9.91325 -0.88563 0.0 9.89148 -0.85419 0.0 9.87777 -0.81569 0.0 9.873 -0.771 0.0 9.87791 -0.7301 0.0 9.89193 -0.69415 0.0 9.914 -0.66425 0.0 9.94307 -0.64152 0.0 9.97809 -0.62706 0.0 9.58 -0.458 0.0 9.413 -0.621 0.0 9.413 -0.631 0.0 9.491 -0.631 0.0 9.491 -0.868 0.0 9.49508 -0.90657 0.0 9.5073 -0.94056 0.0 9.52763 -0.96887 0.0 9.55604 -0.99044 0.0 9.5925 -1.00418 0.0 9.637 -1.009 0.0 9.65292 -1.00796 0.0 9.671 -1.005 0.0 9.69025 -1.00038 0.0 9.70967 -0.99433 0.0 9.72825 -0.98713 0.0 9.745 -0.979 0.0 9.745 -0.896 0.0 9.72724 -0.90608 0.0 9.70993 -0.91433 0.0 9.693 -0.92075 0.0 9.67641 -0.92533 0.0 9.66009 -0.92808 0.0 9.644 -0.929 0.0 9.63023 -0.92764 0.0 9.61585 -0.92315 0.0 9.60225 -0.91487 0.0 9.59081 -0.90219 0.0 9.58294 -0.88444 0.0 9.58 -0.861 0.0 9.58 -0.631 0.0 9.722 -0.631 0.0 9.722 -0.551 0.0 9.58 -0.551 0.0 9.094 -0.87 0.0 9.06806 -0.88581 0.0 9.04218 -0.89911 0.0 9.01625 -0.90975 0.0 8.99015 -0.91756 0.0 8.96377 -0.92236 0.0 8.937 -0.924 0.0 8.89693 -0.92018 0.0 8.86274 -0.90878 0.0 8.8345 -0.88987 0.0 8.81226 -0.86356 0.0 8.79607 -0.8299 0.0 8.786 -0.789 0.0 9.102 -0.789 0.0 9.09582 -0.71306 0.0 9.07789 -0.65119 0.0 9.04912 -0.60325 0.0 9.01044 -0.56915 0.0 8.96276 -0.54877 0.0 8.907 -0.542 0.0 8.84839 -0.54944 0.0 8.79745 -0.57089 0.0 8.7555 -0.605 0.0 8.72389 -0.65044 0.0 8.70395 -0.70589 0.0 8.697 -0.77 0.0 8.70343 -0.83076 0.0 8.72241 -0.88707 0.0 8.7535 -0.936 0.0 8.79626 -0.97459 0.0 8.85024 -0.99991 0.0 8.915 -1.009 0.0 8.9509 -1.00757 0.0 8.98318 -1.00326 0.0 9.01275 -0.996 0.0 9.04048 -0.98574 0.0 9.06727 -0.97243 0.0 9.094 -0.956 0.0 8.788 -0.73 0.0 8.79641 -0.69713 0.0 8.80959 -0.66967 0.0 8.8275 -0.64787 0.0 8.85007 -0.632 0.0 8.87726 -0.62229 0.0 8.909 -0.619 0.0 8.93845 -0.6225 0.0 8.96356 -0.63267 0.0 8.984 -0.649 0.0 8.99944 -0.671 0.0 9.00956 -0.69817 0.0 9.014 -0.73 0.0 8.595 -0.579 0.0 8.57182 -0.56758 0.0 8.54922 -0.5583 0.0 8.52712 -0.55112 0.0 8.50544 -0.54604 0.0 8.4841 -0.543 0.0 8.463 -0.542 0.0 8.42079 -0.54576 0.0 8.38463 -0.55674 0.0 8.35525 -0.5745 0.0 8.33337 -0.59859 0.0 8.31971 -0.62857 0.0 8.315 -0.664 0.0 8.33055 -0.71771 0.0 8.36944 -0.76 0.0 8.42 -0.79412 0.0 8.47055 -0.82333 0.0 8.50944 -0.85088 0.0 8.525 -0.88 0.0 8.52261 -0.89475 0.0 8.51589 -0.907 0.0 8.5055 -0.91675 0.0 8.49211 -0.924 0.0 8.47639 -0.92875 0.0 8.459 -0.931 0.0 8.43964 -0.92941 0.0 8.41778 -0.92459 0.0 8.39375 -0.9165 0.0 8.36789 -0.90507 0.0 8.34053 -0.89026 0.0 8.312 -0.872 0.0 8.312 -0.968 0.0 8.33988 -0.98145 0.0 8.366 -0.99196 0.0 8.39112 -0.99975 0.0 8.416 -1.00504 0.0 8.44137 -1.00805 0.0 8.468 -1.009 0.0 8.50848 -1.00471 0.0 8.54415 -0.99233 0.0 8.57387 -0.97262 0.0 8.59652 -0.94633 0.0 8.61094 -0.91421 0.0 8.616 -0.877 0.0 8.61366 -0.8551 0.0 8.60626 -0.83478 0.0 8.59325 -0.81512 0.0 8.57407 -0.79522 0.0 8.54818 -0.77415 0.0 8.515 -0.751 0.0 8.4795 -0.72975 0.0 8.45163 -0.71167 0.0 8.43088 -0.69625 0.0 8.4167 -0.683 0.0 8.40859 -0.67142 0.0 8.406 -0.661 0.0 8.40787 -0.64963 0.0 8.4133 -0.6397 0.0 8.422 -0.6315 0.0 8.4337 -0.6253 0.0 8.44813 -0.62137 0.0 8.465 -0.62 0.0 8.48262 -0.62119 0.0 8.50226 -0.62485 0.0 8.52363 -0.63113 0.0 8.54641 -0.64015 0.0 8.5703 -0.65206 0.0 8.595 -0.667 0.0 8.208 -1.0 0.0 8.208 -0.551 0.0 8.119 -0.551 0.0 8.119 -0.872 0.0 8.10378 -0.8909 0.0 8.08726 -0.90656 0.0 8.06962 -0.91887 0.0 8.05107 -0.92778 0.0 8.0318 -0.93318 0.0 8.012 -0.935 0.0 7.984 -0.93204 0.0 7.96104 -0.92333 0.0 7.94313 -0.90912 0.0 7.9303 -0.88967 0.0 7.92258 -0.86521 0.0 7.92 -0.836 0.0 7.92 -0.551 0.0 7.831 -0.551 0.0 7.831 -0.83 0.0 7.83616 -0.88284 0.0 7.85096 -0.92707 0.0 7.87438 -0.96225 0.0 7.90537 -0.98793 0.0 7.94292 -1.00366 0.0 7.986 -1.009 0.0 8.00856 -1.00689 0.0 8.03182 -1.00078 0.0 8.05513 -0.991 0.0 8.07785 -0.97789 0.0 8.09936 -0.96178 0.0 8.119 -0.943 0.0 8.119 -1.0 0.0 7.492 -0.542 0.0 7.42792 -0.55 0.0 7.371 -0.5727 0.0 7.32325 -0.60812 0.0 7.28667 -0.6543 0.0 7.26325 -0.70925 0.0 7.255 -0.771 0.0 7.26297 -0.83655 0.0 7.28578 -0.89404 0.0 7.32175 -0.94175 0.0 7.36922 -0.97796 0.0 7.42653 -1.00095 0.0 7.492 -1.009 0.0 7.56 -1.00123 0.0 7.619 -0.97885 0.0 7.6675 -0.94325 0.0 7.704 -0.89581 0.0 7.727 -0.83794 0.0 7.735 -0.771 0.0 7.72679 -0.70786 0.0 7.70333 -0.65252 0.0 7.66638 -0.60662 0.0 7.61767 -0.57181 0.0 7.55896 -0.54973 0.0 7.491 -0.622 0.0 7.53324 -0.62707 0.0 7.57022 -0.64156 0.0 7.60088 -0.66438 0.0 7.62411 -0.69444 0.0 7.63885 -0.73068 0.0 7.644 -0.772 0.0 7.63919 -0.81731 0.0 7.62522 -0.85581 0.0 7.60275 -0.88688 0.0 7.57244 -0.90985 0.0 7.53497 -0.92411 0.0 7.491 -0.929 0.0 7.4504 -0.92389 0.0 7.41519 -0.90915 0.0 7.38625 -0.88563 0.0 7.36448 -0.85419 0.0 7.35077 -0.81569 0.0 7.346 -0.771 0.0 7.35091 -0.7301 0.0 7.36493 -0.69415 0.0 7.387 -0.66425 0.0 7.41607 -0.64152 0.0 7.45109 -0.62706 0.0 6.507 -0.551 0.0 6.507 -1.0 0.0 6.596 -1.0 0.0 6.596 -0.674 0.0 6.61402 -0.65485 0.0 6.63148 -0.64011 0.0 6.649 -0.62937 0.0 6.66719 -0.62222 0.0 6.68665 -0.61824 0.0 6.708 -0.617 0.0 6.72928 -0.61963 0.0 6.74856 -0.62774 0.0 6.765 -0.64162 0.0 6.77778 -0.66159 0.0 6.78606 -0.68795 0.0 6.789 -0.721 0.0 6.789 -1.0 0.0 6.878 -1.0 0.0 6.878 -0.674 0.0 6.89451 -0.65825 0.0 6.9117 -0.64433 0.0 6.92913 -0.63275 0.0 6.9463 -0.624 0.0 6.96275 -0.61858 0.0 6.978 -0.617 0.0 7.0026 -0.62006 0.0 7.02478 -0.62911 0.0 7.04363 -0.644 0.0 7.05822 -0.66456 0.0 7.06765 -0.69061 0.0 7.071 -0.722 0.0 7.071 -1.0 0.0 7.16 -1.0 0.0 7.16 -0.718 0.0 7.15528 -0.66816 0.0 7.14159 -0.62526 0.0 7.11963 -0.59025 0.0 7.09007 -0.56407 0.0 7.05363 -0.54768 0.0 7.011 -0.542 0.0 6.98038 -0.54494 0.0 6.95233 -0.55322 0.0 6.92663 -0.566 0.0 6.903 -0.58244 0.0 6.88121 -0.60172 0.0 6.861 -0.623 0.0 6.84462 -0.5986 0.0 6.82559 -0.57844 0.0 6.80413 -0.56262 0.0 6.78041 -0.55122 0.0 6.75463 -0.54432 0.0 6.727 -0.542 0.0 6.70591 -0.54384 0.0 6.68459 -0.54941 0.0 6.663 -0.55875 0.0 6.64107 -0.57193 0.0 6.61876 -0.58899 0.0 6.596 -0.61 0.0 6.596 -0.551 0.0 6.004 -0.458 0.0 5.837 -0.621 0.0 5.837 -0.631 0.0 5.915 -0.631 0.0 5.915 -0.868 0.0 5.91908 -0.90657 0.0 5.9313 -0.94056 0.0 5.95163 -0.96887 0.0 5.98004 -0.99044 0.0 6.0165 -1.00418 0.0 6.061 -1.009 0.0 6.07692 -1.00796 0.0 6.095 -1.005 0.0 6.11425 -1.00038 0.0 6.13367 -0.99433 0.0 6.15225 -0.98713 0.0 6.169 -0.979 0.0 6.169 -0.896 0.0 6.15124 -0.90608 0.0 6.13393 -0.91433 0.0 6.117 -0.92075 0.0 6.10041 -0.92533 0.0 6.08409 -0.92808 0.0 6.068 -0.929 0.0 6.05423 -0.92764 0.0 6.03985 -0.92315 0.0 6.02625 -0.91487 0.0 6.01482 -0.90219 0.0 6.00694 -0.88444 0.0 6.004 -0.861 0.0 6.004 -0.631 0.0 6.146 -0.631 0.0 6.146 -0.551 0.0 6.004 -0.551 0.0 5.883 -0.318 0.0 5.84619 -0.31024 0.0 5.81348 -0.30859 0.0 5.7845 -0.3125 0.0 5.75885 -0.32141 0.0 5.73615 -0.33476 0.0 5.716 -0.352 0.0 5.69928 -0.37069 0.0 5.68522 -0.39148 0.0 5.674 -0.4155 0.0 5.66578 -0.44385 0.0 5.66072 -0.47765 0.0 5.659 -0.518 0.0 5.659 -0.551 0.0 5.596 -0.551 0.0 5.596 -0.631 0.0 5.659 -0.631 0.0 5.659 -1.0 0.0 5.748 -1.0 0.0 5.748 -0.631 0.0 5.829 -0.631 0.0 5.829 -0.551 0.0 5.748 -0.551 0.0 5.748 -0.508 0.0 5.75004 -0.47582 0.0 5.75663 -0.44856 0.0 5.7685 -0.42662 0.0 5.78637 -0.41044 0.0 5.81096 -0.40043 0.0 5.843 -0.397 0.0 5.85048 -0.39718 0.0 5.85715 -0.39774 0.0 5.86338 -0.39875 0.0 5.86952 -0.40026 0.0 5.87594 -0.40232 0.0 5.883 -0.405 0.0 5.546 -0.87 0.0 5.52007 -0.88581 0.0 5.49419 -0.89911 0.0 5.46825 -0.90975 0.0 5.44215 -0.91756 0.0 5.41577 -0.92236 0.0 5.389 -0.924 0.0 5.34893 -0.92018 0.0 5.31474 -0.90878 0.0 5.2865 -0.88987 0.0 5.26426 -0.86356 0.0 5.24807 -0.8299 0.0 5.238 -0.789 0.0 5.554 -0.789 0.0 5.54782 -0.71306 0.0 5.52989 -0.65119 0.0 5.50113 -0.60325 0.0 5.46244 -0.56915 0.0 5.41476 -0.54877 0.0 5.359 -0.542 0.0 5.30039 -0.54944 0.0 5.24944 -0.57089 0.0 5.2075 -0.605 0.0 5.17589 -0.65044 0.0 5.15594 -0.70589 0.0 5.149 -0.77 0.0 5.15543 -0.83076 0.0 5.17441 -0.88707 0.0 5.2055 -0.936 0.0 5.24826 -0.97459 0.0 5.30224 -0.99991 0.0 5.367 -1.009 0.0 5.4029 -1.00757 0.0 5.43519 -1.00326 0.0 5.46475 -0.996 0.0 5.49248 -0.98574 0.0 5.51927 -0.97243 0.0 5.546 -0.956 0.0 5.24 -0.73 0.0 5.24841 -0.69713 0.0 5.26159 -0.66967 0.0 5.2795 -0.64787 0.0 5.30207 -0.632 0.0 5.32926 -0.62229 0.0 5.361 -0.619 0.0 5.39044 -0.6225 0.0 5.41556 -0.63267 0.0 5.436 -0.649 0.0 5.45144 -0.671 0.0 5.46156 -0.69817 0.0 5.466 -0.73 0.0 5.043 -0.318 0.0 4.954 -0.318 0.0 4.954 -1.0 0.0 5.043 -1.0 0.0 4.451 -1.118 0.0 4.4871 -1.10365 0.0 4.51645 -1.08356 0.0 4.53913 -1.05913 0.0 4.55522 -1.03178 0.0 4.56482 -1.00293 0.0 4.568 -0.974 0.0 4.56573 -0.94633 0.0 4.55915 -0.92263 0.0 4.54863 -0.90338 0.0 4.53452 -0.88904 0.0 4.51719 -0.88009 0.0 4.497 -0.877 0.0 4.48082 -0.87893 0.0 4.46659 -0.88444 0.0 4.45475 -0.89312 0.0 4.44574 -0.90456 0.0 4.44001 -0.91832 0.0 4.438 -0.934 0.0 4.43962 -0.94954 0.0 4.44426 -0.96296 0.0 4.45163 -0.974 0.0 4.46141 -0.98237 0.0 4.4733 -0.9878 0.0 4.487 -0.99 0.0 4.48975 -1.00905 0.0 4.489 -1.02937 0.0 4.48475 -1.04975 0.0 4.477 -1.06896 0.0 4.46575 -1.08579 0.0 4.451 -1.099 0.0 3.68 -0.551 0.0 3.68 -1.0 0.0 3.769 -1.0 0.0 3.769 -0.674 0.0 3.78702 -0.65485 0.0 3.80448 -0.64011 0.0 3.822 -0.62937 0.0 3.84019 -0.62222 0.0 3.85965 -0.61824 0.0 3.881 -0.617 0.0 3.90228 -0.61963 0.0 3.92156 -0.62774 0.0 3.938 -0.64162 0.0 3.95078 -0.66159 0.0 3.95906 -0.68795 0.0 3.962 -0.721 0.0 3.962 -1.0 0.0 4.051 -1.0 0.0 4.051 -0.674 0.0 4.06751 -0.65825 0.0 4.0847 -0.64433 0.0 4.10213 -0.63275 0.0 4.1193 -0.624 0.0 4.13575 -0.61858 0.0 4.151 -0.617 0.0 4.1756 -0.62006 0.0 4.19778 -0.62911 0.0 4.21663 -0.644 0.0 4.23122 -0.66456 0.0 4.24065 -0.69061 0.0 4.244 -0.722 0.0 4.244 -1.0 0.0 4.333 -1.0 0.0 4.333 -0.718 0.0 4.32828 -0.66816 0.0 4.31459 -0.62526 0.0 4.29263 -0.59025 0.0 4.26307 -0.56407 0.0 4.22663 -0.54768 0.0 4.184 -0.542 0.0 4.15338 -0.54494 0.0 4.12533 -0.55322 0.0 4.09963 -0.566 0.0 4.076 -0.58244 0.0 4.05421 -0.60172 0.0 4.034 -0.623 0.0 4.01762 -0.5986 0.0 3.99859 -0.57844 0.0 3.97713 -0.56262 0.0 3.95341 -0.55122 0.0 3.92763 -0.54432 0.0 3.9 -0.542 0.0 3.87891 -0.54384 0.0 3.85759 -0.54941 0.0 3.836 -0.55875 0.0 3.81407 -0.57193 0.0 3.79176 -0.58899 0.0 3.769 -0.61 0.0 3.769 -0.551 0.0 3.556 -0.551 0.0 3.467 -0.551 0.0 3.467 -1.0 0.0 3.556 -1.0 0.0 3.565 -0.415 0.0 3.56309 -0.401 0.0 3.5577 -0.38837 0.0 3.54938 -0.37762 0.0 3.53863 -0.3693 0.0 3.526 -0.36391 0.0 3.512 -0.362 0.0 3.498 -0.36391 0.0 3.48537 -0.3693 0.0 3.47463 -0.37762 0.0 3.4663 -0.38837 0.0 3.46091 -0.401 0.0 3.459 -0.415 0.0 3.46091 -0.429 0.0 3.4663 -0.44163 0.0 3.47463 -0.45237 0.0 3.48537 -0.4607 0.0 3.498 -0.46609 0.0 3.512 -0.468 0.0 3.526 -0.46609 0.0 3.53863 -0.4607 0.0 3.54938 -0.45237 0.0 3.5577 -0.44163 0.0 3.56309 -0.429 0.0 3.386 -0.92 0.0 3.3762 -0.92699 0.0 3.36693 -0.93289 0.0 3.35838 -0.93762 0.0 3.35074 -0.94111 0.0 3.34422 -0.94326 0.0 3.339 -0.944 0.0 3.33392 -0.94348 0.0 3.3297 -0.94181 0.0 3.32638 -0.93888 0.0 3.32396 -0.93452 0.0 3.3225 -0.92861 0.0 3.322 -0.921 0.0 3.322 -0.69 0.0 3.31625 -0.64362 0.0 3.29996 -0.6063 0.0 3.27463 -0.57775 0.0 3.2417 -0.5577 0.0 3.20267 -0.54588 0.0 3.159 -0.542 0.0 3.12782 -0.54367 0.0 3.09926 -0.5487 0.0 3.07325 -0.55712 0.0 3.04974 -0.56896 0.0 3.02868 -0.58425 0.0 3.01 -0.603 0.0 3.01 -0.7 0.0 3.03205 -0.67681 0.0 3.05504 -0.65815 0.0 3.07875 -0.64387 0.0 3.10296 -0.63385 0.0 3.12745 -0.62794 0.0 3.152 -0.626 0.0 3.17675 -0.62796 0.0 3.197 -0.63404 0.0 3.21275 -0.6445 0.0 3.224 -0.65963 0.0 3.23075 -0.6797 0.0 3.233 -0.705 0.0 3.233 -0.729 0.0 3.154 -0.757 0.0 3.11767 -0.77037 0.0 3.08233 -0.78559 0.0 3.0505 -0.80437 0.0 3.02467 -0.82841 0.0 3.00733 -0.85938 0.0 3.001 -0.899 0.0 3.00457 -0.92729 0.0 3.01485 -0.9533 0.0 3.03125 -0.97575 0.0 3.05315 -0.99337 0.0 3.07994 -1.00488 0.0 3.111 -1.009 0.0 3.13149 -1.00775 0.0 3.15193 -1.00396 0.0 3.17225 -0.99762 0.0 3.19241 -0.9887 0.0 3.21234 -0.97717 0.0 3.232 -0.963 0.0 3.23711 -0.97752 0.0 3.24452 -0.98915 0.0 3.25438 -0.998 0.0 3.26681 -1.00419 0.0 3.28198 -1.00781 0.0 3.3 -1.009 0.0 3.31325 -1.00828 0.0 3.32563 -1.00593 0.0 3.33813 -1.00162 0.0 3.3517 -0.99507 0.0 3.36734 -0.98597 0.0 3.386 -0.974 0.0 3.233 -0.909 0.0 3.22083 -0.91973 0.0 3.20833 -0.92881 0.0 3.1955 -0.93613 0.0 3.18233 -0.94152 0.0 3.16883 -0.94486 0.0 3.155 -0.946 0.0 3.13741 -0.9439 0.0 3.12196 -0.93789 0.0 3.10913 -0.92838 0.0 3.09937 -0.91578 0.0 3.09317 -0.90051 0.0 3.091 -0.883 0.0 3.09624 -0.85862 0.0 3.11093 -0.838 0.0 3.1335 -0.82038 0.0 3.16241 -0.805 0.0 3.19609 -0.79112 0.0 3.233 -0.778 0.0 2.656 -0.87 0.0 2.63006 -0.88581 0.0 2.60419 -0.89911 0.0 2.57825 -0.90975 0.0 2.55215 -0.91756 0.0 2.52577 -0.92236 0.0 2.499 -0.924 0.0 2.45893 -0.92018 0.0 2.42474 -0.90878 0.0 2.3965 -0.88987 0.0 2.37426 -0.86356 0.0 2.35807 -0.8299 0.0 2.348 -0.789 0.0 2.664 -0.789 0.0 2.65782 -0.71306 0.0 2.63989 -0.65119 0.0 2.61113 -0.60325 0.0 2.57244 -0.56915 0.0 2.52476 -0.54877 0.0 2.469 -0.542 0.0 2.41039 -0.54944 0.0 2.35944 -0.57089 0.0 2.3175 -0.605 0.0 2.28589 -0.65044 0.0 2.26594 -0.70589 0.0 2.259 -0.77 0.0 2.26543 -0.83076 0.0 2.28441 -0.88707 0.0 2.3155 -0.936 0.0 2.35826 -0.97459 0.0 2.41224 -0.99991 0.0 2.477 -1.009 0.0 2.5129 -1.00757 0.0 2.54519 -1.00326 0.0 2.57475 -0.996 0.0 2.60248 -0.98574 0.0 2.62927 -0.97243 0.0 2.656 -0.956 0.0 2.35 -0.73 0.0 2.35841 -0.69713 0.0 2.37159 -0.66967 0.0 2.3895 -0.64787 0.0 2.41207 -0.632 0.0 2.43926 -0.62229 0.0 2.471 -0.619 0.0 2.50044 -0.6225 0.0 2.52556 -0.63267 0.0 2.546 -0.649 0.0 2.56144 -0.671 0.0 2.57156 -0.69817 0.0 2.576 -0.73 0.0 2.157 -0.579 0.0 2.13382 -0.56758 0.0 2.11122 -0.5583 0.0 2.08913 -0.55112 0.0 2.06744 -0.54604 0.0 2.0461 -0.543 0.0 2.025 -0.542 0.0 1.98279 -0.54576 0.0 1.94663 -0.55674 0.0 1.91725 -0.5745 0.0 1.89537 -0.59859 0.0 1.88171 -0.62857 0.0 1.877 -0.664 0.0 1.89256 -0.71771 0.0 1.93144 -0.76 0.0 1.982 -0.79412 0.0 2.03256 -0.82333 0.0 2.07144 -0.85088 0.0 2.087 -0.88 0.0 2.08461 -0.89475 0.0 2.07789 -0.907 0.0 2.0675 -0.91675 0.0 2.05411 -0.924 0.0 2.03839 -0.92875 0.0 2.021 -0.931 0.0 2.00164 -0.92941 0.0 1.97978 -0.92459 0.0 1.95575 -0.9165 0.0 1.92989 -0.90507 0.0 1.90253 -0.89026 0.0 1.874 -0.872 0.0 1.874 -0.968 0.0 1.90188 -0.98145 0.0 1.928 -0.99196 0.0 1.95313 -0.99975 0.0 1.978 -1.00504 0.0 2.00337 -1.00805 0.0 2.03 -1.009 0.0 2.07048 -1.00471 0.0 2.10615 -0.99233 0.0 2.13587 -0.97262 0.0 2.15852 -0.94633 0.0 2.17294 -0.91421 0.0 2.178 -0.877 0.0 2.17566 -0.8551 0.0 2.16826 -0.83478 0.0 2.15525 -0.81512 0.0 2.13607 -0.79522 0.0 2.11018 -0.77415 0.0 2.077 -0.751 0.0 2.0415 -0.72975 0.0 2.01363 -0.71167 0.0 1.99288 -0.69625 0.0 1.9787 -0.683 0.0 1.97059 -0.67142 0.0 1.968 -0.661 0.0 1.96987 -0.64963 0.0 1.9753 -0.6397 0.0 1.984 -0.6315 0.0 1.9957 -0.6253 0.0 2.01013 -0.62137 0.0 2.027 -0.62 0.0 2.04462 -0.62119 0.0 2.06426 -0.62485 0.0 2.08562 -0.63113 0.0 2.10841 -0.64015 0.0 2.1323 -0.65206 0.0 2.157 -0.667 0.0 1.77 -1.0 0.0 1.77 -0.551 0.0 1.681 -0.551 0.0 1.681 -0.872 0.0 1.66578 -0.8909 0.0 1.64926 -0.90656 0.0 1.63163 -0.91887 0.0 1.61307 -0.92778 0.0 1.5938 -0.93318 0.0 1.574 -0.935 0.0 1.546 -0.93204 0.0 1.52304 -0.92333 0.0 1.50513 -0.90912 0.0 1.4923 -0.88967 0.0 1.48458 -0.86521 0.0 1.482 -0.836 0.0 1.482 -0.551 0.0 1.393 -0.551 0.0 1.393 -0.83 0.0 1.39816 -0.88284 0.0 1.41296 -0.92707 0.0 1.43638 -0.96225 0.0 1.46737 -0.98793 0.0 1.50492 -1.00366 0.0 1.548 -1.009 0.0 1.57056 -1.00689 0.0 1.59381 -1.00078 0.0 1.61713 -0.991 0.0 1.63985 -0.97789 0.0 1.66136 -0.96178 0.0 1.681 -0.943 0.0 1.681 -1.0 0.0 1.054 -0.542 0.0 0.98992 -0.55 0.0 0.933 -0.5727 0.0 0.88525 -0.60812 0.0 0.84867 -0.6543 0.0 0.82525 -0.70925 0.0 0.817 -0.771 0.0 0.82497 -0.83655 0.0 0.84778 -0.89404 0.0 0.88375 -0.94175 0.0 0.93122 -0.97796 0.0 0.98853 -1.00095 0.0 1.054 -1.009 0.0 1.122 -1.00123 0.0 1.181 -0.97885 0.0 1.2295 -0.94325 0.0 1.266 -0.89581 0.0 1.289 -0.83794 0.0 1.297 -0.771 0.0 1.28879 -0.70786 0.0 1.26533 -0.65252 0.0 1.22838 -0.60662 0.0 1.17967 -0.57181 0.0 1.12096 -0.54973 0.0 1.053 -0.622 0.0 1.09524 -0.62707 0.0 1.13222 -0.64156 0.0 1.16288 -0.66438 0.0 1.18611 -0.69444 0.0 1.20085 -0.73068 0.0 1.206 -0.772 0.0 1.20119 -0.81731 0.0 1.18722 -0.85581 0.0 1.16475 -0.88688 0.0 1.13444 -0.90985 0.0 1.09697 -0.92411 0.0 1.053 -0.929 0.0 1.0124 -0.92389 0.0 0.97719 -0.90915 0.0 0.94825 -0.88563 0.0 0.92648 -0.85419 0.0 0.91277 -0.81569 0.0 0.908 -0.771 0.0 0.91291 -0.7301 0.0 0.92693 -0.69415 0.0 0.949 -0.66425 0.0 0.97807 -0.64152 0.0 1.01309 -0.62706 0.0 0.709 -0.318 0.0 0.618 -0.318 0.0 0.391 -0.598 0.0 0.165 -0.318 0.0 0.073 -0.318 0.0 0.073 -1.0 0.0 0.171 -1.0 0.0 0.171 -0.469 0.0 0.173 -0.469 0.0 0.383 -0.733 0.0 0.399 -0.733 0.0 0.609 -0.469 0.0 0.611 -0.469 0.0 0.611 -1.0 0.0 0.709 -1.0 0.0 7.379 0.542 0.0 7.212 0.379 0.0 7.212 0.369 0.0 7.29 0.369 0.0 7.29 0.132 0.0 7.29408 0.09343 0.0 7.3063 0.05944 0.0 7.32663 0.03112 0.0 7.35504 0.00956 0.0 7.39151 -0.00418 0.0 7.436 -0.009 0.0 7.45192 -0.00796 0.0 7.47 -0.005 0.0 7.48925 -0.00038 0.0 7.50867 0.00567 0.0 7.52725 0.01288 0.0 7.544 0.021 0.0 7.544 0.104 0.0 7.52624 0.09392 0.0 7.50893 0.08567 0.0 7.492 0.07925 0.0 7.47541 0.07467 0.0 7.45909 0.07192 0.0 7.443 0.071 0.0 7.42923 0.07236 0.0 7.41485 0.07685 0.0 7.40125 0.08513 0.0 7.38982 0.09781 0.0 7.38194 0.11556 0.0 7.379 0.139 0.0 7.379 0.369 0.0 7.521 0.369 0.0 7.521 0.449 0.0 7.379 0.449 0.0 7.151 0.421 0.0 7.12782 0.43242 0.0 7.10522 0.4417 0.0 7.08313 0.44888 0.0 7.06145 0.45396 0.0 7.0401 0.457 0.0 7.019 0.458 0.0 6.97679 0.45424 0.0 6.94063 0.44326 0.0 6.91125 0.4255 0.0 6.88937 0.40141 0.0 6.87571 0.37143 0.0 6.871 0.336 0.0 6.88656 0.28229 0.0 6.92545 0.24 0.0 6.976 0.20588 0.0 7.02656 0.17667 0.0 7.06545 0.14913 0.0 7.081 0.12 0.0 7.07861 0.10525 0.0 7.07189 0.093 0.0 7.0615 0.08325 0.0 7.04811 0.076 0.0 7.03239 0.07125 0.0 7.015 0.069 0.0 6.99564 0.07059 0.0 6.97378 0.07541 0.0 6.94975 0.0835 0.0 6.92389 0.09493 0.0 6.89653 0.10974 0.0 6.868 0.128 0.0 6.868 0.032 0.0 6.89588 0.01855 0.0 6.922 0.00804 0.0 6.94713 0.00025 0.0 6.972 -0.00504 0.0 6.99738 -0.00805 0.0 7.024 -0.009 0.0 7.06448 -0.00471 0.0 7.10015 0.00767 0.0 7.12988 0.02737 0.0 7.15252 0.05367 0.0 7.16694 0.08579 0.0 7.172 0.123 0.0 7.16966 0.1449 0.0 7.16226 0.16522 0.0 7.14925 0.18488 0.0 7.13007 0.20478 0.0 7.10418 0.22585 0.0 7.071 0.249 0.0 7.0355 0.27025 0.0 7.00763 0.28833 0.0 6.98688 0.30375 0.0 6.9727 0.317 0.0 6.96459 0.32858 0.0 6.962 0.339 0.0 6.96387 0.35037 0.0 6.9693 0.3603 0.0 6.978 0.3685 0.0 6.9897 0.3747 0.0 7.00413 0.37863 0.0 7.021 0.38 0.0 7.03862 0.37881 0.0 7.05826 0.37515 0.0 7.07963 0.36887 0.0 7.10241 0.35985 0.0 7.1263 0.34794 0.0 7.151 0.333 0.0 6.786 0.13 0.0 6.76007 0.11419 0.0 6.73419 0.10089 0.0 6.70825 0.09025 0.0 6.68215 0.08244 0.0 6.65577 0.07764 0.0 6.629 0.076 0.0 6.58893 0.07982 0.0 6.55474 0.09122 0.0 6.5265 0.11013 0.0 6.50426 0.13644 0.0 6.48807 0.1701 0.0 6.478 0.211 0.0 6.794 0.211 0.0 6.78782 0.28694 0.0 6.76989 0.34881 0.0 6.74113 0.39675 0.0 6.70245 0.43085 0.0 6.65476 0.45123 0.0 6.599 0.458 0.0 6.54039 0.45056 0.0 6.48945 0.42911 0.0 6.4475 0.395 0.0 6.41589 0.34956 0.0 6.39595 0.29411 0.0 6.389 0.23 0.0 6.39543 0.16924 0.0 6.41441 0.11293 0.0 6.4455 0.064 0.0 6.48826 0.02541 0.0 6.54224 9e-05 0.0 6.607 -0.009 0.0 6.6429 -0.00757 0.0 6.67519 -0.00326 0.0 6.70475 0.004 0.0 6.73248 0.01426 0.0 6.75927 0.02757 0.0 6.786 0.044 0.0 6.48 0.27 0.0 6.48841 0.30288 0.0 6.50159 0.33033 0.0 6.5195 0.35213 0.0 6.54207 0.368 0.0 6.56926 0.37771 0.0 6.601 0.381 0.0 6.63045 0.3775 0.0 6.65556 0.36733 0.0 6.676 0.351 0.0 6.69144 0.329 0.0 6.70156 0.30183 0.0 6.706 0.27 0.0 6.331 0.682 0.0 5.761 0.682 0.0 5.761 0.594 0.0 5.997 0.594 0.0 5.997 0.0 0.0 6.095 0.0 0.0 6.095 0.594 0.0 6.331 0.594 0.0 5.405 0.421 0.0 5.38182 0.43242 0.0 5.35922 0.4417 0.0 5.33713 0.44888 0.0 5.31544 0.45396 0.0 5.2941 0.457 0.0 5.273 0.458 0.0 5.23079 0.45424 0.0 5.19463 0.44326 0.0 5.16525 0.4255 0.0 5.14337 0.40141 0.0 5.12971 0.37143 0.0 5.125 0.336 0.0 5.14056 0.28229 0.0 5.17944 0.24 0.0 5.23 0.20588 0.0 5.28056 0.17667 0.0 5.31945 0.14913 0.0 5.335 0.12 0.0 5.33261 0.10525 0.0 5.32589 0.093 0.0 5.3155 0.08325 0.0 5.30211 0.076 0.0 5.28639 0.07125 0.0 5.269 0.069 0.0 5.24964 0.07059 0.0 5.22778 0.07541 0.0 5.20375 0.0835 0.0 5.17789 0.09493 0.0 5.15053 0.10974 0.0 5.122 0.128 0.0 5.122 0.032 0.0 5.14988 0.01855 0.0 5.176 0.00804 0.0 5.20113 0.00025 0.0 5.226 -0.00504 0.0 5.25138 -0.00805 0.0 5.278 -0.009 0.0 5.31848 -0.00471 0.0 5.35415 0.00767 0.0 5.38388 0.02737 0.0 5.40652 0.05367 0.0 5.42094 0.08579 0.0 5.426 0.123 0.0 5.42366 0.1449 0.0 5.41626 0.16522 0.0 5.40325 0.18488 0.0 5.38407 0.20478 0.0 5.35818 0.22585 0.0 5.325 0.249 0.0 5.2895 0.27025 0.0 5.26163 0.28833 0.0 5.24088 0.30375 0.0 5.2267 0.317 0.0 5.21859 0.32858 0.0 5.216 0.339 0.0 5.21787 0.35037 0.0 5.2233 0.3603 0.0 5.232 0.3685 0.0 5.2437 0.3747 0.0 5.25813 0.37863 0.0 5.275 0.38 0.0 5.29262 0.37881 0.0 5.31226 0.37515 0.0 5.33363 0.36887 0.0 5.35641 0.35985 0.0 5.3803 0.34794 0.0 5.405 0.333 0.0 5.036 0.427 0.0 5.01505 0.43589 0.0 4.99474 0.44348 0.0 4.97437 0.44963 0.0 4.95326 0.45419 0.0 4.9307 0.45702 0.0 4.906 0.458 0.0 4.84233 0.45035 0.0 4.788 0.42815 0.0 4.744 0.3925 0.0 4.71133 0.34452 0.0 4.691 0.28531 0.0 4.684 0.216 0.0 4.69158 0.1535 0.0 4.71333 0.099 0.0 4.74775 0.054 0.0 4.79333 0.02 0.0 4.84858 -0.0015 0.0 4.912 -0.009 0.0 4.93616 -0.00805 0.0 4.96096 -0.00537 0.0 4.98537 -0.00125 0.0 5.00837 0.00404 0.0 5.02892 0.01021 0.0 5.046 0.017 0.0 5.046 0.105 0.0 5.0242 0.09583 0.0 5.00359 0.08833 0.0 4.98387 0.0825 0.0 4.96474 0.07833 0.0 4.94588 0.07583 0.0 4.927 0.075 0.0 4.8838 0.07958 0.0 4.8467 0.09296 0.0 4.8165 0.11463 0.0 4.79396 0.14404 0.0 4.77987 0.18067 0.0 4.775 0.224 0.0 4.77952 0.26686 0.0 4.79252 0.30385 0.0 4.81313 0.33413 0.0 4.84048 0.35681 0.0 4.87373 0.37106 0.0 4.912 0.376 0.0 4.93119 0.3751 0.0 4.95015 0.37215 0.0 4.9695 0.36675 0.0 4.98985 0.35852 0.0 5.01182 0.34706 0.0 5.036 0.332 0.0 4.578 0.449 0.0 4.489 0.449 0.0 4.489 0.0 0.0 4.578 0.0 0.0 4.587 0.585 0.0 4.58509 0.599 0.0 4.5797 0.61163 0.0 4.57137 0.62238 0.0 4.56063 0.6307 0.0 4.548 0.63609 0.0 4.534 0.638 0.0 4.52 0.63609 0.0 4.50737 0.6307 0.0 4.49662 0.62238 0.0 4.4883 0.61163 0.0 4.48291 0.599 0.0 4.481 0.585 0.0 4.48291 0.571 0.0 4.4883 0.55837 0.0 4.49663 0.54763 0.0 4.50737 0.5393 0.0 4.52001 0.53391 0.0 4.534 0.532 0.0 4.548 0.53391 0.0 4.56063 0.5393 0.0 4.57138 0.54763 0.0 4.5797 0.55837 0.0 4.58509 0.571 0.0 4.363 0.421 0.0 4.33982 0.43242 0.0 4.31722 0.4417 0.0 4.29513 0.44888 0.0 4.27344 0.45396 0.0 4.2521 0.457 0.0 4.231 0.458 0.0 4.18879 0.45424 0.0 4.15263 0.44326 0.0 4.12325 0.4255 0.0 4.10137 0.40141 0.0 4.08771 0.37143 0.0 4.083 0.336 0.0 4.09856 0.28229 0.0 4.13744 0.24 0.0 4.188 0.20588 0.0 4.23856 0.17667 0.0 4.27744 0.14913 0.0 4.293 0.12 0.0 4.29061 0.10525 0.0 4.28389 0.093 0.0 4.2735 0.08325 0.0 4.26011 0.076 0.0 4.24439 0.07125 0.0 4.227 0.069 0.0 4.20764 0.07059 0.0 4.18578 0.07541 0.0 4.16175 0.0835 0.0 4.13589 0.09493 0.0 4.10853 0.10974 0.0 4.08 0.128 0.0 4.08 0.032 0.0 4.10787 0.01855 0.0 4.134 0.00804 0.0 4.15912 0.00025 0.0 4.184 -0.00504 0.0 4.20937 -0.00805 0.0 4.236 -0.009 0.0 4.27648 -0.00471 0.0 4.31215 0.00767 0.0 4.34188 0.02737 0.0 4.36452 0.05367 0.0 4.37894 0.08579 0.0 4.384 0.123 0.0 4.38166 0.1449 0.0 4.37426 0.16522 0.0 4.36125 0.18488 0.0 4.34207 0.20478 0.0 4.31618 0.22585 0.0 4.283 0.249 0.0 4.2475 0.27025 0.0 4.21963 0.28833 0.0 4.19887 0.30375 0.0 4.1847 0.317 0.0 4.17659 0.32858 0.0 4.174 0.339 0.0 4.17587 0.35037 0.0 4.1813 0.3603 0.0 4.19 0.3685 0.0 4.2017 0.3747 0.0 4.21613 0.37863 0.0 4.233 0.38 0.0 4.25062 0.37881 0.0 4.27026 0.37515 0.0 4.29163 0.36887 0.0 4.31441 0.35985 0.0 4.3383 0.34794 0.0 4.363 0.333 0.0 4.039 0.449 0.0 3.939 0.449 0.0 3.823 0.196 0.0 3.702 0.449 0.0 3.601 0.449 0.0 3.775 0.096 0.0 3.622 -0.23 0.0 3.721 -0.23 0.0 3.251 0.682 0.0 3.162 0.682 0.0 3.162 0.0 0.0 3.251 0.0 0.0 3.251 0.322 0.0 3.27117 0.34313 0.0 3.29004 0.35974 0.0 3.30813 0.37213 0.0 3.32596 0.38059 0.0 3.34408 0.38545 0.0 3.363 0.387 0.0 3.38827 0.38351 0.0 3.40982 0.37341 0.0 3.42725 0.35725 0.0 3.44019 0.33559 0.0 3.44823 0.30899 0.0 3.451 0.278 0.0 3.451 0.0 0.0 3.54 0.0 0.0 3.54 0.275 0.0 3.53478 0.33126 0.0 3.51989 0.37711 0.0 3.4965 0.41263 0.0 3.46578 0.43789 0.0 3.42889 0.45299 0.0 3.387 0.458 0.0 3.36207 0.45595 0.0 3.33759 0.44993 0.0 3.314 0.44013 0.0 3.29174 0.42674 0.0 3.27126 0.40997 0.0 3.253 0.39 0.0 3.251 0.39 0.0 2.661 0.682 0.0 2.661 0.0 0.0 2.759 0.0 0.0 2.759 0.295 0.0 2.861 0.295 0.0 2.9329 0.30172 0.0 2.99085 0.32074 0.0 3.03525 0.35038 0.0 3.06648 0.38893 0.0 3.08493 0.4347 0.0 3.091 0.486 0.0 3.08527 0.53802 0.0 3.06785 0.58481 0.0 3.03838 0.6245 0.0 2.99648 0.65519 0.0 2.94181 0.67498 0.0 2.874 0.682 0.0 2.759 0.594 0.0 2.874 0.594 0.0 2.9135 0.58977 0.0 2.94363 0.57815 0.0 2.96538 0.56075 0.0 2.9797 0.53919 0.0 2.98759 0.51506 0.0 2.99 0.49 0.0 2.98618 0.45846 0.0 2.97511 0.43204 0.0 2.95737 0.411 0.0 2.93356 0.39563 0.0 2.90424 0.3862 0.0 2.87 0.383 0.0 2.759 0.383 0.0 2.147 0.542 0.0 1.98 0.379 0.0 1.98 0.369 0.0 2.058 0.369 0.0 2.058 0.132 0.0 2.06208 0.09343 0.0 2.0743 0.05944 0.0 2.09462 0.03112 0.0 2.12304 0.00956 0.0 2.1595 -0.00418 0.0 2.204 -0.009 0.0 2.21992 -0.00796 0.0 2.238 -0.005 0.0 2.25725 -0.00038 0.0 2.27667 0.00567 0.0 2.29525 0.01288 0.0 2.312 0.021 0.0 2.312 0.104 0.0 2.29424 0.09392 0.0 2.27693 0.08567 0.0 2.26 0.07925 0.0 2.24341 0.07467 0.0 2.22709 0.07192 0.0 2.211 0.071 0.0 2.19723 0.07236 0.0 2.18285 0.07685 0.0 2.16925 0.08513 0.0 2.15781 0.09781 0.0 2.14994 0.11556 0.0 2.147 0.139 0.0 2.147 0.369 0.0 2.289 0.369 0.0 2.289 0.449 0.0 2.147 0.449 0.0 1.939 0.13 0.0 1.91306 0.11419 0.0 1.88719 0.10089 0.0 1.86125 0.09025 0.0 1.83515 0.08244 0.0 1.80877 0.07764 0.0 1.782 0.076 0.0 1.74193 0.07982 0.0 1.70774 0.09122 0.0 1.6795 0.11013 0.0 1.65726 0.13644 0.0 1.64107 0.1701 0.0 1.631 0.211 0.0 1.947 0.211 0.0 1.94082 0.28694 0.0 1.92289 0.34881 0.0 1.89412 0.39675 0.0 1.85544 0.43085 0.0 1.80776 0.45123 0.0 1.752 0.458 0.0 1.69339 0.45056 0.0 1.64244 0.42911 0.0 1.6005 0.395 0.0 1.56889 0.34956 0.0 1.54894 0.29411 0.0 1.542 0.23 0.0 1.54843 0.16924 0.0 1.56741 0.11293 0.0 1.5985 0.064 0.0 1.64126 0.02541 0.0 1.69524 9e-05 0.0 1.76 -0.009 0.0 1.7959 -0.00757 0.0 1.82819 -0.00326 0.0 1.85775 0.004 0.0 1.88548 0.01426 0.0 1.91227 0.02757 0.0 1.939 0.044 0.0 1.633 0.27 0.0 1.64141 0.30288 0.0 1.65459 0.33033 0.0 1.6725 0.35213 0.0 1.69507 0.368 0.0 1.72226 0.37771 0.0 1.754 0.381 0.0 1.78344 0.3775 0.0 1.80856 0.36733 0.0 1.829 0.351 0.0 1.84444 0.329 0.0 1.85456 0.30183 0.0 1.859 0.27 0.0 1.436 0.682 0.0 1.347 0.682 0.0 1.347 0.0 0.0 1.436 0.0 0.0 1.217 0.682 0.0 1.128 0.682 0.0 1.128 0.0 0.0 1.217 0.0 0.0 1.0 0.0 0.0 1.0 0.449 0.0 0.911 0.449 0.0 0.911 0.128 0.0 0.89578 0.1091 0.0 0.87926 0.09344 0.0 0.86163 0.08113 0.0 0.84307 0.07222 0.0 0.8238 0.06682 0.0 0.804 0.065 0.0 0.776 0.06796 0.0 0.75304 0.07667 0.0 0.73513 0.09088 0.0 0.7223 0.11033 0.0 0.71458 0.13479 0.0 0.712 0.164 0.0 0.712 0.449 0.0 0.623 0.449 0.0 0.623 0.17 0.0 0.62816 0.11716 0.0 0.64296 0.07293 0.0 0.66638 0.03775 0.0 0.69737 0.01207 0.0 0.73492 -0.00366 0.0 0.778 -0.009 0.0 0.80056 -0.00689 0.0 0.82381 -0.00078 0.0 0.84712 0.009 0.0 0.86985 0.02211 0.0 0.89136 0.03822 0.0 0.911 0.057 0.0 0.911 0.0 0.0 0.075 0.0 0.0 0.309 0.0 0.0 0.38571 0.00765 0.0 0.44567 0.02852 0.0 0.49013 0.0595 0.0 0.52033 0.09748 0.0 0.53754 0.13935 0.0 0.543 0.182 0.0 0.53794 0.22581 0.0 0.52315 0.26481 0.0 0.49925 0.29838 0.0 0.46685 0.32585 0.0 0.42656 0.34661 0.0 0.379 0.36 0.0 0.379 0.362 0.0 0.41136 0.37795 0.0 0.43752 0.39696 0.0 0.45763 0.41925 0.0 0.47181 0.44504 0.0 0.48023 0.47455 0.0 0.483 0.508 0.0 0.47765 0.55075 0.0 0.46122 0.59133 0.0 0.43313 0.62725 0.0 0.39278 0.656 0.0 0.3396 0.67508 0.0 0.273 0.682 0.0 0.075 0.682 0.0 0.173 0.594 0.0 0.263 0.594 0.0 0.30306 0.5905 0.0 0.33385 0.5807 0.0 0.35625 0.56563 0.0 0.37115 0.5463 0.0 0.37944 0.52375 0.0 0.382 0.499 0.0 0.37807 0.46558 0.0 0.36622 0.4383 0.0 0.34638 0.41713 0.0 0.31844 0.40204 0.0 0.28235 0.393 0.0 0.238 0.39 0.0 0.173 0.39 0.0 0.173 0.302 0.0 0.291 0.302 0.0 0.33795 0.29845 0.0 0.37593 0.2883 0.0 0.40513 0.27225 0.0 0.42574 0.25104 0.0 0.43797 0.22538 0.0 0.442 0.196 0.0 0.43917 0.17029 0.0 0.4297 0.14533 0.0 0.41212 0.12288 0.0 0.38496 0.10467 0.0 0.34675 0.09246 0.0 0.296 0.088 0.0 0.173 0.088 0.0 + + + + + + + + + + 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    20 0 19 1 18 2 20 3 18 4 17 5 21 6 20 7 17 8 21 9 17 10 16 11 22 12 21 13 16 14 22 15 16 16 44 17 44 18 16 19 45 20 45 21 16 22 15 23 23 24 22 25 43 26 43 27 22 28 44 29 23 30 43 31 42 32 46 33 45 34 15 35 23 36 42 37 41 38 47 39 46 40 15 41 23 42 41 43 40 44 48 45 47 46 15 47 24 48 23 49 40 50 48 51 15 52 14 53 24 54 40 55 39 56 49 57 48 58 14 59 24 60 39 61 38 62 50 63 49 64 14 65 25 66 24 67 38 68 50 69 14 70 13 71 25 72 38 73 50 74 25 75 50 76 13 77 26 78 25 79 12 80 12 81 25 82 13 83 26 84 12 85 11 86 26 87 11 88 10 89 27 90 26 91 10 92 27 93 10 94 9 95 1 96 0 97 37 98 2 99 1 100 37 101 28 102 27 103 9 104 28 105 9 106 8 107 3 108 2 109 37 110 28 111 8 112 7 113 4 114 3 115 37 116 5 117 4 118 37 119 28 120 7 121 6 122 6 123 5 124 37 125 28 126 6 127 37 128 29 129 28 130 37 131 29 132 37 133 36 134 29 135 36 136 35 137 30 138 29 139 35 140 30 141 35 142 34 143 30 144 34 145 33 146 31 147 30 148 33 149 31 150 33 151 32 152 52 153 51 154 84 155 52 156 84 157 83 158 52 159 83 160 82 161 53 162 52 163 82 164 54 165 53 166 82 167 55 168 54 169 81 170 81 171 54 172 82 173 55 174 81 175 80 176 55 177 80 178 79 179 56 180 55 181 79 182 56 183 79 184 78 185 69 186 68 187 67 188 56 189 78 190 77 191 70 192 69 193 67 194 57 195 56 196 77 197 71 198 70 199 67 200 57 201 77 202 76 203 72 204 71 205 67 206 57 207 76 208 75 209 73 210 72 211 67 212 57 213 75 214 74 215 74 216 73 217 67 218 57 219 74 220 67 221 58 222 57 223 67 224 59 225 58 226 67 227 59 228 67 229 66 230 59 231 66 232 65 233 60 234 59 235 65 236 60 237 65 238 64 239 60 240 64 241 63 242 61 243 60 244 63 245 61 246 63 247 62 248 105 249 104 250 103 251 106 252 105 253 103 254 106 255 103 256 102 257 107 258 106 259 102 260 108 261 107 262 102 263 108 264 102 265 101 266 109 267 108 268 101 269 109 270 101 271 100 272 110 273 109 274 100 275 111 276 110 277 112 278 112 279 110 280 113 281 113 282 110 283 114 284 114 285 110 286 115 287 115 288 110 289 116 290 116 291 110 292 117 293 117 294 110 295 100 296 117 297 100 298 118 299 118 300 100 301 99 302 119 303 118 304 99 305 120 306 119 307 99 308 120 309 99 310 98 311 121 312 120 313 98 314 122 315 121 316 98 317 123 318 122 319 98 320 123 321 98 322 97 323 124 324 123 325 97 326 125 327 124 328 174 329 174 330 124 331 97 332 126 333 125 334 174 335 127 336 126 337 174 338 127 339 174 340 173 341 156 342 174 343 97 344 128 345 127 346 173 347 128 348 173 349 172 350 129 351 128 352 172 353 129 354 172 355 171 356 129 357 171 358 170 359 130 360 129 361 170 362 130 363 170 364 169 365 130 366 169 367 168 368 131 369 130 370 168 371 131 372 168 373 167 374 132 375 131 376 167 377 132 378 167 379 166 380 157 381 156 382 97 383 132 384 166 385 165 386 158 387 157 388 97 389 86 390 85 391 155 392 158 393 97 394 96 395 87 396 86 397 155 398 133 399 132 400 165 401 133 402 165 403 164 404 158 405 96 406 95 407 159 408 158 409 95 410 88 411 87 412 155 413 159 414 95 415 94 416 160 417 159 418 94 419 89 420 88 421 155 422 133 423 164 424 163 425 160 426 94 427 93 428 90 429 89 430 155 431 161 432 160 433 93 434 161 435 93 436 92 437 91 438 90 439 155 440 161 441 92 442 91 443 133 444 163 445 162 446 161 447 91 448 155 449 162 450 161 451 155 452 133 453 162 454 143 455 143 456 162 457 155 458 134 459 133 460 143 461 134 462 143 463 142 464 144 465 143 466 155 467 144 468 155 469 154 470 135 471 134 472 142 473 135 474 142 475 141 476 145 477 144 478 154 479 145 480 154 481 153 482 135 483 141 484 140 485 146 486 145 487 153 488 136 489 135 490 140 491 146 492 153 493 152 494 136 495 140 496 139 497 147 498 146 499 152 500 147 501 152 502 151 503 136 504 139 505 138 506 148 507 147 508 151 509 137 510 136 511 138 512 148 513 151 514 150 515 149 516 148 517 150 518 177 519 176 520 175 521 177 522 175 523 256 524 178 525 177 526 256 527 179 528 178 529 256 530 180 531 179 532 255 533 255 534 179 535 256 536 180 537 255 538 275 539 275 540 255 541 254 542 181 543 180 544 274 545 274 546 180 547 275 548 276 549 275 550 254 551 277 552 276 553 254 554 181 555 274 556 273 557 277 558 254 559 253 560 278 561 277 562 253 563 181 564 273 565 272 566 279 567 278 568 253 569 181 570 272 571 271 572 279 573 253 574 252 575 182 576 181 577 271 578 280 579 279 580 252 581 280 582 252 583 251 584 182 585 271 586 270 587 280 588 251 589 250 590 257 591 280 592 250 593 182 594 270 595 269 596 257 597 250 598 249 599 183 600 182 601 269 602 258 603 257 604 249 605 183 606 269 607 268 608 258 609 249 610 248 611 184 612 183 613 268 614 259 615 258 616 248 617 184 618 268 619 267 620 259 621 248 622 247 623 185 624 184 625 267 626 260 627 259 628 247 629 186 630 185 631 267 632 186 633 267 634 266 635 260 636 247 637 246 638 187 639 186 640 266 641 261 642 260 643 246 644 187 645 266 646 265 647 261 648 246 649 245 650 188 651 187 652 265 653 262 654 261 655 245 656 188 657 265 658 264 659 263 660 262 661 245 662 188 663 264 664 263 665 189 666 188 667 263 668 189 669 263 670 245 671 189 672 245 673 244 674 190 675 189 676 244 677 190 678 244 679 243 680 191 681 190 682 243 683 191 684 243 685 242 686 192 687 191 688 242 689 193 690 192 691 242 692 194 693 193 694 242 695 194 696 242 697 241 698 195 699 194 700 241 701 196 702 195 703 241 704 197 705 196 706 241 707 197 708 241 709 240 710 198 711 197 712 240 713 198 714 240 715 239 716 198 717 239 718 238 719 199 720 198 721 238 722 199 723 238 724 237 725 200 726 199 727 237 728 201 729 200 730 237 731 201 732 237 733 236 734 202 735 201 736 236 737 202 738 236 739 235 740 203 741 202 742 235 743 203 744 235 745 234 746 204 747 203 748 234 749 204 750 234 751 233 752 205 753 204 754 233 755 205 756 233 757 232 758 206 759 205 760 232 761 206 762 232 763 231 764 207 765 206 766 231 767 207 768 231 769 230 770 208 771 207 772 230 773 208 774 230 775 229 776 209 777 208 778 229 779 209 780 229 781 228 782 210 783 209 784 228 785 210 786 228 787 299 788 299 789 228 790 300 791 300 792 228 793 227 794 211 795 210 796 298 797 298 798 210 799 299 800 301 801 300 802 227 803 211 804 298 805 297 806 302 807 301 808 227 809 211 810 297 811 296 812 302 813 227 814 226 815 303 816 302 817 226 818 212 819 211 820 296 821 212 822 296 823 295 824 304 825 303 826 226 827 212 828 295 829 294 830 304 831 226 832 225 833 213 834 212 835 294 836 281 837 304 838 225 839 213 840 294 841 293 842 281 843 225 844 224 845 213 846 293 847 292 848 214 849 213 850 292 851 282 852 281 853 224 854 214 855 292 856 291 857 283 858 282 859 224 860 214 861 291 862 290 863 283 864 224 865 223 866 284 867 283 868 223 869 215 870 214 871 290 872 215 873 290 874 289 875 285 876 284 877 223 878 215 879 289 880 288 881 286 882 285 883 223 884 215 885 288 886 287 887 287 888 286 889 223 890 215 891 287 892 223 893 215 894 223 895 222 896 216 897 215 898 222 899 217 900 216 901 222 902 217 903 222 904 221 905 218 906 217 907 221 908 218 909 221 910 220 911 219 912 218 913 220 914 316 915 315 916 314 917 317 918 316 919 314 920 317 921 314 922 313 923 318 924 317 925 313 926 318 927 313 928 312 929 319 930 318 931 312 932 319 933 312 934 311 935 320 936 319 937 311 938 320 939 311 940 310 941 321 942 320 943 310 944 321 945 310 946 309 947 322 948 321 949 309 950 322 951 309 952 332 953 323 954 322 955 332 956 323 957 332 958 331 959 324 960 323 961 331 962 324 963 331 964 330 965 325 966 324 967 330 968 325 969 330 970 329 971 326 972 325 973 329 974 326 975 329 976 328 977 327 978 326 979 328 980 307 981 306 982 305 983 307 984 305 985 308 986 333 987 339 988 338 989 333 990 338 991 337 992 337 993 336 994 335 995 337 996 335 997 334 998 333 999 337 1000 334 1001 360 1002 359 1003 358 1004 361 1005 360 1006 358 1007 361 1008 358 1009 357 1010 362 1011 361 1012 357 1013 363 1014 362 1015 357 1016 363 1017 357 1018 356 1019 364 1020 363 1021 356 1022 364 1023 356 1024 355 1025 365 1026 364 1027 355 1028 366 1029 365 1030 367 1031 367 1032 365 1033 368 1034 368 1035 365 1036 369 1037 369 1038 365 1039 370 1040 370 1041 365 1042 371 1043 371 1044 365 1045 372 1046 372 1047 365 1048 355 1049 372 1050 355 1051 373 1052 373 1053 355 1054 354 1055 374 1056 373 1057 354 1058 375 1059 374 1060 354 1061 375 1062 354 1063 353 1064 376 1065 375 1066 353 1067 377 1068 376 1069 353 1070 378 1071 377 1072 353 1073 378 1074 353 1075 352 1076 379 1077 378 1078 352 1079 380 1080 379 1081 429 1082 429 1083 379 1084 352 1085 381 1086 380 1087 429 1088 382 1089 381 1090 429 1091 382 1092 429 1093 428 1094 411 1095 429 1096 352 1097 383 1098 382 1099 428 1100 383 1101 428 1102 427 1103 384 1104 383 1105 427 1106 384 1107 427 1108 426 1109 384 1110 426 1111 425 1112 385 1113 384 1114 425 1115 385 1116 425 1117 424 1118 385 1119 424 1120 423 1121 386 1122 385 1123 423 1124 386 1125 423 1126 422 1127 387 1128 386 1129 422 1130 387 1131 422 1132 421 1133 412 1134 411 1135 352 1136 387 1137 421 1138 420 1139 413 1140 412 1141 352 1142 341 1143 340 1144 410 1145 413 1146 352 1147 351 1148 342 1149 341 1150 410 1151 388 1152 387 1153 420 1154 388 1155 420 1156 419 1157 413 1158 351 1159 350 1160 414 1161 413 1162 350 1163 343 1164 342 1165 410 1166 414 1167 350 1168 349 1169 415 1170 414 1171 349 1172 344 1173 343 1174 410 1175 388 1176 419 1177 418 1178 415 1179 349 1180 348 1181 345 1182 344 1183 410 1184 416 1185 415 1186 348 1187 416 1188 348 1189 347 1190 346 1191 345 1192 410 1193 416 1194 347 1195 346 1196 388 1197 418 1198 417 1199 416 1200 346 1201 410 1202 417 1203 416 1204 410 1205 388 1206 417 1207 398 1208 398 1209 417 1210 410 1211 389 1212 388 1213 398 1214 389 1215 398 1216 397 1217 399 1218 398 1219 410 1220 399 1221 410 1222 409 1223 390 1224 389 1225 397 1226 390 1227 397 1228 396 1229 400 1230 399 1231 409 1232 400 1233 409 1234 408 1235 390 1236 396 1237 395 1238 401 1239 400 1240 408 1241 391 1242 390 1243 395 1244 401 1245 408 1246 407 1247 391 1248 395 1249 394 1250 402 1251 401 1252 407 1253 402 1254 407 1255 406 1256 391 1257 394 1258 393 1259 403 1260 402 1261 406 1262 392 1263 391 1264 393 1265 403 1266 406 1267 405 1268 404 1269 403 1270 405 1271 456 1272 455 1273 454 1274 457 1275 456 1276 454 1277 457 1278 454 1279 453 1280 458 1281 457 1282 453 1283 432 1284 431 1285 430 1286 432 1287 430 1288 462 1289 459 1290 458 1291 453 1292 459 1293 453 1294 452 1295 460 1296 459 1297 452 1298 460 1299 452 1300 451 1301 461 1302 460 1303 440 1304 440 1305 460 1306 451 1307 432 1308 462 1309 461 1310 432 1311 461 1312 434 1313 434 1314 461 1315 435 1316 435 1317 461 1318 436 1319 436 1320 461 1321 437 1322 437 1323 461 1324 438 1325 438 1326 461 1327 439 1328 439 1329 461 1330 440 1331 441 1332 440 1333 451 1334 442 1335 441 1336 451 1337 442 1338 451 1339 450 1340 443 1341 442 1342 450 1343 444 1344 443 1345 450 1346 445 1347 444 1348 450 1349 445 1350 450 1351 449 1352 432 1353 434 1354 433 1355 446 1356 445 1357 449 1358 447 1359 446 1360 449 1361 447 1362 449 1363 448 1364 464 1365 463 1366 486 1367 464 1368 486 1369 485 1370 465 1371 464 1372 485 1373 465 1374 485 1375 484 1376 466 1377 465 1378 484 1379 466 1380 484 1381 487 1382 487 1383 484 1384 488 1385 488 1386 484 1387 483 1388 467 1389 466 1390 510 1391 510 1392 466 1393 487 1394 467 1395 510 1396 509 1397 489 1398 488 1399 483 1400 467 1401 509 1402 508 1403 490 1404 489 1405 483 1406 490 1407 483 1408 482 1409 468 1410 467 1411 508 1412 468 1413 508 1414 507 1415 491 1416 490 1417 482 1418 468 1419 507 1420 506 1421 492 1422 491 1423 482 1424 492 1425 482 1426 481 1427 469 1428 468 1429 506 1430 469 1431 506 1432 505 1433 493 1434 492 1435 481 1436 470 1437 469 1438 505 1439 470 1440 505 1441 504 1442 493 1443 481 1444 480 1445 494 1446 493 1447 480 1448 470 1449 504 1450 503 1451 495 1452 494 1453 480 1454 471 1455 470 1456 503 1457 495 1458 480 1459 479 1460 471 1461 503 1462 502 1463 496 1464 495 1465 479 1466 471 1467 502 1468 501 1469 497 1470 496 1471 479 1472 472 1473 471 1474 501 1475 497 1476 479 1477 478 1478 472 1479 501 1480 500 1481 498 1482 497 1483 478 1484 472 1485 500 1486 499 1487 499 1488 498 1489 478 1490 472 1491 499 1492 478 1493 473 1494 472 1495 478 1496 473 1497 478 1498 477 1499 474 1500 473 1501 477 1502 474 1503 477 1504 476 1505 475 1506 474 1507 476 1508 512 1509 511 1510 544 1511 512 1512 544 1513 543 1514 512 1515 543 1516 542 1517 513 1518 512 1519 542 1520 514 1521 513 1522 542 1523 515 1524 514 1525 541 1526 541 1527 514 1528 542 1529 515 1530 541 1531 540 1532 515 1533 540 1534 539 1535 516 1536 515 1537 539 1538 516 1539 539 1540 538 1541 529 1542 528 1543 527 1544 516 1545 538 1546 537 1547 530 1548 529 1549 527 1550 517 1551 516 1552 537 1553 531 1554 530 1555 527 1556 517 1557 537 1558 536 1559 532 1560 531 1561 527 1562 517 1563 536 1564 535 1565 533 1566 532 1567 527 1568 517 1569 535 1570 534 1571 534 1572 533 1573 527 1574 517 1575 534 1576 527 1577 518 1578 517 1579 527 1580 519 1581 518 1582 527 1583 519 1584 527 1585 526 1586 519 1587 526 1588 525 1589 520 1590 519 1591 525 1592 520 1593 525 1594 524 1595 520 1596 524 1597 523 1598 521 1599 520 1600 523 1601 521 1602 523 1603 522 1604 552 1605 551 1606 550 1607 552 1608 550 1609 549 1610 553 1611 552 1612 549 1613 553 1614 549 1615 548 1616 553 1617 548 1618 547 1619 554 1620 553 1621 547 1622 554 1623 547 1624 546 1625 554 1626 546 1627 545 1628 555 1629 554 1630 545 1631 555 1632 545 1633 606 1634 606 1635 545 1636 607 1637 607 1638 545 1639 608 1640 608 1641 545 1642 609 1643 609 1644 545 1645 610 1646 610 1647 545 1648 611 1649 611 1650 545 1651 612 1652 556 1653 555 1654 606 1655 556 1656 606 1657 605 1658 556 1659 605 1660 604 1661 556 1662 604 1663 603 1664 557 1665 556 1666 603 1667 557 1668 603 1669 602 1670 557 1671 602 1672 601 1673 557 1674 601 1675 600 1676 557 1677 600 1678 599 1679 558 1680 557 1681 599 1682 558 1683 599 1684 598 1685 558 1686 598 1687 597 1688 558 1689 597 1690 596 1691 558 1692 596 1693 595 1694 559 1695 558 1696 595 1697 559 1698 595 1699 594 1700 559 1701 594 1702 593 1703 560 1704 559 1705 593 1706 560 1707 593 1708 592 1709 561 1710 560 1711 592 1712 561 1713 592 1714 591 1715 561 1716 591 1717 590 1718 562 1719 561 1720 590 1721 562 1722 590 1723 589 1724 563 1725 562 1726 589 1727 563 1728 589 1729 588 1730 576 1731 575 1732 574 1733 563 1734 588 1735 587 1736 564 1737 563 1738 587 1739 576 1740 574 1741 573 1742 565 1743 564 1744 587 1745 576 1746 573 1747 572 1748 566 1749 565 1750 587 1751 566 1752 587 1753 586 1754 576 1755 572 1756 571 1757 567 1758 566 1759 586 1760 568 1761 567 1762 586 1763 576 1764 571 1765 570 1766 569 1767 568 1768 586 1769 576 1770 570 1771 569 1772 576 1773 569 1774 586 1775 576 1776 586 1777 585 1778 577 1779 576 1780 585 1781 577 1782 585 1783 584 1784 578 1785 577 1786 584 1787 579 1788 578 1789 584 1790 579 1791 584 1792 583 1793 580 1794 579 1795 583 1796 580 1797 583 1798 582 1799 581 1800 580 1801 582 1802 618 1803 617 1804 616 1805 618 1806 616 1807 615 1808 615 1809 614 1810 613 1811 615 1812 613 1813 620 1814 618 1815 615 1816 620 1817 619 1818 618 1819 620 1820 641 1821 640 1822 639 1823 641 1824 639 1825 638 1826 642 1827 641 1828 638 1829 642 1830 638 1831 637 1832 643 1833 642 1834 637 1835 643 1836 637 1837 665 1838 665 1839 637 1840 666 1841 666 1842 637 1843 636 1844 644 1845 643 1846 664 1847 664 1848 643 1849 665 1850 644 1851 664 1852 663 1853 667 1854 666 1855 636 1856 644 1857 663 1858 662 1859 668 1860 667 1861 636 1862 644 1863 662 1864 661 1865 669 1866 668 1867 636 1868 645 1869 644 1870 661 1871 669 1872 636 1873 635 1874 645 1875 661 1876 660 1877 670 1878 669 1879 635 1880 645 1881 660 1882 659 1883 671 1884 670 1885 635 1886 646 1887 645 1888 659 1889 671 1890 635 1891 634 1892 646 1893 659 1894 671 1895 646 1896 671 1897 634 1898 647 1899 646 1900 633 1901 633 1902 646 1903 634 1904 647 1905 633 1906 632 1907 647 1908 632 1909 631 1910 648 1911 647 1912 631 1913 648 1914 631 1915 630 1916 622 1917 621 1918 658 1919 623 1920 622 1921 658 1922 649 1923 648 1924 630 1925 649 1926 630 1927 629 1928 624 1929 623 1930 658 1931 649 1932 629 1933 628 1934 625 1935 624 1936 658 1937 626 1938 625 1939 658 1940 649 1941 628 1942 627 1943 627 1944 626 1945 658 1946 649 1947 627 1948 658 1949 650 1950 649 1951 658 1952 650 1953 658 1954 657 1955 650 1956 657 1957 656 1958 651 1959 650 1960 656 1961 651 1962 656 1963 655 1964 651 1965 655 1966 654 1967 652 1968 651 1969 654 1970 652 1971 654 1972 653 1973 680 1974 679 1975 678 1976 680 1977 678 1978 681 1979 674 1980 673 1981 672 1982 674 1983 672 1984 677 1985 675 1986 674 1987 677 1988 675 1989 677 1990 676 1991 705 1992 704 1993 703 1994 705 1995 703 1996 702 1997 706 1998 705 1999 702 2000 706 2001 702 2002 701 2003 683 2004 682 2005 712 2006 683 2007 712 2008 711 2009 707 2010 706 2011 701 2012 707 2013 701 2014 700 2015 707 2016 700 2017 699 2018 708 2019 707 2020 699 2021 708 2022 699 2023 698 2024 709 2025 708 2026 698 2027 709 2028 698 2029 691 2030 691 2031 698 2032 692 2033 692 2034 698 2035 693 2036 693 2037 698 2038 694 2039 694 2040 698 2041 695 2042 695 2043 698 2044 696 2045 696 2046 698 2047 697 2048 710 2049 709 2050 690 2051 690 2052 709 2053 691 2054 710 2055 690 2056 689 2057 710 2058 689 2059 688 2060 683 2061 711 2062 710 2063 683 2064 710 2065 687 2066 687 2067 710 2068 688 2069 683 2070 687 2071 686 2072 683 2073 686 2074 685 2075 683 2076 685 2077 684 2078 714 2079 713 2080 736 2081 714 2082 736 2083 735 2084 715 2085 714 2086 735 2087 715 2088 735 2089 734 2090 716 2091 715 2092 734 2093 716 2094 734 2095 737 2096 737 2097 734 2098 738 2099 738 2100 734 2101 733 2102 717 2103 716 2104 760 2105 760 2106 716 2107 737 2108 717 2109 760 2110 759 2111 739 2112 738 2113 733 2114 717 2115 759 2116 758 2117 740 2118 739 2119 733 2120 740 2121 733 2122 732 2123 718 2124 717 2125 758 2126 718 2127 758 2128 757 2129 741 2130 740 2131 732 2132 718 2133 757 2134 756 2135 742 2136 741 2137 732 2138 742 2139 732 2140 731 2141 719 2142 718 2143 756 2144 719 2145 756 2146 755 2147 743 2148 742 2149 731 2150 720 2151 719 2152 755 2153 720 2154 755 2155 754 2156 743 2157 731 2158 730 2159 744 2160 743 2161 730 2162 720 2163 754 2164 753 2165 745 2166 744 2167 730 2168 721 2169 720 2170 753 2171 745 2172 730 2173 729 2174 721 2175 753 2176 752 2177 746 2178 745 2179 729 2180 721 2181 752 2182 751 2183 747 2184 746 2185 729 2186 722 2187 721 2188 751 2189 747 2190 729 2191 728 2192 722 2193 751 2194 750 2195 748 2196 747 2197 728 2198 722 2199 750 2200 749 2201 749 2202 748 2203 728 2204 722 2205 749 2206 728 2207 723 2208 722 2209 728 2210 723 2211 728 2212 727 2213 724 2214 723 2215 727 2216 724 2217 727 2218 726 2219 725 2220 724 2221 726 2222 768 2223 767 2224 766 2225 768 2226 766 2227 765 2228 769 2229 768 2230 765 2231 769 2232 765 2233 764 2234 769 2235 764 2236 763 2237 770 2238 769 2239 763 2240 770 2241 763 2242 762 2243 770 2244 762 2245 761 2246 771 2247 770 2248 761 2249 771 2250 761 2251 822 2252 822 2253 761 2254 823 2255 823 2256 761 2257 824 2258 824 2259 761 2260 825 2261 825 2262 761 2263 826 2264 826 2265 761 2266 827 2267 827 2268 761 2269 828 2270 772 2271 771 2272 822 2273 772 2274 822 2275 821 2276 772 2277 821 2278 820 2279 772 2280 820 2281 819 2282 773 2283 772 2284 819 2285 773 2286 819 2287 818 2288 773 2289 818 2290 817 2291 773 2292 817 2293 816 2294 773 2295 816 2296 815 2297 774 2298 773 2299 815 2300 774 2301 815 2302 814 2303 774 2304 814 2305 813 2306 774 2307 813 2308 812 2309 774 2310 812 2311 811 2312 775 2313 774 2314 811 2315 775 2316 811 2317 810 2318 775 2319 810 2320 809 2321 776 2322 775 2323 809 2324 776 2325 809 2326 808 2327 777 2328 776 2329 808 2330 777 2331 808 2332 807 2333 777 2334 807 2335 806 2336 778 2337 777 2338 806 2339 778 2340 806 2341 805 2342 779 2343 778 2344 805 2345 779 2346 805 2347 804 2348 792 2349 791 2350 790 2351 779 2352 804 2353 803 2354 780 2355 779 2356 803 2357 792 2358 790 2359 789 2360 781 2361 780 2362 803 2363 792 2364 789 2365 788 2366 782 2367 781 2368 803 2369 782 2370 803 2371 802 2372 792 2373 788 2374 787 2375 783 2376 782 2377 802 2378 784 2379 783 2380 802 2381 792 2382 787 2383 786 2384 785 2385 784 2386 802 2387 792 2388 786 2389 785 2390 792 2391 785 2392 802 2393 792 2394 802 2395 801 2396 793 2397 792 2398 801 2399 793 2400 801 2401 800 2402 794 2403 793 2404 800 2405 795 2406 794 2407 800 2408 795 2409 800 2410 799 2411 796 2412 795 2413 799 2414 796 2415 799 2416 798 2417 797 2418 796 2419 798 2420 852 2421 851 2422 850 2423 852 2424 850 2425 849 2426 853 2427 852 2428 849 2429 853 2430 849 2431 848 2432 830 2433 829 2434 859 2435 830 2436 859 2437 858 2438 854 2439 853 2440 848 2441 854 2442 848 2443 847 2444 854 2445 847 2446 846 2447 855 2448 854 2449 846 2450 855 2451 846 2452 845 2453 856 2454 855 2455 845 2456 856 2457 845 2458 838 2459 838 2460 845 2461 839 2462 839 2463 845 2464 840 2465 840 2466 845 2467 841 2468 841 2469 845 2470 842 2471 842 2472 845 2473 843 2474 843 2475 845 2476 844 2477 857 2478 856 2479 837 2480 837 2481 856 2482 838 2483 857 2484 837 2485 836 2486 857 2487 836 2488 835 2489 830 2490 858 2491 857 2492 830 2493 857 2494 834 2495 834 2496 857 2497 835 2498 830 2499 834 2500 833 2501 830 2502 833 2503 832 2504 830 2505 832 2506 831 2507 878 2508 877 2509 876 2510 878 2511 876 2512 875 2513 863 2514 862 2515 861 2516 863 2517 861 2518 860 2519 879 2520 878 2521 875 2522 879 2523 875 2524 874 2525 879 2526 874 2527 873 2528 864 2529 863 2530 860 2531 880 2532 879 2533 873 2534 880 2535 873 2536 872 2537 865 2538 864 2539 860 2540 866 2541 865 2542 890 2543 890 2544 865 2545 860 2546 880 2547 872 2548 871 2549 867 2550 866 2551 890 2552 880 2553 871 2554 870 2555 881 2556 880 2557 870 2558 868 2559 867 2560 890 2561 881 2562 870 2563 869 2564 869 2565 868 2566 890 2567 881 2568 869 2569 890 2570 881 2571 890 2572 889 2573 891 2574 890 2575 860 2576 881 2577 889 2578 888 2579 882 2580 881 2581 888 2582 882 2583 888 2584 887 2585 883 2586 882 2587 887 2588 883 2589 887 2590 886 2591 883 2592 886 2593 885 2594 884 2595 883 2596 885 2597 899 2598 898 2599 897 2600 899 2601 897 2602 896 2603 899 2604 896 2605 895 2606 900 2607 899 2608 895 2609 900 2610 895 2611 894 2612 900 2613 894 2614 893 2615 900 2616 893 2617 892 2618 901 2619 900 2620 892 2621 901 2622 892 2623 935 2624 935 2625 892 2626 936 2627 936 2628 892 2629 937 2630 937 2631 892 2632 938 2633 938 2634 892 2635 939 2636 939 2637 892 2638 940 2639 940 2640 892 2641 941 2642 901 2643 935 2644 934 2645 901 2646 934 2647 933 2648 902 2649 901 2650 933 2651 902 2652 933 2653 932 2654 902 2655 932 2656 931 2657 903 2658 902 2659 931 2660 903 2661 931 2662 930 2663 904 2664 903 2665 930 2666 904 2667 930 2668 929 2669 904 2670 929 2671 928 2672 905 2673 904 2674 928 2675 905 2676 928 2677 927 2678 906 2679 905 2680 927 2681 906 2682 927 2683 926 2684 907 2685 906 2686 926 2687 918 2688 917 2689 916 2690 907 2691 926 2692 925 2693 919 2694 918 2695 916 2696 920 2697 919 2698 916 2699 907 2700 925 2701 924 2702 908 2703 907 2704 924 2705 921 2706 920 2707 916 2708 922 2709 921 2710 916 2711 908 2712 924 2713 923 2714 923 2715 922 2716 916 2717 908 2718 923 2719 916 2720 908 2721 916 2722 915 2723 909 2724 908 2725 915 2726 909 2727 915 2728 914 2729 909 2730 914 2731 913 2732 909 2733 913 2734 912 2735 910 2736 909 2737 912 2738 910 2739 912 2740 911 2741 943 2742 942 2743 975 2744 943 2745 975 2746 974 2747 943 2748 974 2749 973 2750 944 2751 943 2752 973 2753 945 2754 944 2755 973 2756 946 2757 945 2758 972 2759 972 2760 945 2761 973 2762 946 2763 972 2764 971 2765 946 2766 971 2767 970 2768 947 2769 946 2770 970 2771 947 2772 970 2773 969 2774 960 2775 959 2776 958 2777 947 2778 969 2779 968 2780 961 2781 960 2782 958 2783 948 2784 947 2785 968 2786 962 2787 961 2788 958 2789 948 2790 968 2791 967 2792 963 2793 962 2794 958 2795 948 2796 967 2797 966 2798 964 2799 963 2800 958 2801 948 2802 966 2803 965 2804 965 2805 964 2806 958 2807 948 2808 965 2809 958 2810 949 2811 948 2812 958 2813 950 2814 949 2815 958 2816 950 2817 958 2818 957 2819 950 2820 957 2821 956 2822 951 2823 950 2824 956 2825 951 2826 956 2827 955 2828 951 2829 955 2830 954 2831 952 2832 951 2833 954 2834 952 2835 954 2836 953 2837 977 2838 976 2839 999 2840 977 2841 999 2842 998 2843 978 2844 977 2845 998 2846 978 2847 998 2848 997 2849 979 2850 978 2851 997 2852 979 2853 997 2854 1000 2855 1000 2856 997 2857 1001 2858 1001 2859 997 2860 996 2861 980 2862 979 2863 1023 2864 1023 2865 979 2866 1000 2867 980 2868 1023 2869 1022 2870 1002 2871 1001 2872 996 2873 980 2874 1022 2875 1021 2876 1003 2877 1002 2878 996 2879 1003 2880 996 2881 995 2882 981 2883 980 2884 1021 2885 981 2886 1021 2887 1020 2888 1004 2889 1003 2890 995 2891 981 2892 1020 2893 1019 2894 1005 2895 1004 2896 995 2897 1005 2898 995 2899 994 2900 982 2901 981 2902 1019 2903 982 2904 1019 2905 1018 2906 1006 2907 1005 2908 994 2909 983 2910 982 2911 1018 2912 983 2913 1018 2914 1017 2915 1006 2916 994 2917 993 2918 1007 2919 1006 2920 993 2921 983 2922 1017 2923 1016 2924 1008 2925 1007 2926 993 2927 984 2928 983 2929 1016 2930 1008 2931 993 2932 992 2933 984 2934 1016 2935 1015 2936 1009 2937 1008 2938 992 2939 984 2940 1015 2941 1014 2942 1010 2943 1009 2944 992 2945 985 2946 984 2947 1014 2948 1010 2949 992 2950 991 2951 985 2952 1014 2953 1013 2954 1011 2955 1010 2956 991 2957 985 2958 1013 2959 1012 2960 1012 2961 1011 2962 991 2963 985 2964 1012 2965 991 2966 986 2967 985 2968 991 2969 986 2970 991 2971 990 2972 987 2973 986 2974 990 2975 987 2976 990 2977 989 2978 988 2979 987 2980 989 2981 1026 2982 1025 2983 1024 2984 1026 2985 1024 2986 1056 2987 1050 2988 1049 2989 1048 2990 1051 2991 1050 2992 1048 2993 1051 2994 1048 2995 1047 2996 1052 2997 1051 2998 1047 2999 1053 3000 1052 3001 1047 3002 1053 3003 1047 3004 1046 3005 1054 3006 1053 3007 1046 3008 1054 3009 1046 3010 1045 3011 1055 3012 1054 3013 1034 3014 1034 3015 1054 3016 1045 3017 1026 3018 1056 3019 1055 3020 1026 3021 1055 3022 1028 3023 1028 3024 1055 3025 1029 3026 1029 3027 1055 3028 1030 3029 1030 3030 1055 3031 1031 3032 1031 3033 1055 3034 1032 3035 1032 3036 1055 3037 1033 3038 1033 3039 1055 3040 1034 3041 1035 3042 1034 3043 1045 3044 1036 3045 1035 3046 1045 3047 1036 3048 1045 3049 1044 3050 1037 3051 1036 3052 1044 3053 1038 3054 1037 3055 1044 3056 1039 3057 1038 3058 1044 3059 1039 3060 1044 3061 1043 3062 1026 3063 1028 3064 1027 3065 1040 3066 1039 3067 1043 3068 1041 3069 1040 3070 1043 3071 1041 3072 1043 3073 1042 3074 1064 3075 1063 3076 1062 3077 1064 3078 1062 3079 1061 3080 1065 3081 1064 3082 1061 3083 1065 3084 1061 3085 1060 3086 1065 3087 1060 3088 1059 3089 1066 3090 1065 3091 1059 3092 1066 3093 1059 3094 1058 3095 1066 3096 1058 3097 1057 3098 1067 3099 1066 3100 1057 3101 1067 3102 1057 3103 1118 3104 1118 3105 1057 3106 1119 3107 1119 3108 1057 3109 1120 3110 1120 3111 1057 3112 1121 3113 1121 3114 1057 3115 1122 3116 1122 3117 1057 3118 1123 3119 1123 3120 1057 3121 1124 3122 1068 3123 1067 3124 1118 3125 1068 3126 1118 3127 1117 3128 1068 3129 1117 3130 1116 3131 1068 3132 1116 3133 1115 3134 1069 3135 1068 3136 1115 3137 1069 3138 1115 3139 1114 3140 1069 3141 1114 3142 1113 3143 1069 3144 1113 3145 1112 3146 1069 3147 1112 3148 1111 3149 1070 3150 1069 3151 1111 3152 1070 3153 1111 3154 1110 3155 1070 3156 1110 3157 1109 3158 1070 3159 1109 3160 1108 3161 1070 3162 1108 3163 1107 3164 1071 3165 1070 3166 1107 3167 1071 3168 1107 3169 1106 3170 1071 3171 1106 3172 1105 3173 1072 3174 1071 3175 1105 3176 1072 3177 1105 3178 1104 3179 1073 3180 1072 3181 1104 3182 1073 3183 1104 3184 1103 3185 1073 3186 1103 3187 1102 3188 1074 3189 1073 3190 1102 3191 1074 3192 1102 3193 1101 3194 1075 3195 1074 3196 1101 3197 1075 3198 1101 3199 1100 3200 1088 3201 1087 3202 1086 3203 1075 3204 1100 3205 1099 3206 1076 3207 1075 3208 1099 3209 1088 3210 1086 3211 1085 3212 1077 3213 1076 3214 1099 3215 1088 3216 1085 3217 1084 3218 1078 3219 1077 3220 1099 3221 1078 3222 1099 3223 1098 3224 1088 3225 1084 3226 1083 3227 1079 3228 1078 3229 1098 3230 1080 3231 1079 3232 1098 3233 1088 3234 1083 3235 1082 3236 1081 3237 1080 3238 1098 3239 1088 3240 1082 3241 1081 3242 1088 3243 1081 3244 1098 3245 1088 3246 1098 3247 1097 3248 1089 3249 1088 3250 1097 3251 1089 3252 1097 3253 1096 3254 1090 3255 1089 3256 1096 3257 1091 3258 1090 3259 1096 3260 1091 3261 1096 3262 1095 3263 1092 3264 1091 3265 1095 3266 1092 3267 1095 3268 1094 3269 1093 3270 1092 3271 1094 3272 1130 3273 1129 3274 1128 3275 1130 3276 1128 3277 1127 3278 1127 3279 1126 3280 1125 3281 1127 3282 1125 3283 1132 3284 1130 3285 1127 3286 1132 3287 1131 3288 1130 3289 1132 3290 1135 3291 1134 3292 1133 3293 1135 3294 1133 3295 1136 3296 1157 3297 1156 3298 1159 3299 1159 3300 1156 3301 1155 3302 1159 3303 1155 3304 1154 3305 1159 3306 1154 3307 1153 3308 1159 3309 1153 3310 1152 3311 1159 3312 1152 3313 1160 3314 1160 3315 1152 3316 1161 3317 1161 3318 1152 3319 1151 3320 1157 3321 1159 3322 1178 3323 1162 3324 1161 3325 1151 3326 1163 3327 1162 3328 1151 3329 1163 3330 1151 3331 1150 3332 1164 3333 1163 3334 1150 3335 1165 3336 1164 3337 1150 3338 1165 3339 1150 3340 1149 3341 1166 3342 1165 3343 1149 3344 1167 3345 1166 3346 1149 3347 1167 3348 1149 3349 1148 3350 1168 3351 1167 3352 1148 3353 1168 3354 1148 3355 1147 3356 1169 3357 1168 3358 1147 3359 1170 3360 1169 3361 1147 3362 1170 3363 1147 3364 1146 3365 1157 3366 1178 3367 1177 3368 1171 3369 1170 3370 1146 3371 1157 3372 1177 3373 1137 3374 1137 3375 1177 3376 1176 3377 1137 3378 1176 3379 1175 3380 1172 3381 1171 3382 1146 3383 1137 3384 1175 3385 1174 3386 1137 3387 1174 3388 1173 3389 1137 3390 1173 3391 1172 3392 1137 3393 1172 3394 1146 3395 1137 3396 1146 3397 1145 3398 1137 3399 1145 3400 1144 3401 1157 3402 1137 3403 1158 3404 1138 3405 1137 3406 1144 3407 1139 3408 1138 3409 1144 3410 1140 3411 1139 3412 1144 3413 1140 3414 1144 3415 1143 3416 1141 3417 1140 3418 1143 3419 1142 3420 1141 3421 1143 3422 1199 3423 1198 3424 1201 3425 1201 3426 1198 3427 1197 3428 1201 3429 1197 3430 1196 3431 1201 3432 1196 3433 1195 3434 1201 3435 1195 3436 1194 3437 1201 3438 1194 3439 1202 3440 1202 3441 1194 3442 1203 3443 1203 3444 1194 3445 1193 3446 1199 3447 1201 3448 1220 3449 1204 3450 1203 3451 1193 3452 1205 3453 1204 3454 1193 3455 1205 3456 1193 3457 1192 3458 1206 3459 1205 3460 1192 3461 1207 3462 1206 3463 1192 3464 1207 3465 1192 3466 1191 3467 1208 3468 1207 3469 1191 3470 1209 3471 1208 3472 1191 3473 1209 3474 1191 3475 1190 3476 1210 3477 1209 3478 1190 3479 1210 3480 1190 3481 1189 3482 1211 3483 1210 3484 1189 3485 1212 3486 1211 3487 1189 3488 1212 3489 1189 3490 1188 3491 1199 3492 1220 3493 1219 3494 1213 3495 1212 3496 1188 3497 1199 3498 1219 3499 1179 3500 1179 3501 1219 3502 1218 3503 1179 3504 1218 3505 1217 3506 1214 3507 1213 3508 1188 3509 1179 3510 1217 3511 1216 3512 1179 3513 1216 3514 1215 3515 1179 3516 1215 3517 1214 3518 1179 3519 1214 3520 1188 3521 1179 3522 1188 3523 1187 3524 1179 3525 1187 3526 1186 3527 1199 3528 1179 3529 1200 3530 1180 3531 1179 3532 1186 3533 1181 3534 1180 3535 1186 3536 1182 3537 1181 3538 1186 3539 1182 3540 1186 3541 1185 3542 1183 3543 1182 3544 1185 3545 1184 3546 1183 3547 1185 3548 1241 3549 1240 3550 1239 3551 1242 3552 1241 3553 1239 3554 1242 3555 1239 3556 1238 3557 1243 3558 1242 3559 1238 3560 1244 3561 1243 3562 1238 3563 1244 3564 1238 3565 1237 3566 1245 3567 1244 3568 1237 3569 1245 3570 1237 3571 1236 3572 1246 3573 1245 3574 1236 3575 1247 3576 1246 3577 1248 3578 1248 3579 1246 3580 1249 3581 1249 3582 1246 3583 1250 3584 1250 3585 1246 3586 1251 3587 1251 3588 1246 3589 1252 3590 1252 3591 1246 3592 1253 3593 1253 3594 1246 3595 1236 3596 1253 3597 1236 3598 1254 3599 1254 3600 1236 3601 1235 3602 1255 3603 1254 3604 1235 3605 1256 3606 1255 3607 1235 3608 1256 3609 1235 3610 1234 3611 1257 3612 1256 3613 1234 3614 1258 3615 1257 3616 1234 3617 1259 3618 1258 3619 1234 3620 1259 3621 1234 3622 1233 3623 1260 3624 1259 3625 1233 3626 1261 3627 1260 3628 1310 3629 1310 3630 1260 3631 1233 3632 1262 3633 1261 3634 1310 3635 1263 3636 1262 3637 1310 3638 1263 3639 1310 3640 1309 3641 1292 3642 1310 3643 1233 3644 1264 3645 1263 3646 1309 3647 1264 3648 1309 3649 1308 3650 1265 3651 1264 3652 1308 3653 1265 3654 1308 3655 1307 3656 1265 3657 1307 3658 1306 3659 1266 3660 1265 3661 1306 3662 1266 3663 1306 3664 1305 3665 1266 3666 1305 3667 1304 3668 1267 3669 1266 3670 1304 3671 1267 3672 1304 3673 1303 3674 1268 3675 1267 3676 1303 3677 1268 3678 1303 3679 1302 3680 1293 3681 1292 3682 1233 3683 1268 3684 1302 3685 1301 3686 1294 3687 1293 3688 1233 3689 1222 3690 1221 3691 1291 3692 1294 3693 1233 3694 1232 3695 1223 3696 1222 3697 1291 3698 1269 3699 1268 3700 1301 3701 1269 3702 1301 3703 1300 3704 1294 3705 1232 3706 1231 3707 1295 3708 1294 3709 1231 3710 1224 3711 1223 3712 1291 3713 1295 3714 1231 3715 1230 3716 1296 3717 1295 3718 1230 3719 1225 3720 1224 3721 1291 3722 1269 3723 1300 3724 1299 3725 1296 3726 1230 3727 1229 3728 1226 3729 1225 3730 1291 3731 1297 3732 1296 3733 1229 3734 1297 3735 1229 3736 1228 3737 1227 3738 1226 3739 1291 3740 1297 3741 1228 3742 1227 3743 1269 3744 1299 3745 1298 3746 1297 3747 1227 3748 1291 3749 1298 3750 1297 3751 1291 3752 1269 3753 1298 3754 1279 3755 1279 3756 1298 3757 1291 3758 1270 3759 1269 3760 1279 3761 1270 3762 1279 3763 1278 3764 1280 3765 1279 3766 1291 3767 1280 3768 1291 3769 1290 3770 1271 3771 1270 3772 1278 3773 1271 3774 1278 3775 1277 3776 1281 3777 1280 3778 1290 3779 1281 3780 1290 3781 1289 3782 1271 3783 1277 3784 1276 3785 1282 3786 1281 3787 1289 3788 1272 3789 1271 3790 1276 3791 1282 3792 1289 3793 1288 3794 1272 3795 1276 3796 1275 3797 1283 3798 1282 3799 1288 3800 1283 3801 1288 3802 1287 3803 1272 3804 1275 3805 1274 3806 1284 3807 1283 3808 1287 3809 1273 3810 1272 3811 1274 3812 1284 3813 1287 3814 1286 3815 1285 3816 1284 3817 1286 3818 1312 3819 1311 3820 1334 3821 1312 3822 1334 3823 1333 3824 1313 3825 1312 3826 1333 3827 1313 3828 1333 3829 1332 3830 1314 3831 1313 3832 1332 3833 1314 3834 1332 3835 1335 3836 1335 3837 1332 3838 1336 3839 1336 3840 1332 3841 1331 3842 1315 3843 1314 3844 1358 3845 1358 3846 1314 3847 1335 3848 1315 3849 1358 3850 1357 3851 1337 3852 1336 3853 1331 3854 1315 3855 1357 3856 1356 3857 1338 3858 1337 3859 1331 3860 1338 3861 1331 3862 1330 3863 1316 3864 1315 3865 1356 3866 1316 3867 1356 3868 1355 3869 1339 3870 1338 3871 1330 3872 1316 3873 1355 3874 1354 3875 1340 3876 1339 3877 1330 3878 1340 3879 1330 3880 1329 3881 1317 3882 1316 3883 1354 3884 1317 3885 1354 3886 1353 3887 1341 3888 1340 3889 1329 3890 1318 3891 1317 3892 1353 3893 1318 3894 1353 3895 1352 3896 1341 3897 1329 3898 1328 3899 1342 3900 1341 3901 1328 3902 1318 3903 1352 3904 1351 3905 1343 3906 1342 3907 1328 3908 1319 3909 1318 3910 1351 3911 1343 3912 1328 3913 1327 3914 1319 3915 1351 3916 1350 3917 1344 3918 1343 3919 1327 3920 1319 3921 1350 3922 1349 3923 1345 3924 1344 3925 1327 3926 1320 3927 1319 3928 1349 3929 1345 3930 1327 3931 1326 3932 1320 3933 1349 3934 1348 3935 1346 3936 1345 3937 1326 3938 1320 3939 1348 3940 1347 3941 1347 3942 1346 3943 1326 3944 1320 3945 1347 3946 1326 3947 1321 3948 1320 3949 1326 3950 1321 3951 1326 3952 1325 3953 1322 3954 1321 3955 1325 3956 1322 3957 1325 3958 1324 3959 1323 3960 1322 3961 1324 3962 1360 3963 1359 3964 1392 3965 1360 3966 1392 3967 1391 3968 1360 3969 1391 3970 1390 3971 1361 3972 1360 3973 1390 3974 1362 3975 1361 3976 1390 3977 1363 3978 1362 3979 1389 3980 1389 3981 1362 3982 1390 3983 1363 3984 1389 3985 1388 3986 1363 3987 1388 3988 1387 3989 1364 3990 1363 3991 1387 3992 1364 3993 1387 3994 1386 3995 1377 3996 1376 3997 1375 3998 1364 3999 1386 4000 1385 4001 1378 4002 1377 4003 1375 4004 1365 4005 1364 4006 1385 4007 1379 4008 1378 4009 1375 4010 1365 4011 1385 4012 1384 4013 1380 4014 1379 4015 1375 4016 1365 4017 1384 4018 1383 4019 1381 4020 1380 4021 1375 4022 1365 4023 1383 4024 1382 4025 1382 4026 1381 4027 1375 4028 1365 4029 1382 4030 1375 4031 1366 4032 1365 4033 1375 4034 1367 4035 1366 4036 1375 4037 1367 4038 1375 4039 1374 4040 1367 4041 1374 4042 1373 4043 1368 4044 1367 4045 1373 4046 1368 4047 1373 4048 1372 4049 1368 4050 1372 4051 1371 4052 1369 4053 1368 4054 1371 4055 1369 4056 1371 4057 1370 4058 1413 4059 1412 4060 1411 4061 1413 4062 1411 4063 1410 4064 1414 4065 1413 4066 1410 4067 1414 4068 1410 4069 1409 4070 1415 4071 1414 4072 1409 4073 1415 4074 1409 4075 1437 4076 1437 4077 1409 4078 1438 4079 1438 4080 1409 4081 1408 4082 1416 4083 1415 4084 1436 4085 1436 4086 1415 4087 1437 4088 1416 4089 1436 4090 1435 4091 1439 4092 1438 4093 1408 4094 1416 4095 1435 4096 1434 4097 1440 4098 1439 4099 1408 4100 1416 4101 1434 4102 1433 4103 1441 4104 1440 4105 1408 4106 1417 4107 1416 4108 1433 4109 1441 4110 1408 4111 1407 4112 1417 4113 1433 4114 1432 4115 1442 4116 1441 4117 1407 4118 1417 4119 1432 4120 1431 4121 1443 4122 1442 4123 1407 4124 1418 4125 1417 4126 1431 4127 1443 4128 1407 4129 1406 4130 1418 4131 1431 4132 1443 4133 1418 4134 1443 4135 1406 4136 1419 4137 1418 4138 1405 4139 1405 4140 1418 4141 1406 4142 1419 4143 1405 4144 1404 4145 1419 4146 1404 4147 1403 4148 1420 4149 1419 4150 1403 4151 1420 4152 1403 4153 1402 4154 1394 4155 1393 4156 1430 4157 1395 4158 1394 4159 1430 4160 1421 4161 1420 4162 1402 4163 1421 4164 1402 4165 1401 4166 1396 4167 1395 4168 1430 4169 1421 4170 1401 4171 1400 4172 1397 4173 1396 4174 1430 4175 1398 4176 1397 4177 1430 4178 1421 4179 1400 4180 1399 4181 1399 4182 1398 4183 1430 4184 1421 4185 1399 4186 1430 4187 1422 4188 1421 4189 1430 4190 1422 4191 1430 4192 1429 4193 1422 4194 1429 4195 1428 4196 1423 4197 1422 4198 1428 4199 1423 4200 1428 4201 1427 4202 1423 4203 1427 4204 1426 4205 1424 4206 1423 4207 1426 4208 1424 4209 1426 4210 1425 4211 1451 4212 1450 4213 1449 4214 1451 4215 1449 4216 1448 4217 1452 4218 1451 4219 1448 4220 1452 4221 1448 4222 1447 4223 1452 4224 1447 4225 1446 4226 1453 4227 1452 4228 1446 4229 1453 4230 1446 4231 1445 4232 1453 4233 1445 4234 1444 4235 1454 4236 1453 4237 1444 4238 1454 4239 1444 4240 1505 4241 1505 4242 1444 4243 1506 4244 1506 4245 1444 4246 1507 4247 1507 4248 1444 4249 1508 4250 1508 4251 1444 4252 1509 4253 1509 4254 1444 4255 1510 4256 1510 4257 1444 4258 1511 4259 1455 4260 1454 4261 1505 4262 1455 4263 1505 4264 1504 4265 1455 4266 1504 4267 1503 4268 1455 4269 1503 4270 1502 4271 1456 4272 1455 4273 1502 4274 1456 4275 1502 4276 1501 4277 1456 4278 1501 4279 1500 4280 1456 4281 1500 4282 1499 4283 1456 4284 1499 4285 1498 4286 1457 4287 1456 4288 1498 4289 1457 4290 1498 4291 1497 4292 1457 4293 1497 4294 1496 4295 1457 4296 1496 4297 1495 4298 1457 4299 1495 4300 1494 4301 1458 4302 1457 4303 1494 4304 1458 4305 1494 4306 1493 4307 1458 4308 1493 4309 1492 4310 1459 4311 1458 4312 1492 4313 1459 4314 1492 4315 1491 4316 1460 4317 1459 4318 1491 4319 1460 4320 1491 4321 1490 4322 1460 4323 1490 4324 1489 4325 1461 4326 1460 4327 1489 4328 1461 4329 1489 4330 1488 4331 1462 4332 1461 4333 1488 4334 1462 4335 1488 4336 1487 4337 1475 4338 1474 4339 1473 4340 1462 4341 1487 4342 1486 4343 1463 4344 1462 4345 1486 4346 1475 4347 1473 4348 1472 4349 1464 4350 1463 4351 1486 4352 1475 4353 1472 4354 1471 4355 1465 4356 1464 4357 1486 4358 1465 4359 1486 4360 1485 4361 1475 4362 1471 4363 1470 4364 1466 4365 1465 4366 1485 4367 1467 4368 1466 4369 1485 4370 1475 4371 1470 4372 1469 4373 1468 4374 1467 4375 1485 4376 1475 4377 1469 4378 1468 4379 1475 4380 1468 4381 1485 4382 1475 4383 1485 4384 1484 4385 1476 4386 1475 4387 1484 4388 1476 4389 1484 4390 1483 4391 1477 4392 1476 4393 1483 4394 1478 4395 1477 4396 1483 4397 1478 4398 1483 4399 1482 4400 1479 4401 1478 4402 1482 4403 1479 4404 1482 4405 1481 4406 1480 4407 1479 4408 1481 4409 1530 4410 1529 4411 1528 4412 1530 4413 1528 4414 1527 4415 1515 4416 1514 4417 1513 4418 1515 4419 1513 4420 1512 4421 1531 4422 1530 4423 1527 4424 1531 4425 1527 4426 1526 4427 1531 4428 1526 4429 1525 4430 1516 4431 1515 4432 1512 4433 1532 4434 1531 4435 1525 4436 1532 4437 1525 4438 1524 4439 1517 4440 1516 4441 1512 4442 1518 4443 1517 4444 1542 4445 1542 4446 1517 4447 1512 4448 1532 4449 1524 4450 1523 4451 1519 4452 1518 4453 1542 4454 1532 4455 1523 4456 1522 4457 1533 4458 1532 4459 1522 4460 1520 4461 1519 4462 1542 4463 1533 4464 1522 4465 1521 4466 1521 4467 1520 4468 1542 4469 1533 4470 1521 4471 1542 4472 1533 4473 1542 4474 1541 4475 1543 4476 1542 4477 1512 4478 1533 4479 1541 4480 1540 4481 1534 4482 1533 4483 1540 4484 1534 4485 1540 4486 1539 4487 1535 4488 1534 4489 1539 4490 1535 4491 1539 4492 1538 4493 1535 4494 1538 4495 1537 4496 1536 4497 1535 4498 1537 4499 1545 4500 1544 4501 1567 4502 1545 4503 1567 4504 1566 4505 1546 4506 1545 4507 1566 4508 1546 4509 1566 4510 1565 4511 1547 4512 1546 4513 1565 4514 1547 4515 1565 4516 1568 4517 1568 4518 1565 4519 1569 4520 1569 4521 1565 4522 1564 4523 1548 4524 1547 4525 1591 4526 1591 4527 1547 4528 1568 4529 1548 4530 1591 4531 1590 4532 1570 4533 1569 4534 1564 4535 1548 4536 1590 4537 1589 4538 1571 4539 1570 4540 1564 4541 1571 4542 1564 4543 1563 4544 1549 4545 1548 4546 1589 4547 1549 4548 1589 4549 1588 4550 1572 4551 1571 4552 1563 4553 1549 4554 1588 4555 1587 4556 1573 4557 1572 4558 1563 4559 1573 4560 1563 4561 1562 4562 1550 4563 1549 4564 1587 4565 1550 4566 1587 4567 1586 4568 1574 4569 1573 4570 1562 4571 1551 4572 1550 4573 1586 4574 1551 4575 1586 4576 1585 4577 1574 4578 1562 4579 1561 4580 1575 4581 1574 4582 1561 4583 1551 4584 1585 4585 1584 4586 1576 4587 1575 4588 1561 4589 1552 4590 1551 4591 1584 4592 1576 4593 1561 4594 1560 4595 1552 4596 1584 4597 1583 4598 1577 4599 1576 4600 1560 4601 1552 4602 1583 4603 1582 4604 1578 4605 1577 4606 1560 4607 1553 4608 1552 4609 1582 4610 1578 4611 1560 4612 1559 4613 1553 4614 1582 4615 1581 4616 1579 4617 1578 4618 1559 4619 1553 4620 1581 4621 1580 4622 1580 4623 1579 4624 1559 4625 1553 4626 1580 4627 1559 4628 1554 4629 1553 4630 1559 4631 1554 4632 1559 4633 1558 4634 1555 4635 1554 4636 1558 4637 1555 4638 1558 4639 1557 4640 1556 4641 1555 4642 1557 4643 1644 4644 1643 4645 1642 4646 1632 4647 1631 4648 1630 4649 1645 4650 1644 4651 1642 4652 1645 4653 1642 4654 1641 4655 1633 4656 1632 4657 1630 4658 1633 4659 1630 4660 1629 4661 1646 4662 1645 4663 1641 4664 1593 4665 1592 4666 1650 4667 1593 4668 1650 4669 1649 4670 1646 4671 1641 4672 1640 4673 1634 4674 1633 4675 1629 4676 1647 4677 1646 4678 1640 4679 1647 4680 1640 4681 1639 4682 1634 4683 1629 4684 1628 4685 1635 4686 1634 4687 1628 4688 1648 4689 1647 4690 1639 4691 1648 4692 1639 4693 1638 4694 1636 4695 1635 4696 1628 4697 1649 4698 1648 4699 1638 4700 1636 4701 1628 4702 1627 4703 1649 4704 1638 4705 1637 4706 1637 4707 1636 4708 1616 4709 1616 4710 1636 4711 1627 4712 1593 4713 1649 4714 1595 4715 1595 4716 1649 4717 1596 4718 1596 4719 1649 4720 1597 4721 1597 4722 1649 4723 1598 4724 1598 4725 1649 4726 1599 4727 1599 4728 1649 4729 1600 4730 1600 4731 1649 4732 1601 4733 1601 4734 1649 4735 1637 4736 1602 4737 1601 4738 1637 4739 1637 4740 1616 4741 1615 4742 1617 4743 1616 4744 1627 4745 1637 4746 1615 4747 1614 4748 1603 4749 1602 4750 1637 4751 1618 4752 1617 4753 1627 4754 1603 4755 1637 4756 1614 4757 1603 4758 1614 4759 1613 4760 1618 4761 1627 4762 1626 4763 1604 4764 1603 4765 1613 4766 1619 4767 1618 4768 1626 4769 1604 4770 1613 4771 1612 4772 1605 4773 1604 4774 1612 4775 1620 4776 1619 4777 1626 4778 1605 4779 1612 4780 1611 4781 1605 4782 1611 4783 1610 4784 1606 4785 1605 4786 1610 4787 1621 4788 1620 4789 1626 4790 1621 4791 1626 4792 1625 4793 1593 4794 1595 4795 1594 4796 1606 4797 1610 4798 1609 4799 1607 4800 1606 4801 1609 4802 1622 4803 1621 4804 1625 4805 1622 4806 1625 4807 1624 4808 1608 4809 1607 4810 1609 4811 1623 4812 1622 4813 1624 4814 1652 4815 1651 4816 1684 4817 1652 4818 1684 4819 1683 4820 1652 4821 1683 4822 1682 4823 1653 4824 1652 4825 1682 4826 1654 4827 1653 4828 1682 4829 1655 4830 1654 4831 1681 4832 1681 4833 1654 4834 1682 4835 1655 4836 1681 4837 1680 4838 1655 4839 1680 4840 1679 4841 1656 4842 1655 4843 1679 4844 1656 4845 1679 4846 1678 4847 1669 4848 1668 4849 1667 4850 1656 4851 1678 4852 1677 4853 1670 4854 1669 4855 1667 4856 1657 4857 1656 4858 1677 4859 1671 4860 1670 4861 1667 4862 1657 4863 1677 4864 1676 4865 1672 4866 1671 4867 1667 4868 1657 4869 1676 4870 1675 4871 1673 4872 1672 4873 1667 4874 1657 4875 1675 4876 1674 4877 1674 4878 1673 4879 1667 4880 1657 4881 1674 4882 1667 4883 1658 4884 1657 4885 1667 4886 1659 4887 1658 4888 1667 4889 1659 4890 1667 4891 1666 4892 1659 4893 1666 4894 1665 4895 1660 4896 1659 4897 1665 4898 1660 4899 1665 4900 1664 4901 1660 4902 1664 4903 1663 4904 1661 4905 1660 4906 1663 4907 1661 4908 1663 4909 1662 4910 1688 4911 1687 4912 1686 4913 1688 4914 1686 4915 1685 4916 1689 4917 1688 4918 1685 4919 1689 4920 1685 4921 1720 4922 1690 4923 1689 4924 1720 4925 1691 4926 1690 4927 1717 4928 1717 4929 1690 4930 1718 4931 1718 4932 1690 4933 1719 4934 1719 4935 1690 4936 1720 4937 1692 4938 1691 4939 1717 4940 1693 4941 1692 4942 1714 4943 1714 4944 1692 4945 1715 4946 1715 4947 1692 4948 1716 4949 1716 4950 1692 4951 1717 4952 1694 4953 1693 4954 1713 4955 1713 4956 1693 4957 1714 4958 1694 4959 1713 4960 1712 4961 1694 4962 1712 4963 1711 4964 1695 4965 1694 4966 1711 4967 1695 4968 1711 4969 1710 4970 1696 4971 1695 4972 1710 4973 1696 4974 1710 4975 1709 4976 1696 4977 1709 4978 1708 4979 1697 4980 1696 4981 1708 4982 1697 4983 1708 4984 1707 4985 1698 4986 1697 4987 1707 4988 1700 4989 1699 4990 1698 4991 1700 4992 1698 4993 1707 4994 1700 4995 1707 4996 1706 4997 1700 4998 1706 4999 1705 5000 1701 5001 1700 5002 1705 5003 1702 5004 1701 5005 1704 5006 1704 5007 1701 5008 1705 5009 1702 5010 1704 5011 1703 5012 1741 5013 1740 5014 1739 5015 1741 5016 1739 5017 1738 5018 1742 5019 1741 5020 1738 5021 1742 5022 1738 5023 1737 5024 1743 5025 1742 5026 1737 5027 1743 5028 1737 5029 1765 5030 1765 5031 1737 5032 1766 5033 1766 5034 1737 5035 1736 5036 1744 5037 1743 5038 1764 5039 1764 5040 1743 5041 1765 5042 1744 5043 1764 5044 1763 5045 1767 5046 1766 5047 1736 5048 1744 5049 1763 5050 1762 5051 1768 5052 1767 5053 1736 5054 1744 5055 1762 5056 1761 5057 1769 5058 1768 5059 1736 5060 1745 5061 1744 5062 1761 5063 1769 5064 1736 5065 1735 5066 1745 5067 1761 5068 1760 5069 1770 5070 1769 5071 1735 5072 1745 5073 1760 5074 1759 5075 1771 5076 1770 5077 1735 5078 1746 5079 1745 5080 1759 5081 1771 5082 1735 5083 1734 5084 1746 5085 1759 5086 1771 5087 1746 5088 1771 5089 1734 5090 1747 5091 1746 5092 1733 5093 1733 5094 1746 5095 1734 5096 1747 5097 1733 5098 1732 5099 1747 5100 1732 5101 1731 5102 1748 5103 1747 5104 1731 5105 1748 5106 1731 5107 1730 5108 1722 5109 1721 5110 1758 5111 1723 5112 1722 5113 1758 5114 1749 5115 1748 5116 1730 5117 1749 5118 1730 5119 1729 5120 1724 5121 1723 5122 1758 5123 1749 5124 1729 5125 1728 5126 1725 5127 1724 5128 1758 5129 1726 5130 1725 5131 1758 5132 1749 5133 1728 5134 1727 5135 1727 5136 1726 5137 1758 5138 1749 5139 1727 5140 1758 5141 1750 5142 1749 5143 1758 5144 1750 5145 1758 5146 1757 5147 1750 5148 1757 5149 1756 5150 1751 5151 1750 5152 1756 5153 1751 5154 1756 5155 1755 5156 1751 5157 1755 5158 1754 5159 1752 5160 1751 5161 1754 5162 1752 5163 1754 5164 1753 5165 1774 5166 1773 5167 1772 5168 1774 5169 1772 5170 1775 5171 1789 5172 1788 5173 1787 5174 1790 5175 1789 5176 1787 5177 1790 5178 1787 5179 1786 5180 1791 5181 1790 5182 1786 5183 1791 5184 1786 5185 1785 5186 1792 5187 1791 5188 1785 5189 1792 5190 1785 5191 1784 5192 1793 5193 1792 5194 1784 5195 1794 5196 1793 5197 1784 5198 1794 5199 1784 5200 1783 5201 1795 5202 1794 5203 1783 5204 1795 5205 1783 5206 1782 5207 1796 5208 1795 5209 1782 5210 1797 5211 1796 5212 1782 5213 1797 5214 1782 5215 1781 5216 1798 5217 1797 5218 1781 5219 1799 5220 1798 5221 1800 5222 1800 5223 1798 5224 1781 5225 1801 5226 1800 5227 1781 5228 1801 5229 1781 5230 1780 5231 1802 5232 1801 5233 1780 5234 1803 5235 1802 5236 1780 5237 1803 5238 1780 5239 1779 5240 1804 5241 1803 5242 1779 5243 1804 5244 1779 5245 1778 5246 1805 5247 1804 5248 1778 5249 1805 5250 1778 5251 1777 5252 1806 5253 1805 5254 1777 5255 1776 5256 1806 5257 1777 5258 1859 5259 1858 5260 1857 5261 1847 5262 1846 5263 1845 5264 1860 5265 1859 5266 1857 5267 1860 5268 1857 5269 1856 5270 1848 5271 1847 5272 1845 5273 1848 5274 1845 5275 1844 5276 1861 5277 1860 5278 1856 5279 1808 5280 1807 5281 1865 5282 1808 5283 1865 5284 1864 5285 1861 5286 1856 5287 1855 5288 1849 5289 1848 5290 1844 5291 1862 5292 1861 5293 1855 5294 1862 5295 1855 5296 1854 5297 1849 5298 1844 5299 1843 5300 1850 5301 1849 5302 1843 5303 1863 5304 1862 5305 1854 5306 1863 5307 1854 5308 1853 5309 1851 5310 1850 5311 1843 5312 1864 5313 1863 5314 1853 5315 1851 5316 1843 5317 1842 5318 1864 5319 1853 5320 1852 5321 1852 5322 1851 5323 1831 5324 1831 5325 1851 5326 1842 5327 1808 5328 1864 5329 1810 5330 1810 5331 1864 5332 1811 5333 1811 5334 1864 5335 1812 5336 1812 5337 1864 5338 1813 5339 1813 5340 1864 5341 1814 5342 1814 5343 1864 5344 1815 5345 1815 5346 1864 5347 1816 5348 1816 5349 1864 5350 1852 5351 1817 5352 1816 5353 1852 5354 1852 5355 1831 5356 1830 5357 1832 5358 1831 5359 1842 5360 1852 5361 1830 5362 1829 5363 1818 5364 1817 5365 1852 5366 1833 5367 1832 5368 1842 5369 1818 5370 1852 5371 1829 5372 1818 5373 1829 5374 1828 5375 1833 5376 1842 5377 1841 5378 1819 5379 1818 5380 1828 5381 1834 5382 1833 5383 1841 5384 1819 5385 1828 5386 1827 5387 1820 5388 1819 5389 1827 5390 1835 5391 1834 5392 1841 5393 1820 5394 1827 5395 1826 5396 1820 5397 1826 5398 1825 5399 1821 5400 1820 5401 1825 5402 1836 5403 1835 5404 1841 5405 1836 5406 1841 5407 1840 5408 1808 5409 1810 5410 1809 5411 1821 5412 1825 5413 1824 5414 1822 5415 1821 5416 1824 5417 1837 5418 1836 5419 1840 5420 1837 5421 1840 5422 1839 5423 1823 5424 1822 5425 1824 5426 1838 5427 1837 5428 1839 5429 1877 5430 1876 5431 1875 5432 1878 5433 1877 5434 1875 5435 1878 5436 1875 5437 1874 5438 1879 5439 1878 5440 1874 5441 1879 5442 1874 5443 1873 5444 1880 5445 1879 5446 1873 5447 1880 5448 1873 5449 1872 5450 1881 5451 1880 5452 1872 5453 1881 5454 1872 5455 1871 5456 1882 5457 1881 5458 1871 5459 1882 5460 1871 5461 1870 5462 1883 5463 1882 5464 1870 5465 1883 5466 1870 5467 1893 5468 1884 5469 1883 5470 1893 5471 1884 5472 1893 5473 1892 5474 1885 5475 1884 5476 1892 5477 1885 5478 1892 5479 1891 5480 1886 5481 1885 5482 1891 5483 1886 5484 1891 5485 1890 5486 1887 5487 1886 5488 1890 5489 1887 5490 1890 5491 1889 5492 1888 5493 1887 5494 1889 5495 1868 5496 1867 5497 1866 5498 1868 5499 1866 5500 1869 5501 1914 5502 1913 5503 1912 5504 1915 5505 1914 5506 1912 5507 1915 5508 1912 5509 1911 5510 1916 5511 1915 5512 1911 5513 1917 5514 1916 5515 1911 5516 1917 5517 1911 5518 1910 5519 1918 5520 1917 5521 1910 5522 1918 5523 1910 5524 1909 5525 1919 5526 1918 5527 1909 5528 1920 5529 1919 5530 1921 5531 1921 5532 1919 5533 1922 5534 1922 5535 1919 5536 1923 5537 1923 5538 1919 5539 1924 5540 1924 5541 1919 5542 1925 5543 1925 5544 1919 5545 1926 5546 1926 5547 1919 5548 1909 5549 1926 5550 1909 5551 1927 5552 1927 5553 1909 5554 1908 5555 1928 5556 1927 5557 1908 5558 1929 5559 1928 5560 1908 5561 1929 5562 1908 5563 1907 5564 1930 5565 1929 5566 1907 5567 1931 5568 1930 5569 1907 5570 1932 5571 1931 5572 1907 5573 1932 5574 1907 5575 1906 5576 1933 5577 1932 5578 1906 5579 1934 5580 1933 5581 1983 5582 1983 5583 1933 5584 1906 5585 1935 5586 1934 5587 1983 5588 1936 5589 1935 5590 1983 5591 1936 5592 1983 5593 1982 5594 1965 5595 1983 5596 1906 5597 1937 5598 1936 5599 1982 5600 1937 5601 1982 5602 1981 5603 1938 5604 1937 5605 1981 5606 1938 5607 1981 5608 1980 5609 1938 5610 1980 5611 1979 5612 1939 5613 1938 5614 1979 5615 1939 5616 1979 5617 1978 5618 1939 5619 1978 5620 1977 5621 1940 5622 1939 5623 1977 5624 1940 5625 1977 5626 1976 5627 1941 5628 1940 5629 1976 5630 1941 5631 1976 5632 1975 5633 1966 5634 1965 5635 1906 5636 1941 5637 1975 5638 1974 5639 1967 5640 1966 5641 1906 5642 1895 5643 1894 5644 1964 5645 1967 5646 1906 5647 1905 5648 1896 5649 1895 5650 1964 5651 1942 5652 1941 5653 1974 5654 1942 5655 1974 5656 1973 5657 1967 5658 1905 5659 1904 5660 1968 5661 1967 5662 1904 5663 1897 5664 1896 5665 1964 5666 1968 5667 1904 5668 1903 5669 1969 5670 1968 5671 1903 5672 1898 5673 1897 5674 1964 5675 1942 5676 1973 5677 1972 5678 1969 5679 1903 5680 1902 5681 1899 5682 1898 5683 1964 5684 1970 5685 1969 5686 1902 5687 1970 5688 1902 5689 1901 5690 1900 5691 1899 5692 1964 5693 1970 5694 1901 5695 1900 5696 1942 5697 1972 5698 1971 5699 1970 5700 1900 5701 1964 5702 1971 5703 1970 5704 1964 5705 1942 5706 1971 5707 1952 5708 1952 5709 1971 5710 1964 5711 1943 5712 1942 5713 1952 5714 1943 5715 1952 5716 1951 5717 1953 5718 1952 5719 1964 5720 1953 5721 1964 5722 1963 5723 1944 5724 1943 5725 1951 5726 1944 5727 1951 5728 1950 5729 1954 5730 1953 5731 1963 5732 1954 5733 1963 5734 1962 5735 1944 5736 1950 5737 1949 5738 1955 5739 1954 5740 1962 5741 1945 5742 1944 5743 1949 5744 1955 5745 1962 5746 1961 5747 1945 5748 1949 5749 1948 5750 1956 5751 1955 5752 1961 5753 1956 5754 1961 5755 1960 5756 1945 5757 1948 5758 1947 5759 1957 5760 1956 5761 1960 5762 1946 5763 1945 5764 1947 5765 1957 5766 1960 5767 1959 5768 1958 5769 1957 5770 1959 5771 2004 5772 2003 5773 2002 5774 2004 5775 2002 5776 2001 5777 2005 5778 2004 5779 2001 5780 2005 5781 2001 5782 2000 5783 2006 5784 2005 5785 2000 5786 2006 5787 2000 5788 2028 5789 2028 5790 2000 5791 2029 5792 2029 5793 2000 5794 1999 5795 2007 5796 2006 5797 2027 5798 2027 5799 2006 5800 2028 5801 2007 5802 2027 5803 2026 5804 2030 5805 2029 5806 1999 5807 2007 5808 2026 5809 2025 5810 2031 5811 2030 5812 1999 5813 2007 5814 2025 5815 2024 5816 2032 5817 2031 5818 1999 5819 2008 5820 2007 5821 2024 5822 2032 5823 1999 5824 1998 5825 2008 5826 2024 5827 2023 5828 2033 5829 2032 5830 1998 5831 2008 5832 2023 5833 2022 5834 2034 5835 2033 5836 1998 5837 2009 5838 2008 5839 2022 5840 2034 5841 1998 5842 1997 5843 2009 5844 2022 5845 2034 5846 2009 5847 2034 5848 1997 5849 2010 5850 2009 5851 1996 5852 1996 5853 2009 5854 1997 5855 2010 5856 1996 5857 1995 5858 2010 5859 1995 5860 1994 5861 2011 5862 2010 5863 1994 5864 2011 5865 1994 5866 1993 5867 1985 5868 1984 5869 2021 5870 1986 5871 1985 5872 2021 5873 2012 5874 2011 5875 1993 5876 2012 5877 1993 5878 1992 5879 1987 5880 1986 5881 2021 5882 2012 5883 1992 5884 1991 5885 1988 5886 1987 5887 2021 5888 1989 5889 1988 5890 2021 5891 2012 5892 1991 5893 1990 5894 1990 5895 1989 5896 2021 5897 2012 5898 1990 5899 2021 5900 2013 5901 2012 5902 2021 5903 2013 5904 2021 5905 2020 5906 2013 5907 2020 5908 2019 5909 2014 5910 2013 5911 2019 5912 2014 5913 2019 5914 2018 5915 2014 5916 2018 5917 2017 5918 2015 5919 2014 5920 2017 5921 2015 5922 2017 5923 2016 5924 2042 5925 2041 5926 2040 5927 2042 5928 2040 5929 2039 5930 2043 5931 2042 5932 2039 5933 2043 5934 2039 5935 2038 5936 2043 5937 2038 5938 2037 5939 2044 5940 2043 5941 2037 5942 2044 5943 2037 5944 2036 5945 2044 5946 2036 5947 2035 5948 2045 5949 2044 5950 2035 5951 2045 5952 2035 5953 2096 5954 2096 5955 2035 5956 2097 5957 2097 5958 2035 5959 2098 5960 2098 5961 2035 5962 2099 5963 2099 5964 2035 5965 2100 5966 2100 5967 2035 5968 2101 5969 2101 5970 2035 5971 2102 5972 2046 5973 2045 5974 2096 5975 2046 5976 2096 5977 2095 5978 2046 5979 2095 5980 2094 5981 2046 5982 2094 5983 2093 5984 2047 5985 2046 5986 2093 5987 2047 5988 2093 5989 2092 5990 2047 5991 2092 5992 2091 5993 2047 5994 2091 5995 2090 5996 2047 5997 2090 5998 2089 5999 2048 6000 2047 6001 2089 6002 2048 6003 2089 6004 2088 6005 2048 6006 2088 6007 2087 6008 2048 6009 2087 6010 2086 6011 2048 6012 2086 6013 2085 6014 2049 6015 2048 6016 2085 6017 2049 6018 2085 6019 2084 6020 2049 6021 2084 6022 2083 6023 2050 6024 2049 6025 2083 6026 2050 6027 2083 6028 2082 6029 2051 6030 2050 6031 2082 6032 2051 6033 2082 6034 2081 6035 2051 6036 2081 6037 2080 6038 2052 6039 2051 6040 2080 6041 2052 6042 2080 6043 2079 6044 2053 6045 2052 6046 2079 6047 2053 6048 2079 6049 2078 6050 2066 6051 2065 6052 2064 6053 2053 6054 2078 6055 2077 6056 2054 6057 2053 6058 2077 6059 2066 6060 2064 6061 2063 6062 2055 6063 2054 6064 2077 6065 2066 6066 2063 6067 2062 6068 2056 6069 2055 6070 2077 6071 2056 6072 2077 6073 2076 6074 2066 6075 2062 6076 2061 6077 2057 6078 2056 6079 2076 6080 2058 6081 2057 6082 2076 6083 2066 6084 2061 6085 2060 6086 2059 6087 2058 6088 2076 6089 2066 6090 2060 6091 2059 6092 2066 6093 2059 6094 2076 6095 2066 6096 2076 6097 2075 6098 2067 6099 2066 6100 2075 6101 2067 6102 2075 6103 2074 6104 2068 6105 2067 6106 2074 6107 2069 6108 2068 6109 2074 6110 2069 6111 2074 6112 2073 6113 2070 6114 2069 6115 2073 6116 2070 6117 2073 6118 2072 6119 2071 6120 2070 6121 2072 6122 2121 6123 2120 6124 2119 6125 2121 6126 2119 6127 2118 6128 2106 6129 2105 6130 2104 6131 2106 6132 2104 6133 2103 6134 2122 6135 2121 6136 2118 6137 2122 6138 2118 6139 2117 6140 2122 6141 2117 6142 2116 6143 2107 6144 2106 6145 2103 6146 2123 6147 2122 6148 2116 6149 2123 6150 2116 6151 2115 6152 2108 6153 2107 6154 2103 6155 2109 6156 2108 6157 2133 6158 2133 6159 2108 6160 2103 6161 2123 6162 2115 6163 2114 6164 2110 6165 2109 6166 2133 6167 2123 6168 2114 6169 2113 6170 2124 6171 2123 6172 2113 6173 2111 6174 2110 6175 2133 6176 2124 6177 2113 6178 2112 6179 2112 6180 2111 6181 2133 6182 2124 6183 2112 6184 2133 6185 2124 6186 2133 6187 2132 6188 2134 6189 2133 6190 2103 6191 2124 6192 2132 6193 2131 6194 2125 6195 2124 6196 2131 6197 2125 6198 2131 6199 2130 6200 2126 6201 2125 6202 2130 6203 2126 6204 2130 6205 2129 6206 2126 6207 2129 6208 2128 6209 2127 6210 2126 6211 2128 6212 2136 6213 2135 6214 2158 6215 2136 6216 2158 6217 2157 6218 2137 6219 2136 6220 2157 6221 2137 6222 2157 6223 2156 6224 2138 6225 2137 6226 2156 6227 2138 6228 2156 6229 2159 6230 2159 6231 2156 6232 2160 6233 2160 6234 2156 6235 2155 6236 2139 6237 2138 6238 2182 6239 2182 6240 2138 6241 2159 6242 2139 6243 2182 6244 2181 6245 2161 6246 2160 6247 2155 6248 2139 6249 2181 6250 2180 6251 2162 6252 2161 6253 2155 6254 2162 6255 2155 6256 2154 6257 2140 6258 2139 6259 2180 6260 2140 6261 2180 6262 2179 6263 2163 6264 2162 6265 2154 6266 2140 6267 2179 6268 2178 6269 2164 6270 2163 6271 2154 6272 2164 6273 2154 6274 2153 6275 2141 6276 2140 6277 2178 6278 2141 6279 2178 6280 2177 6281 2165 6282 2164 6283 2153 6284 2142 6285 2141 6286 2177 6287 2142 6288 2177 6289 2176 6290 2165 6291 2153 6292 2152 6293 2166 6294 2165 6295 2152 6296 2142 6297 2176 6298 2175 6299 2167 6300 2166 6301 2152 6302 2143 6303 2142 6304 2175 6305 2167 6306 2152 6307 2151 6308 2143 6309 2175 6310 2174 6311 2168 6312 2167 6313 2151 6314 2143 6315 2174 6316 2173 6317 2169 6318 2168 6319 2151 6320 2144 6321 2143 6322 2173 6323 2169 6324 2151 6325 2150 6326 2144 6327 2173 6328 2172 6329 2170 6330 2169 6331 2150 6332 2144 6333 2172 6334 2171 6335 2171 6336 2170 6337 2150 6338 2144 6339 2171 6340 2150 6341 2145 6342 2144 6343 2150 6344 2145 6345 2150 6346 2149 6347 2146 6348 2145 6349 2149 6350 2146 6351 2149 6352 2148 6353 2147 6354 2146 6355 2148 6356 2188 6357 2187 6358 2186 6359 2188 6360 2186 6361 2190 6362 2190 6363 2186 6364 2191 6365 2191 6366 2186 6367 2185 6368 2185 6369 2184 6370 2183 6371 2185 6372 2183 6373 2194 6374 2194 6375 2183 6376 2195 6377 2195 6378 2183 6379 2197 6380 2188 6381 2190 6382 2189 6383 2192 6384 2191 6385 2185 6386 2185 6387 2194 6388 2193 6389 2196 6390 2195 6391 2197 6392 2192 6393 2185 6394 2193 6395 2199 6396 2198 6397 2231 6398 2199 6399 2231 6400 2230 6401 2199 6402 2230 6403 2229 6404 2200 6405 2199 6406 2229 6407 2201 6408 2200 6409 2229 6410 2202 6411 2201 6412 2228 6413 2228 6414 2201 6415 2229 6416 2202 6417 2228 6418 2227 6419 2202 6420 2227 6421 2226 6422 2203 6423 2202 6424 2226 6425 2203 6426 2226 6427 2225 6428 2216 6429 2215 6430 2214 6431 2203 6432 2225 6433 2224 6434 2217 6435 2216 6436 2214 6437 2204 6438 2203 6439 2224 6440 2218 6441 2217 6442 2214 6443 2204 6444 2224 6445 2223 6446 2219 6447 2218 6448 2214 6449 2204 6450 2223 6451 2222 6452 2220 6453 2219 6454 2214 6455 2204 6456 2222 6457 2221 6458 2221 6459 2220 6460 2214 6461 2204 6462 2221 6463 2214 6464 2205 6465 2204 6466 2214 6467 2206 6468 2205 6469 2214 6470 2206 6471 2214 6472 2213 6473 2206 6474 2213 6475 2212 6476 2207 6477 2206 6478 2212 6479 2207 6480 2212 6481 2211 6482 2207 6483 2211 6484 2210 6485 2208 6486 2207 6487 2210 6488 2208 6489 2210 6490 2209 6491 2239 6492 2238 6493 2237 6494 2239 6495 2237 6496 2236 6497 2240 6498 2239 6499 2236 6500 2240 6501 2236 6502 2235 6503 2240 6504 2235 6505 2234 6506 2241 6507 2240 6508 2234 6509 2241 6510 2234 6511 2233 6512 2241 6513 2233 6514 2232 6515 2242 6516 2241 6517 2232 6518 2242 6519 2232 6520 2293 6521 2293 6522 2232 6523 2294 6524 2294 6525 2232 6526 2295 6527 2295 6528 2232 6529 2296 6530 2296 6531 2232 6532 2297 6533 2297 6534 2232 6535 2298 6536 2298 6537 2232 6538 2299 6539 2243 6540 2242 6541 2293 6542 2243 6543 2293 6544 2292 6545 2243 6546 2292 6547 2291 6548 2243 6549 2291 6550 2290 6551 2244 6552 2243 6553 2290 6554 2244 6555 2290 6556 2289 6557 2244 6558 2289 6559 2288 6560 2244 6561 2288 6562 2287 6563 2244 6564 2287 6565 2286 6566 2245 6567 2244 6568 2286 6569 2245 6570 2286 6571 2285 6572 2245 6573 2285 6574 2284 6575 2245 6576 2284 6577 2283 6578 2245 6579 2283 6580 2282 6581 2246 6582 2245 6583 2282 6584 2246 6585 2282 6586 2281 6587 2246 6588 2281 6589 2280 6590 2247 6591 2246 6592 2280 6593 2247 6594 2280 6595 2279 6596 2248 6597 2247 6598 2279 6599 2248 6600 2279 6601 2278 6602 2248 6603 2278 6604 2277 6605 2249 6606 2248 6607 2277 6608 2249 6609 2277 6610 2276 6611 2250 6612 2249 6613 2276 6614 2250 6615 2276 6616 2275 6617 2263 6618 2262 6619 2261 6620 2250 6621 2275 6622 2274 6623 2251 6624 2250 6625 2274 6626 2263 6627 2261 6628 2260 6629 2252 6630 2251 6631 2274 6632 2263 6633 2260 6634 2259 6635 2253 6636 2252 6637 2274 6638 2253 6639 2274 6640 2273 6641 2263 6642 2259 6643 2258 6644 2254 6645 2253 6646 2273 6647 2255 6648 2254 6649 2273 6650 2263 6651 2258 6652 2257 6653 2256 6654 2255 6655 2273 6656 2263 6657 2257 6658 2256 6659 2263 6660 2256 6661 2273 6662 2263 6663 2273 6664 2272 6665 2264 6666 2263 6667 2272 6668 2264 6669 2272 6670 2271 6671 2265 6672 2264 6673 2271 6674 2266 6675 2265 6676 2271 6677 2266 6678 2271 6679 2270 6680 2267 6681 2266 6682 2270 6683 2267 6684 2270 6685 2269 6686 2268 6687 2267 6688 2269 6689 2320 6690 2319 6691 2318 6692 2320 6693 2318 6694 2317 6695 2321 6696 2320 6697 2317 6698 2321 6699 2317 6700 2316 6701 2322 6702 2321 6703 2316 6704 2322 6705 2316 6706 2344 6707 2344 6708 2316 6709 2345 6710 2345 6711 2316 6712 2315 6713 2323 6714 2322 6715 2343 6716 2343 6717 2322 6718 2344 6719 2323 6720 2343 6721 2342 6722 2346 6723 2345 6724 2315 6725 2323 6726 2342 6727 2341 6728 2347 6729 2346 6730 2315 6731 2323 6732 2341 6733 2340 6734 2348 6735 2347 6736 2315 6737 2324 6738 2323 6739 2340 6740 2348 6741 2315 6742 2314 6743 2324 6744 2340 6745 2339 6746 2349 6747 2348 6748 2314 6749 2324 6750 2339 6751 2338 6752 2350 6753 2349 6754 2314 6755 2325 6756 2324 6757 2338 6758 2350 6759 2314 6760 2313 6761 2325 6762 2338 6763 2350 6764 2325 6765 2350 6766 2313 6767 2326 6768 2325 6769 2312 6770 2312 6771 2325 6772 2313 6773 2326 6774 2312 6775 2311 6776 2326 6777 2311 6778 2310 6779 2327 6780 2326 6781 2310 6782 2327 6783 2310 6784 2309 6785 2301 6786 2300 6787 2337 6788 2302 6789 2301 6790 2337 6791 2328 6792 2327 6793 2309 6794 2328 6795 2309 6796 2308 6797 2303 6798 2302 6799 2337 6800 2328 6801 2308 6802 2307 6803 2304 6804 2303 6805 2337 6806 2305 6807 2304 6808 2337 6809 2328 6810 2307 6811 2306 6812 2306 6813 2305 6814 2337 6815 2328 6816 2306 6817 2337 6818 2329 6819 2328 6820 2337 6821 2329 6822 2337 6823 2336 6824 2329 6825 2336 6826 2335 6827 2330 6828 2329 6829 2335 6830 2330 6831 2335 6832 2334 6833 2330 6834 2334 6835 2333 6836 2331 6837 2330 6838 2333 6839 2331 6840 2333 6841 2332 6842 2353 6843 2352 6844 2351 6845 2353 6846 2351 6847 2358 6848 2354 6849 2353 6850 2358 6851 2355 6852 2354 6853 2357 6854 2357 6855 2354 6856 2358 6857 2355 6858 2357 6859 2356 6860 2366 6861 2365 6862 2364 6863 2366 6864 2364 6865 2363 6866 2367 6867 2366 6868 2363 6869 2367 6870 2363 6871 2362 6872 2367 6873 2362 6874 2361 6875 2368 6876 2367 6877 2361 6878 2368 6879 2361 6880 2360 6881 2368 6882 2360 6883 2359 6884 2369 6885 2368 6886 2359 6887 2369 6888 2359 6889 2420 6890 2420 6891 2359 6892 2421 6893 2421 6894 2359 6895 2422 6896 2422 6897 2359 6898 2423 6899 2423 6900 2359 6901 2424 6902 2424 6903 2359 6904 2425 6905 2425 6906 2359 6907 2426 6908 2370 6909 2369 6910 2420 6911 2370 6912 2420 6913 2419 6914 2370 6915 2419 6916 2418 6917 2370 6918 2418 6919 2417 6920 2371 6921 2370 6922 2417 6923 2371 6924 2417 6925 2416 6926 2371 6927 2416 6928 2415 6929 2371 6930 2415 6931 2414 6932 2371 6933 2414 6934 2413 6935 2372 6936 2371 6937 2413 6938 2372 6939 2413 6940 2412 6941 2372 6942 2412 6943 2411 6944 2372 6945 2411 6946 2410 6947 2372 6948 2410 6949 2409 6950 2373 6951 2372 6952 2409 6953 2373 6954 2409 6955 2408 6956 2373 6957 2408 6958 2407 6959 2374 6960 2373 6961 2407 6962 2374 6963 2407 6964 2406 6965 2375 6966 2374 6967 2406 6968 2375 6969 2406 6970 2405 6971 2375 6972 2405 6973 2404 6974 2376 6975 2375 6976 2404 6977 2376 6978 2404 6979 2403 6980 2377 6981 2376 6982 2403 6983 2377 6984 2403 6985 2402 6986 2390 6987 2389 6988 2388 6989 2377 6990 2402 6991 2401 6992 2378 6993 2377 6994 2401 6995 2390 6996 2388 6997 2387 6998 2379 6999 2378 7000 2401 7001 2390 7002 2387 7003 2386 7004 2380 7005 2379 7006 2401 7007 2380 7008 2401 7009 2400 7010 2390 7011 2386 7012 2385 7013 2381 7014 2380 7015 2400 7016 2382 7017 2381 7018 2400 7019 2390 7020 2385 7021 2384 7022 2383 7023 2382 7024 2400 7025 2390 7026 2384 7027 2383 7028 2390 7029 2383 7030 2400 7031 2390 7032 2400 7033 2399 7034 2391 7035 2390 7036 2399 7037 2391 7038 2399 7039 2398 7040 2392 7041 2391 7042 2398 7043 2393 7044 2392 7045 2398 7046 2393 7047 2398 7048 2397 7049 2394 7050 2393 7051 2397 7052 2394 7053 2397 7054 2396 7055 2395 7056 2394 7057 2396 7058 2434 7059 2433 7060 2432 7061 2434 7062 2432 7063 2431 7064 2434 7065 2431 7066 2430 7067 2435 7068 2434 7069 2430 7070 2435 7071 2430 7072 2429 7073 2435 7074 2429 7075 2428 7076 2435 7077 2428 7078 2427 7079 2436 7080 2435 7081 2427 7082 2436 7083 2427 7084 2470 7085 2470 7086 2427 7087 2471 7088 2471 7089 2427 7090 2472 7091 2472 7092 2427 7093 2473 7094 2473 7095 2427 7096 2474 7097 2474 7098 2427 7099 2475 7100 2475 7101 2427 7102 2476 7103 2437 7104 2436 7105 2469 7106 2469 7107 2436 7108 2470 7109 2437 7110 2469 7111 2468 7112 2437 7113 2468 7114 2467 7115 2438 7116 2437 7117 2467 7118 2438 7119 2467 7120 2466 7121 2438 7122 2466 7123 2465 7124 2439 7125 2438 7126 2465 7127 2439 7128 2465 7129 2464 7130 2439 7131 2464 7132 2463 7133 2440 7134 2439 7135 2463 7136 2440 7137 2463 7138 2462 7139 2441 7140 2440 7141 2462 7142 2441 7143 2462 7144 2461 7145 2441 7146 2461 7147 2460 7148 2453 7149 2452 7150 2451 7151 2442 7152 2441 7153 2460 7154 2454 7155 2453 7156 2451 7157 2442 7158 2460 7159 2459 7160 2455 7161 2454 7162 2451 7163 2456 7164 2455 7165 2451 7166 2442 7167 2459 7168 2458 7169 2457 7170 2456 7171 2451 7172 2458 7173 2457 7174 2451 7175 2442 7176 2458 7177 2451 7178 2443 7179 2442 7180 2451 7181 2444 7182 2443 7183 2451 7184 2444 7185 2451 7186 2450 7187 2444 7188 2450 7189 2449 7190 2444 7191 2449 7192 2448 7193 2444 7194 2448 7195 2447 7196 2445 7197 2444 7198 2447 7199 2445 7200 2447 7201 2446 7202 2488 7203 2487 7204 2486 7205 2489 7206 2488 7207 2486 7208 2489 7209 2486 7210 2485 7211 2490 7212 2489 7213 2485 7214 2490 7215 2485 7216 2484 7217 2491 7218 2490 7219 2484 7220 2491 7221 2484 7222 2483 7223 2492 7224 2491 7225 2483 7226 2492 7227 2483 7228 2482 7229 2493 7230 2492 7231 2482 7232 2493 7233 2482 7234 2481 7235 2494 7236 2493 7237 2481 7238 2494 7239 2481 7240 2504 7241 2494 7242 2504 7243 2503 7244 2495 7245 2494 7246 2503 7247 2495 7248 2503 7249 2502 7250 2496 7251 2495 7252 2502 7253 2496 7254 2502 7255 2501 7256 2497 7257 2496 7258 2501 7259 2497 7260 2501 7261 2500 7262 2498 7263 2497 7264 2500 7265 2498 7266 2500 7267 2499 7268 2479 7269 2478 7270 2477 7271 2479 7272 2477 7273 2480 7274 2512 7275 2511 7276 2510 7277 2512 7278 2510 7279 2509 7280 2513 7281 2512 7282 2509 7283 2513 7284 2509 7285 2508 7286 2513 7287 2508 7288 2507 7289 2514 7290 2513 7291 2507 7292 2514 7293 2507 7294 2506 7295 2514 7296 2506 7297 2505 7298 2515 7299 2514 7300 2505 7301 2515 7302 2505 7303 2566 7304 2566 7305 2505 7306 2567 7307 2567 7308 2505 7309 2568 7310 2568 7311 2505 7312 2569 7313 2569 7314 2505 7315 2570 7316 2570 7317 2505 7318 2571 7319 2571 7320 2505 7321 2572 7322 2516 7323 2515 7324 2566 7325 2516 7326 2566 7327 2565 7328 2516 7329 2565 7330 2564 7331 2516 7332 2564 7333 2563 7334 2517 7335 2516 7336 2563 7337 2517 7338 2563 7339 2562 7340 2517 7341 2562 7342 2561 7343 2517 7344 2561 7345 2560 7346 2517 7347 2560 7348 2559 7349 2518 7350 2517 7351 2559 7352 2518 7353 2559 7354 2558 7355 2518 7356 2558 7357 2557 7358 2518 7359 2557 7360 2556 7361 2518 7362 2556 7363 2555 7364 2519 7365 2518 7366 2555 7367 2519 7368 2555 7369 2554 7370 2519 7371 2554 7372 2553 7373 2520 7374 2519 7375 2553 7376 2520 7377 2553 7378 2552 7379 2521 7380 2520 7381 2552 7382 2521 7383 2552 7384 2551 7385 2521 7386 2551 7387 2550 7388 2522 7389 2521 7390 2550 7391 2522 7392 2550 7393 2549 7394 2523 7395 2522 7396 2549 7397 2523 7398 2549 7399 2548 7400 2536 7401 2535 7402 2534 7403 2523 7404 2548 7405 2547 7406 2524 7407 2523 7408 2547 7409 2536 7410 2534 7411 2533 7412 2525 7413 2524 7414 2547 7415 2536 7416 2533 7417 2532 7418 2526 7419 2525 7420 2547 7421 2526 7422 2547 7423 2546 7424 2536 7425 2532 7426 2531 7427 2527 7428 2526 7429 2546 7430 2528 7431 2527 7432 2546 7433 2536 7434 2531 7435 2530 7436 2529 7437 2528 7438 2546 7439 2536 7440 2530 7441 2529 7442 2536 7443 2529 7444 2546 7445 2536 7446 2546 7447 2545 7448 2537 7449 2536 7450 2545 7451 2537 7452 2545 7453 2544 7454 2538 7455 2537 7456 2544 7457 2539 7458 2538 7459 2544 7460 2539 7461 2544 7462 2543 7463 2540 7464 2539 7465 2543 7466 2540 7467 2543 7468 2542 7469 2541 7470 2540 7471 2542 7472 2578 7473 2577 7474 2576 7475 2578 7476 2576 7477 2575 7478 2575 7479 2574 7480 2573 7481 2575 7482 2573 7483 2580 7484 2578 7485 2575 7486 2580 7487 2579 7488 2578 7489 2580 7490 2583 7491 2582 7492 2581 7493 2583 7494 2581 7495 2613 7496 2607 7497 2606 7498 2605 7499 2608 7500 2607 7501 2605 7502 2608 7503 2605 7504 2604 7505 2609 7506 2608 7507 2604 7508 2610 7509 2609 7510 2604 7511 2610 7512 2604 7513 2603 7514 2611 7515 2610 7516 2603 7517 2611 7518 2603 7519 2602 7520 2612 7521 2611 7522 2591 7523 2591 7524 2611 7525 2602 7526 2583 7527 2613 7528 2612 7529 2583 7530 2612 7531 2585 7532 2585 7533 2612 7534 2586 7535 2586 7536 2612 7537 2587 7538 2587 7539 2612 7540 2588 7541 2588 7542 2612 7543 2589 7544 2589 7545 2612 7546 2590 7547 2590 7548 2612 7549 2591 7550 2592 7551 2591 7552 2602 7553 2593 7554 2592 7555 2602 7556 2593 7557 2602 7558 2601 7559 2594 7560 2593 7561 2601 7562 2595 7563 2594 7564 2601 7565 2596 7566 2595 7567 2601 7568 2596 7569 2601 7570 2600 7571 2583 7572 2585 7573 2584 7574 2597 7575 2596 7576 2600 7577 2598 7578 2597 7579 2600 7580 2598 7581 2600 7582 2599 7583 2615 7584 2614 7585 2631 7586 2631 7587 2614 7588 2630 7589 2631 7590 2630 7591 2629 7592 2631 7593 2629 7594 2628 7595 2631 7596 2628 7597 2627 7598 2631 7599 2627 7600 2632 7601 2632 7602 2627 7603 2626 7604 2615 7605 2631 7606 2645 7607 2633 7608 2632 7609 2626 7610 2634 7611 2633 7612 2626 7613 2634 7614 2626 7615 2625 7616 2635 7617 2634 7618 2625 7619 2636 7620 2635 7621 2625 7622 2637 7623 2636 7624 2625 7625 2637 7626 2625 7627 2624 7628 2638 7629 2637 7630 2624 7631 2639 7632 2638 7633 2624 7634 2639 7635 2624 7636 2623 7637 2640 7638 2639 7639 2623 7640 2640 7641 2623 7642 2622 7643 2641 7644 2640 7645 2622 7646 2642 7647 2641 7648 2622 7649 2643 7650 2642 7651 2622 7652 2643 7653 2622 7654 2621 7655 2644 7656 2643 7657 2621 7658 2615 7659 2645 7660 2617 7661 2617 7662 2645 7663 2644 7664 2617 7665 2644 7666 2621 7667 2617 7668 2621 7669 2620 7670 2617 7671 2620 7672 2619 7673 2617 7674 2619 7675 2618 7676 2615 7677 2617 7678 2616 7679 2647 7680 2646 7681 2679 7682 2647 7683 2679 7684 2678 7685 2647 7686 2678 7687 2677 7688 2648 7689 2647 7690 2677 7691 2649 7692 2648 7693 2677 7694 2650 7695 2649 7696 2676 7697 2676 7698 2649 7699 2677 7700 2650 7701 2676 7702 2675 7703 2650 7704 2675 7705 2674 7706 2651 7707 2650 7708 2674 7709 2651 7710 2674 7711 2673 7712 2664 7713 2663 7714 2662 7715 2651 7716 2673 7717 2672 7718 2665 7719 2664 7720 2662 7721 2652 7722 2651 7723 2672 7724 2666 7725 2665 7726 2662 7727 2652 7728 2672 7729 2671 7730 2667 7731 2666 7732 2662 7733 2652 7734 2671 7735 2670 7736 2668 7737 2667 7738 2662 7739 2652 7740 2670 7741 2669 7742 2669 7743 2668 7744 2662 7745 2652 7746 2669 7747 2662 7748 2653 7749 2652 7750 2662 7751 2654 7752 2653 7753 2662 7754 2654 7755 2662 7756 2661 7757 2654 7758 2661 7759 2660 7760 2655 7761 2654 7762 2660 7763 2655 7764 2660 7765 2659 7766 2655 7767 2659 7768 2658 7769 2656 7770 2655 7771 2658 7772 2656 7773 2658 7774 2657 7775 2700 7776 2699 7777 2698 7778 2700 7779 2698 7780 2697 7781 2701 7782 2700 7783 2697 7784 2701 7785 2697 7786 2696 7787 2702 7788 2701 7789 2696 7790 2702 7791 2696 7792 2724 7793 2724 7794 2696 7795 2725 7796 2725 7797 2696 7798 2695 7799 2703 7800 2702 7801 2723 7802 2723 7803 2702 7804 2724 7805 2703 7806 2723 7807 2722 7808 2726 7809 2725 7810 2695 7811 2703 7812 2722 7813 2721 7814 2727 7815 2726 7816 2695 7817 2703 7818 2721 7819 2720 7820 2728 7821 2727 7822 2695 7823 2704 7824 2703 7825 2720 7826 2728 7827 2695 7828 2694 7829 2704 7830 2720 7831 2719 7832 2729 7833 2728 7834 2694 7835 2704 7836 2719 7837 2718 7838 2730 7839 2729 7840 2694 7841 2705 7842 2704 7843 2718 7844 2730 7845 2694 7846 2693 7847 2705 7848 2718 7849 2730 7850 2705 7851 2730 7852 2693 7853 2706 7854 2705 7855 2692 7856 2692 7857 2705 7858 2693 7859 2706 7860 2692 7861 2691 7862 2706 7863 2691 7864 2690 7865 2707 7866 2706 7867 2690 7868 2707 7869 2690 7870 2689 7871 2681 7872 2680 7873 2717 7874 2682 7875 2681 7876 2717 7877 2708 7878 2707 7879 2689 7880 2708 7881 2689 7882 2688 7883 2683 7884 2682 7885 2717 7886 2708 7887 2688 7888 2687 7889 2684 7890 2683 7891 2717 7892 2685 7893 2684 7894 2717 7895 2708 7896 2687 7897 2686 7898 2686 7899 2685 7900 2717 7901 2708 7902 2686 7903 2717 7904 2709 7905 2708 7906 2717 7907 2709 7908 2717 7909 2716 7910 2709 7911 2716 7912 2715 7913 2710 7914 2709 7915 2715 7916 2710 7917 2715 7918 2714 7919 2710 7920 2714 7921 2713 7922 2711 7923 2710 7924 2713 7925 2711 7926 2713 7927 2712 7928 2733 7929 2732 7930 2731 7931 2733 7932 2731 7933 2734 7934 2737 7935 2736 7936 2735 7937 2737 7938 2735 7939 2738 7940 2757 7941 2756 7942 2755 7943 2757 7944 2755 7945 2754 7946 2742 7947 2741 7948 2740 7949 2742 7950 2740 7951 2739 7952 2758 7953 2757 7954 2754 7955 2758 7956 2754 7957 2753 7958 2758 7959 2753 7960 2752 7961 2743 7962 2742 7963 2739 7964 2759 7965 2758 7966 2752 7967 2759 7968 2752 7969 2751 7970 2744 7971 2743 7972 2739 7973 2745 7974 2744 7975 2769 7976 2769 7977 2744 7978 2739 7979 2759 7980 2751 7981 2750 7982 2746 7983 2745 7984 2769 7985 2759 7986 2750 7987 2749 7988 2760 7989 2759 7990 2749 7991 2747 7992 2746 7993 2769 7994 2760 7995 2749 7996 2748 7997 2748 7998 2747 7999 2769 8000 2760 8001 2748 8002 2769 8003 2760 8004 2769 8005 2768 8006 2770 8007 2769 8008 2739 8009 2760 8010 2768 8011 2767 8012 2761 8013 2760 8014 2767 8015 2761 8016 2767 8017 2766 8018 2762 8019 2761 8020 2766 8021 2762 8022 2766 8023 2765 8024 2762 8025 2765 8026 2764 8027 2763 8028 2762 8029 2764 8030 2771 8031 2798 8032 2799 8033 2799 8034 2798 8035 2797 8036 2799 8037 2797 8038 2796 8039 2799 8040 2796 8041 2795 8042 2799 8043 2795 8044 2794 8045 2799 8046 2794 8047 2800 8048 2800 8049 2794 8050 2793 8051 2771 8052 2799 8053 2813 8054 2801 8055 2800 8056 2793 8057 2801 8058 2793 8059 2792 8060 2802 8061 2801 8062 2792 8063 2803 8064 2802 8065 2792 8066 2804 8067 2803 8068 2792 8069 2804 8070 2792 8071 2791 8072 2805 8073 2804 8074 2791 8075 2806 8076 2805 8077 2791 8078 2806 8079 2791 8080 2790 8081 2807 8082 2806 8083 2790 8084 2807 8085 2790 8086 2789 8087 2808 8088 2807 8089 2789 8090 2808 8091 2789 8092 2788 8093 2809 8094 2808 8095 2788 8096 2809 8097 2788 8098 2787 8099 2810 8100 2809 8101 2787 8102 2811 8103 2810 8104 2787 8105 2811 8106 2787 8107 2786 8108 2812 8109 2811 8110 2786 8111 2771 8112 2813 8113 2814 8114 2814 8115 2813 8116 2812 8117 2814 8118 2812 8119 2786 8120 2814 8121 2786 8122 2785 8123 2814 8124 2785 8125 2784 8126 2814 8127 2784 8128 2783 8129 2814 8130 2783 8131 2782 8132 2814 8133 2782 8134 2815 8135 2815 8136 2782 8137 2781 8138 2771 8139 2814 8140 2828 8141 2816 8142 2815 8143 2781 8144 2817 8145 2816 8146 2781 8147 2817 8148 2781 8149 2780 8150 2818 8151 2817 8152 2780 8153 2819 8154 2818 8155 2780 8156 2819 8157 2780 8158 2779 8159 2820 8160 2819 8161 2779 8162 2820 8163 2779 8164 2778 8165 2821 8166 2820 8167 2778 8168 2822 8169 2821 8170 2778 8171 2822 8172 2778 8173 2777 8174 2823 8175 2822 8176 2777 8177 2824 8178 2823 8179 2777 8180 2824 8181 2777 8182 2776 8183 2825 8184 2824 8185 2776 8186 2826 8187 2825 8188 2776 8189 2826 8190 2776 8191 2775 8192 2827 8193 2826 8194 2775 8195 2771 8196 2828 8197 2827 8198 2771 8199 2827 8200 2775 8201 2771 8202 2775 8203 2774 8204 2771 8205 2774 8206 2773 8207 2771 8208 2773 8209 2772 8210

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 0.0 -0.0 1.0 -0.0 0.0 -1.0 + + + + + + + + + + 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 + + + + + + + + + + + + + + +

    1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

    +
    +
    +
    + + + + 1.19619 0.58226 -1.0 0.41454 -0.7869 -1.0 -1.39461 0.06574 -1.0 -0.80381 0.58226 -1.0 1.19619 0.58226 1.0 0.41454 -0.7869 1.0 -1.39461 0.06574 1.0 -0.80381 0.58226 1.0 + + + + + + + + + + 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 + + + + + + + + + + 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + + + + 1.12341 0.59904 -1.0 0.34176 -0.77012 -1.0 -1.46739 0.08252 -1.0 -0.87659 0.59904 -1.0 1.12341 0.59904 1.0 0.34176 -0.77012 1.0 -1.46739 0.08252 1.0 -0.87659 0.59904 1.0 + + + + + + + + + + 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 + + + + + + + + + + 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + + + + 1.35033 0.45305 -1.0 0.56868 -0.9161 -1.0 -1.24047 -0.06347 -1.0 -0.64967 0.45305 -1.0 1.35033 0.45305 1.0 0.56868 -0.9161 1.0 -1.24047 -0.06347 1.0 -0.64967 0.45305 1.0 + + + + + + + + + + 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 + + + + + + + + + + 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + + + + 0.0 -0.0 -1.41421 1.02332 -0.74348 -0.63246 -0.39087 -1.20299 -0.63246 -1.26491 -0.0 -0.63246 -0.39087 1.20299 -0.63246 1.02332 0.74348 -0.63246 0.39087 -1.20299 0.63246 -1.02332 -0.74348 0.63246 -1.02332 0.74348 0.63246 0.39087 1.20299 0.63246 1.26491 0.0 0.63246 -0.0 0.0 1.41421 0.6015 -0.43701 -1.20301 -0.22975 -0.7071 -1.20301 0.37175 -1.14412 -0.74351 0.6015 0.43701 -1.20301 1.203 -0.0 -0.7435 -0.74349 -0.0 -1.203 -0.97325 -0.7071 -0.7435 -0.22975 0.7071 -1.20301 -0.97325 0.7071 -0.7435 0.37175 1.14412 -0.74351 1.345 0.43701 -0.0 1.345 -0.43701 0.0 0.83125 -1.14412 0.0 -0.0 -1.41421 0.0 -0.83125 -1.14412 0.0 -1.345 -0.43701 0.0 -1.345 0.43701 -0.0 -0.83125 1.14412 -0.0 0.0 1.41421 -0.0 0.83125 1.14412 -0.0 0.97325 -0.7071 0.7435 -0.37175 -1.14412 0.74351 -1.203 0.0 0.7435 -0.37175 1.14412 0.74351 0.97325 0.7071 0.7435 0.74349 0.0 1.203 0.22975 -0.7071 1.20301 -0.6015 -0.43701 1.20301 -0.6015 0.43701 1.20301 0.22975 0.7071 1.20301 + + + + + + + + + + 0.0 0.0 -1.0 0.72359 -0.52571 -0.44719 -0.27638 -0.85064 -0.44719 -0.89441 0.0 -0.44719 -0.27638 0.85064 -0.44719 0.72359 0.52571 -0.44719 0.27638 -0.85064 0.44722 -0.72359 -0.52571 0.44719 -0.72359 0.52571 0.44719 0.27638 0.85064 0.44719 0.89441 0.0 0.44719 0.0 0.0 1.0 0.42531 -0.309 -0.85064 -0.16245 -0.49998 -0.85064 0.26286 -0.80898 -0.52571 0.42531 0.309 -0.85064 0.85064 0.0 -0.52571 -0.52571 0.0 -0.85064 -0.68816 -0.49998 -0.52571 -0.16245 0.49998 -0.85064 -0.68816 0.49998 -0.52571 0.26286 0.80898 -0.52571 0.95105 0.309 0.0 0.95105 -0.309 0.0 0.58776 -0.80902 0.0 0.0 -1.0 0.0 -0.58776 -0.80902 0.0 -0.95105 -0.309 0.0 -0.95105 0.309 0.0 -0.58776 0.80902 0.0 0.0 1.0 0.0 0.58776 0.80902 0.0 0.68816 -0.49998 0.52571 -0.26286 -0.80898 0.52571 -0.85064 0.0 0.52571 -0.26286 0.80898 0.52571 0.68816 0.49998 0.52571 0.52571 0.0 0.85064 0.16245 -0.49998 0.85064 -0.42531 -0.309 0.85064 -0.42531 0.309 0.85064 0.16245 0.49998 0.85064 + + + + + + + + + + 0.75311 0.11158 0.95018 0.21117 0.82689 0.27054 0.95018 0.21117 0.75311 0.11158 1.14943 0.09989 0.46246 0.11286 1.14943 0.09989 0.75311 0.11158 1.14943 0.09989 1.07744 0.2618 0.95018 0.21117 0.90005 0.39508 0.82689 0.27054 0.95018 0.21117 0.95018 0.21117 1.00617 0.39104 0.90005 0.39508 0.95447 0.53487 0.90005 0.39508 1.00617 0.39104 0.95018 0.21117 1.07744 0.2618 1.00617 0.39104 0.32261 0.22952 0.14943 0.09989 0.46246 0.11286 0.14943 0.09989 0.32261 0.22952 0.19133 0.29524 0.27674 0.38955 0.19133 0.29524 0.32261 0.22952 0.19133 0.29524 0.07744 0.2618 0.14943 0.09989 0.20413 0.49383 0.19133 0.29524 0.27674 0.38955 0.19133 0.29524 0.20413 0.49383 0.10855 0.42958 0.13244 0.59936 0.10855 0.42958 0.20413 0.49383 0.10855 0.42958 0.07744 0.2618 0.19133 0.29524 0.04129 0.57872 0.10855 0.42958 0.13244 0.59936 0.10855 0.42958 0.04129 0.57872 0.00617 0.39104 0.95447 0.53487 1.00617 0.39104 1.04129 0.57872 0.00617 0.39104 0.07744 0.2618 0.10855 0.42958 0.79899 0.43978 0.82689 0.27054 0.90005 0.39508 0.90005 0.39508 0.86836 0.58509 0.79899 0.43978 0.77674 0.61045 0.79899 0.43978 0.86836 0.58509 0.86836 0.58509 0.90005 0.39508 0.95447 0.53487 0.59019 0.23871 0.46246 0.11286 0.75311 0.11158 0.75311 0.11158 0.71658 0.30753 0.59019 0.23871 0.63244 0.40064 0.59019 0.23871 0.71658 0.30753 0.71658 0.30753 0.75311 0.11158 0.82689 0.27054 0.36836 0.41491 0.27674 0.38955 0.32261 0.22952 0.32261 0.22952 0.45654 0.28896 0.36836 0.41491 0.45447 0.46513 0.36836 0.41491 0.45654 0.28896 0.45654 0.28896 0.32261 0.22952 0.46246 0.11286 0.21658 0.69247 0.13244 0.59936 0.20413 0.49383 0.20413 0.49383 0.29899 0.56022 0.21658 0.69247 0.32689 0.72946 0.21658 0.69247 0.29899 0.56022 0.29899 0.56022 0.20413 0.49383 0.27674 0.38955 0.95654 0.71104 0.95447 0.53487 1.04129 0.57872 1.04129 0.57872 1.09019 0.76129 0.95654 0.71104 0.96246 0.88714 0.95654 0.71104 1.09019 0.76129 0.09019 0.76129 0.04129 0.57872 0.13244 0.59936 0.70413 0.50617 0.79899 0.43978 0.77674 0.61045 0.79899 0.43978 0.70413 0.50617 0.71658 0.30753 0.63244 0.40064 0.71658 0.30753 0.70413 0.50617 0.71658 0.30753 0.82689 0.27054 0.79899 0.43978 0.54129 0.42128 0.59019 0.23871 0.63244 0.40064 0.59019 0.23871 0.54129 0.42128 0.45654 0.28896 0.45447 0.46513 0.45654 0.28896 0.54129 0.42128 0.45654 0.28896 0.46246 0.11286 0.59019 0.23871 0.40005 0.60492 0.36836 0.41491 0.45447 0.46513 0.36836 0.41491 0.40005 0.60492 0.29899 0.56022 0.32689 0.72946 0.29899 0.56022 0.40005 0.60492 0.29899 0.56022 0.27674 0.38955 0.36836 0.41491 0.25311 0.88842 0.21658 0.69247 0.32689 0.72946 0.21658 0.69247 0.25311 0.88842 0.09019 0.76129 0.96246 0.88714 1.09019 0.76129 1.25311 0.88842 0.09019 0.76129 0.13244 0.59936 0.21658 0.69247 0.82261 0.77048 0.95654 0.71104 0.96246 0.88714 0.95654 0.71104 0.82261 0.77048 0.86836 0.58509 0.77674 0.61045 0.86836 0.58509 0.82261 0.77048 0.86836 0.58509 0.95447 0.53487 0.95654 0.71104 0.60855 0.57042 0.63244 0.40064 0.70413 0.50617 0.70413 0.50617 0.69133 0.70476 0.60855 0.57042 0.57744 0.7382 0.60855 0.57042 0.69133 0.70476 0.69133 0.70476 0.70413 0.50617 0.77674 0.61045 0.50617 0.60896 0.45447 0.46513 0.54129 0.42128 0.54129 0.42128 0.60855 0.57042 0.50617 0.60896 0.57744 0.7382 0.50617 0.60896 0.60855 0.57042 0.60855 0.57042 0.54129 0.42128 0.63244 0.40064 0.45018 0.78883 0.32689 0.72946 0.40005 0.60492 0.40005 0.60492 0.50617 0.60896 0.45018 0.78883 0.57744 0.7382 0.45018 0.78883 0.50617 0.60896 0.50617 0.60896 0.40005 0.60492 0.45447 0.46513 0.64943 0.90011 0.96246 0.88714 1.25311 0.88842 0.25311 0.88842 0.45018 0.78883 0.64943 0.90011 0.57744 0.7382 0.64943 0.90011 0.45018 0.78883 0.45018 0.78883 0.25311 0.88842 0.32689 0.72946 0.69133 0.70476 0.77674 0.61045 0.82261 0.77048 0.82261 0.77048 0.64943 0.90011 0.69133 0.70476 0.57744 0.7382 0.69133 0.70476 0.64943 0.90011 0.64943 0.90011 0.82261 0.77048 0.96246 0.88714 + + + + + + + + + + + + + + +

    14 0 12 1 1 2 12 3 14 4 13 5 2 6 13 7 14 8 13 9 0 10 12 11 16 12 1 13 12 14 12 15 15 16 16 17 5 18 16 19 15 20 12 21 0 22 15 23 18 24 13 25 2 26 13 27 18 28 17 29 3 30 17 31 18 32 17 33 0 34 13 35 20 36 17 37 3 38 17 39 20 40 19 41 4 42 19 43 20 44 19 45 0 46 17 47 21 48 19 49 4 50 19 51 21 52 15 53 5 54 15 55 21 56 15 57 0 58 19 59 23 60 1 61 16 62 16 63 22 64 23 65 10 66 23 67 22 68 22 69 16 70 5 71 25 72 2 73 14 74 14 75 24 76 25 77 6 78 25 79 24 80 24 81 14 82 1 83 27 84 3 85 18 86 18 87 26 88 27 89 7 90 27 91 26 92 26 93 18 94 2 95 29 96 4 97 20 98 20 99 28 100 29 101 8 102 29 103 28 104 28 105 20 106 3 107 31 108 5 109 21 110 21 111 30 112 31 113 9 114 31 115 30 116 30 117 21 118 4 119 32 120 23 121 10 122 23 123 32 124 24 125 6 126 24 127 32 128 24 129 1 130 23 131 33 132 25 133 6 134 25 135 33 136 26 137 7 138 26 139 33 140 26 141 2 142 25 143 34 144 27 145 7 146 27 147 34 148 28 149 8 150 28 151 34 152 28 153 3 154 27 155 35 156 29 157 8 158 29 159 35 160 30 161 9 162 30 163 35 164 30 165 4 166 29 167 36 168 31 169 9 170 31 171 36 172 22 173 10 174 22 175 36 176 22 177 5 178 31 179 38 180 6 181 32 182 32 183 37 184 38 185 11 186 38 187 37 188 37 189 32 190 10 191 39 192 7 193 33 194 33 195 38 196 39 197 11 198 39 199 38 200 38 201 33 202 6 203 40 204 8 205 34 206 34 207 39 208 40 209 11 210 40 211 39 212 39 213 34 214 7 215 41 216 9 217 35 218 35 219 40 220 41 221 11 222 41 223 40 224 40 225 35 226 8 227 37 228 10 229 36 230 36 231 41 232 37 233 11 234 37 235 41 236 41 237 36 238 9 239

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 + + + + + + + + + + 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.42013 0.42013 -0.42013 0.49402 0.33009 -0.42013 0.54892 0.22737 -0.42013 0.58273 0.11591 -0.42013 0.59415 0.0 -0.42013 0.58273 -0.11591 -0.42013 0.54892 -0.22737 -0.42013 0.49402 -0.33009 -0.42013 0.42013 -0.42013 -0.42013 0.33009 -0.49402 -0.42013 0.22737 -0.54892 -0.42013 0.11591 -0.58273 -0.42013 -0.0 -0.59415 -0.42013 -0.11591 -0.58273 -0.42013 -0.22737 -0.54892 -0.42013 -0.33009 -0.49402 -0.42013 -0.42013 -0.42013 -0.42013 -0.49402 -0.33009 -0.42013 -0.54892 -0.22737 -0.42013 -0.58273 -0.11591 -0.42013 -0.59415 0.0 -0.42013 -0.58273 0.11591 -0.42013 -0.54892 0.22737 -0.42013 -0.49402 0.33009 -0.42013 -0.42013 0.42013 -0.42013 -0.33009 0.49402 -0.42013 -0.22737 0.54892 -0.42013 -0.11591 0.58273 -0.42013 0.0 0.59415 -0.42013 0.11591 0.58273 -0.42013 0.22737 0.54892 -0.42013 0.33009 0.49402 -0.42013 -0.0 0.0 0.42013 -0.0 0.0 -0.42013 + + + + + + + + + + 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 + + + + + + + + + + + + + + +

    1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 0.0 -0.0 1.0 -0.0 0.0 -1.0 + + + + + + + + + + 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 + + + + + + + + + + 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 + + + + + + + + + + + + + + +

    1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 + + + + + + + + + + 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 + + + + + + + + + + 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 + + + + + + + + + + + + + + +

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.5076 0.17099 0.5076 0.02724 0.81102 0.02724 0.5076 0.17099 0.5076 0.02724 0.81102 0.02724 0.5076 0.17099 0.81102 0.17099 0.81102 0.02724 0.5076 0.17099 0.81102 0.17099 0.81102 0.02724 0.2494 0.17099 0.10396 0.17099 0.10396 0.02724 0.2494 0.17099 0.10396 0.17099 0.10396 0.02724 0.2494 0.48019 0.10396 0.48019 0.10396 0.78361 0.2494 0.48019 0.10396 0.48019 0.10396 0.78361 0.2494 0.67389 0.10396 0.67389 0.10396 0.81764 0.2494 0.67389 0.10396 0.67389 0.10396 0.81764 0.7506 0.48019 0.89604 0.48019 0.89604 0.78361 0.7506 0.48019 0.89604 0.48019 0.89604 0.78361 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 + + + + + + + + + + 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 + + + + + + + + + + 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 + + + + + + + + + + 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + + + + + +

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 + + + + + + + + + + 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 + + + + + + + + + + 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 + + + + + + + + + + + + + + +

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    +
    +
    +
    + + + + 15.68421 15.68421 0.0 15.68421 -15.68421 0.0 -15.68421 -15.68421 0.0 -15.6842 15.68421 0.0 0.0 15.68421 0.0 -15.68421 0.0 0.0 0.0 -15.68421 0.0 15.68421 -0.0 0.0 0.0 -0.0 0.0 7.84211 15.68421 0.0 -7.8421 15.68421 0.0 -15.68421 -7.8421 0.0 -15.68421 7.84211 0.0 7.84211 -15.68421 0.0 -7.84211 -15.68421 0.0 15.68421 7.8421 0.0 15.68421 -7.84211 0.0 -7.8421 0.0 0.0 0.0 7.8421 0.0 7.84211 -0.0 0.0 0.0 -7.84211 0.0 -7.8421 7.84211 0.0 7.84211 7.8421 0.0 -7.8421 -7.84211 0.0 7.84211 -7.84211 0.0 + + + + + + + + + + 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 + + + + + + + + + + + + + + +

    10 3 12 12 21 10 4 10 21 21 18 4 21 12 5 5 17 21 18 21 17 17 8 18 9 4 18 18 22 9 0 9 22 22 15 0 22 18 8 8 19 22 15 22 19 19 7 15 17 5 11 11 23 17 8 17 23 23 20 8 23 11 2 2 14 23 20 23 14 14 6 20 19 8 20 20 24 19 7 19 24 24 16 7 24 20 6 6 13 24 16 24 13 13 1 16

    +
    +
    +
    + + + + d:/bullet_logo.JPG + + + + + + + 1.0 1.0 0.71397 + 0.0 + 0.0 + 0.0 + + + + + + + + + + + + + + + + + + + + + + -14.55524 -12.21748 -0.85392 + 0.0 0.0 1.0 -0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 90.0 + + + + + + + + -14.51144 -12.21746 1.49207 + 0.0 0.0 1.0 -0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 90.0 + 0.59992 0.59992 0.59992 + + + + + + + + -10.54595 9.00056 -7.95634 + 0.0 0.0 1.0 161.23931 + 0.0 1.0 0.0 7.87085 + 1.0 0.0 0.0 -1.43785 + + + + + + + + + + -11.51412 -12.21752 -6.47685 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -40.16574 + 1.0 0.0 0.0 89.99999 + + + + + + + + + + -10.80608 -12.21753 -8.20963 + 0.0 0.0 1.0 179.99999 + 0.0 1.0 0.0 -68.68968 + 1.0 0.0 0.0 -90.0 + + + + + + + + + + -12.13872 -12.21753 -8.73677 + 0.0 0.0 1.0 -0.0 + 0.0 1.0 0.0 61.88929 + 1.0 0.0 0.0 89.99999 + + + + + + + + + + -11.09567 -3.46707 -5.6227 + 0.0 0.0 1.0 13.53526 + 0.0 1.0 0.0 -3.36769 + 1.0 0.0 0.0 31.10502 + + + + + + + + + + -5.6758 9.44806 -7.98855 + 0.0 0.0 1.0 90.0 + 0.0 1.0 0.0 -30.45178 + 1.0 0.0 0.0 90.0 + + + + 5.76483 -5.12569 1.3994 + 0.0 0.0 1.0 -5.78135 + 0.0 1.0 0.0 8.39643 + 1.0 0.0 0.0 -226.35694 + + + + + + + + + + -4.6651 -3.31256 -8.47664 + 0.0 0.0 1.0 165.33786 + 0.0 1.0 0.0 -9.4701 + 1.0 0.0 0.0 164.1133 + + + + + + + + + + 12.0373 6.52345 -7.84086 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -36.81686 + + + + + + + + + + 10.69918 0.32979 -8.69131 + 0.0 0.0 1.0 -38.06934 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + + + + + + + + + + 10.6716 0.3339 -6.5472 + 0.0 0.0 1.0 -38.06934 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + + + + + + + + + + 10.64675 0.37131 -4.4428 + 0.0 0.0 1.0 -38.06934 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + + + + + + + + + + 13.39988 -6.62079 -7.48373 + 0.0 0.0 1.0 -23.42368 + 0.0 1.0 0.0 -47.70962 + 1.0 0.0 0.0 14.68375 + + + + + + + + + + 1.07068 1.0946 -9.17122 + + + + + + + + + + 3.07068 1.0946 -9.17122 + + + + + + + + + + -0.92932 1.0946 -9.17122 + + + + + + + + + + -0.92932 1.0946 -7.17122 + + + + + + + + + + 3.07068 1.0946 -7.17122 + + + + + + + + + + 1.07068 1.0946 -7.17122 + + + + + + + + + + 1.07068 3.0946 -8.17122 + + + + + + + + + + 1.07068 -0.9054 -8.17122 + + + + + + + + + + 1.07068 1.0946 -8.17122 + + + + + + + + + + 1.07068 1.0946 -6.17122 + + + + + + + + + + 1.07068 -0.9054 -6.17122 + + + + + + + + + + 1.07068 3.0946 -6.17122 + + + + + + + + + + 1.07068 1.0946 -5.17122 + + + + + + + + + + 3.07068 1.0946 -5.17122 + + + + + + + + + + -0.92932 1.0946 -5.17122 + + + + + + + + + + -0.92932 1.0946 -3.17122 + + + + + + + + + + 3.07068 1.0946 -3.17122 + + + + + + + + + + 1.07068 1.0946 -3.17122 + + + + + + + + + + 1.07068 3.0946 -4.17122 + + + + + + + + + + 1.07068 -0.9054 -4.17122 + + + + + + + + + + 1.07068 1.0946 -4.17122 + + + + + + + + + + 1.07068 1.0946 -2.17122 + + + + + + + + + + 1.07068 -0.9054 -2.17122 + + + + + + + + + + 1.07068 3.0946 -2.17122 + + + + + + + + + + 1.07068 1.0946 -1.17122 + + + + + + + + + + 3.07068 1.0946 -1.17122 + + + + + + + + + + -0.92932 1.0946 -1.17122 + + + + + + + + + + -0.92932 1.0946 0.82878 + + + + + + + + + + 3.07068 1.0946 0.82878 + + + + + + + + + + 1.07068 1.0946 0.82878 + + + + + + + + + + 1.07068 3.0946 -0.17122 + + + + + + + + + + 1.07068 -0.9054 -0.17122 + + + + + + + + + + 1.07068 1.0946 -0.17122 + + + + + + + + + + 1.07068 1.0946 1.82878 + + + + + + + + + + 1.07068 -0.9054 1.82878 + + + + + + + + + + 1.07068 3.0946 1.82878 + + + + + + + + + + 1.07068 1.0946 2.82878 + + + + + + + + + + 3.07068 1.0946 2.82878 + + + + + + + + + + -0.92932 1.0946 2.82878 + + + + + + + + + + 1.07068 -12.41267 -2.84635 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -12.65713 -3.97696 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -12.93214 -4.92423 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -15.19337 -5.0159 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 1.07068 -13.57384 -7.5827 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 -0.0 + 1.0 0.0 0.0 -146.99812 + + + + + + + + + + 0.62583 12.00328 -8.00472 + 0.0 0.0 1.0 3.21265 + 0.0 1.0 0.0 -12.03335 + 1.0 0.0 0.0 66.50218 + + + + + + + + + + 1.28844 9.15244 -3.68906 + + + + 1.07068 -7.9054 -7.17122 + + + + + + + + + + 1.07068 -8.9054 -8.17122 + + + + + + + + + + 1.07068 -6.9054 -8.17122 + + + + + + + + + + 1.07068 -7.9054 -9.17122 + + + + + + + + + + -6.69969 -10.22419 -7.75589 + 0.0 0.0 1.0 -0.18482 + 0.0 1.0 0.0 -14.9718 + 1.0 0.0 0.0 -1.78118 + + + + + + + + + + 3.07068 1.0946 4.82878 + + + + + + + + + + 1.07068 1.0946 4.82878 + + + + + + + + + + 1.07068 -5.9054 -9.17122 + + + + + + + + + + 1.07068 3.0946 3.82878 + + + + + + + + + + 1.07068 -0.9054 3.82878 + + + + + + + + + + 1.07068 1.0946 3.82878 + + + + + + + + + + 0.31712 0.02145 -9.78565 + + + + + + + + + + 9.62214 -5.88949 -0.13709 + 0.0 0.0 1.0 106.93632 + 0.0 1.0 0.0 3.16371 + 1.0 0.0 0.0 37.26105 + + + + -7.40201 -33.19793 -3.19828 + 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 90.0 + + + + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + + + + + 2.358 0.3455 0.0 + + + false + 1.0 + + + + + + + + + + 7.3295 1.456 0.0 + + + false + 1.0 + + + + + + + + + + 1.0 + 1.0 + 0 0 + 1.0 + + + true + 1.0 + + + + + + + + + + + true + 1.0 + + + + + + + + + + + true + 1.0 + + + + + + + + + + + true + 1.0 + + + + + + + + + + 1.4 + + + true + 1.0 + + + + + + + + + + 1.0 1.0 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 0 0 + 0.42013 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 0 0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 1.0 + 1.0 + 1.0 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.22491 0.46923 0.2223 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 1.0 1.0 1.0 + + + false + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 1.0 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.97962 3.0 0.5 + + + true + 1.0 + + + + + + + + + + 0.47933 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 1.0 0.47376 + + + true + 1.0 + + + + + + + + + + 3.0 0.98954 0.47376 + + + true + 1.0 + + + + + + + + + + + false + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 0 -9.810000 + 0.0166666 + + + + + + + + diff --git a/Code/Physics/src/Bullet-C-Api.h b/Code/Physics/Bullet Source/src/Bullet-C-Api.h similarity index 100% rename from Code/Physics/src/Bullet-C-Api.h rename to Code/Physics/Bullet Source/src/Bullet-C-Api.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvt.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btDispatcher.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp diff --git a/Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h similarity index 100% rename from Code/Physics/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h rename to Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h diff --git a/Code/Physics/src/BulletCollision/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletCollision/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObject.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCollisionWorld.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btGhostObject.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btManifoldResult.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionDispatch/btUnionFind.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btBox2dShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btBoxShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCapsuleShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionMargin.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCollisionMargin.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionMargin.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCollisionShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCompoundShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConcaveShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConeShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvex2dShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexHullShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexInternalShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btCylinderShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btEmptyShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMaterial.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMaterial.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMaterial.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMaterial.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMultiSphereShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btOptimizedBvh.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btShapeHull.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btSphereShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTetrahedronShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleBuffer.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleBuffer.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleCallback.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMesh.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btTriangleShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btTriangleShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleShape.h diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp diff --git a/Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/CollisionShapes/btUniformScalingShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.h diff --git a/Code/Physics/src/BulletCollision/Doxyfile b/Code/Physics/Bullet Source/src/BulletCollision/Doxyfile similarity index 100% rename from Code/Physics/src/BulletCollision/Doxyfile rename to Code/Physics/Bullet Source/src/BulletCollision/Doxyfile diff --git a/Code/Physics/src/BulletCollision/Gimpact/btBoxCollision.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btBoxCollision.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btBoxCollision.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btBoxCollision.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btClipPolygon.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btClipPolygon.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btClipPolygon.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btClipPolygon.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btCompoundFromGimpact.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btCompoundFromGimpact.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btCompoundFromGimpact.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btCompoundFromGimpact.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btContactProcessing.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactBvh.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactMassUtil.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactMassUtil.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactMassUtil.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGImpactShape.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGenericPoolAllocator.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btGeometryOperations.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGeometryOperations.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btGeometryOperations.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGeometryOperations.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btQuantization.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btQuantization.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btQuantization.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btQuantization.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/btTriangleShapeEx.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_array.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_array.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_array.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_array.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_bitset.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_bitset.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_bitset.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_bitset.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_box_collision.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_collision.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_box_collision.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_collision.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_box_set.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_box_set.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_box_set.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_clip_polygon.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_clip_polygon.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_clip_polygon.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_clip_polygon.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_contact.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_contact.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_contact.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_contact.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_geom_types.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geom_types.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_geom_types.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geom_types.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_geometry.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geometry.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_geometry.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geometry.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_hash_table.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_hash_table.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_hash_table.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_hash_table.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_linear_math.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_linear_math.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_linear_math.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_linear_math.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_math.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_math.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_math.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_math.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_memory.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_memory.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_memory.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_memory.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_radixsort.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_radixsort.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_radixsort.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_radixsort.h diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.cpp diff --git a/Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.h b/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.h similarity index 100% rename from Code/Physics/src/BulletCollision/Gimpact/gim_tri_collision.h rename to Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp diff --git a/Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h similarity index 100% rename from Code/Physics/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h rename to Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h diff --git a/Code/Physics/src/BulletCollision/premake4.lua b/Code/Physics/Bullet Source/src/BulletCollision/premake4.lua similarity index 100% rename from Code/Physics/src/BulletCollision/premake4.lua rename to Code/Physics/Bullet Source/src/BulletCollision/premake4.lua diff --git a/Code/Physics/src/BulletDynamics/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletDynamics/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt diff --git a/Code/Physics/src/BulletDynamics/Character/btCharacterControllerInterface.h b/Code/Physics/Bullet Source/src/BulletDynamics/Character/btCharacterControllerInterface.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Character/btCharacterControllerInterface.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Character/btCharacterControllerInterface.h diff --git a/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.cpp diff --git a/Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.h b/Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Character/btKinematicCharacterController.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btContactConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btGearConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverBody.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverBody.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverBody.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h diff --git a/Code/Physics/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/Bullet-C-API.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/Bullet-C-API.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/Bullet-C-API.cpp diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btActionInterface.h b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btActionInterface.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btActionInterface.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btActionInterface.h diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp similarity index 99% rename from Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 610db477..fb8a4068 100644 --- a/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -340,10 +340,6 @@ void btDiscreteDynamicsWorld::applyGravity() btRigidBody* body = m_nonStaticRigidBodies[i]; if (body->isActive()) { - // MOD: Changing gravity for every body so they are pulled towards 0, 0, 0 - btTransform trans; - body->getMotionState()->getWorldTransform(trans); - body->setGravity(-trans.getOrigin().normalized()*10); body->applyGravity(); } } diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDynamicsWorld.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btDynamicsWorld.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDynamicsWorld.h diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.cpp diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.h b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btRigidBody.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.h diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp diff --git a/Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBody.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyLink.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLink.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyLink.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLink.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h diff --git a/Code/Physics/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btPATHSolver.h b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btPATHSolver.h similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btPATHSolver.h rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btPATHSolver.h diff --git a/Code/Physics/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h similarity index 100% rename from Code/Physics/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h rename to Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Vehicle/btRaycastVehicle.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.h diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btVehicleRaycaster.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Vehicle/btVehicleRaycaster.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btVehicleRaycaster.h diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.cpp similarity index 100% rename from Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.cpp rename to Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.cpp diff --git a/Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.h b/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.h similarity index 100% rename from Code/Physics/src/BulletDynamics/Vehicle/btWheelInfo.h rename to Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.h diff --git a/Code/Physics/src/BulletDynamics/premake4.lua b/Code/Physics/Bullet Source/src/BulletDynamics/premake4.lua similarity index 100% rename from Code/Physics/src/BulletDynamics/premake4.lua rename to Code/Physics/Bullet Source/src/BulletDynamics/premake4.lua diff --git a/Code/Physics/src/BulletMultiThreaded/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h diff --git a/Code/Physics/src/BulletMultiThreaded/HeapManager.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/HeapManager.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/HeapManager.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/HeapManager.h diff --git a/Code/Physics/src/BulletMultiThreaded/PlatformDefinitions.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PlatformDefinitions.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/PlatformDefinitions.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/PlatformDefinitions.h diff --git a/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/PosixThreadSupport.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.h diff --git a/Code/Physics/src/BulletMultiThreaded/PpuAddressSpace.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PpuAddressSpace.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/PpuAddressSpace.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/PpuAddressSpace.h diff --git a/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SequentialThreadSupport.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuCollisionTaskProcess.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuDoubleBuffer.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuDoubleBuffer.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuDoubleBuffer.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuDoubleBuffer.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuFakeDma.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuFakeDma.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuFakeDma.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuFakeDma.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuFakeDma.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuFakeDma.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuFakeDma.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuFakeDma.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuLibspe2Support.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTask/readme.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/readme.txt similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuSampleTask/readme.txt rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/readme.txt diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuSampleTaskProcess.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.h diff --git a/Code/Physics/src/BulletMultiThreaded/SpuSync.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSync.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/SpuSync.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSync.h diff --git a/Code/Physics/src/BulletMultiThreaded/TrbDynBody.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbDynBody.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/TrbDynBody.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbDynBody.h diff --git a/Code/Physics/src/BulletMultiThreaded/TrbStateVec.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbStateVec.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/TrbStateVec.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbStateVec.h diff --git a/Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/Win32ThreadSupport.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphase.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpuDefines.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuDefines.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpuDefines.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuDefines.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpuUtilsSharedCode.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuUtilsSharedCode.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpuUtilsSharedCode.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuUtilsSharedCode.h diff --git a/Code/Physics/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h diff --git a/Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btParallelConstraintSolver.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.h diff --git a/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.cpp similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.cpp rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.cpp diff --git a/Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/btThreadSupportInterface.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.h diff --git a/Code/Physics/src/BulletMultiThreaded/vectormath2bullet.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/vectormath2bullet.h similarity index 100% rename from Code/Physics/src/BulletMultiThreaded/vectormath2bullet.h rename to Code/Physics/Bullet Source/src/BulletMultiThreaded/vectormath2bullet.h diff --git a/Code/Physics/src/BulletSoftBody/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt similarity index 100% rename from Code/Physics/src/BulletSoftBody/CMakeLists.txt rename to Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt diff --git a/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.cpp diff --git a/Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btDefaultSoftBodySolver.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBody.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBody.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftBody.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBody.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyData.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyData.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyData.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyData.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyHelpers.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyInternals.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyInternals.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyInternals.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyInternals.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftBodySolvers.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolvers.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftBodySolvers.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolvers.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftRigidDynamicsWorld.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.h diff --git a/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp diff --git a/Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h diff --git a/Code/Physics/src/BulletSoftBody/btSparseSDF.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSparseSDF.h similarity index 100% rename from Code/Physics/src/BulletSoftBody/btSparseSDF.h rename to Code/Physics/Bullet Source/src/BulletSoftBody/btSparseSDF.h diff --git a/Code/Physics/src/BulletSoftBody/premake4.lua b/Code/Physics/Bullet Source/src/BulletSoftBody/premake4.lua similarity index 100% rename from Code/Physics/src/BulletSoftBody/premake4.lua rename to Code/Physics/Bullet Source/src/BulletSoftBody/premake4.lua diff --git a/Code/Physics/src/CMakeLists.txt b/Code/Physics/Bullet Source/src/CMakeLists.txt similarity index 100% rename from Code/Physics/src/CMakeLists.txt rename to Code/Physics/Bullet Source/src/CMakeLists.txt diff --git a/Code/Physics/src/LinearMath/CMakeLists.txt b/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt similarity index 100% rename from Code/Physics/src/LinearMath/CMakeLists.txt rename to Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt diff --git a/Code/Physics/src/LinearMath/btAabbUtil2.h b/Code/Physics/Bullet Source/src/LinearMath/btAabbUtil2.h similarity index 100% rename from Code/Physics/src/LinearMath/btAabbUtil2.h rename to Code/Physics/Bullet Source/src/LinearMath/btAabbUtil2.h diff --git a/Code/Physics/src/LinearMath/btAlignedAllocator.cpp b/Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btAlignedAllocator.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.cpp diff --git a/Code/Physics/src/LinearMath/btAlignedAllocator.h b/Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.h similarity index 100% rename from Code/Physics/src/LinearMath/btAlignedAllocator.h rename to Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.h diff --git a/Code/Physics/src/LinearMath/btAlignedObjectArray.h b/Code/Physics/Bullet Source/src/LinearMath/btAlignedObjectArray.h similarity index 100% rename from Code/Physics/src/LinearMath/btAlignedObjectArray.h rename to Code/Physics/Bullet Source/src/LinearMath/btAlignedObjectArray.h diff --git a/Code/Physics/src/LinearMath/btConvexHull.cpp b/Code/Physics/Bullet Source/src/LinearMath/btConvexHull.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btConvexHull.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btConvexHull.cpp diff --git a/Code/Physics/src/LinearMath/btConvexHull.h b/Code/Physics/Bullet Source/src/LinearMath/btConvexHull.h similarity index 100% rename from Code/Physics/src/LinearMath/btConvexHull.h rename to Code/Physics/Bullet Source/src/LinearMath/btConvexHull.h diff --git a/Code/Physics/src/LinearMath/btConvexHullComputer.cpp b/Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btConvexHullComputer.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.cpp diff --git a/Code/Physics/src/LinearMath/btConvexHullComputer.h b/Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.h similarity index 100% rename from Code/Physics/src/LinearMath/btConvexHullComputer.h rename to Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.h diff --git a/Code/Physics/src/LinearMath/btDefaultMotionState.h b/Code/Physics/Bullet Source/src/LinearMath/btDefaultMotionState.h similarity index 100% rename from Code/Physics/src/LinearMath/btDefaultMotionState.h rename to Code/Physics/Bullet Source/src/LinearMath/btDefaultMotionState.h diff --git a/Code/Physics/src/LinearMath/btGeometryUtil.cpp b/Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btGeometryUtil.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.cpp diff --git a/Code/Physics/src/LinearMath/btGeometryUtil.h b/Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.h similarity index 100% rename from Code/Physics/src/LinearMath/btGeometryUtil.h rename to Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.h diff --git a/Code/Physics/src/LinearMath/btGrahamScan2dConvexHull.h b/Code/Physics/Bullet Source/src/LinearMath/btGrahamScan2dConvexHull.h similarity index 100% rename from Code/Physics/src/LinearMath/btGrahamScan2dConvexHull.h rename to Code/Physics/Bullet Source/src/LinearMath/btGrahamScan2dConvexHull.h diff --git a/Code/Physics/src/LinearMath/btHashMap.h b/Code/Physics/Bullet Source/src/LinearMath/btHashMap.h similarity index 100% rename from Code/Physics/src/LinearMath/btHashMap.h rename to Code/Physics/Bullet Source/src/LinearMath/btHashMap.h diff --git a/Code/Physics/src/LinearMath/btIDebugDraw.h b/Code/Physics/Bullet Source/src/LinearMath/btIDebugDraw.h similarity index 100% rename from Code/Physics/src/LinearMath/btIDebugDraw.h rename to Code/Physics/Bullet Source/src/LinearMath/btIDebugDraw.h diff --git a/Code/Physics/src/LinearMath/btList.h b/Code/Physics/Bullet Source/src/LinearMath/btList.h similarity index 100% rename from Code/Physics/src/LinearMath/btList.h rename to Code/Physics/Bullet Source/src/LinearMath/btList.h diff --git a/Code/Physics/src/LinearMath/btMatrix3x3.h b/Code/Physics/Bullet Source/src/LinearMath/btMatrix3x3.h similarity index 100% rename from Code/Physics/src/LinearMath/btMatrix3x3.h rename to Code/Physics/Bullet Source/src/LinearMath/btMatrix3x3.h diff --git a/Code/Physics/src/LinearMath/btMatrixX.h b/Code/Physics/Bullet Source/src/LinearMath/btMatrixX.h similarity index 100% rename from Code/Physics/src/LinearMath/btMatrixX.h rename to Code/Physics/Bullet Source/src/LinearMath/btMatrixX.h diff --git a/Code/Physics/src/LinearMath/btMinMax.h b/Code/Physics/Bullet Source/src/LinearMath/btMinMax.h similarity index 100% rename from Code/Physics/src/LinearMath/btMinMax.h rename to Code/Physics/Bullet Source/src/LinearMath/btMinMax.h diff --git a/Code/Physics/src/LinearMath/btMotionState.h b/Code/Physics/Bullet Source/src/LinearMath/btMotionState.h similarity index 100% rename from Code/Physics/src/LinearMath/btMotionState.h rename to Code/Physics/Bullet Source/src/LinearMath/btMotionState.h diff --git a/Code/Physics/src/LinearMath/btPolarDecomposition.cpp b/Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btPolarDecomposition.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.cpp diff --git a/Code/Physics/src/LinearMath/btPolarDecomposition.h b/Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.h similarity index 100% rename from Code/Physics/src/LinearMath/btPolarDecomposition.h rename to Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.h diff --git a/Code/Physics/src/LinearMath/btPoolAllocator.h b/Code/Physics/Bullet Source/src/LinearMath/btPoolAllocator.h similarity index 100% rename from Code/Physics/src/LinearMath/btPoolAllocator.h rename to Code/Physics/Bullet Source/src/LinearMath/btPoolAllocator.h diff --git a/Code/Physics/src/LinearMath/btQuadWord.h b/Code/Physics/Bullet Source/src/LinearMath/btQuadWord.h similarity index 100% rename from Code/Physics/src/LinearMath/btQuadWord.h rename to Code/Physics/Bullet Source/src/LinearMath/btQuadWord.h diff --git a/Code/Physics/src/LinearMath/btQuaternion.h b/Code/Physics/Bullet Source/src/LinearMath/btQuaternion.h similarity index 100% rename from Code/Physics/src/LinearMath/btQuaternion.h rename to Code/Physics/Bullet Source/src/LinearMath/btQuaternion.h diff --git a/Code/Physics/src/LinearMath/btQuickprof.cpp b/Code/Physics/Bullet Source/src/LinearMath/btQuickprof.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btQuickprof.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btQuickprof.cpp diff --git a/Code/Physics/src/LinearMath/btQuickprof.h b/Code/Physics/Bullet Source/src/LinearMath/btQuickprof.h similarity index 100% rename from Code/Physics/src/LinearMath/btQuickprof.h rename to Code/Physics/Bullet Source/src/LinearMath/btQuickprof.h diff --git a/Code/Physics/src/LinearMath/btRandom.h b/Code/Physics/Bullet Source/src/LinearMath/btRandom.h similarity index 100% rename from Code/Physics/src/LinearMath/btRandom.h rename to Code/Physics/Bullet Source/src/LinearMath/btRandom.h diff --git a/Code/Physics/src/LinearMath/btScalar.h b/Code/Physics/Bullet Source/src/LinearMath/btScalar.h similarity index 100% rename from Code/Physics/src/LinearMath/btScalar.h rename to Code/Physics/Bullet Source/src/LinearMath/btScalar.h diff --git a/Code/Physics/src/LinearMath/btSerializer.cpp b/Code/Physics/Bullet Source/src/LinearMath/btSerializer.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btSerializer.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btSerializer.cpp diff --git a/Code/Physics/src/LinearMath/btSerializer.h b/Code/Physics/Bullet Source/src/LinearMath/btSerializer.h similarity index 100% rename from Code/Physics/src/LinearMath/btSerializer.h rename to Code/Physics/Bullet Source/src/LinearMath/btSerializer.h diff --git a/Code/Physics/src/LinearMath/btStackAlloc.h b/Code/Physics/Bullet Source/src/LinearMath/btStackAlloc.h similarity index 100% rename from Code/Physics/src/LinearMath/btStackAlloc.h rename to Code/Physics/Bullet Source/src/LinearMath/btStackAlloc.h diff --git a/Code/Physics/src/LinearMath/btTransform.h b/Code/Physics/Bullet Source/src/LinearMath/btTransform.h similarity index 100% rename from Code/Physics/src/LinearMath/btTransform.h rename to Code/Physics/Bullet Source/src/LinearMath/btTransform.h diff --git a/Code/Physics/src/LinearMath/btTransformUtil.h b/Code/Physics/Bullet Source/src/LinearMath/btTransformUtil.h similarity index 100% rename from Code/Physics/src/LinearMath/btTransformUtil.h rename to Code/Physics/Bullet Source/src/LinearMath/btTransformUtil.h diff --git a/Code/Physics/src/LinearMath/btVector3.cpp b/Code/Physics/Bullet Source/src/LinearMath/btVector3.cpp similarity index 100% rename from Code/Physics/src/LinearMath/btVector3.cpp rename to Code/Physics/Bullet Source/src/LinearMath/btVector3.cpp diff --git a/Code/Physics/src/LinearMath/btVector3.h b/Code/Physics/Bullet Source/src/LinearMath/btVector3.h similarity index 100% rename from Code/Physics/src/LinearMath/btVector3.h rename to Code/Physics/Bullet Source/src/LinearMath/btVector3.h diff --git a/Code/Physics/src/LinearMath/premake4.lua b/Code/Physics/Bullet Source/src/LinearMath/premake4.lua similarity index 100% rename from Code/Physics/src/LinearMath/premake4.lua rename to Code/Physics/Bullet Source/src/LinearMath/premake4.lua diff --git a/Code/Physics/src/Makefile.am b/Code/Physics/Bullet Source/src/Makefile.am similarity index 100% rename from Code/Physics/src/Makefile.am rename to Code/Physics/Bullet Source/src/Makefile.am diff --git a/Code/Physics/src/MiniCL/CMakeLists.txt b/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt similarity index 100% rename from Code/Physics/src/MiniCL/CMakeLists.txt rename to Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt diff --git a/Code/Physics/src/MiniCL/MiniCL.cpp b/Code/Physics/Bullet Source/src/MiniCL/MiniCL.cpp similarity index 100% rename from Code/Physics/src/MiniCL/MiniCL.cpp rename to Code/Physics/Bullet Source/src/MiniCL/MiniCL.cpp diff --git a/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.cpp b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.cpp similarity index 100% rename from Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.cpp rename to Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.cpp diff --git a/Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.h b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.h similarity index 100% rename from Code/Physics/src/MiniCL/MiniCLTask/MiniCLTask.h rename to Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.h diff --git a/Code/Physics/src/MiniCL/MiniCLTaskScheduler.cpp b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.cpp similarity index 100% rename from Code/Physics/src/MiniCL/MiniCLTaskScheduler.cpp rename to Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.cpp diff --git a/Code/Physics/src/MiniCL/MiniCLTaskScheduler.h b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.h similarity index 100% rename from Code/Physics/src/MiniCL/MiniCLTaskScheduler.h rename to Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.h diff --git a/Code/Physics/src/MiniCL/cl.h b/Code/Physics/Bullet Source/src/MiniCL/cl.h similarity index 100% rename from Code/Physics/src/MiniCL/cl.h rename to Code/Physics/Bullet Source/src/MiniCL/cl.h diff --git a/Code/Physics/src/MiniCL/cl_MiniCL_Defs.h b/Code/Physics/Bullet Source/src/MiniCL/cl_MiniCL_Defs.h similarity index 100% rename from Code/Physics/src/MiniCL/cl_MiniCL_Defs.h rename to Code/Physics/Bullet Source/src/MiniCL/cl_MiniCL_Defs.h diff --git a/Code/Physics/src/MiniCL/cl_gl.h b/Code/Physics/Bullet Source/src/MiniCL/cl_gl.h similarity index 100% rename from Code/Physics/src/MiniCL/cl_gl.h rename to Code/Physics/Bullet Source/src/MiniCL/cl_gl.h diff --git a/Code/Physics/src/MiniCL/cl_platform.h b/Code/Physics/Bullet Source/src/MiniCL/cl_platform.h similarity index 100% rename from Code/Physics/src/MiniCL/cl_platform.h rename to Code/Physics/Bullet Source/src/MiniCL/cl_platform.h diff --git a/Code/Physics/src/btBulletCollisionCommon.h b/Code/Physics/Bullet Source/src/btBulletCollisionCommon.h similarity index 100% rename from Code/Physics/src/btBulletCollisionCommon.h rename to Code/Physics/Bullet Source/src/btBulletCollisionCommon.h diff --git a/Code/Physics/src/btBulletDynamicsCommon.h b/Code/Physics/Bullet Source/src/btBulletDynamicsCommon.h similarity index 100% rename from Code/Physics/src/btBulletDynamicsCommon.h rename to Code/Physics/Bullet Source/src/btBulletDynamicsCommon.h diff --git a/Code/Physics/src/vectormath/neon/boolInVec.h b/Code/Physics/Bullet Source/src/vectormath/neon/boolInVec.h similarity index 100% rename from Code/Physics/src/vectormath/neon/boolInVec.h rename to Code/Physics/Bullet Source/src/vectormath/neon/boolInVec.h diff --git a/Code/Physics/src/vectormath/neon/floatInVec.h b/Code/Physics/Bullet Source/src/vectormath/neon/floatInVec.h similarity index 100% rename from Code/Physics/src/vectormath/neon/floatInVec.h rename to Code/Physics/Bullet Source/src/vectormath/neon/floatInVec.h diff --git a/Code/Physics/src/vectormath/neon/mat_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/mat_aos.h similarity index 100% rename from Code/Physics/src/vectormath/neon/mat_aos.h rename to Code/Physics/Bullet Source/src/vectormath/neon/mat_aos.h diff --git a/Code/Physics/src/vectormath/neon/quat_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/quat_aos.h similarity index 100% rename from Code/Physics/src/vectormath/neon/quat_aos.h rename to Code/Physics/Bullet Source/src/vectormath/neon/quat_aos.h diff --git a/Code/Physics/src/vectormath/neon/vec_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/vec_aos.h similarity index 100% rename from Code/Physics/src/vectormath/neon/vec_aos.h rename to Code/Physics/Bullet Source/src/vectormath/neon/vec_aos.h diff --git a/Code/Physics/src/vectormath/neon/vectormath_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/vectormath_aos.h similarity index 100% rename from Code/Physics/src/vectormath/neon/vectormath_aos.h rename to Code/Physics/Bullet Source/src/vectormath/neon/vectormath_aos.h diff --git a/Code/Physics/src/vectormath/scalar/boolInVec.h b/Code/Physics/Bullet Source/src/vectormath/scalar/boolInVec.h similarity index 100% rename from Code/Physics/src/vectormath/scalar/boolInVec.h rename to Code/Physics/Bullet Source/src/vectormath/scalar/boolInVec.h diff --git a/Code/Physics/src/vectormath/scalar/floatInVec.h b/Code/Physics/Bullet Source/src/vectormath/scalar/floatInVec.h similarity index 100% rename from Code/Physics/src/vectormath/scalar/floatInVec.h rename to Code/Physics/Bullet Source/src/vectormath/scalar/floatInVec.h diff --git a/Code/Physics/src/vectormath/scalar/mat_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/mat_aos.h similarity index 100% rename from Code/Physics/src/vectormath/scalar/mat_aos.h rename to Code/Physics/Bullet Source/src/vectormath/scalar/mat_aos.h diff --git a/Code/Physics/src/vectormath/scalar/quat_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/quat_aos.h similarity index 100% rename from Code/Physics/src/vectormath/scalar/quat_aos.h rename to Code/Physics/Bullet Source/src/vectormath/scalar/quat_aos.h diff --git a/Code/Physics/src/vectormath/scalar/vec_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/vec_aos.h similarity index 100% rename from Code/Physics/src/vectormath/scalar/vec_aos.h rename to Code/Physics/Bullet Source/src/vectormath/scalar/vec_aos.h diff --git a/Code/Physics/src/vectormath/scalar/vectormath_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/vectormath_aos.h similarity index 100% rename from Code/Physics/src/vectormath/scalar/vectormath_aos.h rename to Code/Physics/Bullet Source/src/vectormath/scalar/vectormath_aos.h diff --git a/Code/Physics/src/vectormath/sse/boolInVec.h b/Code/Physics/Bullet Source/src/vectormath/sse/boolInVec.h similarity index 100% rename from Code/Physics/src/vectormath/sse/boolInVec.h rename to Code/Physics/Bullet Source/src/vectormath/sse/boolInVec.h diff --git a/Code/Physics/src/vectormath/sse/floatInVec.h b/Code/Physics/Bullet Source/src/vectormath/sse/floatInVec.h similarity index 100% rename from Code/Physics/src/vectormath/sse/floatInVec.h rename to Code/Physics/Bullet Source/src/vectormath/sse/floatInVec.h diff --git a/Code/Physics/src/vectormath/sse/mat_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/mat_aos.h similarity index 100% rename from Code/Physics/src/vectormath/sse/mat_aos.h rename to Code/Physics/Bullet Source/src/vectormath/sse/mat_aos.h diff --git a/Code/Physics/src/vectormath/sse/quat_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/quat_aos.h similarity index 100% rename from Code/Physics/src/vectormath/sse/quat_aos.h rename to Code/Physics/Bullet Source/src/vectormath/sse/quat_aos.h diff --git a/Code/Physics/src/vectormath/sse/vec_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/vec_aos.h similarity index 100% rename from Code/Physics/src/vectormath/sse/vec_aos.h rename to Code/Physics/Bullet Source/src/vectormath/sse/vec_aos.h diff --git a/Code/Physics/src/vectormath/sse/vecidx_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/vecidx_aos.h similarity index 100% rename from Code/Physics/src/vectormath/sse/vecidx_aos.h rename to Code/Physics/Bullet Source/src/vectormath/sse/vecidx_aos.h diff --git a/Code/Physics/src/vectormath/sse/vectormath_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/vectormath_aos.h similarity index 100% rename from Code/Physics/src/vectormath/sse/vectormath_aos.h rename to Code/Physics/Bullet Source/src/vectormath/sse/vectormath_aos.h diff --git a/Code/Physics/src/vectormath/vmInclude.h b/Code/Physics/Bullet Source/src/vectormath/vmInclude.h similarity index 100% rename from Code/Physics/src/vectormath/vmInclude.h rename to Code/Physics/Bullet Source/src/vectormath/vmInclude.h diff --git a/Code/Physics/Bullet Source/test1.oec b/Code/Physics/Bullet Source/test1.oec new file mode 100644 index 00000000..7fac1d15 --- /dev/null +++ b/Code/Physics/Bullet Source/test1.oec @@ -0,0 +1,227 @@ +# OctaveEngine Casual (Jul 14 2008) +version 2 +p 22000 1 ff 7fff66ff 13 79 0 0 13 79 0 0 0 +p 22000 1 ff 7fff66ff 12.25 77.5 0 0 12.25 77.5 0 0 0 +p 22000 1 ff 7fff66ff 12.25 78.25 0 0 12.25 78.25 0 0 0 +p 22000 1 ff 7fff66ff 13 77.5 0 0 13 77.5 0 0 0 +p 22000 1 ff 7fff66ff 13 78.25 0 0 13 78.25 0 0 0 +p 22000 1 ff 7fff66ff 13.75 77.5 0 0 13.75 77.5 0 0 0 +p 22000 1 ff 7fff66ff 13.75 78.25 0 0 13.75 78.25 0 0 0 +p 22000 2 ff 7fff66ff 14.75 73.625 0 0 14.75 73.625 0 0 0 +p 22000 2 ff 7fff66ff 15.5 73.625 0 0 15.5 73.625 0 0 0 +p 22000 2 ff 7fff66ff 16.25 73.625 0 0 16.25 73.625 0 0 0 +p 22000 2 ff 7fff66ff 17 73.625 0 0 17 73.625 0 0 0 +p 22000 2 ff 7fff66ff 17.75 73.625 0 0 17.75 73.625 0 0 0 +p 22000 2 ff 7fff66ff 18.5 73.625 0 0 18.5 73.625 0 0 0 +p 22000 3 ff 7fff66ff 26 79 0 0 26 79 0 0 0 +p 22000 3 ff 7fff66ff 26.2372 78.2885 0 0 26.2372 78.2885 0 0 0 +p 22000 3 ff 7fff66ff 26.9705 78.1313 0 0 26.9705 78.1313 0 0 0 +p 22000 3 ff 7fff66ff 27.2344 78.8334 0 0 27.2344 78.8334 0 0 0 +p 22000 3 ff 7fff66ff 27.0215 79.5525 0 0 27.0215 79.5525 0 0 0 +p 22000 3 ff 7fff66ff 26.5164 80.107 0 0 26.5164 80.107 0 0 0 +p 22000 4 ff 7fff66ff 42 73.875 0 0 42 73.875 0 0 0 +p 22000 4 ff 7fff66ff 42.5857 73.4065 0 0 42.5857 73.4065 0 0 0 +p 22000 4 ff 7fff66ff 41.8884 73.1303 0 0 41.8884 73.1303 0 0 0 +p 22000 4 ff 7fff66ff 41.3003 72.6648 0 0 41.3003 72.6648 0 0 0 +p 22000 4 ff 7fff66ff 40.6805 73.0872 0 0 40.6805 73.0872 0 0 0 +p 22000 5 ff 7fff66ff 57.125 74 0 0 57.125 74 0 0 0 +p 22000 5 ff 7fff66ff 57.7958 73.6646 0 0 57.7958 73.6646 0 0 0 +p 22000 5 ff 7fff66ff 58.1111 74.3451 0 0 58.1111 74.3451 0 0 0 +p 22000 5 ff 7fff66ff 57.5445 74.8364 0 0 57.5445 74.8364 0 0 0 +p 822000 12 ff 99cc7fff 41.875 70 0 0 41.875 70 0 0 0 +p 822000 12 ff 99cc7fff 41.125 70 0 0 41.125 70 0 0 0 +p 822000 12 ff 99cc7fff 40.3852 70.1233 0 0 40.3852 70.1233 0 0 0 +p 822000 12 ff 99cc7fff 39.6352 70.125 0 0 39.6352 70.125 0 0 0 +p 822000 12 ff 99cc7fff 38.8926 70.2299 0 0 38.8926 70.2299 0 0 0 +p 822000 12 ff 99cc7fff 38.1428 70.2495 0 0 38.1428 70.2495 0 0 0 +p 822000 12 ff 99cc7fff 37.3928 70.25 0 0 37.3928 70.25 0 0 0 +p 22000 15 ff 7fff66ff 62.25 57.625 0 0 62.25 57.625 0 0 0 +p 22000 15 ff 7fff66ff 62.9615 57.3878 0 0 62.9615 57.3878 0 0 0 +p 22000 15 ff 7fff66ff 62.8866 58.1341 0 0 62.8866 58.1341 0 0 0 +p 22000 15 ff 7fff66ff 62.2927 58.5921 0 0 62.2927 58.5921 0 0 0 +p 22000 14 ff 7fff66ff 46.875 59 0 0 46.875 59 0 0 0 +p 22000 14 ff 7fff66ff 47.3435 58.4143 0 0 47.3435 58.4143 0 0 0 +p 22000 14 ff 7fff66ff 48.0775 58.26 0 0 48.0775 58.26 0 0 0 +p 22000 14 ff 7fff66ff 48.4494 58.9113 0 0 48.4494 58.9113 0 0 0 +p 22000 14 ff 7fff66ff 48.2759 59.641 0 0 48.2759 59.641 0 0 0 +p 22000 17 ff 7fff66ff 32.625 58.625 0 0 32.625 58.625 0 0 0 +p 22000 17 ff 7fff66ff 33.2958 58.2896 0 0 33.2958 58.2896 0 0 0 +p 22000 17 ff 7fff66ff 34.045 58.2538 0 0 34.045 58.2538 0 0 0 +p 22000 17 ff 7fff66ff 34.3483 58.9397 0 0 34.3483 58.9397 0 0 0 +p 22000 16 ff 7fff66ff 23 50 0 0 23 50 0 0 0 +p 22000 16 ff 7fff66ff 23.6512 49.6279 0 0 23.6512 49.6279 0 0 0 +p 22000 16 ff 7fff66ff 24.3928 49.5162 0 0 24.3928 49.5162 0 0 0 +p 22000 16 ff 7fff66ff 24.1695 50.2321 0 0 24.1695 50.2321 0 0 0 +p 22000 18 ff 7fff66ff 18.375 59.25 0 0 18.375 59.25 0 0 0 +p 22000 18 ff 7fff66ff 18.9053 58.7197 0 0 18.9053 58.7197 0 0 0 +p 22000 18 ff 7fff66ff 19.4651 59.2189 0 0 19.4651 59.2189 0 0 0 +p 22000 18 ff 7fff66ff 19.3792 59.9639 0 0 19.3792 59.9639 0 0 0 +p 22000 7 ff 7fff66ff 44.125 51.75 0 0 44.125 51.75 0 0 0 +p 22000 7 ff 7fff66ff 44.0017 51.0102 0 0 44.0017 51.0102 0 0 0 +p 22000 7 ff 7fff66ff 44.743 51.1239 0 0 44.743 51.1239 0 0 0 +p 22000 7 ff 7fff66ff 45.0428 51.8114 0 0 45.0428 51.8114 0 0 0 +p 22000 8 ff 7fff66ff 59.125 49.375 0 0 59.125 49.375 0 0 0 +p 22000 8 ff 7fff66ff 59.125 48.625 0 0 59.125 48.625 0 0 0 +p 22000 8 ff 7fff66ff 59.7958 48.2896 0 0 59.7958 48.2896 0 0 0 +p 22000 8 ff 7fff66ff 59.9739 49.0181 0 0 59.9739 49.0181 0 0 0 +p 22000 9 ff 7fff66ff 42.5 41.625 0 0 42.5 41.625 0 0 0 +p 22000 9 ff 7fff66ff 43.0303 41.0947 0 0 43.0303 41.0947 0 0 0 +p 22000 9 ff 7fff66ff 43.7798 41.1216 0 0 43.7798 41.1216 0 0 0 +p 22000 9 ff 7fff66ff 44.3525 41.6059 0 0 44.3525 41.6059 0 0 0 +p 22000 9 ff 7fff66ff 43.9569 42.2431 0 0 43.9569 42.2431 0 0 0 +p 22000 a ff 7fff66ff 70.375 63.125 0 0 70.375 63.125 0 0 0 +p 22000 a ff 7fff66ff 70.375 62.375 0 0 70.375 62.375 0 0 0 +p 22000 a ff 7fff66ff 71.1148 62.4983 0 0 71.1148 62.4983 0 0 0 +p 22000 a ff 7fff66ff 71.2476 63.2365 0 0 71.2476 63.2365 0 0 0 +p 22000 b ff 7fff66ff 15.5 40.375 0 0 15.5 40.375 0 0 0 +p 22000 b ff 7fff66ff 16.124 39.959 0 0 16.124 39.959 0 0 0 +p 22000 b ff 7fff66ff 16.8729 39.9999 0 0 16.8729 39.9999 0 0 0 +p 22000 b ff 7fff66ff 17.2098 40.67 0 0 17.2098 40.67 0 0 0 +p 22000 c ff 7fff66ff 29.375 37.875 0 0 29.375 37.875 0 0 0 +p 22000 c ff 7fff66ff 29.791 37.251 0 0 29.791 37.251 0 0 0 +p 22000 c ff 7fff66ff 30.5326 37.139 0 0 30.5326 37.139 0 0 0 +p 22000 c ff 7fff66ff 30.6126 37.8847 0 0 30.6126 37.8847 0 0 0 +p 22000 d ff 7fff66ff 69.75 49 0 0 69.75 49 0 0 0 +p 22000 d ff 7fff66ff 69.8733 48.2602 0 0 69.8733 48.2602 0 0 0 +p 22000 d ff 7fff66ff 69.875 47.5102 0 0 69.875 47.5102 0 0 0 +p 22000 d ff 7fff66ff 69.875 46.7602 0 0 69.875 46.7602 0 0 0 +p 22000 d ff 7fff66ff 69.875 46.0102 0 0 69.875 46.0102 0 0 0 +p 22000 e ff 7fff66ff 61.625 38 0 0 61.625 38 0 0 0 +p 22000 e ff 7fff66ff 61.625 37.25 0 0 61.625 37.25 0 0 0 +p 22000 e ff 7fff66ff 61.625 36.5 0 0 61.625 36.5 0 0 0 +p 22000 e ff 7fff66ff 61.625 35.75 0 0 61.625 35.75 0 0 0 +p 22000 e ff 7fff66ff 61.625 35 0 0 61.625 35 0 0 0 +p 22000 11 ff 7fff66ff 7.25 54 0 0 7.25 54 0 0 0 +p 22000 11 ff 7fff66ff 7.25 53.25 0 0 7.25 53.25 0 0 0 +p 22000 11 ff 7fff66ff 7.25 52.5 0 0 7.25 52.5 0 0 0 +p 22000 11 ff 7fff66ff 7.25 51.75 0 0 7.25 51.75 0 0 0 +p 402000 0 ff b26666ff 55.75 70.75 0 0 55.75 70.75 0 0 0 +p 402000 0 ff b26666ff 55.75 70 0 0 55.75 70 0 0 0 +p 402000 0 ff b26666ff 56.5 70 0 0 56.5 70 0 0 0 +p 402000 0 ff b26666ff 56.5 70.75 0 0 56.5 70.75 0 0 0 +p 402000 0 ff b26666ff 57.25 70.75 0 0 57.25 70.75 0 0 0 +p 402000 0 ff b26666ff 57.25 70 0 0 57.25 70 0 0 0 +p 402000 0 ff b26666ff 58 70 0 0 58 70 0 0 0 +p 402000 0 ff b26666ff 58 70.75 0 0 58 70.75 0 0 0 +p 402000 0 ff b26666ff 58.75 70 0 0 58.75 70 0 0 0 +p 402000 0 ff b26666ff 58.75 70.75 0 0 58.75 70.75 0 0 0 +p 402000 0 ff b26666ff 59.5 70.75 0 0 59.5 70.75 0 0 0 +p 402000 0 ff b26666ff 59.5 70 0 0 59.5 70 0 0 0 +p 402000 0 ff b26666ff 60.25 70 0 0 60.25 70 0 0 0 +p 402000 0 ff b26666ff 60.25 70.75 0 0 60.25 70.75 0 0 0 +p 402000 0 ff b26666ff 61 70 0 0 61 70 0 0 0 +p 402000 0 ff b26666ff 61 70.75 0 0 61 70.75 0 0 0 +p 402000 0 ff b26666ff 43 35.5 0 0 43 35.5 0 0 0 +p 402000 0 ff b26666ff 43 34 0 0 43 34 0 0 0 +p 402000 0 ff b26666ff 43 34.75 0 0 43 34.75 0 0 0 +p 402000 0 ff b26666ff 43.75 35.5 0 0 43.75 35.5 0 0 0 +p 402000 0 ff b26666ff 43.75 34 0 0 43.75 34 0 0 0 +p 402000 0 ff b26666ff 43.75 34.75 0 0 43.75 34.75 0 0 0 +p 402000 0 ff b26666ff 44.5 34.75 0 0 44.5 34.75 0 0 0 +p 402000 0 ff b26666ff 44.5 34 0 0 44.5 34 0 0 0 +p 402000 0 ff b26666ff 45.25 34 0 0 45.25 34 0 0 0 +p 402000 0 ff b26666ff 45.25 34.75 0 0 45.25 34.75 0 0 0 +p 402000 0 ff b26666ff 46 34 0 0 46 34 0 0 0 +p 402000 0 ff b26666ff 46 34.75 0 0 46 34.75 0 0 0 +@ time 7.52012 +@ timeStep 1504 +@ scale 8 +@ timeStepsPerFrame 8 +@ framesPerSecond 25 +@ pauseFlag 1 +@ randSeed 0 +@ gravityFlag 1 +@ gravityAcceleration 0.001 +@ gravityAmplification 1 +@ gravityAngle 0 +@ boundsFlag 1 +@ boundsThickness 0.25 +@ boundsLeft 0 +@ boundsRight 94.75 +@ boundsBottom 0 +@ boundsTop 89.25 +@ boundsRadius 1 +@ standardDistance 0.75 +@ standardDensity 1.0025 +@ maxSpeed 0.5 +@ pressureCoefficient 0.05 +@ repulsionCoefficient 0.05 +@ dampingFlag 1 +@ dampingCoefficient 0.05 +@ staticPressureFlag 0 +@ staticPressureCoefficient 0.5 +@ staticPressureIteration 1 +@ staticMaxPressure 0.5 +@ springCoefficient 0.05 +@ springIteration 5 +@ elasticCoefficient 0.5 +@ elasticIteration 5 +@ mochiElasticityCoefficient 0.1 +@ mochiSpringCoefficient 0.1 +@ mochiIteration 3 +@ viscosityCoefficient 0.4 +@ viscosityIteration 5 +@ surfaceTensionCoefficient 0.1 +@ surfacePressureCoefficient 0.05 +@ surfaceTensionIteration 5 +@ powderSpringCoefficient 0.5 +@ powderDampingCoefficient 0.3 +@ powderFrictionCoefficient 0.05 +@ powderLightProbability 0.5 +@ powderExtinguishProbability 0.05 +@ powderExplosionCoefficient 1 +@ brittlenessCoefficient 0.5 +@ jetCoefficient 0.5 +@ fuelLightProbability 0.01 +@ fuelExtinguishProbability 0.0005 +@ upCoefficient 10 +@ downCoefficient 10 +@ yukiSpringCoefficient 0.02 +@ yukiMeltingProbability 0.0001 +@ resistanceFlag 0 +@ resistanceCoefficient 0.02 +@ fireFlag 1 +@ fireProbability 0.005 +@ fireLife 1000 +@ fireBuoyancyCoefficient 10 +@ splashFlag 0 +@ splashProbability 0.05 +@ splashExpansion 1e-005 +@ splashMinLife 50 +@ bubbleFlag 0 +@ bubbleProbability 0.05 +@ bubbleLife 10000 +@ bubbleBuoyancyCoefficient 20 +@ pouringFlag 0 +@ pouringRainFlag 0 +@ pouringLocation 10 +@ pouringThickness 2 +@ pouringVelocity 0.1 +@ pouringTimer 0 +@ pouringMaterial 113 +@ pouringLayer -1 +@ clearFlag 1 +@ clearColorRed 0.2 +@ clearColorBlue 0.2 +@ clearColorGreen 0.2 +@ clearColorAlpha 1 +@ mouseRadius 1 +@ mouseDelay 10 +@ mouseForce 1 +@ lineWidth 1 +@ usersCharge 0 +@ usersMaxCharge 15 +@ usersSpeedX 0.05 +@ usersSpeedY 0.15 +@ usersForceX 0.05 +@ usersForceY 0.5 +@ usersX 0 +@ usersY 0 +@ viewWidth 0 +@ viewHeight 0 +@ scrollFlag 0 +@ scrollX 0 +@ scrollY 0 +@ scrollAngle 0 +@ colorFlag 1 +@ renderMode 2 diff --git a/Code/Physics/BulletCollision/BulletCollision.vcxproj b/Code/Physics/BulletCollision/BulletCollision.vcxproj deleted file mode 100644 index 28c24c6e..00000000 --- a/Code/Physics/BulletCollision/BulletCollision.vcxproj +++ /dev/null @@ -1,487 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {B84D4C8B-DF9F-4B41-994D-A6FFFA64F274} - Win32Proj - Win32 - BulletCollision - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(SolutionDir)Physics\Debug\ - BulletCollision.dir\Debug\ - BulletCollision_Debug - .lib - $(SolutionDir)Physics\Release - BulletCollision.dir\Release\ - BulletCollision - .lib - C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\MinSizeRel\ - BulletCollision.dir\MinSizeRel\ - BulletCollision_MinsizeRel - .lib - C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\RelWithDebInfo\ - BulletCollision.dir\RelWithDebInfo\ - BulletCollision_RelWithDebugInfo - .lib - - - - $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebugDLL - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreadedDLL - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreadedDLL - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreadedDLL - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp - false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp - false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp - false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Physics/BulletCollision/BulletCollision.vcxproj.user b/Code/Physics/BulletCollision/BulletCollision.vcxproj.user deleted file mode 100644 index a375ae35..00000000 --- a/Code/Physics/BulletCollision/BulletCollision.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend b/Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend deleted file mode 100644 index d667b1b5..00000000 --- a/Code/Physics/BulletCollision/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision/CMakeLists.txt diff --git a/Code/Physics/BulletConfig.cmake b/Code/Physics/BulletConfig.cmake new file mode 100644 index 00000000..2f728869 --- /dev/null +++ b/Code/Physics/BulletConfig.cmake @@ -0,0 +1,25 @@ +# -*- cmake -*- +# +# BulletConfig.cmake(.in) +# + +# Use the following variables to compile and link against Bullet: +# BULLET_FOUND - True if Bullet was found on your system +# BULLET_USE_FILE - The file making Bullet usable +# BULLET_DEFINITIONS - Definitions needed to build with Bullet +# BULLET_INCLUDE_DIR - Directory where Bullet-C-Api.h can be found +# BULLET_INCLUDE_DIRS - List of directories of Bullet and it's dependencies +# BULLET_LIBRARIES - List of libraries to link against Bullet library +# BULLET_LIBRARY_DIRS - List of directories containing Bullet' libraries +# BULLET_ROOT_DIR - The base directory of Bullet +# BULLET_VERSION_STRING - A human-readable string containing the version + +set ( BULLET_FOUND 1 ) +set ( BULLET_USE_FILE "C:/Program Files (x86)/BULLET_PHYSICS/lib/cmake/bullet/UseBullet.cmake" ) +set ( BULLET_DEFINITIONS "" ) +set ( BULLET_INCLUDE_DIR "" ) +set ( BULLET_INCLUDE_DIRS "" ) +set ( BULLET_LIBRARIES "LinearMath;BulletCollisions;BulletDynamics;BulletSoftBody" ) +set ( BULLET_LIBRARY_DIRS "" ) +set ( BULLET_ROOT_DIR "C:/Program Files (x86)/BULLET_PHYSICS" ) +set ( BULLET_VERSION_STRING "2.82" ) diff --git a/Code/Physics/BulletDynamics/BulletDynamics.vcxproj b/Code/Physics/BulletDynamics/BulletDynamics.vcxproj deleted file mode 100644 index fed75f6d..00000000 --- a/Code/Physics/BulletDynamics/BulletDynamics.vcxproj +++ /dev/null @@ -1,343 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {6BCE5708-BFA3-4DE3-9942-E521A8A4EFE2} - Win32Proj - Win32 - BulletDynamics - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(SolutionDir)Physics\Debug\ - BulletDynamics.dir\Debug\ - BulletDynamics_Debug - .lib - $(SolutionDir)Physics\Release - BulletDynamics.dir\Release\ - BulletDynamics - .lib - C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\MinSizeRel\ - BulletDynamics.dir\MinSizeRel\ - BulletDynamics_MinsizeRel - .lib - C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\RelWithDebInfo\ - BulletDynamics.dir\RelWithDebInfo\ - BulletDynamics_RelWithDebugInfo - .lib - - - - $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebugDLL - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreadedDLL - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreadedDLL - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreadedDLL - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - - - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user b/Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user deleted file mode 100644 index a375ae35..00000000 --- a/Code/Physics/BulletDynamics/BulletDynamics.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend b/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 89a4cf45..00000000 --- a/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics/CMakeLists.txt diff --git a/Code/Physics/CMakeCache.txt b/Code/Physics/CMakeCache.txt new file mode 100644 index 00000000..7cd2cea1 --- /dev/null +++ b/Code/Physics/CMakeCache.txt @@ -0,0 +1,471 @@ +# This is the CMakeCache file. +# For build in directory: c:/DV1477/Git Repository/Danbias/Code/Physics +# It was generated by CMake: C:/Program Files (x86)/CMake 2.8/bin/cmake.exe +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a file. +AMD_OPENCL_BASE_DIR:PATH=AMD_OPENCL_BASE_DIR-NOTFOUND + +//Build OpenCL demos for AMD (GPU or CPU) +BUILD_AMD_OPENCL_DEMOS:BOOL=OFF + +//Build original Bullet CPU demos +BUILD_CPU_DEMOS:BOOL=ON + +//Set when you want to build the demos +BUILD_DEMOS:BOOL=ON + +//Set when you want to build the extras +BUILD_EXTRAS:BOOL=OFF + +//Build OpenCL demos for Intel (CPU) +BUILD_INTEL_OPENCL_DEMOS:BOOL=OFF + +//Build OpenCL demos for MiniCL (Generic CPU) +BUILD_MINICL_OPENCL_DEMOS:BOOL=ON + +//Use BulletMultiThreading +BUILD_MULTITHREADING:BOOL=ON + +//Build OpenCL demos for NVidia (GPU) +BUILD_NVIDIA_OPENCL_DEMOS:BOOL=OFF + +//Build Unit Tests +BUILD_UNIT_TESTS:BOOL=OFF + +//Value Computed by CMake +BULLET_PHYSICS_BINARY_DIR:STATIC=C:/DV1477/Git Repository/Danbias/Code/Physics + +//Value Computed by CMake +BULLET_PHYSICS_SOURCE_DIR:STATIC=C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source + +//Dependencies for target +BulletCollision_LIB_DEPENDS:STATIC= + +//Dependencies for target +BulletDynamics_LIB_DEPENDS:STATIC= + +//Dependencies for target +BulletMultiThreaded_LIB_DEPENDS:STATIC= + +//Dependencies for target +BulletSoftBodySolvers_DX11_LIB_DEPENDS:STATIC= + +//Dependencies for target +BulletSoftBodySolvers_OpenCL_Mini_LIB_DEPENDS:STATIC= + +//Dependencies for target +BulletSoftBody_LIB_DEPENDS:STATIC= + +//For backwards compatibility, what version of CMake commands and +// syntax should this version of CMake try to support. +CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4 + +//Semicolon separated list of supported configuration types, only +// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything +// else will be ignored. +CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 /GR /EHsc + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 + +//Flags used by the compiler during release minsize builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG + +//Libraries linked by defalut with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 + +//Flags used by the compiler during release minsize builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG + +//Libraries linked by defalut with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib + +//Adds a postfix for debug-built libraries. +CMAKE_DEBUG_POSTFIX:STRING=_Debug + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING=' /machine:X86 ' + +//Flags used by the linker during debug builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during release minsize builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during release builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/BULLET_PHYSICS + +//Path to a program. +CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe + +//make program +CMAKE_MAKE_PROGRAM:FILEPATH=C:/PROGRA~2/MICROS~3.0/Common7/IDE/devenv.com + +//Adds a postfix for MinsizeRelease-built libraries. +CMAKE_MINSIZEREL_POSTFIX:STRING=_MinsizeRel + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING=' /machine:X86 ' + +//Flags used by the linker during debug builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during release minsize builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during release builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=BULLET_PHYSICS + +//RC compiler +CMAKE_RC_COMPILER:FILEPATH=rc + +//Flags for Fortran compiler. +CMAKE_RC_FLAGS:STRING=' ' + +//Adds a postfix for ReleaseWithDebug-built libraries. +CMAKE_RELWITHDEBINFO_POSTFIX:STRING=_RelWithDebugInfo + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING=' /machine:X86 ' + +//Flags used by the linker during debug builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during release minsize builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during release builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=OFF + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=OFF + +//Flags used by the linker during the creation of static libraries. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If true, cmake will use relative paths in makefiles and projects. +CMAKE_USE_RELATIVE_PATHS:BOOL=OFF + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=OFF + +//Path to a file. +DIRECTX_SDK_BASE_DIR:PATH=C:/Program Files (x86)/Microsoft DirectX SDK (June 2010) + +//Microsoft directX SDK include path +DX11_INCLUDE_PATH:STRING=C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Include + +//Single output directory for building all executables. +EXECUTABLE_OUTPUT_PATH:PATH= + +//Path to a file. +GLUT_INCLUDE_DIR:PATH=GLUT_INCLUDE_DIR-NOTFOUND + +//Path to a library. +GLUT_glut_LIBRARY:FILEPATH=GLUT_glut_LIBRARY-NOTFOUND + +//Set when you want extra libraries installed +INSTALL_EXTRA_LIBS:BOOL=OFF + +//Set when you want to install libraries +INSTALL_LIBS:BOOL=OFF + +//Path to a file. +INTEL_OPENCL_BASE_DIR:PATH=INTEL_OPENCL_BASE_DIR-NOTFOUND + +//Add MSVC postfix for executable names (_Debug) +INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES:BOOL=OFF + +//Create MSVC projectfiles that can be distributed +INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES:BOOL=OFF + +//Create MSVC projectfiles with relative paths +INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES:BOOL=OFF + +//Internal update serialization structures +INTERNAL_UPDATE_SERIALIZATION_STRUCTURES:BOOL=OFF + +//Single output directory for building all libraries. +LIBRARY_OUTPUT_PATH:PATH=C:/DV1477/Git Repository/Danbias/Code/Physics/lib + +//Dependencies for target +LinearMath_LIB_DEPENDS:STATIC= + +//Dependencies for target +MiniCL_LIB_DEPENDS:STATIC= + +//Path to a file. +NVIDIA_OPENCL_BASE_DIR:PATH=NVIDIA_OPENCL_BASE_DIR-NOTFOUND + +//OpenGL library for win32 +OPENGL_gl_LIBRARY:STRING=opengl32 + +//GLU library for win32 +OPENGL_glu_LIBRARY:STRING=glu32 + +//Use custom vectormath library +USE_CUSTOM_VECTOR_MATH:BOOL=OFF + +//Use double precision +USE_DOUBLE_PRECISION:BOOL=OFF + +//Use DirectX 11 +USE_DX11:BOOL=ON + +//Use Glut +USE_GLUT:BOOL=ON + +//Use Graphical Benchmark +USE_GRAPHICAL_BENCHMARK:BOOL=ON + +//Use MSVC /fp:fast option +USE_MSVC_FAST_FLOATINGPOINT:BOOL=ON + +//Use MSVC Incremental Linking +USE_MSVC_INCREMENTAL_LINKING:BOOL=OFF + +//Use MSVC Runtime Library DLL (/MD or /MDd) +USE_MSVC_RUNTIME_LIBRARY_DLL:BOOL=OFF + +//Use MSVC /arch:sse option +USE_MSVC_SSE:BOOL=ON + +//Use Multithreaded Benchmark +USE_MULTITHREADED_BENCHMARK:BOOL=OFF + + +######################## +# INTERNAL cache entries +######################## + +//Stored GUID +ALL_BUILD_GUID_CMAKE:INTERNAL=14E546AD-2393-41B9-BAA2-134241286A4E +//Stored GUID +BulletCollision_GUID_CMAKE:INTERNAL=C933A737-D7BA-4136-95AF-D12310BD6BA8 +//Stored GUID +BulletDynamics_GUID_CMAKE:INTERNAL=74EDC06C-85E5-47BC-B42D-F55CE6E9928B +//Stored GUID +BulletMultiThreaded_GUID_CMAKE:INTERNAL=83B388D3-BE71-476A-AA6A-CC7082E3866D +//Stored GUID +BulletSoftBodySolvers_DX11_GUID_CMAKE:INTERNAL=2CF89262-94E6-4A9F-A29A-1BE6D73DDA85 +//Stored GUID +BulletSoftBodySolvers_OpenCL_Mini_GUID_CMAKE:INTERNAL=80FC7669-D649-4212-8B6F-C0167CE9CB59 +//Stored GUID +BulletSoftBody_GUID_CMAKE:INTERNAL=14DC504E-697F-4178-8E05-87173957FE59 +//ADVANCED property for variable: CMAKE_BUILD_TOOL +CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 +//What is the target build tool cmake is generating for. +CMAKE_BUILD_TOOL:INTERNAL=C:/PROGRA~2/MICROS~3.0/Common7/IDE/devenv.com +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=c:/DV1477/Git Repository/Danbias/Code/Physics +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/cmake.exe +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/cpack.exe +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/ctest.exe +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/cmake-gui.exe +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Visual Studio 11 +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Start directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=12 +//ADVANCED property for variable: CMAKE_RC_COMPILER +CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1 +CMAKE_RC_COMPILER_WORKS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS +CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=C:/Program Files (x86)/CMake 2.8/share/cmake-2.8 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Suppress Warnings that are meant for the author of the CMakeLists.txt +// files. +CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=FALSE +//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS +CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Details about finding OpenGL +FIND_PACKAGE_MESSAGE_DETAILS_OpenGL:INTERNAL=[opengl32][v()] +//ADVANCED property for variable: GLUT_INCLUDE_DIR +GLUT_INCLUDE_DIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: GLUT_glut_LIBRARY +GLUT_glut_LIBRARY-ADVANCED:INTERNAL=1 +//Stored GUID +INSTALL_GUID_CMAKE:INTERNAL=71641E56-5E9E-462B-844F-A9F8A6D82120 +//Stored GUID +LinearMath_GUID_CMAKE:INTERNAL=D4985405-3286-4026-BD61-E9E53DC5027E +//Stored GUID +MiniCL_GUID_CMAKE:INTERNAL=FA9E3157-5228-4CA4-8327-BD0AF11BD390 +//ADVANCED property for variable: OPENGL_gl_LIBRARY +OPENGL_gl_LIBRARY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: OPENGL_glu_LIBRARY +OPENGL_glu_LIBRARY-ADVANCED:INTERNAL=1 +//Stored GUID +SG_Filter_CMake Rules_GUID_CMAKE:INTERNAL=25AA48BF-9AB1-4661-81E4-21DC63B45029 +//Stored GUID +SG_Filter_Header Files_GUID_CMAKE:INTERNAL=DC4D0118-25E6-4CAA-B131-BCA655977BFA +//Stored GUID +SG_Filter_Object Files_GUID_CMAKE:INTERNAL=F83DE1D7-C15C-47D0-A697-3C273FD0E918 +//Stored GUID +SG_Filter_Resources_GUID_CMAKE:INTERNAL=7CEBDF2C-7E7D-42BC-911B-92C65E0725AB +//Stored GUID +SG_Filter_Source Files_GUID_CMAKE:INTERNAL=9B00025E-DDC2-40FD-8DE1-C35F1698B109 +//Stored GUID +ZERO_CHECK_GUID_CMAKE:INTERNAL=53399ED8-C4B0-4F84-9CA8-623049125822 + diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake new file mode 100644 index 00000000..69bac982 --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake @@ -0,0 +1,56 @@ +set(CMAKE_C_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/cl.exe") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "MSVC") +set(CMAKE_C_COMPILER_VERSION "17.0.61030.0") +set(CMAKE_C_PLATFORM_ID "Windows") +set(MSVC_C_ARCHITECTURE_ID X86) +set(CMAKE_AR "") +set(CMAKE_RANLIB "") +set(CMAKE_LINKER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "4") +set(CMAKE_C_COMPILER_ABI "") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + + + + +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") + + + diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake new file mode 100644 index 00000000..5cddd9ef --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake @@ -0,0 +1,57 @@ +set(CMAKE_CXX_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/cl.exe") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "MSVC") +set(CMAKE_CXX_COMPILER_VERSION "17.0.61030.0") +set(CMAKE_CXX_PLATFORM_ID "Windows") +set(MSVC_CXX_ARCHITECTURE_ID X86) +set(CMAKE_AR "") +set(CMAKE_RANLIB "") +set(CMAKE_LINKER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe") +set(CMAKE_COMPILER_IS_GNUCXX ) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "4") +set(CMAKE_CXX_COMPILER_ABI "") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + + + + +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") + + + diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin b/Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000000000000000000000000000000000000..9880b1d79591c82985cd662cb2487c63b47a24d3 GIT binary patch literal 30208 zcmeHw4R}=5ng5x5;D8AUk|?RSqQ4i*gmB6Sb6-}Q5@CN=R7r? z?V0-W+J-{set$p~S|uSE_6uIWP;*m*&>3(`#kslD<|RnK zfAER=$A55Kmkc+(=F&aJ%Wvuwq)Xan>UQ(=LfuZDUZmTL^yfERsQWQbXC%@Bp4NNY zJVfhU&K)+!R_dm(Q?b$dWZg-Yp*vr9K4X=DSTtx?0n&T~2bHZ_K7+9-RK$}^*&qre zG(4Hi+RG8C9W~}@Dj^_aI~X%lx)W)l9Tij0ZpKz)B81f%J1O`%ncZ!Z=jMUC8C&)gsf9c5v7&uehpHByx!cNiJat}_zCJnWLt^H>7FyQtV}KJ(@4hGK}REE7V6aS`P9KSt-?4sK3wqQ$^VL# z#Y3P5J_g(%zRQ8gLy?lZ4so5Qh5%NI%!t&&hd8BzUCU95h!nFe(>nC=Wqiz8ljyq# zWyRQ#2?J$;~l<11F~@CP&Tgxu4nct@R!p7v8?7|(f1F^7Y^BuVL@SF=Obdl zcIZw~ry5_|M`OG*KOznyW%8vSO5>ZgVSv9J=w?O-=7!*;S@&zR zt>ktiqZHB}TB3T*!*u>|A^6B#d@7l2_FzO=EdaE}12s4@q-KDG(w(^7KvAvgj#t>>FO24tEgQoZro4D9%}$)Zz1x zAzl>Q*-5N$gC={vKND(s`5#pkIzG^d5l%4qfz^}Cz=s2hjAm_`s$}&WZnnZOCfeh^ zZ1gmtJ>lE+oN6?eXb)u*MS8eJCF%(l&82uKo3JL;H|ZlEW^J0O*mIPu`wC!V(Hx$v zIS@HaJgY@}Fdr%Z1pX9#Z&h2U^JMrYrAe=3M7r}c!!_VTnbCWDfsp<87t2>^SUm-E zsWh9T^>!CrMy2UVOlJKSj4eKhsocj!nSr4`pOxq;DL;?35Q;niB={eag3aDtk^S8-U@g;h!1@ zKc)caAO6hxF@JXSv-}wx88;%DCAcX^{2gR4`2N8#c^Lvv@G?IpEW7?{`>Ck?sM2(_ zo;S&a4}zV+4Mw({WZ{`Zwj-0;9U0yN$EeiJ>wO#Wt>ba4j<+li>{aH^lf!}g?E zW2O^keXw`SK`7)PwdQ+JGKS;S4{V!Ee8@IPr4*GxLeTuKrP+B{-zdaG0BE5NKHgR}VLo#m}kcAU+1i_eT&MBYj*BLAWmk*nhU6(n?myA8&A zMOtWXe8>8STS-5{{E}c+Nl5Ng#Z5xZ(#*9ayjJ;dNsDF~{*iFa`Uy5<}{+jp* zUjW7HeQCxr#`eFRe}2;#&>@#y#2b*3>?Jf2mMc5#o@;I;q>ii(K`m^7Y$FE?wBf;{^Suk-u@q7qEhH8q zTgF)UynVAE$l>!bh9P7a*69gWq}k89kJ-=2r`XQ`QOBxu0ut7idJ>pj4;HMPrL5E2 z&?iADO{ZX5dH`uKj`(~|ASY@&q1aDN8e-E) z5K8UV5(*#BKsUqZqvyA=l)#z~DAe*(SF)79t)ouk?_yJ-xd74$7`MtziSs^ThuZv{ zz5{x2NX+qBS*T!#G6hS2hI%w|D697)f(8HI+6l|Yk>=+LIywHVz{l|k#_`o6+8Po^ zWG`FvESxcXv0|I;Q0%j?tQSBo`N-$g#b;q`iLG4He`DV<$FmN);Wz~5=V|BzLUGGS$xHzJ*rx?mB*VCeJA=?Yz62mAN}U=`S9$x9280Y!Vf9a}tf3)xskLJsi#TVdv8SUS8im z)b+oW*SDL}7xVfaMyf2$@t9rcBb*> zMnHBn$83A>N)dO&e+iZ&2P;wbj1Y?F47EXx=WMDm9Kb;^6zj_-QYaBy8eK<6)+%)` z2_T-CL6jD(b>0f6Y+C&^tZG?av!L2alNBX4eR6I)QGG(pcHnYs-ABW9X|mSn`zWWf_Mcb{_tf4ut?;9lDmtwc+V(xkDF5Tk3!SDxHzY<%# zP^5#EO}ED$977Z1i^G|*73{9w?ciWrUoOF7D|A2}QGS0{#u93^D)uaauYUceyO!ye z0Wzw*wEuL*yFXA~iu^kBsfW?>-G@@xpNahLL(bvsr|*X>8?Y{w^AYSN*5h}9U6N=* z?%&CrBv8l`jw2tw3JyToqBp*G^&3%?VKCVAjphfl_rb21=}f5TuG!UjPaJS~2GI%J zJIyj?360^bw#})H?9W^_JOrsZ4`oe(r^tzAby05e3kkOu^Yn@GhM~e<3YwL$epPd{ z|LE^jHTvK|#6$f@5Tkb%|INF2gB&G)uZHuQDTCUeT>1>O5SDfNkBq55 z6Iljhq01ey{$n8G!0Y^8qM53XJxFluAhVy|>4Y(m`-uPQ!^EN@&r>)f4b5slj>!3iM_1LDa7cC3E{&B4rJ zVkQAPi&r2=to9F%c=HsRqgnl`d{u+Gmn5Jy@Z>|*4s|cJiuH4RHJqcqahfJoxpW^N zForY@lN#$kIm!o`KunDErw))%e}+|WO6*y}AaNxc9Q%(%1I}Ec!E^5M273uZ6P(7D zryG^c8bhmymHTM?k%P0fcW<)VwPd#C7&A9pKHpjA*q5-C?5jzi*LMixXlU+#Ew67U zjfkvjf<;wxi^{vR4|OT4%8flV4`mkn4#ju%KJzEr*OC9SeX&;Pye+GtBU3G>K{(>q zU=Al(mk5^lxYZ)xJs4z>hsSOnuj4W81l6L|JTBvLCF11zY~p+BaK^g_PA|sdjdxA+ zgxZ9^DwrhCt)dK5WO6<>irlsC!<-Qlhq9?c7uRDlNE_o|uG!CF->HEcCh4iB!SS~;NL6#ts?5W%3aixDqx~nK z9gx)Zo;^uOT!U144ksZeHOLjPc;p;(9O^laN)MRas@|6%amgwiB7*kX@m^mAIt?z? ze})<+rXkjUij!fUG7|A#B09t|^dP9-M+|6C<&1hCb)KM%P005n&r)Mu_*+VhXuh{! z7yi3fPe(q;2;RA(y=sr0COWUb8x-0j&)9#DQj0u&UkhWbJ=(`>7vqTJ>iv3Mh5 z0WG#TS0w+Jcjr=+1{@ey0&$>G%a4M{z-lc&M)?*k&mhx*by_})@@_4!N4|Z)g92AS z>Nf|VaW(rH-%njUK6BGM^vy{fMJ26Shag6HsjuU`VX}JA{-Spz2kv-WKd_`>ZOZY` zk!37KBB)E|$zGEA50LN3jM>lDIpX`cKc9!GpOMnV%MzV=JeU{ogSH)09r0d{3VRCw z+_O%rK@S~Sj`;di&C{v5rB*c4=nNaQvkvU;n&UM<#Hg@N*9 z+(*X_?Nz$)o62Hy|KQ)g)@#<&aYJ*gOfT!#CfepbSzD0zWb>5B;JnO3tFC_2_?}Vi ze@(tf(VN~3PF3E$`gf+)V?q70$lwCghr!dP59Kw>wu)hLU|}I5cJa*h@j~#wiwY2- z`A|01>xQ!j2;$iRDZxpRrJ?r!#O!D4XibaRkMk6c1I!Qn~~!Snk5orG>5>i{H%vsP$QWTu0B<|7abq_YQ!a-3cYwonuM7{-!dfbW-ZQgec{E<3IckC=?X6*&3h2ScXA z8>gAd4g|BUrv1V9l$rxLVk)3EMd%DkRHxX_#;`@y)nfyoSi98l2^xirldL#~jt%HI z8@q`OK7f2>O&kqrC{~;gC^OXhN(i6QYn*G91Bqj6=&QDU+I4Rqc5}LTD3jKkEEu69 z-l^pyBGs|*G*mZgAkWk+HW+Wv3KL#;HG7^1c*jNY=a4{S&ie@*A$$4CUEO!U8|BIr z7j{v6sgL4v55=Mzar^ed9X!eHxu0OAXB%E*L%rJp zA-T-6s;*7g^M=kj(Q$$!@K{F;T6wuZrEf%zBqA#!$_P;aDO*D zlgsD3pbzcYKj8 zIc#HYWJ^9y0EcWjm>?Vn=1ku>6|ZKI)4C`wBbss|&+DRvq#OIV77W6+^wDi3gT!gf z@KhXz5*9xLHQ91Pg=BtI%2x_@LKnpinKMHy^c#PJz@SI?zyy$WN<9w8K)1=$t?;qAiqKL~mV_K4Mhrwgo2I3Bb$7c~I_sZ!sErGNI(h^8ZAT5Ek1kw^nOCT+Q zv;@);NJ}6sfwTnD5=cuRErGNI(h^8ZAT5Ek1pYfDK(`j@CoO@$E(sWBSpT{hPIH@< zz+XrLJM*o7Ak%5LX1tDmu#%5(40Xp) zx8layo2oQpZ#9&yA^hayWKQO1E+#WC+sGu8Ldd&V5OJ7wrOGnu1SaB7 z0L%$&KLWLKF(2aFQSS!PBDANcomI0IK-`EovNm7_@aIEq3ra-Y$y!mS`ViXs(89^O z@mY+D6b97NOoOZEo* z#LrS!NEYOP5bAXKe5jRsx+HuVB^>hl*9*QtC?o{hg~T^CG&-G9XCT-!k<7|Ko69F` zbOpVxR-Yt*krO}dvCFI?Z`dlvi8(9-ui9dl|fj@07J|Fu^U~a~r@EP>Ax&6=5 zpNxH_#ysLLcHT)ZCyq{=`}XPRuUt&}^2PE++D|j%gKoCNN-7gt$uN7Q%`#?8LX8VHe{FhS|WFiCf1k2J3G^Vxi1lPff?$i+mWaWV>U@b#fqi7boT$R@As z354kjLXL%K9wFq~2s?AN1<6QVLVMWXMm7fH z_4$egfq&`<{e?qe0D6ECltN*jO!Nqax}4C;Ew%YvK@cRS1Sm)fsV(5&DET>QUN@mp z(xpsp>=NAG_I4?VMxQ{Wcp5$oz}R9`X`aWG@;&5cGza7%S;7g?04I4N3~WWaAk$}@ zNZ#bpIBPE7H9}7yEQBCXpIhj3g*E_75<-D+u#L-*O1w)x2r9X{NS1I~vLv*6WoiTR zwSk}@b-Oydd{VU_Ov|0x=5fJk3Zk&UD_kKMx@&8%G)>E0>T&tklMFdsd^CzaAeG>& z2SW7u1ez@u1knZui|%g2Jb2|El0Ox-*&qr5IO9&NL~f`LK0c+%XOgd-q*_V&k>{M? zbqQyZ=amx@N;qK2%^OaldyX4Ex0@#a27h3aU#Jg5#+{O|)FWXXu?2&HpvDB|u^yI8 zR_bM)uw;QP#Xox>i{5~|4Yo_x8-y2_#&Q8^0@L>U91P?de#Uk z0<(io2!AfN9yxAMss0uM=aYJ@1-2KI!swHFxE$*)tq}_mv=ulxrdqF0^1C`E(#0gq z9&m@Te%(l5jCo<>_@HZDUSAmN+2uuUVWChIO021gwG>n5m!Ku#gus$ZA!rvBm#!9& zhA|QeTp3v@#^MH#K0xu$F+EYT&LGdqcO7kVQF$?{u!G<{1MK5Qbz z5B?DoK5110gQ^zHJinMPwcL#T;m%ep^<)T1rA-p47N}hVv=O;!i`{N?7pjKV6AgNj zKJd@vj}?XR*M;D7BSHXeV%j1=W>kki6yYb5!u-!W&jPeNpBmFYP*U@docSuH>Uj)W z)qu~3)!;*1CHOO7E^7F`fsm=L8M;@WsH>SUQ;UJu%od~Vio_g_x2u=d-_#}fZ;*Oy z-K#(c<+`vG>}htve`_FuEyZ?90uptFo^E2b(Bf5~Sr1ETLGNDJ4cSWwp&i!If*#2> z!q93TTF}mutR;XN;=UOCw*XG-D(y)LA6r{c^J8!6<+S|VF3Cb`ID~AI>@EmfqbE6v zbLB#Hp9FK%ETOStX!HR!shseF2=tEx=pPR(C%~Wh&?f-&@brYdZ7A4X8zfpr6WPYju9h09HN3v1t+O%Mvoz4zg-Tnu)Ml(Qlp4#f zD=RB4?sB(kj9r3+Li+h^2@HPav+L8fUk(X4(&ye^j)_i>@^dAyHEj!@E2A$90{#)P zN@G2kNU7|fiGOE|Ku@xM_k?=eMONlRm{@;gLOsEIFR@aRYX8iH`sUeI=0*6ldi|wV z_7#Nm^XE%|_N6q3^w1X;AG`RcH3U01{P{hlDg1Agz_A_UT>bv<87sR7-(sHtJBqKJ z(KqHl>Dh_8yAU=b_z-SExDjCq!ZipNB1}Q}@IHK63*mKyLkN2ib|UOR*od$W;d%rE zf`G6GZT_66>t4q0K)45?9bq5BVT9ud|AwGPAFGjGk6=ZpL?}RD2=71!ClHPz97K2m z;rj^N5$-^^9U+LY7GWhqHNsU0vk|5vJOUbHkl`2cq~-gUmG2szb7_5}v%YbubH$A- z8gaCEx6Zk`txLvRH*Rv-k_@M-Gqm1GmwC`$ozuBq!Zn81?+UIDvBC_eGbG7QTyr?- zR+q6>&tzql zr``MlLSh$b{ow8)*y+N}MlcAC&2-Xr7MSdGO6r%dkHjfnF+R={J4g3`y{umyG`PE z+6mFH$1|PaZv&f~?F{>QZZ-PAy;q>k>26)mUI7iz*KR`Dty#`QP9$D81~y2}O)fb^ zcjSIPYB?D2wRbr~jO`-1P;XAH?_in6yPv%>Wm8+It*eKy_GLRab>e`e3nHQNFHjD3 z;Q}ZD*aE7!pmo!M$$Ba1^aKJM@HsVYWFH?E`)94DF)0g2Fwlmhd1ltx{B&*P&~Eqf z|5Wg!XNMHT{d=d&-zM={g|^JgScZ8H2kBle(RziOEtmjp_eyVT&=u5<(PvNbh2$V^X%^!H>Jw|Bw;p+v77s>4idN;yzua`op%8Au;(Pi9W{D$#+#vd9VG43_) zH=Z{3mfce^L3H$|+TORkNz*R$WWV9_g!-dMy0{Kfhh9uM|o5E`tqLgZUh=a zYG?I*)!(juqI#@4!=yJ&Hx-yJG0inCFkNe^Fo~ub(+#Eu)2*g9Q-DhG)PpPMc*3+5}#*O*JqmF7j}TC?5UXuj3lYWA9MGxwN#&D+g)o4;uuF#n@@(ENh= zLo*Ynh&kc~;w*8Fc!ju7EE7%Q5^;rCC*CZ&M4xz@xJm349~TdbzY|AAy=A(kz;cO2 zuv}re#!_mjv{)=Pmg_AJOS7fL(rWQo{1(}AyJf58YnJVndo1@`zH52N@*~S`3+&xN zzkSBqtMX$ED)s__P&)e(uhZU6i)gVaFi(a%;QE4CbQak*TcOR`hjW+Fh|FzG| zBtg-8TYK;8&pG++ueH}+d+oK?T6>?phlBmr?JScqmW80IjO|5AkCn%tADu?^v{}zg zW4oukI(x5f#jCR$J>HPe6%4Ekx;lk6m){?dg;q%jhW&!qFVx=LAan-YQb}Ik)Hw;# zA060T|Kua@=#t^)H`;Vh@bbGl1?i%;>AGD!E!6GcX_0OZ(qG(Ir27d^FHEEt@wDFC z<{?_=;@n|lY=tg|{WdmQpTs%AGIZzb&S$I&5Q_%wDnwd<;GnWq%V#i_Lq$BvlntUl z!o!ovti2qO+EHVkrV;`&ww*CEr8|%&+EFp}>|$&cCPY}Jv6F(ImD$xcd5#{uhq1Ni z95rJlveYeu#!Z!oh%XxJS^WzjQ4(~!WEW%a&PKfh;c^7dFw(?hMb{-78he#!Y(ao* z*cyZhkCm~(60e51P>%|XolQkpi!kA_5?(MA#E>+Z>_CPD+<`FRu~NT5$rk|P&D1Ys z#qqi(AR%jIY|&&$x^ylH9H!?K37h8*Hz^}^L$)z0AfZ-@O`re5)>W&lEYm&~wT~&b zG37U__iN~%inoY{UMpkaSskoHhk(C>*#y$XU&53*;(v!Ya$rWXJ&+P;@ke+~VX{Ue z4SwQPnT+jR0U8}TwP?q^RnfTEqxAyV>W)GI|EU`MA9bWtI% zg$nxk@1`&oKTe&9Yzy%?&2xH&m8nI28p-%t=w?LBLY*2upE}s8RTu}yhYNl@1z)qW zcnH+M$ABBecRCPxC{ps)BChk)62MB48IfA_FsD?wa~Vnzkz%%aYKK0)l#e-U5`Fi; z42V4eLVq29@(5j^G>C591E^w-$bpj$%_|3T!D^{()cBGkW;^ZPNmWrPo|v~G+ere% zf2^viV$F)$P7K+O6GX9}c;*4f$~bsB|B0zl+sVl0lT5x)v7I#8PK2ibi~PuN#_*dF z@loLE!nqx@;tyr=@ebdp0a>_eD4W*;*E4e^_{(j8SXObd==%rdi-v4Rv7j)p^Cx1# zcJx#u2oFyk%C5rrsgET6nI3&T2rvf-T&5Awh-ajbGUU0QZs?%r5TXv|`B${}9HD%M zTJ#{7?u^K&F04Bo*?gRZrx@SZOJlsNAR-PTW%6YnO5>ZfVSv9}=w?O-=7!*;Sr2Hl zt>kqhqZH8;LWL-CD0wuObxIM`Z$vUAwk&)aX+bFq3#WtG%w7&Oa`>ha2mT_>{sWgoOn7POtg;m?f zdaG%Dqi#mDX>9lc zOkiYC7sWJU;`hxX-_Mb9s%>XNR{*Fq<(lepgBQ_~uq+n}lX-)_+MXNA24FaA_-Dq! zPbmQUhd;A^%AXziJbwm9#*K((32w>}e;*kPzJD-GUWULEyv$Ds%dWr1ellu5qBI?; z=S?!9c+lEu~r5R}c)6;uDNtv&S z1aBYH<`Hw#Taz+h0cIT;oWUpW3~!aP<7}>5d}h>Q@>Xgw`4_dATov!HFrgFNZ7|j= z(n537`_^aWS$xeYW_VY?ijha~k6w@F6(BwJT?{PNbf#V{I)Q~5%A>Jtw2wk_)S{CB z8f{|$szvcsKGrmX1|z(|n9(+pY;&4x+gQvtW;_CA?A<&@{gYhBZboMKGK{-9VLt;z9jnrDNLX9yNnmz8Sg>-IvQBM9 zAJ~dCYa1E}m^xKBTbPup`@gVW(9sIto=7 z#)2@SFyqU;RRqkxZ=bSHbAH^@UpCe6G)%?DBKx_6eXavM{Xe}nR z=ny%+)BPWY=cq+TkdKV6%O2n2%*U^!+Qr$xW zh-YRHrFm|OL{{%tin>r$&o_yVp8|@_H0n1d>$&~*j_A?J z`20o0nIMZ77CkH~+CTaSn!BH&?UowW(461*Et2jlvDD z8C71{cPit9N0e70zs`K-QMCNv;S~1gB7g9(b2$6i2O!G^tV z_cA956!L`QD1fhm15h^WjUQg~Rup9z3^skE1;OmSuq$Rd9V)(iW=;N6`yHM^bOQHI zvy53nV>qj=vzA2mWiA~ag4CP`vvS}ma${Ltl$-oQ!tKR8ZKAwksIZs9W+kj&*&OXZ z@;gWu5vXW9rXE zmcdx)3P-H}D2O=lI=_c#rs`u45ga?n>}Pj4VGQIx;=lSNv8c#%6wXLPvs&ISV;&sw zRtOVv>>teUFM|G*4Gw4Q(nX%mNaLFms5Q zNr2Aa703}=@&`w}Ifv$GM!zaw-JtFv31|&G1(3Bv-9xQn{TyEn=c;d=qDfUQ+sg-x zAx*`k#`;f;@_{B06C?eZ10>X+W7W%vJx>@Uu0(^Q|2NTqGnZ)af_uEd9>UNBr?KVf zMrE_c&`M(Eej0z|z)bDko2+&XnQaBe%*~e1ch*_?G@!h@8{n_?)_&;r5tQ9(M%WCMzR4Zr@j`+2h z!wJ?Uf+ap~wb*wr23hRkv75(hc}zP&wRjbe%XwUdIJrKX_?|kP@xlI63$b|PUDG_F zHsP-dC&_b*D8m$)T!4)tcddIdXT-$8Y^u=3^_UFO#yFU3_V_Rc9GO6MlnPpYpcx&S zLdHl9>fpe4XyArPda7w~{M`&v)m*eH_b}}EI-q!(V!lazM9@cSDGN{U&`+uluk+9W zFf?sb8@ND=aML*UvWccbCo>5?44=hELyC`2b%M8MT0gMJJdTxT;_8u*-yF0Z_xJD| zB!`vBm3b=(=;z8PTusS1bJIN>Uc^^qs=L5x98CDsrHO8ul?qy#Jr9GzO7+cX|8Zys zBz1#lcM=lUAXT12NyrHeawRMtIR_nwdXAye117hq_a{hPx)O(opuJ|i*VlnggNyZ_ zriO`Wi1nZ3WSFO%M7)QH4si@U2&(rJ0~%C0t=>zR2jb{5$J_ z7F(DnlK;!UYcWa#4vZ^-IMAr&M?qv@m6ji)e2bQ6km}Tp6@x9!i&%xABPwC?2iOxJ8%nSHI+m0!YcrQnVJ%xYa zS*z8chmI^qd|j&M+0@)pE1GF^h7H;o2X=SO@me5aR9HYhI`*|eYOMC?8z&JJYJMpnhp&aGvRt;3?B5^6I5q#4tIqun-Zuc;<$95%}Lp1&Gjm zFq`Ui!`TA_@oa~b;H1dXQ2Re(_S1E=rp4^XcnZe>=8r@U2pG~7EJxa)@Wx?$SJ6dR z$JGLH;XP%#{Qk|DP=N6stLW-I4})xj>X->H*4M^sPBtjIh6Xy)XkMv0KrX*;5wAEC zT|K7gVmN28dg|39eW;ktE5>N|eGz4Ksso4M`F;O~gl-?}03?R9R%>p33~$4+COyJP zJ$U7<-v(Cx(>A?nD2%Pxi0L()cG^y4?lYYZPA7fUsD+<8wS&mnMv3wx$ciwkS@{t< zdD(X&(?LG-F^C1y*^NXwMlS`Msfm3IV@WW;_e(gbInG&^9oK|MOvd1Hoc!^FA=9A^ zQ%&XjgV|QozTk&S?S33F6;hjGbcQ6VQ|xDA*dprcu>nx5U26C^jY7srRvbge26UW_ zUBm_-K!LJ4j)pW8E6xX$>1urygiqRog!8ysrR5Oxsv9+sXG#_uj5lb739q}FJ6y<^JO^|Do(dy>#=TV*^yVvk#@A>~6%w{!sQNUW?if1`DY%(BUoVdVYBu*u`znhuK z<@0^ehkUYeJoH~Jos*Exe^w^gKt}H&v1sFc5pMG{$J;w1XybbU+WFr!z7t z3JyaFi=Tm-Y`LK#GCwL6D23ajg|Y2G9)3p?S!(@Li+5p{sTSArco~mZ@YuoQMjq1% zo?1M@<2aA$Ojj*F!DBioREz1&M=hpPAhnndG}L19(`qs8u+(BYCs2!N3#As*+nQQT zuQ0ez;W0T2+-2~XmL%L^@R+uNxWnM_8N|uGaym^*AT5Ek1kw^nOCT+Qv;@);NJ}6s zfwTnD5=cuRErGNI(h^8ZAT5Ek1kw^nOCT+Q{|X7vtws7tOWY) zSCYVv0_$Ii^4}2IOVTpfg@0q1e$o;k2_(OjK|eqGIzr<*ga)b^ucIHV6d)W$-BHvn zziG+MH6iaEQlQ=G?vjJI8Om1^e)4fLC-XBGlbM%oU=m6p6Y(bi z<^;AMfm*qk5AhwScY|m#+SAj{YFG;(Zp0f{8!!X-^P#o{C8F+RtteA{2yK06;bh(T z97bgdgKC1nPPULxFR>Cp7^}U-%GM%mLwFeB2ttGGYFjUK1-yP)3JPt3U@+Vzdjo#r zXR#|J3vxgRb-H{$)XF_w626QQ4tf3S1YaN&5(4c);#(RToldDU5bT*qW<{XQjfN{22>acF6Mdp>l9oh*!h@ed@t=}q zBBkFE(KC-rHvs9F88arK#swSlq0|LEmY}y@)Oz`dk^*xA zN+XnkLH0q^h{inrw*fFOpZ%-ZRm^~JE#}Yw%`ou4(nM-F3vNuoX=X<8?< z!t@0q0;Nnva-+4@))$t@{%j2nPM$tjgs&HMNkLza5OQsRow?eAWTY;kJ?w8I8-wxs zd?kXwKXruu!l5t#J-`S`p|DRTdW1q_le`cHw!B@C=`&6w zZ}MoIHJ9&Np(hX)LJ+9WEp)m<>wzT+p+Gp;#$`w)-X$Ldm0VpUOE@iA5?Z}7wE_7h zfuJCDyE?mkQjH)?&70EZalvT{qA<@ZTqzj3mn^x;G&OIr$K_u~GURme(J1n9|y1O0o;FWtw{#4XvgD3>xj61OsxuHJz_>?A}NxpWHY9-}Io^yiN zC7el~S58PM;eaJKZ#aqWS#J33Zkqh-{eg{sp*{>5cS^!ykA!u^77PZ08WWhudRQ`9 zsh4%ak_EOH|LlP*dOh+s*e+Rb5ME#^%LAkdxGuiF5ia>K0ai@b-vt|Yu^yD`StFkDH&yQ0`F%omD7i8VE`mSXDs60{_o5Lj|41nuIIvQ+}o zFh(MQDtsWP&I;?=NIy&mYcCZ+}Vnyo(v(Wv`Hd00<~*^HX=85q1%n_LN(BOqCrp6 z2mXcpvEmT^x)6MBL_Y9a8N*+R5ko|wb&cJhB=t+*^ zY`IX~XTcn`i)gGE8htoTsvx`|0{tTa`o{yy2=He<^hp5b9bbR{OfuVjU_u7E{ddnmBZ{$4pziz#MhffFm#WgLp&86knU*EFSD+~2fS0Ln-@vhfW>+-jH zU7?o6*q^jGJUtue16EDm&bq0-hZwHdEB7>v~w zmBz}FE_bWO*riA)q@T~1z~I+Dzdl|2)sTQAeeV6$nCSE~ z2nf5;<}Z1=?qlpugnJR%5%wY+LO6!-?+AMIu?p!82v&qDghB*{@IGX49N`GU0feUz zeu%IQ;ZB4*5P}G65LO`6AY6?w6JZ*{W1ukx8Gad0TE2f>`L5PE7uPpB>l+t4m*2F! z5l4&n=$xzCx@5d{<0h9a%5b_mL+hM$nFsCFIi2eyTw{3suHd>5E6Q*>Lz3*oHHVXK zbs1{~y`Ws%x{hA$gEHuaIHW<6`O*GjT*}HUFGr*IScXRUmJDZ`23e0>z~Am&Cwp){ z?dBH{61!OI2X_y_P8V)Af)GsVXV}kktI!ATy#j4cck4R#8fbvNb`#2O%W@`iBJsK*uwHU*bjcyQ zBlq)B%fW!Jy~`P5Y$wTudUI-h2g^0y{p_`zjcuW}t{%eLo9*1#i35@@h=j`Tpd9ML z1yBO88B}pW>!t&fbyCpj2?W;Tb86biK0PeDtJl-R|T6 zr{G7=4k?KH_fD6;P2#f(ZJCp?6!RPo(!E@w^>R0xHv!tnrxieUhM)~SAzA9AOOS;j zI_IGryI5B%P3$j{xje*AeJ}_I-AzD)mSxquydfO@B<6(X7xY%(!jE4bF}8=w#6;qT zfw31eR|H({72ejME2tf#&&=_K$*8f)aG@nIsPoBVjQ1WOlPRDC3%ri;%u?PM8Uv*k;1l zu82q)bV~$IddH#5xGDm+6*5UkI1pSSxn$fNC1rD?t^Ow43S${p?k~d$r)i`m@RgB( zj?KVW5w=VoGJUcN`?Jr0ZrJv80fO$c8Cw^5R1w;5Pi8!~k#4uNo zXobNq6~wtsjZ5ZN%@sm2T%C&+PjPOK6q>uhk~h`t3WcQ3R{YWg1pFa!ZaC<#3AK47 z{H|htrSw`4><# zUe4R0Wk_lZ2k|?LL>Z8vbbA=RNNz{ay8)hiofJw{POPS@iZES}uaGuKKEX$^IM)?g z&i4bsxkA{xu#Fa7ac;ZI7n0@**QMx~uRC`y=IbW$WWFvnI5an3my{a{pF1<@%CrQ& zf)XgeehPkjo}u0#8UE4mgyA{EKEpx7zZhOOyk+>6;iTb1!=DUUr5BW5R$5-Vuyjf3 zjiq&^D@$8SU8U-7>GP!@mCh0r?^aoR(*c`FrMnHfM-8h^xgO@#~@@enZm|Cu320b9r}pU-?7jpOoiRTnNcsQ&C#ssA#HKSJ6}Pt%}Dg-mS=~ z^jF?d`HjkZE5Bd)tm#`q1^U>$9t7L2}=$da&w8RgYIaS@lfS)auu(k5#X# zan{^l^WB=KYQ}0ZOnTEaQ=#cn(`?f`({-jwlW3|n-Dqks-DYYt1-PUlrkLs5rhha& zV>)d5h3QhWV7}6Pt+~uxWnN%jVz!$b&9|9b&0h2E<{oped7Jqj^S8|d=6^B|nqM-1 zVrF8Fm@8f&&JbsbSBmq+a?vC%5|@j0;w_>}^oh5N8^vDnN%4UAJ8@LhTc%kGEtgsZ z%axXEEoGJ}i^WoFxxwPFG+SCMtrm~PZ;>r`ShiTcVcBN6*Yben`<90-Kep_$z}_A7 z+h_a^y0oCYuwq7~p}M@fs@hy_t!^=|HM`9ov(MZ`zwla%Ga@99LPJN4r;U13p#?t) jVlx3NH&huK4XX^@hWiW;7VxyFP(h~Svkih=~1cBJP literal 0 HcmV?d00001 diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake new file mode 100644 index 00000000..f71ace0e --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake @@ -0,0 +1,6 @@ +set(CMAKE_RC_COMPILER "rc") +set(CMAKE_RC_COMPILER_ARG1 "") +set(CMAKE_RC_COMPILER_LOADED 1) +set(CMAKE_RC_SOURCE_FILE_EXTENSIONS rc) +set(CMAKE_RC_OUTPUT_EXTENSION .res) +set(CMAKE_RC_COMPILER_ENV_VAR "RC") diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake new file mode 100644 index 00000000..c10783ee --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Windows-6.1") +set(CMAKE_HOST_SYSTEM_NAME "Windows") +set(CMAKE_HOST_SYSTEM_VERSION "6.1") +set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64") + + + +set(CMAKE_SYSTEM "Windows-6.1") +set(CMAKE_SYSTEM_NAME "Windows") +set(CMAKE_SYSTEM_VERSION "6.1") +set(CMAKE_SYSTEM_PROCESSOR "AMD64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 00000000..cba81d4a --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,389 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_C = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) +# if defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" +# else +# if __IBMC__ >= 800 +# define COMPILER_ID "XL" +# else +# define COMPILER_ID "VisualAge" +# endif + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +/* Analog VisualDSP++ >= 4.5.6 */ +#elif defined(__VISUALDSPVERSION__) +# define COMPILER_ID "ADSP" + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) + +/* Analog VisualDSP++ < 4.5.6 */ +#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" + +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +/* sdcc, the small devices C compiler for embedded systems, + http://sdcc.sourceforge.net */ +#elif defined(SDCC) +# define COMPILER_ID "SDCC" + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + +/* This compiler is either not known or is too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" + +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#else /* unknown platform */ +# define PLATFORM_ID "" + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# define ARCHITECTURE_ID "ARM" + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID "" +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif + (void)argv; + return require; +} +#endif diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj new file mode 100644 index 00000000..cec63969 --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj @@ -0,0 +1,52 @@ + + + + + Debug + Win32 + + + + {CAE07175-D007-4FC3-BFE8-47B392814159} + CompilerIdC + Win32Proj + + + + Application + v110 + MultiByte + + + + <_ProjectFileVersion>10.0.30319.1 + .\ + $(Configuration)\ + false + + + + Disabled + %(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + + + TurnOffAllWarnings + + + + + false + Console + + + for %%i in (cl.exe) do %40echo CMAKE_C_COMPILER=%%~$PATH:i + + + + + + + diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CMakeCCompilerId.obj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CMakeCCompilerId.obj new file mode 100644 index 0000000000000000000000000000000000000000..85a99d188a255624c75ba9a1daeb3d8125b46465 GIT binary patch literal 1497 zcmZ`(OKTHR6h70jX%%f#e9(o9F;q~HF^Q$AQA(OeOC;0QJX&q0#%VHXN1IHTOlvC? zy3-OA`~!k61@|sQL>F$vzu?N96x_K8)N}5=(CKtINdfj_QR4A<~T*w11c?E@%b zBg3U32Eos&(@VUC_^#j(j|_P+)it+Wo-+Rc{RiY-po!2q3XEhv9z|#K!Hyo zCoXuj)tDdWBVN9jmqE_LF`l9**ORH4=|U!-NynoBEw`A+=97V5bUu@uo7PgffI|ED zgY7*w8>A8JAQ9D*i=pvIM4z=>C2Kb9rsdksj-E8?tCrE!6L!Va7uI*0Rv8n`cx=vC z8)j1vtCMOdtcH{VsH;aWB8sa0Q7ycuYpWa+t?`Dj@zSESRfbnwQ8;Z|*@R$Q{`75hn(5AhnqDX$mr zO-^v^Bo_H#6#Wp3#?kv()U!Zo%XFHST`vZig(4~sfVBiWATEFjpOSQkF zVTZH98**}LaQM@pthM*GcI!Mt3W)T{srG)V-8#b%4UrMK(B3b!Tf~3PQC5SbUn^hF zA~J~02ba-Pl@B85hgqbdKg}X^%+8_ri5P&^^+AljoN8672S4EOkY0JLY8oyc=9L6{ z9O+gXy+&Cgt@T>B%18{dL^|uWZiUgKl_k;`MZxXeFC8wuNHQAfgR$IfD10--^uns3 zTY!Ei`JR(ouhm1J1CxA=X=!&~%9%p|PJ~MIXY;^hEoC%l|hz#Aj?k7|t zWz!mO_oiNAhgPZ?R-K2?4~kgb+a>9q@8^!-aHRWBK=&j|G%I~^ZoCHIzQ`E|zeeZ3 zFn}Zft7?cU#(`&;m8^QzE_u=ssd(Qa^YkN9k_?ne*?gjuu3K*0XqqC;t#7(0u==sl Mqa*Pmk9D-?e@N^GGynhq literal 0 HcmV?d00001 diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate new file mode 100644 index 00000000..c6df3dc3 --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate @@ -0,0 +1,2 @@ +#v4.0:v110:false +Debug|Win32|C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\| diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log new file mode 100644 index 00000000..51517d68 --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log @@ -0,0 +1,17 @@ +Build started 2014-02-10 09:29:19. + 1>Project "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\CompilerIdC.vcxproj" on node 2 (Build target(s)). + 1>ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\CL.exe /c /nologo /W0 /WX- /Od /Oy- /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc110.pdb" /Gd /TC /analyze- /errorReport:prompt CMakeCCompilerId.c + CMakeCCompilerId.c + Link: + C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:".\CompilerIdC.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdC.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdC.lib" /MACHINE:X86 /SAFESEH Debug\CMakeCCompilerId.obj + CompilerIdC.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\.\CompilerIdC.exe + PostBuildEvent: + for %%i in (cl.exe) do @echo CMAKE_C_COMPILER=%%~$PATH:i + :VCEnd + CMAKE_C_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe + 1>Done Building Project "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\CompilerIdC.vcxproj" (Build target(s)). + +Build succeeded. + +Time Elapsed 00:00:00.23 diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 00000000..e8220b26 --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,377 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) +# if defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" +# else +# if __IBMCPP__ >= 800 +# define COMPILER_ID "XL" +# else +# define COMPILER_ID "VisualAge" +# endif + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +/* Analog VisualDSP++ >= 4.5.6 */ +#elif defined(__VISUALDSPVERSION__) +# define COMPILER_ID "ADSP" + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) + +/* Analog VisualDSP++ < 4.5.6 */ +#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" + +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + +/* This compiler is either not known or is too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" + +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#else /* unknown platform */ +# define PLATFORM_ID "" + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# define ARCHITECTURE_ID "ARM" + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID "" +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif + (void)argv; + return require; +} diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj new file mode 100644 index 00000000..9d0069d6 --- /dev/null +++ b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj @@ -0,0 +1,52 @@ + + + + + Debug + Win32 + + + + {CAE07175-D007-4FC3-BFE8-47B392814159} + CompilerIdCXX + Win32Proj + + + + Application + v110 + MultiByte + + + + <_ProjectFileVersion>10.0.30319.1 + .\ + $(Configuration)\ + false + + + + Disabled + %(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + + + TurnOffAllWarnings + + + + + false + Console + + + for %%i in (cl.exe) do %40echo CMAKE_CXX_COMPILER=%%~$PATH:i + + + + + + + diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj new file mode 100644 index 0000000000000000000000000000000000000000..e9dc019ebab86370e9c0f0ebc72403358ab001d8 GIT binary patch literal 1495 zcmZ`(OHUI~6h6a1!6zl^Lc?Oxpkg#*TONgKwDd)qv{3s%V%yZAozhX-X=VlxSGsUP z8W-%{_!ImA8WI<7OpO1)jXOi)&P5HLbMH)5<869FcH zi(EILqdBV$K(*eG!7En z8Y197l#M~+F5*d>Lp&1XMPy5TVeydZH0qDYJ41<3$ViZVDjQa9DwTP{KvcsxZsO!^ zn@2~DcrhRG3WK~k@8un%KYq4A*?i)l`)A5z1Od{`-Xusb$ zKHxAxm_P%ua5=sfm<@%>%bF$S)Q)aymTv5o<4Su&Q_ONqudC&3bI;Uj7-W>^YEs)$ z&2ms)kOM(Eh=f)L5hGQPt*@8k^a(f*!;?8#-*^ULxIZEI07ilKZX7}1X0)22n|i~N zrgOKX)sCgLw3k|YQ*tuUSx?J31U&2&FEVcowU>FRmE>x;W*@9X?^1yQth%Ebrlz+` zekOsC%pJde9dcPR~GMbZ!a(f^`7nikq*i?EXG&2P5#-bTfpw=RJJ$&OY_onj8!MWL47BCL;uA!zo zpCHq&XbAYK5M*5_zyplvE&1-8vk1*T$KAjq#1p86iCw%p{v8cUwWVln?!pMRGrb6~ zeK_bKRUV=y#NG1rokW37PA|@dX8~|BGY(&6{{Tjj_`g+e>@17}?=X6(wHtcXsr*P} zCL4`Mp~_IZProject "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\CompilerIdCXX.vcxproj" on node 2 (Build target(s)). + 1>ClCompile: + C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\CL.exe /c /nologo /W0 /WX- /Od /Oy- /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc110.pdb" /Gd /TP /analyze- /errorReport:prompt CMakeCXXCompilerId.cpp + CMakeCXXCompilerId.cpp + Link: + C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:".\CompilerIdCXX.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdCXX.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdCXX.lib" /MACHINE:X86 /SAFESEH Debug\CMakeCXXCompilerId.obj + CompilerIdCXX.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\.\CompilerIdCXX.exe + PostBuildEvent: + for %%i in (cl.exe) do @echo CMAKE_CXX_COMPILER=%%~$PATH:i + :VCEnd + CMAKE_CXX_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe + 1>Done Building Project "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\CompilerIdCXX.vcxproj" (Build target(s)). + +Build succeeded. + +Time Elapsed 00:00:00.20 diff --git a/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule b/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule b/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule b/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule b/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/CMakeOutput.log b/Code/Physics/CMakeFiles/CMakeOutput.log new file mode 100644 index 00000000..50893944 --- /dev/null +++ b/Code/Physics/CMakeFiles/CMakeOutput.log @@ -0,0 +1,119 @@ +The system is: Windows - 6.1 - AMD64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: +Build flags: +Id flags: + +The output was: +0 + +Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. +Copyright (C) Microsoft Corp. All rights reserved. +1>------ Build started: Project: CompilerIdC, Configuration: Debug Win32 ------ +1> CMakeCCompilerId.c +1> CompilerIdC.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\.\CompilerIdC.exe +1> CMAKE_C_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CompilerIdC.exe" + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CompilerIdC.vcxproj" + +The C compiler identification is MSVC, found in "C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.exe" + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: +Build flags: +Id flags: + +The output was: +0 + +Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. +Copyright (C) Microsoft Corp. All rights reserved. +1>------ Build started: Project: CompilerIdCXX, Configuration: Debug Win32 ------ +1> CMakeCXXCompilerId.cpp +1> CompilerIdCXX.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\.\CompilerIdCXX.exe +1> CMAKE_CXX_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.exe" + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.vcxproj" + +The CXX compiler identification is MSVC, found in "C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.exe" + +Determining if the C compiler works passed with the following output: +Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp + +Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec1419522888 + +Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. +Copyright (C) Microsoft Corp. All rights reserved. +1>------ Build started: Project: cmTryCompileExec1419522888, Configuration: Debug Win32 ------ +1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 +1> Copyright (C) Microsoft Corporation. All rights reserved. +1> +1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"cmTryCompileExec1419522888.dir\Debug\\" /Fd"cmTryCompileExec1419522888.dir\Debug\vc110.pdb" /Gd /TC /analyze- /errorReport:prompt testCCompiler.c +1> +1> testCCompiler.c +1> cmTryCompileExec1419522888.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec1419522888.exe +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + + +Detecting C compiler ABI info compiled with the following output: +Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp + +Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec3902347442 + +Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. +Copyright (C) Microsoft Corp. All rights reserved. +1>------ Build started: Project: cmTryCompileExec3902347442, Configuration: Debug Win32 ------ +1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 +1> Copyright (C) Microsoft Corporation. All rights reserved. +1> +1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"cmTryCompileExec3902347442.dir\Debug\\" /Fd"cmTryCompileExec3902347442.dir\Debug\vc110.pdb" /Gd /TC /analyze- /errorReport:prompt "C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCCompilerABI.c" +1> +1> CMakeCCompilerABI.c +1> cmTryCompileExec3902347442.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec3902347442.exe +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + + +Determining if the CXX compiler works passed with the following output: +Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp + +Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec3540497414 + +Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. +Copyright (C) Microsoft Corp. All rights reserved. +1>------ Build started: Project: cmTryCompileExec3540497414, Configuration: Debug Win32 ------ +1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 +1> Copyright (C) Microsoft Corporation. All rights reserved. +1> +1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"cmTryCompileExec3540497414.dir\Debug\\" /Fd"cmTryCompileExec3540497414.dir\Debug\vc110.pdb" /Gd /TP /analyze- /errorReport:prompt testCXXCompiler.cxx +1> +1> testCXXCompiler.cxx +1> cmTryCompileExec3540497414.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec3540497414.exe +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp + +Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec3700395636 + +Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. +Copyright (C) Microsoft Corp. All rights reserved. +1>------ Build started: Project: cmTryCompileExec3700395636, Configuration: Debug Win32 ------ +1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 +1> Copyright (C) Microsoft Corporation. All rights reserved. +1> +1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"cmTryCompileExec3700395636.dir\Debug\\" /Fd"cmTryCompileExec3700395636.dir\Debug\vc110.pdb" /Gd /TP /analyze- /errorReport:prompt "C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXCompilerABI.cpp" +1> +1> CMakeCXXCompilerABI.cpp +1> cmTryCompileExec3700395636.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec3700395636.exe +========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== + + diff --git a/Code/Physics/CMakeFiles/TargetDirectories.txt b/Code/Physics/CMakeFiles/TargetDirectories.txt new file mode 100644 index 00000000..7e769539 --- /dev/null +++ b/Code/Physics/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,10 @@ +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ALL_BUILD.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletCollision/CMakeFiles/BulletCollision.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletDynamics/CMakeFiles/BulletDynamics.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/CMakeFiles/BulletMultiThreaded.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletSoftBody/CMakeFiles/BulletSoftBody.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/BulletSoftBodySolvers_DX11.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/BulletSoftBodySolvers_OpenCL_Mini.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/LinearMath/CMakeFiles/LinearMath.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/src/MiniCL/CMakeFiles/MiniCL.dir +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ZERO_CHECK.dir diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule b/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule b/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule b/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule b/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/cmake.check_cache b/Code/Physics/CMakeFiles/cmake.check_cache new file mode 100644 index 00000000..3dccd731 --- /dev/null +++ b/Code/Physics/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule b/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule b/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule b/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule new file mode 100644 index 00000000..2d3998c9 --- /dev/null +++ b/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule @@ -0,0 +1 @@ +# generated from CMake diff --git a/Code/Physics/BulletCollision/CMakeFiles/generate.stamp b/Code/Physics/CMakeFiles/generate.stamp similarity index 100% rename from Code/Physics/BulletCollision/CMakeFiles/generate.stamp rename to Code/Physics/CMakeFiles/generate.stamp diff --git a/Code/Physics/CMakeFiles/generate.stamp.depend b/Code/Physics/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..34f1c5a8 --- /dev/null +++ b/Code/Physics/CMakeFiles/generate.stamp.depend @@ -0,0 +1,33 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeGenericSystem.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/WindowsPaths.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCInformation.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC-C.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC.cmake +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeRCInformation.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCXXInformation.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC-CXX.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindOpenGL.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageMessage.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeParseArguments.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindGLU.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindOpenGL.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageMessage.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeParseArguments.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindGLUT.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageMessage.cmake +C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeParseArguments.cmake +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/BulletConfig.cmake.in diff --git a/Code/Physics/CMakeFiles/generate.stamp.list b/Code/Physics/CMakeFiles/generate.stamp.list new file mode 100644 index 00000000..8f20741d --- /dev/null +++ b/Code/Physics/CMakeFiles/generate.stamp.list @@ -0,0 +1,12 @@ +C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp +C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp diff --git a/Code/Physics/LinearMath/INSTALL.vcxproj b/Code/Physics/INSTALL.vcxproj similarity index 79% rename from Code/Physics/LinearMath/INSTALL.vcxproj rename to Code/Physics/INSTALL.vcxproj index 30c2d9d0..79dfd7c3 100644 --- a/Code/Physics/LinearMath/INSTALL.vcxproj +++ b/Code/Physics/INSTALL.vcxproj @@ -19,7 +19,7 @@ - {0A758B62-DE3C-493C-985D-39E48A384A7C} + {71641E56-5E9E-462B-844F-A9F8A6D82120} Win32Proj Win32 INSTALL @@ -64,7 +64,7 @@ - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -86,7 +86,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -108,7 +108,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -130,7 +130,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -151,7 +151,7 @@ if %errorlevel% neq 0 goto :VCEnd - + setlocal cd . @@ -162,8 +162,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force false setlocal @@ -175,8 +175,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force false setlocal @@ -188,8 +188,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force false setlocal @@ -201,14 +201,14 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/014b29ea83ffdb14ab17f55265953026/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force false - - F5149B3B-C2B1-4522-9FFD-121CED456BD3 + + 14E546AD-2393-41B9-BAA2-134241286A4E diff --git a/Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend b/Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend deleted file mode 100644 index eca1700c..00000000 --- a/Code/Physics/LinearMath/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt diff --git a/Code/Physics/LinearMath/LinearMath.vcxproj.user b/Code/Physics/LinearMath/LinearMath.vcxproj.user deleted file mode 100644 index a375ae35..00000000 --- a/Code/Physics/LinearMath/LinearMath.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Physics/ZERO_CHECK.vcxproj b/Code/Physics/ZERO_CHECK.vcxproj new file mode 100644 index 00000000..db94fe03 --- /dev/null +++ b/Code/Physics/ZERO_CHECK.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {53399ED8-C4B0-4F84-9CA8-623049125822} + Win32Proj + Win32 + ZERO_CHECK + + + + Utility + false + MultiByte + v110 + + + Utility + false + MultiByte + v110 + + + Utility + false + MultiByte + v110 + + + Utility + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Checking Build System + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + Checking Build System + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + Checking Build System + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + Checking Build System + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + + + + + + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK + false + + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK + false + + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK + false + + setlocal +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK + false + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Physics/cmake_install.cmake b/Code/Physics/cmake_install.cmake new file mode 100644 index 00000000..f3cbeaca --- /dev/null +++ b/Code/Physics/cmake_install.cmake @@ -0,0 +1,52 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/bullet" TYPE FILE FILES + "C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/UseBullet.cmake" + "C:/DV1477/Git Repository/Danbias/Code/Physics/BulletConfig.cmake" + ) +ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + +IF(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/cmake_install.cmake") + +ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) + +IF(CMAKE_INSTALL_COMPONENT) + SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +ELSE(CMAKE_INSTALL_COMPONENT) + SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +ENDIF(CMAKE_INSTALL_COMPONENT) + +FILE(WRITE "C:/DV1477/Git Repository/Danbias/Code/Physics/${CMAKE_INSTALL_MANIFEST}" "") +FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES}) + FILE(APPEND "C:/DV1477/Git Repository/Danbias/Code/Physics/${CMAKE_INSTALL_MANIFEST}" "${file}\n") +ENDFOREACH(file) diff --git a/Code/Physics/src/BulletCollision/BulletCollision.vcxproj b/Code/Physics/src/BulletCollision/BulletCollision.vcxproj new file mode 100644 index 00000000..7359cac7 --- /dev/null +++ b/Code/Physics/src/BulletCollision/BulletCollision.vcxproj @@ -0,0 +1,485 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {C933A737-D7BA-4136-95AF-D12310BD6BA8} + Win32Proj + Win32 + BulletCollision + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + BulletCollision.dir\Debug\ + BulletCollision_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + BulletCollision.dir\Release\ + BulletCollision + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + BulletCollision.dir\MinSizeRel\ + BulletCollision_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + BulletCollision.dir\RelWithDebInfo\ + BulletCollision_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/CMakeFiles/generate.stamp b/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp similarity index 100% rename from Code/Physics/BulletDynamics/CMakeFiles/generate.stamp rename to Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp diff --git a/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..242b5658 --- /dev/null +++ b/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt diff --git a/Code/Physics/src/BulletCollision/INSTALL.vcxproj b/Code/Physics/src/BulletCollision/INSTALL.vcxproj new file mode 100644 index 00000000..1ae267df --- /dev/null +++ b/Code/Physics/src/BulletCollision/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletCollision/cmake_install.cmake b/Code/Physics/src/BulletCollision/cmake_install.cmake new file mode 100644 index 00000000..9ec4b209 --- /dev/null +++ b/Code/Physics/src/BulletCollision/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj b/Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj new file mode 100644 index 00000000..0718896d --- /dev/null +++ b/Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj @@ -0,0 +1,343 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} + Win32Proj + Win32 + BulletDynamics + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + BulletDynamics.dir\Debug\ + BulletDynamics_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + BulletDynamics.dir\Release\ + BulletDynamics + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + BulletDynamics.dir\MinSizeRel\ + BulletDynamics_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + BulletDynamics.dir\RelWithDebInfo\ + BulletDynamics_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Code/Physics/LinearMath/CMakeFiles/generate.stamp b/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp similarity index 100% rename from Code/Physics/LinearMath/CMakeFiles/generate.stamp rename to Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp diff --git a/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..49695f70 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt diff --git a/Code/Physics/src/BulletDynamics/INSTALL.vcxproj b/Code/Physics/src/BulletDynamics/INSTALL.vcxproj new file mode 100644 index 00000000..c2d4ef71 --- /dev/null +++ b/Code/Physics/src/BulletDynamics/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/BulletDynamics/cmake_install.cmake b/Code/Physics/src/BulletDynamics/cmake_install.cmake similarity index 89% rename from Code/Physics/BulletDynamics/cmake_install.cmake rename to Code/Physics/src/BulletDynamics/cmake_install.cmake index 3cf003da..5d4eca19 100644 --- a/Code/Physics/BulletDynamics/cmake_install.cmake +++ b/Code/Physics/src/BulletDynamics/cmake_install.cmake @@ -1,4 +1,4 @@ -# Install script for directory: C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletDynamics +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) diff --git a/Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj b/Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj new file mode 100644 index 00000000..be239532 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {83B388D3-BE71-476A-AA6A-CC7082E3866D} + Win32Proj + Win32 + BulletMultiThreaded + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + BulletMultiThreaded.dir\Debug\ + BulletMultiThreaded_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + BulletMultiThreaded.dir\Release\ + BulletMultiThreaded + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + BulletMultiThreaded.dir\MinSizeRel\ + BulletMultiThreaded_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + BulletMultiThreaded.dir\RelWithDebInfo\ + BulletMultiThreaded_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebug + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 53399ED8-C4B0-4F84-9CA8-623049125822 + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..4b035201 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..c42cec08 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj new file mode 100644 index 00000000..7290b1bc --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj @@ -0,0 +1,293 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85} + Win32Proj + Win32 + BulletSoftBodySolvers_DX11 + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + BulletSoftBodySolvers_DX11.dir\Debug\ + BulletSoftBodySolvers_DX11_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + BulletSoftBodySolvers_DX11.dir\Release\ + BulletSoftBodySolvers_DX11 + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + BulletSoftBodySolvers_DX11.dir\MinSizeRel\ + BulletSoftBodySolvers_DX11_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + BulletSoftBodySolvers_DX11.dir\RelWithDebInfo\ + BulletSoftBodySolvers_DX11_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebug + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 53399ED8-C4B0-4F84-9CA8-623049125822 + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..4f8d772e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj new file mode 100644 index 00000000..ed127c88 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake new file mode 100644 index 00000000..474a3928 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11 + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj new file mode 100644 index 00000000..23e3ae3c --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..90fb95f5 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj new file mode 100644 index 00000000..478d15e4 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj new file mode 100644 index 00000000..afe67dd0 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj @@ -0,0 +1,284 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {80FC7669-D649-4212-8B6F-C0167CE9CB59} + Win32Proj + Win32 + BulletSoftBodySolvers_OpenCL_Mini + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + BulletSoftBodySolvers_OpenCL_Mini.dir\Debug\ + BulletSoftBodySolvers_OpenCL_Mini_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + BulletSoftBodySolvers_OpenCL_Mini.dir\Release\ + BulletSoftBodySolvers_OpenCL_Mini + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + BulletSoftBodySolvers_OpenCL_Mini.dir\MinSizeRel\ + BulletSoftBodySolvers_OpenCL_Mini_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + BulletSoftBodySolvers_OpenCL_Mini.dir\RelWithDebInfo\ + BulletSoftBodySolvers_OpenCL_Mini_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebug + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + 53399ED8-C4B0-4F84-9CA8-623049125822 + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..89f3173a --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj new file mode 100644 index 00000000..adfaafeb --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake new file mode 100644 index 00000000..54342e1e --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake new file mode 100644 index 00000000..deb5133d --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake @@ -0,0 +1,35 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +IF(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake") + +ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) + diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake new file mode 100644 index 00000000..90f58c37 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake @@ -0,0 +1,36 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +IF(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake") + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake") + +ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) + diff --git a/Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj new file mode 100644 index 00000000..6f114658 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake new file mode 100644 index 00000000..1556c814 --- /dev/null +++ b/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake @@ -0,0 +1,35 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +IF(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake") + +ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) + diff --git a/Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj b/Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj new file mode 100644 index 00000000..ead70727 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj @@ -0,0 +1,288 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {14DC504E-697F-4178-8E05-87173957FE59} + Win32Proj + Win32 + BulletSoftBody + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + BulletSoftBody.dir\Debug\ + BulletSoftBody_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + BulletSoftBody.dir\Release\ + BulletSoftBody + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + BulletSoftBody.dir\MinSizeRel\ + BulletSoftBody_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + BulletSoftBody.dir\RelWithDebInfo\ + BulletSoftBody_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebug + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + + + + + + + + + + + + 53399ED8-C4B0-4F84-9CA8-623049125822 + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp b/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..42b8971d --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt diff --git a/Code/Physics/src/BulletSoftBody/INSTALL.vcxproj b/Code/Physics/src/BulletSoftBody/INSTALL.vcxproj new file mode 100644 index 00000000..39d05026 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/src/BulletSoftBody/cmake_install.cmake b/Code/Physics/src/BulletSoftBody/cmake_install.cmake new file mode 100644 index 00000000..4f658151 --- /dev/null +++ b/Code/Physics/src/BulletSoftBody/cmake_install.cmake @@ -0,0 +1,29 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + diff --git a/Code/Physics/src/CMakeFiles/generate.stamp b/Code/Physics/src/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/CMakeFiles/generate.stamp.depend b/Code/Physics/src/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..5c345586 --- /dev/null +++ b/Code/Physics/src/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/CMakeLists.txt diff --git a/Code/Physics/BulletDynamics/INSTALL.vcxproj b/Code/Physics/src/INSTALL.vcxproj similarity index 79% rename from Code/Physics/BulletDynamics/INSTALL.vcxproj rename to Code/Physics/src/INSTALL.vcxproj index 8480d320..3a27b8a1 100644 --- a/Code/Physics/BulletDynamics/INSTALL.vcxproj +++ b/Code/Physics/src/INSTALL.vcxproj @@ -19,7 +19,7 @@ - {0A758B62-DE3C-493C-985D-39E48A384A7C} + {71641E56-5E9E-462B-844F-A9F8A6D82120} Win32Proj Win32 INSTALL @@ -64,7 +64,7 @@ - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -86,7 +86,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -108,7 +108,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -130,7 +130,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -151,7 +151,7 @@ if %errorlevel% neq 0 goto :VCEnd - + setlocal cd . @@ -162,8 +162,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force false setlocal @@ -175,8 +175,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force false setlocal @@ -188,8 +188,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force false setlocal @@ -201,14 +201,14 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/26c1e2c959f534a1cd3ce71328ceef74/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletDynamics\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force false - - F5149B3B-C2B1-4522-9FFD-121CED456BD3 + + 14E546AD-2393-41B9-BAA2-134241286A4E diff --git a/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp b/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend b/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..e22cf59b --- /dev/null +++ b/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt diff --git a/Code/Physics/src/LinearMath/INSTALL.vcxproj b/Code/Physics/src/LinearMath/INSTALL.vcxproj new file mode 100644 index 00000000..a21294ef --- /dev/null +++ b/Code/Physics/src/LinearMath/INSTALL.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {71641E56-5E9E-462B-844F-A9F8A6D82120} + Win32Proj + Win32 + INSTALL + + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + + + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force + false + + setlocal +cd . +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force + false + + + + + 14E546AD-2393-41B9-BAA2-134241286A4E + + + + + + \ No newline at end of file diff --git a/Code/Physics/LinearMath/LinearMath.vcxproj b/Code/Physics/src/LinearMath/LinearMath.vcxproj similarity index 58% rename from Code/Physics/LinearMath/LinearMath.vcxproj rename to Code/Physics/src/LinearMath/LinearMath.vcxproj index efa93177..305ab63f 100644 --- a/Code/Physics/LinearMath/LinearMath.vcxproj +++ b/Code/Physics/src/LinearMath/LinearMath.vcxproj @@ -19,7 +19,7 @@ - {22C0C4D8-6C43-406A-9CDB-76A4F800971A} + {D4985405-3286-4026-BD61-E9E53DC5027E} Win32Proj Win32 LinearMath @@ -58,26 +58,26 @@ <_ProjectFileVersion>10.0.20506.1 - $(SolutionDir)Physics\Debug\ + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ LinearMath.dir\Debug\ LinearMath_Debug .lib - $(SolutionDir)Physics\Release + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ LinearMath.dir\Release\ LinearMath .lib - C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\MinSizeRel\ + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ LinearMath.dir\MinSizeRel\ LinearMath_MinsizeRel .lib - C:\Users\Robin\Programmering\GitHub\Danbias\Code\Physics\RelWithDebInfo\ + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ LinearMath.dir\RelWithDebInfo\ LinearMath_RelWithDebugInfo .lib - $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) Debug/ EnableFastChecks CompileAsCpp @@ -88,7 +88,7 @@ Disabled Disabled NotUsing - MultiThreadedDebugDLL + MultiThreadedDLL true Level3 WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) @@ -96,10 +96,10 @@ WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -109,7 +109,7 @@ - $(SolutionDir)Physics\Glut;$(SolutionDir)Physics\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) Release/ CompileAsCpp StreamingSIMDExtensions @@ -118,7 +118,7 @@ AnySuitable MaxSpeed NotUsing - MultiThreadedDLL + MultiThreaded true Level3 @@ -128,10 +128,10 @@ WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -141,7 +141,7 @@ - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) MinSizeRel/ CompileAsCpp StreamingSIMDExtensions @@ -150,7 +150,7 @@ OnlyExplicitInline MinSpace NotUsing - MultiThreadedDLL + MultiThreaded true Level3 @@ -160,10 +160,10 @@ WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -173,7 +173,7 @@ - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) RelWithDebInfo/ CompileAsCpp ProgramDatabase @@ -183,7 +183,7 @@ OnlyExplicitInline MaxSpeed NotUsing - MultiThreadedDLL + MultiThreaded true Level3 WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) @@ -191,10 +191,10 @@ WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -203,10 +203,10 @@ - - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone @@ -214,12 +214,12 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone @@ -227,12 +227,12 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone @@ -240,12 +240,12 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp false - Building Custom Rule C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704 -BC:/Users/Robin/Programmering/Bullet/Binaries --check-stamp-file C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" if %errorlevel% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone @@ -253,49 +253,46 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath/CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\LinearMath\CMakeFiles\generate.stamp + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/Physics/BulletCollision/cmake_install.cmake b/Code/Physics/src/LinearMath/cmake_install.cmake similarity index 89% rename from Code/Physics/BulletCollision/cmake_install.cmake rename to Code/Physics/src/LinearMath/cmake_install.cmake index 20924d01..19b348f5 100644 --- a/Code/Physics/BulletCollision/cmake_install.cmake +++ b/Code/Physics/src/LinearMath/cmake_install.cmake @@ -1,4 +1,4 @@ -# Install script for directory: C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/BulletCollision +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) diff --git a/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp b/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp new file mode 100644 index 00000000..9b5f49fa --- /dev/null +++ b/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp @@ -0,0 +1 @@ +# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend b/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend new file mode 100644 index 00000000..aed156a6 --- /dev/null +++ b/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend @@ -0,0 +1,2 @@ +# CMake generation dependency list for this directory. +C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt diff --git a/Code/Physics/BulletCollision/INSTALL.vcxproj b/Code/Physics/src/MiniCL/INSTALL.vcxproj similarity index 79% rename from Code/Physics/BulletCollision/INSTALL.vcxproj rename to Code/Physics/src/MiniCL/INSTALL.vcxproj index f8528ea7..d88be3fa 100644 --- a/Code/Physics/BulletCollision/INSTALL.vcxproj +++ b/Code/Physics/src/MiniCL/INSTALL.vcxproj @@ -19,7 +19,7 @@ - {0A758B62-DE3C-493C-985D-39E48A384A7C} + {71641E56-5E9E-462B-844F-A9F8A6D82120} Win32Proj Win32 INSTALL @@ -64,7 +64,7 @@ - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -86,7 +86,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -108,7 +108,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -130,7 +130,7 @@ if %errorlevel% neq 0 goto :VCEnd - C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\Glut;C:\Users\Robin\Programmering\Bullet\bullet-2.82-r2704\src;%(AdditionalIncludeDirectories) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) $(IntDir) %(Filename).h %(Filename).tlb @@ -151,7 +151,7 @@ if %errorlevel% neq 0 goto :VCEnd - + setlocal cd . @@ -162,8 +162,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force false setlocal @@ -175,8 +175,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force false setlocal @@ -188,8 +188,8 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force false setlocal @@ -201,14 +201,14 @@ endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone exit /b %1 :cmDone if %errorlevel% neq 0 goto :VCEnd - C:/Users/Robin/Programmering/Bullet/Binaries/CMakeFiles/2488fbf1c07ab778f5bdaf8ca8459122/INSTALL_force.rule;%(AdditionalInputs) - C:\Users\Robin\Programmering\Bullet\Binaries\src\BulletCollision\CMakeFiles\INSTALL_force + C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force false - - F5149B3B-C2B1-4522-9FFD-121CED456BD3 + + 14E546AD-2393-41B9-BAA2-134241286A4E diff --git a/Code/Physics/src/MiniCL/MiniCL.vcxproj b/Code/Physics/src/MiniCL/MiniCL.vcxproj new file mode 100644 index 00000000..11346872 --- /dev/null +++ b/Code/Physics/src/MiniCL/MiniCL.vcxproj @@ -0,0 +1,277 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + MinSizeRel + Win32 + + + RelWithDebInfo + Win32 + + + + {FA9E3157-5228-4CA4-8327-BD0AF11BD390} + Win32Proj + Win32 + MiniCL + + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + StaticLibrary + false + MultiByte + v110 + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ + MiniCL.dir\Debug\ + MiniCL_Debug + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ + MiniCL.dir\Release\ + MiniCL + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ + MiniCL.dir\MinSizeRel\ + MiniCL_MinsizeRel + .lib + C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ + MiniCL.dir\RelWithDebInfo\ + MiniCL_RelWithDebugInfo + .lib + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + Disabled + Disabled + NotUsing + MultiThreadedDebug + true + Level3 + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + AnySuitable + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + MinSizeRel/ + CompileAsCpp + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MinSpace + NotUsing + MultiThreaded + true + Level3 + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + RelWithDebInfo/ + CompileAsCpp + ProgramDatabase + StreamingSIMDExtensions + Sync + Fast + OnlyExplicitInline + MaxSpeed + NotUsing + MultiThreaded + true + Level3 + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + + + C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp + false + Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt + setlocal +"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) + C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp + false + + + + + + + + + + + + + + + + 53399ED8-C4B0-4F84-9CA8-623049125822 + + + + + + \ No newline at end of file diff --git a/Code/Physics/LinearMath/cmake_install.cmake b/Code/Physics/src/MiniCL/cmake_install.cmake similarity index 90% rename from Code/Physics/LinearMath/cmake_install.cmake rename to Code/Physics/src/MiniCL/cmake_install.cmake index c82b699b..2159470a 100644 --- a/Code/Physics/LinearMath/cmake_install.cmake +++ b/Code/Physics/src/MiniCL/cmake_install.cmake @@ -1,4 +1,4 @@ -# Install script for directory: C:/Users/Robin/Programmering/Bullet/bullet-2.82-r2704/src/LinearMath +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) diff --git a/Code/Physics/src/cmake_install.cmake b/Code/Physics/src/cmake_install.cmake new file mode 100644 index 00000000..a17a786d --- /dev/null +++ b/Code/Physics/src/cmake_install.cmake @@ -0,0 +1,40 @@ +# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +IF(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for each subdirectory. + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletSoftBody/cmake_install.cmake") + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletCollision/cmake_install.cmake") + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletDynamics/cmake_install.cmake") + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/LinearMath/cmake_install.cmake") + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/MiniCL/cmake_install.cmake") + INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake") + +ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) + diff --git a/Code/suo6F49.tmp b/Code/suo6F49.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 diff --git a/Code/suoBC7E.tmp b/Code/suoBC7E.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 diff --git a/Code/suoC9A6.tmp b/Code/suoC9A6.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 diff --git a/Code/suoDD74.tmp b/Code/suoDD74.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 diff --git a/Code/suoE071.tmp b/Code/suoE071.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 diff --git a/Code/suoE544.tmp b/Code/suoE544.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 From c16851f02477104420de0cae5c3a04e5f3f4818a Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 11:14:45 +0100 Subject: [PATCH 19/35] Using only lib and include --- Code/DanBias.sln | 74 - Code/GamePhysics/GamePhysics.vcxproj | 2 +- Code/Physics/ALL_BUILD.vcxproj | 244 - Code/Physics/BULLET_PHYSICS.sln | 162 - Code/Physics/Bullet Source/AUTHORS | 22 - Code/Physics/Bullet Source/BspDemo.bsp | Bin 105100 -> 0 bytes .../Bullet Source/{src => }/Bullet-C-Api.h | 0 .../BroadphaseCollision/btAxisSweep3.cpp | 0 .../BroadphaseCollision/btAxisSweep3.h | 0 .../btBroadphaseInterface.h | 0 .../BroadphaseCollision/btBroadphaseProxy.cpp | 0 .../BroadphaseCollision/btBroadphaseProxy.h | 0 .../btCollisionAlgorithm.cpp | 0 .../btCollisionAlgorithm.h | 0 .../BroadphaseCollision/btDbvt.cpp | 0 .../BroadphaseCollision/btDbvt.h | 0 .../BroadphaseCollision/btDbvtBroadphase.cpp | 0 .../BroadphaseCollision/btDbvtBroadphase.h | 0 .../BroadphaseCollision/btDispatcher.cpp | 0 .../BroadphaseCollision/btDispatcher.h | 0 .../btMultiSapBroadphase.cpp | 0 .../btMultiSapBroadphase.h | 0 .../btOverlappingPairCache.cpp | 0 .../btOverlappingPairCache.h | 0 .../btOverlappingPairCallback.h | 0 .../BroadphaseCollision/btQuantizedBvh.cpp | 0 .../BroadphaseCollision/btQuantizedBvh.h | 0 .../btSimpleBroadphase.cpp | 0 .../BroadphaseCollision/btSimpleBroadphase.h | 0 .../{src => }/BulletCollision/CMakeLists.txt | 0 .../SphereTriangleDetector.cpp | 0 .../SphereTriangleDetector.h | 0 .../btActivatingCollisionAlgorithm.cpp | 0 .../btActivatingCollisionAlgorithm.h | 0 .../btBox2dBox2dCollisionAlgorithm.cpp | 0 .../btBox2dBox2dCollisionAlgorithm.h | 0 .../btBoxBoxCollisionAlgorithm.cpp | 0 .../btBoxBoxCollisionAlgorithm.h | 0 .../CollisionDispatch/btBoxBoxDetector.cpp | 0 .../CollisionDispatch/btBoxBoxDetector.h | 0 .../btCollisionConfiguration.h | 0 .../CollisionDispatch/btCollisionCreateFunc.h | 0 .../btCollisionDispatcher.cpp | 0 .../CollisionDispatch/btCollisionDispatcher.h | 0 .../CollisionDispatch/btCollisionObject.cpp | 0 .../CollisionDispatch/btCollisionObject.h | 0 .../btCollisionObjectWrapper.h | 0 .../CollisionDispatch/btCollisionWorld.cpp | 0 .../CollisionDispatch/btCollisionWorld.h | 0 .../btCompoundCollisionAlgorithm.cpp | 0 .../btCompoundCollisionAlgorithm.h | 0 .../btCompoundCompoundCollisionAlgorithm.cpp | 0 .../btCompoundCompoundCollisionAlgorithm.h | 0 .../btConvex2dConvex2dAlgorithm.cpp | 0 .../btConvex2dConvex2dAlgorithm.h | 0 .../btConvexConcaveCollisionAlgorithm.cpp | 0 .../btConvexConcaveCollisionAlgorithm.h | 0 .../btConvexConvexAlgorithm.cpp | 0 .../btConvexConvexAlgorithm.h | 0 .../btConvexPlaneCollisionAlgorithm.cpp | 0 .../btConvexPlaneCollisionAlgorithm.h | 0 .../btDefaultCollisionConfiguration.cpp | 0 .../btDefaultCollisionConfiguration.h | 0 .../btEmptyCollisionAlgorithm.cpp | 0 .../btEmptyCollisionAlgorithm.h | 0 .../CollisionDispatch/btGhostObject.cpp | 0 .../CollisionDispatch/btGhostObject.h | 0 .../btHashedSimplePairCache.cpp | 0 .../btHashedSimplePairCache.h | 0 .../btInternalEdgeUtility.cpp | 0 .../CollisionDispatch/btInternalEdgeUtility.h | 0 .../CollisionDispatch/btManifoldResult.cpp | 0 .../CollisionDispatch/btManifoldResult.h | 0 .../btSimulationIslandManager.cpp | 0 .../btSimulationIslandManager.h | 0 .../btSphereBoxCollisionAlgorithm.cpp | 0 .../btSphereBoxCollisionAlgorithm.h | 0 .../btSphereSphereCollisionAlgorithm.cpp | 0 .../btSphereSphereCollisionAlgorithm.h | 0 .../btSphereTriangleCollisionAlgorithm.cpp | 0 .../btSphereTriangleCollisionAlgorithm.h | 0 .../CollisionDispatch/btUnionFind.cpp | 0 .../CollisionDispatch/btUnionFind.h | 0 .../CollisionShapes/btBox2dShape.cpp | 0 .../CollisionShapes/btBox2dShape.h | 0 .../CollisionShapes/btBoxShape.cpp | 0 .../CollisionShapes/btBoxShape.h | 0 .../btBvhTriangleMeshShape.cpp | 0 .../CollisionShapes/btBvhTriangleMeshShape.h | 0 .../CollisionShapes/btCapsuleShape.cpp | 0 .../CollisionShapes/btCapsuleShape.h | 0 .../CollisionShapes/btCollisionMargin.h | 0 .../CollisionShapes/btCollisionShape.cpp | 0 .../CollisionShapes/btCollisionShape.h | 0 .../CollisionShapes/btCompoundShape.cpp | 0 .../CollisionShapes/btCompoundShape.h | 0 .../CollisionShapes/btConcaveShape.cpp | 0 .../CollisionShapes/btConcaveShape.h | 0 .../CollisionShapes/btConeShape.cpp | 0 .../CollisionShapes/btConeShape.h | 0 .../CollisionShapes/btConvex2dShape.cpp | 0 .../CollisionShapes/btConvex2dShape.h | 0 .../CollisionShapes/btConvexHullShape.cpp | 0 .../CollisionShapes/btConvexHullShape.h | 0 .../CollisionShapes/btConvexInternalShape.cpp | 0 .../CollisionShapes/btConvexInternalShape.h | 0 .../btConvexPointCloudShape.cpp | 0 .../CollisionShapes/btConvexPointCloudShape.h | 0 .../CollisionShapes/btConvexPolyhedron.cpp | 0 .../CollisionShapes/btConvexPolyhedron.h | 0 .../CollisionShapes/btConvexShape.cpp | 0 .../CollisionShapes/btConvexShape.h | 0 .../btConvexTriangleMeshShape.cpp | 0 .../btConvexTriangleMeshShape.h | 0 .../CollisionShapes/btCylinderShape.cpp | 0 .../CollisionShapes/btCylinderShape.h | 0 .../CollisionShapes/btEmptyShape.cpp | 0 .../CollisionShapes/btEmptyShape.h | 0 .../btHeightfieldTerrainShape.cpp | 0 .../btHeightfieldTerrainShape.h | 0 .../CollisionShapes/btMaterial.h | 0 .../CollisionShapes/btMinkowskiSumShape.cpp | 0 .../CollisionShapes/btMinkowskiSumShape.h | 0 .../CollisionShapes/btMultiSphereShape.cpp | 0 .../CollisionShapes/btMultiSphereShape.h | 0 .../btMultimaterialTriangleMeshShape.cpp | 0 .../btMultimaterialTriangleMeshShape.h | 0 .../CollisionShapes/btOptimizedBvh.cpp | 0 .../CollisionShapes/btOptimizedBvh.h | 0 .../btPolyhedralConvexShape.cpp | 0 .../CollisionShapes/btPolyhedralConvexShape.h | 0 .../btScaledBvhTriangleMeshShape.cpp | 0 .../btScaledBvhTriangleMeshShape.h | 0 .../CollisionShapes/btShapeHull.cpp | 0 .../CollisionShapes/btShapeHull.h | 0 .../CollisionShapes/btSphereShape.cpp | 0 .../CollisionShapes/btSphereShape.h | 0 .../CollisionShapes/btStaticPlaneShape.cpp | 0 .../CollisionShapes/btStaticPlaneShape.h | 0 .../btStridingMeshInterface.cpp | 0 .../CollisionShapes/btStridingMeshInterface.h | 0 .../CollisionShapes/btTetrahedronShape.cpp | 0 .../CollisionShapes/btTetrahedronShape.h | 0 .../CollisionShapes/btTriangleBuffer.cpp | 0 .../CollisionShapes/btTriangleBuffer.h | 0 .../CollisionShapes/btTriangleCallback.cpp | 0 .../CollisionShapes/btTriangleCallback.h | 0 .../btTriangleIndexVertexArray.cpp | 0 .../btTriangleIndexVertexArray.h | 0 .../btTriangleIndexVertexMaterialArray.cpp | 0 .../btTriangleIndexVertexMaterialArray.h | 0 .../CollisionShapes/btTriangleInfoMap.h | 0 .../CollisionShapes/btTriangleMesh.cpp | 0 .../CollisionShapes/btTriangleMesh.h | 0 .../CollisionShapes/btTriangleMeshShape.cpp | 0 .../CollisionShapes/btTriangleMeshShape.h | 0 .../CollisionShapes/btTriangleShape.h | 0 .../CollisionShapes/btUniformScalingShape.cpp | 0 .../CollisionShapes/btUniformScalingShape.h | 0 .../{src => }/BulletCollision/Doxyfile | 0 .../BulletCollision/Gimpact/btBoxCollision.h | 0 .../BulletCollision/Gimpact/btClipPolygon.h | 0 .../Gimpact/btCompoundFromGimpact.h | 0 .../Gimpact/btContactProcessing.cpp | 0 .../Gimpact/btContactProcessing.h | 0 .../BulletCollision/Gimpact/btGImpactBvh.cpp | 0 .../BulletCollision/Gimpact/btGImpactBvh.h | 0 .../Gimpact/btGImpactCollisionAlgorithm.cpp | 0 .../Gimpact/btGImpactCollisionAlgorithm.h | 0 .../Gimpact/btGImpactMassUtil.h | 0 .../Gimpact/btGImpactQuantizedBvh.cpp | 0 .../Gimpact/btGImpactQuantizedBvh.h | 0 .../Gimpact/btGImpactShape.cpp | 0 .../BulletCollision/Gimpact/btGImpactShape.h | 0 .../Gimpact/btGenericPoolAllocator.cpp | 0 .../Gimpact/btGenericPoolAllocator.h | 0 .../Gimpact/btGeometryOperations.h | 0 .../BulletCollision/Gimpact/btQuantization.h | 0 .../Gimpact/btTriangleShapeEx.cpp | 0 .../Gimpact/btTriangleShapeEx.h | 0 .../BulletCollision/Gimpact/gim_array.h | 0 .../Gimpact/gim_basic_geometry_operations.h | 0 .../BulletCollision/Gimpact/gim_bitset.h | 0 .../Gimpact/gim_box_collision.h | 0 .../BulletCollision/Gimpact/gim_box_set.cpp | 0 .../BulletCollision/Gimpact/gim_box_set.h | 0 .../Gimpact/gim_clip_polygon.h | 0 .../BulletCollision/Gimpact/gim_contact.cpp | 0 .../BulletCollision/Gimpact/gim_contact.h | 0 .../BulletCollision/Gimpact/gim_geom_types.h | 0 .../BulletCollision/Gimpact/gim_geometry.h | 0 .../BulletCollision/Gimpact/gim_hash_table.h | 0 .../BulletCollision/Gimpact/gim_linear_math.h | 0 .../BulletCollision/Gimpact/gim_math.h | 0 .../BulletCollision/Gimpact/gim_memory.cpp | 0 .../BulletCollision/Gimpact/gim_memory.h | 0 .../BulletCollision/Gimpact/gim_radixsort.h | 0 .../Gimpact/gim_tri_collision.cpp | 0 .../Gimpact/gim_tri_collision.h | 0 .../btContinuousConvexCollision.cpp | 0 .../btContinuousConvexCollision.h | 0 .../NarrowPhaseCollision/btConvexCast.cpp | 0 .../NarrowPhaseCollision/btConvexCast.h | 0 .../btConvexPenetrationDepthSolver.h | 0 .../btDiscreteCollisionDetectorInterface.h | 0 .../NarrowPhaseCollision/btGjkConvexCast.cpp | 0 .../NarrowPhaseCollision/btGjkConvexCast.h | 0 .../NarrowPhaseCollision/btGjkEpa2.cpp | 0 .../NarrowPhaseCollision/btGjkEpa2.h | 0 .../btGjkEpaPenetrationDepthSolver.cpp | 0 .../btGjkEpaPenetrationDepthSolver.h | 0 .../btGjkPairDetector.cpp | 0 .../NarrowPhaseCollision/btGjkPairDetector.h | 0 .../NarrowPhaseCollision/btManifoldPoint.h | 0 .../btMinkowskiPenetrationDepthSolver.cpp | 0 .../btMinkowskiPenetrationDepthSolver.h | 0 .../btPersistentManifold.cpp | 0 .../btPersistentManifold.h | 0 .../NarrowPhaseCollision/btPointCollector.h | 0 .../btPolyhedralContactClipping.cpp | 0 .../btPolyhedralContactClipping.h | 0 .../btRaycastCallback.cpp | 0 .../NarrowPhaseCollision/btRaycastCallback.h | 0 .../btSimplexSolverInterface.h | 0 .../btSubSimplexConvexCast.cpp | 0 .../btSubSimplexConvexCast.h | 0 .../btVoronoiSimplexSolver.cpp | 0 .../btVoronoiSimplexSolver.h | 0 .../{src => }/BulletCollision/premake4.lua | 0 .../Bullet Source/BulletConfig.cmake.in | 25 - .../{src => }/BulletDynamics/CMakeLists.txt | 0 .../btCharacterControllerInterface.h | 0 .../btKinematicCharacterController.cpp | 0 .../btKinematicCharacterController.h | 0 .../btConeTwistConstraint.cpp | 0 .../ConstraintSolver/btConeTwistConstraint.h | 0 .../ConstraintSolver/btConstraintSolver.h | 0 .../ConstraintSolver/btContactConstraint.cpp | 0 .../ConstraintSolver/btContactConstraint.h | 0 .../ConstraintSolver/btContactSolverInfo.h | 0 .../ConstraintSolver/btFixedConstraint.cpp | 0 .../ConstraintSolver/btFixedConstraint.h | 0 .../ConstraintSolver/btGearConstraint.cpp | 0 .../ConstraintSolver/btGearConstraint.h | 0 .../btGeneric6DofConstraint.cpp | 0 .../btGeneric6DofConstraint.h | 0 .../btGeneric6DofSpringConstraint.cpp | 0 .../btGeneric6DofSpringConstraint.h | 0 .../ConstraintSolver/btHinge2Constraint.cpp | 0 .../ConstraintSolver/btHinge2Constraint.h | 0 .../ConstraintSolver/btHingeConstraint.cpp | 0 .../ConstraintSolver/btHingeConstraint.h | 0 .../ConstraintSolver/btJacobianEntry.h | 0 .../btPoint2PointConstraint.cpp | 0 .../btPoint2PointConstraint.h | 0 .../btSequentialImpulseConstraintSolver.cpp | 0 .../btSequentialImpulseConstraintSolver.h | 0 .../ConstraintSolver/btSliderConstraint.cpp | 0 .../ConstraintSolver/btSliderConstraint.h | 0 .../btSolve2LinearConstraint.cpp | 0 .../btSolve2LinearConstraint.h | 0 .../ConstraintSolver/btSolverBody.h | 0 .../ConstraintSolver/btSolverConstraint.h | 0 .../ConstraintSolver/btTypedConstraint.cpp | 0 .../ConstraintSolver/btTypedConstraint.h | 0 .../btUniversalConstraint.cpp | 0 .../ConstraintSolver/btUniversalConstraint.h | 0 .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 0 .../Dynamics/btActionInterface.h | 0 .../Dynamics/btDiscreteDynamicsWorld.cpp | 0 .../Dynamics/btDiscreteDynamicsWorld.h | 0 .../BulletDynamics/Dynamics/btDynamicsWorld.h | 0 .../BulletDynamics/Dynamics/btRigidBody.cpp | 0 .../BulletDynamics/Dynamics/btRigidBody.h | 0 .../Dynamics/btSimpleDynamicsWorld.cpp | 0 .../Dynamics/btSimpleDynamicsWorld.h | 0 .../Featherstone/btMultiBody.cpp | 0 .../BulletDynamics/Featherstone/btMultiBody.h | 0 .../Featherstone/btMultiBodyConstraint.cpp | 0 .../Featherstone/btMultiBodyConstraint.h | 0 .../btMultiBodyConstraintSolver.cpp | 0 .../btMultiBodyConstraintSolver.h | 0 .../Featherstone/btMultiBodyDynamicsWorld.cpp | 0 .../Featherstone/btMultiBodyDynamicsWorld.h | 0 .../btMultiBodyJointLimitConstraint.cpp | 0 .../btMultiBodyJointLimitConstraint.h | 0 .../Featherstone/btMultiBodyJointMotor.cpp | 0 .../Featherstone/btMultiBodyJointMotor.h | 0 .../Featherstone/btMultiBodyLink.h | 0 .../Featherstone/btMultiBodyLinkCollider.h | 0 .../Featherstone/btMultiBodyPoint2Point.cpp | 0 .../Featherstone/btMultiBodyPoint2Point.h | 0 .../btMultiBodySolverConstraint.h | 0 .../MLCPSolvers/btDantzigLCP.cpp | 0 .../BulletDynamics/MLCPSolvers/btDantzigLCP.h | 0 .../MLCPSolvers/btDantzigSolver.h | 0 .../MLCPSolvers/btMLCPSolver.cpp | 0 .../BulletDynamics/MLCPSolvers/btMLCPSolver.h | 0 .../MLCPSolvers/btMLCPSolverInterface.h | 0 .../BulletDynamics/MLCPSolvers/btPATHSolver.h | 0 .../MLCPSolvers/btSolveProjectedGaussSeidel.h | 0 .../Vehicle/btRaycastVehicle.cpp | 0 .../BulletDynamics/Vehicle/btRaycastVehicle.h | 0 .../Vehicle/btVehicleRaycaster.h | 0 .../BulletDynamics/Vehicle/btWheelInfo.cpp | 0 .../BulletDynamics/Vehicle/btWheelInfo.h | 0 .../{src => }/BulletDynamics/premake4.lua | 0 Code/Physics/Bullet Source/BulletLicense.txt | 18 - Code/Physics/Bullet Source/CMakeLists.txt | 439 - Code/Physics/Bullet Source/COPYING | 17 - Code/Physics/Bullet Source/ChangeLog | 795 - Code/Physics/Bullet Source/Doxyfile | 780 - .../Bullet Source/Glut/EmptyGL/GL/egl_cpx.h | 13 - .../Bullet Source/Glut/EmptyGL/GL/egl_defs.h | 706 - .../Glut/EmptyGL/GL/egl_logged.h | 20 - .../Glut/EmptyGL/GL/egl_tokens.h | 459 - .../Bullet Source/Glut/EmptyGL/GL/egl_void.h | 422 - .../Bullet Source/Glut/EmptyGL/GL/gl.h | 47 - .../Bullet Source/Glut/EmptyGL/GL/glu.h | 23 - .../Bullet Source/Glut/EmptyGL/GL/glut.h | 60 - Code/Physics/Bullet Source/Glut/GL/glew.h | 15507 ---------------- Code/Physics/Bullet Source/Glut/GL/glext.h | 3326 ---- Code/Physics/Bullet Source/Glut/GL/glut.h | 607 - Code/Physics/Bullet Source/Glut/GL/glxew.h | 1587 -- Code/Physics/Bullet Source/Glut/GL/glxext.h | 546 - Code/Physics/Bullet Source/Glut/GL/wglew.h | 1363 -- Code/Physics/Bullet Source/Glut/GL/wglext.h | 466 - .../Bullet Source/Glut/btGlutInclude.h | 43 - Code/Physics/Bullet Source/INSTALL | 111 - .../{src => }/LinearMath/CMakeLists.txt | 0 .../{src => }/LinearMath/btAabbUtil2.h | 0 .../LinearMath/btAlignedAllocator.cpp | 0 .../{src => }/LinearMath/btAlignedAllocator.h | 0 .../LinearMath/btAlignedObjectArray.h | 0 .../{src => }/LinearMath/btConvexHull.cpp | 0 .../{src => }/LinearMath/btConvexHull.h | 0 .../LinearMath/btConvexHullComputer.cpp | 0 .../LinearMath/btConvexHullComputer.h | 0 .../LinearMath/btDefaultMotionState.h | 0 .../{src => }/LinearMath/btGeometryUtil.cpp | 0 .../{src => }/LinearMath/btGeometryUtil.h | 0 .../LinearMath/btGrahamScan2dConvexHull.h | 0 .../{src => }/LinearMath/btHashMap.h | 0 .../{src => }/LinearMath/btIDebugDraw.h | 0 .../{src => }/LinearMath/btList.h | 0 .../{src => }/LinearMath/btMatrix3x3.h | 0 .../{src => }/LinearMath/btMatrixX.h | 0 .../{src => }/LinearMath/btMinMax.h | 0 .../{src => }/LinearMath/btMotionState.h | 0 .../LinearMath/btPolarDecomposition.cpp | 0 .../LinearMath/btPolarDecomposition.h | 0 .../{src => }/LinearMath/btPoolAllocator.h | 0 .../{src => }/LinearMath/btQuadWord.h | 0 .../{src => }/LinearMath/btQuaternion.h | 0 .../{src => }/LinearMath/btQuickprof.cpp | 0 .../{src => }/LinearMath/btQuickprof.h | 0 .../{src => }/LinearMath/btRandom.h | 0 .../{src => }/LinearMath/btScalar.h | 0 .../{src => }/LinearMath/btSerializer.cpp | 0 .../{src => }/LinearMath/btSerializer.h | 0 .../{src => }/LinearMath/btStackAlloc.h | 0 .../{src => }/LinearMath/btTransform.h | 0 .../{src => }/LinearMath/btTransformUtil.h | 0 .../{src => }/LinearMath/btVector3.cpp | 0 .../{src => }/LinearMath/btVector3.h | 0 .../{src => }/LinearMath/premake4.lua | 0 Code/Physics/Bullet Source/Makefile.am | 7 - Code/Physics/Bullet Source/NEWS | 5 - Code/Physics/Bullet Source/README | 6 - Code/Physics/Bullet Source/RELEASING.TXT | 36 - Code/Physics/Bullet Source/UseBullet.cmake | 10 - Code/Physics/Bullet Source/VERSION | 1 - Code/Physics/Bullet Source/acinclude.m4 | 3054 --- Code/Physics/Bullet Source/autogen.sh | 61 - .../{src => }/btBulletCollisionCommon.h | 0 .../{src => }/btBulletDynamicsCommon.h | 0 Code/Physics/Bullet Source/bullet.pc.cmake | 6 - Code/Physics/Bullet Source/bullet.pc.in | 11 - Code/Physics/Bullet Source/bullet_logo.png | Bin 3380 -> 0 bytes Code/Physics/Bullet Source/config.h.in | 113 - Code/Physics/Bullet Source/configure.ac | 172 - Code/Physics/Bullet Source/convex0.bin | Bin 548 -> 0 bytes Code/Physics/Bullet Source/file.obj | 3578 ---- .../Bullet Source/heightfield128x128.raw | 37 - Code/Physics/Bullet Source/install-sh | 322 - Code/Physics/Bullet Source/jenga.dae | 5632 ------ .../src/BulletMultiThreaded/CMakeLists.txt | 126 - .../GpuSoftBodySolvers/CMakeLists.txt | 13 - .../GpuSoftBodySolvers/DX11/CMakeLists.txt | 86 - .../DX11/HLSL/ApplyForces.hlsl | 95 - .../DX11/HLSL/ComputeBounds.hlsl | 83 - .../DX11/HLSL/Integrate.hlsl | 41 - .../DX11/HLSL/OutputToVertexArray.hlsl | 63 - .../DX11/HLSL/PrepareLinks.hlsl | 44 - .../DX11/HLSL/SolvePositions.hlsl | 55 - .../DX11/HLSL/SolvePositionsSIMDBatched.hlsl | 147 - .../DX11/HLSL/UpdateConstants.hlsl | 48 - .../DX11/HLSL/UpdateNodes.hlsl | 49 - .../DX11/HLSL/UpdateNormals.hlsl | 98 - .../DX11/HLSL/UpdatePositions.hlsl | 44 - .../HLSL/UpdatePositionsFromVelocities.hlsl | 35 - .../DX11/HLSL/VSolveLinks.hlsl | 55 - .../solveCollisionsAndUpdateVelocities.hlsl | 170 - ...lisionsAndUpdateVelocitiesSIMDBatched.hlsl | 191 - .../DX11/btSoftBodySolverBuffer_DX11.h | 323 - .../DX11/btSoftBodySolverLinkData_DX11.h | 103 - .../btSoftBodySolverLinkData_DX11SIMDAware.h | 173 - .../DX11/btSoftBodySolverTriangleData_DX11.h | 96 - .../DX11/btSoftBodySolverVertexBuffer_DX11.h | 107 - .../DX11/btSoftBodySolverVertexData_DX11.h | 63 - .../DX11/btSoftBodySolver_DX11.cpp | 2236 --- .../DX11/btSoftBodySolver_DX11.h | 691 - .../DX11/btSoftBodySolver_DX11SIMDAware.cpp | 1051 -- .../DX11/btSoftBodySolver_DX11SIMDAware.h | 81 - .../GpuSoftBodySolvers/DX11/premake4.lua | 23 - .../OpenCL/AMD/CMakeLists.txt | 65 - .../OpenCL/AMD/premake4.lua | 27 - .../OpenCL/Apple/CMakeLists.txt | 80 - .../GpuSoftBodySolvers/OpenCL/CMakeLists.txt | 17 - .../OpenCL/Intel/CMakeLists.txt | 85 - .../OpenCL/Intel/premake4.lua | 27 - .../OpenCL/MiniCL/CMakeLists.txt | 78 - .../OpenCL/MiniCL/MiniCLTaskWrap.cpp | 249 - .../OpenCL/NVidia/CMakeLists.txt | 84 - .../OpenCL/NVidia/premake4.lua | 27 - .../OpenCL/OpenCLC10/ApplyForces.cl | 102 - .../OpenCL/OpenCLC10/ComputeBounds.cl | 82 - .../OpenCL/OpenCLC10/Integrate.cl | 35 - .../OpenCL/OpenCLC10/OutputToVertexArray.cl | 46 - .../OpenCL/OpenCLC10/PrepareLinks.cl | 38 - .../SolveCollisionsAndUpdateVelocities.cl | 204 - ...ollisionsAndUpdateVelocitiesSIMDBatched.cl | 242 - .../OpenCL/OpenCLC10/SolvePositions.cl | 57 - .../OpenCLC10/SolvePositionsSIMDBatched.cl | 130 - .../OpenCL/OpenCLC10/UpdateConstants.cl | 44 - .../OpenCLC10/UpdateFixedVertexPositions.cl | 25 - .../OpenCL/OpenCLC10/UpdateNodes.cl | 39 - .../OpenCL/OpenCLC10/UpdateNormals.cl | 102 - .../OpenCL/OpenCLC10/UpdatePositions.cl | 34 - .../UpdatePositionsFromVelocities.cl | 28 - .../OpenCL/OpenCLC10/VSolveLinks.cl | 45 - .../OpenCL/btSoftBodySolverBuffer_OpenCL.h | 209 - .../OpenCL/btSoftBodySolverLinkData_OpenCL.h | 99 - ...btSoftBodySolverLinkData_OpenCLSIMDAware.h | 169 - .../OpenCL/btSoftBodySolverOutputCLtoGL.cpp | 126 - .../OpenCL/btSoftBodySolverOutputCLtoGL.h | 62 - .../btSoftBodySolverTriangleData_OpenCL.h | 84 - .../btSoftBodySolverVertexBuffer_OpenGL.h | 166 - .../btSoftBodySolverVertexData_OpenCL.h | 52 - .../OpenCL/btSoftBodySolver_OpenCL.cpp | 1820 -- .../OpenCL/btSoftBodySolver_OpenCL.h | 527 - .../btSoftBodySolver_OpenCLSIMDAware.cpp | 1101 -- .../OpenCL/btSoftBodySolver_OpenCLSIMDAware.h | 81 - .../Shared/btSoftBodySolverData.h | 748 - .../src/BulletMultiThreaded/HeapManager.h | 117 - .../BulletMultiThreaded/PlatformDefinitions.h | 103 - .../PosixThreadSupport.cpp | 409 - .../BulletMultiThreaded/PosixThreadSupport.h | 147 - .../src/BulletMultiThreaded/PpuAddressSpace.h | 37 - .../SequentialThreadSupport.cpp | 181 - .../SequentialThreadSupport.h | 100 - .../SpuCollisionObjectWrapper.cpp | 48 - .../SpuCollisionObjectWrapper.h | 40 - .../SpuCollisionTaskProcess.cpp | 317 - .../SpuCollisionTaskProcess.h | 163 - .../SpuContactManifoldCollisionAlgorithm.cpp | 69 - .../SpuContactManifoldCollisionAlgorithm.h | 121 - .../src/BulletMultiThreaded/SpuDoubleBuffer.h | 126 - .../src/BulletMultiThreaded/SpuFakeDma.cpp | 215 - .../src/BulletMultiThreaded/SpuFakeDma.h | 135 - .../SpuGatheringCollisionDispatcher.cpp | 283 - .../SpuGatheringCollisionDispatcher.h | 72 - .../BulletMultiThreaded/SpuLibspe2Support.cpp | 257 - .../BulletMultiThreaded/SpuLibspe2Support.h | 180 - .../SpuNarrowPhaseCollisionTask/Box.h | 167 - .../SpuCollisionShapes.cpp | 302 - .../SpuCollisionShapes.h | 128 - .../SpuContactResult.cpp | 248 - .../SpuContactResult.h | 106 - .../SpuConvexPenetrationDepthSolver.h | 50 - .../SpuGatheringCollisionTask.cpp | 1432 -- .../SpuGatheringCollisionTask.h | 140 - .../SpuLocalSupport.h | 19 - .../SpuMinkowskiPenetrationDepthSolver.cpp | 347 - .../SpuMinkowskiPenetrationDepthSolver.h | 47 - .../SpuPreferredPenetrationDirections.h | 70 - .../boxBoxDistance.cpp | 1160 -- .../boxBoxDistance.h | 65 - .../SpuNarrowPhaseCollisionTask/readme.txt | 1 - .../SpuSampleTask/SpuSampleTask.cpp | 214 - .../SpuSampleTask/SpuSampleTask.h | 54 - .../SpuSampleTask/readme.txt | 1 - .../SpuSampleTaskProcess.cpp | 222 - .../SpuSampleTaskProcess.h | 153 - .../src/BulletMultiThreaded/SpuSync.h | 149 - .../src/BulletMultiThreaded/TrbDynBody.h | 79 - .../src/BulletMultiThreaded/TrbStateVec.h | 339 - .../Win32ThreadSupport.cpp | 458 - .../BulletMultiThreaded/Win32ThreadSupport.h | 141 - .../btGpu3DGridBroadphase.cpp | 590 - .../btGpu3DGridBroadphase.h | 140 - .../btGpu3DGridBroadphaseSharedCode.h | 430 - .../btGpu3DGridBroadphaseSharedDefs.h | 61 - .../btGpu3DGridBroadphaseSharedTypes.h | 67 - .../src/BulletMultiThreaded/btGpuDefines.h | 211 - .../btGpuUtilsSharedCode.h | 55 - .../btGpuUtilsSharedDefs.h | 52 - .../btParallelConstraintSolver.cpp | 1552 -- .../btParallelConstraintSolver.h | 288 - .../btThreadSupportInterface.cpp | 22 - .../btThreadSupportInterface.h | 89 - .../BulletMultiThreaded/vectormath2bullet.h | 73 - .../src/BulletSoftBody/CMakeLists.txt | 67 - .../btDefaultSoftBodySolver.cpp | 151 - .../BulletSoftBody/btDefaultSoftBodySolver.h | 63 - .../src/BulletSoftBody/btSoftBody.cpp | 3655 ---- .../src/BulletSoftBody/btSoftBody.h | 1000 - .../btSoftBodyConcaveCollisionAlgorithm.cpp | 357 - .../btSoftBodyConcaveCollisionAlgorithm.h | 155 - .../src/BulletSoftBody/btSoftBodyData.h | 217 - .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 1055 -- .../src/BulletSoftBody/btSoftBodyHelpers.h | 143 - .../src/BulletSoftBody/btSoftBodyInternals.h | 908 - ...oftBodyRigidBodyCollisionConfiguration.cpp | 134 - ...tSoftBodyRigidBodyCollisionConfiguration.h | 48 - .../btSoftBodySolverVertexBuffer.h | 165 - .../src/BulletSoftBody/btSoftBodySolvers.h | 154 - .../btSoftRigidCollisionAlgorithm.cpp | 86 - .../btSoftRigidCollisionAlgorithm.h | 75 - .../btSoftRigidDynamicsWorld.cpp | 367 - .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 107 - .../btSoftSoftCollisionAlgorithm.cpp | 48 - .../btSoftSoftCollisionAlgorithm.h | 69 - .../src/BulletSoftBody/btSparseSDF.h | 319 - .../src/BulletSoftBody/premake4.lua | 11 - Code/Physics/Bullet Source/src/CMakeLists.txt | 32 - Code/Physics/Bullet Source/src/Makefile.am | 612 - .../Bullet Source/src/MiniCL/CMakeLists.txt | 69 - .../Bullet Source/src/MiniCL/MiniCL.cpp | 788 - .../src/MiniCL/MiniCLTask/MiniCLTask.cpp | 74 - .../src/MiniCL/MiniCLTask/MiniCLTask.h | 62 - .../src/MiniCL/MiniCLTaskScheduler.cpp | 519 - .../src/MiniCL/MiniCLTaskScheduler.h | 194 - Code/Physics/Bullet Source/src/MiniCL/cl.h | 867 - .../Bullet Source/src/MiniCL/cl_MiniCL_Defs.h | 439 - Code/Physics/Bullet Source/src/MiniCL/cl_gl.h | 113 - .../Bullet Source/src/MiniCL/cl_platform.h | 254 - .../src/vectormath/neon/boolInVec.h | 226 - .../src/vectormath/neon/floatInVec.h | 344 - .../src/vectormath/neon/mat_aos.h | 1631 -- .../src/vectormath/neon/quat_aos.h | 413 - .../src/vectormath/neon/vec_aos.h | 1427 -- .../src/vectormath/neon/vectormath_aos.h | 1890 -- .../src/vectormath/scalar/boolInVec.h | 225 - .../src/vectormath/scalar/floatInVec.h | 343 - .../src/vectormath/scalar/mat_aos.h | 1630 -- .../src/vectormath/scalar/quat_aos.h | 433 - .../src/vectormath/scalar/vec_aos.h | 1426 -- .../src/vectormath/scalar/vectormath_aos.h | 1872 -- .../src/vectormath/sse/boolInVec.h | 247 - .../src/vectormath/sse/floatInVec.h | 340 - .../src/vectormath/sse/mat_aos.h | 2190 --- .../src/vectormath/sse/quat_aos.h | 579 - .../src/vectormath/sse/vec_aos.h | 1455 -- .../src/vectormath/sse/vecidx_aos.h | 80 - .../src/vectormath/sse/vectormath_aos.h | 2547 --- .../Bullet Source/src/vectormath/vmInclude.h | 31 - Code/Physics/Bullet Source/test1.oec | 227 - Code/Physics/BulletConfig.cmake | 25 - Code/Physics/CMakeCache.txt | 471 - .../CMakeFiles/2.8.12.2/CMakeCCompiler.cmake | 56 - .../2.8.12.2/CMakeCXXCompiler.cmake | 57 - .../2.8.12.2/CMakeDetermineCompilerABI_C.bin | Bin 30208 -> 0 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 30208 -> 0 bytes .../CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake | 6 - .../CMakeFiles/2.8.12.2/CMakeSystem.cmake | 15 - .../2.8.12.2/CompilerIdC/CMakeCCompilerId.c | 389 - .../2.8.12.2/CompilerIdC/CompilerIdC.vcxproj | 52 - .../CompilerIdC/Debug/CMakeCCompilerId.obj | Bin 1497 -> 0 bytes .../Debug/CompilerIdC.lastbuildstate | 2 - .../CompilerIdC/Debug/CompilerIdC.log | 17 - .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 377 - .../CompilerIdCXX/CompilerIdCXX.vcxproj | 52 - .../Debug/CMakeCXXCompilerId.obj | Bin 1495 -> 0 bytes .../Debug/CompilerIdCXX.lastbuildstate | 2 - .../CompilerIdCXX/Debug/CompilerIdCXX.log | 17 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - Code/Physics/CMakeFiles/CMakeOutput.log | 119 - Code/Physics/CMakeFiles/TargetDirectories.txt | 10 - .../ALL_BUILD.rule | 1 - .../INSTALL_force.rule | 1 - .../ZERO_CHECK.rule | 1 - .../generate.stamp.rule | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - Code/Physics/CMakeFiles/cmake.check_cache | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - .../INSTALL_force.rule | 1 - Code/Physics/CMakeFiles/generate.stamp | 1 - Code/Physics/CMakeFiles/generate.stamp.depend | 33 - Code/Physics/CMakeFiles/generate.stamp.list | 12 - Code/Physics/INSTALL.vcxproj | 217 - Code/Physics/ZERO_CHECK.vcxproj | 217 - Code/Physics/cmake_install.cmake | 52 - .../BulletCollision/BulletCollision.vcxproj | 485 - .../BulletCollision/CMakeFiles/generate.stamp | 1 - .../CMakeFiles/generate.stamp.depend | 2 - .../src/BulletCollision/INSTALL.vcxproj | 217 - .../src/BulletCollision/cmake_install.cmake | 29 - .../src/BulletDynamics/BulletDynamics.vcxproj | 343 - .../BulletDynamics/CMakeFiles/generate.stamp | 1 - .../CMakeFiles/generate.stamp.depend | 2 - .../src/BulletDynamics/INSTALL.vcxproj | 217 - .../src/BulletDynamics/cmake_install.cmake | 29 - .../BulletMultiThreaded.vcxproj | 316 - .../CMakeFiles/generate.stamp | 1 - .../CMakeFiles/generate.stamp.depend | 2 - .../CMakeFiles/generate.stamp | 1 - .../CMakeFiles/generate.stamp.depend | 2 - .../DX11/BulletSoftBodySolvers_DX11.vcxproj | 293 - .../DX11/CMakeFiles/generate.stamp | 1 - .../DX11/CMakeFiles/generate.stamp.depend | 2 - .../GpuSoftBodySolvers/DX11/INSTALL.vcxproj | 217 - .../DX11/cmake_install.cmake | 29 - .../GpuSoftBodySolvers/INSTALL.vcxproj | 217 - .../OpenCL/CMakeFiles/generate.stamp | 1 - .../OpenCL/CMakeFiles/generate.stamp.depend | 2 - .../GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj | 217 - .../BulletSoftBodySolvers_OpenCL_Mini.vcxproj | 284 - .../OpenCL/MiniCL/CMakeFiles/generate.stamp | 1 - .../MiniCL/CMakeFiles/generate.stamp.depend | 2 - .../OpenCL/MiniCL/INSTALL.vcxproj | 217 - .../OpenCL/MiniCL/cmake_install.cmake | 29 - .../OpenCL/cmake_install.cmake | 35 - .../GpuSoftBodySolvers/cmake_install.cmake | 36 - .../src/BulletMultiThreaded/INSTALL.vcxproj | 217 - .../BulletMultiThreaded/cmake_install.cmake | 35 - .../src/BulletSoftBody/BulletSoftBody.vcxproj | 288 - .../BulletSoftBody/CMakeFiles/generate.stamp | 1 - .../CMakeFiles/generate.stamp.depend | 2 - .../src/BulletSoftBody/INSTALL.vcxproj | 217 - .../src/BulletSoftBody/cmake_install.cmake | 29 - Code/Physics/src/CMakeFiles/generate.stamp | 1 - .../src/CMakeFiles/generate.stamp.depend | 2 - Code/Physics/src/INSTALL.vcxproj | 217 - .../src/LinearMath/CMakeFiles/generate.stamp | 1 - .../CMakeFiles/generate.stamp.depend | 2 - Code/Physics/src/LinearMath/INSTALL.vcxproj | 217 - .../Physics/src/LinearMath/LinearMath.vcxproj | 300 - .../src/LinearMath/cmake_install.cmake | 29 - .../src/MiniCL/CMakeFiles/generate.stamp | 1 - .../MiniCL/CMakeFiles/generate.stamp.depend | 2 - Code/Physics/src/MiniCL/INSTALL.vcxproj | 217 - Code/Physics/src/MiniCL/MiniCL.vcxproj | 277 - Code/Physics/src/MiniCL/cmake_install.cmake | 29 - Code/Physics/src/cmake_install.cmake | 40 - Code/suoFE00.tmp | Bin 0 -> 1536 bytes 663 files changed, 1 insertion(+), 107905 deletions(-) delete mode 100644 Code/Physics/ALL_BUILD.vcxproj delete mode 100644 Code/Physics/BULLET_PHYSICS.sln delete mode 100644 Code/Physics/Bullet Source/AUTHORS delete mode 100644 Code/Physics/Bullet Source/BspDemo.bsp rename Code/Physics/Bullet Source/{src => }/Bullet-C-Api.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btAxisSweep3.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btDbvt.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btDbvt.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btDispatcher.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btDispatcher.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btQuantizedBvh.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CMakeLists.txt (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/SphereTriangleDetector.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btBoxBoxDetector.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionConfiguration.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionDispatcher.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionObject.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionObject.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionWorld.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCollisionWorld.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btGhostObject.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btGhostObject.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btManifoldResult.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btManifoldResult.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSimulationIslandManager.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btUnionFind.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionDispatch/btUnionFind.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btBox2dShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btBox2dShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btBoxShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btBoxShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCapsuleShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCapsuleShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCollisionMargin.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCollisionShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCollisionShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCompoundShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCompoundShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConcaveShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConcaveShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConeShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConeShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvex2dShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvex2dShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexHullShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexHullShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexInternalShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexInternalShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexPointCloudShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexPolyhedron.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCylinderShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btCylinderShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btEmptyShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btEmptyShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMaterial.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMinkowskiSumShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMultiSphereShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMultiSphereShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btOptimizedBvh.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btOptimizedBvh.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btShapeHull.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btShapeHull.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btSphereShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btSphereShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btStaticPlaneShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btStridingMeshInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTetrahedronShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTetrahedronShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleBuffer.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleBuffer.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleCallback.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleCallback.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleInfoMap.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleMesh.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleMesh.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleMeshShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btTriangleShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btUniformScalingShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/CollisionShapes/btUniformScalingShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Doxyfile (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btBoxCollision.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btClipPolygon.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btCompoundFromGimpact.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btContactProcessing.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btContactProcessing.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactBvh.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactBvh.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactMassUtil.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactQuantizedBvh.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactShape.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGImpactShape.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGenericPoolAllocator.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGenericPoolAllocator.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btGeometryOperations.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btQuantization.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btTriangleShapeEx.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/btTriangleShapeEx.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_array.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_basic_geometry_operations.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_bitset.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_box_collision.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_box_set.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_box_set.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_clip_polygon.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_contact.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_contact.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_geom_types.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_geometry.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_hash_table.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_linear_math.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_math.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_memory.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_memory.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_radixsort.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_tri_collision.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/Gimpact/gim_tri_collision.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btConvexCast.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btPointCollector.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletCollision/premake4.lua (100%) delete mode 100644 Code/Physics/Bullet Source/BulletConfig.cmake.in rename Code/Physics/Bullet Source/{src => }/BulletDynamics/CMakeLists.txt (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Character/btCharacterControllerInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Character/btKinematicCharacterController.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Character/btKinematicCharacterController.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btConstraintSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btContactConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btContactConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btContactSolverInfo.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btFixedConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btGearConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btGearConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btHinge2Constraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btHingeConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btJacobianEntry.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSliderConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSolverBody.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btSolverConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btTypedConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/ConstraintSolver/btUniversalConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/Bullet-C-API.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btActionInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btDynamicsWorld.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btRigidBody.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btRigidBody.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBody.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBody.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyJointMotor.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyLink.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btDantzigLCP.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btDantzigSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btMLCPSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btPATHSolver.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Vehicle/btRaycastVehicle.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Vehicle/btRaycastVehicle.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Vehicle/btVehicleRaycaster.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Vehicle/btWheelInfo.cpp (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/Vehicle/btWheelInfo.h (100%) rename Code/Physics/Bullet Source/{src => }/BulletDynamics/premake4.lua (100%) delete mode 100644 Code/Physics/Bullet Source/BulletLicense.txt delete mode 100644 Code/Physics/Bullet Source/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/COPYING delete mode 100644 Code/Physics/Bullet Source/ChangeLog delete mode 100644 Code/Physics/Bullet Source/Doxyfile delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_cpx.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_defs.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_logged.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_tokens.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_void.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/gl.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/glu.h delete mode 100644 Code/Physics/Bullet Source/Glut/EmptyGL/GL/glut.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/glew.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/glext.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/glut.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/glxew.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/glxext.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/wglew.h delete mode 100644 Code/Physics/Bullet Source/Glut/GL/wglext.h delete mode 100644 Code/Physics/Bullet Source/Glut/btGlutInclude.h delete mode 100644 Code/Physics/Bullet Source/INSTALL rename Code/Physics/Bullet Source/{src => }/LinearMath/CMakeLists.txt (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btAabbUtil2.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btAlignedAllocator.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btAlignedAllocator.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btAlignedObjectArray.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btConvexHull.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btConvexHull.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btConvexHullComputer.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btConvexHullComputer.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btDefaultMotionState.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btGeometryUtil.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btGeometryUtil.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btGrahamScan2dConvexHull.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btHashMap.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btIDebugDraw.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btList.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btMatrix3x3.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btMatrixX.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btMinMax.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btMotionState.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btPolarDecomposition.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btPolarDecomposition.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btPoolAllocator.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btQuadWord.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btQuaternion.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btQuickprof.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btQuickprof.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btRandom.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btScalar.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btSerializer.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btSerializer.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btStackAlloc.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btTransform.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btTransformUtil.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btVector3.cpp (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/btVector3.h (100%) rename Code/Physics/Bullet Source/{src => }/LinearMath/premake4.lua (100%) delete mode 100644 Code/Physics/Bullet Source/Makefile.am delete mode 100644 Code/Physics/Bullet Source/NEWS delete mode 100644 Code/Physics/Bullet Source/README delete mode 100644 Code/Physics/Bullet Source/RELEASING.TXT delete mode 100644 Code/Physics/Bullet Source/UseBullet.cmake delete mode 100644 Code/Physics/Bullet Source/VERSION delete mode 100644 Code/Physics/Bullet Source/acinclude.m4 delete mode 100644 Code/Physics/Bullet Source/autogen.sh rename Code/Physics/Bullet Source/{src => }/btBulletCollisionCommon.h (100%) rename Code/Physics/Bullet Source/{src => }/btBulletDynamicsCommon.h (100%) delete mode 100644 Code/Physics/Bullet Source/bullet.pc.cmake delete mode 100644 Code/Physics/Bullet Source/bullet.pc.in delete mode 100644 Code/Physics/Bullet Source/bullet_logo.png delete mode 100644 Code/Physics/Bullet Source/config.h.in delete mode 100644 Code/Physics/Bullet Source/configure.ac delete mode 100644 Code/Physics/Bullet Source/convex0.bin delete mode 100644 Code/Physics/Bullet Source/file.obj delete mode 100644 Code/Physics/Bullet Source/heightfield128x128.raw delete mode 100644 Code/Physics/Bullet Source/install-sh delete mode 100644 Code/Physics/Bullet Source/jenga.dae delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/HeapManager.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/PlatformDefinitions.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/PpuAddressSpace.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuDoubleBuffer.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuFakeDma.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuFakeDma.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/readme.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSync.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbDynBody.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbStateVec.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuDefines.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuUtilsSharedCode.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuUtilsSharedDefs.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.h delete mode 100644 Code/Physics/Bullet Source/src/BulletMultiThreaded/vectormath2bullet.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyData.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyInternals.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolvers.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/btSparseSDF.h delete mode 100644 Code/Physics/Bullet Source/src/BulletSoftBody/premake4.lua delete mode 100644 Code/Physics/Bullet Source/src/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/Makefile.am delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/MiniCL.cpp delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.cpp delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.h delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.cpp delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.h delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/cl.h delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/cl_MiniCL_Defs.h delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/cl_gl.h delete mode 100644 Code/Physics/Bullet Source/src/MiniCL/cl_platform.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/neon/boolInVec.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/neon/floatInVec.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/neon/mat_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/neon/quat_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/neon/vec_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/neon/vectormath_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/scalar/boolInVec.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/scalar/floatInVec.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/scalar/mat_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/scalar/quat_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/scalar/vec_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/scalar/vectormath_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/boolInVec.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/floatInVec.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/mat_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/quat_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/vec_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/vecidx_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/sse/vectormath_aos.h delete mode 100644 Code/Physics/Bullet Source/src/vectormath/vmInclude.h delete mode 100644 Code/Physics/Bullet Source/test1.oec delete mode 100644 Code/Physics/BulletConfig.cmake delete mode 100644 Code/Physics/CMakeCache.txt delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CMakeCCompilerId.obj delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CompilerIdCXX.lastbuildstate delete mode 100644 Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CompilerIdCXX.log delete mode 100644 Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/CMakeOutput.log delete mode 100644 Code/Physics/CMakeFiles/TargetDirectories.txt delete mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule delete mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule delete mode 100644 Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule delete mode 100644 Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/cmake.check_cache delete mode 100644 Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule delete mode 100644 Code/Physics/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/CMakeFiles/generate.stamp.list delete mode 100644 Code/Physics/INSTALL.vcxproj delete mode 100644 Code/Physics/ZERO_CHECK.vcxproj delete mode 100644 Code/Physics/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletCollision/BulletCollision.vcxproj delete mode 100644 Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletCollision/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletCollision/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj delete mode 100644 Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletDynamics/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletDynamics/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletMultiThreaded/cmake_install.cmake delete mode 100644 Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj delete mode 100644 Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/BulletSoftBody/INSTALL.vcxproj delete mode 100644 Code/Physics/src/BulletSoftBody/cmake_install.cmake delete mode 100644 Code/Physics/src/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/INSTALL.vcxproj delete mode 100644 Code/Physics/src/LinearMath/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/LinearMath/INSTALL.vcxproj delete mode 100644 Code/Physics/src/LinearMath/LinearMath.vcxproj delete mode 100644 Code/Physics/src/LinearMath/cmake_install.cmake delete mode 100644 Code/Physics/src/MiniCL/CMakeFiles/generate.stamp delete mode 100644 Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend delete mode 100644 Code/Physics/src/MiniCL/INSTALL.vcxproj delete mode 100644 Code/Physics/src/MiniCL/MiniCL.vcxproj delete mode 100644 Code/Physics/src/MiniCL/cmake_install.cmake delete mode 100644 Code/Physics/src/cmake_install.cmake create mode 100644 Code/suoFE00.tmp diff --git a/Code/DanBias.sln b/Code/DanBias.sln index 68ed1d24..a8d583d8 100644 --- a/Code/DanBias.sln +++ b/Code/DanBias.sln @@ -24,11 +24,6 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetworkDependencies", "Network\NetworkDependencies\NetworkDependencies.vcxproj", "{C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamePhysics", "GamePhysics\GamePhysics.vcxproj", "{104FA3E9-94D9-4E1D-A941-28A03BC8A095}" - ProjectSection(ProjectDependencies) = postProject - {D4985405-3286-4026-BD61-E9E53DC5027E} = {D4985405-3286-4026-BD61-E9E53DC5027E} - {C933A737-D7BA-4136-95AF-D12310BD6BA8} = {C933A737-D7BA-4136-95AF-D12310BD6BA8} - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} = {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} - EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasGame", "Game\DanBiasGame\DanBiasGame.vcxproj", "{2A1BC987-AF42-4500-802D-89CD32FC1309}" EndProject @@ -50,12 +45,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aDanBiasGameLauncher", "Gam EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Physics", "Physics", "{0D86E569-9C74-47F0-BDB2-390C0C9A084B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "Physics\src\BulletCollision\BulletCollision.vcxproj", "{C933A737-D7BA-4136-95AF-D12310BD6BA8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "Physics\src\LinearMath\LinearMath.vcxproj", "{D4985405-3286-4026-BD61-E9E53DC5027E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletDynamics", "Physics\src\BulletDynamics\BulletDynamics.vcxproj", "{74EDC06C-85E5-47BC-B42D-F55CE6E9928B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms @@ -510,66 +499,6 @@ Global {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Win32.Build.0 = Release|Win32 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.ActiveCfg = Release|x64 {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.Build.0 = Release|x64 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.ActiveCfg = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.Build.0 = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|x64.ActiveCfg = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.ActiveCfg = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.Build.0 = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|x64.ActiveCfg = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.ActiveCfg = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.Build.0 = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|x64.ActiveCfg = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Mixed Platforms.Build.0 = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.ActiveCfg = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.Build.0 = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|x64.ActiveCfg = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.ActiveCfg = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.Build.0 = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|x64.ActiveCfg = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Mixed Platforms.ActiveCfg = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Mixed Platforms.Build.0 = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Mixed Platforms.Build.0 = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.ActiveCfg = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.Build.0 = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|x64.ActiveCfg = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Mixed Platforms.ActiveCfg = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Mixed Platforms.Build.0 = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -586,8 +515,5 @@ Global {060B1890-CBF3-4808-BA99-A4776222093B} = {20720CA7-795C-45AD-A302-9383A6DD503A} {143BD516-20A1-4890-A3E4-F8BFD02220E7} = {20720CA7-795C-45AD-A302-9383A6DD503A} {666FEA52-975F-41CD-B224-B19AF3C0ABBA} = {20720CA7-795C-45AD-A302-9383A6DD503A} - {C933A737-D7BA-4136-95AF-D12310BD6BA8} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} - {D4985405-3286-4026-BD61-E9E53DC5027E} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} = {0D86E569-9C74-47F0-BDB2-390C0C9A084B} EndGlobalSection EndGlobal diff --git a/Code/GamePhysics/GamePhysics.vcxproj b/Code/GamePhysics/GamePhysics.vcxproj index a9746245..84d380be 100644 --- a/Code/GamePhysics/GamePhysics.vcxproj +++ b/Code/GamePhysics/GamePhysics.vcxproj @@ -89,7 +89,7 @@ Level3 Disabled - $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\src;%(AdditionalIncludeDirectories) + $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\;%(AdditionalIncludeDirectories) _WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions) false diff --git a/Code/Physics/ALL_BUILD.vcxproj b/Code/Physics/ALL_BUILD.vcxproj deleted file mode 100644 index 545f3181..00000000 --- a/Code/Physics/ALL_BUILD.vcxproj +++ /dev/null @@ -1,244 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {14E546AD-2393-41B9-BAA2-134241286A4E} - Win32Proj - Win32 - ALL_BUILD - - - - Utility - false - MultiByte - v110 - - - Utility - false - MultiByte - v110 - - - Utility - false - MultiByte - v110 - - - Utility - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp - false - - - - - Build all projects - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD - false - Build all projects - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD - false - Build all projects - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD - false - Build all projects - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ALL_BUILD - false - - - - - - - - C933A737-D7BA-4136-95AF-D12310BD6BA8 - - - 74EDC06C-85E5-47BC-B42D-F55CE6E9928B - - - 83B388D3-BE71-476A-AA6A-CC7082E3866D - - - 14DC504E-697F-4178-8E05-87173957FE59 - - - 2CF89262-94E6-4A9F-A29A-1BE6D73DDA85 - - - 80FC7669-D649-4212-8B6F-C0167CE9CB59 - - - D4985405-3286-4026-BD61-E9E53DC5027E - - - FA9E3157-5228-4CA4-8327-BD0AF11BD390 - - - 53399ED8-C4B0-4F84-9CA8-623049125822 - - - - - - \ No newline at end of file diff --git a/Code/Physics/BULLET_PHYSICS.sln b/Code/Physics/BULLET_PHYSICS.sln deleted file mode 100644 index b7c18743..00000000 --- a/Code/Physics/BULLET_PHYSICS.sln +++ /dev/null @@ -1,162 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{14E546AD-2393-41B9-BAA2-134241286A4E}" - ProjectSection(ProjectDependencies) = postProject - {C933A737-D7BA-4136-95AF-D12310BD6BA8} = {C933A737-D7BA-4136-95AF-D12310BD6BA8} - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} = {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} - {83B388D3-BE71-476A-AA6A-CC7082E3866D} = {83B388D3-BE71-476A-AA6A-CC7082E3866D} - {14DC504E-697F-4178-8E05-87173957FE59} = {14DC504E-697F-4178-8E05-87173957FE59} - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85} = {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85} - {80FC7669-D649-4212-8B6F-C0167CE9CB59} = {80FC7669-D649-4212-8B6F-C0167CE9CB59} - {D4985405-3286-4026-BD61-E9E53DC5027E} = {D4985405-3286-4026-BD61-E9E53DC5027E} - {FA9E3157-5228-4CA4-8327-BD0AF11BD390} = {FA9E3157-5228-4CA4-8327-BD0AF11BD390} - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletCollision", "src\BulletCollision\BulletCollision.vcxproj", "{C933A737-D7BA-4136-95AF-D12310BD6BA8}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletDynamics", "src\BulletDynamics\BulletDynamics.vcxproj", "{74EDC06C-85E5-47BC-B42D-F55CE6E9928B}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletMultiThreaded", "src\BulletMultiThreaded\BulletMultiThreaded.vcxproj", "{83B388D3-BE71-476A-AA6A-CC7082E3866D}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletSoftBody", "src\BulletSoftBody\BulletSoftBody.vcxproj", "{14DC504E-697F-4178-8E05-87173957FE59}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletSoftBodySolvers_DX11", "src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\BulletSoftBodySolvers_DX11.vcxproj", "{2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BulletSoftBodySolvers_OpenCL_Mini", "src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\BulletSoftBodySolvers_OpenCL_Mini.vcxproj", "{80FC7669-D649-4212-8B6F-C0167CE9CB59}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INSTALL", "INSTALL.vcxproj", "{71641E56-5E9E-462B-844F-A9F8A6D82120}" - ProjectSection(ProjectDependencies) = postProject - {14E546AD-2393-41B9-BAA2-134241286A4E} = {14E546AD-2393-41B9-BAA2-134241286A4E} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinearMath", "src\LinearMath\LinearMath.vcxproj", "{D4985405-3286-4026-BD61-E9E53DC5027E}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MiniCL", "src\MiniCL\MiniCL.vcxproj", "{FA9E3157-5228-4CA4-8327-BD0AF11BD390}" - ProjectSection(ProjectDependencies) = postProject - {53399ED8-C4B0-4F84-9CA8-623049125822} = {53399ED8-C4B0-4F84-9CA8-623049125822} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{53399ED8-C4B0-4F84-9CA8-623049125822}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - MinSizeRel|Win32 = MinSizeRel|Win32 - RelWithDebInfo|Win32 = RelWithDebInfo|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {14E546AD-2393-41B9-BAA2-134241286A4E}.Debug|Win32.ActiveCfg = Debug|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.Debug|Win32.Build.0 = Debug|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.Release|Win32.ActiveCfg = Release|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.Release|Win32.Build.0 = Release|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {14E546AD-2393-41B9-BAA2-134241286A4E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.ActiveCfg = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Debug|Win32.Build.0 = Debug|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.ActiveCfg = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.Release|Win32.Build.0 = Release|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {C933A737-D7BA-4136-95AF-D12310BD6BA8}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.ActiveCfg = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Debug|Win32.Build.0 = Debug|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.ActiveCfg = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.Release|Win32.Build.0 = Release|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Debug|Win32.ActiveCfg = Debug|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Debug|Win32.Build.0 = Debug|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Release|Win32.ActiveCfg = Release|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.Release|Win32.Build.0 = Release|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {83B388D3-BE71-476A-AA6A-CC7082E3866D}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.Debug|Win32.ActiveCfg = Debug|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.Debug|Win32.Build.0 = Debug|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.Release|Win32.ActiveCfg = Release|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.Release|Win32.Build.0 = Release|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {14DC504E-697F-4178-8E05-87173957FE59}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Debug|Win32.ActiveCfg = Debug|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Debug|Win32.Build.0 = Debug|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Release|Win32.ActiveCfg = Release|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.Release|Win32.Build.0 = Release|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Debug|Win32.ActiveCfg = Debug|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Debug|Win32.Build.0 = Debug|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Release|Win32.ActiveCfg = Release|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.Release|Win32.Build.0 = Release|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {80FC7669-D649-4212-8B6F-C0167CE9CB59}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {71641E56-5E9E-462B-844F-A9F8A6D82120}.Debug|Win32.ActiveCfg = Debug|Win32 - {71641E56-5E9E-462B-844F-A9F8A6D82120}.Release|Win32.ActiveCfg = Release|Win32 - {71641E56-5E9E-462B-844F-A9F8A6D82120}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {71641E56-5E9E-462B-844F-A9F8A6D82120}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.ActiveCfg = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Debug|Win32.Build.0 = Debug|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.ActiveCfg = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.Release|Win32.Build.0 = Release|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {D4985405-3286-4026-BD61-E9E53DC5027E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Debug|Win32.ActiveCfg = Debug|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Debug|Win32.Build.0 = Debug|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Release|Win32.ActiveCfg = Release|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.Release|Win32.Build.0 = Release|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {FA9E3157-5228-4CA4-8327-BD0AF11BD390}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.Debug|Win32.ActiveCfg = Debug|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.Debug|Win32.Build.0 = Debug|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.Release|Win32.ActiveCfg = Release|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.Release|Win32.Build.0 = Release|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32 - {53399ED8-C4B0-4F84-9CA8-623049125822}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/Code/Physics/Bullet Source/AUTHORS b/Code/Physics/Bullet Source/AUTHORS deleted file mode 100644 index f2cc86dd..00000000 --- a/Code/Physics/Bullet Source/AUTHORS +++ /dev/null @@ -1,22 +0,0 @@ - -Bullet Physics Library is an open source project with help from the community at the Physics Forum -See the forum at http://bulletphysics.com - -The project was started by Erwin Coumans - -Following people contributed to Bullet -(random order, please let us know on the forum if your name should be in this list) - -Gino van den Bergen: LinearMath classes -Christer Ericson: parts of the voronoi simplex solver -Simon Hobbs: 3d axis sweep and prune, Extras/SATCollision, separating axis theorem + SIMD code -Dirk Gregorius: generic D6 constraint -Erin Catto: accumulated impulse in sequential impulse -Nathanael Presson: EPA penetration depth calculation -Francisco Leon: GIMPACT Concave Concave collision -Joerg Henrichs: make buildsystem (work in progress) -Eric Sunshine: jam + msvcgen buildsystem -Steve Baker: GPU physics and general implementation improvements -Jay Lee: Double precision support -KleMiX, aka Vsevolod Klementjev, managed version, rewritten in C# for XNA -Erwin Coumans: most other source code diff --git a/Code/Physics/Bullet Source/BspDemo.bsp b/Code/Physics/Bullet Source/BspDemo.bsp deleted file mode 100644 index 4ed414d75b92d4d94b05589c46bc8f66bee34686..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105100 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 HQ-1y*qN~We diff --git a/Code/Physics/Bullet Source/src/Bullet-C-Api.h b/Code/Physics/Bullet Source/Bullet-C-Api.h similarity index 100% rename from Code/Physics/Bullet Source/src/Bullet-C-Api.h rename to Code/Physics/Bullet Source/Bullet-C-Api.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvt.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btDispatcher.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h rename to Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt b/Code/Physics/Bullet Source/BulletCollision/CMakeLists.txt similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt rename to Code/Physics/Bullet Source/BulletCollision/CMakeLists.txt diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/SphereTriangleDetector.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/SphereTriangleDetector.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxDetector.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btBoxBoxDetector.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionConfiguration.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionConfiguration.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionDispatcher.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionDispatcher.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionObject.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionObject.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionObject.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObject.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionObject.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionWorld.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionWorld.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionWorld.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCollisionWorld.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCollisionWorld.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btGhostObject.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btGhostObject.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btGhostObject.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btGhostObject.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btGhostObject.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btManifoldResult.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btManifoldResult.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btManifoldResult.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btManifoldResult.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btManifoldResult.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSimulationIslandManager.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSimulationIslandManager.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btUnionFind.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btUnionFind.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.h b/Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btUnionFind.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionDispatch/btUnionFind.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionDispatch/btUnionFind.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBox2dShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBox2dShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBox2dShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBox2dShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBox2dShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBoxShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBoxShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBoxShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBoxShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBoxShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCapsuleShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCapsuleShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCapsuleShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCapsuleShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCapsuleShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCollisionMargin.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionMargin.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCollisionMargin.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCollisionShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCollisionShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCollisionShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCollisionShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCollisionShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCompoundShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCompoundShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCompoundShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCompoundShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCompoundShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConcaveShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConcaveShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConcaveShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConcaveShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConcaveShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConeShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConeShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConeShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConeShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConeShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvex2dShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvex2dShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvex2dShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvex2dShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvex2dShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexHullShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexHullShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexHullShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexHullShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexHullShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexInternalShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexInternalShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexInternalShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexInternalShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexInternalShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPointCloudShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPointCloudShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPolyhedron.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexPolyhedron.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCylinderShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCylinderShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCylinderShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btCylinderShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btCylinderShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btEmptyShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btEmptyShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btEmptyShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btEmptyShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btEmptyShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMaterial.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMaterial.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMaterial.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMaterial.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMinkowskiSumShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMinkowskiSumShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultiSphereShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultiSphereShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultiSphereShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultiSphereShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultiSphereShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btOptimizedBvh.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btOptimizedBvh.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btOptimizedBvh.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btOptimizedBvh.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btOptimizedBvh.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btShapeHull.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btShapeHull.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btShapeHull.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btShapeHull.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btShapeHull.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btSphereShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btSphereShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btSphereShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btSphereShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btSphereShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStaticPlaneShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStaticPlaneShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStridingMeshInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btStridingMeshInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTetrahedronShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTetrahedronShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTetrahedronShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTetrahedronShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTetrahedronShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleBuffer.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleBuffer.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleBuffer.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleBuffer.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleBuffer.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleCallback.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleCallback.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleCallback.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleCallback.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleCallback.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleInfoMap.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleInfoMap.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMesh.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMesh.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMesh.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMesh.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMesh.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMeshShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleMeshShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btTriangleShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btTriangleShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btUniformScalingShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btUniformScalingShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btUniformScalingShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/CollisionShapes/btUniformScalingShape.h rename to Code/Physics/Bullet Source/BulletCollision/CollisionShapes/btUniformScalingShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Doxyfile b/Code/Physics/Bullet Source/BulletCollision/Doxyfile similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Doxyfile rename to Code/Physics/Bullet Source/BulletCollision/Doxyfile diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btBoxCollision.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btBoxCollision.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btBoxCollision.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btBoxCollision.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btClipPolygon.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btClipPolygon.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btClipPolygon.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btClipPolygon.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btCompoundFromGimpact.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btCompoundFromGimpact.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btCompoundFromGimpact.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btCompoundFromGimpact.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btContactProcessing.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btContactProcessing.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btContactProcessing.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btContactProcessing.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btContactProcessing.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactBvh.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactBvh.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactBvh.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactBvh.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactBvh.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactMassUtil.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactMassUtil.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactMassUtil.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactQuantizedBvh.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactQuantizedBvh.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactShape.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactShape.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactShape.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGImpactShape.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGImpactShape.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGenericPoolAllocator.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGenericPoolAllocator.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGenericPoolAllocator.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGenericPoolAllocator.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGenericPoolAllocator.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGeometryOperations.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btGeometryOperations.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btGeometryOperations.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btGeometryOperations.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btQuantization.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btQuantization.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btQuantization.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btQuantization.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btTriangleShapeEx.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btTriangleShapeEx.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/btTriangleShapeEx.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/btTriangleShapeEx.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/btTriangleShapeEx.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_array.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_array.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_array.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_array.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_basic_geometry_operations.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_basic_geometry_operations.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_bitset.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_bitset.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_bitset.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_bitset.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_collision.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_box_collision.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_collision.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_box_collision.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_box_set.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_box_set.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_box_set.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_box_set.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_box_set.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_clip_polygon.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_clip_polygon.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_clip_polygon.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_clip_polygon.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_contact.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_contact.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_contact.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_contact.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_contact.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geom_types.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_geom_types.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geom_types.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_geom_types.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geometry.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_geometry.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_geometry.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_geometry.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_hash_table.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_hash_table.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_hash_table.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_hash_table.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_linear_math.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_linear_math.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_linear_math.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_linear_math.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_math.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_math.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_math.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_math.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_memory.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_memory.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_memory.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_memory.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_memory.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_radixsort.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_radixsort.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_radixsort.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_radixsort.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_tri_collision.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.cpp rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_tri_collision.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.h b/Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_tri_collision.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/Gimpact/gim_tri_collision.h rename to Code/Physics/Bullet Source/BulletCollision/Gimpact/gim_tri_collision.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btConvexCast.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btConvexCast.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPointCollector.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPointCollector.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp diff --git a/Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h rename to Code/Physics/Bullet Source/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletCollision/premake4.lua b/Code/Physics/Bullet Source/BulletCollision/premake4.lua similarity index 100% rename from Code/Physics/Bullet Source/src/BulletCollision/premake4.lua rename to Code/Physics/Bullet Source/BulletCollision/premake4.lua diff --git a/Code/Physics/Bullet Source/BulletConfig.cmake.in b/Code/Physics/Bullet Source/BulletConfig.cmake.in deleted file mode 100644 index f5dc7bdb..00000000 --- a/Code/Physics/Bullet Source/BulletConfig.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -# -*- cmake -*- -# -# BulletConfig.cmake(.in) -# - -# Use the following variables to compile and link against Bullet: -# BULLET_FOUND - True if Bullet was found on your system -# BULLET_USE_FILE - The file making Bullet usable -# BULLET_DEFINITIONS - Definitions needed to build with Bullet -# BULLET_INCLUDE_DIR - Directory where Bullet-C-Api.h can be found -# BULLET_INCLUDE_DIRS - List of directories of Bullet and it's dependencies -# BULLET_LIBRARIES - List of libraries to link against Bullet library -# BULLET_LIBRARY_DIRS - List of directories containing Bullet' libraries -# BULLET_ROOT_DIR - The base directory of Bullet -# BULLET_VERSION_STRING - A human-readable string containing the version - -set ( BULLET_FOUND 1 ) -set ( BULLET_USE_FILE "@BULLET_USE_FILE@" ) -set ( BULLET_DEFINITIONS "@BULLET_DEFINITIONS@" ) -set ( BULLET_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@" ) -set ( BULLET_INCLUDE_DIRS "@INCLUDE_INSTALL_DIR@" ) -set ( BULLET_LIBRARIES "@BULLET_LIBRARIES@" ) -set ( BULLET_LIBRARY_DIRS "@LIB_DESTINATION@" ) -set ( BULLET_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" ) -set ( BULLET_VERSION_STRING "@BULLET_VERSION@" ) \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt b/Code/Physics/Bullet Source/BulletDynamics/CMakeLists.txt similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt rename to Code/Physics/Bullet Source/BulletDynamics/CMakeLists.txt diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Character/btCharacterControllerInterface.h b/Code/Physics/Bullet Source/BulletDynamics/Character/btCharacterControllerInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Character/btCharacterControllerInterface.h rename to Code/Physics/Bullet Source/BulletDynamics/Character/btCharacterControllerInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/Code/Physics/Bullet Source/BulletDynamics/Character/btKinematicCharacterController.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Character/btKinematicCharacterController.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.h b/Code/Physics/Bullet Source/BulletDynamics/Character/btKinematicCharacterController.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Character/btKinematicCharacterController.h rename to Code/Physics/Bullet Source/BulletDynamics/Character/btKinematicCharacterController.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btConstraintSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btConstraintSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btContactConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btContactConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btContactConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btContactConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btContactSolverInfo.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btContactSolverInfo.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btFixedConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btFixedConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGearConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGearConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGearConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGearConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGearConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHinge2Constraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHinge2Constraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHingeConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btHingeConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btJacobianEntry.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btJacobianEntry.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSliderConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSliderConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolverBody.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverBody.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolverBody.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolverConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btSolverConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btTypedConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btTypedConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btUniversalConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/ConstraintSolver/btUniversalConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/Bullet-C-API.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/Bullet-C-API.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/Bullet-C-API.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btActionInterface.h b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btActionInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btActionInterface.h rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btActionInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btDynamicsWorld.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btDynamicsWorld.h rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btDynamicsWorld.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.cpp b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btRigidBody.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btRigidBody.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.h b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btRigidBody.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btRigidBody.h rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btRigidBody.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/Code/Physics/Bullet Source/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h rename to Code/Physics/Bullet Source/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBody.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBody.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBody.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBody.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBody.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointMotor.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyJointMotor.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLink.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyLink.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLink.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyLink.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h rename to Code/Physics/Bullet Source/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btDantzigLCP.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btDantzigLCP.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btDantzigSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btDantzigSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btMLCPSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btMLCPSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btPATHSolver.h b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btPATHSolver.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btPATHSolver.h rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btPATHSolver.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h rename to Code/Physics/Bullet Source/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/Code/Physics/Bullet Source/BulletDynamics/Vehicle/btRaycastVehicle.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Vehicle/btRaycastVehicle.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/Code/Physics/Bullet Source/BulletDynamics/Vehicle/btRaycastVehicle.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btRaycastVehicle.h rename to Code/Physics/Bullet Source/BulletDynamics/Vehicle/btRaycastVehicle.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/Code/Physics/Bullet Source/BulletDynamics/Vehicle/btVehicleRaycaster.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btVehicleRaycaster.h rename to Code/Physics/Bullet Source/BulletDynamics/Vehicle/btVehicleRaycaster.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/Code/Physics/Bullet Source/BulletDynamics/Vehicle/btWheelInfo.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.cpp rename to Code/Physics/Bullet Source/BulletDynamics/Vehicle/btWheelInfo.cpp diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.h b/Code/Physics/Bullet Source/BulletDynamics/Vehicle/btWheelInfo.h similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/Vehicle/btWheelInfo.h rename to Code/Physics/Bullet Source/BulletDynamics/Vehicle/btWheelInfo.h diff --git a/Code/Physics/Bullet Source/src/BulletDynamics/premake4.lua b/Code/Physics/Bullet Source/BulletDynamics/premake4.lua similarity index 100% rename from Code/Physics/Bullet Source/src/BulletDynamics/premake4.lua rename to Code/Physics/Bullet Source/BulletDynamics/premake4.lua diff --git a/Code/Physics/Bullet Source/BulletLicense.txt b/Code/Physics/Bullet Source/BulletLicense.txt deleted file mode 100644 index 2e5680a8..00000000 --- a/Code/Physics/Bullet Source/BulletLicense.txt +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -Free for commercial use, please report projects in the forum at http://www.bulletphysics.org - -In case you want to display a Bullet logo in your software: you can download the Bullet logo in various vector formats and high resolution at the download section in http://bullet.googlecode.com diff --git a/Code/Physics/Bullet Source/CMakeLists.txt b/Code/Physics/Bullet Source/CMakeLists.txt deleted file mode 100644 index 18a089a9..00000000 --- a/Code/Physics/Bullet Source/CMakeLists.txt +++ /dev/null @@ -1,439 +0,0 @@ -cmake_minimum_required(VERSION 2.4.3) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) - -#this line has to appear before 'PROJECT' in order to be able to disable incremental linking -SET(MSVC_INCREMENTAL_DEFAULT ON) - -PROJECT(BULLET_PHYSICS) -SET(BULLET_VERSION 2.82) - -IF(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - - -IF (NOT CMAKE_BUILD_TYPE) -# SET(CMAKE_BUILD_TYPE "Debug") - SET(CMAKE_BUILD_TYPE "Release") -ENDIF (NOT CMAKE_BUILD_TYPE) - -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") -#MESSAGE("CMAKE_CXX_FLAGS_DEBUG="+${CMAKE_CXX_FLAGS_DEBUG}) - -OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF) -OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON) - - -OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" OFF) -OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF) - -OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF) - -IF (USE_CUSTOM_VECTOR_MATH) - ADD_DEFINITIONS(-DUSE_SYSTEM_VECTORMATH) - IF(WIN32) - SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/sse CACHE PATH "Vector Math library include path.") - ELSE(WIN32) - SET (VECTOR_MATH_INCLUDE ${BULLET_PHYSICS_SOURCE_DIR}/src/vectormath/scalar CACHE PATH "Vector Math library include path.") - ENDIF(WIN32) -ENDIF(USE_CUSTOM_VECTOR_MATH) - - -IF (APPLE OR MSVC) - OPTION(BUILD_MULTITHREADING "Use BulletMultiThreading" ON) -ELSE() - OPTION(BUILD_MULTITHREADING "Use BulletMultiThreading" OFF) -ENDIF() - -IF (BUILD_MULTITHREADING) - OPTION(USE_MULTITHREADED_BENCHMARK "Use Multithreaded Benchmark" OFF) - IF (USE_MULTITHREADED_BENCHMARK) - ADD_DEFINITIONS(-DUSE_PARALLEL_SOLVER_BENCHMARK -DUSE_PARALLEL_DISPATCHER_BENCHMARK) - ENDIF(USE_MULTITHREADED_BENCHMARK) - - IF (MSVC OR APPLE) - OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" ON) - ELSE() - OPTION(BUILD_MINICL_OPENCL_DEMOS "Build OpenCL demos for MiniCL (Generic CPU)" OFF) - ENDIF(MSVC OR APPLE) - - IF(MSVC) - FIND_PATH(DIRECTX_SDK_BASE_DIR Include/D3D11.h PATH $ENV{DXSDK_DIR} ) - IF(DIRECTX_SDK_BASE_DIR) - OPTION(USE_DX11 "Use DirectX 11" ON) - ELSE() - OPTION(USE_DX11 "Use DirectX 11" OFF) - ENDIF() - - FIND_PATH(AMD_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{ATISTREAMSDKROOT} $ENV{AMDAPPSDKROOT} ) - IF(AMD_OPENCL_BASE_DIR) - #AMD adds an extras slash at the end of the ATISTREAMSDKROOT variable - SET(AMD_OPENCL_INCLUDES ${AMD_OPENCL_BASE_DIR}/include ) - MESSAGE("AMD OPENCL SDK FOUND") - IF (CMAKE_CL_64) - SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86_64 ) - ELSE(CMAKE_CL_64) - SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86 ) - ENDIF(CMAKE_CL_64) - SET(CMAKE_ATISTREAMSDK_LIBRARY ${CMAKE_ATISTREAMSDK_LIBPATH}/OpenCL.lib ) - OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" ON) - IF (CMAKE_CL_64) - SET(CMAK_GLEW_LIBRARY - ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew64s.lib ) - ELSE(CMAKE_CL_64) - SET(CMAK_GLEW_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glew32s.lib ) - ENDIF(CMAKE_CL_64) - ELSE() - OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" OFF) - ENDIF() - - FIND_PATH(INTEL_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{INTELOCLSDKROOT} ) - IF(INTEL_OPENCL_BASE_DIR) - SET(INTEL_OPENCL_INCLUDES ${INTEL_OPENCL_BASE_DIR}/include ) - MESSAGE("INTEL OPENCL SDK FOUND") - MESSAGE(${INTEL_OPENCL_INCLUDES}) - IF (CMAKE_CL_64) - SET(CMAKE_INTELOCLSDK_LIBPATH ${INTEL_OPENCL_BASE_DIR}/lib/x64 ) - ELSE(CMAKE_CL_64) - SET(CMAKE_INTELOCLSDK_LIBPATH ${INTEL_OPENCL_BASE_DIR}/lib/x86 ) - ENDIF(CMAKE_CL_64) - SET(INTEL_OPENCL_LIBRARIES ${CMAKE_INTELOCLSDK_LIBPATH}/OpenCL.lib) - OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" ON) - ELSE() - OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" OFF) - ENDIF() - - FIND_PATH(NVIDIA_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{CUDA_PATH} ) - IF(NVIDIA_OPENCL_BASE_DIR) - SET(NVIDIA_OPENCL_INCLUDES ${NVIDIA_OPENCL_BASE_DIR}/include ) - MESSAGE("NVIDIA OPENCL SDK FOUND") - MESSAGE(${NVIDIA_OPENCL_INCLUDES}) - IF (CMAKE_CL_64) - SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/lib/x64 ) - ELSE(CMAKE_CL_64) - SET(CMAKE_NVSDKCOMPUTE_LIBPATH ${NVIDIA_OPENCL_BASE_DIR}/lib/Win32 ) - ENDIF(CMAKE_CL_64) - SET(NVIDIA_OPENCL_LIBRARIES ${CMAKE_NVSDKCOMPUTE_LIBPATH}/OpenCL.lib) - - OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) - ELSE() - OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) - ENDIF() - ELSE(MSVC) - FIND_PATH(AMD_OPENCL_BASE_DIR include/CL/cl.h PATH $ENV{ATISTREAMSDKROOT} $ENV{AMDAPPSDKROOT} ) - IF(AMD_OPENCL_BASE_DIR) - #AMD adds an extras slash at the end of the ATISTREAMSDKROOT variable - SET(AMD_OPENCL_INCLUDES ${AMD_OPENCL_BASE_DIR}/include ) - MESSAGE("AMD OPENCL SDK FOUND") - MESSAGE(${AMD_OPENCL_INCLUDES}) - IF (CMAKE_CL_64) - SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86_64 ) - ELSE(CMAKE_CL_64) - SET(CMAKE_ATISTREAMSDK_LIBPATH ${AMD_OPENCL_BASE_DIR}/lib/x86 ) - ENDIF(CMAKE_CL_64) - OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" ON) - SET(CMAKE_ATISTREAMSDK_LIBRARY OpenCL ) - ELSE() - OPTION(BUILD_AMD_OPENCL_DEMOS "Build OpenCL demos for AMD (GPU or CPU)" OFF) - ENDIF(AMD_OPENCL_BASE_DIR) - - FIND_PATH(INTEL_OPENCL_INCLUDES CL/cl.h) - FIND_PATH(INTEL_OPENCL_ICD_CFG intelocl64.icd /etc/OpenCL/vendors) - FIND_LIBRARY(INTEL_OPENCL_LIBRARIES OpenCL PATH /usr/lib64) - IF (INTEL_OPENCL_INCLUDES AND INTEL_OPENCL_LIBRARIES AND INTEL_OPENCL_ICD_CFG) - MESSAGE("INTEL OPENCL SDK FOUND") - MESSAGE(${INTEL_OPENCL_LIBRARIES}) - OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" ON) - ELSE () - MESSAGE("INTEL OPENCL NOT FOUND") - OPTION(BUILD_INTEL_OPENCL_DEMOS "Build OpenCL demos for Intel (CPU)" OFF) - ENDIF () - - - FIND_PATH(NVIDIA_OPENCL_INCLUDES CL/cl.h) - FIND_PATH(NVIDIA_OPENCL_ICD_CFG nvidia.icd /etc/OpenCL/vendors) - FIND_LIBRARY(NVIDIA_OPENCL_LIBRARIES OpenCL PATH /usr/lib64 /usr/local/lib) - IF (NVIDIA_OPENCL_INCLUDES AND NVIDIA_OPENCL_LIBRARIES AND NVIDIA_OPENCL_ICD_CFG) - MESSAGE("NVidia OPENCL FOUND") - MESSAGE(${NVIDIA_OPENCL_LIBRARIES}) - OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" ON) - ELSE () - MESSAGE("NVidia OPENCL NOT FOUND") - OPTION(BUILD_NVIDIA_OPENCL_DEMOS "Build OpenCL demos for NVidia (GPU)" OFF) - ENDIF () - ENDIF(MSVC) - -ELSE(BUILD_MULTITHREADING) -# SET(BUILD_NVIDIA_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for NVidia" FORCE) -# SET(BUILD_AMD_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for AMD" FORCE) -# SET(BUILD_INTEL_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for Intel (CPU)" FORCE) -# SET(BUILD_MINICL_OPENCL_DEMOS OFF CACHE BOOL "Build OpenCL demos for MiniCL (Generic CPU)" FORCE) -# SET(USE_DX11 OFF CACHE BOOL "Use DirectX 11" FORCE) -# SET(USE_MULTITHREADED_BENCHMARK OFF CACHE BOOL "Use Multithreaded Benchmark" FORCE) -ENDIF(BUILD_MULTITHREADING) - - - - -#SET(CMAKE_EXE_LINKER_FLAGS_INIT "/STACK:10000000 /INCREMENTAL:NO") -#SET(CMAKE_EXE_LINKER_FLAGS "/STACK:10000000 /INCREMENTAL:NO") - -#MESSAGE("MSVC_INCREMENTAL_YES_FLAG"+${MSVC_INCREMENTAL_YES_FLAG}) - - -IF(MSVC) - IF (NOT USE_MSVC_INCREMENTAL_LINKING) - #MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT}) - SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO") - - STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) - SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/INCREMENTAL:NO ${replacementFlags}" ) - MESSAGE("CMAKE_EXE_LINKER_FLAGS_DEBUG=${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - -# STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags2 ${CMAKE_EXE_LINKER_FLAGS}) -# SET(CMAKE_EXE_LINKER_FLAGS ${replacementFlag2}) -# STRING(REPLACE "INCREMENTAL:YES" "" replacementFlags3 ${CMAKE_EXTRA_LINK_FLAGS}) -# SET(CMAKE_EXTRA_LINK_FLAGS ${replacementFlag3}) - - - STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags3 ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}) - SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacementFlags3}) - SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/INCREMENTAL:NO ${replacementFlags3}" ) - - ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING) - - IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) - #We statically link to reduce dependancies - FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - IF(${flag_var} MATCHES "/MD") - STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - ENDIF(${flag_var} MATCHES "/MD") - IF(${flag_var} MATCHES "/MDd") - STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") - ENDIF(${flag_var} MATCHES "/MDd") - ENDFOREACH(flag_var) - ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL) - - IF (CMAKE_CL_64) - ADD_DEFINITIONS(-D_WIN64) - ELSE() - OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" ON) - IF (USE_MSVC_SSE) - ADD_DEFINITIONS(/arch:SSE) - ENDIF() - ENDIF() - OPTION(USE_MSVC_FAST_FLOATINGPOINT "Use MSVC /fp:fast option" ON) - IF (USE_MSVC_FAST_FLOATINGPOINT) - ADD_DEFINITIONS(/fp:fast) - ENDIF() -ENDIF(MSVC) - - - -IF (WIN32) -OPTION(INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES "Create MSVC projectfiles that can be distributed" OFF) - -IF (INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - SET (LIBRARY_OUTPUT_PATH ${BULLET_PHYSICS_SOURCE_DIR}/lib CACHE PATH "Single output directory for building all libraries.") - SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}) - SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${BULLET_PHYSICS_SOURCE_DIR}) - SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${BULLET_PHYSICS_SOURCE_DIR}) - SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${BULLET_PHYSICS_SOURCE_DIR}) - SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${BULLET_PHYSICS_SOURCE_DIR}) -ELSE() - SET (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib CACHE PATH "Single output directory for building all libraries.") -ENDIF() - - - -OPTION(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES "Create MSVC projectfiles with relative paths" OFF) -OPTION(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES "Add MSVC postfix for executable names (_Debug)" OFF) - -SET(CMAKE_DEBUG_POSTFIX "_Debug" CACHE STRING "Adds a postfix for debug-built libraries.") -SET(CMAKE_MINSIZEREL_POSTFIX "_MinsizeRel" CACHE STRING "Adds a postfix for MinsizeRelease-built libraries.") -SET(CMAKE_RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo" CACHE STRING "Adds a postfix for ReleaseWithDebug-built libraries.") - - - - - -IF (INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) -SET(CMAKE_SUPPRESS_REGENERATION 1) -SET(CMAKE_USE_RELATIVE_PATHS 1) -ENDIF(INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES) - -ENDIF (WIN32) - - -OPTION(BUILD_CPU_DEMOS "Build original Bullet CPU demos" ON) - - - -OPTION(INTERNAL_UPDATE_SERIALIZATION_STRUCTURES "Internal update serialization structures" OFF) -IF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) -ADD_DEFINITIONS( -DBT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) -ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES) - -IF (USE_DOUBLE_PRECISION) -ADD_DEFINITIONS( -DBT_USE_DOUBLE_PRECISION) -SET( BULLET_DOUBLE_DEF "-DBT_USE_DOUBLE_PRECISION") -ENDIF (USE_DOUBLE_PRECISION) - -IF(USE_GRAPHICAL_BENCHMARK) -ADD_DEFINITIONS( -DUSE_GRAPHICAL_BENCHMARK) -ENDIF (USE_GRAPHICAL_BENCHMARK) - -IF (WIN32) -OPTION(USE_GLUT "Use Glut" ON) -ADD_DEFINITIONS( -D_IRR_STATIC_LIB_ ) -ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) -ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE ) -ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) - -IF (USE_GLUT AND MSVC) - string (REPLACE "/D_WINDOWS" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - remove_definitions(-D_WINDOWS ) -ENDIF() - - - -ELSE(WIN32) -OPTION(USE_GLUT "Use Glut" ON) -ENDIF(WIN32) - - -IF(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - - -# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system -# This should be the case. - -FIND_PACKAGE(OpenGL) -IF (OPENGL_FOUND) - MESSAGE("OPENGL FOUND") - MESSAGE(${OPENGL_LIBRARIES}) -ELSE (OPENGL_FOUND) - MESSAGE("OPENGL NOT FOUND") - SET(OPENGL_gl_LIBRARY opengl32) - SET(OPENGL_glu_LIBRARY glu32) -ENDIF (OPENGL_FOUND) - -# ADD_DEFINITIONS(-DBT_USE_FREEGLUT) - -FIND_PACKAGE(GLU) - -IF (USE_GLUT) - FIND_PACKAGE(GLUT) - IF (GLUT_FOUND) - MESSAGE("GLUT FOUND") - MESSAGE(${GLUT_glut_LIBRARY}) - ELSE (GLUT_FOUND) - IF (MINGW) - MESSAGE ("GLUT NOT FOUND not found, trying to use MINGW glut32") - SET(GLUT_glut_LIBRARY glut32) - #TODO add better GLUT detection for MinGW - SET(GLUT_FOUND TRUE) - ENDIF (MINGW) - IF (MSVC) - SET(GLUT_FOUND TRUE) - IF (CMAKE_CL_64) - message("Win64 using Glut/glut64.lib") - SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut64.lib) - ELSE(CMAKE_CL_64) - message("Win32 using Glut/glut32.lib") - SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib) - ENDIF (CMAKE_CL_64) - INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/Glut) - ELSE() - MESSAGE("GLUT NOT FOUND") - ENDIF (MSVC) - ENDIF (GLUT_FOUND) - - IF(NOT WIN32) - # This is added for linux. This should always work if everything is installed and working fine. - INCLUDE_DIRECTORIES(/usr/include /usr/local/include) - ENDIF() -ENDIF(USE_GLUT) - - -OPTION(BUILD_DEMOS "Set when you want to build the demos" ON) -IF(BUILD_DEMOS) - IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/Demos AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/Demos) - SUBDIRS(Demos) - ENDIF() -ENDIF(BUILD_DEMOS) - -# "Demos_ps3") -IF (MSVC) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF(EXISTS ${BULLET_PHYSICS_SOURCE_DIR}/Demos_ps3 AND IS_DIRECTORY ${BULLET_PHYSICS_SOURCE_DIR}/Demos_ps3) - MESSAGE("Demos_ps3 found") - SUBDIRS(Demos_ps3) - ENDIF() - ENDIF() -ENDIF(MSVC) - - -OPTION(BUILD_EXTRAS "Set when you want to build the extras" ON) -IF(BUILD_EXTRAS) - SUBDIRS(Extras) -ENDIF(BUILD_EXTRAS) - -#Maya Dynamica plugin is moved to http://dynamica.googlecode.com - -SUBDIRS(src) - -IF("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") - OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) -ELSE() - IF(APPLE AND FRAMEWORK) - OPTION(INSTALL_LIBS "Set when you want to install libraries" ON) - ELSE() -#by default, don't enable the 'INSTALL' option for Xcode and MSVC projectfiles - OPTION(INSTALL_LIBS "Set when you want to install libraries" OFF) - ENDIF() -ENDIF() - -IF(INSTALL_LIBS) - SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) - SET (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") - ## the following are directories where stuff will be installed to - SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/bullet/" CACHE PATH "The subdirectory to the header prefix") - SET(PKGCONFIG_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files") - IF(NOT WIN32) - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bullet.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc @ONLY) - INSTALL( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/bullet.pc - DESTINATION - ${PKGCONFIG_INSTALL_PREFIX}) - ENDIF(NOT WIN32) -ENDIF(INSTALL_LIBS) - -#INSTALL of other files requires CMake 2.6 -IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - OPTION(INSTALL_EXTRA_LIBS "Set when you want extra libraries installed" OFF) -ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - -OPTION(BUILD_UNIT_TESTS "Build Unit Tests" OFF) - -IF (BUILD_UNIT_TESTS) - SUBDIRS(UnitTests) -ENDIF() - -set (BULLET_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/bullet ) -list (APPEND BULLET_LIBRARIES LinearMath) -list (APPEND BULLET_LIBRARIES BulletCollisions) -list (APPEND BULLET_LIBRARIES BulletDynamics) -list (APPEND BULLET_LIBRARIES BulletSoftBody) -set (BULLET_USE_FILE ${CMAKE_INSTALL_PREFIX}/${BULLET_CONFIG_CMAKE_PATH}/UseBullet.cmake) -configure_file ( ${CMAKE_SOURCE_DIR}/BulletConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/BulletConfig.cmake - @ONLY ESCAPE_QUOTES - ) -install ( FILES ${CMAKE_SOURCE_DIR}/UseBullet.cmake - ${CMAKE_CURRENT_BINARY_DIR}/BulletConfig.cmake - DESTINATION ${BULLET_CONFIG_CMAKE_PATH} - ) diff --git a/Code/Physics/Bullet Source/COPYING b/Code/Physics/Bullet Source/COPYING deleted file mode 100644 index 794842d9..00000000 --- a/Code/Physics/Bullet Source/COPYING +++ /dev/null @@ -1,17 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2011 Erwin Coumans http://bulletphysics.org - -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. -*/ - -All files in the Bullet/src folder are under this Zlib license. -Files in the Extras and Demos folder may have a different license, see the respective files. diff --git a/Code/Physics/Bullet Source/ChangeLog b/Code/Physics/Bullet Source/ChangeLog deleted file mode 100644 index f5c85c80..00000000 --- a/Code/Physics/Bullet Source/ChangeLog +++ /dev/null @@ -1,795 +0,0 @@ -Bullet Continuous Collision Detection and Physics Library -Primary author and maintainer: Erwin Coumans - -This ChangeLog is incomplete, for an up-to-date list of all fixed issues see http://bullet.googlecode.com -using http://tinyurl.com/yabmjjj - -2013 October 23 - - Bullet 2.82 release - - See docs/BulletQuickstart.pdf or issue tracked for details. - -2012 September 10 - - Bullet 2.81 release preparation - -2011 September 15 - - Bullet 2.79 release, revision 2433 (mainly a bugfix release) - - Revert a change in 2.78 related to speculative contacts (it has undesired side effects) - - Use HACD Hierachical Approximate Convex Decomposition (thanks to Khaled Mammou and Sujeon Kim) - - Add Intel cmake-build support for OpenCL accelerated cloth/particle - - add premake4 build system support to autogenerate visual studio project files that can be shipped (see msvc folder) - - preliminary build support for Google NativeClient, using premake4 (see msvc folder) - - -2011 April 8 - - Bullet 2.78 release 2383 - - Added FractureDemo - - Added Separatinx Axis Test and Polyhedral Clipping support (See InternalEdgeDemo) - - Added speculative contacts as CCD response method (See CcdPhysicsDemo) - - OpenCL and DirectCompute cloth as basic support for capsule collision - -2010 September 7 - - autotools now uses CamelCase naming for libraries just like cmake: - libbulletdynamics -> libBulletDynamics, libbulletmath -> libLinearMath - -2010 July 21 - - Preparing for Bullet 2.77 release, around revision r2135 - - Added an OpenCL particle demo, running on NVidia, AMD and MiniCL - Thanks to NVidia for the original particle demo from their OpenCL SDK - - Added GPU deformable object solvers for OpenCL and DirectCompute, and a DirectX 11 cloth demo - Thanks to AMD - - Create a separate library for MiniCL, - MiniCL is a rudimentary OpenCL wrapper that allows to compile OpenCL kernels for multi-core CPU, using Win32 Threads or Posix - - Moved vectormath into Bullet/src, and added a SSE implementation - - Added a btParallelConstraintSolver, mainly for PlayStation 3 Cell SPUs (although it runs fine on CPU too) - -2010 March 6 - - Dynamica Maya plugin (and COLLADA support) is moved to http://dynamica.googlecode.com - -2010 February - - Bullet 2.76 release, revision 2010 - - support for the .bullet binary file format - - btInternalEdgeUtility to adjust unwanted collisions against internal triangle edges - - Improved Maya Dynamica plugin with better constraint authoring and .bullet file export - - -2009 September 17 - - Minor update to Bullet 2.75 release, revision 1776 - - Support for btConvex2dShape, check out Bullet/Demos/Box2dDemo - - Fixes in build systems - - Minor fix in btGjkPairDetector - - Initialize world transform for btCollisionShape in constructor - - -2009 September 6 - - Bullet 2.75 release - - Added SPH fluid simulation in Extras, not integrated with rigid body / soft body yet - Thanks to Rama Hoetzlein to make this contribution available under the ZLib license - - add special capsule-capsule collider code in btConvexConvexCollisionAlgorithm, to speed up capsule-ragdolls - - soft body improvement: faster building of bending constraints - - soft body improvement: allow to disable/enable cluster self-collision - - soft body fix: 'exploding' soft bodies when using cluster collision - - fix some degenerate cases in continuous convex cast, could impact ray cast/convex cast - Thanks to Jacob Langford for the report and reproduction cases, see http://code.google.com/p/bullet/issues/detail?id=250&can=1&start=200 - - re-enabled split impulse - - added btHinge2Constraint, btUniversalConstraint, btGeneric6DofSpringConstraint - - demonstrate 2D physics with 2D/3D object interaction - - -2008 December 2 - - Fix contact refresh issues with btCompoundShape, introduced with btDbvt acceleration structure in btCompoundCollisionAlgorithm - - Made btSequentialImpulseConstraintSolver 100% compatible with ODE quickstep - constraints can use 'solveConstraint' method or 'getInfo/getInfo2' - -2008 November 30 - - Add highly optimized SIMD branchless PGS/SI solver innerloop - -2008 November 12 - - Add compound shape export to BulletColladaConverter - Thanks to JamesH for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=12&t=2840 - - Fix compiler build for Visual Studio 6 - Thanks to JoF for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2841 - -2008 November 11 - - Add CProfileManager::dumpAll() to dump performance statistics to console using printf. - - Add support for interaction between btSoftBody and btCollisionObject/btGhostObject - -2008 November 8 - - Fix PosixThreadSupport - - Add improved btHeightfieldTerrainShape support and new Demos/TerrainDemo - Thanks to tomva, http://code.google.com/p/bullet/issues/detail?id=63&can=1 - - Moved kinematic character controller from Demos/CharacterDemo into src/BulletDynamics/Character/btKinematicCharacterController.cpp - -2008 November 6 - - reduced default memory pool allocation from 40Mb to 3Mb. This should be more suitable for all platforms, including iPhone - - improved CUDA broadphase - - IBM Cell SDK 3.x support, fix ibmsdk Makefiles - - improved CMake support with 'install' and 'framework option - -2008 November 4 - - add btAxisSweep::resetPool to avoid non-determinism due to shuffled linked list - Thanks to Ole for the contribution, - -2008 October 30 - - disabled btTriangleMesh duplicate search by default, it is extremely slow - - added Extras/IFF binary chunk serialization library as preparation for in-game native platform serialization (planned COLLADA DOM -> IFF converter) - -2008 October 20 - - added SCE Physics Effects box-box collision detection for SPU/BulletMultiThreaded version - See Bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp - Thanks to Sony Computer Entertainment Japan, SCEI for the contribution - -2008 October 17 - - Added btGhostObject support, this helps character controller, explosions, triggers and other local spatial queries - -2008 October 10 - - Moved aabb to btBroadphaseProxy, improves rayTest dramatically. Further raytest improvements using the broadphase acceleration structures are planned - - Moved BulletMultiThreaded from Extras to /src/BulletMultiThreaded for better integration - - -2008 October 3 - - Add support for autoconf automake - ./autogen.sh and ./configure will create both Makefile and Jamfile. CMake and autogenerated Visual Studio projectfiles remain supported too. - - Improved ColladaConverter: plane shape export, and callback for shape construction to allow deletion of memory - -2008 Sept 30 - - Improved Soft Body support, fixed issues related to soft body colliding against concave triangle meshes - - Shared more code between regular version and SPU/BulletMultiThreaded, in particular GJK/EPA - -2008 Sept 28 - - Fixed rotation issues in Dynamic Maya Plugin - -2008 Sept 11 - - Enable CCD motion clamping for btDiscreteDynamicsWorld, to avoid tunneling. A more advanced solution will be implemented in btContinuousDynamicsWorld. - -2008 Sept 7 - - Add btScaledBvhTriangleMeshShape, to allow re-use of btBvhTriangleMeshShape of different sizes, without copying of the BVH data. - -2008 Sept 5 - - Enabled Demos/ForkLiftDemo - Thanks Roman Ponomarev. - -2008 Sept 4 - - Added btCudaBroadphase in Extras/CUDA: some research into accelerating Bullet using CUDA. - Thanks to the particle demo from the NVidia CUDA SDK. - -2008 Sept 3 - - Several bug fixes and contributions related to inertia tensor, memory leaks etc. - Thanks to Ole K. - -2008 Sept 1 - - Updated CDTestFramework, with latest version of OPCODE Array SAP. See Extras/CDTestFramework - Thanks to Pierre Terdiman for the update - -2008 August 25 - - Walt Disney Studios contributes their in-house Maya Plugin for simulating Bullet physics, with options for other engines such as PhysBam or PhysX. - Thanks to Nicola Candussi and Arthur Shek - -2008 August 14 - - Improved performance for btDbvtBroadphase, based on dual dynamic AABB trees (one for static, one for dynamic objects, where objects can move from one to the other tree) - Thanks to Nathanael Presson again, for all his work. - -2008 July 31 - - Added Havok .hkx to COLLADA Physics .dae converter patch+information - - Fix btSubsimplexConvexCast - Thanks to Nacho, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2422) - - Fix in rendering, GL_STENCIL - - btTriangleIndexVertexArray indices should be unsigned int/unsigned short int, - - Made InternalProcessAllTriangles virtual, thanks to - Both thank to Fullmetalcoder, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2401 - - clamp impulse for btPoint2PointConstraint - Thanks to Martijn Reuvers, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2418 - - Free memory of bvh, pass in scaling factor (optional) - Thanks to Roy Eltham, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2375 - -2008 July 27 - -btDbvtBroadphase: - - Fixed a performance issues reported by 'reltham' - - Added btDbvtBroadphase::optimize() for people who want good performances right -away or don't do dynamics. - - fixed compilation issues when DBVT_BP_PROFILE was set. -btSoftBody: - - Fixed singular matrix issues related to polar decomposition (flat meshes). -DemoApplication: - - Shadows (enable/disable through 'g' or DemoApplication::setShadows(bool)). - - Texture can be enable/disable through 'u' -CDFramework: - - fixed compilation issues. - All thanks to Nathanael Presson - -2008 July 10 - - Added btMultimaterialTriangleMeshShape and MultiMaterialDemo - Thanks to Alex Silverman for the contribution - -2008 June 30 - - Added initial support for kinematic character controller - Thanks to John McCutchan - -2008 April 14 - - Added ray cast support for Soft Bodies - Thanks to Nathanael Presson for the contribution - -2008 April 9 - - Cleanup of Stan Melax ConvexHull, removed Extras/ConvexHull, moved sources into LinearMath/BulletCollision - -2008 April 4 - - Added btSliderConstraint and demo - Thanks Roman Ponomarev - -2008 April 3 - - Fixed btMinkowskiSumShape, and added hitpoint to btSubsimplexConvexCast - -2008 April 2 - - Added Extras/CdTestFrameWork - Thanks Pierre Terdiman - -2008 April 1 - - Added posix thread (pthread) support - Thanks Enrico - -2008 March 30 - - Added Soft Body, cloth, rope and deformable volumes, including demos and interaction - Thanks Nathanael Presson for this great contribution - - 2008 March 17 - - Improved BulletColladaConverter - Thanks John McCutchan - -2008 March 15 - - btMultiSapBroadphase in a working state. Needs more optimizations to be fully useable. - - Allow btOptimizedBvh to be used for arbitrary objects, not just triangles - - added quicksort to btAlignedObjectArray - - removed btTypedUserInfo, added btHashMap - -2008 March 30 - - Moved quickstep solver and boxbox into Bullet/src folder - Thanks Russell L. Smith for permission to redistribute Open Dynamics Engine quickstep and box-box under the ZLib license - -2008 Feb 27 - - Added initial version for Character Control Demo - - Applied fixes to IBM Cell SDK 3.0 build makefiles - Thanks Jochen and mojo for reporting/providing patch: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1922 - -2008 Feb 8 - - Bugfixes in ConvexCast support against the world. - Thanks to Isgmasa for reporting/providing fix: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1823 - -2008 Feb 6 - - Added btCapsuleShapeX and btCapsuleShapeZ for capsules around X and Z axis (default capsule is around Y) - -2008 Feb 3 - - Added btTypedUserInfo, useful for serialization - -2008 Jan 31 - - Add support for 16 and 32-bit indices for SPU / BulletMultiThreaded version. - -2008 Jan 29 - - Added COLLADA Physics export/serialization/snapshot from any Bullet btDynamicsWorld. Saving the physics world into a text .xml file is useful for debugging etc. - -2008 Jan 23 - - Added Stan Melax Convex Hull utility library in Extras/ConvexHull. This is useful to render non-polyhedral convex objects, and to simplify convex polyhedra. - -2008 Jan 14 - - Add support for batch raycasting on SPU / BulletMultiThreaded - -2007 Dec 16 - - Added btRigidBodyConstructionInfo, to make it easier to set individual setting (and leave other untouched) during rigid body construction. - Thanks Vangelis Kokkevis for pointing this out. - - Fixed memoryleak in the ConstraintDemo and Raytracer demo. - - Fixed issue with clearing forces/gravity at the end of the stepSimulation, instead of during internalSingleStepSimulation. - Thanks chunky for pointing this out: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1780 - - Disabled additional damping in rigid body by default, but enable it in most demos. Set btRigidBodyConstructionInfo m_additionalDamping to true to enable this. - - Removed obsolete QUICKPROF BEGIN/END_PROFILE, and enabled BT_PROFILE. Profiling is enabled by default (see Bullet/Demos/OpenGL/DemoApplication.cpp how to use this). - User can switch off profiling by enabling define BT_NO_PROFILE in Bullet/src/btQuickprof.h. - -2007 Dec 14 - - Added Hello World and BulletMultiThreaded demos - - Add portable version of BulletMultiThreaded, through SequentialThreadSupport (non-parallel but sharing the same code-path) - - Add Cmake support for AllBulletDemos - - -2007 Dec 11 - - Moved the 'btRigidBody::clearForce' to the end of the stepSimulation, instead of in each substep. - See discussion http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1601 - - Added btConvexPlaneCollisionAlgorithm, makes planes perform better, and prevents tunneling - Thanks Andy O'Neil for reporting the performance/functionality issue - - Fixes for IBM Cell SDK 3.0 - Thanks to Jochen Roth for the patch. - -2007 Dec 10 - - Fixes in btHeightfieldTerrainShape - Thanks to Jay Lee for the patch. - -2007 Dec 9 - - Only update aabb of active objects - Thanks Peter Tchernev for reporting (http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1764 ) - - Added workaround to compile libxml under Visual Studio 2008 Beta 2 - - Make glui compile under MSVC 9.0 beta (vsnprintf is already defined) - -2007 Dec 6 - - Added DynamicControlDemo, showing dynamic control through constraint motors - Thanks to Eddy Boxerman - - Add support for generic concave shapes for convex cast. - - Added convex cast query to collision world. - - Added workaround for OpenGL bug in Mac OS X 10.5.0 (Leopard) - - Added concave raycast demo - All above thanks to John McCutchan (JMC) - - Fixed issues that prevent Linux version to compile. - Thanks to Enrico for reporting and patch, see - - Fixed misleading name 'numTriangleIndices' into 'numTriangles' - Thanks Sean Tasker for reporting: - -2007 Nov 28: - - Added raycast against trianglemesh. Will be extended to object cast soon. - Thanks John McCutchan (JMC) - - make getNumPoints const correct, add const getPoints(). - Thanks Dirk Gregorius - - Bugfix: allow btCollisionObjects (non-btRigidBody) to interact properly with btRigidBody for cache-friendly btSequentialImpulseConstraintSolver. - Thanks Andy O'Neil for pointing this out. - - Bugfix: don't fail if spheres have identical center, use arbitrary separating normal (1,0,0) - Thanks Sean Tasker for reporting! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1681 - - -2007, November 20 - - Added hierarchical profiling - - Fixed memory leak in btMultiSapBroadphase, - - Fixed hash function (typo, should use 2 proxies) - Thanks to Stephen (shatcher) for reporting and fixes! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1696 - -2007 Nov 11 - - Fixed parallel solver (BulletMultiThreaded) friction issue - - Terminate Win32 Threads when closing the CcdPhysicsDemo (when USE_PARALLEL_SOLVER/USE_PARALLEL_DISPATCHER is defined) - -2007 Nov 6 - - Added support for 16-bit indices for triangle meshes - - Added support for multiple mesh parts using btBvhTriangleMeshShape. - Thanks to Tim Johansson - -2007 Oct 22 - - All memory allocations go through btAlignedAlloc/btAlignedFree. User can override this to verify memory leaks - - added a few more demos to AllBulletDemos - - fix for one of the constructors of btHingeConstraint - Thanks Marcus Hennix - -2007 Oct 20 - - included glui, a GLUT/OpenGL based toolkit for some graphical user elements - Removed dynamic_cast from glui, to allow linkage without rtti - - added Box2D framework using glui, allowing all demos to run within one executable - Thanks Erin Catto for the FrameWork skeleton (http://www.box2d.org) - -2007 Ocy 17 - - Allow user to pass in their own memory (stack and pool) allocators, through collisionConfiguration. See demos how to use this - -2007 Oct 14 - - Included working version of Cell SPU parallel optimized version for Libspe2 SPU task scheduler. - This version compiles and runs on Playstation 3 Linux and IBM CellBlade, see BulletSpuOptimized.pdf for build instructions - (Official Playstation 3 developers can request a SPURS version through Sony PS3 Devnet.) - Thanks to IBM 'Extreme Blue' project for the contribution - http://www-913.ibm.com/employment/us/extremeblue/ - Thanks Minh Cuong Tran, Benjamin Hoeferlin, Frederick Roth and Martina Huellmann - for various contributions to get this initial Libspe2 parallel version up and running. - -2007 Oct 13 - - made 'btCollisionShape::calculateLocalInertia' const - Thanks to cgripeos, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1514 - - applied a large patch to remove warnings - Thanks to Enrico, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1568 - - removed SSE includes, added #incude for memset in Extras/quickstep, thanks Eternl Knight - -2007 Oct 11 - - added Hashed Overlapping Pair Cache, recommended by Pierre Terdiman. It works like a charm, thanks Pierre and Erin Catto (code from Box2D) - - modified some margins inside btBoxShape, btCylinderShape and btSphereShape - - added cone debug rendering (for cones with x, y and z up-axis) - - added improvements for optional Extra/quickstep, thanks to Remotion - - some performance improvements for Bullet constraint solver - -2007 Sept 28 - - upgraded GIMPACT to version 0.3 - Thanks to Francisco Leon - -2007 Sept 27 - - added contribution from IBM Extreme Blue project for Libspe2 support. This allow to execute BulletMultiThreaded on Cell SPU under PS3 Linux and Cell Blade. See http://www-913.ibm.com/employment/us/extremeblue - Thanks to Minh Cuong Tran, Frederick Roth, Martina Heullmann and Benjamin Hoeferlin. - -2007 Sept 13 - - Improved btGenericD6Constraint. It can be used to create ragdolls (similar to the new btConeTwistConstraint). See GenericJointDemo - - Added support for Bullet constraints in the optional Extras/quickstep ODE solver. See CcdPhysicsDemo, enable #COMPARE_WITH_QUICKSTEP and add libquickstep to the dependencies. - For both patches/improvements thanks Francisco Leon/projectileman - -2007 Sept 10 - - removed union from btQuadWordStorage, it caused issues under certain version of gcc/Linux - -2007 Sept 10 - - Reverted constraint solver, due to some issues. Need to review the recent memory allocation changes. - - Fixed issue with kinematic objects rotating at low speed: quaternion was de-normalized, passing value > 1 into acosf returns #IND00 invalid values - - 16 byte memory alignment for BVH serialization - - memory cleanup for btPoolAllocator - -2007 Sept 9 - - Added serialization for BVH/btBvhTriangleMeshShape, including endian swapping. See ConcaveDemo for an example. - Thanks to Phil Knight for the contribution. - - Fixed issues related to stack allocator/compound collision algorithm - Thanks Proctoid, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=18&t=1460 - - Increase some default memory pool settings, and added a fallback for the constraints solver to use heap memory - - Removed accidential testing code in btScalar.h related to operator new. - - Enable btAxis3Sweep and bt32BitAxis3Sweep to be linked in at the same time, using template - -2007 Sept 7 - - Replaced several dynamic memory allocations by stack allocation and pool allocations - - Added branch-free quantized aabb bounding box overlap check, works better on Playstation 3 and XBox 360 - Thanks to Phil Knight. Also see www.cellperformance.com for related articles - - Collision algorithms and settings for the memory/stack allocator can be done using btDefaultCollisionConfiguration - This is an API change. See demos how to modify existing implementations with a one-liner. - - Register several collision algorithms by default (sphere-sphere, sphere-box, sphere-triangle) - - Use other traveral method for BVH by default, this improves triangle mesh collision performance. - -2007 Aug 31 - - fixed MSVC 6 build - Thanks Proctoid, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1375 - - fixed double precision build issues - Thanks Alex Silverman, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1434 - -2007 Aug 24 - - fixed bug in btMatrix3x3::transposeTimes(const btMatrix3x3& m) const. Luckily it wasn't used in core parts of the library (yet). - Thanks to Jay Lee - -2007 Aug 15 - - fixed bug in Extras/GIMPACT 0.2 related to moving triangle meshes - Thanks Thomas, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1368 - -2007 Aug 14 - - added parallel constraint solver. Works on Playstation 3 Cell SPU and multi core (Win Threads on PC and XBox 360). - See Extras/BulletMultiThreaded for SpuSolverTask subfolder and SpuParallelSolver.cpp - Thanks Marten Svanfeldt (Starbreeze Studios) - - fixed some bugs related to parallel collision detection (Extras/BulletMultiThreaded) - Thanks Marten Svanfeldt (Starbreeze Studios) - -2007 Aug 2 - - added compound and concave-convex (swapped) case for BulletMultiThreaded collision detection, thanks to Marten Svanfeldt - - refactored broadphase and overlapping pair cache. This allows performance improvement by combining multiple broadphases. This helps add/remove of large batches of objects and large worlds. See also Pierre Terdiman forum topic: - http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 - - -2007 July 27 - - added Ragdoll Demo - Thanks to Marten Svanfeldt (Starbreeze Studios) - - - added Vector Math library for SIMD 3D graphics linear algebra (vector, matrix, quaternion) - See Bullet/Extras/vectormathlibrary - Supports SIMD SSE, PowerPC PPU and Cell SPU (including PS3 Linux and CellBlade), as well as generic portable scalar version - Will be used to improve BulletMultiThreaded performance - Open Sourced by Sony Computer Entertainment Inc. under the new BSD license - - added SIMD math library - 4-way SIMD for common math functions like atan2f4, cosf4, floorf4, fabsf4, rsqrtf4 etc. Used by Vector Math library under PPU and SPU. - Supports PowerPC (PPU) and Cell SPU, including PS3 Linux and CellBlade. - See Bullet/Extras/simdmathlibrary - Open sourced by Sony Computer Entertainment Inc. under the new BSD license - - -2007 July 25 - - added several patches: per-rigidbody sleeping threshold. added Assert to prevent deletion of rigidbody while constraints are still pointing at it - Thanks to Marten Svanfeldt (Starbreeze Studios) - -2007 July 13 - - fixed relative #include paths again. We can't use "../" relative paths: some compilers choke on it (it causes extreme long paths) - Within the libraries, we always need to start with "BulletCollision/" or "BulletDynamics/ or "LinearMath/" - -2007 July 10 - - Updated Bullet User Manual - -2007 July 5 - - added btConeTwistConstraint, especially useful for ragdolls. See Demos/RagdollDemo - Thanks to Marten Svanfeldt (Starbreeze Studios) - -2007 June 29 - - btHeightfieldTerrainShape: Added heightfield support, with customizations - - Upgraded to GIMPACT 0.2, see Extras/GIMPACT and MovingConcaveDemo - - Several patches from Marten Svanfeldt (Starbreeze Studios) - Improved collision filtering (in broadphase and rigidbody) - Improved debug rendering - Allow to set collision filter group/mask in addRigidBody - - -2007 June 15 - - Changed btAlignedObjectArray to call copy constructor/replacement new for duplication, rather then assignment operator (operator=). - -2007 June 11 - - Added multi-threading. Originally for Playstation 3 Cell SPU, but the same code can run using Win32 Threads using fake DMA transfers (memcpy) - Libspe2 support for Cell Blade / PS3 Linux is upcoming - See Extras/BulletMultiThreaded. Usage: replace btCollisionDispatcher by btSpuGatheringCollisionDispatcher - - - Added managed Bullet library, entirely rewritten in C# for Windows and XBox 360 XNA - See Extras/BulletX - Thanks to KleMiX, aka Vsevolod Klementjev - -2007 May 31 - - sign-bit went wrong in case of 32-bit broadphase, causing quantization problems. - Thanks DevO for reporting. - -2007 May 23 - - Fixed quantization problem for planar triangle meshes in btOptimizedBvh - Thanks Phil Knight for reporting and helping to fix this bug. - -2007 May 20 - - btAxisSweep3: Fixed a bug in btAxisSweep3 (sweep and prune) related to object removal. Only showed up when at least one btStaticPlaneShape was inserted. - Thanks tbp for more details on reproducing case. - - btAxisSweep3: Fixed issue with full 32bit precision btAxisSweep3 (define BP_USE_FIXEDPOINT_INT_32), it used only 0xffff/65536 for quantization instead of full integer space (0xffffffff) - - btRaycastVehicle: Added 'getForwardVector' and getCurrentSpeedKmHour utility functions - - Fixed local scaling issues (btConvexTriangleMeshShape, btBvhTriangleMeshShape, removed scaling from btMatrix3x3). - Thanks Volker for reporting! - - Added second filename search, so that starting BspDemo and ConvexDecompositionDemo from within Visual Studio (without setting the starting path) still works - -2007 April 22 - - Added braking functionality to btRaycastVehicle - - Removed tons of warnings, under MSVC 2005 compilation in -W4 - -2007 March 21 - - Fixed issues: comma at end of enum causes errors for some compilers - - Fixed initialization bug in LocalRayResult ( m_localShapeInfo(localShapeInfo) ) - -2007 March 20 - - Added refit tree to quantized stackless tree, and updated ConcaveDemo as example. - -2007 March 17 - - Added constraint solver optimizations, avoiding cross products during iterations, and gather rigidbody/constraint info in contiguous memory (btSolverBody/btSolverConstraint) - - These optimizations don't give large benefit yet, but it has good potential. Turned on by default. Can be switched off using solver->setSolverMode(SOLVER_RANDMIZE_ORDER). - - Enabled anti-jitter for rigid bodies. This is experimental, and can be switched off by setting a global (it is experimental so no proper interface) gJitterVelocityDampingFactor = 1.0; - - Fixed bug in islandmanifold.heapSort(btPersistentManifoldSortPredicate()); , thanks Noehrgel for reporting this (affected Sun Solaris) - -2007 March 12 - - Added compile-time toggle between on 16-bit and 32-bit fixed-point SAP broadphase. - This allows the number of bodies to exceed 32767 - - Enable useQuantizedAabbCompression on btTriangleMesh, see ColladaDemo - -2007 March 8 - - Fixed bug in constraint/island sorting (caused by replacing STL by dedicated btAlignedObjectArray with heapSort) - Thanks Clemens Unterkofler for pointing this out! - -2007 March 6 - - removed STL from the Bullet library: replace std::vector by btAlignedObjectArray. Also removed the std::set for overlapping pair set, and turned it into an overlapping pair array. The SAP only adds objects, never removed. Removal is postponed for during traversal of overlapping pairs (duplicates and non-overlapping pairs are removed during that traversal). - - added heap sort and binary search/linear search to btAlignedObjectArray - - fixed wrong cast, thanks Hamstray, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1015 - - -2007 Feb 25 - - Improved performance of convex collision shapes, cache local AABB instead of recomputation. This fixes issue with very slow performance in larger .bsp levels - -2007 Feb 24 - - Added compressed/quantized AABB tree, 16 bytes per node, while supporting 32-bit (triangle) indices. - Should be faster and smaller then original version (quantized aabb check is done in integer space) - Original aabb tree nodes are still supported. They are 44 bytes, with full floating point precision and additional subPart index. - - added meter-unit scaling support in ColladaConverter.cpp - -2007 Feb 21 - - Build system: updated bullet.pc.in library names - - Updated EPA comparison integration (missing parameter) - -2007 Jan 04 - - fixed optimized AABB tree building: in some cases the tree building fails due to unbalanced trees, which generated stack overflow - -2006 Dec 15 - - added contribution to allow double precision collision detection/dynamics. Define BT_USE_DOUBLE_PRECISION in your project and libraries that include Bullet - -2006 Dec 14 - - merged contact and non-contact constraint solving into one loop, will improve stability of jointed bodies during collisions - - added first draft for hingeConstraint motor - -2006 Dec 8, Erwin Coumans - - preparation for SIMD: added btAlignedAllocator and btAlignedObjectArray, to replace stl std::vector, same interface, but compatible with 16 byte alignment - - cleaned up dependencies in autogenerated msvc projectfiles - - aligned btVector3 on 16 bytes boundary, under win32. see if developers will come up with problems - -2006 Dec 04, Erwin Coumans - Added btNearCallback. This is similar to Open Dynamics Engine (ODE) dNearCallback, but important differences: - - contact points are persistent (lifetime more then one frame, for warmstarting/incremental contact point management) - - continuous collision detection, time of impact - Added btRigidBody::isInWorld(), returns true if btRigidBody is inside a btCollisionWorld/btDynamicsWorld derived class - Added angularFactor to btRigidbody, this helps some character control (no angular impulse applied) - - -2006 Nov 28 - Moved StackAlloc from EPA into LinearMath/btStackAlloc - renamed internal class ConcaveShape into btConcaveShape - added btHeightfieldTerrainShape (not completed yet) - -2006 Nov 15 Nathanael Presson - Added EPA penetration depth algorithm, Expanding Polytope Algorithm - Added Pierre Terdiman penetration depth comparison/test DEMO - Fixed Bullet's Minkowski sampling penetration depth solver - Contributed by Nathanael Presson - -2006 Nov 11 Francisco León Nájera - Added GIMPACT trimesh collision detection: concave versus concave, - Contributed by Francisco León Nájera - -2006 Nov 2 - Minor refactoring: btCollisionObject changes from struct into class, added accessor methods - Force use of btMotionState to synchronize graphics transform, disabled old btRigidBody constructor that accepts btTransform - Renamed treshold into threshold throughout the code - -2006 Oct 30 - Enable decoupling of physics and graphics framerate using interpolation and internal fixed timestep, based on btMotionState - Enabled raycast vehicle demo (still needs tuning) - Refresh contact points, even when they are already persistent. - Fixed debugDraw colors (thanks pc0de for reporting) - Use Dispatcher in ConcaveConvexCollisionAlgorithm (so it uses the registered collision algorithm, not hardcoded convexconcave) - Improved performance of constraint solver by precalculating the cross product/impulse arm - Added collision comparison code: ODE box-box, also sphere-triangle - Added safety check into GJK, and an assert for AABB's that are very large - Fixed kinematic support (deriving velocities for animated objects) - Updated comparison/optional quickstep solver in Extras - UserCollisionAlgorithm demonstrates btTriangleMesh usage (easier trimesh compared to index array version) - Removed scaling from btTransform (we only want to deal with rigid transforms) - -2006 Oct 4 - Fixed minor leak in btOptimizeBVH - Cleanup of btRigidBody construction - added getW() in btQuaternion - assert when setLinearVelocity is called on btRigidBody - renamed projectfile library from collada-dom to colladadom (to make VC6 happy) - -2006 Sept 27 - Big Refactoring: renamed and moved files, create a replacement for CcdPhysicsEnvironment/CcdPhysicsController. - All Bullet classes in LinearMath, BulletCollision and BulletDynamics start with bt, and methods start with lowercase. - Moved classes into src folder, which is the only include folder needed. - Added 2 headerfiles in src: btBulletCollisionCommon.h and btBulletDynamicsCommon.h - -2006 Sept 23 - Fixed 2 bugs, causing crashes when removing objects. Should do better unit-testing. UnionFind and 3D SAP were involved. - -2006 Sept 19 - Allow programmable friction and contact solver model. User can register their own functions for several interaction types. - Improved performance, and removed hardcoded maximum overlaps (switched from C-array to stl::set) - -2006 Sept 16 - Added Bullet 2.0 User Manual - Allow registration of custom user collision algorithms - -2006 Sept 10 - Started cleaning up demos - -2006 Sept 4 - Fixed concave collision bug (caused instability/missing collisions in meshes/compounds) - Fixed memoryleak in OptimizedBvh, added RayTestSingle to CollisionWorld - Prepared for VehicleDemo - Increased Performance (island generation for sleeping objects took too much time) - Better COLLADA 1.4.1 physics conformance in ColladaDemo - -2006 August 11 - Added Quake BspDemo - Improved CCD for compound and non-convex objects - -2006 August 10 - Added per-triangle material (friction/restitution) support for non-convex meshes. See ConcaveDemo for usage. - -2006 August 9 - Added CMake support (see http://cmake.org) - This can autogenerate makefiles, projectfiles cross platform (including MacOS X Xcode ) - Just run cmake . in the root folder and it will autogenerate build files - -2006 July 26 Erwin Coumans - Upgraded to COLLADA-DOM 1.4.1, latest SVN version - ColladaDemo can export snapshots to .dae - -2006 July 24 Erwin Coumans - Added Compound CollisionShape support - (this is still low performance -> requires stackless tree-versus-tree traversal for better performance) - -2006 July 15 Erwin Coumans - Added initial support for Parallel execution (collision detection, constraint solving) - See ParallelPhysicsEnvironment in Extras\PhysicsInterface\CcdPhysics - -2006 July 10 Erwin Coumans - Added MacOS X support (some build issues mainly) - -2006 July 5 Erwin Coumans - Improved COLLADA 1.4 physics import, both COLLADA-DOM and FCollada - -2006 June 29 Erwin Coumans - Refactoring of the broadphase - Moved some optional files to Extras: Algebraic ccd and EPA, quickstep - Moved the limits on bodies/overlap to 32k and 65k - -2006 June 25 Erwin Coumans - Added basic Collision Filtering, during broadphase - Allow adding meshes to the TriangleIndexVertexArray, - (input for TriangleMeshShape) - Preparation for CompoundShape - -2006 June 19 Erwin Coumans - Added support for COLLADA Physics Import. - Both jam and Visual Studio can compile ColladaDemo - -2006 June 18 Dirk Gregorius - Started implementing Generic6DOF joint and setup basic interface - - -2006 June 17 Frank Richter - Bumped version in configure.ac to 1.5.6 (assuming that "1.5f" is - the next version released). - Updated files in mk/autoconf and mk/jam with copies from CS; fixes a - GLU detection issue on MinGW. - Set msvc/bullet_ico.ico as the default application icon. - Disabled exceptions for gcc builds. - Applied a patch from Michael D. Adams to fix a warning with gcc. -2006 jUNE 16 Erwin Coumans - Constraints now merge simulation islands. - -2006 May 24 - Improved GJK accuracy, fixed GjkConvexCast issue, thanks to ~MyXa~ for reporting - -2006 May 19 - Added restitution support - Moved out Friction and Dynamics info from ManifoldPoint (removed logical dependency) - Added a void* m_userPersistentData in ManifoldPoint. - Added a ContactDestroyedCallback, to allow user to handle destruction of m_userPersistentData - -2006 May 13 - Fixed some bugs in friction / jacobian calculations. Reported by Dirk Gregorius. Thanks! - -2006 May 9 - Fixed raycasting filtering - Moved repository to SVN at https://svn.sourceforge.net/svnroot/bullet - -2006 April 27 - Moved raycasting to CollisionWorld, to make it more generic - Added basic CCD option in the CcdCollisionDemo - Fixed 'noResponse' mode, for triggering rigidbodies (useful for Artificial Intelligence queries) - Improved Bullet/ODE sample (in Extras) - -2006 April 10 - Separating Axis Test (SAT) convex hull collision detector, contribution by Simon Hobbs - Added SIMD SSE Math classes (for above SAT) - Added Mouse picking in CcdPhysicsDemo - Improved penetration depth estimation in MinkowskiPenetrationDepthSolver, both accuracy and performance - Added Hinge constraint - Added quickprof profiling (see http://sourceforge.net/projects/quickprof ) - -2006 March 21 Frank Richter - Removed VC manifest files. - Removed superfluous "grpplugins" projects. - -2006 March 20 Erwin Coumans - Clamped the acculumated impulse rather then intermediate impulse (within the iteration) - Use the persistent contacts for reusing the impulse - Separated friction and normal solving for better stability - Decreased the default number of iterations of the constraint solver from 10 to 4 - -2006 March 19 Frank Richter - Removed a couple of CSisms from the VC projects. - Fixed VC include & lib paths to go to the Addtional* options - instead the command line arguments. - Added pkgconfig support. - -2006 March 14 Frank Richter - Added support for shipped GLUT on MinGW. - Fixed GLUT support on MinGW. - -2006 March 13 Frank Richter - Bolted on Jam-based build system. - Generated VC project files. - Fixed GCC warnings. - Fixed Linux build issues. - -2006 March 13 -Added 3D Sweep and Prune Broadphase Collision Detection, Contribution from Simon Hobbs. - -2006 March 2 - Minor change in license to ZLib/LibPNG - This makes it legally a bit easier to deploy on Playstation 3 - Prepared for more generic constraints, added ConstraintsDemo - -2006 Feb 23 - Rearranged files and dependencies to allow for easier standalone Collision Detection without Bullet Dynamics. - See Demos/CollisionInterfaceDemo and Extras/ode/ode/test/test_BulletGjk.cpp for examples how to use. - -2005 August 6 - Bullet 0.2 release with demos, sources, doxygen, draft manual - -2005 June 1 - First public release of Bullet - - -... todo: add history - -2003 Initial version (continuous collision detection) diff --git a/Code/Physics/Bullet Source/Doxyfile b/Code/Physics/Bullet Source/Doxyfile deleted file mode 100644 index d483fe4b..00000000 --- a/Code/Physics/Bullet Source/Doxyfile +++ /dev/null @@ -1,780 +0,0 @@ -# Doxyfile 1.2.4 - -# This file describes the settings to be used by doxygen for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- - - - - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. -PROJECT_NAME = "Bullet Collision Detection & Physics Library" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, -# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, -# Polish, Portuguese and Slovene. - -OUTPUT_LANGUAGE = English - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these class will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. - -STRIP_FROM_PATH = - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a class diagram (in Html and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. - -CLASS_DIAGRAMS = YES - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower case letters. If set to YES upper case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are adviced to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -JAVADOC_AUTOBRIEF = YES - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. - -INHERIT_DOCS = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# The ENABLE_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = NO - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = src - - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -FILE_PATTERNS = *.h *.cpp *.c - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse. - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = YES - -# HHC_LOCATION = "C:\Program Files\HTML Help Workshop\hhc.exe" -HHC_LOCATION = "C:\Program Files (x86)\HTML Help Workshop\hhc.exe" - - -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -#HTML_STYLESHEET = "\\server\exchange\Software Development\Documentation\DoxyGen\doxygen.css" - -CHM_FILE = BulletDocs.chm -HHC_LOCATION = "c:\program files\HTML Help Workshop\hhc.exe" -GENERATE_CHI = YES -BINARY_TOC = YES - -TOC_EXPAND = YES - -SHOW_DIRECTORIES = YES - - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 1 - -# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript and frames is required (for instance Netscape 4.0+ -# or Internet explorer 4.0+). - -GENERATE_TREEVIEW = YES - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using a WORD or other. -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Warning: This feature -# is still experimental and very incomplete. - -GENERATE_XML = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = src - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = "ATTRIBUTE_ALIGNED128(x)=x" \ - "ATTRIBUTE_ALIGNED16(x)=x" \ - "SIMD_FORCE_INLINE=inline" \ - "VECTORMATH_FORCE_INLINE=inline" \ - "USE_WIN32_THREADING=1"\ - "USE_PTHREADS=1"\ - "_WIN32=1" - - -# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tagfiles. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to -# YES then doxygen will generate a graph for each documented file showing -# the direct and indirect include dependencies of the file with other -# documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to -# YES then doxygen will generate a graph for each documented header file showing -# the documented files that directly or indirectly include this file - -INCLUDED_BY_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - - -# delete intermediate dot files? - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = search.cgi - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = c:\program files\doxygen\bin - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_cpx.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_cpx.h deleted file mode 100644 index 16a685aa..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_cpx.h +++ /dev/null @@ -1,13 +0,0 @@ -// todo - implement these as you see fit. -inline GLint glRenderMode(GLenum a0) { return GL_RENDER; }; // ymmv. should return previous mode -inline GLenum glGetError() { return GL_NO_ERROR; }; -inline GLboolean glIsList(GLuint a0) { return GL_TRUE; }; -inline GLuint glGenLists(GLsizei a0) { return (GLuint)a0; }; -inline const GLubyte* glGetString(GLenum a0) { return (const GLubyte *)"egl-xyzzy"; }; -inline GLboolean glIsEnabled(GLenum a0) { return GL_TRUE; }; -inline GLboolean glAreTexturesResident(GLsizei a0,const GLuint * a1,GLboolean * a2) { return GL_TRUE; }; -inline GLboolean glIsTexture(GLuint a0) { return GL_TRUE; }; -inline void glGetBooleanv(GLenum a0,GLboolean * a1) { *a1 = GL_TRUE; }; -inline void glGetDoublev(GLenum a0,GLdouble * a1) { *a1 = 0.0; }; -inline void glGetFloatv(GLenum a0,GLfloat * a1) { *a1 = 0.0f; }; -inline void glGetIntegerv(GLenum a0,GLint * a1) { *a1 = 0; }; diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_defs.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_defs.h deleted file mode 100644 index cbd57114..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_defs.h +++ /dev/null @@ -1,706 +0,0 @@ -#ifndef EGL_DEFS_H -#define EGL_DEFS_H - -typedef unsigned int GLenum; -typedef unsigned char GLboolean; -typedef unsigned int GLbitfield; -typedef void GLvoid; -typedef signed char GLbyte; -typedef short GLshort; -typedef int GLint; -typedef unsigned char GLubyte; -typedef unsigned short GLushort; -typedef unsigned int GLuint; -typedef int GLsizei; -typedef float GLfloat; -typedef float GLclampf; -typedef double GLdouble; -typedef double GLclampd; - -#define __gl_h_ -#define GL_VERSION_1_1 1 -#define GL_VERSION_1_2 1 -#define GL_VERSION_1_3 1 -#define GL_ARB_imaging 1 -#define GL_FALSE 0x0 -#define GL_TRUE 0x1 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_2_BYTES 0x1407 -#define GL_3_BYTES 0x1408 -#define GL_4_BYTES 0x1409 -#define GL_DOUBLE 0x140A -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_QUADS 0x0007 -#define GL_QUAD_STRIP 0x0008 -#define GL_POLYGON 0x0009 -#define GL_VERTEX_ARRAY 0x8074 -#define GL_NORMAL_ARRAY 0x8075 -#define GL_COLOR_ARRAY 0x8076 -#define GL_INDEX_ARRAY 0x8077 -#define GL_TEXTURE_COORD_ARRAY 0x8078 -#define GL_EDGE_FLAG_ARRAY 0x8079 -#define GL_VERTEX_ARRAY_SIZE 0x807A -#define GL_VERTEX_ARRAY_TYPE 0x807B -#define GL_VERTEX_ARRAY_STRIDE 0x807C -#define GL_NORMAL_ARRAY_TYPE 0x807E -#define GL_NORMAL_ARRAY_STRIDE 0x807F -#define GL_COLOR_ARRAY_SIZE 0x8081 -#define GL_COLOR_ARRAY_TYPE 0x8082 -#define GL_COLOR_ARRAY_STRIDE 0x8083 -#define GL_INDEX_ARRAY_TYPE 0x8085 -#define GL_INDEX_ARRAY_STRIDE 0x8086 -#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 -#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 -#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A -#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C -#define GL_VERTEX_ARRAY_POINTER 0x808E -#define GL_NORMAL_ARRAY_POINTER 0x808F -#define GL_COLOR_ARRAY_POINTER 0x8090 -#define GL_INDEX_ARRAY_POINTER 0x8091 -#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 -#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 -#define GL_V2F 0x2A20 -#define GL_V3F 0x2A21 -#define GL_C4UB_V2F 0x2A22 -#define GL_C4UB_V3F 0x2A23 -#define GL_C3F_V3F 0x2A24 -#define GL_N3F_V3F 0x2A25 -#define GL_C4F_N3F_V3F 0x2A26 -#define GL_T2F_V3F 0x2A27 -#define GL_T4F_V4F 0x2A28 -#define GL_T2F_C4UB_V3F 0x2A29 -#define GL_T2F_C3F_V3F 0x2A2A -#define GL_T2F_N3F_V3F 0x2A2B -#define GL_T2F_C4F_N3F_V3F 0x2A2C -#define GL_T4F_C4F_N3F_V4F 0x2A2D -#define GL_MATRIX_MODE 0x0BA0 -#define GL_MODELVIEW 0x1700 -#define GL_PROJECTION 0x1701 -#define GL_TEXTURE 0x1702 -#define GL_POINT_SMOOTH 0x0B10 -#define GL_POINT_SIZE 0x0B11 -#define GL_POINT_SIZE_GRANULARITY 0x0B13 -#define GL_POINT_SIZE_RANGE 0x0B12 -#define GL_LINE_SMOOTH 0x0B20 -#define GL_LINE_STIPPLE 0x0B24 -#define GL_LINE_STIPPLE_PATTERN 0x0B25 -#define GL_LINE_STIPPLE_REPEAT 0x0B26 -#define GL_LINE_WIDTH 0x0B21 -#define GL_LINE_WIDTH_GRANULARITY 0x0B23 -#define GL_LINE_WIDTH_RANGE 0x0B22 -#define GL_POINT 0x1B00 -#define GL_LINE 0x1B01 -#define GL_FILL 0x1B02 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_POLYGON_MODE 0x0B40 -#define GL_POLYGON_SMOOTH 0x0B41 -#define GL_POLYGON_STIPPLE 0x0B42 -#define GL_EDGE_FLAG 0x0B43 -#define GL_CULL_FACE 0x0B44 -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_POINT 0x2A01 -#define GL_POLYGON_OFFSET_LINE 0x2A02 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_COMPILE 0x1300 -#define GL_COMPILE_AND_EXECUTE 0x1301 -#define GL_LIST_BASE 0x0B32 -#define GL_LIST_INDEX 0x0B33 -#define GL_LIST_MODE 0x0B30 -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_DEPTH_TEST 0x0B71 -#define GL_DEPTH_BITS 0x0D56 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_LIGHTING 0x0B50 -#define GL_LIGHT0 0x4000 -#define GL_LIGHT1 0x4001 -#define GL_LIGHT2 0x4002 -#define GL_LIGHT3 0x4003 -#define GL_LIGHT4 0x4004 -#define GL_LIGHT5 0x4005 -#define GL_LIGHT6 0x4006 -#define GL_LIGHT7 0x4007 -#define GL_SPOT_EXPONENT 0x1205 -#define GL_SPOT_CUTOFF 0x1206 -#define GL_CONSTANT_ATTENUATION 0x1207 -#define GL_LINEAR_ATTENUATION 0x1208 -#define GL_QUADRATIC_ATTENUATION 0x1209 -#define GL_AMBIENT 0x1200 -#define GL_DIFFUSE 0x1201 -#define GL_SPECULAR 0x1202 -#define GL_SHININESS 0x1601 -#define GL_EMISSION 0x1600 -#define GL_POSITION 0x1203 -#define GL_SPOT_DIRECTION 0x1204 -#define GL_AMBIENT_AND_DIFFUSE 0x1602 -#define GL_COLOR_INDEXES 0x1603 -#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 -#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 -#define GL_LIGHT_MODEL_AMBIENT 0x0B53 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_SHADE_MODEL 0x0B54 -#define GL_FLAT 0x1D00 -#define GL_SMOOTH 0x1D01 -#define GL_COLOR_MATERIAL 0x0B57 -#define GL_COLOR_MATERIAL_FACE 0x0B55 -#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 -#define GL_NORMALIZE 0x0BA1 -#define GL_CLIP_PLANE0 0x3000 -#define GL_CLIP_PLANE1 0x3001 -#define GL_CLIP_PLANE2 0x3002 -#define GL_CLIP_PLANE3 0x3003 -#define GL_CLIP_PLANE4 0x3004 -#define GL_CLIP_PLANE5 0x3005 -#define GL_ACCUM_RED_BITS 0x0D58 -#define GL_ACCUM_GREEN_BITS 0x0D59 -#define GL_ACCUM_BLUE_BITS 0x0D5A -#define GL_ACCUM_ALPHA_BITS 0x0D5B -#define GL_ACCUM_CLEAR_VALUE 0x0B80 -#define GL_ACCUM 0x0100 -#define GL_ADD 0x0104 -#define GL_LOAD 0x0101 -#define GL_MULT 0x0103 -#define GL_RETURN 0x0102 -#define GL_ALPHA_TEST 0x0BC0 -#define GL_ALPHA_TEST_REF 0x0BC2 -#define GL_ALPHA_TEST_FUNC 0x0BC1 -#define GL_BLEND 0x0BE2 -#define GL_BLEND_SRC 0x0BE1 -#define GL_BLEND_DST 0x0BE0 -#define GL_ZERO 0x0 -#define GL_ONE 0x1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_FEEDBACK 0x1C01 -#define GL_RENDER 0x1C00 -#define GL_SELECT 0x1C02 -#define GL_2D 0x0600 -#define GL_3D 0x0601 -#define GL_3D_COLOR 0x0602 -#define GL_3D_COLOR_TEXTURE 0x0603 -#define GL_4D_COLOR_TEXTURE 0x0604 -#define GL_POINT_TOKEN 0x0701 -#define GL_LINE_TOKEN 0x0702 -#define GL_LINE_RESET_TOKEN 0x0707 -#define GL_POLYGON_TOKEN 0x0703 -#define GL_BITMAP_TOKEN 0x0704 -#define GL_DRAW_PIXEL_TOKEN 0x0705 -#define GL_COPY_PIXEL_TOKEN 0x0706 -#define GL_PASS_THROUGH_TOKEN 0x0700 -#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 -#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 -#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 -#define GL_SELECTION_BUFFER_POINTER 0x0DF3 -#define GL_SELECTION_BUFFER_SIZE 0x0DF4 -#define GL_FOG 0x0B60 -#define GL_FOG_MODE 0x0B65 -#define GL_FOG_DENSITY 0x0B62 -#define GL_FOG_COLOR 0x0B66 -#define GL_FOG_INDEX 0x0B61 -#define GL_FOG_START 0x0B63 -#define GL_FOG_END 0x0B64 -#define GL_LINEAR 0x2601 -#define GL_EXP 0x0800 -#define GL_EXP2 0x0801 -#define GL_LOGIC_OP 0x0BF1 -#define GL_INDEX_LOGIC_OP 0x0BF1 -#define GL_COLOR_LOGIC_OP 0x0BF2 -#define GL_LOGIC_OP_MODE 0x0BF0 -#define GL_CLEAR 0x1500 -#define GL_SET 0x150F -#define GL_COPY 0x1503 -#define GL_COPY_INVERTED 0x150C -#define GL_NOOP 0x1505 -#define GL_INVERT 0x150A -#define GL_AND 0x1501 -#define GL_NAND 0x150E -#define GL_OR 0x1507 -#define GL_NOR 0x1508 -#define GL_XOR 0x1506 -#define GL_EQUIV 0x1509 -#define GL_AND_REVERSE 0x1502 -#define GL_AND_INVERTED 0x1504 -#define GL_OR_REVERSE 0x150B -#define GL_OR_INVERTED 0x150D -#define GL_STENCIL_BITS 0x0D57 -#define GL_STENCIL_TEST 0x0B90 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_STENCIL_INDEX 0x1901 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_NONE 0x0 -#define GL_LEFT 0x0406 -#define GL_RIGHT 0x0407 -#define GL_FRONT_LEFT 0x0400 -#define GL_FRONT_RIGHT 0x0401 -#define GL_BACK_LEFT 0x0402 -#define GL_BACK_RIGHT 0x0403 -#define GL_AUX0 0x0409 -#define GL_AUX1 0x040A -#define GL_AUX2 0x040B -#define GL_AUX3 0x040C -#define GL_COLOR_INDEX 0x1900 -#define GL_RED 0x1903 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_ALPHA 0x1906 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A -#define GL_ALPHA_BITS 0x0D55 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_INDEX_BITS 0x0D51 -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_AUX_BUFFERS 0x0C00 -#define GL_READ_BUFFER 0x0C02 -#define GL_DRAW_BUFFER 0x0C01 -#define GL_DOUBLEBUFFER 0x0C32 -#define GL_STEREO 0x0C33 -#define GL_BITMAP 0x1A00 -#define GL_COLOR 0x1800 -#define GL_DEPTH 0x1801 -#define GL_STENCIL 0x1802 -#define GL_DITHER 0x0BD0 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_MAX_LIST_NESTING 0x0B31 -#define GL_MAX_EVAL_ORDER 0x0D30 -#define GL_MAX_LIGHTS 0x0D31 -#define GL_MAX_CLIP_PLANES 0x0D32 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 -#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 -#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 -#define GL_MAX_NAME_STACK_DEPTH 0x0D37 -#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 -#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B -#define GL_ATTRIB_STACK_DEPTH 0x0BB0 -#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_CURRENT_INDEX 0x0B01 -#define GL_CURRENT_COLOR 0x0B00 -#define GL_CURRENT_NORMAL 0x0B02 -#define GL_CURRENT_RASTER_COLOR 0x0B04 -#define GL_CURRENT_RASTER_DISTANCE 0x0B09 -#define GL_CURRENT_RASTER_INDEX 0x0B05 -#define GL_CURRENT_RASTER_POSITION 0x0B07 -#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 -#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 -#define GL_CURRENT_TEXTURE_COORDS 0x0B03 -#define GL_INDEX_CLEAR_VALUE 0x0C20 -#define GL_INDEX_MODE 0x0C30 -#define GL_INDEX_WRITEMASK 0x0C21 -#define GL_MODELVIEW_MATRIX 0x0BA6 -#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 -#define GL_NAME_STACK_DEPTH 0x0D70 -#define GL_PROJECTION_MATRIX 0x0BA7 -#define GL_PROJECTION_STACK_DEPTH 0x0BA4 -#define GL_RENDER_MODE 0x0C40 -#define GL_RGBA_MODE 0x0C31 -#define GL_TEXTURE_MATRIX 0x0BA8 -#define GL_TEXTURE_STACK_DEPTH 0x0BA5 -#define GL_VIEWPORT 0x0BA2 -#define GL_AUTO_NORMAL 0x0D80 -#define GL_MAP1_COLOR_4 0x0D90 -#define GL_MAP1_INDEX 0x0D91 -#define GL_MAP1_NORMAL 0x0D92 -#define GL_MAP1_TEXTURE_COORD_1 0x0D93 -#define GL_MAP1_TEXTURE_COORD_2 0x0D94 -#define GL_MAP1_TEXTURE_COORD_3 0x0D95 -#define GL_MAP1_TEXTURE_COORD_4 0x0D96 -#define GL_MAP1_VERTEX_3 0x0D97 -#define GL_MAP1_VERTEX_4 0x0D98 -#define GL_MAP2_COLOR_4 0x0DB0 -#define GL_MAP2_INDEX 0x0DB1 -#define GL_MAP2_NORMAL 0x0DB2 -#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 -#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 -#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 -#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 -#define GL_MAP2_VERTEX_3 0x0DB7 -#define GL_MAP2_VERTEX_4 0x0DB8 -#define GL_MAP1_GRID_DOMAIN 0x0DD0 -#define GL_MAP1_GRID_SEGMENTS 0x0DD1 -#define GL_MAP2_GRID_DOMAIN 0x0DD2 -#define GL_MAP2_GRID_SEGMENTS 0x0DD3 -#define GL_COEFF 0x0A00 -#define GL_ORDER 0x0A01 -#define GL_DOMAIN 0x0A02 -#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 -#define GL_POINT_SMOOTH_HINT 0x0C51 -#define GL_LINE_SMOOTH_HINT 0x0C52 -#define GL_POLYGON_SMOOTH_HINT 0x0C53 -#define GL_FOG_HINT 0x0C54 -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_MAP_COLOR 0x0D10 -#define GL_MAP_STENCIL 0x0D11 -#define GL_INDEX_SHIFT 0x0D12 -#define GL_INDEX_OFFSET 0x0D13 -#define GL_RED_SCALE 0x0D14 -#define GL_RED_BIAS 0x0D15 -#define GL_GREEN_SCALE 0x0D18 -#define GL_GREEN_BIAS 0x0D19 -#define GL_BLUE_SCALE 0x0D1A -#define GL_BLUE_BIAS 0x0D1B -#define GL_ALPHA_SCALE 0x0D1C -#define GL_ALPHA_BIAS 0x0D1D -#define GL_DEPTH_SCALE 0x0D1E -#define GL_DEPTH_BIAS 0x0D1F -#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 -#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 -#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 -#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 -#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 -#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 -#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 -#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 -#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 -#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 -#define GL_PIXEL_MAP_S_TO_S 0x0C71 -#define GL_PIXEL_MAP_I_TO_I 0x0C70 -#define GL_PIXEL_MAP_I_TO_R 0x0C72 -#define GL_PIXEL_MAP_I_TO_G 0x0C73 -#define GL_PIXEL_MAP_I_TO_B 0x0C74 -#define GL_PIXEL_MAP_I_TO_A 0x0C75 -#define GL_PIXEL_MAP_R_TO_R 0x0C76 -#define GL_PIXEL_MAP_G_TO_G 0x0C77 -#define GL_PIXEL_MAP_B_TO_B 0x0C78 -#define GL_PIXEL_MAP_A_TO_A 0x0C79 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_PACK_LSB_FIRST 0x0D01 -#define GL_PACK_ROW_LENGTH 0x0D02 -#define GL_PACK_SKIP_PIXELS 0x0D04 -#define GL_PACK_SKIP_ROWS 0x0D03 -#define GL_PACK_SWAP_BYTES 0x0D00 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_UNPACK_LSB_FIRST 0x0CF1 -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SWAP_BYTES 0x0CF0 -#define GL_ZOOM_X 0x0D16 -#define GL_ZOOM_Y 0x0D17 -#define GL_TEXTURE_ENV 0x2300 -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_TEXTURE_1D 0x0DE0 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_ENV_COLOR 0x2201 -#define GL_TEXTURE_GEN_S 0x0C60 -#define GL_TEXTURE_GEN_T 0x0C61 -#define GL_TEXTURE_GEN_MODE 0x2500 -#define GL_TEXTURE_BORDER_COLOR 0x1004 -#define GL_TEXTURE_WIDTH 0x1000 -#define GL_TEXTURE_HEIGHT 0x1001 -#define GL_TEXTURE_BORDER 0x1005 -#define GL_TEXTURE_COMPONENTS 0x1003 -#define GL_TEXTURE_RED_SIZE 0x805C -#define GL_TEXTURE_GREEN_SIZE 0x805D -#define GL_TEXTURE_BLUE_SIZE 0x805E -#define GL_TEXTURE_ALPHA_SIZE 0x805F -#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 -#define GL_TEXTURE_INTENSITY_SIZE 0x8061 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_OBJECT_LINEAR 0x2401 -#define GL_OBJECT_PLANE 0x2501 -#define GL_EYE_LINEAR 0x2400 -#define GL_EYE_PLANE 0x2502 -#define GL_SPHERE_MAP 0x2402 -#define GL_DECAL 0x2101 -#define GL_MODULATE 0x2100 -#define GL_NEAREST 0x2600 -#define GL_REPEAT 0x2901 -#define GL_CLAMP 0x2900 -#define GL_S 0x2000 -#define GL_T 0x2001 -#define GL_R 0x2002 -#define GL_Q 0x2003 -#define GL_TEXTURE_GEN_R 0x0C62 -#define GL_TEXTURE_GEN_Q 0x0C63 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_NO_ERROR 0x0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_CURRENT_BIT 0x00000001 -#define GL_POINT_BIT 0x00000002 -#define GL_LINE_BIT 0x00000004 -#define GL_POLYGON_BIT 0x00000008 -#define GL_POLYGON_STIPPLE_BIT 0x00000010 -#define GL_PIXEL_MODE_BIT 0x00000020 -#define GL_LIGHTING_BIT 0x00000040 -#define GL_FOG_BIT 0x00000080 -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_ACCUM_BUFFER_BIT 0x00000200 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_VIEWPORT_BIT 0x00000800 -#define GL_TRANSFORM_BIT 0x00001000 -#define GL_ENABLE_BIT 0x00002000 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_HINT_BIT 0x00008000 -#define GL_EVAL_BIT 0x00010000 -#define GL_LIST_BIT 0x00020000 -#define GL_TEXTURE_BIT 0x00040000 -#define GL_SCISSOR_BIT 0x00080000 -#define GL_ALL_ATTRIB_BITS 0x000FFFFF -#define GL_PROXY_TEXTURE_1D 0x8063 -#define GL_PROXY_TEXTURE_2D 0x8064 -#define GL_TEXTURE_PRIORITY 0x8066 -#define GL_TEXTURE_RESIDENT 0x8067 -#define GL_TEXTURE_BINDING_1D 0x8068 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 -#define GL_ALPHA4 0x803B -#define GL_ALPHA8 0x803C -#define GL_ALPHA12 0x803D -#define GL_ALPHA16 0x803E -#define GL_LUMINANCE4 0x803F -#define GL_LUMINANCE8 0x8040 -#define GL_LUMINANCE12 0x8041 -#define GL_LUMINANCE16 0x8042 -#define GL_LUMINANCE4_ALPHA4 0x8043 -#define GL_LUMINANCE6_ALPHA2 0x8044 -#define GL_LUMINANCE8_ALPHA8 0x8045 -#define GL_LUMINANCE12_ALPHA4 0x8046 -#define GL_LUMINANCE12_ALPHA12 0x8047 -#define GL_LUMINANCE16_ALPHA16 0x8048 -#define GL_INTENSITY 0x8049 -#define GL_INTENSITY4 0x804A -#define GL_INTENSITY8 0x804B -#define GL_INTENSITY12 0x804C -#define GL_INTENSITY16 0x804D -#define GL_R3_G3_B2 0x2A10 -#define GL_RGB4 0x804F -#define GL_RGB5 0x8050 -#define GL_RGB8 0x8051 -#define GL_RGB10 0x8052 -#define GL_RGB12 0x8053 -#define GL_RGB16 0x8054 -#define GL_RGBA2 0x8055 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGBA8 0x8058 -#define GL_RGB10_A2 0x8059 -#define GL_RGBA12 0x805A -#define GL_RGBA16 0x805B -#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 -#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 -#define GL_ALL_CLIENT_ATTRIB_BITS 0xFFFFFFFF -#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF -#define GL_RESCALE_NORMAL 0x803A -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_UNSIGNED_BYTE_3_3_2 0x8032 -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 -#define GL_SINGLE_COLOR 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR 0x81FA -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 -#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 -#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 -#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_PACK_SKIP_IMAGES 0x806B -#define GL_PACK_IMAGE_HEIGHT 0x806C -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_PROXY_TEXTURE_3D 0x8070 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_COLOR_TABLE 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 -#define GL_PROXY_COLOR_TABLE 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 -#define GL_COLOR_TABLE_SCALE 0x80D6 -#define GL_COLOR_TABLE_BIAS 0x80D7 -#define GL_COLOR_TABLE_FORMAT 0x80D8 -#define GL_COLOR_TABLE_WIDTH 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF -#define GL_CONVOLUTION_1D 0x8010 -#define GL_CONVOLUTION_2D 0x8011 -#define GL_SEPARABLE_2D 0x8012 -#define GL_CONVOLUTION_BORDER_MODE 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS 0x8015 -#define GL_REDUCE 0x8016 -#define GL_CONVOLUTION_FORMAT 0x8017 -#define GL_CONVOLUTION_WIDTH 0x8018 -#define GL_CONVOLUTION_HEIGHT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 -#define GL_CONSTANT_BORDER 0x8151 -#define GL_REPLICATE_BORDER 0x8153 -#define GL_CONVOLUTION_BORDER_COLOR 0x8154 -#define GL_COLOR_MATRIX 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA -#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB -#define GL_HISTOGRAM 0x8024 -#define GL_PROXY_HISTOGRAM 0x8025 -#define GL_HISTOGRAM_WIDTH 0x8026 -#define GL_HISTOGRAM_FORMAT 0x8027 -#define GL_HISTOGRAM_RED_SIZE 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C -#define GL_HISTOGRAM_SINK 0x802D -#define GL_MINMAX 0x802E -#define GL_MINMAX_FORMAT 0x802F -#define GL_MINMAX_SINK 0x8030 -#define GL_TABLE_TOO_LARGE 0x8031 -#define GL_BLEND_EQUATION 0x8009 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_FUNC_ADD 0x8006 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_BLEND_COLOR 0x8005 -#define GL_TEXTURE0_ARB 0x84C0 -#define GL_TEXTURE1_ARB 0x84C1 -#define GL_TEXTURE2_ARB 0x84C2 -#define GL_TEXTURE3_ARB 0x84C3 -#define GL_TEXTURE4_ARB 0x84C4 -#define GL_TEXTURE5_ARB 0x84C5 -#define GL_TEXTURE6_ARB 0x84C6 -#define GL_TEXTURE7_ARB 0x84C7 -#define GL_TEXTURE8_ARB 0x84C8 -#define GL_TEXTURE9_ARB 0x84C9 -#define GL_TEXTURE10_ARB 0x84CA -#define GL_TEXTURE11_ARB 0x84CB -#define GL_TEXTURE12_ARB 0x84CC -#define GL_TEXTURE13_ARB 0x84CD -#define GL_TEXTURE14_ARB 0x84CE -#define GL_TEXTURE15_ARB 0x84CF -#define GL_TEXTURE16_ARB 0x84D0 -#define GL_TEXTURE17_ARB 0x84D1 -#define GL_TEXTURE18_ARB 0x84D2 -#define GL_TEXTURE19_ARB 0x84D3 -#define GL_TEXTURE20_ARB 0x84D4 -#define GL_TEXTURE21_ARB 0x84D5 -#define GL_TEXTURE22_ARB 0x84D6 -#define GL_TEXTURE23_ARB 0x84D7 -#define GL_TEXTURE24_ARB 0x84D8 -#define GL_TEXTURE25_ARB 0x84D9 -#define GL_TEXTURE26_ARB 0x84DA -#define GL_TEXTURE27_ARB 0x84DB -#define GL_TEXTURE28_ARB 0x84DC -#define GL_TEXTURE29_ARB 0x84DD -#define GL_TEXTURE30_ARB 0x84DE -#define GL_TEXTURE31_ARB 0x84DF -#define GL_ACTIVE_TEXTURE_ARB 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 -#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 - -#endif diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_logged.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_logged.h deleted file mode 100644 index 67efcafe..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_logged.h +++ /dev/null @@ -1,20 +0,0 @@ -inline void glFinish() {xGLL(EGL_TOKEN_glFinish);}; -inline void glClear(GLbitfield a0) {xGLL(EGL_TOKEN_glClear);xGLL(a0);}; -inline void glFlush() {xGLL(EGL_TOKEN_glFlush);}; -inline void glMatrixMode(GLenum a0) {xGLL(EGL_TOKEN_glMatrixMode);xGLL(a0);}; -inline void glOrtho(GLdouble a0,GLdouble a1,GLdouble a2,GLdouble a3,GLdouble a4,GLdouble a5) {xGLL(EGL_TOKEN_glOrtho);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);xGLL(a4);xGLL(a5);}; -inline void glFrustum(GLdouble a0,GLdouble a1,GLdouble a2,GLdouble a3,GLdouble a4,GLdouble a5) {xGLL(EGL_TOKEN_glFrustum);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);xGLL(a4);xGLL(a5);}; -inline void glViewport(GLint a0,GLint a1,GLsizei a2,GLsizei a3) {xGLL(EGL_TOKEN_glViewport);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);}; -inline void glPushMatrix() {xGLL(EGL_TOKEN_glPushMatrix);}; -inline void glPopMatrix() {xGLL(EGL_TOKEN_glPopMatrix);}; -inline void glLoadIdentity() {xGLL(EGL_TOKEN_glLoadIdentity);}; -inline void glLoadMatrixd(const GLdouble * a0) {xGLL(EGL_TOKEN_glLoadMatrixd);xGLL(a0);}; -inline void glLoadMatrixf(const GLfloat * a0) {xGLL(EGL_TOKEN_glLoadMatrixf);xGLL(a0);}; -inline void glMultMatrixd(const GLdouble * a0) {xGLL(EGL_TOKEN_glMultMatrixd);xGLL(a0);}; -inline void glMultMatrixf(const GLfloat * a0) {xGLL(EGL_TOKEN_glMultMatrixf);xGLL(a0);}; -inline void glRotated(GLdouble a0,GLdouble a1,GLdouble a2,GLdouble a3) {xGLL(EGL_TOKEN_glRotated);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);}; -inline void glRotatef(GLfloat a0,GLfloat a1,GLfloat a2,GLfloat a3) {xGLL(EGL_TOKEN_glRotatef);xGLL(a0);xGLL(a1);xGLL(a2);xGLL(a3);}; -inline void glScaled(GLdouble a0,GLdouble a1,GLdouble a2) {xGLL(EGL_TOKEN_glScaled);xGLL(a0);xGLL(a1);xGLL(a2);}; -inline void glScalef(GLfloat a0,GLfloat a1,GLfloat a2) {xGLL(EGL_TOKEN_glScalef);xGLL(a0);xGLL(a1);xGLL(a2);}; -inline void glTranslated(GLdouble a0,GLdouble a1,GLdouble a2) {xGLL(EGL_TOKEN_glTranslated);xGLL(a0);xGLL(a1);xGLL(a2);}; -inline void glTranslatef(GLfloat a0,GLfloat a1,GLfloat a2) {xGLL(EGL_TOKEN_glTranslatef);xGLL(a0);xGLL(a1);xGLL(a2);}; diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_tokens.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_tokens.h deleted file mode 100644 index 9678adcd..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_tokens.h +++ /dev/null @@ -1,459 +0,0 @@ -#ifndef EGL_TOKENS_H -#define EGL_TOKENS_H - -#define EGL_TOKEN_glClearIndex 0x0 -#define EGL_TOKEN_glClearColor 0x1 -#define EGL_TOKEN_glClear 0x2 -#define EGL_TOKEN_glIndexMask 0x3 -#define EGL_TOKEN_glColorMask 0x4 -#define EGL_TOKEN_glAlphaFunc 0x5 -#define EGL_TOKEN_glBlendFunc 0x6 -#define EGL_TOKEN_glLogicOp 0x7 -#define EGL_TOKEN_glCullFace 0x8 -#define EGL_TOKEN_glFrontFace 0x9 -#define EGL_TOKEN_glPointSize 0xa -#define EGL_TOKEN_glLineWidth 0xb -#define EGL_TOKEN_glLineStipple 0xc -#define EGL_TOKEN_glPolygonMode 0xd -#define EGL_TOKEN_glPolygonOffset 0xe -#define EGL_TOKEN_glPolygonStipple 0xf -#define EGL_TOKEN_glGetPolygonStipple 0x10 -#define EGL_TOKEN_glEdgeFlag 0x11 -#define EGL_TOKEN_glEdgeFlagv 0x12 -#define EGL_TOKEN_glScissor 0x13 -#define EGL_TOKEN_glClipPlane 0x14 -#define EGL_TOKEN_glGetClipPlane 0x15 -#define EGL_TOKEN_glDrawBuffer 0x16 -#define EGL_TOKEN_glReadBuffer 0x17 -#define EGL_TOKEN_glEnable 0x18 -#define EGL_TOKEN_glDisable 0x19 -#define EGL_TOKEN_glIsEnabled 0x1a -#define EGL_TOKEN_glEnableClientState 0x1b -#define EGL_TOKEN_glDisableClientState 0x1c -#define EGL_TOKEN_glGetBooleanv 0x1d -#define EGL_TOKEN_glGetDoublev 0x1e -#define EGL_TOKEN_glGetFloatv 0x1f -#define EGL_TOKEN_glGetIntegerv 0x20 -#define EGL_TOKEN_glPushAttrib 0x21 -#define EGL_TOKEN_glPopAttrib 0x22 -#define EGL_TOKEN_glPushClientAttrib 0x23 -#define EGL_TOKEN_glPopClientAttrib 0x24 -#define EGL_TOKEN_glRenderMode 0x25 -#define EGL_TOKEN_glGetError 0x26 -#define EGL_TOKEN_glGetString 0x27 -#define EGL_TOKEN_glFinish 0x28 -#define EGL_TOKEN_glFlush 0x29 -#define EGL_TOKEN_glHint 0x2a -#define EGL_TOKEN_glClearDepth 0x2b -#define EGL_TOKEN_glDepthFunc 0x2c -#define EGL_TOKEN_glDepthMask 0x2d -#define EGL_TOKEN_glDepthRange 0x2e -#define EGL_TOKEN_glClearAccum 0x2f -#define EGL_TOKEN_glAccum 0x30 -#define EGL_TOKEN_glMatrixMode 0x31 -#define EGL_TOKEN_glOrtho 0x32 -#define EGL_TOKEN_glFrustum 0x33 -#define EGL_TOKEN_glViewport 0x34 -#define EGL_TOKEN_glPushMatrix 0x35 -#define EGL_TOKEN_glPopMatrix 0x36 -#define EGL_TOKEN_glLoadIdentity 0x37 -#define EGL_TOKEN_glLoadMatrixd 0x38 -#define EGL_TOKEN_glLoadMatrixf 0x39 -#define EGL_TOKEN_glMultMatrixd 0x3a -#define EGL_TOKEN_glMultMatrixf 0x3b -#define EGL_TOKEN_glRotated 0x3c -#define EGL_TOKEN_glRotatef 0x3d -#define EGL_TOKEN_glScaled 0x3e -#define EGL_TOKEN_glScalef 0x3f -#define EGL_TOKEN_glTranslated 0x40 -#define EGL_TOKEN_glTranslatef 0x41 -#define EGL_TOKEN_glIsList 0x42 -#define EGL_TOKEN_glDeleteLists 0x43 -#define EGL_TOKEN_glGenLists 0x44 -#define EGL_TOKEN_glNewList 0x45 -#define EGL_TOKEN_glEndList 0x46 -#define EGL_TOKEN_glCallList 0x47 -#define EGL_TOKEN_glCallLists 0x48 -#define EGL_TOKEN_glListBase 0x49 -#define EGL_TOKEN_glBegin 0x4a -#define EGL_TOKEN_glEnd 0x4b -#define EGL_TOKEN_glVertex2d 0x4c -#define EGL_TOKEN_glVertex2f 0x4d -#define EGL_TOKEN_glVertex2i 0x4e -#define EGL_TOKEN_glVertex2s 0x4f -#define EGL_TOKEN_glVertex3d 0x50 -#define EGL_TOKEN_glVertex3f 0x51 -#define EGL_TOKEN_glVertex3i 0x52 -#define EGL_TOKEN_glVertex3s 0x53 -#define EGL_TOKEN_glVertex4d 0x54 -#define EGL_TOKEN_glVertex4f 0x55 -#define EGL_TOKEN_glVertex4i 0x56 -#define EGL_TOKEN_glVertex4s 0x57 -#define EGL_TOKEN_glVertex2dv 0x58 -#define EGL_TOKEN_glVertex2fv 0x59 -#define EGL_TOKEN_glVertex2iv 0x5a -#define EGL_TOKEN_glVertex2sv 0x5b -#define EGL_TOKEN_glVertex3dv 0x5c -#define EGL_TOKEN_glVertex3fv 0x5d -#define EGL_TOKEN_glVertex3iv 0x5e -#define EGL_TOKEN_glVertex3sv 0x5f -#define EGL_TOKEN_glVertex4dv 0x60 -#define EGL_TOKEN_glVertex4fv 0x61 -#define EGL_TOKEN_glVertex4iv 0x62 -#define EGL_TOKEN_glVertex4sv 0x63 -#define EGL_TOKEN_glNormal3b 0x64 -#define EGL_TOKEN_glNormal3d 0x65 -#define EGL_TOKEN_glNormal3f 0x66 -#define EGL_TOKEN_glNormal3i 0x67 -#define EGL_TOKEN_glNormal3s 0x68 -#define EGL_TOKEN_glNormal3bv 0x69 -#define EGL_TOKEN_glNormal3dv 0x6a -#define EGL_TOKEN_glNormal3fv 0x6b -#define EGL_TOKEN_glNormal3iv 0x6c -#define EGL_TOKEN_glNormal3sv 0x6d -#define EGL_TOKEN_glIndexd 0x6e -#define EGL_TOKEN_glIndexf 0x6f -#define EGL_TOKEN_glIndexi 0x70 -#define EGL_TOKEN_glIndexs 0x71 -#define EGL_TOKEN_glIndexub 0x72 -#define EGL_TOKEN_glIndexdv 0x73 -#define EGL_TOKEN_glIndexfv 0x74 -#define EGL_TOKEN_glIndexiv 0x75 -#define EGL_TOKEN_glIndexsv 0x76 -#define EGL_TOKEN_glIndexubv 0x77 -#define EGL_TOKEN_glColor3b 0x78 -#define EGL_TOKEN_glColor3d 0x79 -#define EGL_TOKEN_glColor3f 0x7a -#define EGL_TOKEN_glColor3i 0x7b -#define EGL_TOKEN_glColor3s 0x7c -#define EGL_TOKEN_glColor3ub 0x7d -#define EGL_TOKEN_glColor3ui 0x7e -#define EGL_TOKEN_glColor3us 0x7f -#define EGL_TOKEN_glColor4b 0x80 -#define EGL_TOKEN_glColor4d 0x81 -#define EGL_TOKEN_glColor4f 0x82 -#define EGL_TOKEN_glColor4i 0x83 -#define EGL_TOKEN_glColor4s 0x84 -#define EGL_TOKEN_glColor4ub 0x85 -#define EGL_TOKEN_glColor4ui 0x86 -#define EGL_TOKEN_glColor4us 0x87 -#define EGL_TOKEN_glColor3bv 0x88 -#define EGL_TOKEN_glColor3dv 0x89 -#define EGL_TOKEN_glColor3fv 0x8a -#define EGL_TOKEN_glColor3iv 0x8b -#define EGL_TOKEN_glColor3sv 0x8c -#define EGL_TOKEN_glColor3ubv 0x8d -#define EGL_TOKEN_glColor3uiv 0x8e -#define EGL_TOKEN_glColor3usv 0x8f -#define EGL_TOKEN_glColor4bv 0x90 -#define EGL_TOKEN_glColor4dv 0x91 -#define EGL_TOKEN_glColor4fv 0x92 -#define EGL_TOKEN_glColor4iv 0x93 -#define EGL_TOKEN_glColor4sv 0x94 -#define EGL_TOKEN_glColor4ubv 0x95 -#define EGL_TOKEN_glColor4uiv 0x96 -#define EGL_TOKEN_glColor4usv 0x97 -#define EGL_TOKEN_glTexCoord1d 0x98 -#define EGL_TOKEN_glTexCoord1f 0x99 -#define EGL_TOKEN_glTexCoord1i 0x9a -#define EGL_TOKEN_glTexCoord1s 0x9b -#define EGL_TOKEN_glTexCoord2d 0x9c -#define EGL_TOKEN_glTexCoord2f 0x9d -#define EGL_TOKEN_glTexCoord2i 0x9e -#define EGL_TOKEN_glTexCoord2s 0x9f -#define EGL_TOKEN_glTexCoord3d 0xa0 -#define EGL_TOKEN_glTexCoord3f 0xa1 -#define EGL_TOKEN_glTexCoord3i 0xa2 -#define EGL_TOKEN_glTexCoord3s 0xa3 -#define EGL_TOKEN_glTexCoord4d 0xa4 -#define EGL_TOKEN_glTexCoord4f 0xa5 -#define EGL_TOKEN_glTexCoord4i 0xa6 -#define EGL_TOKEN_glTexCoord4s 0xa7 -#define EGL_TOKEN_glTexCoord1dv 0xa8 -#define EGL_TOKEN_glTexCoord1fv 0xa9 -#define EGL_TOKEN_glTexCoord1iv 0xaa -#define EGL_TOKEN_glTexCoord1sv 0xab -#define EGL_TOKEN_glTexCoord2dv 0xac -#define EGL_TOKEN_glTexCoord2fv 0xad -#define EGL_TOKEN_glTexCoord2iv 0xae -#define EGL_TOKEN_glTexCoord2sv 0xaf -#define EGL_TOKEN_glTexCoord3dv 0xb0 -#define EGL_TOKEN_glTexCoord3fv 0xb1 -#define EGL_TOKEN_glTexCoord3iv 0xb2 -#define EGL_TOKEN_glTexCoord3sv 0xb3 -#define EGL_TOKEN_glTexCoord4dv 0xb4 -#define EGL_TOKEN_glTexCoord4fv 0xb5 -#define EGL_TOKEN_glTexCoord4iv 0xb6 -#define EGL_TOKEN_glTexCoord4sv 0xb7 -#define EGL_TOKEN_glRasterPos2d 0xb8 -#define EGL_TOKEN_glRasterPos2f 0xb9 -#define EGL_TOKEN_glRasterPos2i 0xba -#define EGL_TOKEN_glRasterPos2s 0xbb -#define EGL_TOKEN_glRasterPos3d 0xbc -#define EGL_TOKEN_glRasterPos3f 0xbd -#define EGL_TOKEN_glRasterPos3i 0xbe -#define EGL_TOKEN_glRasterPos3s 0xbf -#define EGL_TOKEN_glRasterPos4d 0xc0 -#define EGL_TOKEN_glRasterPos4f 0xc1 -#define EGL_TOKEN_glRasterPos4i 0xc2 -#define EGL_TOKEN_glRasterPos4s 0xc3 -#define EGL_TOKEN_glRasterPos2dv 0xc4 -#define EGL_TOKEN_glRasterPos2fv 0xc5 -#define EGL_TOKEN_glRasterPos2iv 0xc6 -#define EGL_TOKEN_glRasterPos2sv 0xc7 -#define EGL_TOKEN_glRasterPos3dv 0xc8 -#define EGL_TOKEN_glRasterPos3fv 0xc9 -#define EGL_TOKEN_glRasterPos3iv 0xca -#define EGL_TOKEN_glRasterPos3sv 0xcb -#define EGL_TOKEN_glRasterPos4dv 0xcc -#define EGL_TOKEN_glRasterPos4fv 0xcd -#define EGL_TOKEN_glRasterPos4iv 0xce -#define EGL_TOKEN_glRasterPos4sv 0xcf -#define EGL_TOKEN_glRectd 0xd0 -#define EGL_TOKEN_glRectf 0xd1 -#define EGL_TOKEN_glRecti 0xd2 -#define EGL_TOKEN_glRects 0xd3 -#define EGL_TOKEN_glRectdv 0xd4 -#define EGL_TOKEN_glRectfv 0xd5 -#define EGL_TOKEN_glRectiv 0xd6 -#define EGL_TOKEN_glRectsv 0xd7 -#define EGL_TOKEN_glVertexPointer 0xd8 -#define EGL_TOKEN_glNormalPointer 0xd9 -#define EGL_TOKEN_glColorPointer 0xda -#define EGL_TOKEN_glIndexPointer 0xdb -#define EGL_TOKEN_glTexCoordPointer 0xdc -#define EGL_TOKEN_glEdgeFlagPointer 0xdd -#define EGL_TOKEN_glGetPointerv 0xde -#define EGL_TOKEN_glArrayElement 0xdf -#define EGL_TOKEN_glDrawArrays 0xe0 -#define EGL_TOKEN_glDrawElements 0xe1 -#define EGL_TOKEN_glInterleavedArrays 0xe2 -#define EGL_TOKEN_glShadeModel 0xe3 -#define EGL_TOKEN_glLightf 0xe4 -#define EGL_TOKEN_glLighti 0xe5 -#define EGL_TOKEN_glLightfv 0xe6 -#define EGL_TOKEN_glLightiv 0xe7 -#define EGL_TOKEN_glGetLightfv 0xe8 -#define EGL_TOKEN_glGetLightiv 0xe9 -#define EGL_TOKEN_glLightModelf 0xea -#define EGL_TOKEN_glLightModeli 0xeb -#define EGL_TOKEN_glLightModelfv 0xec -#define EGL_TOKEN_glLightModeliv 0xed -#define EGL_TOKEN_glMaterialf 0xee -#define EGL_TOKEN_glMateriali 0xef -#define EGL_TOKEN_glMaterialfv 0xf0 -#define EGL_TOKEN_glMaterialiv 0xf1 -#define EGL_TOKEN_glGetMaterialfv 0xf2 -#define EGL_TOKEN_glGetMaterialiv 0xf3 -#define EGL_TOKEN_glColorMaterial 0xf4 -#define EGL_TOKEN_glPixelZoom 0xf5 -#define EGL_TOKEN_glPixelStoref 0xf6 -#define EGL_TOKEN_glPixelStorei 0xf7 -#define EGL_TOKEN_glPixelTransferf 0xf8 -#define EGL_TOKEN_glPixelTransferi 0xf9 -#define EGL_TOKEN_glPixelMapfv 0xfa -#define EGL_TOKEN_glPixelMapuiv 0xfb -#define EGL_TOKEN_glPixelMapusv 0xfc -#define EGL_TOKEN_glGetPixelMapfv 0xfd -#define EGL_TOKEN_glGetPixelMapuiv 0xfe -#define EGL_TOKEN_glGetPixelMapusv 0xff -#define EGL_TOKEN_glBitmap 0x100 -#define EGL_TOKEN_glReadPixels 0x101 -#define EGL_TOKEN_glDrawPixels 0x102 -#define EGL_TOKEN_glCopyPixels 0x103 -#define EGL_TOKEN_glStencilFunc 0x104 -#define EGL_TOKEN_glStencilMask 0x105 -#define EGL_TOKEN_glStencilOp 0x106 -#define EGL_TOKEN_glClearStencil 0x107 -#define EGL_TOKEN_glTexGend 0x108 -#define EGL_TOKEN_glTexGenf 0x109 -#define EGL_TOKEN_glTexGeni 0x10a -#define EGL_TOKEN_glTexGendv 0x10b -#define EGL_TOKEN_glTexGenfv 0x10c -#define EGL_TOKEN_glTexGeniv 0x10d -#define EGL_TOKEN_glGetTexGendv 0x10e -#define EGL_TOKEN_glGetTexGenfv 0x10f -#define EGL_TOKEN_glGetTexGeniv 0x110 -#define EGL_TOKEN_glTexEnvf 0x111 -#define EGL_TOKEN_glTexEnvi 0x112 -#define EGL_TOKEN_glTexEnvfv 0x113 -#define EGL_TOKEN_glTexEnviv 0x114 -#define EGL_TOKEN_glGetTexEnvfv 0x115 -#define EGL_TOKEN_glGetTexEnviv 0x116 -#define EGL_TOKEN_glTexParameterf 0x117 -#define EGL_TOKEN_glTexParameteri 0x118 -#define EGL_TOKEN_glTexParameterfv 0x119 -#define EGL_TOKEN_glTexParameteriv 0x11a -#define EGL_TOKEN_glGetTexParameterfv 0x11b -#define EGL_TOKEN_glGetTexParameteriv 0x11c -#define EGL_TOKEN_glGetTexLevelParameterfv 0x11d -#define EGL_TOKEN_glGetTexLevelParameteriv 0x11e -#define EGL_TOKEN_glTexImage1D 0x11f -#define EGL_TOKEN_glTexImage2D 0x120 -#define EGL_TOKEN_glGetTexImage 0x121 -#define EGL_TOKEN_glGenTextures 0x122 -#define EGL_TOKEN_glDeleteTextures 0x123 -#define EGL_TOKEN_glBindTexture 0x124 -#define EGL_TOKEN_glPrioritizeTextures 0x125 -#define EGL_TOKEN_glAreTexturesResident 0x126 -#define EGL_TOKEN_glIsTexture 0x127 -#define EGL_TOKEN_glTexSubImage1D 0x128 -#define EGL_TOKEN_glTexSubImage2D 0x129 -#define EGL_TOKEN_glCopyTexImage1D 0x12a -#define EGL_TOKEN_glCopyTexImage2D 0x12b -#define EGL_TOKEN_glCopyTexSubImage1D 0x12c -#define EGL_TOKEN_glCopyTexSubImage2D 0x12d -#define EGL_TOKEN_glMap1d 0x12e -#define EGL_TOKEN_glMap1f 0x12f -#define EGL_TOKEN_glMap2d 0x130 -#define EGL_TOKEN_glMap2f 0x131 -#define EGL_TOKEN_glGetMapdv 0x132 -#define EGL_TOKEN_glGetMapfv 0x133 -#define EGL_TOKEN_glGetMapiv 0x134 -#define EGL_TOKEN_glEvalCoord1d 0x135 -#define EGL_TOKEN_glEvalCoord1f 0x136 -#define EGL_TOKEN_glEvalCoord1dv 0x137 -#define EGL_TOKEN_glEvalCoord1fv 0x138 -#define EGL_TOKEN_glEvalCoord2d 0x139 -#define EGL_TOKEN_glEvalCoord2f 0x13a -#define EGL_TOKEN_glEvalCoord2dv 0x13b -#define EGL_TOKEN_glEvalCoord2fv 0x13c -#define EGL_TOKEN_glMapGrid1d 0x13d -#define EGL_TOKEN_glMapGrid1f 0x13e -#define EGL_TOKEN_glMapGrid2d 0x13f -#define EGL_TOKEN_glMapGrid2f 0x140 -#define EGL_TOKEN_glEvalPoint1 0x141 -#define EGL_TOKEN_glEvalPoint2 0x142 -#define EGL_TOKEN_glEvalMesh1 0x143 -#define EGL_TOKEN_glEvalMesh2 0x144 -#define EGL_TOKEN_glFogf 0x145 -#define EGL_TOKEN_glFogi 0x146 -#define EGL_TOKEN_glFogfv 0x147 -#define EGL_TOKEN_glFogiv 0x148 -#define EGL_TOKEN_glFeedbackBuffer 0x149 -#define EGL_TOKEN_glPassThrough 0x14a -#define EGL_TOKEN_glSelectBuffer 0x14b -#define EGL_TOKEN_glInitNames 0x14c -#define EGL_TOKEN_glLoadName 0x14d -#define EGL_TOKEN_glPushName 0x14e -#define EGL_TOKEN_glPopName 0x14f -#define EGL_TOKEN_glDrawRangeElements 0x150 -#define EGL_TOKEN_glTexImage3D 0x151 -#define EGL_TOKEN_glTexSubImage3D 0x152 -#define EGL_TOKEN_glCopyTexSubImage3D 0x153 -#define EGL_TOKEN_glColorTable 0x154 -#define EGL_TOKEN_glColorSubTable 0x155 -#define EGL_TOKEN_glColorTableParameteriv 0x156 -#define EGL_TOKEN_glColorTableParameterfv 0x157 -#define EGL_TOKEN_glCopyColorSubTable 0x158 -#define EGL_TOKEN_glCopyColorTable 0x159 -#define EGL_TOKEN_glGetColorTable 0x15a -#define EGL_TOKEN_glGetColorTableParameterfv 0x15b -#define EGL_TOKEN_glGetColorTableParameteriv 0x15c -#define EGL_TOKEN_glBlendEquation 0x15d -#define EGL_TOKEN_glBlendColor 0x15e -#define EGL_TOKEN_glHistogram 0x15f -#define EGL_TOKEN_glResetHistogram 0x160 -#define EGL_TOKEN_glGetHistogram 0x161 -#define EGL_TOKEN_glGetHistogramParameterfv 0x162 -#define EGL_TOKEN_glGetHistogramParameteriv 0x163 -#define EGL_TOKEN_glMinmax 0x164 -#define EGL_TOKEN_glResetMinmax 0x165 -#define EGL_TOKEN_glGetMinmax 0x166 -#define EGL_TOKEN_glGetMinmaxParameterfv 0x167 -#define EGL_TOKEN_glGetMinmaxParameteriv 0x168 -#define EGL_TOKEN_glConvolutionFilter1D 0x169 -#define EGL_TOKEN_glConvolutionFilter2D 0x16a -#define EGL_TOKEN_glConvolutionParameterf 0x16b -#define EGL_TOKEN_glConvolutionParameterfv 0x16c -#define EGL_TOKEN_glConvolutionParameteri 0x16d -#define EGL_TOKEN_glConvolutionParameteriv 0x16e -#define EGL_TOKEN_glCopyConvolutionFilter1D 0x16f -#define EGL_TOKEN_glCopyConvolutionFilter2D 0x170 -#define EGL_TOKEN_glGetConvolutionFilter 0x171 -#define EGL_TOKEN_glGetConvolutionParameterfv 0x172 -#define EGL_TOKEN_glGetConvolutionParameteriv 0x173 -#define EGL_TOKEN_glSeparableFilter2D 0x174 -#define EGL_TOKEN_glGetSeparableFilter 0x175 -#define EGL_TOKEN_glActiveTexture 0x176 -#define EGL_TOKEN_glClientActiveTexture 0x177 -#define EGL_TOKEN_glCompressedTexImage1D 0x178 -#define EGL_TOKEN_glCompressedTexImage2D 0x179 -#define EGL_TOKEN_glCompressedTexImage3D 0x17a -#define EGL_TOKEN_glCompressedTexSubImage1D 0x17b -#define EGL_TOKEN_glCompressedTexSubImage2D 0x17c -#define EGL_TOKEN_glCompressedTexSubImage3D 0x17d -#define EGL_TOKEN_glGetCompressedTexImage 0x17e -#define EGL_TOKEN_glMultiTexCoord1d 0x17f -#define EGL_TOKEN_glMultiTexCoord1dv 0x180 -#define EGL_TOKEN_glMultiTexCoord1f 0x181 -#define EGL_TOKEN_glMultiTexCoord1fv 0x182 -#define EGL_TOKEN_glMultiTexCoord1i 0x183 -#define EGL_TOKEN_glMultiTexCoord1iv 0x184 -#define EGL_TOKEN_glMultiTexCoord1s 0x185 -#define EGL_TOKEN_glMultiTexCoord1sv 0x186 -#define EGL_TOKEN_glMultiTexCoord2d 0x187 -#define EGL_TOKEN_glMultiTexCoord2dv 0x188 -#define EGL_TOKEN_glMultiTexCoord2f 0x189 -#define EGL_TOKEN_glMultiTexCoord2fv 0x18a -#define EGL_TOKEN_glMultiTexCoord2i 0x18b -#define EGL_TOKEN_glMultiTexCoord2iv 0x18c -#define EGL_TOKEN_glMultiTexCoord2s 0x18d -#define EGL_TOKEN_glMultiTexCoord2sv 0x18e -#define EGL_TOKEN_glMultiTexCoord3d 0x18f -#define EGL_TOKEN_glMultiTexCoord3dv 0x190 -#define EGL_TOKEN_glMultiTexCoord3f 0x191 -#define EGL_TOKEN_glMultiTexCoord3fv 0x192 -#define EGL_TOKEN_glMultiTexCoord3i 0x193 -#define EGL_TOKEN_glMultiTexCoord3iv 0x194 -#define EGL_TOKEN_glMultiTexCoord3s 0x195 -#define EGL_TOKEN_glMultiTexCoord3sv 0x196 -#define EGL_TOKEN_glMultiTexCoord4d 0x197 -#define EGL_TOKEN_glMultiTexCoord4dv 0x198 -#define EGL_TOKEN_glMultiTexCoord4f 0x199 -#define EGL_TOKEN_glMultiTexCoord4fv 0x19a -#define EGL_TOKEN_glMultiTexCoord4i 0x19b -#define EGL_TOKEN_glMultiTexCoord4iv 0x19c -#define EGL_TOKEN_glMultiTexCoord4s 0x19d -#define EGL_TOKEN_glMultiTexCoord4sv 0x19e -#define EGL_TOKEN_glLoadTransposeMatrixd 0x19f -#define EGL_TOKEN_glLoadTransposeMatrixf 0x1a0 -#define EGL_TOKEN_glMultTransposeMatrixd 0x1a1 -#define EGL_TOKEN_glMultTransposeMatrixf 0x1a2 -#define EGL_TOKEN_glSampleCoverage 0x1a3 -#define EGL_TOKEN_glActiveTextureARB 0x1a4 -#define EGL_TOKEN_glClientActiveTextureARB 0x1a5 -#define EGL_TOKEN_glMultiTexCoord1dARB 0x1a6 -#define EGL_TOKEN_glMultiTexCoord1dvARB 0x1a7 -#define EGL_TOKEN_glMultiTexCoord1fARB 0x1a8 -#define EGL_TOKEN_glMultiTexCoord1fvARB 0x1a9 -#define EGL_TOKEN_glMultiTexCoord1iARB 0x1aa -#define EGL_TOKEN_glMultiTexCoord1ivARB 0x1ab -#define EGL_TOKEN_glMultiTexCoord1sARB 0x1ac -#define EGL_TOKEN_glMultiTexCoord1svARB 0x1ad -#define EGL_TOKEN_glMultiTexCoord2dARB 0x1ae -#define EGL_TOKEN_glMultiTexCoord2dvARB 0x1af -#define EGL_TOKEN_glMultiTexCoord2fARB 0x1b0 -#define EGL_TOKEN_glMultiTexCoord2fvARB 0x1b1 -#define EGL_TOKEN_glMultiTexCoord2iARB 0x1b2 -#define EGL_TOKEN_glMultiTexCoord2ivARB 0x1b3 -#define EGL_TOKEN_glMultiTexCoord2sARB 0x1b4 -#define EGL_TOKEN_glMultiTexCoord2svARB 0x1b5 -#define EGL_TOKEN_glMultiTexCoord3dARB 0x1b6 -#define EGL_TOKEN_glMultiTexCoord3dvARB 0x1b7 -#define EGL_TOKEN_glMultiTexCoord3fARB 0x1b8 -#define EGL_TOKEN_glMultiTexCoord3fvARB 0x1b9 -#define EGL_TOKEN_glMultiTexCoord3iARB 0x1ba -#define EGL_TOKEN_glMultiTexCoord3ivARB 0x1bb -#define EGL_TOKEN_glMultiTexCoord3sARB 0x1bc -#define EGL_TOKEN_glMultiTexCoord3svARB 0x1bd -#define EGL_TOKEN_glMultiTexCoord4dARB 0x1be -#define EGL_TOKEN_glMultiTexCoord4dvARB 0x1bf -#define EGL_TOKEN_glMultiTexCoord4fARB 0x1c0 -#define EGL_TOKEN_glMultiTexCoord4fvARB 0x1c1 -#define EGL_TOKEN_glMultiTexCoord4iARB 0x1c2 -#define EGL_TOKEN_glMultiTexCoord4ivARB 0x1c3 -#define EGL_TOKEN_glMultiTexCoord4sARB 0x1c4 -#define EGL_TOKEN_glMultiTexCoord4svARB 0x1c5 - -#endif diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_void.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_void.h deleted file mode 100644 index 82cb7e36..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/egl_void.h +++ /dev/null @@ -1,422 +0,0 @@ -#define glClearIndex(_a0) {(void)(_a0);} -#define glClearColor(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glIndexMask(_a0) {(void)(_a0);} -#define glColorMask(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glAlphaFunc(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glBlendFunc(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glLogicOp(_a0) {(void)(_a0);} -#define glCullFace(_a0) {(void)(_a0);} -#define glFrontFace(_a0) {(void)(_a0);} -#define glPointSize(_a0) {(void)(_a0);} -#define glLineWidth(_a0) {(void)(_a0);} -#define glLineStipple(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPolygonMode(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPolygonOffset(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPolygonStipple(_a0) {(void)(_a0);} -#define glGetPolygonStipple(_a0) {(void)(_a0);} -#define glEdgeFlag(_a0) {(void)(_a0);} -#define glEdgeFlagv(_a0) {(void)(_a0);} -#define glScissor(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glClipPlane(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glGetClipPlane(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glDrawBuffer(_a0) {(void)(_a0);} -#define glReadBuffer(_a0) {(void)(_a0);} -#define glEnable(_a0) {(void)(_a0);} -#define glDisable(_a0) {(void)(_a0);} -#define glEnableClientState(_a0) {(void)(_a0);} -#define glDisableClientState(_a0) {(void)(_a0);} -#define glPushAttrib(_a0) {(void)(_a0);} -#define glPopAttrib() {} -#define glPushClientAttrib(_a0) {(void)(_a0);} -#define glPopClientAttrib() {} -#define glHint(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glClearDepth(_a0) {(void)(_a0);} -#define glDepthFunc(_a0) {(void)(_a0);} -#define glDepthMask(_a0) {(void)(_a0);} -#define glDepthRange(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glClearAccum(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glAccum(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glDeleteLists(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glNewList(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glEndList() {} -#define glCallList(_a0) {(void)(_a0);} -#define glCallLists(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glListBase(_a0) {(void)(_a0);} -#define glBegin(_a0) {(void)(_a0);} -#define glEnd() {} -#define glVertex2d(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glVertex2f(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glVertex2i(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glVertex2s(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glVertex3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glVertex3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glVertex3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glVertex3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glVertex4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glVertex4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glVertex4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glVertex4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glVertex2dv(_a0) {(void)(_a0);} -#define glVertex2fv(_a0) {(void)(_a0);} -#define glVertex2iv(_a0) {(void)(_a0);} -#define glVertex2sv(_a0) {(void)(_a0);} -#define glVertex3dv(_a0) {(void)(_a0);} -#define glVertex3fv(_a0) {(void)(_a0);} -#define glVertex3iv(_a0) {(void)(_a0);} -#define glVertex3sv(_a0) {(void)(_a0);} -#define glVertex4dv(_a0) {(void)(_a0);} -#define glVertex4fv(_a0) {(void)(_a0);} -#define glVertex4iv(_a0) {(void)(_a0);} -#define glVertex4sv(_a0) {(void)(_a0);} -#define glNormal3b(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glNormal3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glNormal3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glNormal3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glNormal3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glNormal3bv(_a0) {(void)(_a0);} -#define glNormal3dv(_a0) {(void)(_a0);} -#define glNormal3fv(_a0) {(void)(_a0);} -#define glNormal3iv(_a0) {(void)(_a0);} -#define glNormal3sv(_a0) {(void)(_a0);} -#define glIndexd(_a0) {(void)(_a0);} -#define glIndexf(_a0) {(void)(_a0);} -#define glIndexi(_a0) {(void)(_a0);} -#define glIndexs(_a0) {(void)(_a0);} -#define glIndexub(_a0) {(void)(_a0);} -#define glIndexdv(_a0) {(void)(_a0);} -#define glIndexfv(_a0) {(void)(_a0);} -#define glIndexiv(_a0) {(void)(_a0);} -#define glIndexsv(_a0) {(void)(_a0);} -#define glIndexubv(_a0) {(void)(_a0);} -#define glColor3b(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3ub(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3ui(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor3us(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColor4b(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4ub(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4ui(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor4us(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glColor3bv(_a0) {(void)(_a0);} -#define glColor3dv(_a0) {(void)(_a0);} -#define glColor3fv(_a0) {(void)(_a0);} -#define glColor3iv(_a0) {(void)(_a0);} -#define glColor3sv(_a0) {(void)(_a0);} -#define glColor3ubv(_a0) {(void)(_a0);} -#define glColor3uiv(_a0) {(void)(_a0);} -#define glColor3usv(_a0) {(void)(_a0);} -#define glColor4bv(_a0) {(void)(_a0);} -#define glColor4dv(_a0) {(void)(_a0);} -#define glColor4fv(_a0) {(void)(_a0);} -#define glColor4iv(_a0) {(void)(_a0);} -#define glColor4sv(_a0) {(void)(_a0);} -#define glColor4ubv(_a0) {(void)(_a0);} -#define glColor4uiv(_a0) {(void)(_a0);} -#define glColor4usv(_a0) {(void)(_a0);} -#define glTexCoord1d(_a0) {(void)(_a0);} -#define glTexCoord1f(_a0) {(void)(_a0);} -#define glTexCoord1i(_a0) {(void)(_a0);} -#define glTexCoord1s(_a0) {(void)(_a0);} -#define glTexCoord2d(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glTexCoord2f(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glTexCoord2i(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glTexCoord2s(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glTexCoord3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexCoord3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexCoord3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexCoord3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexCoord4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glTexCoord4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glTexCoord4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glTexCoord4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glTexCoord1dv(_a0) {(void)(_a0);} -#define glTexCoord1fv(_a0) {(void)(_a0);} -#define glTexCoord1iv(_a0) {(void)(_a0);} -#define glTexCoord1sv(_a0) {(void)(_a0);} -#define glTexCoord2dv(_a0) {(void)(_a0);} -#define glTexCoord2fv(_a0) {(void)(_a0);} -#define glTexCoord2iv(_a0) {(void)(_a0);} -#define glTexCoord2sv(_a0) {(void)(_a0);} -#define glTexCoord3dv(_a0) {(void)(_a0);} -#define glTexCoord3fv(_a0) {(void)(_a0);} -#define glTexCoord3iv(_a0) {(void)(_a0);} -#define glTexCoord3sv(_a0) {(void)(_a0);} -#define glTexCoord4dv(_a0) {(void)(_a0);} -#define glTexCoord4fv(_a0) {(void)(_a0);} -#define glTexCoord4iv(_a0) {(void)(_a0);} -#define glTexCoord4sv(_a0) {(void)(_a0);} -#define glRasterPos2d(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRasterPos2f(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRasterPos2i(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRasterPos2s(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRasterPos3d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glRasterPos3f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glRasterPos3i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glRasterPos3s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glRasterPos4d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRasterPos4f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRasterPos4i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRasterPos4s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRasterPos2dv(_a0) {(void)(_a0);} -#define glRasterPos2fv(_a0) {(void)(_a0);} -#define glRasterPos2iv(_a0) {(void)(_a0);} -#define glRasterPos2sv(_a0) {(void)(_a0);} -#define glRasterPos3dv(_a0) {(void)(_a0);} -#define glRasterPos3fv(_a0) {(void)(_a0);} -#define glRasterPos3iv(_a0) {(void)(_a0);} -#define glRasterPos3sv(_a0) {(void)(_a0);} -#define glRasterPos4dv(_a0) {(void)(_a0);} -#define glRasterPos4fv(_a0) {(void)(_a0);} -#define glRasterPos4iv(_a0) {(void)(_a0);} -#define glRasterPos4sv(_a0) {(void)(_a0);} -#define glRectd(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRectf(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRecti(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRects(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glRectdv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRectfv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRectiv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glRectsv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glVertexPointer(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glNormalPointer(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColorPointer(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glIndexPointer(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexCoordPointer(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glEdgeFlagPointer(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glGetPointerv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glArrayElement(_a0) {(void)(_a0);} -#define glDrawArrays(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glDrawElements(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glInterleavedArrays(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glShadeModel(_a0) {(void)(_a0);} -#define glLightf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glLighti(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glLightfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glLightiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetLightfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetLightiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glLightModelf(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glLightModeli(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glLightModelfv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glLightModeliv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMaterialf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMateriali(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMaterialfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMaterialiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetMaterialfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetMaterialiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColorMaterial(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPixelZoom(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPixelStoref(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPixelStorei(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPixelTransferf(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPixelTransferi(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPixelMapfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glPixelMapuiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glPixelMapusv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetPixelMapfv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glGetPixelMapuiv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glGetPixelMapusv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glBitmap(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glReadPixels(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glDrawPixels(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glCopyPixels(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glStencilFunc(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glStencilMask(_a0) {(void)(_a0);} -#define glStencilOp(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glClearStencil(_a0) {(void)(_a0);} -#define glTexGend(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexGenf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexGeni(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexGendv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexGenfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexGeniv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexGendv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexGenfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexGeniv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexEnvf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexEnvi(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexEnvfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexEnviv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexEnvfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexEnviv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexParameterf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexParameteri(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetTexLevelParameterfv(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glGetTexLevelParameteriv(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glTexImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} -#define glTexImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} -#define glGetTexImage(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glGenTextures(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glDeleteTextures(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glBindTexture(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glPrioritizeTextures(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glTexSubImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glTexSubImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} -#define glCopyTexImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glCopyTexImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} -#define glCopyTexSubImage1D(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glCopyTexSubImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} -#define glMap1d(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glMap1f(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glMap2d(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);} -#define glMap2f(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);} -#define glGetMapdv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetMapfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetMapiv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glEvalCoord1d(_a0) {(void)(_a0);} -#define glEvalCoord1f(_a0) {(void)(_a0);} -#define glEvalCoord1dv(_a0) {(void)(_a0);} -#define glEvalCoord1fv(_a0) {(void)(_a0);} -#define glEvalCoord2d(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glEvalCoord2f(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glEvalCoord2dv(_a0) {(void)(_a0);} -#define glEvalCoord2fv(_a0) {(void)(_a0);} -#define glMapGrid1d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMapGrid1f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMapGrid2d(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glMapGrid2f(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glEvalPoint1(_a0) {(void)(_a0);} -#define glEvalPoint2(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glEvalMesh1(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glEvalMesh2(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glFogf(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glFogi(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glFogfv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glFogiv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glFeedbackBuffer(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glPassThrough(_a0) {(void)(_a0);} -#define glSelectBuffer(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glInitNames() {} -#define glLoadName(_a0) {(void)(_a0);} -#define glPushName(_a0) {(void)(_a0);} -#define glPopName() {} -#define glDrawRangeElements(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glTexImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);} -#define glTexSubImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9,_a10) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);(void)(_a10);} -#define glCopyTexSubImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} -#define glColorTable(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glColorSubTable(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glColorTableParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glColorTableParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glCopyColorSubTable(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glCopyColorTable(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glGetColorTable(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glGetColorTableParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetColorTableParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glBlendEquation(_a0) {(void)(_a0);} -#define glBlendColor(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glHistogram(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glResetHistogram(_a0) {(void)(_a0);} -#define glGetHistogram(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glGetHistogramParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetHistogramParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMinmax(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glResetMinmax(_a0) {(void)(_a0);} -#define glGetMinmax(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glGetMinmaxParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetMinmaxParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glConvolutionFilter1D(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glConvolutionFilter2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glConvolutionParameterf(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glConvolutionParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glConvolutionParameteri(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glConvolutionParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glCopyConvolutionFilter1D(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glCopyConvolutionFilter2D(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glGetConvolutionFilter(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glGetConvolutionParameterfv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glGetConvolutionParameteriv(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glSeparableFilter2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} -#define glGetSeparableFilter(_a0,_a1,_a2,_a3,_a4,_a5) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);} -#define glActiveTexture(_a0) {(void)(_a0);} -#define glClientActiveTexture(_a0) {(void)(_a0);} -#define glCompressedTexImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glCompressedTexImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);} -#define glCompressedTexImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} -#define glCompressedTexSubImage1D(_a0,_a1,_a2,_a3,_a4,_a5,_a6) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);} -#define glCompressedTexSubImage2D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);} -#define glCompressedTexSubImage3D(_a0,_a1,_a2,_a3,_a4,_a5,_a6,_a7,_a8,_a9,_a10) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);(void)(_a5);(void)(_a6);(void)(_a7);(void)(_a8);(void)(_a9);(void)(_a10);} -#define glGetCompressedTexImage(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord1d(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1dv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1f(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1fv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1i(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1iv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1s(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1sv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2d(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2dv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2f(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2fv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2i(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2iv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2s(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2sv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3d(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3dv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3f(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3fv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3i(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3iv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3s(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3sv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4d(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4dv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4f(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4fv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4i(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4iv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4s(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4sv(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glLoadTransposeMatrixd(_a0) {(void)(_a0);} -#define glLoadTransposeMatrixf(_a0) {(void)(_a0);} -#define glMultTransposeMatrixd(_a0) {(void)(_a0);} -#define glMultTransposeMatrixf(_a0) {(void)(_a0);} -#define glSampleCoverage(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glActiveTextureARB(_a0) {(void)(_a0);} -#define glClientActiveTextureARB(_a0) {(void)(_a0);} -#define glMultiTexCoord1dARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1fARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1iARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1sARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord1svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2dARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2fARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2iARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord2sARB(_a0,_a1,_a2) {(void)(_a0);(void)(_a1);(void)(_a2);} -#define glMultiTexCoord2svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3dARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3fARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3iARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord3sARB(_a0,_a1,_a2,_a3) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);} -#define glMultiTexCoord3svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4dARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4dvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4fARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4fvARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4iARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4ivARB(_a0,_a1) {(void)(_a0);(void)(_a1);} -#define glMultiTexCoord4sARB(_a0,_a1,_a2,_a3,_a4) {(void)(_a0);(void)(_a1);(void)(_a2);(void)(_a3);(void)(_a4);} -#define glMultiTexCoord4svARB(_a0,_a1) {(void)(_a0);(void)(_a1);} diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/gl.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/gl.h deleted file mode 100644 index ee588a60..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/gl.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __EGL_H -#define __EGL_H - -// include types and defines - -#include - -// include log tokens - -#include - -// include simple void functions we ignore - -#include - -// include functions that need a bit of work, but we don't log - -#include - -// include functions we log - -#ifdef EGL_LOG_PTR - -extern unsigned int *EGL_LOG_PTR; - -inline void xGLL(int a) { *EGL_LOG_PTR=(unsigned int)a; EGL_LOG_PTR++; }; -inline void xGLL(unsigned int a) { *EGL_LOG_PTR=a; EGL_LOG_PTR++; }; -inline void xGLL(float a) { *(float *)EGL_LOG_PTR=a; EGL_LOG_PTR++; }; -inline void xGLL(double a) { *(float *)EGL_LOG_PTR=(float)a; EGL_LOG_PTR++; }; -inline void xGLL(const float *a) { for(int t=0;t!=16;t++) xGLL(a[t]); }; -inline void xGLL(const double *a) { for(int t=0;t!=16;t++) xGLL(a[t]); }; -#else - -inline void xGLL(int a) {}; -inline void xGLL(unsigned int a) {}; -inline void xGLL(float a) {}; -inline void xGLL(double a) {}; -inline void xGLL(const float *a) {}; -inline void xGLL(const double *a) {}; - -#endif - -// functions we might log - -#include - -#endif diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glu.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glu.h deleted file mode 100644 index 95a40b2c..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glu.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef EMPTY_GLU -#define EMPTY_GLU - -inline void gluOrtho2D( int a,int b, int c ,int d ) { } ; -inline void gluLookAt( - GLfloat a,GLfloat b, GLfloat c, - GLfloat d,GLfloat e, GLfloat f, - GLfloat g,GLfloat h, GLfloat i ) { }; - -#define GLU_FILL 1 -#define GLU_SMOOTH 2 - -typedef int GLUquadric; -typedef GLUquadric GLUquadricObj; - -inline GLUquadric *gluNewQuadric() { return (GLUquadric *)1; }; -inline void gluQuadricDrawStyle( GLUquadric *o, int mode) {}; -inline void gluQuadricNormals( GLUquadric *o, int mode) {}; -inline void gluDeleteQuadric( GLUquadric *q) {}; -inline void gluDisk (GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops) {}; -inline void gluCylinder (GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks) {}; -inline int gluBuild2DMipmaps (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, const void *data) { return 0;} -#endif diff --git a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glut.h b/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glut.h deleted file mode 100644 index 9007ecda..00000000 --- a/Code/Physics/Bullet Source/Glut/EmptyGL/GL/glut.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef EMPTY_GLUT_H -#define EMPTY_GLUT_H - -#include -#include - - -#define GLUT_KEY_F1 0 -#define GLUT_KEY_F2 1 -#define GLUT_KEY_END 2 -#define GLUT_KEY_LEFT 3 -#define GLUT_KEY_RIGHT 4 -#define GLUT_KEY_UP 5 -#define GLUT_KEY_DOWN 6 -#define GLUT_KEY_PAGE_UP 7 -#define GLUT_KEY_PAGE_DOWN 8 -#define GLUT_KEY_HOME 9 -#define GLUT_KEY_F3 10 -#define GLUT_KEY_F4 11 -#define GLUT_KEY_F5 12 -#define GLUT_ACTIVE_SHIFT 13 - - -#define GLUT_DOUBLE 1 -#define GLUT_RGBA 2 -#define GLUT_DEPTH 4 -#define GLUT_STENCIL 8 -#define GLUT_WINDOW_WIDTH 16 -#define GLUT_WINDOW_HEIGHT 32 -#define GLUT_RGB 64 - - - - -inline void glutSwapBuffers() {} -inline void glutShowWindow() {} -inline void glutPostRedisplay() {} -inline void glutInit(int *argc, char **argv) {} -inline void glutInitDisplayMode( unsigned int ) {} -inline void glutInitWindowPosition(int x, int y) {} -inline void glutInitWindowSize(int x, int y) {} -inline int glutCreateWindow( const char *str) {return 0;} -inline void glutKeyboardFunc( void (*func)(unsigned char, int ,int ) ) {} -inline void glutSpecialFunc( void (*func)(int key, int x,int y) ) {} -inline void glutSpecialUpFunc( void (*func)(int key, int x,int y) ) {} -inline void glutReshapeFunc( void (*func)(int w,int h) ) {} -inline void glutDisplayFunc( void (*func)() ) {} -inline void glutIdleFunc( void (*func)() ) {} -inline void glutMotionFunc( void (*func)(int x,int y) ) {} -inline void glutMouseFunc( void (*func)(int button,int state,int x,int y) ) {} -inline void glutMainLoop() {} -inline void glutSetWindow(int bla) {} - -inline void glutSolidCube(GLfloat ) {} -inline void glutSolidSphere(GLfloat , int a , int b) {} -inline void glutSolidCone(GLfloat ,GLfloat , int a , int b) {} -inline int glutGetModifiers() { return 0;} -inline void gluPerspective(float a,float b,float c,float d) {} -inline float glutGet(int code) { return 0.f;} -#endif diff --git a/Code/Physics/Bullet Source/Glut/GL/glew.h b/Code/Physics/Bullet Source/Glut/GL/glew.h deleted file mode 100644 index f70103d1..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/glew.h +++ /dev/null @@ -1,15507 +0,0 @@ -/* -** The OpenGL Extension Wrangler Library -** Copyright (C) 2002-2008, Milan Ikits -** Copyright (C) 2002-2008, Marcelo E. Magallon -** Copyright (C) 2002, Lev Povalahev -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** * The name of the author may be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -** THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - * Mesa 3-D graphics library - * Version: 7.0 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* -** Copyright (c) 2007 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -#ifndef __glew_h__ -#define __glew_h__ -#define __GLEW_H__ - -#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H) -#error gl.h included before glew.h -#endif -#if defined(__glext_h_) || defined(__GLEXT_H_) -#error glext.h included before glew.h -#endif -#if defined(__gl_ATI_h_) -#error glATI.h included before glew.h -#endif - -#define __gl_h_ -#define __GL_H__ -#define __X_GL_H -#define __glext_h_ -#define __GLEXT_H_ -#define __gl_ATI_h_ - -#if defined(_WIN32) - -/* - * GLEW does not include to avoid name space pollution. - * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t - * defined properly. - */ -/* */ -#ifndef APIENTRY -#define GLEW_APIENTRY_DEFINED -# if defined(__MINGW32__) || defined(__CYGWIN__) -# define APIENTRY __stdcall -# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) -# define APIENTRY __stdcall -# else -# define APIENTRY -# endif -#endif -#ifndef GLAPI -# if defined(__MINGW32__) || defined(__CYGWIN__) -# define GLAPI extern -# endif -#endif -/* */ -#ifndef CALLBACK -#define GLEW_CALLBACK_DEFINED -# if defined(__MINGW32__) || defined(__CYGWIN__) -# define CALLBACK __attribute__ ((__stdcall__)) -# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) -# define CALLBACK __stdcall -# else -# define CALLBACK -# endif -#endif -/* and */ -#ifndef WINGDIAPI -#define GLEW_WINGDIAPI_DEFINED -#define WINGDIAPI __declspec(dllimport) -#endif -/* */ -#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED) -typedef unsigned short wchar_t; -# define _WCHAR_T_DEFINED -#endif -/* */ -#if !defined(_W64) -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif -#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) && !defined(__MINGW64__) -# ifdef _WIN64 -typedef __int64 ptrdiff_t; -# else -typedef _W64 int ptrdiff_t; -# endif -# define _PTRDIFF_T_DEFINED -# define _PTRDIFF_T_ -#endif - -#ifndef GLAPI -# if defined(__MINGW32__) || defined(__CYGWIN__) -# define GLAPI extern -# else -# define GLAPI WINGDIAPI -# endif -#endif - -#ifndef GLAPIENTRY -#define GLAPIENTRY APIENTRY -#endif - -/* - * GLEW_STATIC is defined for static library. - * GLEW_BUILD is defined for building the DLL library. - */ - -#ifdef GLEW_STATIC -# define GLEWAPI extern -#else -# ifdef GLEW_BUILD -# define GLEWAPI extern __declspec(dllexport) -# else -# define GLEWAPI extern __declspec(dllimport) -# endif -#endif - -#else /* _UNIX */ - -/* - * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO - * C. On my system, this amounts to _3 lines_ of included code, all of - * them pretty much harmless. If you know of a way of detecting 32 vs - * 64 _targets_ at compile time you are free to replace this with - * something that's portable. For now, _this_ is the portable solution. - * (mem, 2004-01-04) - */ - -#include - -/* SGI MIPSPro doesn't like stdint.h in C++ mode */ - -#if defined(__sgi) && !defined(__GNUC__) -#include -#else -#include -#endif - -#define GLEW_APIENTRY_DEFINED -#define APIENTRY - -/* - * GLEW_STATIC is defined for static library. - */ - -#ifdef GLEW_STATIC -# define GLEWAPI extern -#else -# if defined(__GNUC__) && __GNUC__>=4 -# define GLEWAPI extern __attribute__ ((visibility("default"))) -# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) -# define GLEWAPI extern __global -# else -# define GLEWAPI extern -# endif -#endif - -/* */ -#ifndef GLAPI -#define GLAPI extern -#endif -#ifndef GLAPIENTRY -#define GLAPIENTRY -#endif - -#endif /* _WIN32 */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* ----------------------------- GL_VERSION_1_1 ---------------------------- */ - -#ifndef GL_VERSION_1_1 -#define GL_VERSION_1_1 1 - -typedef unsigned int GLenum; -typedef unsigned int GLbitfield; -typedef unsigned int GLuint; -typedef int GLint; -typedef int GLsizei; -typedef unsigned char GLboolean; -typedef signed char GLbyte; -typedef short GLshort; -typedef unsigned char GLubyte; -typedef unsigned short GLushort; -typedef unsigned long GLulong; -typedef float GLfloat; -typedef float GLclampf; -typedef double GLdouble; -typedef double GLclampd; -typedef void GLvoid; -#if defined(_MSC_VER) && _MSC_VER < 1400 -typedef __int64 GLint64EXT; -typedef unsigned __int64 GLuint64EXT; -#elif defined(_MSC_VER) || defined(__BORLANDC__) -typedef signed long long GLint64EXT; -typedef unsigned long long GLuint64EXT; -#else -# if defined(__MINGW32__) || defined(__CYGWIN__) -#include -# endif -typedef int64_t GLint64EXT; -typedef uint64_t GLuint64EXT; -#endif -typedef GLint64EXT GLint64; -typedef GLuint64EXT GLuint64; -typedef struct __GLsync *GLsync; - -typedef char GLchar; - -#define GL_ZERO 0 -#define GL_FALSE 0 -#define GL_LOGIC_OP 0x0BF1 -#define GL_NONE 0 -#define GL_TEXTURE_COMPONENTS 0x1003 -#define GL_NO_ERROR 0 -#define GL_POINTS 0x0000 -#define GL_CURRENT_BIT 0x00000001 -#define GL_TRUE 1 -#define GL_ONE 1 -#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_POINT_BIT 0x00000002 -#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 -#define GL_LINE_STRIP 0x0003 -#define GL_LINE_BIT 0x00000004 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_QUADS 0x0007 -#define GL_QUAD_STRIP 0x0008 -#define GL_POLYGON_BIT 0x00000008 -#define GL_POLYGON 0x0009 -#define GL_POLYGON_STIPPLE_BIT 0x00000010 -#define GL_PIXEL_MODE_BIT 0x00000020 -#define GL_LIGHTING_BIT 0x00000040 -#define GL_FOG_BIT 0x00000080 -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_ACCUM 0x0100 -#define GL_LOAD 0x0101 -#define GL_RETURN 0x0102 -#define GL_MULT 0x0103 -#define GL_ADD 0x0104 -#define GL_NEVER 0x0200 -#define GL_ACCUM_BUFFER_BIT 0x00000200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_FRONT_LEFT 0x0400 -#define GL_FRONT_RIGHT 0x0401 -#define GL_BACK_LEFT 0x0402 -#define GL_BACK_RIGHT 0x0403 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_LEFT 0x0406 -#define GL_RIGHT 0x0407 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_AUX0 0x0409 -#define GL_AUX1 0x040A -#define GL_AUX2 0x040B -#define GL_AUX3 0x040C -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_2D 0x0600 -#define GL_3D 0x0601 -#define GL_3D_COLOR 0x0602 -#define GL_3D_COLOR_TEXTURE 0x0603 -#define GL_4D_COLOR_TEXTURE 0x0604 -#define GL_PASS_THROUGH_TOKEN 0x0700 -#define GL_POINT_TOKEN 0x0701 -#define GL_LINE_TOKEN 0x0702 -#define GL_POLYGON_TOKEN 0x0703 -#define GL_BITMAP_TOKEN 0x0704 -#define GL_DRAW_PIXEL_TOKEN 0x0705 -#define GL_COPY_PIXEL_TOKEN 0x0706 -#define GL_LINE_RESET_TOKEN 0x0707 -#define GL_EXP 0x0800 -#define GL_VIEWPORT_BIT 0x00000800 -#define GL_EXP2 0x0801 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_COEFF 0x0A00 -#define GL_ORDER 0x0A01 -#define GL_DOMAIN 0x0A02 -#define GL_CURRENT_COLOR 0x0B00 -#define GL_CURRENT_INDEX 0x0B01 -#define GL_CURRENT_NORMAL 0x0B02 -#define GL_CURRENT_TEXTURE_COORDS 0x0B03 -#define GL_CURRENT_RASTER_COLOR 0x0B04 -#define GL_CURRENT_RASTER_INDEX 0x0B05 -#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 -#define GL_CURRENT_RASTER_POSITION 0x0B07 -#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 -#define GL_CURRENT_RASTER_DISTANCE 0x0B09 -#define GL_POINT_SMOOTH 0x0B10 -#define GL_POINT_SIZE 0x0B11 -#define GL_POINT_SIZE_RANGE 0x0B12 -#define GL_POINT_SIZE_GRANULARITY 0x0B13 -#define GL_LINE_SMOOTH 0x0B20 -#define GL_LINE_WIDTH 0x0B21 -#define GL_LINE_WIDTH_RANGE 0x0B22 -#define GL_LINE_WIDTH_GRANULARITY 0x0B23 -#define GL_LINE_STIPPLE 0x0B24 -#define GL_LINE_STIPPLE_PATTERN 0x0B25 -#define GL_LINE_STIPPLE_REPEAT 0x0B26 -#define GL_LIST_MODE 0x0B30 -#define GL_MAX_LIST_NESTING 0x0B31 -#define GL_LIST_BASE 0x0B32 -#define GL_LIST_INDEX 0x0B33 -#define GL_POLYGON_MODE 0x0B40 -#define GL_POLYGON_SMOOTH 0x0B41 -#define GL_POLYGON_STIPPLE 0x0B42 -#define GL_EDGE_FLAG 0x0B43 -#define GL_CULL_FACE 0x0B44 -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_LIGHTING 0x0B50 -#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 -#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 -#define GL_LIGHT_MODEL_AMBIENT 0x0B53 -#define GL_SHADE_MODEL 0x0B54 -#define GL_COLOR_MATERIAL_FACE 0x0B55 -#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 -#define GL_COLOR_MATERIAL 0x0B57 -#define GL_FOG 0x0B60 -#define GL_FOG_INDEX 0x0B61 -#define GL_FOG_DENSITY 0x0B62 -#define GL_FOG_START 0x0B63 -#define GL_FOG_END 0x0B64 -#define GL_FOG_MODE 0x0B65 -#define GL_FOG_COLOR 0x0B66 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_TEST 0x0B71 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_ACCUM_CLEAR_VALUE 0x0B80 -#define GL_STENCIL_TEST 0x0B90 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_MATRIX_MODE 0x0BA0 -#define GL_NORMALIZE 0x0BA1 -#define GL_VIEWPORT 0x0BA2 -#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 -#define GL_PROJECTION_STACK_DEPTH 0x0BA4 -#define GL_TEXTURE_STACK_DEPTH 0x0BA5 -#define GL_MODELVIEW_MATRIX 0x0BA6 -#define GL_PROJECTION_MATRIX 0x0BA7 -#define GL_TEXTURE_MATRIX 0x0BA8 -#define GL_ATTRIB_STACK_DEPTH 0x0BB0 -#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 -#define GL_ALPHA_TEST 0x0BC0 -#define GL_ALPHA_TEST_FUNC 0x0BC1 -#define GL_ALPHA_TEST_REF 0x0BC2 -#define GL_DITHER 0x0BD0 -#define GL_BLEND_DST 0x0BE0 -#define GL_BLEND_SRC 0x0BE1 -#define GL_BLEND 0x0BE2 -#define GL_LOGIC_OP_MODE 0x0BF0 -#define GL_INDEX_LOGIC_OP 0x0BF1 -#define GL_COLOR_LOGIC_OP 0x0BF2 -#define GL_AUX_BUFFERS 0x0C00 -#define GL_DRAW_BUFFER 0x0C01 -#define GL_READ_BUFFER 0x0C02 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_INDEX_CLEAR_VALUE 0x0C20 -#define GL_INDEX_WRITEMASK 0x0C21 -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_INDEX_MODE 0x0C30 -#define GL_RGBA_MODE 0x0C31 -#define GL_DOUBLEBUFFER 0x0C32 -#define GL_STEREO 0x0C33 -#define GL_RENDER_MODE 0x0C40 -#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 -#define GL_POINT_SMOOTH_HINT 0x0C51 -#define GL_LINE_SMOOTH_HINT 0x0C52 -#define GL_POLYGON_SMOOTH_HINT 0x0C53 -#define GL_FOG_HINT 0x0C54 -#define GL_TEXTURE_GEN_S 0x0C60 -#define GL_TEXTURE_GEN_T 0x0C61 -#define GL_TEXTURE_GEN_R 0x0C62 -#define GL_TEXTURE_GEN_Q 0x0C63 -#define GL_PIXEL_MAP_I_TO_I 0x0C70 -#define GL_PIXEL_MAP_S_TO_S 0x0C71 -#define GL_PIXEL_MAP_I_TO_R 0x0C72 -#define GL_PIXEL_MAP_I_TO_G 0x0C73 -#define GL_PIXEL_MAP_I_TO_B 0x0C74 -#define GL_PIXEL_MAP_I_TO_A 0x0C75 -#define GL_PIXEL_MAP_R_TO_R 0x0C76 -#define GL_PIXEL_MAP_G_TO_G 0x0C77 -#define GL_PIXEL_MAP_B_TO_B 0x0C78 -#define GL_PIXEL_MAP_A_TO_A 0x0C79 -#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 -#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 -#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 -#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 -#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 -#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 -#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 -#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 -#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 -#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 -#define GL_UNPACK_SWAP_BYTES 0x0CF0 -#define GL_UNPACK_LSB_FIRST 0x0CF1 -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_SWAP_BYTES 0x0D00 -#define GL_PACK_LSB_FIRST 0x0D01 -#define GL_PACK_ROW_LENGTH 0x0D02 -#define GL_PACK_SKIP_ROWS 0x0D03 -#define GL_PACK_SKIP_PIXELS 0x0D04 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_MAP_COLOR 0x0D10 -#define GL_MAP_STENCIL 0x0D11 -#define GL_INDEX_SHIFT 0x0D12 -#define GL_INDEX_OFFSET 0x0D13 -#define GL_RED_SCALE 0x0D14 -#define GL_RED_BIAS 0x0D15 -#define GL_ZOOM_X 0x0D16 -#define GL_ZOOM_Y 0x0D17 -#define GL_GREEN_SCALE 0x0D18 -#define GL_GREEN_BIAS 0x0D19 -#define GL_BLUE_SCALE 0x0D1A -#define GL_BLUE_BIAS 0x0D1B -#define GL_ALPHA_SCALE 0x0D1C -#define GL_ALPHA_BIAS 0x0D1D -#define GL_DEPTH_SCALE 0x0D1E -#define GL_DEPTH_BIAS 0x0D1F -#define GL_MAX_EVAL_ORDER 0x0D30 -#define GL_MAX_LIGHTS 0x0D31 -#define GL_MAX_CLIP_PLANES 0x0D32 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 -#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 -#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 -#define GL_MAX_NAME_STACK_DEPTH 0x0D37 -#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 -#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_INDEX_BITS 0x0D51 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_ACCUM_RED_BITS 0x0D58 -#define GL_ACCUM_GREEN_BITS 0x0D59 -#define GL_ACCUM_BLUE_BITS 0x0D5A -#define GL_ACCUM_ALPHA_BITS 0x0D5B -#define GL_NAME_STACK_DEPTH 0x0D70 -#define GL_AUTO_NORMAL 0x0D80 -#define GL_MAP1_COLOR_4 0x0D90 -#define GL_MAP1_INDEX 0x0D91 -#define GL_MAP1_NORMAL 0x0D92 -#define GL_MAP1_TEXTURE_COORD_1 0x0D93 -#define GL_MAP1_TEXTURE_COORD_2 0x0D94 -#define GL_MAP1_TEXTURE_COORD_3 0x0D95 -#define GL_MAP1_TEXTURE_COORD_4 0x0D96 -#define GL_MAP1_VERTEX_3 0x0D97 -#define GL_MAP1_VERTEX_4 0x0D98 -#define GL_MAP2_COLOR_4 0x0DB0 -#define GL_MAP2_INDEX 0x0DB1 -#define GL_MAP2_NORMAL 0x0DB2 -#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 -#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 -#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 -#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 -#define GL_MAP2_VERTEX_3 0x0DB7 -#define GL_MAP2_VERTEX_4 0x0DB8 -#define GL_MAP1_GRID_DOMAIN 0x0DD0 -#define GL_MAP1_GRID_SEGMENTS 0x0DD1 -#define GL_MAP2_GRID_DOMAIN 0x0DD2 -#define GL_MAP2_GRID_SEGMENTS 0x0DD3 -#define GL_TEXTURE_1D 0x0DE0 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 -#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 -#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 -#define GL_SELECTION_BUFFER_POINTER 0x0DF3 -#define GL_SELECTION_BUFFER_SIZE 0x0DF4 -#define GL_TEXTURE_WIDTH 0x1000 -#define GL_TRANSFORM_BIT 0x00001000 -#define GL_TEXTURE_HEIGHT 0x1001 -#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 -#define GL_TEXTURE_BORDER_COLOR 0x1004 -#define GL_TEXTURE_BORDER 0x1005 -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_AMBIENT 0x1200 -#define GL_DIFFUSE 0x1201 -#define GL_SPECULAR 0x1202 -#define GL_POSITION 0x1203 -#define GL_SPOT_DIRECTION 0x1204 -#define GL_SPOT_EXPONENT 0x1205 -#define GL_SPOT_CUTOFF 0x1206 -#define GL_CONSTANT_ATTENUATION 0x1207 -#define GL_LINEAR_ATTENUATION 0x1208 -#define GL_QUADRATIC_ATTENUATION 0x1209 -#define GL_COMPILE 0x1300 -#define GL_COMPILE_AND_EXECUTE 0x1301 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_2_BYTES 0x1407 -#define GL_3_BYTES 0x1408 -#define GL_4_BYTES 0x1409 -#define GL_DOUBLE 0x140A -#define GL_CLEAR 0x1500 -#define GL_AND 0x1501 -#define GL_AND_REVERSE 0x1502 -#define GL_COPY 0x1503 -#define GL_AND_INVERTED 0x1504 -#define GL_NOOP 0x1505 -#define GL_XOR 0x1506 -#define GL_OR 0x1507 -#define GL_NOR 0x1508 -#define GL_EQUIV 0x1509 -#define GL_INVERT 0x150A -#define GL_OR_REVERSE 0x150B -#define GL_COPY_INVERTED 0x150C -#define GL_OR_INVERTED 0x150D -#define GL_NAND 0x150E -#define GL_SET 0x150F -#define GL_EMISSION 0x1600 -#define GL_SHININESS 0x1601 -#define GL_AMBIENT_AND_DIFFUSE 0x1602 -#define GL_COLOR_INDEXES 0x1603 -#define GL_MODELVIEW 0x1700 -#define GL_PROJECTION 0x1701 -#define GL_TEXTURE 0x1702 -#define GL_COLOR 0x1800 -#define GL_DEPTH 0x1801 -#define GL_STENCIL 0x1802 -#define GL_COLOR_INDEX 0x1900 -#define GL_STENCIL_INDEX 0x1901 -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_RED 0x1903 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A -#define GL_BITMAP 0x1A00 -#define GL_POINT 0x1B00 -#define GL_LINE 0x1B01 -#define GL_FILL 0x1B02 -#define GL_RENDER 0x1C00 -#define GL_FEEDBACK 0x1C01 -#define GL_SELECT 0x1C02 -#define GL_FLAT 0x1D00 -#define GL_SMOOTH 0x1D01 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_S 0x2000 -#define GL_ENABLE_BIT 0x00002000 -#define GL_T 0x2001 -#define GL_R 0x2002 -#define GL_Q 0x2003 -#define GL_MODULATE 0x2100 -#define GL_DECAL 0x2101 -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_TEXTURE_ENV_COLOR 0x2201 -#define GL_TEXTURE_ENV 0x2300 -#define GL_EYE_LINEAR 0x2400 -#define GL_OBJECT_LINEAR 0x2401 -#define GL_SPHERE_MAP 0x2402 -#define GL_TEXTURE_GEN_MODE 0x2500 -#define GL_OBJECT_PLANE 0x2501 -#define GL_EYE_PLANE 0x2502 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_CLAMP 0x2900 -#define GL_REPEAT 0x2901 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_POINT 0x2A01 -#define GL_POLYGON_OFFSET_LINE 0x2A02 -#define GL_R3_G3_B2 0x2A10 -#define GL_V2F 0x2A20 -#define GL_V3F 0x2A21 -#define GL_C4UB_V2F 0x2A22 -#define GL_C4UB_V3F 0x2A23 -#define GL_C3F_V3F 0x2A24 -#define GL_N3F_V3F 0x2A25 -#define GL_C4F_N3F_V3F 0x2A26 -#define GL_T2F_V3F 0x2A27 -#define GL_T4F_V4F 0x2A28 -#define GL_T2F_C4UB_V3F 0x2A29 -#define GL_T2F_C3F_V3F 0x2A2A -#define GL_T2F_N3F_V3F 0x2A2B -#define GL_T2F_C4F_N3F_V3F 0x2A2C -#define GL_T4F_C4F_N3F_V4F 0x2A2D -#define GL_CLIP_PLANE0 0x3000 -#define GL_CLIP_PLANE1 0x3001 -#define GL_CLIP_PLANE2 0x3002 -#define GL_CLIP_PLANE3 0x3003 -#define GL_CLIP_PLANE4 0x3004 -#define GL_CLIP_PLANE5 0x3005 -#define GL_LIGHT0 0x4000 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_LIGHT1 0x4001 -#define GL_LIGHT2 0x4002 -#define GL_LIGHT3 0x4003 -#define GL_LIGHT4 0x4004 -#define GL_LIGHT5 0x4005 -#define GL_LIGHT6 0x4006 -#define GL_LIGHT7 0x4007 -#define GL_HINT_BIT 0x00008000 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_ALPHA4 0x803B -#define GL_ALPHA8 0x803C -#define GL_ALPHA12 0x803D -#define GL_ALPHA16 0x803E -#define GL_LUMINANCE4 0x803F -#define GL_LUMINANCE8 0x8040 -#define GL_LUMINANCE12 0x8041 -#define GL_LUMINANCE16 0x8042 -#define GL_LUMINANCE4_ALPHA4 0x8043 -#define GL_LUMINANCE6_ALPHA2 0x8044 -#define GL_LUMINANCE8_ALPHA8 0x8045 -#define GL_LUMINANCE12_ALPHA4 0x8046 -#define GL_LUMINANCE12_ALPHA12 0x8047 -#define GL_LUMINANCE16_ALPHA16 0x8048 -#define GL_INTENSITY 0x8049 -#define GL_INTENSITY4 0x804A -#define GL_INTENSITY8 0x804B -#define GL_INTENSITY12 0x804C -#define GL_INTENSITY16 0x804D -#define GL_RGB4 0x804F -#define GL_RGB5 0x8050 -#define GL_RGB8 0x8051 -#define GL_RGB10 0x8052 -#define GL_RGB12 0x8053 -#define GL_RGB16 0x8054 -#define GL_RGBA2 0x8055 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGBA8 0x8058 -#define GL_RGB10_A2 0x8059 -#define GL_RGBA12 0x805A -#define GL_RGBA16 0x805B -#define GL_TEXTURE_RED_SIZE 0x805C -#define GL_TEXTURE_GREEN_SIZE 0x805D -#define GL_TEXTURE_BLUE_SIZE 0x805E -#define GL_TEXTURE_ALPHA_SIZE 0x805F -#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 -#define GL_TEXTURE_INTENSITY_SIZE 0x8061 -#define GL_PROXY_TEXTURE_1D 0x8063 -#define GL_PROXY_TEXTURE_2D 0x8064 -#define GL_TEXTURE_PRIORITY 0x8066 -#define GL_TEXTURE_RESIDENT 0x8067 -#define GL_TEXTURE_BINDING_1D 0x8068 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_VERTEX_ARRAY 0x8074 -#define GL_NORMAL_ARRAY 0x8075 -#define GL_COLOR_ARRAY 0x8076 -#define GL_INDEX_ARRAY 0x8077 -#define GL_TEXTURE_COORD_ARRAY 0x8078 -#define GL_EDGE_FLAG_ARRAY 0x8079 -#define GL_VERTEX_ARRAY_SIZE 0x807A -#define GL_VERTEX_ARRAY_TYPE 0x807B -#define GL_VERTEX_ARRAY_STRIDE 0x807C -#define GL_NORMAL_ARRAY_TYPE 0x807E -#define GL_NORMAL_ARRAY_STRIDE 0x807F -#define GL_COLOR_ARRAY_SIZE 0x8081 -#define GL_COLOR_ARRAY_TYPE 0x8082 -#define GL_COLOR_ARRAY_STRIDE 0x8083 -#define GL_INDEX_ARRAY_TYPE 0x8085 -#define GL_INDEX_ARRAY_STRIDE 0x8086 -#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 -#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 -#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A -#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C -#define GL_VERTEX_ARRAY_POINTER 0x808E -#define GL_NORMAL_ARRAY_POINTER 0x808F -#define GL_COLOR_ARRAY_POINTER 0x8090 -#define GL_INDEX_ARRAY_POINTER 0x8091 -#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 -#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 -#define GL_COLOR_INDEX1_EXT 0x80E2 -#define GL_COLOR_INDEX2_EXT 0x80E3 -#define GL_COLOR_INDEX4_EXT 0x80E4 -#define GL_COLOR_INDEX8_EXT 0x80E5 -#define GL_COLOR_INDEX12_EXT 0x80E6 -#define GL_COLOR_INDEX16_EXT 0x80E7 -#define GL_EVAL_BIT 0x00010000 -#define GL_LIST_BIT 0x00020000 -#define GL_TEXTURE_BIT 0x00040000 -#define GL_SCISSOR_BIT 0x00080000 -#define GL_ALL_ATTRIB_BITS 0x000fffff -#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff - -GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value); -GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref); -GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences); -GLAPI void GLAPIENTRY glArrayElement (GLint i); -GLAPI void GLAPIENTRY glBegin (GLenum mode); -GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture); -GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); -GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); -GLAPI void GLAPIENTRY glCallList (GLuint list); -GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists); -GLAPI void GLAPIENTRY glClear (GLbitfield mask); -GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -GLAPI void GLAPIENTRY glClearDepth (GLclampd depth); -GLAPI void GLAPIENTRY glClearIndex (GLfloat c); -GLAPI void GLAPIENTRY glClearStencil (GLint s); -GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation); -GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue); -GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v); -GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue); -GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v); -GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue); -GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v); -GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue); -GLAPI void GLAPIENTRY glColor3iv (const GLint *v); -GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue); -GLAPI void GLAPIENTRY glColor3sv (const GLshort *v); -GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue); -GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v); -GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue); -GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v); -GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue); -GLAPI void GLAPIENTRY glColor3usv (const GLushort *v); -GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); -GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v); -GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); -GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v); -GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v); -GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha); -GLAPI void GLAPIENTRY glColor4iv (const GLint *v); -GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha); -GLAPI void GLAPIENTRY glColor4sv (const GLshort *v); -GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v); -GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha); -GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v); -GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha); -GLAPI void GLAPIENTRY glColor4usv (const GLushort *v); -GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode); -GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); -GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); -GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void GLAPIENTRY glCullFace (GLenum mode); -GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range); -GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); -GLAPI void GLAPIENTRY glDepthFunc (GLenum func); -GLAPI void GLAPIENTRY glDepthMask (GLboolean flag); -GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar); -GLAPI void GLAPIENTRY glDisable (GLenum cap); -GLAPI void GLAPIENTRY glDisableClientState (GLenum array); -GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); -GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode); -GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag); -GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); -GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag); -GLAPI void GLAPIENTRY glEnable (GLenum cap); -GLAPI void GLAPIENTRY glEnableClientState (GLenum array); -GLAPI void GLAPIENTRY glEnd (void); -GLAPI void GLAPIENTRY glEndList (void); -GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u); -GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u); -GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u); -GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u); -GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v); -GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u); -GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v); -GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u); -GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2); -GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); -GLAPI void GLAPIENTRY glEvalPoint1 (GLint i); -GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j); -GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer); -GLAPI void GLAPIENTRY glFinish (void); -GLAPI void GLAPIENTRY glFlush (void); -GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param); -GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glFrontFace (GLenum mode); -GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range); -GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures); -GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params); -GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation); -GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params); -GLAPI GLenum GLAPIENTRY glGetError (void); -GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v); -GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v); -GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v); -GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values); -GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values); -GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values); -GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params); -GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask); -GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name); -GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); -GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); -GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode); -GLAPI void GLAPIENTRY glIndexMask (GLuint mask); -GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void GLAPIENTRY glIndexd (GLdouble c); -GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c); -GLAPI void GLAPIENTRY glIndexf (GLfloat c); -GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c); -GLAPI void GLAPIENTRY glIndexi (GLint c); -GLAPI void GLAPIENTRY glIndexiv (const GLint *c); -GLAPI void GLAPIENTRY glIndexs (GLshort c); -GLAPI void GLAPIENTRY glIndexsv (const GLshort *c); -GLAPI void GLAPIENTRY glIndexub (GLubyte c); -GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c); -GLAPI void GLAPIENTRY glInitNames (void); -GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); -GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap); -GLAPI GLboolean GLAPIENTRY glIsList (GLuint list); -GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture); -GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param); -GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param); -GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern); -GLAPI void GLAPIENTRY glLineWidth (GLfloat width); -GLAPI void GLAPIENTRY glListBase (GLuint base); -GLAPI void GLAPIENTRY glLoadIdentity (void); -GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m); -GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m); -GLAPI void GLAPIENTRY glLoadName (GLuint name); -GLAPI void GLAPIENTRY glLogicOp (GLenum opcode); -GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2); -GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2); -GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); -GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); -GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param); -GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glMatrixMode (GLenum mode); -GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m); -GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m); -GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode); -GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz); -GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v); -GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz); -GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v); -GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); -GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v); -GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz); -GLAPI void GLAPIENTRY glNormal3iv (const GLint *v); -GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz); -GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v); -GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -GLAPI void GLAPIENTRY glPassThrough (GLfloat token); -GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values); -GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values); -GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values); -GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param); -GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param); -GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor); -GLAPI void GLAPIENTRY glPointSize (GLfloat size); -GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode); -GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units); -GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask); -GLAPI void GLAPIENTRY glPopAttrib (void); -GLAPI void GLAPIENTRY glPopClientAttrib (void); -GLAPI void GLAPIENTRY glPopMatrix (void); -GLAPI void GLAPIENTRY glPopName (void); -GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities); -GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask); -GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask); -GLAPI void GLAPIENTRY glPushMatrix (void); -GLAPI void GLAPIENTRY glPushName (GLuint name); -GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y); -GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v); -GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y); -GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v); -GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y); -GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v); -GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y); -GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v); -GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z); -GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v); -GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z); -GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v); -GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z); -GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v); -GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z); -GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v); -GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v); -GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v); -GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w); -GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v); -GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v); -GLAPI void GLAPIENTRY glReadBuffer (GLenum mode); -GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); -GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2); -GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); -GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2); -GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2); -GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2); -GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2); -GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2); -GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode); -GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z); -GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); -GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer); -GLAPI void GLAPIENTRY glShadeModel (GLenum mode); -GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); -GLAPI void GLAPIENTRY glStencilMask (GLuint mask); -GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); -GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s); -GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v); -GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s); -GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v); -GLAPI void GLAPIENTRY glTexCoord1i (GLint s); -GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v); -GLAPI void GLAPIENTRY glTexCoord1s (GLshort s); -GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v); -GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t); -GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v); -GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t); -GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v); -GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t); -GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v); -GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t); -GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v); -GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r); -GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v); -GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); -GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v); -GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r); -GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v); -GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r); -GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v); -GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q); -GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v); -GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); -GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v); -GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q); -GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v); -GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); -GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v); -GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); -GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param); -GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params); -GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); -GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); -GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); -GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z); -GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); -GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y); -GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v); -GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y); -GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v); -GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y); -GLAPI void GLAPIENTRY glVertex2iv (const GLint *v); -GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y); -GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v); -GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z); -GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v); -GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z); -GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v); -GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z); -GLAPI void GLAPIENTRY glVertex3iv (const GLint *v); -GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z); -GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v); -GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v); -GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v); -GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w); -GLAPI void GLAPIENTRY glVertex4iv (const GLint *v); -GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v); -GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); - -#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1) - -#endif /* GL_VERSION_1_1 */ - -/* ---------------------------------- GLU ---------------------------------- */ - -#ifndef GLEW_NO_GLU -/* this is where we can safely include GLU */ -# if defined(__APPLE__) && defined(__MACH__) -# include -# else -# include -# endif -#endif - -/* ----------------------------- GL_VERSION_1_2 ---------------------------- */ - -#ifndef GL_VERSION_1_2 -#define GL_VERSION_1_2 1 - -#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 -#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 -#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 -#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 -#define GL_UNSIGNED_BYTE_3_3_2 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_RESCALE_NORMAL 0x803A -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_PACK_SKIP_IMAGES 0x806B -#define GL_PACK_IMAGE_HEIGHT 0x806C -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_PROXY_TEXTURE_3D 0x8070 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 -#define GL_SINGLE_COLOR 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR 0x81FA -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E - -typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); - -#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D) -#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements) -#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D) -#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D) - -#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2) - -#endif /* GL_VERSION_1_2 */ - -/* ---------------------------- GL_VERSION_1_2_1 --------------------------- */ - -#ifndef GL_VERSION_1_2_1 -#define GL_VERSION_1_2_1 1 - -#define GLEW_VERSION_1_2_1 GLEW_GET_VAR(__GLEW_VERSION_1_2_1) - -#endif /* GL_VERSION_1_2_1 */ - -/* ----------------------------- GL_VERSION_1_3 ---------------------------- */ - -#ifndef GL_VERSION_1_3 -#define GL_VERSION_1_3 1 - -#define GL_MULTISAMPLE 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE 0x809F -#define GL_SAMPLE_COVERAGE 0x80A0 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB -#define GL_CLAMP_TO_BORDER 0x812D -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 -#define GL_MAX_TEXTURE_UNITS 0x84E2 -#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 -#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 -#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 -#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 -#define GL_SUBTRACT 0x84E7 -#define GL_COMPRESSED_ALPHA 0x84E9 -#define GL_COMPRESSED_LUMINANCE 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB -#define GL_COMPRESSED_INTENSITY 0x84EC -#define GL_COMPRESSED_RGB 0x84ED -#define GL_COMPRESSED_RGBA 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT 0x84EF -#define GL_NORMAL_MAP 0x8511 -#define GL_REFLECTION_MAP 0x8512 -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C -#define GL_COMBINE 0x8570 -#define GL_COMBINE_RGB 0x8571 -#define GL_COMBINE_ALPHA 0x8572 -#define GL_RGB_SCALE 0x8573 -#define GL_ADD_SIGNED 0x8574 -#define GL_INTERPOLATE 0x8575 -#define GL_CONSTANT 0x8576 -#define GL_PRIMARY_COLOR 0x8577 -#define GL_PREVIOUS 0x8578 -#define GL_SOURCE0_RGB 0x8580 -#define GL_SOURCE1_RGB 0x8581 -#define GL_SOURCE2_RGB 0x8582 -#define GL_SOURCE0_ALPHA 0x8588 -#define GL_SOURCE1_ALPHA 0x8589 -#define GL_SOURCE2_ALPHA 0x858A -#define GL_OPERAND0_RGB 0x8590 -#define GL_OPERAND1_RGB 0x8591 -#define GL_OPERAND2_RGB 0x8592 -#define GL_OPERAND0_ALPHA 0x8598 -#define GL_OPERAND1_ALPHA 0x8599 -#define GL_OPERAND2_ALPHA 0x859A -#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 -#define GL_TEXTURE_COMPRESSED 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_DOT3_RGB 0x86AE -#define GL_DOT3_RGBA 0x86AF -#define GL_MULTISAMPLE_BIT 0x20000000 - -typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); -typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img); -typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); -typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); -typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); -typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); - -#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture) -#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture) -#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D) -#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D) -#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D) -#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D) -#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D) -#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D) -#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage) -#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd) -#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf) -#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd) -#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf) -#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d) -#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv) -#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f) -#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv) -#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i) -#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv) -#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s) -#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv) -#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d) -#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv) -#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f) -#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv) -#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i) -#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv) -#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s) -#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv) -#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d) -#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv) -#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f) -#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv) -#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i) -#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv) -#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s) -#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv) -#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d) -#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv) -#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f) -#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv) -#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i) -#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv) -#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s) -#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv) -#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage) - -#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3) - -#endif /* GL_VERSION_1_3 */ - -/* ----------------------------- GL_VERSION_1_4 ---------------------------- */ - -#ifndef GL_VERSION_1_4 -#define GL_VERSION_1_4 1 - -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_POINT_SIZE_MIN 0x8126 -#define GL_POINT_SIZE_MAX 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 -#define GL_POINT_DISTANCE_ATTENUATION 0x8129 -#define GL_GENERATE_MIPMAP 0x8191 -#define GL_GENERATE_MIPMAP_HINT 0x8192 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_DEPTH_COMPONENT32 0x81A7 -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_FOG_COORDINATE_SOURCE 0x8450 -#define GL_FOG_COORDINATE 0x8451 -#define GL_FRAGMENT_DEPTH 0x8452 -#define GL_CURRENT_FOG_COORDINATE 0x8453 -#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 -#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 -#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 -#define GL_FOG_COORDINATE_ARRAY 0x8457 -#define GL_COLOR_SUM 0x8458 -#define GL_CURRENT_SECONDARY_COLOR 0x8459 -#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A -#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B -#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C -#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D -#define GL_SECONDARY_COLOR_ARRAY 0x845E -#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD -#define GL_TEXTURE_FILTER_CONTROL 0x8500 -#define GL_TEXTURE_LOD_BIAS 0x8501 -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_TEXTURE_DEPTH_SIZE 0x884A -#define GL_DEPTH_TEXTURE_MODE 0x884B -#define GL_TEXTURE_COMPARE_MODE 0x884C -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#define GL_COMPARE_R_TO_TEXTURE 0x884E - -typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); -typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); -typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); -typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p); - -#define glBlendColor GLEW_GET_FUN(__glewBlendColor) -#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation) -#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate) -#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer) -#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd) -#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv) -#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf) -#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv) -#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays) -#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements) -#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf) -#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv) -#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri) -#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv) -#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b) -#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv) -#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d) -#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv) -#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f) -#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv) -#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i) -#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv) -#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s) -#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv) -#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub) -#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv) -#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui) -#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv) -#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us) -#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv) -#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer) -#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d) -#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv) -#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f) -#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv) -#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i) -#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv) -#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s) -#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv) -#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d) -#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv) -#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f) -#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv) -#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i) -#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv) -#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s) -#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv) - -#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4) - -#endif /* GL_VERSION_1_4 */ - -/* ----------------------------- GL_VERSION_1_5 ---------------------------- */ - -#ifndef GL_VERSION_1_5 -#define GL_VERSION_1_5 1 - -#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE -#define GL_FOG_COORD GL_FOG_COORDINATE -#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY -#define GL_SRC0_RGB GL_SOURCE0_RGB -#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER -#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE -#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA -#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE -#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE -#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA -#define GL_SRC1_RGB GL_SOURCE1_RGB -#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING -#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA -#define GL_SRC2_RGB GL_SOURCE2_RGB -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 -#define GL_QUERY_COUNTER_BITS 0x8864 -#define GL_CURRENT_QUERY 0x8865 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 -#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A -#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B -#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C -#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D -#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F -#define GL_READ_ONLY 0x88B8 -#define GL_WRITE_ONLY 0x88B9 -#define GL_READ_WRITE 0x88BA -#define GL_BUFFER_ACCESS 0x88BB -#define GL_BUFFER_MAPPED 0x88BC -#define GL_BUFFER_MAP_POINTER 0x88BD -#define GL_STREAM_DRAW 0x88E0 -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_DRAW 0x88E4 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_SAMPLES_PASSED 0x8914 - -typedef ptrdiff_t GLintptr; -typedef ptrdiff_t GLsizeiptr; - -typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); -typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); -typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); -typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); -typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); -typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); -typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); -typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); -typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); -typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target); - -#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery) -#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer) -#define glBufferData GLEW_GET_FUN(__glewBufferData) -#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData) -#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers) -#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries) -#define glEndQuery GLEW_GET_FUN(__glewEndQuery) -#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) -#define glGenQueries GLEW_GET_FUN(__glewGenQueries) -#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv) -#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv) -#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData) -#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv) -#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv) -#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv) -#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer) -#define glIsQuery GLEW_GET_FUN(__glewIsQuery) -#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer) -#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer) - -#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5) - -#endif /* GL_VERSION_1_5 */ - -/* ----------------------------- GL_VERSION_2_0 ---------------------------- */ - -#ifndef GL_VERSION_2_0 -#define GL_VERSION_2_0 1 - -#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 -#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_DRAW_BUFFER0 0x8825 -#define GL_DRAW_BUFFER1 0x8826 -#define GL_DRAW_BUFFER2 0x8827 -#define GL_DRAW_BUFFER3 0x8828 -#define GL_DRAW_BUFFER4 0x8829 -#define GL_DRAW_BUFFER5 0x882A -#define GL_DRAW_BUFFER6 0x882B -#define GL_DRAW_BUFFER7 0x882C -#define GL_DRAW_BUFFER8 0x882D -#define GL_DRAW_BUFFER9 0x882E -#define GL_DRAW_BUFFER10 0x882F -#define GL_DRAW_BUFFER11 0x8830 -#define GL_DRAW_BUFFER12 0x8831 -#define GL_DRAW_BUFFER13 0x8832 -#define GL_DRAW_BUFFER14 0x8833 -#define GL_DRAW_BUFFER15 0x8834 -#define GL_BLEND_EQUATION_ALPHA 0x883D -#define GL_POINT_SPRITE 0x8861 -#define GL_COORD_REPLACE 0x8862 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_MAX_TEXTURE_COORDS 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A -#define GL_MAX_VARYING_FLOATS 0x8B4B -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_SHADER_TYPE 0x8B4F -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_1D 0x8B5D -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_SAMPLER_1D_SHADOW 0x8B61 -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_DELETE_STATUS 0x8B80 -#define GL_COMPILE_STATUS 0x8B81 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D -#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 -#define GL_LOWER_LEFT 0x8CA1 -#define GL_UPPER_LEFT 0x8CA2 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 - -typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); -typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name); -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum); -typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader); -typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void); -typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type); -typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program); -typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader); -typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); -typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); -typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs); -typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint); -typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); -typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); -typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param); -typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); -typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source); -typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param); -typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); -typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); -typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); -typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); -typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths); -typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); -typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); -typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); -typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0); -typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); -typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); -typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); -typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program); -typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); - -#define glAttachShader GLEW_GET_FUN(__glewAttachShader) -#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) -#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) -#define glCompileShader GLEW_GET_FUN(__glewCompileShader) -#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram) -#define glCreateShader GLEW_GET_FUN(__glewCreateShader) -#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram) -#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader) -#define glDetachShader GLEW_GET_FUN(__glewDetachShader) -#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray) -#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers) -#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray) -#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib) -#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform) -#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders) -#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation) -#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog) -#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv) -#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog) -#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource) -#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv) -#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation) -#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv) -#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv) -#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv) -#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv) -#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv) -#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv) -#define glIsProgram GLEW_GET_FUN(__glewIsProgram) -#define glIsShader GLEW_GET_FUN(__glewIsShader) -#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram) -#define glShaderSource GLEW_GET_FUN(__glewShaderSource) -#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate) -#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate) -#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate) -#define glUniform1f GLEW_GET_FUN(__glewUniform1f) -#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv) -#define glUniform1i GLEW_GET_FUN(__glewUniform1i) -#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv) -#define glUniform2f GLEW_GET_FUN(__glewUniform2f) -#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv) -#define glUniform2i GLEW_GET_FUN(__glewUniform2i) -#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv) -#define glUniform3f GLEW_GET_FUN(__glewUniform3f) -#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv) -#define glUniform3i GLEW_GET_FUN(__glewUniform3i) -#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv) -#define glUniform4f GLEW_GET_FUN(__glewUniform4f) -#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv) -#define glUniform4i GLEW_GET_FUN(__glewUniform4i) -#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv) -#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv) -#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv) -#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv) -#define glUseProgram GLEW_GET_FUN(__glewUseProgram) -#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram) -#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d) -#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv) -#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f) -#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv) -#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s) -#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv) -#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d) -#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv) -#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f) -#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv) -#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s) -#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv) -#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d) -#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv) -#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f) -#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv) -#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s) -#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv) -#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv) -#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv) -#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv) -#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub) -#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv) -#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv) -#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv) -#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv) -#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d) -#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv) -#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f) -#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv) -#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv) -#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s) -#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv) -#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv) -#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) -#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) -#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) - -#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) - -#endif /* GL_VERSION_2_0 */ - -/* ----------------------------- GL_VERSION_2_1 ---------------------------- */ - -#ifndef GL_VERSION_2_1 -#define GL_VERSION_2_1 1 - -#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F -#define GL_PIXEL_PACK_BUFFER 0x88EB -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF -#define GL_FLOAT_MAT2x3 0x8B65 -#define GL_FLOAT_MAT2x4 0x8B66 -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT3x4 0x8B68 -#define GL_FLOAT_MAT4x2 0x8B69 -#define GL_FLOAT_MAT4x3 0x8B6A -#define GL_SRGB 0x8C40 -#define GL_SRGB8 0x8C41 -#define GL_SRGB_ALPHA 0x8C42 -#define GL_SRGB8_ALPHA8 0x8C43 -#define GL_SLUMINANCE_ALPHA 0x8C44 -#define GL_SLUMINANCE8_ALPHA8 0x8C45 -#define GL_SLUMINANCE 0x8C46 -#define GL_SLUMINANCE8 0x8C47 -#define GL_COMPRESSED_SRGB 0x8C48 -#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 -#define GL_COMPRESSED_SLUMINANCE 0x8C4A -#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B - -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - -#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv) -#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv) -#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv) -#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv) -#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv) -#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv) - -#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1) - -#endif /* GL_VERSION_2_1 */ - -/* ----------------------------- GL_VERSION_3_0 ---------------------------- */ - -#ifndef GL_VERSION_3_0 -#define GL_VERSION_3_0 1 - -#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES -#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 -#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 -#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 -#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB -#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 -#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 -#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 -#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS -#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 -#define GL_MAJOR_VERSION 0x821B -#define GL_MINOR_VERSION 0x821C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_CONTEXT_FLAGS 0x821E -#define GL_DEPTH_BUFFER 0x8223 -#define GL_STENCIL_BUFFER 0x8224 -#define GL_COMPRESSED_RED 0x8225 -#define GL_COMPRESSED_RG 0x8226 -#define GL_RGBA32F 0x8814 -#define GL_RGB32F 0x8815 -#define GL_RGBA16F 0x881A -#define GL_RGB16F 0x881B -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD -#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF -#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 -#define GL_CLAMP_VERTEX_COLOR 0x891A -#define GL_CLAMP_FRAGMENT_COLOR 0x891B -#define GL_CLAMP_READ_COLOR 0x891C -#define GL_FIXED_ONLY 0x891D -#define GL_TEXTURE_RED_TYPE 0x8C10 -#define GL_TEXTURE_GREEN_TYPE 0x8C11 -#define GL_TEXTURE_BLUE_TYPE 0x8C12 -#define GL_TEXTURE_ALPHA_TYPE 0x8C13 -#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 -#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 -#define GL_TEXTURE_DEPTH_TYPE 0x8C16 -#define GL_UNSIGNED_NORMALIZED 0x8C17 -#define GL_TEXTURE_1D_ARRAY 0x8C18 -#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 -#define GL_TEXTURE_2D_ARRAY 0x8C1A -#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B -#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C -#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D -#define GL_R11F_G11F_B10F 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B -#define GL_RGB9_E5 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E -#define GL_TEXTURE_SHARED_SIZE 0x8C3F -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 -#define GL_PRIMITIVES_GENERATED 0x8C87 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 -#define GL_RASTERIZER_DISCARD 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B -#define GL_INTERLEAVED_ATTRIBS 0x8C8C -#define GL_SEPARATE_ATTRIBS 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F -#define GL_RGBA32UI 0x8D70 -#define GL_RGB32UI 0x8D71 -#define GL_RGBA16UI 0x8D76 -#define GL_RGB16UI 0x8D77 -#define GL_RGBA8UI 0x8D7C -#define GL_RGB8UI 0x8D7D -#define GL_RGBA32I 0x8D82 -#define GL_RGB32I 0x8D83 -#define GL_RGBA16I 0x8D88 -#define GL_RGB16I 0x8D89 -#define GL_RGBA8I 0x8D8E -#define GL_RGB8I 0x8D8F -#define GL_RED_INTEGER 0x8D94 -#define GL_GREEN_INTEGER 0x8D95 -#define GL_BLUE_INTEGER 0x8D96 -#define GL_ALPHA_INTEGER 0x8D97 -#define GL_RGB_INTEGER 0x8D98 -#define GL_RGBA_INTEGER 0x8D99 -#define GL_BGR_INTEGER 0x8D9A -#define GL_BGRA_INTEGER 0x8D9B -#define GL_SAMPLER_1D_ARRAY 0x8DC0 -#define GL_SAMPLER_2D_ARRAY 0x8DC1 -#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 -#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 -#define GL_UNSIGNED_INT_VEC2 0x8DC6 -#define GL_UNSIGNED_INT_VEC3 0x8DC7 -#define GL_UNSIGNED_INT_VEC4 0x8DC8 -#define GL_INT_SAMPLER_1D 0x8DC9 -#define GL_INT_SAMPLER_2D 0x8DCA -#define GL_INT_SAMPLER_3D 0x8DCB -#define GL_INT_SAMPLER_CUBE 0x8DCC -#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE -#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF -#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 -#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 -#define GL_QUERY_WAIT 0x8E13 -#define GL_QUERY_NO_WAIT 0x8E14 -#define GL_QUERY_BY_REGION_WAIT 0x8E15 -#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 - -typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum); -typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum); -typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*); -typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum); -typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint); -typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*); -typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*); -typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*); -typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); -typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint); -typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint); -typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void); -typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void); -typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*); -typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*); -typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint); -typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*); -typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*); -typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*); -typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint); -typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*); -typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*); -typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum); -typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint); -typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*); -typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*); -typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*); -typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*); - -#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender) -#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback) -#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation) -#define glClampColor GLEW_GET_FUN(__glewClampColor) -#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi) -#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv) -#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv) -#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv) -#define glColorMaski GLEW_GET_FUN(__glewColorMaski) -#define glDisablei GLEW_GET_FUN(__glewDisablei) -#define glEnablei GLEW_GET_FUN(__glewEnablei) -#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender) -#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback) -#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v) -#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation) -#define glGetStringi GLEW_GET_FUN(__glewGetStringi) -#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv) -#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv) -#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying) -#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv) -#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv) -#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv) -#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi) -#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv) -#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv) -#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings) -#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui) -#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv) -#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui) -#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv) -#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui) -#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv) -#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui) -#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv) -#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i) -#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv) -#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui) -#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv) -#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i) -#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv) -#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui) -#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv) -#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i) -#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv) -#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui) -#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv) -#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv) -#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i) -#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv) -#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv) -#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv) -#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui) -#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv) -#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv) -#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer) - -#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0) - -#endif /* GL_VERSION_3_0 */ - -/* ----------------------------- GL_VERSION_3_1 ---------------------------- */ - -#ifndef GL_VERSION_3_1 -#define GL_VERSION_3_1 1 - -#define GL_TEXTURE_RECTANGLE 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 -#define GL_SAMPLER_2D_RECT 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 -#define GL_TEXTURE_BUFFER 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D -#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E -#define GL_SAMPLER_BUFFER 0x8DC2 -#define GL_INT_SAMPLER_2D_RECT 0x8DCD -#define GL_INT_SAMPLER_BUFFER 0x8DD0 -#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 -#define GL_RED_SNORM 0x8F90 -#define GL_RG_SNORM 0x8F91 -#define GL_RGB_SNORM 0x8F92 -#define GL_RGBA_SNORM 0x8F93 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGB8_SNORM 0x8F96 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_R16_SNORM 0x8F98 -#define GL_RG16_SNORM 0x8F99 -#define GL_RGB16_SNORM 0x8F9A -#define GL_RGBA16_SNORM 0x8F9B -#define GL_SIGNED_NORMALIZED 0x8F9C -#define GL_PRIMITIVE_RESTART 0x8F9D -#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E -#define GL_BUFFER_ACCESS_FLAGS 0x911F -#define GL_BUFFER_MAP_LENGTH 0x9120 -#define GL_BUFFER_MAP_OFFSET 0x9121 - -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei); -typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint); -typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint); - -#define glDrawArraysInstanced GLEW_GET_FUN(__glewDrawArraysInstanced) -#define glDrawElementsInstanced GLEW_GET_FUN(__glewDrawElementsInstanced) -#define glPrimitiveRestartIndex GLEW_GET_FUN(__glewPrimitiveRestartIndex) -#define glTexBuffer GLEW_GET_FUN(__glewTexBuffer) - -#define GLEW_VERSION_3_1 GLEW_GET_VAR(__GLEW_VERSION_3_1) - -#endif /* GL_VERSION_3_1 */ - -/* ----------------------------- GL_VERSION_3_2 ---------------------------- */ - -#ifndef GL_VERSION_3_2 -#define GL_VERSION_3_2 1 - -#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 -#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 -#define GL_LINES_ADJACENCY 0x000A -#define GL_LINE_STRIP_ADJACENCY 0x000B -#define GL_TRIANGLES_ADJACENCY 0x000C -#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D -#define GL_PROGRAM_POINT_SIZE 0x8642 -#define GL_GEOMETRY_VERTICES_OUT 0x8916 -#define GL_GEOMETRY_INPUT_TYPE 0x8917 -#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 -#define GL_GEOMETRY_SHADER 0x8DD9 -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 -#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 -#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 -#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 -#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 -#define GL_CONTEXT_PROFILE_MASK 0x9126 - -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum, GLenum, GLint64 *); -typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *); - -#define glFramebufferTexture GLEW_GET_FUN(__glewFramebufferTexture) -#define glGetBufferParameteri64v GLEW_GET_FUN(__glewGetBufferParameteri64v) -#define glGetInteger64i_v GLEW_GET_FUN(__glewGetInteger64i_v) - -#define GLEW_VERSION_3_2 GLEW_GET_VAR(__GLEW_VERSION_3_2) - -#endif /* GL_VERSION_3_2 */ - -/* ----------------------------- GL_VERSION_3_3 ---------------------------- */ - -#ifndef GL_VERSION_3_3 -#define GL_VERSION_3_3 1 - -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE -#define GL_ANY_SAMPLES_PASSED 0x8C2F -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 -#define GL_RGB10_A2UI 0x906F - -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); - -#define glVertexAttribDivisor GLEW_GET_FUN(__glewVertexAttribDivisor) - -#define GLEW_VERSION_3_3 GLEW_GET_VAR(__GLEW_VERSION_3_3) - -#endif /* GL_VERSION_3_3 */ - -/* ----------------------------- GL_VERSION_4_0 ---------------------------- */ - -#ifndef GL_VERSION_4_0 -#define GL_VERSION_4_0 1 - -#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F -#define GL_SAMPLE_SHADING 0x8C36 -#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 -#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C -#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D -#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E -#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F -#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F -#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B -#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F - -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); -typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value); - -#define glBlendEquationSeparatei GLEW_GET_FUN(__glewBlendEquationSeparatei) -#define glBlendEquationi GLEW_GET_FUN(__glewBlendEquationi) -#define glBlendFuncSeparatei GLEW_GET_FUN(__glewBlendFuncSeparatei) -#define glBlendFunci GLEW_GET_FUN(__glewBlendFunci) -#define glMinSampleShading GLEW_GET_FUN(__glewMinSampleShading) - -#define GLEW_VERSION_4_0 GLEW_GET_VAR(__GLEW_VERSION_4_0) - -#endif /* GL_VERSION_4_0 */ - -/* ----------------------------- GL_VERSION_4_1 ---------------------------- */ - -#ifndef GL_VERSION_4_1 -#define GL_VERSION_4_1 1 - -#define GLEW_VERSION_4_1 GLEW_GET_VAR(__GLEW_VERSION_4_1) - -#endif /* GL_VERSION_4_1 */ - -/* -------------------------- GL_3DFX_multisample -------------------------- */ - -#ifndef GL_3DFX_multisample -#define GL_3DFX_multisample 1 - -#define GL_MULTISAMPLE_3DFX 0x86B2 -#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 -#define GL_SAMPLES_3DFX 0x86B4 -#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 - -#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample) - -#endif /* GL_3DFX_multisample */ - -/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */ - -#ifndef GL_3DFX_tbuffer -#define GL_3DFX_tbuffer 1 - -typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); - -#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX) - -#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer) - -#endif /* GL_3DFX_tbuffer */ - -/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */ - -#ifndef GL_3DFX_texture_compression_FXT1 -#define GL_3DFX_texture_compression_FXT1 1 - -#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 -#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 - -#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1) - -#endif /* GL_3DFX_texture_compression_FXT1 */ - -/* ----------------------- GL_AMD_blend_minmax_factor ---------------------- */ - -#ifndef GL_AMD_blend_minmax_factor -#define GL_AMD_blend_minmax_factor 1 - -#define GL_FACTOR_MIN_AMD 0x901C -#define GL_FACTOR_MAX_AMD 0x901D - -#define GLEW_AMD_blend_minmax_factor GLEW_GET_VAR(__GLEW_AMD_blend_minmax_factor) - -#endif /* GL_AMD_blend_minmax_factor */ - -/* ----------------------- GL_AMD_conservative_depth ----------------------- */ - -#ifndef GL_AMD_conservative_depth -#define GL_AMD_conservative_depth 1 - -#define GLEW_AMD_conservative_depth GLEW_GET_VAR(__GLEW_AMD_conservative_depth) - -#endif /* GL_AMD_conservative_depth */ - -/* -------------------------- GL_AMD_debug_output -------------------------- */ - -#ifndef GL_AMD_debug_output -#define GL_AMD_debug_output 1 - -#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 -#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145 -#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147 -#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148 -#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149 -#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A -#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B -#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C -#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D -#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E -#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F -#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 - -typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); - -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf); -typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message); - -#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD) -#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD) -#define glDebugMessageInsertAMD GLEW_GET_FUN(__glewDebugMessageInsertAMD) -#define glGetDebugMessageLogAMD GLEW_GET_FUN(__glewGetDebugMessageLogAMD) - -#define GLEW_AMD_debug_output GLEW_GET_VAR(__GLEW_AMD_debug_output) - -#endif /* GL_AMD_debug_output */ - -/* ---------------------- GL_AMD_depth_clamp_separate ---------------------- */ - -#ifndef GL_AMD_depth_clamp_separate -#define GL_AMD_depth_clamp_separate 1 - -#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E -#define GL_DEPTH_CLAMP_FAR_AMD 0x901F - -#define GLEW_AMD_depth_clamp_separate GLEW_GET_VAR(__GLEW_AMD_depth_clamp_separate) - -#endif /* GL_AMD_depth_clamp_separate */ - -/* ----------------------- GL_AMD_draw_buffers_blend ----------------------- */ - -#ifndef GL_AMD_draw_buffers_blend -#define GL_AMD_draw_buffers_blend 1 - -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); - -#define glBlendEquationIndexedAMD GLEW_GET_FUN(__glewBlendEquationIndexedAMD) -#define glBlendEquationSeparateIndexedAMD GLEW_GET_FUN(__glewBlendEquationSeparateIndexedAMD) -#define glBlendFuncIndexedAMD GLEW_GET_FUN(__glewBlendFuncIndexedAMD) -#define glBlendFuncSeparateIndexedAMD GLEW_GET_FUN(__glewBlendFuncSeparateIndexedAMD) - -#define GLEW_AMD_draw_buffers_blend GLEW_GET_VAR(__GLEW_AMD_draw_buffers_blend) - -#endif /* GL_AMD_draw_buffers_blend */ - -/* ------------------------- GL_AMD_name_gen_delete ------------------------ */ - -#ifndef GL_AMD_name_gen_delete -#define GL_AMD_name_gen_delete 1 - -#define GL_DATA_BUFFER_AMD 0x9151 -#define GL_PERFORMANCE_MONITOR_AMD 0x9152 -#define GL_QUERY_OBJECT_AMD 0x9153 -#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154 -#define GL_SAMPLER_OBJECT_AMD 0x9155 - -typedef void (GLAPIENTRY * PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint* names); -typedef void (GLAPIENTRY * PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint* names); -typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name); - -#define glDeleteNamesAMD GLEW_GET_FUN(__glewDeleteNamesAMD) -#define glGenNamesAMD GLEW_GET_FUN(__glewGenNamesAMD) -#define glIsNameAMD GLEW_GET_FUN(__glewIsNameAMD) - -#define GLEW_AMD_name_gen_delete GLEW_GET_VAR(__GLEW_AMD_name_gen_delete) - -#endif /* GL_AMD_name_gen_delete */ - -/* ----------------------- GL_AMD_performance_monitor ---------------------- */ - -#ifndef GL_AMD_performance_monitor -#define GL_AMD_performance_monitor 1 - -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_COUNTER_TYPE_AMD 0x8BC0 -#define GL_COUNTER_RANGE_AMD 0x8BC1 -#define GL_UNSIGNED_INT64_AMD 0x8BC2 -#define GL_PERCENTAGE_AMD 0x8BC3 -#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 -#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 -#define GL_PERFMON_RESULT_AMD 0x8BC6 - -typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); -typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups); -typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList); - -#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD) -#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD) -#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD) -#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD) -#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD) -#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD) -#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD) -#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD) -#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD) -#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD) -#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD) - -#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor) - -#endif /* GL_AMD_performance_monitor */ - -/* ------------------------ GL_AMD_sample_positions ------------------------ */ - -#ifndef GL_AMD_sample_positions -#define GL_AMD_sample_positions 1 - -#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F - -typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat* val); - -#define glSetMultisamplefvAMD GLEW_GET_FUN(__glewSetMultisamplefvAMD) - -#define GLEW_AMD_sample_positions GLEW_GET_VAR(__GLEW_AMD_sample_positions) - -#endif /* GL_AMD_sample_positions */ - -/* ------------------ GL_AMD_seamless_cubemap_per_texture ------------------ */ - -#ifndef GL_AMD_seamless_cubemap_per_texture -#define GL_AMD_seamless_cubemap_per_texture 1 - -#define GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB 0x884F - -#define GLEW_AMD_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_AMD_seamless_cubemap_per_texture) - -#endif /* GL_AMD_seamless_cubemap_per_texture */ - -/* ---------------------- GL_AMD_shader_stencil_export --------------------- */ - -#ifndef GL_AMD_shader_stencil_export -#define GL_AMD_shader_stencil_export 1 - -#define GLEW_AMD_shader_stencil_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_export) - -#endif /* GL_AMD_shader_stencil_export */ - -/* ------------------------ GL_AMD_texture_texture4 ------------------------ */ - -#ifndef GL_AMD_texture_texture4 -#define GL_AMD_texture_texture4 1 - -#define GLEW_AMD_texture_texture4 GLEW_GET_VAR(__GLEW_AMD_texture_texture4) - -#endif /* GL_AMD_texture_texture4 */ - -/* --------------- GL_AMD_transform_feedback3_lines_triangles -------------- */ - -#ifndef GL_AMD_transform_feedback3_lines_triangles -#define GL_AMD_transform_feedback3_lines_triangles 1 - -#define GLEW_AMD_transform_feedback3_lines_triangles GLEW_GET_VAR(__GLEW_AMD_transform_feedback3_lines_triangles) - -#endif /* GL_AMD_transform_feedback3_lines_triangles */ - -/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */ - -#ifndef GL_AMD_vertex_shader_tessellator -#define GL_AMD_vertex_shader_tessellator 1 - -#define GL_SAMPLER_BUFFER_AMD 0x9001 -#define GL_INT_SAMPLER_BUFFER_AMD 0x9002 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003 -#define GL_TESSELLATION_MODE_AMD 0x9004 -#define GL_TESSELLATION_FACTOR_AMD 0x9005 -#define GL_DISCRETE_AMD 0x9006 -#define GL_CONTINUOUS_AMD 0x9007 - -typedef void (GLAPIENTRY * PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor); -typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); - -#define glTessellationFactorAMD GLEW_GET_FUN(__glewTessellationFactorAMD) -#define glTessellationModeAMD GLEW_GET_FUN(__glewTessellationModeAMD) - -#define GLEW_AMD_vertex_shader_tessellator GLEW_GET_VAR(__GLEW_AMD_vertex_shader_tessellator) - -#endif /* GL_AMD_vertex_shader_tessellator */ - -/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */ - -#ifndef GL_APPLE_aux_depth_stencil -#define GL_APPLE_aux_depth_stencil 1 - -#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 - -#define GLEW_APPLE_aux_depth_stencil GLEW_GET_VAR(__GLEW_APPLE_aux_depth_stencil) - -#endif /* GL_APPLE_aux_depth_stencil */ - -/* ------------------------ GL_APPLE_client_storage ------------------------ */ - -#ifndef GL_APPLE_client_storage -#define GL_APPLE_client_storage 1 - -#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 - -#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage) - -#endif /* GL_APPLE_client_storage */ - -/* ------------------------- GL_APPLE_element_array ------------------------ */ - -#ifndef GL_APPLE_element_array -#define GL_APPLE_element_array 1 - -#define GL_ELEMENT_ARRAY_APPLE 0x8A0C -#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D -#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E - -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); -typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); - -#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE) -#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE) -#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE) -#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE) -#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE) - -#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array) - -#endif /* GL_APPLE_element_array */ - -/* ----------------------------- GL_APPLE_fence ---------------------------- */ - -#ifndef GL_APPLE_fence -#define GL_APPLE_fence 1 - -#define GL_DRAW_PIXELS_APPLE 0x8A0A -#define GL_FENCE_APPLE 0x8A0B - -typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences); -typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); -typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); -typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences); -typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence); -typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence); -typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence); -typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); - -#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE) -#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE) -#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE) -#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE) -#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE) -#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE) -#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE) -#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE) - -#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence) - -#endif /* GL_APPLE_fence */ - -/* ------------------------- GL_APPLE_float_pixels ------------------------- */ - -#ifndef GL_APPLE_float_pixels -#define GL_APPLE_float_pixels 1 - -#define GL_HALF_APPLE 0x140B -#define GL_RGBA_FLOAT32_APPLE 0x8814 -#define GL_RGB_FLOAT32_APPLE 0x8815 -#define GL_ALPHA_FLOAT32_APPLE 0x8816 -#define GL_INTENSITY_FLOAT32_APPLE 0x8817 -#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 -#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 -#define GL_RGBA_FLOAT16_APPLE 0x881A -#define GL_RGB_FLOAT16_APPLE 0x881B -#define GL_ALPHA_FLOAT16_APPLE 0x881C -#define GL_INTENSITY_FLOAT16_APPLE 0x881D -#define GL_LUMINANCE_FLOAT16_APPLE 0x881E -#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F -#define GL_COLOR_FLOAT_APPLE 0x8A0F - -#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels) - -#endif /* GL_APPLE_float_pixels */ - -/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */ - -#ifndef GL_APPLE_flush_buffer_range -#define GL_APPLE_flush_buffer_range 1 - -#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 -#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 - -typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); - -#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE) -#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE) - -#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range) - -#endif /* GL_APPLE_flush_buffer_range */ - -/* ----------------------- GL_APPLE_object_purgeable ----------------------- */ - -#ifndef GL_APPLE_object_purgeable -#define GL_APPLE_object_purgeable 1 - -#define GL_BUFFER_OBJECT_APPLE 0x85B3 -#define GL_RELEASED_APPLE 0x8A19 -#define GL_VOLATILE_APPLE 0x8A1A -#define GL_RETAINED_APPLE 0x8A1B -#define GL_UNDEFINED_APPLE 0x8A1C -#define GL_PURGEABLE_APPLE 0x8A1D - -typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params); -typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); -typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); - -#define glGetObjectParameterivAPPLE GLEW_GET_FUN(__glewGetObjectParameterivAPPLE) -#define glObjectPurgeableAPPLE GLEW_GET_FUN(__glewObjectPurgeableAPPLE) -#define glObjectUnpurgeableAPPLE GLEW_GET_FUN(__glewObjectUnpurgeableAPPLE) - -#define GLEW_APPLE_object_purgeable GLEW_GET_VAR(__GLEW_APPLE_object_purgeable) - -#endif /* GL_APPLE_object_purgeable */ - -/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */ - -#ifndef GL_APPLE_pixel_buffer -#define GL_APPLE_pixel_buffer 1 - -#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10 - -#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer) - -#endif /* GL_APPLE_pixel_buffer */ - -/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */ - -#ifndef GL_APPLE_rgb_422 -#define GL_APPLE_rgb_422 1 - -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB -#define GL_RGB_422_APPLE 0x8A1F - -#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422) - -#endif /* GL_APPLE_rgb_422 */ - -/* --------------------------- GL_APPLE_row_bytes -------------------------- */ - -#ifndef GL_APPLE_row_bytes -#define GL_APPLE_row_bytes 1 - -#define GL_PACK_ROW_BYTES_APPLE 0x8A15 -#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 - -#define GLEW_APPLE_row_bytes GLEW_GET_VAR(__GLEW_APPLE_row_bytes) - -#endif /* GL_APPLE_row_bytes */ - -/* ------------------------ GL_APPLE_specular_vector ----------------------- */ - -#ifndef GL_APPLE_specular_vector -#define GL_APPLE_specular_vector 1 - -#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 - -#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector) - -#endif /* GL_APPLE_specular_vector */ - -/* ------------------------- GL_APPLE_texture_range ------------------------ */ - -#ifndef GL_APPLE_texture_range -#define GL_APPLE_texture_range 1 - -#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 -#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 -#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC -#define GL_STORAGE_PRIVATE_APPLE 0x85BD -#define GL_STORAGE_CACHED_APPLE 0x85BE -#define GL_STORAGE_SHARED_APPLE 0x85BF - -typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params); -typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer); - -#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE) -#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE) - -#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range) - -#endif /* GL_APPLE_texture_range */ - -/* ------------------------ GL_APPLE_transform_hint ------------------------ */ - -#ifndef GL_APPLE_transform_hint -#define GL_APPLE_transform_hint 1 - -#define GL_TRANSFORM_HINT_APPLE 0x85B1 - -#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint) - -#endif /* GL_APPLE_transform_hint */ - -/* ---------------------- GL_APPLE_vertex_array_object --------------------- */ - -#ifndef GL_APPLE_vertex_array_object -#define GL_APPLE_vertex_array_object 1 - -#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 - -typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); -typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); -typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); -typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); - -#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE) -#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE) -#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE) -#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE) - -#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object) - -#endif /* GL_APPLE_vertex_array_object */ - -/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */ - -#ifndef GL_APPLE_vertex_array_range -#define GL_APPLE_vertex_array_range 1 - -#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D -#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E -#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F -#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520 -#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 -#define GL_STORAGE_CLIENT_APPLE 0x85B4 -#define GL_STORAGE_CACHED_APPLE 0x85BE -#define GL_STORAGE_SHARED_APPLE 0x85BF - -typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); - -#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) -#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) -#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE) - -#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range) - -#endif /* GL_APPLE_vertex_array_range */ - -/* ------------------- GL_APPLE_vertex_program_evaluators ------------------ */ - -#ifndef GL_APPLE_vertex_program_evaluators -#define GL_APPLE_vertex_program_evaluators 1 - -#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 -#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 -#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 -#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 -#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 -#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 -#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 -#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 -#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 -#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 - -typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); -typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); -typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); -typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points); -typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points); -typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points); -typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points); - -#define glDisableVertexAttribAPPLE GLEW_GET_FUN(__glewDisableVertexAttribAPPLE) -#define glEnableVertexAttribAPPLE GLEW_GET_FUN(__glewEnableVertexAttribAPPLE) -#define glIsVertexAttribEnabledAPPLE GLEW_GET_FUN(__glewIsVertexAttribEnabledAPPLE) -#define glMapVertexAttrib1dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1dAPPLE) -#define glMapVertexAttrib1fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1fAPPLE) -#define glMapVertexAttrib2dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2dAPPLE) -#define glMapVertexAttrib2fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2fAPPLE) - -#define GLEW_APPLE_vertex_program_evaluators GLEW_GET_VAR(__GLEW_APPLE_vertex_program_evaluators) - -#endif /* GL_APPLE_vertex_program_evaluators */ - -/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */ - -#ifndef GL_APPLE_ycbcr_422 -#define GL_APPLE_ycbcr_422 1 - -#define GL_YCBCR_422_APPLE 0x85B9 -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB - -#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422) - -#endif /* GL_APPLE_ycbcr_422 */ - -/* ------------------------ GL_ARB_ES2_compatibility ----------------------- */ - -#ifndef GL_ARB_ES2_compatibility -#define GL_ARB_ES2_compatibility 1 - -#define GL_FIXED 0x140C -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 -#define GL_SHADER_BINARY_FORMATS 0x8DF8 -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 -#define GL_SHADER_COMPILER 0x8DFA -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD - -typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d); -typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); -typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision); -typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void); -typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length); - -#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf) -#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef) -#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat) -#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler) -#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary) - -#define GLEW_ARB_ES2_compatibility GLEW_GET_VAR(__GLEW_ARB_ES2_compatibility) - -#endif /* GL_ARB_ES2_compatibility */ - -/* ----------------------- GL_ARB_blend_func_extended ---------------------- */ - -#ifndef GL_ARB_blend_func_extended -#define GL_ARB_blend_func_extended 1 - -#define GL_SRC1_COLOR 0x88F9 -#define GL_ONE_MINUS_SRC1_COLOR 0x88FA -#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB -#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC - -typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name); -typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name); - -#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed) -#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex) - -#define GLEW_ARB_blend_func_extended GLEW_GET_VAR(__GLEW_ARB_blend_func_extended) - -#endif /* GL_ARB_blend_func_extended */ - -/* ---------------------------- GL_ARB_cl_event ---------------------------- */ - -#ifndef GL_ARB_cl_event -#define GL_ARB_cl_event 1 - -#define GL_SYNC_CL_EVENT_ARB 0x8240 -#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 - -typedef struct _cl_context *cl_context; -typedef struct _cl_event *cl_event; - -typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context context, cl_event event, GLbitfield flags); - -#define glCreateSyncFromCLeventARB GLEW_GET_FUN(__glewCreateSyncFromCLeventARB) - -#define GLEW_ARB_cl_event GLEW_GET_VAR(__GLEW_ARB_cl_event) - -#endif /* GL_ARB_cl_event */ - -/* ----------------------- GL_ARB_color_buffer_float ----------------------- */ - -#ifndef GL_ARB_color_buffer_float -#define GL_ARB_color_buffer_float 1 - -#define GL_RGBA_FLOAT_MODE_ARB 0x8820 -#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A -#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B -#define GL_CLAMP_READ_COLOR_ARB 0x891C -#define GL_FIXED_ONLY_ARB 0x891D - -typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); - -#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB) - -#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float) - -#endif /* GL_ARB_color_buffer_float */ - -/* -------------------------- GL_ARB_compatibility ------------------------- */ - -#ifndef GL_ARB_compatibility -#define GL_ARB_compatibility 1 - -#define GLEW_ARB_compatibility GLEW_GET_VAR(__GLEW_ARB_compatibility) - -#endif /* GL_ARB_compatibility */ - -/* --------------------------- GL_ARB_copy_buffer -------------------------- */ - -#ifndef GL_ARB_copy_buffer -#define GL_ARB_copy_buffer 1 - -#define GL_COPY_READ_BUFFER 0x8F36 -#define GL_COPY_WRITE_BUFFER 0x8F37 - -typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size); - -#define glCopyBufferSubData GLEW_GET_FUN(__glewCopyBufferSubData) - -#define GLEW_ARB_copy_buffer GLEW_GET_VAR(__GLEW_ARB_copy_buffer) - -#endif /* GL_ARB_copy_buffer */ - -/* -------------------------- GL_ARB_debug_output -------------------------- */ - -#ifndef GL_ARB_debug_output -#define GL_ARB_debug_output 1 - -#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 -#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 -#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 -#define GL_DEBUG_SOURCE_API_ARB 0x8246 -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 -#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 -#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 -#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A -#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B -#define GL_DEBUG_TYPE_ERROR_ARB 0x824C -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E -#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F -#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 -#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 -#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 -#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 -#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 -#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 - -typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); - -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf); -typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog); - -#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB) -#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB) -#define glDebugMessageInsertARB GLEW_GET_FUN(__glewDebugMessageInsertARB) -#define glGetDebugMessageLogARB GLEW_GET_FUN(__glewGetDebugMessageLogARB) - -#define GLEW_ARB_debug_output GLEW_GET_VAR(__GLEW_ARB_debug_output) - -#endif /* GL_ARB_debug_output */ - -/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */ - -#ifndef GL_ARB_depth_buffer_float -#define GL_ARB_depth_buffer_float 1 - -#define GL_DEPTH_COMPONENT32F 0x8CAC -#define GL_DEPTH32F_STENCIL8 0x8CAD -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD - -#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float) - -#endif /* GL_ARB_depth_buffer_float */ - -/* --------------------------- GL_ARB_depth_clamp -------------------------- */ - -#ifndef GL_ARB_depth_clamp -#define GL_ARB_depth_clamp 1 - -#define GL_DEPTH_CLAMP 0x864F - -#define GLEW_ARB_depth_clamp GLEW_GET_VAR(__GLEW_ARB_depth_clamp) - -#endif /* GL_ARB_depth_clamp */ - -/* -------------------------- GL_ARB_depth_texture ------------------------- */ - -#ifndef GL_ARB_depth_texture -#define GL_ARB_depth_texture 1 - -#define GL_DEPTH_COMPONENT16_ARB 0x81A5 -#define GL_DEPTH_COMPONENT24_ARB 0x81A6 -#define GL_DEPTH_COMPONENT32_ARB 0x81A7 -#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A -#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B - -#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture) - -#endif /* GL_ARB_depth_texture */ - -/* -------------------------- GL_ARB_draw_buffers -------------------------- */ - -#ifndef GL_ARB_draw_buffers -#define GL_ARB_draw_buffers 1 - -#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 -#define GL_DRAW_BUFFER0_ARB 0x8825 -#define GL_DRAW_BUFFER1_ARB 0x8826 -#define GL_DRAW_BUFFER2_ARB 0x8827 -#define GL_DRAW_BUFFER3_ARB 0x8828 -#define GL_DRAW_BUFFER4_ARB 0x8829 -#define GL_DRAW_BUFFER5_ARB 0x882A -#define GL_DRAW_BUFFER6_ARB 0x882B -#define GL_DRAW_BUFFER7_ARB 0x882C -#define GL_DRAW_BUFFER8_ARB 0x882D -#define GL_DRAW_BUFFER9_ARB 0x882E -#define GL_DRAW_BUFFER10_ARB 0x882F -#define GL_DRAW_BUFFER11_ARB 0x8830 -#define GL_DRAW_BUFFER12_ARB 0x8831 -#define GL_DRAW_BUFFER13_ARB 0x8832 -#define GL_DRAW_BUFFER14_ARB 0x8833 -#define GL_DRAW_BUFFER15_ARB 0x8834 - -typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs); - -#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB) - -#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers) - -#endif /* GL_ARB_draw_buffers */ - -/* ----------------------- GL_ARB_draw_buffers_blend ----------------------- */ - -#ifndef GL_ARB_draw_buffers_blend -#define GL_ARB_draw_buffers_blend 1 - -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); - -#define glBlendEquationSeparateiARB GLEW_GET_FUN(__glewBlendEquationSeparateiARB) -#define glBlendEquationiARB GLEW_GET_FUN(__glewBlendEquationiARB) -#define glBlendFuncSeparateiARB GLEW_GET_FUN(__glewBlendFuncSeparateiARB) -#define glBlendFunciARB GLEW_GET_FUN(__glewBlendFunciARB) - -#define GLEW_ARB_draw_buffers_blend GLEW_GET_VAR(__GLEW_ARB_draw_buffers_blend) - -#endif /* GL_ARB_draw_buffers_blend */ - -/* -------------------- GL_ARB_draw_elements_base_vertex ------------------- */ - -#ifndef GL_ARB_draw_elements_base_vertex -#define GL_ARB_draw_elements_base_vertex 1 - -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex); - -#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex) -#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex) -#define glDrawRangeElementsBaseVertex GLEW_GET_FUN(__glewDrawRangeElementsBaseVertex) -#define glMultiDrawElementsBaseVertex GLEW_GET_FUN(__glewMultiDrawElementsBaseVertex) - -#define GLEW_ARB_draw_elements_base_vertex GLEW_GET_VAR(__GLEW_ARB_draw_elements_base_vertex) - -#endif /* GL_ARB_draw_elements_base_vertex */ - -/* -------------------------- GL_ARB_draw_indirect ------------------------- */ - -#ifndef GL_ARB_draw_indirect -#define GL_ARB_draw_indirect 1 - -#define GL_DRAW_INDIRECT_BUFFER 0x8F3F -#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 - -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect); - -#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect) -#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect) - -#define GLEW_ARB_draw_indirect GLEW_GET_VAR(__GLEW_ARB_draw_indirect) - -#endif /* GL_ARB_draw_indirect */ - -/* ------------------------- GL_ARB_draw_instanced ------------------------- */ - -#ifndef GL_ARB_draw_instanced -#define GL_ARB_draw_instanced 1 - -#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced) - -#endif /* GL_ARB_draw_instanced */ - -/* -------------------- GL_ARB_explicit_attrib_location -------------------- */ - -#ifndef GL_ARB_explicit_attrib_location -#define GL_ARB_explicit_attrib_location 1 - -#define GLEW_ARB_explicit_attrib_location GLEW_GET_VAR(__GLEW_ARB_explicit_attrib_location) - -#endif /* GL_ARB_explicit_attrib_location */ - -/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */ - -#ifndef GL_ARB_fragment_coord_conventions -#define GL_ARB_fragment_coord_conventions 1 - -#define GLEW_ARB_fragment_coord_conventions GLEW_GET_VAR(__GLEW_ARB_fragment_coord_conventions) - -#endif /* GL_ARB_fragment_coord_conventions */ - -/* ------------------------ GL_ARB_fragment_program ------------------------ */ - -#ifndef GL_ARB_fragment_program -#define GL_ARB_fragment_program 1 - -#define GL_FRAGMENT_PROGRAM_ARB 0x8804 -#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 -#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 -#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 -#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 -#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 -#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A -#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B -#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C -#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D -#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E -#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F -#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 -#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 - -#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program) - -#endif /* GL_ARB_fragment_program */ - -/* --------------------- GL_ARB_fragment_program_shadow -------------------- */ - -#ifndef GL_ARB_fragment_program_shadow -#define GL_ARB_fragment_program_shadow 1 - -#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow) - -#endif /* GL_ARB_fragment_program_shadow */ - -/* ------------------------- GL_ARB_fragment_shader ------------------------ */ - -#ifndef GL_ARB_fragment_shader -#define GL_ARB_fragment_shader 1 - -#define GL_FRAGMENT_SHADER_ARB 0x8B30 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B - -#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader) - -#endif /* GL_ARB_fragment_shader */ - -/* ----------------------- GL_ARB_framebuffer_object ----------------------- */ - -#ifndef GL_ARB_framebuffer_object -#define GL_ARB_framebuffer_object 1 - -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 -#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 -#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 -#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 -#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 -#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 -#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 -#define GL_FRAMEBUFFER_DEFAULT 0x8218 -#define GL_FRAMEBUFFER_UNDEFINED 0x8219 -#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GL_INDEX 0x8222 -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 -#define GL_DEPTH_STENCIL 0x84F9 -#define GL_UNSIGNED_INT_24_8 0x84FA -#define GL_DEPTH24_STENCIL8 0x88F0 -#define GL_TEXTURE_STENCIL_SIZE 0x88F1 -#define GL_UNSIGNED_NORMALIZED 0x8C17 -#define GL_SRGB 0x8C40 -#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA -#define GL_RENDERBUFFER_SAMPLES 0x8CAB -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_COLOR_ATTACHMENT1 0x8CE1 -#define GL_COLOR_ATTACHMENT2 0x8CE2 -#define GL_COLOR_ATTACHMENT3 0x8CE3 -#define GL_COLOR_ATTACHMENT4 0x8CE4 -#define GL_COLOR_ATTACHMENT5 0x8CE5 -#define GL_COLOR_ATTACHMENT6 0x8CE6 -#define GL_COLOR_ATTACHMENT7 0x8CE7 -#define GL_COLOR_ATTACHMENT8 0x8CE8 -#define GL_COLOR_ATTACHMENT9 0x8CE9 -#define GL_COLOR_ATTACHMENT10 0x8CEA -#define GL_COLOR_ATTACHMENT11 0x8CEB -#define GL_COLOR_ATTACHMENT12 0x8CEC -#define GL_COLOR_ATTACHMENT13 0x8CED -#define GL_COLOR_ATTACHMENT14 0x8CEE -#define GL_COLOR_ATTACHMENT15 0x8CEF -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_STENCIL_INDEX1 0x8D46 -#define GL_STENCIL_INDEX4 0x8D47 -#define GL_STENCIL_INDEX8 0x8D48 -#define GL_STENCIL_INDEX16 0x8D49 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#define GL_MAX_SAMPLES 0x8D57 - -typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); -typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers); -typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer); -typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers); -typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers); -typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); -typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); - -#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer) -#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer) -#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer) -#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus) -#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers) -#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers) -#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer) -#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D) -#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D) -#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D) -#define glFramebufferTextureLayer GLEW_GET_FUN(__glewFramebufferTextureLayer) -#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers) -#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers) -#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap) -#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv) -#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv) -#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer) -#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer) -#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage) -#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample) - -#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object) - -#endif /* GL_ARB_framebuffer_object */ - -/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */ - -#ifndef GL_ARB_framebuffer_sRGB -#define GL_ARB_framebuffer_sRGB 1 - -#define GL_FRAMEBUFFER_SRGB 0x8DB9 - -#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB) - -#endif /* GL_ARB_framebuffer_sRGB */ - -/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */ - -#ifndef GL_ARB_geometry_shader4 -#define GL_ARB_geometry_shader4 1 - -#define GL_LINES_ADJACENCY_ARB 0xA -#define GL_LINE_STRIP_ADJACENCY_ARB 0xB -#define GL_TRIANGLES_ADJACENCY_ARB 0xC -#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD -#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 -#define GL_GEOMETRY_SHADER_ARB 0x8DD9 -#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA -#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB -#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC -#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD -#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 - -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); - -#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB) -#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB) -#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB) -#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB) - -#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4) - -#endif /* GL_ARB_geometry_shader4 */ - -/* ----------------------- GL_ARB_get_program_binary ----------------------- */ - -#ifndef GL_ARB_get_program_binary -#define GL_ARB_get_program_binary 1 - -#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 -#define GL_PROGRAM_BINARY_LENGTH 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE -#define GL_PROGRAM_BINARY_FORMATS 0x87FF - -typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); -typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); - -#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary) -#define glProgramBinary GLEW_GET_FUN(__glewProgramBinary) -#define glProgramParameteri GLEW_GET_FUN(__glewProgramParameteri) - -#define GLEW_ARB_get_program_binary GLEW_GET_VAR(__GLEW_ARB_get_program_binary) - -#endif /* GL_ARB_get_program_binary */ - -/* --------------------------- GL_ARB_gpu_shader5 -------------------------- */ - -#ifndef GL_ARB_gpu_shader5 -#define GL_ARB_gpu_shader5 1 - -#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F -#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C -#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D -#define GL_MAX_VERTEX_STREAMS 0x8E71 - -#define GLEW_ARB_gpu_shader5 GLEW_GET_VAR(__GLEW_ARB_gpu_shader5) - -#endif /* GL_ARB_gpu_shader5 */ - -/* ------------------------- GL_ARB_gpu_shader_fp64 ------------------------ */ - -#ifndef GL_ARB_gpu_shader_fp64 -#define GL_ARB_gpu_shader_fp64 1 - -#define GL_DOUBLE_MAT2 0x8F46 -#define GL_DOUBLE_MAT3 0x8F47 -#define GL_DOUBLE_MAT4 0x8F48 -#define GL_DOUBLE_MAT2x3 0x8F49 -#define GL_DOUBLE_MAT2x4 0x8F4A -#define GL_DOUBLE_MAT3x2 0x8F4B -#define GL_DOUBLE_MAT3x4 0x8F4C -#define GL_DOUBLE_MAT4x2 0x8F4D -#define GL_DOUBLE_MAT4x3 0x8F4E -#define GL_DOUBLE_VEC2 0x8FFC -#define GL_DOUBLE_VEC3 0x8FFD -#define GL_DOUBLE_VEC4 0x8FFE - -typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); -typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); - -#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv) -#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT) -#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT) -#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT) -#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT) -#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT) -#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT) -#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT) -#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT) -#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT) -#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT) -#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT) -#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT) -#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT) -#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT) -#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT) -#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT) -#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT) -#define glUniform1d GLEW_GET_FUN(__glewUniform1d) -#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv) -#define glUniform2d GLEW_GET_FUN(__glewUniform2d) -#define glUniform2dv GLEW_GET_FUN(__glewUniform2dv) -#define glUniform3d GLEW_GET_FUN(__glewUniform3d) -#define glUniform3dv GLEW_GET_FUN(__glewUniform3dv) -#define glUniform4d GLEW_GET_FUN(__glewUniform4d) -#define glUniform4dv GLEW_GET_FUN(__glewUniform4dv) -#define glUniformMatrix2dv GLEW_GET_FUN(__glewUniformMatrix2dv) -#define glUniformMatrix2x3dv GLEW_GET_FUN(__glewUniformMatrix2x3dv) -#define glUniformMatrix2x4dv GLEW_GET_FUN(__glewUniformMatrix2x4dv) -#define glUniformMatrix3dv GLEW_GET_FUN(__glewUniformMatrix3dv) -#define glUniformMatrix3x2dv GLEW_GET_FUN(__glewUniformMatrix3x2dv) -#define glUniformMatrix3x4dv GLEW_GET_FUN(__glewUniformMatrix3x4dv) -#define glUniformMatrix4dv GLEW_GET_FUN(__glewUniformMatrix4dv) -#define glUniformMatrix4x2dv GLEW_GET_FUN(__glewUniformMatrix4x2dv) -#define glUniformMatrix4x3dv GLEW_GET_FUN(__glewUniformMatrix4x3dv) - -#define GLEW_ARB_gpu_shader_fp64 GLEW_GET_VAR(__GLEW_ARB_gpu_shader_fp64) - -#endif /* GL_ARB_gpu_shader_fp64 */ - -/* ------------------------ GL_ARB_half_float_pixel ------------------------ */ - -#ifndef GL_ARB_half_float_pixel -#define GL_ARB_half_float_pixel 1 - -#define GL_HALF_FLOAT_ARB 0x140B - -#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel) - -#endif /* GL_ARB_half_float_pixel */ - -/* ------------------------ GL_ARB_half_float_vertex ----------------------- */ - -#ifndef GL_ARB_half_float_vertex -#define GL_ARB_half_float_vertex 1 - -#define GL_HALF_FLOAT 0x140B - -#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex) - -#endif /* GL_ARB_half_float_vertex */ - -/* ----------------------------- GL_ARB_imaging ---------------------------- */ - -#ifndef GL_ARB_imaging -#define GL_ARB_imaging 1 - -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 -#define GL_FUNC_ADD 0x8006 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_BLEND_EQUATION 0x8009 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_CONVOLUTION_1D 0x8010 -#define GL_CONVOLUTION_2D 0x8011 -#define GL_SEPARABLE_2D 0x8012 -#define GL_CONVOLUTION_BORDER_MODE 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS 0x8015 -#define GL_REDUCE 0x8016 -#define GL_CONVOLUTION_FORMAT 0x8017 -#define GL_CONVOLUTION_WIDTH 0x8018 -#define GL_CONVOLUTION_HEIGHT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 -#define GL_HISTOGRAM 0x8024 -#define GL_PROXY_HISTOGRAM 0x8025 -#define GL_HISTOGRAM_WIDTH 0x8026 -#define GL_HISTOGRAM_FORMAT 0x8027 -#define GL_HISTOGRAM_RED_SIZE 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C -#define GL_HISTOGRAM_SINK 0x802D -#define GL_MINMAX 0x802E -#define GL_MINMAX_FORMAT 0x802F -#define GL_MINMAX_SINK 0x8030 -#define GL_TABLE_TOO_LARGE 0x8031 -#define GL_COLOR_MATRIX 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA -#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB -#define GL_COLOR_TABLE 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 -#define GL_PROXY_COLOR_TABLE 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 -#define GL_COLOR_TABLE_SCALE 0x80D6 -#define GL_COLOR_TABLE_BIAS 0x80D7 -#define GL_COLOR_TABLE_FORMAT 0x80D8 -#define GL_COLOR_TABLE_WIDTH 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF -#define GL_IGNORE_BORDER 0x8150 -#define GL_CONSTANT_BORDER 0x8151 -#define GL_WRAP_BORDER 0x8152 -#define GL_REPLICATE_BORDER 0x8153 -#define GL_CONVOLUTION_BORDER_COLOR 0x8154 - -typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); -typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); -typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); - -#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable) -#define glColorTable GLEW_GET_FUN(__glewColorTable) -#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv) -#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv) -#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D) -#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D) -#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf) -#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv) -#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri) -#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv) -#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable) -#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable) -#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D) -#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D) -#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable) -#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv) -#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv) -#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter) -#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv) -#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv) -#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram) -#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv) -#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv) -#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax) -#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv) -#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv) -#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter) -#define glHistogram GLEW_GET_FUN(__glewHistogram) -#define glMinmax GLEW_GET_FUN(__glewMinmax) -#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram) -#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax) -#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D) - -#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging) - -#endif /* GL_ARB_imaging */ - -/* ------------------------ GL_ARB_instanced_arrays ------------------------ */ - -#ifndef GL_ARB_instanced_arrays -#define GL_ARB_instanced_arrays 1 - -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE - -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); - -#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB) -#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB) -#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB) - -#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays) - -#endif /* GL_ARB_instanced_arrays */ - -/* ------------------------ GL_ARB_map_buffer_range ------------------------ */ - -#ifndef GL_ARB_map_buffer_range -#define GL_ARB_map_buffer_range 1 - -#define GL_MAP_READ_BIT 0x0001 -#define GL_MAP_WRITE_BIT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 - -typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); - -#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange) -#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange) - -#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range) - -#endif /* GL_ARB_map_buffer_range */ - -/* ------------------------- GL_ARB_matrix_palette ------------------------- */ - -#ifndef GL_ARB_matrix_palette -#define GL_ARB_matrix_palette 1 - -#define GL_MATRIX_PALETTE_ARB 0x8840 -#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 -#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 -#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 -#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 -#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 -#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 -#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 -#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 -#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 - -typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); -typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices); -typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices); -typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices); - -#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB) -#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB) -#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB) -#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB) -#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB) - -#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette) - -#endif /* GL_ARB_matrix_palette */ - -/* --------------------------- GL_ARB_multisample -------------------------- */ - -#ifndef GL_ARB_multisample -#define GL_ARB_multisample 1 - -#define GL_MULTISAMPLE_ARB 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F -#define GL_SAMPLE_COVERAGE_ARB 0x80A0 -#define GL_SAMPLE_BUFFERS_ARB 0x80A8 -#define GL_SAMPLES_ARB 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB -#define GL_MULTISAMPLE_BIT_ARB 0x20000000 - -typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); - -#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB) - -#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample) - -#endif /* GL_ARB_multisample */ - -/* -------------------------- GL_ARB_multitexture -------------------------- */ - -#ifndef GL_ARB_multitexture -#define GL_ARB_multitexture 1 - -#define GL_TEXTURE0_ARB 0x84C0 -#define GL_TEXTURE1_ARB 0x84C1 -#define GL_TEXTURE2_ARB 0x84C2 -#define GL_TEXTURE3_ARB 0x84C3 -#define GL_TEXTURE4_ARB 0x84C4 -#define GL_TEXTURE5_ARB 0x84C5 -#define GL_TEXTURE6_ARB 0x84C6 -#define GL_TEXTURE7_ARB 0x84C7 -#define GL_TEXTURE8_ARB 0x84C8 -#define GL_TEXTURE9_ARB 0x84C9 -#define GL_TEXTURE10_ARB 0x84CA -#define GL_TEXTURE11_ARB 0x84CB -#define GL_TEXTURE12_ARB 0x84CC -#define GL_TEXTURE13_ARB 0x84CD -#define GL_TEXTURE14_ARB 0x84CE -#define GL_TEXTURE15_ARB 0x84CF -#define GL_TEXTURE16_ARB 0x84D0 -#define GL_TEXTURE17_ARB 0x84D1 -#define GL_TEXTURE18_ARB 0x84D2 -#define GL_TEXTURE19_ARB 0x84D3 -#define GL_TEXTURE20_ARB 0x84D4 -#define GL_TEXTURE21_ARB 0x84D5 -#define GL_TEXTURE22_ARB 0x84D6 -#define GL_TEXTURE23_ARB 0x84D7 -#define GL_TEXTURE24_ARB 0x84D8 -#define GL_TEXTURE25_ARB 0x84D9 -#define GL_TEXTURE26_ARB 0x84DA -#define GL_TEXTURE27_ARB 0x84DB -#define GL_TEXTURE28_ARB 0x84DC -#define GL_TEXTURE29_ARB 0x84DD -#define GL_TEXTURE30_ARB 0x84DE -#define GL_TEXTURE31_ARB 0x84DF -#define GL_ACTIVE_TEXTURE_ARB 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 -#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 - -typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); -typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); - -#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB) -#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB) -#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB) -#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB) -#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB) -#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB) -#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB) -#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB) -#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB) -#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB) -#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB) -#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB) -#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB) -#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB) -#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB) -#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB) -#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB) -#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB) -#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB) -#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB) -#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB) -#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB) -#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB) -#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB) -#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB) -#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB) -#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB) -#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB) -#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB) -#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB) -#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB) -#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB) -#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB) -#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB) - -#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture) - -#endif /* GL_ARB_multitexture */ - -/* ------------------------- GL_ARB_occlusion_query ------------------------ */ - -#ifndef GL_ARB_occlusion_query -#define GL_ARB_occlusion_query 1 - -#define GL_QUERY_COUNTER_BITS_ARB 0x8864 -#define GL_CURRENT_QUERY_ARB 0x8865 -#define GL_QUERY_RESULT_ARB 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 -#define GL_SAMPLES_PASSED_ARB 0x8914 - -typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); -typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids); -typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids); -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params); -typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id); - -#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB) -#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB) -#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB) -#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB) -#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB) -#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB) -#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB) -#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB) - -#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query) - -#endif /* GL_ARB_occlusion_query */ - -/* ------------------------ GL_ARB_occlusion_query2 ------------------------ */ - -#ifndef GL_ARB_occlusion_query2 -#define GL_ARB_occlusion_query2 1 - -#define GL_ANY_SAMPLES_PASSED 0x8C2F - -#define GLEW_ARB_occlusion_query2 GLEW_GET_VAR(__GLEW_ARB_occlusion_query2) - -#endif /* GL_ARB_occlusion_query2 */ - -/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */ - -#ifndef GL_ARB_pixel_buffer_object -#define GL_ARB_pixel_buffer_object 1 - -#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB -#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF - -#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object) - -#endif /* GL_ARB_pixel_buffer_object */ - -/* ------------------------ GL_ARB_point_parameters ------------------------ */ - -#ifndef GL_ARB_point_parameters -#define GL_ARB_point_parameters 1 - -#define GL_POINT_SIZE_MIN_ARB 0x8126 -#define GL_POINT_SIZE_MAX_ARB 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 -#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 - -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat* params); - -#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB) -#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB) - -#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters) - -#endif /* GL_ARB_point_parameters */ - -/* -------------------------- GL_ARB_point_sprite -------------------------- */ - -#ifndef GL_ARB_point_sprite -#define GL_ARB_point_sprite 1 - -#define GL_POINT_SPRITE_ARB 0x8861 -#define GL_COORD_REPLACE_ARB 0x8862 - -#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite) - -#endif /* GL_ARB_point_sprite */ - -/* ------------------------ GL_ARB_provoking_vertex ------------------------ */ - -#ifndef GL_ARB_provoking_vertex -#define GL_ARB_provoking_vertex 1 - -#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C -#define GL_FIRST_VERTEX_CONVENTION 0x8E4D -#define GL_LAST_VERTEX_CONVENTION 0x8E4E -#define GL_PROVOKING_VERTEX 0x8E4F - -typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode); - -#define glProvokingVertex GLEW_GET_FUN(__glewProvokingVertex) - -#define GLEW_ARB_provoking_vertex GLEW_GET_VAR(__GLEW_ARB_provoking_vertex) - -#endif /* GL_ARB_provoking_vertex */ - -/* --------------------------- GL_ARB_robustness --------------------------- */ - -#ifndef GL_ARB_robustness -#define GL_ARB_robustness 1 - -#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 -#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 -#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 -#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 -#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 -#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 - -typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table); -typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img); -typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image); -typedef void (GLAPIENTRY * PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); -typedef void (GLAPIENTRY * PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble* v); -typedef void (GLAPIENTRY * PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat* v); -typedef void (GLAPIENTRY * PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint* v); -typedef void (GLAPIENTRY * PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); -typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat* values); -typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values); -typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values); -typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern); -typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span); -typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img); -typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params); -typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data); - -#define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB) -#define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB) -#define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB) -#define glGetnHistogramARB GLEW_GET_FUN(__glewGetnHistogramARB) -#define glGetnMapdvARB GLEW_GET_FUN(__glewGetnMapdvARB) -#define glGetnMapfvARB GLEW_GET_FUN(__glewGetnMapfvARB) -#define glGetnMapivARB GLEW_GET_FUN(__glewGetnMapivARB) -#define glGetnMinmaxARB GLEW_GET_FUN(__glewGetnMinmaxARB) -#define glGetnPixelMapfvARB GLEW_GET_FUN(__glewGetnPixelMapfvARB) -#define glGetnPixelMapuivARB GLEW_GET_FUN(__glewGetnPixelMapuivARB) -#define glGetnPixelMapusvARB GLEW_GET_FUN(__glewGetnPixelMapusvARB) -#define glGetnPolygonStippleARB GLEW_GET_FUN(__glewGetnPolygonStippleARB) -#define glGetnSeparableFilterARB GLEW_GET_FUN(__glewGetnSeparableFilterARB) -#define glGetnTexImageARB GLEW_GET_FUN(__glewGetnTexImageARB) -#define glGetnUniformdvARB GLEW_GET_FUN(__glewGetnUniformdvARB) -#define glGetnUniformfvARB GLEW_GET_FUN(__glewGetnUniformfvARB) -#define glGetnUniformivARB GLEW_GET_FUN(__glewGetnUniformivARB) -#define glGetnUniformuivARB GLEW_GET_FUN(__glewGetnUniformuivARB) -#define glReadnPixelsARB GLEW_GET_FUN(__glewReadnPixelsARB) - -#define GLEW_ARB_robustness GLEW_GET_VAR(__GLEW_ARB_robustness) - -#endif /* GL_ARB_robustness */ - -/* ------------------------- GL_ARB_sample_shading ------------------------- */ - -#ifndef GL_ARB_sample_shading -#define GL_ARB_sample_shading 1 - -#define GL_SAMPLE_SHADING_ARB 0x8C36 -#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 - -typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value); - -#define glMinSampleShadingARB GLEW_GET_FUN(__glewMinSampleShadingARB) - -#define GLEW_ARB_sample_shading GLEW_GET_VAR(__GLEW_ARB_sample_shading) - -#endif /* GL_ARB_sample_shading */ - -/* ------------------------- GL_ARB_sampler_objects ------------------------ */ - -#ifndef GL_ARB_sampler_objects -#define GL_ARB_sampler_objects 1 - -#define GL_SAMPLER_BINDING 0x8919 - -typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); -typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers); -typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers); -typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint* params); -typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler); -typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* params); - -#define glBindSampler GLEW_GET_FUN(__glewBindSampler) -#define glDeleteSamplers GLEW_GET_FUN(__glewDeleteSamplers) -#define glGenSamplers GLEW_GET_FUN(__glewGenSamplers) -#define glGetSamplerParameterIiv GLEW_GET_FUN(__glewGetSamplerParameterIiv) -#define glGetSamplerParameterIuiv GLEW_GET_FUN(__glewGetSamplerParameterIuiv) -#define glGetSamplerParameterfv GLEW_GET_FUN(__glewGetSamplerParameterfv) -#define glGetSamplerParameteriv GLEW_GET_FUN(__glewGetSamplerParameteriv) -#define glIsSampler GLEW_GET_FUN(__glewIsSampler) -#define glSamplerParameterIiv GLEW_GET_FUN(__glewSamplerParameterIiv) -#define glSamplerParameterIuiv GLEW_GET_FUN(__glewSamplerParameterIuiv) -#define glSamplerParameterf GLEW_GET_FUN(__glewSamplerParameterf) -#define glSamplerParameterfv GLEW_GET_FUN(__glewSamplerParameterfv) -#define glSamplerParameteri GLEW_GET_FUN(__glewSamplerParameteri) -#define glSamplerParameteriv GLEW_GET_FUN(__glewSamplerParameteriv) - -#define GLEW_ARB_sampler_objects GLEW_GET_VAR(__GLEW_ARB_sampler_objects) - -#endif /* GL_ARB_sampler_objects */ - -/* ------------------------ GL_ARB_seamless_cube_map ----------------------- */ - -#ifndef GL_ARB_seamless_cube_map -#define GL_ARB_seamless_cube_map 1 - -#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F - -#define GLEW_ARB_seamless_cube_map GLEW_GET_VAR(__GLEW_ARB_seamless_cube_map) - -#endif /* GL_ARB_seamless_cube_map */ - -/* --------------------- GL_ARB_separate_shader_objects -------------------- */ - -#ifndef GL_ARB_separate_shader_objects -#define GL_ARB_separate_shader_objects 1 - -#define GL_VERTEX_SHADER_BIT 0x00000001 -#define GL_FRAGMENT_SHADER_BIT 0x00000002 -#define GL_GEOMETRY_SHADER_BIT 0x00000004 -#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 -#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 -#define GL_PROGRAM_SEPARABLE 0x8258 -#define GL_ACTIVE_PROGRAM 0x8259 -#define GL_PROGRAM_PIPELINE_BINDING 0x825A -#define GL_ALL_SHADER_BITS 0xFFFFFFFF - -typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); -typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings); -typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); -typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint x, GLuint y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); -typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); - -#define glActiveShaderProgram GLEW_GET_FUN(__glewActiveShaderProgram) -#define glBindProgramPipeline GLEW_GET_FUN(__glewBindProgramPipeline) -#define glCreateShaderProgramv GLEW_GET_FUN(__glewCreateShaderProgramv) -#define glDeleteProgramPipelines GLEW_GET_FUN(__glewDeleteProgramPipelines) -#define glGenProgramPipelines GLEW_GET_FUN(__glewGenProgramPipelines) -#define glGetProgramPipelineInfoLog GLEW_GET_FUN(__glewGetProgramPipelineInfoLog) -#define glGetProgramPipelineiv GLEW_GET_FUN(__glewGetProgramPipelineiv) -#define glIsProgramPipeline GLEW_GET_FUN(__glewIsProgramPipeline) -#define glProgramUniform1d GLEW_GET_FUN(__glewProgramUniform1d) -#define glProgramUniform1dv GLEW_GET_FUN(__glewProgramUniform1dv) -#define glProgramUniform1f GLEW_GET_FUN(__glewProgramUniform1f) -#define glProgramUniform1fv GLEW_GET_FUN(__glewProgramUniform1fv) -#define glProgramUniform1i GLEW_GET_FUN(__glewProgramUniform1i) -#define glProgramUniform1iv GLEW_GET_FUN(__glewProgramUniform1iv) -#define glProgramUniform1ui GLEW_GET_FUN(__glewProgramUniform1ui) -#define glProgramUniform1uiv GLEW_GET_FUN(__glewProgramUniform1uiv) -#define glProgramUniform2d GLEW_GET_FUN(__glewProgramUniform2d) -#define glProgramUniform2dv GLEW_GET_FUN(__glewProgramUniform2dv) -#define glProgramUniform2f GLEW_GET_FUN(__glewProgramUniform2f) -#define glProgramUniform2fv GLEW_GET_FUN(__glewProgramUniform2fv) -#define glProgramUniform2i GLEW_GET_FUN(__glewProgramUniform2i) -#define glProgramUniform2iv GLEW_GET_FUN(__glewProgramUniform2iv) -#define glProgramUniform2ui GLEW_GET_FUN(__glewProgramUniform2ui) -#define glProgramUniform2uiv GLEW_GET_FUN(__glewProgramUniform2uiv) -#define glProgramUniform3d GLEW_GET_FUN(__glewProgramUniform3d) -#define glProgramUniform3dv GLEW_GET_FUN(__glewProgramUniform3dv) -#define glProgramUniform3f GLEW_GET_FUN(__glewProgramUniform3f) -#define glProgramUniform3fv GLEW_GET_FUN(__glewProgramUniform3fv) -#define glProgramUniform3i GLEW_GET_FUN(__glewProgramUniform3i) -#define glProgramUniform3iv GLEW_GET_FUN(__glewProgramUniform3iv) -#define glProgramUniform3ui GLEW_GET_FUN(__glewProgramUniform3ui) -#define glProgramUniform3uiv GLEW_GET_FUN(__glewProgramUniform3uiv) -#define glProgramUniform4d GLEW_GET_FUN(__glewProgramUniform4d) -#define glProgramUniform4dv GLEW_GET_FUN(__glewProgramUniform4dv) -#define glProgramUniform4f GLEW_GET_FUN(__glewProgramUniform4f) -#define glProgramUniform4fv GLEW_GET_FUN(__glewProgramUniform4fv) -#define glProgramUniform4i GLEW_GET_FUN(__glewProgramUniform4i) -#define glProgramUniform4iv GLEW_GET_FUN(__glewProgramUniform4iv) -#define glProgramUniform4ui GLEW_GET_FUN(__glewProgramUniform4ui) -#define glProgramUniform4uiv GLEW_GET_FUN(__glewProgramUniform4uiv) -#define glProgramUniformMatrix2dv GLEW_GET_FUN(__glewProgramUniformMatrix2dv) -#define glProgramUniformMatrix2fv GLEW_GET_FUN(__glewProgramUniformMatrix2fv) -#define glProgramUniformMatrix2x3dv GLEW_GET_FUN(__glewProgramUniformMatrix2x3dv) -#define glProgramUniformMatrix2x3fv GLEW_GET_FUN(__glewProgramUniformMatrix2x3fv) -#define glProgramUniformMatrix2x4dv GLEW_GET_FUN(__glewProgramUniformMatrix2x4dv) -#define glProgramUniformMatrix2x4fv GLEW_GET_FUN(__glewProgramUniformMatrix2x4fv) -#define glProgramUniformMatrix3dv GLEW_GET_FUN(__glewProgramUniformMatrix3dv) -#define glProgramUniformMatrix3fv GLEW_GET_FUN(__glewProgramUniformMatrix3fv) -#define glProgramUniformMatrix3x2dv GLEW_GET_FUN(__glewProgramUniformMatrix3x2dv) -#define glProgramUniformMatrix3x2fv GLEW_GET_FUN(__glewProgramUniformMatrix3x2fv) -#define glProgramUniformMatrix3x4dv GLEW_GET_FUN(__glewProgramUniformMatrix3x4dv) -#define glProgramUniformMatrix3x4fv GLEW_GET_FUN(__glewProgramUniformMatrix3x4fv) -#define glProgramUniformMatrix4dv GLEW_GET_FUN(__glewProgramUniformMatrix4dv) -#define glProgramUniformMatrix4fv GLEW_GET_FUN(__glewProgramUniformMatrix4fv) -#define glProgramUniformMatrix4x2dv GLEW_GET_FUN(__glewProgramUniformMatrix4x2dv) -#define glProgramUniformMatrix4x2fv GLEW_GET_FUN(__glewProgramUniformMatrix4x2fv) -#define glProgramUniformMatrix4x3dv GLEW_GET_FUN(__glewProgramUniformMatrix4x3dv) -#define glProgramUniformMatrix4x3fv GLEW_GET_FUN(__glewProgramUniformMatrix4x3fv) -#define glUseProgramStages GLEW_GET_FUN(__glewUseProgramStages) -#define glValidateProgramPipeline GLEW_GET_FUN(__glewValidateProgramPipeline) - -#define GLEW_ARB_separate_shader_objects GLEW_GET_VAR(__GLEW_ARB_separate_shader_objects) - -#endif /* GL_ARB_separate_shader_objects */ - -/* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */ - -#ifndef GL_ARB_shader_bit_encoding -#define GL_ARB_shader_bit_encoding 1 - -#define GLEW_ARB_shader_bit_encoding GLEW_GET_VAR(__GLEW_ARB_shader_bit_encoding) - -#endif /* GL_ARB_shader_bit_encoding */ - -/* ------------------------- GL_ARB_shader_objects ------------------------- */ - -#ifndef GL_ARB_shader_objects -#define GL_ARB_shader_objects 1 - -#define GL_PROGRAM_OBJECT_ARB 0x8B40 -#define GL_SHADER_OBJECT_ARB 0x8B48 -#define GL_OBJECT_TYPE_ARB 0x8B4E -#define GL_OBJECT_SUBTYPE_ARB 0x8B4F -#define GL_FLOAT_VEC2_ARB 0x8B50 -#define GL_FLOAT_VEC3_ARB 0x8B51 -#define GL_FLOAT_VEC4_ARB 0x8B52 -#define GL_INT_VEC2_ARB 0x8B53 -#define GL_INT_VEC3_ARB 0x8B54 -#define GL_INT_VEC4_ARB 0x8B55 -#define GL_BOOL_ARB 0x8B56 -#define GL_BOOL_VEC2_ARB 0x8B57 -#define GL_BOOL_VEC3_ARB 0x8B58 -#define GL_BOOL_VEC4_ARB 0x8B59 -#define GL_FLOAT_MAT2_ARB 0x8B5A -#define GL_FLOAT_MAT3_ARB 0x8B5B -#define GL_FLOAT_MAT4_ARB 0x8B5C -#define GL_SAMPLER_1D_ARB 0x8B5D -#define GL_SAMPLER_2D_ARB 0x8B5E -#define GL_SAMPLER_3D_ARB 0x8B5F -#define GL_SAMPLER_CUBE_ARB 0x8B60 -#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 -#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 -#define GL_SAMPLER_2D_RECT_ARB 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 -#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 -#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 -#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 -#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 -#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 -#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 -#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 -#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 -#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 - -typedef char GLcharARB; -typedef unsigned int GLhandleARB; - -typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); -typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); -typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); -typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); -typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); -typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); -typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj); -typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname); -typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog); -typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source); -typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params); -typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); -typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length); -typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); -typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); -typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); -typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); -typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); -typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); -typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); - -#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB) -#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB) -#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB) -#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB) -#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB) -#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB) -#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB) -#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB) -#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB) -#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB) -#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB) -#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB) -#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB) -#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB) -#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB) -#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB) -#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB) -#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB) -#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB) -#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB) -#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB) -#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB) -#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB) -#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB) -#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB) -#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB) -#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB) -#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB) -#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB) -#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB) -#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB) -#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB) -#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB) -#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB) -#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB) -#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB) -#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB) -#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB) -#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB) - -#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects) - -#endif /* GL_ARB_shader_objects */ - -/* ------------------------ GL_ARB_shader_precision ------------------------ */ - -#ifndef GL_ARB_shader_precision -#define GL_ARB_shader_precision 1 - -#define GLEW_ARB_shader_precision GLEW_GET_VAR(__GLEW_ARB_shader_precision) - -#endif /* GL_ARB_shader_precision */ - -/* ---------------------- GL_ARB_shader_stencil_export --------------------- */ - -#ifndef GL_ARB_shader_stencil_export -#define GL_ARB_shader_stencil_export 1 - -#define GLEW_ARB_shader_stencil_export GLEW_GET_VAR(__GLEW_ARB_shader_stencil_export) - -#endif /* GL_ARB_shader_stencil_export */ - -/* ------------------------ GL_ARB_shader_subroutine ----------------------- */ - -#ifndef GL_ARB_shader_subroutine -#define GL_ARB_shader_subroutine 1 - -#define GL_ACTIVE_SUBROUTINES 0x8DE5 -#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 -#define GL_MAX_SUBROUTINES 0x8DE7 -#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 -#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 -#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 -#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 -#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A -#define GL_COMPATIBLE_SUBROUTINES 0x8E4B - -typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); -typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); -typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values); -typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name); -typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params); -typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices); - -#define glGetActiveSubroutineName GLEW_GET_FUN(__glewGetActiveSubroutineName) -#define glGetActiveSubroutineUniformName GLEW_GET_FUN(__glewGetActiveSubroutineUniformName) -#define glGetActiveSubroutineUniformiv GLEW_GET_FUN(__glewGetActiveSubroutineUniformiv) -#define glGetProgramStageiv GLEW_GET_FUN(__glewGetProgramStageiv) -#define glGetSubroutineIndex GLEW_GET_FUN(__glewGetSubroutineIndex) -#define glGetSubroutineUniformLocation GLEW_GET_FUN(__glewGetSubroutineUniformLocation) -#define glGetUniformSubroutineuiv GLEW_GET_FUN(__glewGetUniformSubroutineuiv) -#define glUniformSubroutinesuiv GLEW_GET_FUN(__glewUniformSubroutinesuiv) - -#define GLEW_ARB_shader_subroutine GLEW_GET_VAR(__GLEW_ARB_shader_subroutine) - -#endif /* GL_ARB_shader_subroutine */ - -/* ----------------------- GL_ARB_shader_texture_lod ----------------------- */ - -#ifndef GL_ARB_shader_texture_lod -#define GL_ARB_shader_texture_lod 1 - -#define GLEW_ARB_shader_texture_lod GLEW_GET_VAR(__GLEW_ARB_shader_texture_lod) - -#endif /* GL_ARB_shader_texture_lod */ - -/* ---------------------- GL_ARB_shading_language_100 ---------------------- */ - -#ifndef GL_ARB_shading_language_100 -#define GL_ARB_shading_language_100 1 - -#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C - -#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100) - -#endif /* GL_ARB_shading_language_100 */ - -/* -------------------- GL_ARB_shading_language_include -------------------- */ - -#ifndef GL_ARB_shading_language_include -#define GL_ARB_shading_language_include 1 - -#define GL_SHADER_INCLUDE_ARB 0x8DAE -#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 -#define GL_NAMED_STRING_TYPE_ARB 0x8DEA - -typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length); -typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name); -typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string); -typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params); -typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name); -typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string); - -#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB) -#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB) -#define glGetNamedStringARB GLEW_GET_FUN(__glewGetNamedStringARB) -#define glGetNamedStringivARB GLEW_GET_FUN(__glewGetNamedStringivARB) -#define glIsNamedStringARB GLEW_GET_FUN(__glewIsNamedStringARB) -#define glNamedStringARB GLEW_GET_FUN(__glewNamedStringARB) - -#define GLEW_ARB_shading_language_include GLEW_GET_VAR(__GLEW_ARB_shading_language_include) - -#endif /* GL_ARB_shading_language_include */ - -/* ----------------------------- GL_ARB_shadow ----------------------------- */ - -#ifndef GL_ARB_shadow -#define GL_ARB_shadow 1 - -#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C -#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D -#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E - -#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow) - -#endif /* GL_ARB_shadow */ - -/* ------------------------- GL_ARB_shadow_ambient ------------------------- */ - -#ifndef GL_ARB_shadow_ambient -#define GL_ARB_shadow_ambient 1 - -#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF - -#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient) - -#endif /* GL_ARB_shadow_ambient */ - -/* ------------------------------ GL_ARB_sync ------------------------------ */ - -#ifndef GL_ARB_sync -#define GL_ARB_sync 1 - -#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 -#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 -#define GL_OBJECT_TYPE 0x9112 -#define GL_SYNC_CONDITION 0x9113 -#define GL_SYNC_STATUS 0x9114 -#define GL_SYNC_FLAGS 0x9115 -#define GL_SYNC_FENCE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 -#define GL_UNSIGNALED 0x9118 -#define GL_SIGNALED 0x9119 -#define GL_ALREADY_SIGNALED 0x911A -#define GL_TIMEOUT_EXPIRED 0x911B -#define GL_CONDITION_SATISFIED 0x911C -#define GL_WAIT_FAILED 0x911D -#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF - -typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); -typedef void (GLAPIENTRY * PFNGLDELETESYNCPROC) (GLsync GLsync); -typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags); -typedef void (GLAPIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64* params); -typedef void (GLAPIENTRY * PFNGLGETSYNCIVPROC) (GLsync GLsync,GLenum pname,GLsizei bufSize,GLsizei* length, GLint *values); -typedef GLboolean (GLAPIENTRY * PFNGLISSYNCPROC) (GLsync GLsync); -typedef void (GLAPIENTRY * PFNGLWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); - -#define glClientWaitSync GLEW_GET_FUN(__glewClientWaitSync) -#define glDeleteSync GLEW_GET_FUN(__glewDeleteSync) -#define glFenceSync GLEW_GET_FUN(__glewFenceSync) -#define glGetInteger64v GLEW_GET_FUN(__glewGetInteger64v) -#define glGetSynciv GLEW_GET_FUN(__glewGetSynciv) -#define glIsSync GLEW_GET_FUN(__glewIsSync) -#define glWaitSync GLEW_GET_FUN(__glewWaitSync) - -#define GLEW_ARB_sync GLEW_GET_VAR(__GLEW_ARB_sync) - -#endif /* GL_ARB_sync */ - -/* ----------------------- GL_ARB_tessellation_shader ---------------------- */ - -#ifndef GL_ARB_tessellation_shader -#define GL_ARB_tessellation_shader 1 - -#define GL_PATCHES 0xE -#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 -#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C -#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D -#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E -#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F -#define GL_PATCH_VERTICES 0x8E72 -#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 -#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 -#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 -#define GL_TESS_GEN_MODE 0x8E76 -#define GL_TESS_GEN_SPACING 0x8E77 -#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 -#define GL_TESS_GEN_POINT_MODE 0x8E79 -#define GL_ISOLINES 0x8E7A -#define GL_FRACTIONAL_ODD 0x8E7B -#define GL_FRACTIONAL_EVEN 0x8E7C -#define GL_MAX_PATCH_VERTICES 0x8E7D -#define GL_MAX_TESS_GEN_LEVEL 0x8E7E -#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F -#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 -#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 -#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 -#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 -#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 -#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 -#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 -#define GL_TESS_EVALUATION_SHADER 0x8E87 -#define GL_TESS_CONTROL_SHADER 0x8E88 -#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 -#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A - -typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat* values); -typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); - -#define glPatchParameterfv GLEW_GET_FUN(__glewPatchParameterfv) -#define glPatchParameteri GLEW_GET_FUN(__glewPatchParameteri) - -#define GLEW_ARB_tessellation_shader GLEW_GET_VAR(__GLEW_ARB_tessellation_shader) - -#endif /* GL_ARB_tessellation_shader */ - -/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */ - -#ifndef GL_ARB_texture_border_clamp -#define GL_ARB_texture_border_clamp 1 - -#define GL_CLAMP_TO_BORDER_ARB 0x812D - -#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp) - -#endif /* GL_ARB_texture_border_clamp */ - -/* ---------------------- GL_ARB_texture_buffer_object --------------------- */ - -#ifndef GL_ARB_texture_buffer_object -#define GL_ARB_texture_buffer_object 1 - -#define GL_TEXTURE_BUFFER_ARB 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D -#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E - -typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); - -#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB) - -#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object) - -#endif /* GL_ARB_texture_buffer_object */ - -/* ------------------- GL_ARB_texture_buffer_object_rgb32 ------------------ */ - -#ifndef GL_ARB_texture_buffer_object_rgb32 -#define GL_ARB_texture_buffer_object_rgb32 1 - -#define GLEW_ARB_texture_buffer_object_rgb32 GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object_rgb32) - -#endif /* GL_ARB_texture_buffer_object_rgb32 */ - -/* ----------------------- GL_ARB_texture_compression ---------------------- */ - -#ifndef GL_ARB_texture_compression -#define GL_ARB_texture_compression 1 - -#define GL_COMPRESSED_ALPHA_ARB 0x84E9 -#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB -#define GL_COMPRESSED_INTENSITY_ARB 0x84EC -#define GL_COMPRESSED_RGB_ARB 0x84ED -#define GL_COMPRESSED_RGBA_ARB 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF -#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 -#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 - -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img); - -#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) -#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) -#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB) -#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB) -#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB) -#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB) -#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB) - -#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression) - -#endif /* GL_ARB_texture_compression */ - -/* -------------------- GL_ARB_texture_compression_bptc -------------------- */ - -#ifndef GL_ARB_texture_compression_bptc -#define GL_ARB_texture_compression_bptc 1 - -#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C -#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D -#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E -#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F - -#define GLEW_ARB_texture_compression_bptc GLEW_GET_VAR(__GLEW_ARB_texture_compression_bptc) - -#endif /* GL_ARB_texture_compression_bptc */ - -/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */ - -#ifndef GL_ARB_texture_compression_rgtc -#define GL_ARB_texture_compression_rgtc 1 - -#define GL_COMPRESSED_RED_RGTC1 0x8DBB -#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define GL_COMPRESSED_RG_RGTC2 0x8DBD -#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE - -#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc) - -#endif /* GL_ARB_texture_compression_rgtc */ - -/* ------------------------ GL_ARB_texture_cube_map ------------------------ */ - -#ifndef GL_ARB_texture_cube_map -#define GL_ARB_texture_cube_map 1 - -#define GL_NORMAL_MAP_ARB 0x8511 -#define GL_REFLECTION_MAP_ARB 0x8512 -#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C - -#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map) - -#endif /* GL_ARB_texture_cube_map */ - -/* --------------------- GL_ARB_texture_cube_map_array --------------------- */ - -#ifndef GL_ARB_texture_cube_map_array -#define GL_ARB_texture_cube_map_array 1 - -#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B -#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F - -#define GLEW_ARB_texture_cube_map_array GLEW_GET_VAR(__GLEW_ARB_texture_cube_map_array) - -#endif /* GL_ARB_texture_cube_map_array */ - -/* ------------------------- GL_ARB_texture_env_add ------------------------ */ - -#ifndef GL_ARB_texture_env_add -#define GL_ARB_texture_env_add 1 - -#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add) - -#endif /* GL_ARB_texture_env_add */ - -/* ----------------------- GL_ARB_texture_env_combine ---------------------- */ - -#ifndef GL_ARB_texture_env_combine -#define GL_ARB_texture_env_combine 1 - -#define GL_SUBTRACT_ARB 0x84E7 -#define GL_COMBINE_ARB 0x8570 -#define GL_COMBINE_RGB_ARB 0x8571 -#define GL_COMBINE_ALPHA_ARB 0x8572 -#define GL_RGB_SCALE_ARB 0x8573 -#define GL_ADD_SIGNED_ARB 0x8574 -#define GL_INTERPOLATE_ARB 0x8575 -#define GL_CONSTANT_ARB 0x8576 -#define GL_PRIMARY_COLOR_ARB 0x8577 -#define GL_PREVIOUS_ARB 0x8578 -#define GL_SOURCE0_RGB_ARB 0x8580 -#define GL_SOURCE1_RGB_ARB 0x8581 -#define GL_SOURCE2_RGB_ARB 0x8582 -#define GL_SOURCE0_ALPHA_ARB 0x8588 -#define GL_SOURCE1_ALPHA_ARB 0x8589 -#define GL_SOURCE2_ALPHA_ARB 0x858A -#define GL_OPERAND0_RGB_ARB 0x8590 -#define GL_OPERAND1_RGB_ARB 0x8591 -#define GL_OPERAND2_RGB_ARB 0x8592 -#define GL_OPERAND0_ALPHA_ARB 0x8598 -#define GL_OPERAND1_ALPHA_ARB 0x8599 -#define GL_OPERAND2_ALPHA_ARB 0x859A - -#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine) - -#endif /* GL_ARB_texture_env_combine */ - -/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */ - -#ifndef GL_ARB_texture_env_crossbar -#define GL_ARB_texture_env_crossbar 1 - -#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar) - -#endif /* GL_ARB_texture_env_crossbar */ - -/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */ - -#ifndef GL_ARB_texture_env_dot3 -#define GL_ARB_texture_env_dot3 1 - -#define GL_DOT3_RGB_ARB 0x86AE -#define GL_DOT3_RGBA_ARB 0x86AF - -#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3) - -#endif /* GL_ARB_texture_env_dot3 */ - -/* -------------------------- GL_ARB_texture_float ------------------------- */ - -#ifndef GL_ARB_texture_float -#define GL_ARB_texture_float 1 - -#define GL_RGBA32F_ARB 0x8814 -#define GL_RGB32F_ARB 0x8815 -#define GL_ALPHA32F_ARB 0x8816 -#define GL_INTENSITY32F_ARB 0x8817 -#define GL_LUMINANCE32F_ARB 0x8818 -#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 -#define GL_RGBA16F_ARB 0x881A -#define GL_RGB16F_ARB 0x881B -#define GL_ALPHA16F_ARB 0x881C -#define GL_INTENSITY16F_ARB 0x881D -#define GL_LUMINANCE16F_ARB 0x881E -#define GL_LUMINANCE_ALPHA16F_ARB 0x881F -#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 -#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 -#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 -#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 -#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 -#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 -#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 -#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 - -#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float) - -#endif /* GL_ARB_texture_float */ - -/* ------------------------- GL_ARB_texture_gather ------------------------- */ - -#ifndef GL_ARB_texture_gather -#define GL_ARB_texture_gather 1 - -#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E -#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F -#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F - -#define GLEW_ARB_texture_gather GLEW_GET_VAR(__GLEW_ARB_texture_gather) - -#endif /* GL_ARB_texture_gather */ - -/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */ - -#ifndef GL_ARB_texture_mirrored_repeat -#define GL_ARB_texture_mirrored_repeat 1 - -#define GL_MIRRORED_REPEAT_ARB 0x8370 - -#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat) - -#endif /* GL_ARB_texture_mirrored_repeat */ - -/* ----------------------- GL_ARB_texture_multisample ---------------------- */ - -#ifndef GL_ARB_texture_multisample -#define GL_ARB_texture_multisample 1 - -#define GL_SAMPLE_POSITION 0x8E50 -#define GL_SAMPLE_MASK 0x8E51 -#define GL_SAMPLE_MASK_VALUE 0x8E52 -#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 -#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 -#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 -#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 -#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 -#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 -#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 -#define GL_TEXTURE_SAMPLES 0x9106 -#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 -#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 -#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A -#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B -#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D -#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E -#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F -#define GL_MAX_INTEGER_SAMPLES 0x9110 - -typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val); -typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); - -#define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv) -#define glSampleMaski GLEW_GET_FUN(__glewSampleMaski) -#define glTexImage2DMultisample GLEW_GET_FUN(__glewTexImage2DMultisample) -#define glTexImage3DMultisample GLEW_GET_FUN(__glewTexImage3DMultisample) - -#define GLEW_ARB_texture_multisample GLEW_GET_VAR(__GLEW_ARB_texture_multisample) - -#endif /* GL_ARB_texture_multisample */ - -/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */ - -#ifndef GL_ARB_texture_non_power_of_two -#define GL_ARB_texture_non_power_of_two 1 - -#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two) - -#endif /* GL_ARB_texture_non_power_of_two */ - -/* ------------------------ GL_ARB_texture_query_lod ----------------------- */ - -#ifndef GL_ARB_texture_query_lod -#define GL_ARB_texture_query_lod 1 - -#define GLEW_ARB_texture_query_lod GLEW_GET_VAR(__GLEW_ARB_texture_query_lod) - -#endif /* GL_ARB_texture_query_lod */ - -/* ------------------------ GL_ARB_texture_rectangle ----------------------- */ - -#ifndef GL_ARB_texture_rectangle -#define GL_ARB_texture_rectangle 1 - -#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 -#define GL_SAMPLER_2D_RECT_ARB 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 - -#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle) - -#endif /* GL_ARB_texture_rectangle */ - -/* --------------------------- GL_ARB_texture_rg --------------------------- */ - -#ifndef GL_ARB_texture_rg -#define GL_ARB_texture_rg 1 - -#define GL_RED 0x1903 -#define GL_COMPRESSED_RED 0x8225 -#define GL_COMPRESSED_RG 0x8226 -#define GL_RG 0x8227 -#define GL_RG_INTEGER 0x8228 -#define GL_R8 0x8229 -#define GL_R16 0x822A -#define GL_RG8 0x822B -#define GL_RG16 0x822C -#define GL_R16F 0x822D -#define GL_R32F 0x822E -#define GL_RG16F 0x822F -#define GL_RG32F 0x8230 -#define GL_R8I 0x8231 -#define GL_R8UI 0x8232 -#define GL_R16I 0x8233 -#define GL_R16UI 0x8234 -#define GL_R32I 0x8235 -#define GL_R32UI 0x8236 -#define GL_RG8I 0x8237 -#define GL_RG8UI 0x8238 -#define GL_RG16I 0x8239 -#define GL_RG16UI 0x823A -#define GL_RG32I 0x823B -#define GL_RG32UI 0x823C - -#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg) - -#endif /* GL_ARB_texture_rg */ - -/* ----------------------- GL_ARB_texture_rgb10_a2ui ----------------------- */ - -#ifndef GL_ARB_texture_rgb10_a2ui -#define GL_ARB_texture_rgb10_a2ui 1 - -#define GL_RGB10_A2UI 0x906F - -#define GLEW_ARB_texture_rgb10_a2ui GLEW_GET_VAR(__GLEW_ARB_texture_rgb10_a2ui) - -#endif /* GL_ARB_texture_rgb10_a2ui */ - -/* ------------------------- GL_ARB_texture_swizzle ------------------------ */ - -#ifndef GL_ARB_texture_swizzle -#define GL_ARB_texture_swizzle 1 - -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 - -#define GLEW_ARB_texture_swizzle GLEW_GET_VAR(__GLEW_ARB_texture_swizzle) - -#endif /* GL_ARB_texture_swizzle */ - -/* --------------------------- GL_ARB_timer_query -------------------------- */ - -#ifndef GL_ARB_timer_query -#define GL_ARB_timer_query 1 - -#define GL_TIME_ELAPSED 0x88BF -#define GL_TIMESTAMP 0x8E28 - -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params); -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params); -typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); - -#define glGetQueryObjecti64v GLEW_GET_FUN(__glewGetQueryObjecti64v) -#define glGetQueryObjectui64v GLEW_GET_FUN(__glewGetQueryObjectui64v) -#define glQueryCounter GLEW_GET_FUN(__glewQueryCounter) - -#define GLEW_ARB_timer_query GLEW_GET_VAR(__GLEW_ARB_timer_query) - -#endif /* GL_ARB_timer_query */ - -/* ----------------------- GL_ARB_transform_feedback2 ---------------------- */ - -#ifndef GL_ARB_transform_feedback2 -#define GL_ARB_transform_feedback2 1 - -#define GL_TRANSFORM_FEEDBACK 0x8E22 -#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 -#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 - -typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); -typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids); -typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); -typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); -typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); -typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); - -#define glBindTransformFeedback GLEW_GET_FUN(__glewBindTransformFeedback) -#define glDeleteTransformFeedbacks GLEW_GET_FUN(__glewDeleteTransformFeedbacks) -#define glDrawTransformFeedback GLEW_GET_FUN(__glewDrawTransformFeedback) -#define glGenTransformFeedbacks GLEW_GET_FUN(__glewGenTransformFeedbacks) -#define glIsTransformFeedback GLEW_GET_FUN(__glewIsTransformFeedback) -#define glPauseTransformFeedback GLEW_GET_FUN(__glewPauseTransformFeedback) -#define glResumeTransformFeedback GLEW_GET_FUN(__glewResumeTransformFeedback) - -#define GLEW_ARB_transform_feedback2 GLEW_GET_VAR(__GLEW_ARB_transform_feedback2) - -#endif /* GL_ARB_transform_feedback2 */ - -/* ----------------------- GL_ARB_transform_feedback3 ---------------------- */ - -#ifndef GL_ARB_transform_feedback3 -#define GL_ARB_transform_feedback3 1 - -#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 -#define GL_MAX_VERTEX_STREAMS 0x8E71 - -typedef void (GLAPIENTRY * PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); -typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); -typedef void (GLAPIENTRY * PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); -typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); - -#define glBeginQueryIndexed GLEW_GET_FUN(__glewBeginQueryIndexed) -#define glDrawTransformFeedbackStream GLEW_GET_FUN(__glewDrawTransformFeedbackStream) -#define glEndQueryIndexed GLEW_GET_FUN(__glewEndQueryIndexed) -#define glGetQueryIndexediv GLEW_GET_FUN(__glewGetQueryIndexediv) - -#define GLEW_ARB_transform_feedback3 GLEW_GET_VAR(__GLEW_ARB_transform_feedback3) - -#endif /* GL_ARB_transform_feedback3 */ - -/* ------------------------ GL_ARB_transpose_matrix ------------------------ */ - -#ifndef GL_ARB_transpose_matrix -#define GL_ARB_transpose_matrix 1 - -#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 -#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 -#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 -#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 - -typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); -typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); -typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); -typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); - -#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB) -#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB) -#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB) -#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB) - -#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix) - -#endif /* GL_ARB_transpose_matrix */ - -/* ---------------------- GL_ARB_uniform_buffer_object --------------------- */ - -#ifndef GL_ARB_uniform_buffer_object -#define GL_ARB_uniform_buffer_object 1 - -#define GL_UNIFORM_BUFFER 0x8A11 -#define GL_UNIFORM_BUFFER_BINDING 0x8A28 -#define GL_UNIFORM_BUFFER_START 0x8A29 -#define GL_UNIFORM_BUFFER_SIZE 0x8A2A -#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B -#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C -#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D -#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E -#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F -#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 -#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 -#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 -#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 -#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 -#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 -#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 -#define GL_UNIFORM_TYPE 0x8A37 -#define GL_UNIFORM_SIZE 0x8A38 -#define GL_UNIFORM_NAME_LENGTH 0x8A39 -#define GL_UNIFORM_BLOCK_INDEX 0x8A3A -#define GL_UNIFORM_OFFSET 0x8A3B -#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C -#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D -#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E -#define GL_UNIFORM_BLOCK_BINDING 0x8A3F -#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 -#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 -#define GL_INVALID_INDEX 0xFFFFFFFF - -typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data); -typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices); -typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); - -#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) -#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange) -#define glGetActiveUniformBlockName GLEW_GET_FUN(__glewGetActiveUniformBlockName) -#define glGetActiveUniformBlockiv GLEW_GET_FUN(__glewGetActiveUniformBlockiv) -#define glGetActiveUniformName GLEW_GET_FUN(__glewGetActiveUniformName) -#define glGetActiveUniformsiv GLEW_GET_FUN(__glewGetActiveUniformsiv) -#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v) -#define glGetUniformBlockIndex GLEW_GET_FUN(__glewGetUniformBlockIndex) -#define glGetUniformIndices GLEW_GET_FUN(__glewGetUniformIndices) -#define glUniformBlockBinding GLEW_GET_FUN(__glewUniformBlockBinding) - -#define GLEW_ARB_uniform_buffer_object GLEW_GET_VAR(__GLEW_ARB_uniform_buffer_object) - -#endif /* GL_ARB_uniform_buffer_object */ - -/* ------------------------ GL_ARB_vertex_array_bgra ----------------------- */ - -#ifndef GL_ARB_vertex_array_bgra -#define GL_ARB_vertex_array_bgra 1 - -#define GL_BGRA 0x80E1 - -#define GLEW_ARB_vertex_array_bgra GLEW_GET_VAR(__GLEW_ARB_vertex_array_bgra) - -#endif /* GL_ARB_vertex_array_bgra */ - -/* ----------------------- GL_ARB_vertex_array_object ---------------------- */ - -#ifndef GL_ARB_vertex_array_object -#define GL_ARB_vertex_array_object 1 - -#define GL_VERTEX_ARRAY_BINDING 0x85B5 - -typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array); -typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); -typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); -typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array); - -#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray) -#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays) -#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays) -#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray) - -#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object) - -#endif /* GL_ARB_vertex_array_object */ - -/* ----------------------- GL_ARB_vertex_attrib_64bit ---------------------- */ - -#ifndef GL_ARB_vertex_attrib_64bit -#define GL_ARB_vertex_attrib_64bit 1 - -#define GL_DOUBLE_MAT2 0x8F46 -#define GL_DOUBLE_MAT3 0x8F47 -#define GL_DOUBLE_MAT4 0x8F48 -#define GL_DOUBLE_VEC2 0x8FFC -#define GL_DOUBLE_VEC3 0x8FFD -#define GL_DOUBLE_VEC4 0x8FFE - -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); - -#define glGetVertexAttribLdv GLEW_GET_FUN(__glewGetVertexAttribLdv) -#define glVertexAttribL1d GLEW_GET_FUN(__glewVertexAttribL1d) -#define glVertexAttribL1dv GLEW_GET_FUN(__glewVertexAttribL1dv) -#define glVertexAttribL2d GLEW_GET_FUN(__glewVertexAttribL2d) -#define glVertexAttribL2dv GLEW_GET_FUN(__glewVertexAttribL2dv) -#define glVertexAttribL3d GLEW_GET_FUN(__glewVertexAttribL3d) -#define glVertexAttribL3dv GLEW_GET_FUN(__glewVertexAttribL3dv) -#define glVertexAttribL4d GLEW_GET_FUN(__glewVertexAttribL4d) -#define glVertexAttribL4dv GLEW_GET_FUN(__glewVertexAttribL4dv) -#define glVertexAttribLPointer GLEW_GET_FUN(__glewVertexAttribLPointer) - -#define GLEW_ARB_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_64bit) - -#endif /* GL_ARB_vertex_attrib_64bit */ - -/* -------------------------- GL_ARB_vertex_blend -------------------------- */ - -#ifndef GL_ARB_vertex_blend -#define GL_ARB_vertex_blend 1 - -#define GL_MODELVIEW0_ARB 0x1700 -#define GL_MODELVIEW1_ARB 0x850A -#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 -#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 -#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 -#define GL_VERTEX_BLEND_ARB 0x86A7 -#define GL_CURRENT_WEIGHT_ARB 0x86A8 -#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 -#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA -#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB -#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC -#define GL_WEIGHT_ARRAY_ARB 0x86AD -#define GL_MODELVIEW2_ARB 0x8722 -#define GL_MODELVIEW3_ARB 0x8723 -#define GL_MODELVIEW4_ARB 0x8724 -#define GL_MODELVIEW5_ARB 0x8725 -#define GL_MODELVIEW6_ARB 0x8726 -#define GL_MODELVIEW7_ARB 0x8727 -#define GL_MODELVIEW8_ARB 0x8728 -#define GL_MODELVIEW9_ARB 0x8729 -#define GL_MODELVIEW10_ARB 0x872A -#define GL_MODELVIEW11_ARB 0x872B -#define GL_MODELVIEW12_ARB 0x872C -#define GL_MODELVIEW13_ARB 0x872D -#define GL_MODELVIEW14_ARB 0x872E -#define GL_MODELVIEW15_ARB 0x872F -#define GL_MODELVIEW16_ARB 0x8730 -#define GL_MODELVIEW17_ARB 0x8731 -#define GL_MODELVIEW18_ARB 0x8732 -#define GL_MODELVIEW19_ARB 0x8733 -#define GL_MODELVIEW20_ARB 0x8734 -#define GL_MODELVIEW21_ARB 0x8735 -#define GL_MODELVIEW22_ARB 0x8736 -#define GL_MODELVIEW23_ARB 0x8737 -#define GL_MODELVIEW24_ARB 0x8738 -#define GL_MODELVIEW25_ARB 0x8739 -#define GL_MODELVIEW26_ARB 0x873A -#define GL_MODELVIEW27_ARB 0x873B -#define GL_MODELVIEW28_ARB 0x873C -#define GL_MODELVIEW29_ARB 0x873D -#define GL_MODELVIEW30_ARB 0x873E -#define GL_MODELVIEW31_ARB 0x873F - -typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count); -typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights); -typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights); - -#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB) -#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB) -#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB) -#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB) -#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB) -#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB) -#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB) -#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB) -#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB) -#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB) - -#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend) - -#endif /* GL_ARB_vertex_blend */ - -/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */ - -#ifndef GL_ARB_vertex_buffer_object -#define GL_ARB_vertex_buffer_object 1 - -#define GL_BUFFER_SIZE_ARB 0x8764 -#define GL_BUFFER_USAGE_ARB 0x8765 -#define GL_ARRAY_BUFFER_ARB 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 -#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 -#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 -#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A -#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B -#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C -#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D -#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F -#define GL_READ_ONLY_ARB 0x88B8 -#define GL_WRITE_ONLY_ARB 0x88B9 -#define GL_READ_WRITE_ARB 0x88BA -#define GL_BUFFER_ACCESS_ARB 0x88BB -#define GL_BUFFER_MAPPED_ARB 0x88BC -#define GL_BUFFER_MAP_POINTER_ARB 0x88BD -#define GL_STREAM_DRAW_ARB 0x88E0 -#define GL_STREAM_READ_ARB 0x88E1 -#define GL_STREAM_COPY_ARB 0x88E2 -#define GL_STATIC_DRAW_ARB 0x88E4 -#define GL_STATIC_READ_ARB 0x88E5 -#define GL_STATIC_COPY_ARB 0x88E6 -#define GL_DYNAMIC_DRAW_ARB 0x88E8 -#define GL_DYNAMIC_READ_ARB 0x88E9 -#define GL_DYNAMIC_COPY_ARB 0x88EA - -typedef ptrdiff_t GLintptrARB; -typedef ptrdiff_t GLsizeiptrARB; - -typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data); -typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); -typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data); -typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); -typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); - -#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB) -#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB) -#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB) -#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB) -#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB) -#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB) -#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB) -#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB) -#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB) -#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB) -#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB) - -#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object) - -#endif /* GL_ARB_vertex_buffer_object */ - -/* ------------------------- GL_ARB_vertex_program ------------------------- */ - -#ifndef GL_ARB_vertex_program -#define GL_ARB_vertex_program 1 - -#define GL_COLOR_SUM_ARB 0x8458 -#define GL_VERTEX_PROGRAM_ARB 0x8620 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 -#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 -#define GL_PROGRAM_LENGTH_ARB 0x8627 -#define GL_PROGRAM_STRING_ARB 0x8628 -#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E -#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F -#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 -#define GL_CURRENT_MATRIX_ARB 0x8641 -#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 -#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B -#define GL_PROGRAM_BINDING_ARB 0x8677 -#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A -#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 -#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 -#define GL_PROGRAM_FORMAT_ARB 0x8876 -#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 -#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 -#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 -#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 -#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 -#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 -#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 -#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 -#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 -#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 -#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA -#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB -#define GL_PROGRAM_ATTRIBS_ARB 0x88AC -#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD -#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE -#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF -#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 -#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 -#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 -#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 -#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 -#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 -#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 -#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 -#define GL_MATRIX0_ARB 0x88C0 -#define GL_MATRIX1_ARB 0x88C1 -#define GL_MATRIX2_ARB 0x88C2 -#define GL_MATRIX3_ARB 0x88C3 -#define GL_MATRIX4_ARB 0x88C4 -#define GL_MATRIX5_ARB 0x88C5 -#define GL_MATRIX6_ARB 0x88C6 -#define GL_MATRIX7_ARB 0x88C7 -#define GL_MATRIX8_ARB 0x88C8 -#define GL_MATRIX9_ARB 0x88C9 -#define GL_MATRIX10_ARB 0x88CA -#define GL_MATRIX11_ARB 0x88CB -#define GL_MATRIX12_ARB 0x88CC -#define GL_MATRIX13_ARB 0x88CD -#define GL_MATRIX14_ARB 0x88CE -#define GL_MATRIX15_ARB 0x88CF -#define GL_MATRIX16_ARB 0x88D0 -#define GL_MATRIX17_ARB 0x88D1 -#define GL_MATRIX18_ARB 0x88D2 -#define GL_MATRIX19_ARB 0x88D3 -#define GL_MATRIX20_ARB 0x88D4 -#define GL_MATRIX21_ARB 0x88D5 -#define GL_MATRIX22_ARB 0x88D6 -#define GL_MATRIX23_ARB 0x88D7 -#define GL_MATRIX24_ARB 0x88D8 -#define GL_MATRIX25_ARB 0x88D9 -#define GL_MATRIX26_ARB 0x88DA -#define GL_MATRIX27_ARB 0x88DB -#define GL_MATRIX28_ARB 0x88DC -#define GL_MATRIX29_ARB 0x88DD -#define GL_MATRIX30_ARB 0x88DE -#define GL_MATRIX31_ARB 0x88DF - -typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); -typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs); -typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); -typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); -typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); - -#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) -#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) -#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB) -#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB) -#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB) -#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB) -#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB) -#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB) -#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB) -#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB) -#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB) -#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB) -#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB) -#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB) -#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB) -#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB) -#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB) -#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB) -#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB) -#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB) -#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB) -#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB) -#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB) -#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB) -#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB) -#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB) -#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB) -#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB) -#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB) -#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB) -#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB) -#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB) -#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB) -#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB) -#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB) -#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB) -#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB) -#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB) -#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB) -#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB) -#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB) -#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB) -#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB) -#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB) -#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB) -#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB) -#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB) -#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB) -#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB) -#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB) -#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB) -#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB) -#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB) -#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB) -#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB) -#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB) -#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB) -#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB) -#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB) -#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB) -#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB) -#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB) - -#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program) - -#endif /* GL_ARB_vertex_program */ - -/* -------------------------- GL_ARB_vertex_shader ------------------------- */ - -#ifndef GL_ARB_vertex_shader -#define GL_ARB_vertex_shader 1 - -#define GL_VERTEX_SHADER_ARB 0x8B31 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A -#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D -#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 -#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A - -typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name); -typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); -typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); - -#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB) -#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB) -#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB) - -#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader) - -#endif /* GL_ARB_vertex_shader */ - -/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */ - -#ifndef GL_ARB_vertex_type_2_10_10_10_rev -#define GL_ARB_vertex_type_2_10_10_10_rev 1 - -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_INT_2_10_10_10_REV 0x8D9F - -typedef void (GLAPIENTRY * PFNGLCOLORP3UIPROC) (GLenum type, GLuint color); -typedef void (GLAPIENTRY * PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint* color); -typedef void (GLAPIENTRY * PFNGLCOLORP4UIPROC) (GLenum type, GLuint color); -typedef void (GLAPIENTRY * PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint* color); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint* color); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); -typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint* coords); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value); -typedef void (GLAPIENTRY * PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint* value); - -#define glColorP3ui GLEW_GET_FUN(__glewColorP3ui) -#define glColorP3uiv GLEW_GET_FUN(__glewColorP3uiv) -#define glColorP4ui GLEW_GET_FUN(__glewColorP4ui) -#define glColorP4uiv GLEW_GET_FUN(__glewColorP4uiv) -#define glMultiTexCoordP1ui GLEW_GET_FUN(__glewMultiTexCoordP1ui) -#define glMultiTexCoordP1uiv GLEW_GET_FUN(__glewMultiTexCoordP1uiv) -#define glMultiTexCoordP2ui GLEW_GET_FUN(__glewMultiTexCoordP2ui) -#define glMultiTexCoordP2uiv GLEW_GET_FUN(__glewMultiTexCoordP2uiv) -#define glMultiTexCoordP3ui GLEW_GET_FUN(__glewMultiTexCoordP3ui) -#define glMultiTexCoordP3uiv GLEW_GET_FUN(__glewMultiTexCoordP3uiv) -#define glMultiTexCoordP4ui GLEW_GET_FUN(__glewMultiTexCoordP4ui) -#define glMultiTexCoordP4uiv GLEW_GET_FUN(__glewMultiTexCoordP4uiv) -#define glNormalP3ui GLEW_GET_FUN(__glewNormalP3ui) -#define glNormalP3uiv GLEW_GET_FUN(__glewNormalP3uiv) -#define glSecondaryColorP3ui GLEW_GET_FUN(__glewSecondaryColorP3ui) -#define glSecondaryColorP3uiv GLEW_GET_FUN(__glewSecondaryColorP3uiv) -#define glTexCoordP1ui GLEW_GET_FUN(__glewTexCoordP1ui) -#define glTexCoordP1uiv GLEW_GET_FUN(__glewTexCoordP1uiv) -#define glTexCoordP2ui GLEW_GET_FUN(__glewTexCoordP2ui) -#define glTexCoordP2uiv GLEW_GET_FUN(__glewTexCoordP2uiv) -#define glTexCoordP3ui GLEW_GET_FUN(__glewTexCoordP3ui) -#define glTexCoordP3uiv GLEW_GET_FUN(__glewTexCoordP3uiv) -#define glTexCoordP4ui GLEW_GET_FUN(__glewTexCoordP4ui) -#define glTexCoordP4uiv GLEW_GET_FUN(__glewTexCoordP4uiv) -#define glVertexAttribP1ui GLEW_GET_FUN(__glewVertexAttribP1ui) -#define glVertexAttribP1uiv GLEW_GET_FUN(__glewVertexAttribP1uiv) -#define glVertexAttribP2ui GLEW_GET_FUN(__glewVertexAttribP2ui) -#define glVertexAttribP2uiv GLEW_GET_FUN(__glewVertexAttribP2uiv) -#define glVertexAttribP3ui GLEW_GET_FUN(__glewVertexAttribP3ui) -#define glVertexAttribP3uiv GLEW_GET_FUN(__glewVertexAttribP3uiv) -#define glVertexAttribP4ui GLEW_GET_FUN(__glewVertexAttribP4ui) -#define glVertexAttribP4uiv GLEW_GET_FUN(__glewVertexAttribP4uiv) -#define glVertexP2ui GLEW_GET_FUN(__glewVertexP2ui) -#define glVertexP2uiv GLEW_GET_FUN(__glewVertexP2uiv) -#define glVertexP3ui GLEW_GET_FUN(__glewVertexP3ui) -#define glVertexP3uiv GLEW_GET_FUN(__glewVertexP3uiv) -#define glVertexP4ui GLEW_GET_FUN(__glewVertexP4ui) -#define glVertexP4uiv GLEW_GET_FUN(__glewVertexP4uiv) - -#define GLEW_ARB_vertex_type_2_10_10_10_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_2_10_10_10_rev) - -#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ - -/* ------------------------- GL_ARB_viewport_array ------------------------- */ - -#ifndef GL_ARB_viewport_array -#define GL_ARB_viewport_array 1 - -#define GL_DEPTH_RANGE 0x0B70 -#define GL_VIEWPORT 0x0BA2 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_MAX_VIEWPORTS 0x825B -#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C -#define GL_VIEWPORT_BOUNDS_RANGE 0x825D -#define GL_LAYER_PROVOKING_VERTEX 0x825E -#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F -#define GL_UNDEFINED_VERTEX 0x8260 -#define GL_FIRST_VERTEX_CONVENTION 0x8E4D -#define GL_LAST_VERTEX_CONVENTION 0x8E4E -#define GL_PROVOKING_VERTEX 0x8E4F - -typedef void (GLAPIENTRY * PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd * v); -typedef void (GLAPIENTRY * PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f); -typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble* data); -typedef void (GLAPIENTRY * PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat* data); -typedef void (GLAPIENTRY * PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint * v); -typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint * v); -typedef void (GLAPIENTRY * PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat * v); -typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); -typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat * v); - -#define glDepthRangeArrayv GLEW_GET_FUN(__glewDepthRangeArrayv) -#define glDepthRangeIndexed GLEW_GET_FUN(__glewDepthRangeIndexed) -#define glGetDoublei_v GLEW_GET_FUN(__glewGetDoublei_v) -#define glGetFloati_v GLEW_GET_FUN(__glewGetFloati_v) -#define glScissorArrayv GLEW_GET_FUN(__glewScissorArrayv) -#define glScissorIndexed GLEW_GET_FUN(__glewScissorIndexed) -#define glScissorIndexedv GLEW_GET_FUN(__glewScissorIndexedv) -#define glViewportArrayv GLEW_GET_FUN(__glewViewportArrayv) -#define glViewportIndexedf GLEW_GET_FUN(__glewViewportIndexedf) -#define glViewportIndexedfv GLEW_GET_FUN(__glewViewportIndexedfv) - -#define GLEW_ARB_viewport_array GLEW_GET_VAR(__GLEW_ARB_viewport_array) - -#endif /* GL_ARB_viewport_array */ - -/* --------------------------- GL_ARB_window_pos --------------------------- */ - -#ifndef GL_ARB_window_pos -#define GL_ARB_window_pos 1 - -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p); - -#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB) -#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB) -#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB) -#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB) -#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB) -#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB) -#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB) -#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB) -#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB) -#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB) -#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB) -#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB) -#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB) -#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB) -#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB) -#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB) - -#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos) - -#endif /* GL_ARB_window_pos */ - -/* ------------------------- GL_ATIX_point_sprites ------------------------- */ - -#ifndef GL_ATIX_point_sprites -#define GL_ATIX_point_sprites 1 - -#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0 -#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1 -#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2 -#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3 -#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4 -#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5 - -#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites) - -#endif /* GL_ATIX_point_sprites */ - -/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */ - -#ifndef GL_ATIX_texture_env_combine3 -#define GL_ATIX_texture_env_combine3 1 - -#define GL_MODULATE_ADD_ATIX 0x8744 -#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745 -#define GL_MODULATE_SUBTRACT_ATIX 0x8746 - -#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3) - -#endif /* GL_ATIX_texture_env_combine3 */ - -/* ----------------------- GL_ATIX_texture_env_route ----------------------- */ - -#ifndef GL_ATIX_texture_env_route -#define GL_ATIX_texture_env_route 1 - -#define GL_SECONDARY_COLOR_ATIX 0x8747 -#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 -#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 - -#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route) - -#endif /* GL_ATIX_texture_env_route */ - -/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */ - -#ifndef GL_ATIX_vertex_shader_output_point_size -#define GL_ATIX_vertex_shader_output_point_size 1 - -#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E - -#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size) - -#endif /* GL_ATIX_vertex_shader_output_point_size */ - -/* -------------------------- GL_ATI_draw_buffers -------------------------- */ - -#ifndef GL_ATI_draw_buffers -#define GL_ATI_draw_buffers 1 - -#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 -#define GL_DRAW_BUFFER0_ATI 0x8825 -#define GL_DRAW_BUFFER1_ATI 0x8826 -#define GL_DRAW_BUFFER2_ATI 0x8827 -#define GL_DRAW_BUFFER3_ATI 0x8828 -#define GL_DRAW_BUFFER4_ATI 0x8829 -#define GL_DRAW_BUFFER5_ATI 0x882A -#define GL_DRAW_BUFFER6_ATI 0x882B -#define GL_DRAW_BUFFER7_ATI 0x882C -#define GL_DRAW_BUFFER8_ATI 0x882D -#define GL_DRAW_BUFFER9_ATI 0x882E -#define GL_DRAW_BUFFER10_ATI 0x882F -#define GL_DRAW_BUFFER11_ATI 0x8830 -#define GL_DRAW_BUFFER12_ATI 0x8831 -#define GL_DRAW_BUFFER13_ATI 0x8832 -#define GL_DRAW_BUFFER14_ATI 0x8833 -#define GL_DRAW_BUFFER15_ATI 0x8834 - -typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs); - -#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI) - -#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers) - -#endif /* GL_ATI_draw_buffers */ - -/* -------------------------- GL_ATI_element_array ------------------------- */ - -#ifndef GL_ATI_element_array -#define GL_ATI_element_array 1 - -#define GL_ELEMENT_ARRAY_ATI 0x8768 -#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 -#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A - -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); -typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer); - -#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) -#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) -#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI) - -#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array) - -#endif /* GL_ATI_element_array */ - -/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */ - -#ifndef GL_ATI_envmap_bumpmap -#define GL_ATI_envmap_bumpmap 1 - -#define GL_BUMP_ROT_MATRIX_ATI 0x8775 -#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 -#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 -#define GL_BUMP_TEX_UNITS_ATI 0x8778 -#define GL_DUDV_ATI 0x8779 -#define GL_DU8DV8_ATI 0x877A -#define GL_BUMP_ENVMAP_ATI 0x877B -#define GL_BUMP_TARGET_ATI 0x877C - -typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); -typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); -typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); -typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); - -#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI) -#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI) -#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI) -#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI) - -#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap) - -#endif /* GL_ATI_envmap_bumpmap */ - -/* ------------------------- GL_ATI_fragment_shader ------------------------ */ - -#ifndef GL_ATI_fragment_shader -#define GL_ATI_fragment_shader 1 - -#define GL_RED_BIT_ATI 0x00000001 -#define GL_2X_BIT_ATI 0x00000001 -#define GL_4X_BIT_ATI 0x00000002 -#define GL_GREEN_BIT_ATI 0x00000002 -#define GL_COMP_BIT_ATI 0x00000002 -#define GL_BLUE_BIT_ATI 0x00000004 -#define GL_8X_BIT_ATI 0x00000004 -#define GL_NEGATE_BIT_ATI 0x00000004 -#define GL_BIAS_BIT_ATI 0x00000008 -#define GL_HALF_BIT_ATI 0x00000008 -#define GL_QUARTER_BIT_ATI 0x00000010 -#define GL_EIGHTH_BIT_ATI 0x00000020 -#define GL_SATURATE_BIT_ATI 0x00000040 -#define GL_FRAGMENT_SHADER_ATI 0x8920 -#define GL_REG_0_ATI 0x8921 -#define GL_REG_1_ATI 0x8922 -#define GL_REG_2_ATI 0x8923 -#define GL_REG_3_ATI 0x8924 -#define GL_REG_4_ATI 0x8925 -#define GL_REG_5_ATI 0x8926 -#define GL_CON_0_ATI 0x8941 -#define GL_CON_1_ATI 0x8942 -#define GL_CON_2_ATI 0x8943 -#define GL_CON_3_ATI 0x8944 -#define GL_CON_4_ATI 0x8945 -#define GL_CON_5_ATI 0x8946 -#define GL_CON_6_ATI 0x8947 -#define GL_CON_7_ATI 0x8948 -#define GL_MOV_ATI 0x8961 -#define GL_ADD_ATI 0x8963 -#define GL_MUL_ATI 0x8964 -#define GL_SUB_ATI 0x8965 -#define GL_DOT3_ATI 0x8966 -#define GL_DOT4_ATI 0x8967 -#define GL_MAD_ATI 0x8968 -#define GL_LERP_ATI 0x8969 -#define GL_CND_ATI 0x896A -#define GL_CND0_ATI 0x896B -#define GL_DOT2_ADD_ATI 0x896C -#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D -#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E -#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F -#define GL_NUM_PASSES_ATI 0x8970 -#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 -#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 -#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 -#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 -#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 -#define GL_SWIZZLE_STR_ATI 0x8976 -#define GL_SWIZZLE_STQ_ATI 0x8977 -#define GL_SWIZZLE_STR_DR_ATI 0x8978 -#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 -#define GL_SWIZZLE_STRQ_ATI 0x897A -#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B - -typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); -typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); -typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); -typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void); -typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); -typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); -typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); -typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void); -typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); -typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); -typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); -typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value); - -#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI) -#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI) -#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI) -#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI) -#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI) -#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI) -#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI) -#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI) -#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI) -#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI) -#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI) -#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI) -#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI) -#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI) - -#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader) - -#endif /* GL_ATI_fragment_shader */ - -/* ------------------------ GL_ATI_map_object_buffer ----------------------- */ - -#ifndef GL_ATI_map_object_buffer -#define GL_ATI_map_object_buffer 1 - -typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); -typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); - -#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) -#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI) - -#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer) - -#endif /* GL_ATI_map_object_buffer */ - -/* ----------------------------- GL_ATI_meminfo ---------------------------- */ - -#ifndef GL_ATI_meminfo -#define GL_ATI_meminfo 1 - -#define GL_VBO_FREE_MEMORY_ATI 0x87FB -#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC -#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD - -#define GLEW_ATI_meminfo GLEW_GET_VAR(__GLEW_ATI_meminfo) - -#endif /* GL_ATI_meminfo */ - -/* -------------------------- GL_ATI_pn_triangles -------------------------- */ - -#ifndef GL_ATI_pn_triangles -#define GL_ATI_pn_triangles 1 - -#define GL_PN_TRIANGLES_ATI 0x87F0 -#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 -#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 -#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 -#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 -#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 -#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 -#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 -#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 - -typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); - -#define glPNTrianglesfATI GLEW_GET_FUN(__glewPNTrianglesfATI) -#define glPNTrianglesiATI GLEW_GET_FUN(__glewPNTrianglesiATI) - -#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles) - -#endif /* GL_ATI_pn_triangles */ - -/* ------------------------ GL_ATI_separate_stencil ------------------------ */ - -#ifndef GL_ATI_separate_stencil -#define GL_ATI_separate_stencil 1 - -#define GL_STENCIL_BACK_FUNC_ATI 0x8800 -#define GL_STENCIL_BACK_FAIL_ATI 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 - -typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); -typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); - -#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI) -#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI) - -#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil) - -#endif /* GL_ATI_separate_stencil */ - -/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */ - -#ifndef GL_ATI_shader_texture_lod -#define GL_ATI_shader_texture_lod 1 - -#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod) - -#endif /* GL_ATI_shader_texture_lod */ - -/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */ - -#ifndef GL_ATI_text_fragment_shader -#define GL_ATI_text_fragment_shader 1 - -#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 - -#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader) - -#endif /* GL_ATI_text_fragment_shader */ - -/* --------------------- GL_ATI_texture_compression_3dc -------------------- */ - -#ifndef GL_ATI_texture_compression_3dc -#define GL_ATI_texture_compression_3dc 1 - -#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837 - -#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc) - -#endif /* GL_ATI_texture_compression_3dc */ - -/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */ - -#ifndef GL_ATI_texture_env_combine3 -#define GL_ATI_texture_env_combine3 1 - -#define GL_MODULATE_ADD_ATI 0x8744 -#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 -#define GL_MODULATE_SUBTRACT_ATI 0x8746 - -#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3) - -#endif /* GL_ATI_texture_env_combine3 */ - -/* -------------------------- GL_ATI_texture_float ------------------------- */ - -#ifndef GL_ATI_texture_float -#define GL_ATI_texture_float 1 - -#define GL_RGBA_FLOAT32_ATI 0x8814 -#define GL_RGB_FLOAT32_ATI 0x8815 -#define GL_ALPHA_FLOAT32_ATI 0x8816 -#define GL_INTENSITY_FLOAT32_ATI 0x8817 -#define GL_LUMINANCE_FLOAT32_ATI 0x8818 -#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 -#define GL_RGBA_FLOAT16_ATI 0x881A -#define GL_RGB_FLOAT16_ATI 0x881B -#define GL_ALPHA_FLOAT16_ATI 0x881C -#define GL_INTENSITY_FLOAT16_ATI 0x881D -#define GL_LUMINANCE_FLOAT16_ATI 0x881E -#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F - -#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float) - -#endif /* GL_ATI_texture_float */ - -/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */ - -#ifndef GL_ATI_texture_mirror_once -#define GL_ATI_texture_mirror_once 1 - -#define GL_MIRROR_CLAMP_ATI 0x8742 -#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 - -#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once) - -#endif /* GL_ATI_texture_mirror_once */ - -/* ----------------------- GL_ATI_vertex_array_object ---------------------- */ - -#ifndef GL_ATI_vertex_array_object -#define GL_ATI_vertex_array_object 1 - -#define GL_STATIC_ATI 0x8760 -#define GL_DYNAMIC_ATI 0x8761 -#define GL_PRESERVE_ATI 0x8762 -#define GL_DISCARD_ATI 0x8763 -#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 -#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 -#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 -#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 - -typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); -typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); -typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); -typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage); -typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve); -typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); - -#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) -#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI) -#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI) -#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI) -#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI) -#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI) -#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI) -#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI) -#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI) -#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI) -#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI) -#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI) - -#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object) - -#endif /* GL_ATI_vertex_array_object */ - -/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */ - -#ifndef GL_ATI_vertex_attrib_array_object -#define GL_ATI_vertex_attrib_array_object 1 - -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); - -#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI) -#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI) -#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI) - -#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object) - -#endif /* GL_ATI_vertex_attrib_array_object */ - -/* ------------------------- GL_ATI_vertex_streams ------------------------- */ - -#ifndef GL_ATI_vertex_streams -#define GL_ATI_vertex_streams 1 - -#define GL_MAX_VERTEX_STREAMS_ATI 0x876B -#define GL_VERTEX_SOURCE_ATI 0x876C -#define GL_VERTEX_STREAM0_ATI 0x876D -#define GL_VERTEX_STREAM1_ATI 0x876E -#define GL_VERTEX_STREAM2_ATI 0x876F -#define GL_VERTEX_STREAM3_ATI 0x8770 -#define GL_VERTEX_STREAM4_ATI 0x8771 -#define GL_VERTEX_STREAM5_ATI 0x8772 -#define GL_VERTEX_STREAM6_ATI 0x8773 -#define GL_VERTEX_STREAM7_ATI 0x8774 - -typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v); - -#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI) -#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI) -#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI) -#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI) -#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI) -#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI) -#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI) -#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI) -#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI) -#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI) -#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI) -#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI) -#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI) -#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI) -#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI) -#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI) -#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI) -#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI) -#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI) -#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI) -#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI) -#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI) -#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI) -#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI) -#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI) -#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI) -#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI) -#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI) -#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI) -#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI) -#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI) -#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI) -#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI) -#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI) -#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI) -#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI) -#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI) - -#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams) - -#endif /* GL_ATI_vertex_streams */ - -/* --------------------------- GL_EXT_422_pixels --------------------------- */ - -#ifndef GL_EXT_422_pixels -#define GL_EXT_422_pixels 1 - -#define GL_422_EXT 0x80CC -#define GL_422_REV_EXT 0x80CD -#define GL_422_AVERAGE_EXT 0x80CE -#define GL_422_REV_AVERAGE_EXT 0x80CF - -#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels) - -#endif /* GL_EXT_422_pixels */ - -/* ---------------------------- GL_EXT_Cg_shader --------------------------- */ - -#ifndef GL_EXT_Cg_shader -#define GL_EXT_Cg_shader 1 - -#define GL_CG_VERTEX_SHADER_EXT 0x890E -#define GL_CG_FRAGMENT_SHADER_EXT 0x890F - -#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader) - -#endif /* GL_EXT_Cg_shader */ - -/* ------------------------------ GL_EXT_abgr ------------------------------ */ - -#ifndef GL_EXT_abgr -#define GL_EXT_abgr 1 - -#define GL_ABGR_EXT 0x8000 - -#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr) - -#endif /* GL_EXT_abgr */ - -/* ------------------------------ GL_EXT_bgra ------------------------------ */ - -#ifndef GL_EXT_bgra -#define GL_EXT_bgra 1 - -#define GL_BGR_EXT 0x80E0 -#define GL_BGRA_EXT 0x80E1 - -#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra) - -#endif /* GL_EXT_bgra */ - -/* ------------------------ GL_EXT_bindable_uniform ------------------------ */ - -#ifndef GL_EXT_bindable_uniform -#define GL_EXT_bindable_uniform 1 - -#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 -#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 -#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 -#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED -#define GL_UNIFORM_BUFFER_EXT 0x8DEE -#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF - -typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); -typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); -typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); - -#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT) -#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT) -#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT) - -#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform) - -#endif /* GL_EXT_bindable_uniform */ - -/* --------------------------- GL_EXT_blend_color -------------------------- */ - -#ifndef GL_EXT_blend_color -#define GL_EXT_blend_color 1 - -#define GL_CONSTANT_COLOR_EXT 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 -#define GL_CONSTANT_ALPHA_EXT 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 -#define GL_BLEND_COLOR_EXT 0x8005 - -typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - -#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT) - -#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color) - -#endif /* GL_EXT_blend_color */ - -/* --------------------- GL_EXT_blend_equation_separate -------------------- */ - -#ifndef GL_EXT_blend_equation_separate -#define GL_EXT_blend_equation_separate 1 - -#define GL_BLEND_EQUATION_RGB_EXT 0x8009 -#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D - -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); - -#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT) - -#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate) - -#endif /* GL_EXT_blend_equation_separate */ - -/* ----------------------- GL_EXT_blend_func_separate ---------------------- */ - -#ifndef GL_EXT_blend_func_separate -#define GL_EXT_blend_func_separate 1 - -#define GL_BLEND_DST_RGB_EXT 0x80C8 -#define GL_BLEND_SRC_RGB_EXT 0x80C9 -#define GL_BLEND_DST_ALPHA_EXT 0x80CA -#define GL_BLEND_SRC_ALPHA_EXT 0x80CB - -typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); - -#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT) - -#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate) - -#endif /* GL_EXT_blend_func_separate */ - -/* ------------------------- GL_EXT_blend_logic_op ------------------------- */ - -#ifndef GL_EXT_blend_logic_op -#define GL_EXT_blend_logic_op 1 - -#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op) - -#endif /* GL_EXT_blend_logic_op */ - -/* -------------------------- GL_EXT_blend_minmax -------------------------- */ - -#ifndef GL_EXT_blend_minmax -#define GL_EXT_blend_minmax 1 - -#define GL_FUNC_ADD_EXT 0x8006 -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#define GL_BLEND_EQUATION_EXT 0x8009 - -typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); - -#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT) - -#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax) - -#endif /* GL_EXT_blend_minmax */ - -/* ------------------------- GL_EXT_blend_subtract ------------------------- */ - -#ifndef GL_EXT_blend_subtract -#define GL_EXT_blend_subtract 1 - -#define GL_FUNC_SUBTRACT_EXT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B - -#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract) - -#endif /* GL_EXT_blend_subtract */ - -/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */ - -#ifndef GL_EXT_clip_volume_hint -#define GL_EXT_clip_volume_hint 1 - -#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 - -#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint) - -#endif /* GL_EXT_clip_volume_hint */ - -/* ------------------------------ GL_EXT_cmyka ----------------------------- */ - -#ifndef GL_EXT_cmyka -#define GL_EXT_cmyka 1 - -#define GL_CMYK_EXT 0x800C -#define GL_CMYKA_EXT 0x800D -#define GL_PACK_CMYK_HINT_EXT 0x800E -#define GL_UNPACK_CMYK_HINT_EXT 0x800F - -#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka) - -#endif /* GL_EXT_cmyka */ - -/* ------------------------- GL_EXT_color_subtable ------------------------- */ - -#ifndef GL_EXT_color_subtable -#define GL_EXT_color_subtable 1 - -typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data); -typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); - -#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) -#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT) - -#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable) - -#endif /* GL_EXT_color_subtable */ - -/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */ - -#ifndef GL_EXT_compiled_vertex_array -#define GL_EXT_compiled_vertex_array 1 - -#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 -#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 - -typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); -typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); - -#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT) -#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT) - -#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array) - -#endif /* GL_EXT_compiled_vertex_array */ - -/* --------------------------- GL_EXT_convolution -------------------------- */ - -#ifndef GL_EXT_convolution -#define GL_EXT_convolution 1 - -#define GL_CONVOLUTION_1D_EXT 0x8010 -#define GL_CONVOLUTION_2D_EXT 0x8011 -#define GL_SEPARABLE_2D_EXT 0x8012 -#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 -#define GL_REDUCE_EXT 0x8016 -#define GL_CONVOLUTION_FORMAT_EXT 0x8017 -#define GL_CONVOLUTION_WIDTH_EXT 0x8018 -#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 - -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span); -typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column); - -#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) -#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) -#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT) -#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT) -#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT) -#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT) -#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT) -#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT) -#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT) -#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT) -#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT) -#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT) -#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT) - -#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution) - -#endif /* GL_EXT_convolution */ - -/* ------------------------ GL_EXT_coordinate_frame ------------------------ */ - -#ifndef GL_EXT_coordinate_frame -#define GL_EXT_coordinate_frame 1 - -#define GL_TANGENT_ARRAY_EXT 0x8439 -#define GL_BINORMAL_ARRAY_EXT 0x843A -#define GL_CURRENT_TANGENT_EXT 0x843B -#define GL_CURRENT_BINORMAL_EXT 0x843C -#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E -#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F -#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 -#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 -#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 -#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 -#define GL_MAP1_TANGENT_EXT 0x8444 -#define GL_MAP2_TANGENT_EXT 0x8445 -#define GL_MAP1_BINORMAL_EXT 0x8446 -#define GL_MAP2_BINORMAL_EXT 0x8447 - -typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); -typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); - -#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) -#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) - -#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame) - -#endif /* GL_EXT_coordinate_frame */ - -/* -------------------------- GL_EXT_copy_texture -------------------------- */ - -#ifndef GL_EXT_copy_texture -#define GL_EXT_copy_texture 1 - -typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); - -#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT) -#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT) -#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT) -#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT) -#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT) - -#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture) - -#endif /* GL_EXT_copy_texture */ - -/* --------------------------- GL_EXT_cull_vertex -------------------------- */ - -#ifndef GL_EXT_cull_vertex -#define GL_EXT_cull_vertex 1 - -#define GL_CULL_VERTEX_EXT 0x81AA -#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB -#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC - -typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params); - -#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT) -#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT) - -#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex) - -#endif /* GL_EXT_cull_vertex */ - -/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */ - -#ifndef GL_EXT_depth_bounds_test -#define GL_EXT_depth_bounds_test 1 - -#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 -#define GL_DEPTH_BOUNDS_EXT 0x8891 - -typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); - -#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT) - -#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test) - -#endif /* GL_EXT_depth_bounds_test */ - -/* ----------------------- GL_EXT_direct_state_access ---------------------- */ - -#ifndef GL_EXT_direct_state_access -#define GL_EXT_direct_state_access 1 - -#define GL_PROGRAM_MATRIX_EXT 0x8E2D -#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E -#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F - -typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); -typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); -typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); -typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); -typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); -typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); -typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); -typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); -typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); -typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); -typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); -typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); -typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img); -typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); -typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); -typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param); -typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param); -typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param); -typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); -typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode); -typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); -typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); -typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m); -typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m); -typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); -typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); -typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m); -typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m); -typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); -typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode); -typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode); -typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer); -typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); -typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param); -typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); -typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); -typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); -typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string); -typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); -typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param); -typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); -typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); -typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); - -#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT) -#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT) -#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT) -#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT) -#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT) -#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT) -#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT) -#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT) -#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT) -#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT) -#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT) -#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT) -#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT) -#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT) -#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT) -#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT) -#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT) -#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT) -#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT) -#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT) -#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT) -#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT) -#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT) -#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT) -#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT) -#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT) -#define glDisableClientStateiEXT GLEW_GET_FUN(__glewDisableClientStateiEXT) -#define glDisableVertexArrayAttribEXT GLEW_GET_FUN(__glewDisableVertexArrayAttribEXT) -#define glDisableVertexArrayEXT GLEW_GET_FUN(__glewDisableVertexArrayEXT) -#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT) -#define glEnableClientStateiEXT GLEW_GET_FUN(__glewEnableClientStateiEXT) -#define glEnableVertexArrayAttribEXT GLEW_GET_FUN(__glewEnableVertexArrayAttribEXT) -#define glEnableVertexArrayEXT GLEW_GET_FUN(__glewEnableVertexArrayEXT) -#define glFlushMappedNamedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedNamedBufferRangeEXT) -#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT) -#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT) -#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT) -#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT) -#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT) -#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT) -#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT) -#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT) -#define glGetDoublei_vEXT GLEW_GET_FUN(__glewGetDoublei_vEXT) -#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT) -#define glGetFloati_vEXT GLEW_GET_FUN(__glewGetFloati_vEXT) -#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT) -#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT) -#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT) -#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT) -#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT) -#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT) -#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT) -#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT) -#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT) -#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT) -#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT) -#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT) -#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT) -#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT) -#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT) -#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT) -#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT) -#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT) -#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT) -#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT) -#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT) -#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT) -#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT) -#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT) -#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT) -#define glGetPointeri_vEXT GLEW_GET_FUN(__glewGetPointeri_vEXT) -#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT) -#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT) -#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT) -#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT) -#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT) -#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT) -#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT) -#define glGetVertexArrayIntegeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayIntegeri_vEXT) -#define glGetVertexArrayIntegervEXT GLEW_GET_FUN(__glewGetVertexArrayIntegervEXT) -#define glGetVertexArrayPointeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayPointeri_vEXT) -#define glGetVertexArrayPointervEXT GLEW_GET_FUN(__glewGetVertexArrayPointervEXT) -#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT) -#define glMapNamedBufferRangeEXT GLEW_GET_FUN(__glewMapNamedBufferRangeEXT) -#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT) -#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT) -#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT) -#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT) -#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT) -#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT) -#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT) -#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT) -#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT) -#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT) -#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT) -#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT) -#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT) -#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT) -#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT) -#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT) -#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT) -#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT) -#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT) -#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT) -#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT) -#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT) -#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT) -#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT) -#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT) -#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT) -#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT) -#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT) -#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT) -#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT) -#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT) -#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT) -#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT) -#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT) -#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT) -#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT) -#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT) -#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT) -#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT) -#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT) -#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT) -#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT) -#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT) -#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT) -#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT) -#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT) -#define glNamedCopyBufferSubDataEXT GLEW_GET_FUN(__glewNamedCopyBufferSubDataEXT) -#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT) -#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT) -#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT) -#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT) -#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT) -#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT) -#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT) -#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT) -#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT) -#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT) -#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT) -#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT) -#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT) -#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT) -#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT) -#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT) -#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT) -#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT) -#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT) -#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT) -#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT) -#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT) -#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT) -#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT) -#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT) -#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT) -#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT) -#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT) -#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT) -#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT) -#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT) -#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT) -#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT) -#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT) -#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT) -#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT) -#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT) -#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT) -#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT) -#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT) -#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT) -#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT) -#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT) -#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT) -#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT) -#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT) -#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT) -#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT) -#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT) -#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT) -#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT) -#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT) -#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT) -#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT) -#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT) -#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT) -#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT) -#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT) -#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT) -#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT) -#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT) -#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT) -#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT) -#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT) -#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT) -#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT) -#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT) -#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT) -#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT) -#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT) -#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT) -#define glVertexArrayColorOffsetEXT GLEW_GET_FUN(__glewVertexArrayColorOffsetEXT) -#define glVertexArrayEdgeFlagOffsetEXT GLEW_GET_FUN(__glewVertexArrayEdgeFlagOffsetEXT) -#define glVertexArrayFogCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayFogCoordOffsetEXT) -#define glVertexArrayIndexOffsetEXT GLEW_GET_FUN(__glewVertexArrayIndexOffsetEXT) -#define glVertexArrayMultiTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayMultiTexCoordOffsetEXT) -#define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT) -#define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT) -#define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT) -#define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT) -#define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT) -#define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT) - -#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access) - -#endif /* GL_EXT_direct_state_access */ - -/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */ - -#ifndef GL_EXT_draw_buffers2 -#define GL_EXT_draw_buffers2 1 - -typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); -typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); -typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data); -typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data); -typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); - -#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT) -#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT) -#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT) -#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT) -#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT) -#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT) - -#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2) - -#endif /* GL_EXT_draw_buffers2 */ - -/* ------------------------- GL_EXT_draw_instanced ------------------------- */ - -#ifndef GL_EXT_draw_instanced -#define GL_EXT_draw_instanced 1 - -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); - -#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT) -#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT) - -#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced) - -#endif /* GL_EXT_draw_instanced */ - -/* ----------------------- GL_EXT_draw_range_elements ---------------------- */ - -#ifndef GL_EXT_draw_range_elements -#define GL_EXT_draw_range_elements 1 - -#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 -#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 - -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); - -#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT) - -#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements) - -#endif /* GL_EXT_draw_range_elements */ - -/* ---------------------------- GL_EXT_fog_coord --------------------------- */ - -#ifndef GL_EXT_fog_coord -#define GL_EXT_fog_coord 1 - -#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 -#define GL_FOG_COORDINATE_EXT 0x8451 -#define GL_FRAGMENT_DEPTH_EXT 0x8452 -#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 -#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 -#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 -#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 -#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 - -typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); -typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); -typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); -typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); - -#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT) -#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT) -#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT) -#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT) -#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT) - -#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord) - -#endif /* GL_EXT_fog_coord */ - -/* ------------------------ GL_EXT_fragment_lighting ----------------------- */ - -#ifndef GL_EXT_fragment_lighting -#define GL_EXT_fragment_lighting 1 - -#define GL_FRAGMENT_LIGHTING_EXT 0x8400 -#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401 -#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402 -#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403 -#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404 -#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405 -#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406 -#define GL_LIGHT_ENV_MODE_EXT 0x8407 -#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408 -#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409 -#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A -#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B -#define GL_FRAGMENT_LIGHT0_EXT 0x840C -#define GL_FRAGMENT_LIGHT7_EXT 0x8413 - -typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param); - -#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT) -#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT) -#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT) -#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT) -#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT) -#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT) -#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT) -#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT) -#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT) -#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT) -#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT) -#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT) -#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT) -#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT) -#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT) -#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT) -#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT) -#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT) - -#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting) - -#endif /* GL_EXT_fragment_lighting */ - -/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */ - -#ifndef GL_EXT_framebuffer_blit -#define GL_EXT_framebuffer_blit 1 - -#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 -#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 -#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA - -typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); - -#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT) - -#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit) - -#endif /* GL_EXT_framebuffer_blit */ - -/* --------------------- GL_EXT_framebuffer_multisample -------------------- */ - -#ifndef GL_EXT_framebuffer_multisample -#define GL_EXT_framebuffer_multisample 1 - -#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 -#define GL_MAX_SAMPLES_EXT 0x8D57 - -typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); - -#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT) - -#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample) - -#endif /* GL_EXT_framebuffer_multisample */ - -/* ----------------------- GL_EXT_framebuffer_object ----------------------- */ - -#ifndef GL_EXT_framebuffer_object -#define GL_EXT_framebuffer_object 1 - -#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 -#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 -#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 -#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 -#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC -#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD -#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 -#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 -#define GL_FRAMEBUFFER_EXT 0x8D40 -#define GL_RENDERBUFFER_EXT 0x8D41 -#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 -#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 -#define GL_STENCIL_INDEX1_EXT 0x8D46 -#define GL_STENCIL_INDEX4_EXT 0x8D47 -#define GL_STENCIL_INDEX8_EXT 0x8D48 -#define GL_STENCIL_INDEX16_EXT 0x8D49 -#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 - -typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); -typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); -typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers); -typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers); -typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers); -typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); -typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); - -#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT) -#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT) -#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT) -#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT) -#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT) -#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT) -#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT) -#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT) -#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT) -#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT) -#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT) -#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT) -#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT) -#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT) -#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT) -#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT) -#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT) - -#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object) - -#endif /* GL_EXT_framebuffer_object */ - -/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */ - -#ifndef GL_EXT_framebuffer_sRGB -#define GL_EXT_framebuffer_sRGB 1 - -#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 -#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA - -#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB) - -#endif /* GL_EXT_framebuffer_sRGB */ - -/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */ - -#ifndef GL_EXT_geometry_shader4 -#define GL_EXT_geometry_shader4 1 - -#define GL_LINES_ADJACENCY_EXT 0xA -#define GL_LINE_STRIP_ADJACENCY_EXT 0xB -#define GL_TRIANGLES_ADJACENCY_EXT 0xC -#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD -#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 -#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 -#define GL_GEOMETRY_SHADER_EXT 0x8DD9 -#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA -#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB -#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC -#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD -#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 - -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); - -#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT) -#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT) -#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT) - -#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4) - -#endif /* GL_EXT_geometry_shader4 */ - -/* --------------------- GL_EXT_gpu_program_parameters --------------------- */ - -#ifndef GL_EXT_gpu_program_parameters -#define GL_EXT_gpu_program_parameters 1 - -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); - -#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT) -#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT) - -#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters) - -#endif /* GL_EXT_gpu_program_parameters */ - -/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */ - -#ifndef GL_EXT_gpu_shader4 -#define GL_EXT_gpu_shader4 1 - -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD -#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 -#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 -#define GL_SAMPLER_BUFFER_EXT 0x8DC2 -#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 -#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 -#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 -#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 -#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 -#define GL_INT_SAMPLER_1D_EXT 0x8DC9 -#define GL_INT_SAMPLER_2D_EXT 0x8DCA -#define GL_INT_SAMPLER_3D_EXT 0x8DCB -#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC -#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD -#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE -#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF -#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 -#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 -#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 -#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 - -typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); -typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); -typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); -typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); -typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); - -#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT) -#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT) -#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT) -#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT) -#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT) -#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT) -#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT) -#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT) -#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT) -#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT) -#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT) -#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT) -#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT) -#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT) -#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT) -#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT) -#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT) -#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT) -#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT) -#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT) -#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT) -#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT) -#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT) -#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT) -#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT) -#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT) -#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT) -#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT) -#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT) -#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT) -#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT) -#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT) -#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT) -#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT) - -#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4) - -#endif /* GL_EXT_gpu_shader4 */ - -/* ---------------------------- GL_EXT_histogram --------------------------- */ - -#ifndef GL_EXT_histogram -#define GL_EXT_histogram 1 - -#define GL_HISTOGRAM_EXT 0x8024 -#define GL_PROXY_HISTOGRAM_EXT 0x8025 -#define GL_HISTOGRAM_WIDTH_EXT 0x8026 -#define GL_HISTOGRAM_FORMAT_EXT 0x8027 -#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C -#define GL_HISTOGRAM_SINK_EXT 0x802D -#define GL_MINMAX_EXT 0x802E -#define GL_MINMAX_FORMAT_EXT 0x802F -#define GL_MINMAX_SINK_EXT 0x8030 - -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); -typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); -typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); - -#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT) -#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT) -#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT) -#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT) -#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT) -#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT) -#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT) -#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT) -#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT) -#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT) - -#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram) - -#endif /* GL_EXT_histogram */ - -/* ----------------------- GL_EXT_index_array_formats ---------------------- */ - -#ifndef GL_EXT_index_array_formats -#define GL_EXT_index_array_formats 1 - -#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats) - -#endif /* GL_EXT_index_array_formats */ - -/* --------------------------- GL_EXT_index_func --------------------------- */ - -#ifndef GL_EXT_index_func -#define GL_EXT_index_func 1 - -typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref); - -#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT) - -#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func) - -#endif /* GL_EXT_index_func */ - -/* ------------------------- GL_EXT_index_material ------------------------- */ - -#ifndef GL_EXT_index_material -#define GL_EXT_index_material 1 - -typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); - -#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT) - -#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material) - -#endif /* GL_EXT_index_material */ - -/* -------------------------- GL_EXT_index_texture ------------------------- */ - -#ifndef GL_EXT_index_texture -#define GL_EXT_index_texture 1 - -#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture) - -#endif /* GL_EXT_index_texture */ - -/* -------------------------- GL_EXT_light_texture ------------------------- */ - -#ifndef GL_EXT_light_texture -#define GL_EXT_light_texture 1 - -#define GL_FRAGMENT_MATERIAL_EXT 0x8349 -#define GL_FRAGMENT_NORMAL_EXT 0x834A -#define GL_FRAGMENT_COLOR_EXT 0x834C -#define GL_ATTENUATION_EXT 0x834D -#define GL_SHADOW_ATTENUATION_EXT 0x834E -#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F -#define GL_TEXTURE_LIGHT_EXT 0x8350 -#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 -#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 -#define GL_FRAGMENT_DEPTH_EXT 0x8452 - -typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); -typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); -typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); - -#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT) -#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT) -#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT) - -#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture) - -#endif /* GL_EXT_light_texture */ - -/* ------------------------- GL_EXT_misc_attribute ------------------------- */ - -#ifndef GL_EXT_misc_attribute -#define GL_EXT_misc_attribute 1 - -#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute) - -#endif /* GL_EXT_misc_attribute */ - -/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */ - -#ifndef GL_EXT_multi_draw_arrays -#define GL_EXT_multi_draw_arrays 1 - -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount); - -#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) -#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) - -#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays) - -#endif /* GL_EXT_multi_draw_arrays */ - -/* --------------------------- GL_EXT_multisample -------------------------- */ - -#ifndef GL_EXT_multisample -#define GL_EXT_multisample 1 - -#define GL_MULTISAMPLE_EXT 0x809D -#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F -#define GL_SAMPLE_MASK_EXT 0x80A0 -#define GL_1PASS_EXT 0x80A1 -#define GL_2PASS_0_EXT 0x80A2 -#define GL_2PASS_1_EXT 0x80A3 -#define GL_4PASS_0_EXT 0x80A4 -#define GL_4PASS_1_EXT 0x80A5 -#define GL_4PASS_2_EXT 0x80A6 -#define GL_4PASS_3_EXT 0x80A7 -#define GL_SAMPLE_BUFFERS_EXT 0x80A8 -#define GL_SAMPLES_EXT 0x80A9 -#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA -#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB -#define GL_SAMPLE_PATTERN_EXT 0x80AC -#define GL_MULTISAMPLE_BIT_EXT 0x20000000 - -typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); -typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); - -#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT) -#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT) - -#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample) - -#endif /* GL_EXT_multisample */ - -/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */ - -#ifndef GL_EXT_packed_depth_stencil -#define GL_EXT_packed_depth_stencil 1 - -#define GL_DEPTH_STENCIL_EXT 0x84F9 -#define GL_UNSIGNED_INT_24_8_EXT 0x84FA -#define GL_DEPTH24_STENCIL8_EXT 0x88F0 -#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 - -#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil) - -#endif /* GL_EXT_packed_depth_stencil */ - -/* -------------------------- GL_EXT_packed_float -------------------------- */ - -#ifndef GL_EXT_packed_float -#define GL_EXT_packed_float 1 - -#define GL_R11F_G11F_B10F_EXT 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B -#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C - -#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float) - -#endif /* GL_EXT_packed_float */ - -/* -------------------------- GL_EXT_packed_pixels ------------------------- */ - -#ifndef GL_EXT_packed_pixels -#define GL_EXT_packed_pixels 1 - -#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 - -#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels) - -#endif /* GL_EXT_packed_pixels */ - -/* ------------------------ GL_EXT_paletted_texture ------------------------ */ - -#ifndef GL_EXT_paletted_texture -#define GL_EXT_paletted_texture 1 - -#define GL_TEXTURE_1D 0x0DE0 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_PROXY_TEXTURE_1D 0x8063 -#define GL_PROXY_TEXTURE_2D 0x8064 -#define GL_TEXTURE_3D_EXT 0x806F -#define GL_PROXY_TEXTURE_3D_EXT 0x8070 -#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 -#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF -#define GL_COLOR_INDEX1_EXT 0x80E2 -#define GL_COLOR_INDEX2_EXT 0x80E3 -#define GL_COLOR_INDEX4_EXT 0x80E4 -#define GL_COLOR_INDEX8_EXT 0x80E5 -#define GL_COLOR_INDEX12_EXT 0x80E6 -#define GL_COLOR_INDEX16_EXT 0x80E7 -#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED -#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 -#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B - -typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); - -#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT) -#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT) -#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT) -#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT) - -#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture) - -#endif /* GL_EXT_paletted_texture */ - -/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */ - -#ifndef GL_EXT_pixel_buffer_object -#define GL_EXT_pixel_buffer_object 1 - -#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB -#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF - -#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object) - -#endif /* GL_EXT_pixel_buffer_object */ - -/* ------------------------- GL_EXT_pixel_transform ------------------------ */ - -#ifndef GL_EXT_pixel_transform -#define GL_EXT_pixel_transform 1 - -#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 -#define GL_PIXEL_MAG_FILTER_EXT 0x8331 -#define GL_PIXEL_MIN_FILTER_EXT 0x8332 -#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 -#define GL_CUBIC_EXT 0x8334 -#define GL_AVERAGE_EXT 0x8335 -#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 -#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 -#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 - -typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param); -typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param); -typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); - -#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT) -#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT) -#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT) -#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT) -#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT) -#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT) - -#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform) - -#endif /* GL_EXT_pixel_transform */ - -/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */ - -#ifndef GL_EXT_pixel_transform_color_table -#define GL_EXT_pixel_transform_color_table 1 - -#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table) - -#endif /* GL_EXT_pixel_transform_color_table */ - -/* ------------------------ GL_EXT_point_parameters ------------------------ */ - -#ifndef GL_EXT_point_parameters -#define GL_EXT_point_parameters 1 - -#define GL_POINT_SIZE_MIN_EXT 0x8126 -#define GL_POINT_SIZE_MAX_EXT 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 -#define GL_DISTANCE_ATTENUATION_EXT 0x8129 - -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat* params); - -#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT) -#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT) - -#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters) - -#endif /* GL_EXT_point_parameters */ - -/* ------------------------- GL_EXT_polygon_offset ------------------------- */ - -#ifndef GL_EXT_polygon_offset -#define GL_EXT_polygon_offset 1 - -#define GL_POLYGON_OFFSET_EXT 0x8037 -#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 -#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 - -typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); - -#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT) - -#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset) - -#endif /* GL_EXT_polygon_offset */ - -/* ------------------------ GL_EXT_provoking_vertex ------------------------ */ - -#ifndef GL_EXT_provoking_vertex -#define GL_EXT_provoking_vertex 1 - -#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C -#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D -#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E -#define GL_PROVOKING_VERTEX_EXT 0x8E4F - -typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); - -#define glProvokingVertexEXT GLEW_GET_FUN(__glewProvokingVertexEXT) - -#define GLEW_EXT_provoking_vertex GLEW_GET_VAR(__GLEW_EXT_provoking_vertex) - -#endif /* GL_EXT_provoking_vertex */ - -/* ------------------------- GL_EXT_rescale_normal ------------------------- */ - -#ifndef GL_EXT_rescale_normal -#define GL_EXT_rescale_normal 1 - -#define GL_RESCALE_NORMAL_EXT 0x803A - -#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal) - -#endif /* GL_EXT_rescale_normal */ - -/* -------------------------- GL_EXT_scene_marker -------------------------- */ - -#ifndef GL_EXT_scene_marker -#define GL_EXT_scene_marker 1 - -typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void); -typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void); - -#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT) -#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT) - -#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker) - -#endif /* GL_EXT_scene_marker */ - -/* ------------------------- GL_EXT_secondary_color ------------------------ */ - -#ifndef GL_EXT_secondary_color -#define GL_EXT_secondary_color 1 - -#define GL_COLOR_SUM_EXT 0x8458 -#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 -#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A -#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B -#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C -#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D -#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E - -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); - -#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT) -#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT) -#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT) -#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT) -#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT) -#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT) -#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT) -#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT) -#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT) -#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT) -#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT) -#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT) -#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT) -#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT) -#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT) -#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT) -#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT) - -#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color) - -#endif /* GL_EXT_secondary_color */ - -/* --------------------- GL_EXT_separate_shader_objects -------------------- */ - -#ifndef GL_EXT_separate_shader_objects -#define GL_EXT_separate_shader_objects 1 - -#define GL_ACTIVE_PROGRAM_EXT 0x8B8D - -typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); -typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string); -typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); - -#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT) -#define glCreateShaderProgramEXT GLEW_GET_FUN(__glewCreateShaderProgramEXT) -#define glUseShaderProgramEXT GLEW_GET_FUN(__glewUseShaderProgramEXT) - -#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects) - -#endif /* GL_EXT_separate_shader_objects */ - -/* --------------------- GL_EXT_separate_specular_color -------------------- */ - -#ifndef GL_EXT_separate_specular_color -#define GL_EXT_separate_specular_color 1 - -#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 -#define GL_SINGLE_COLOR_EXT 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA - -#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color) - -#endif /* GL_EXT_separate_specular_color */ - -/* --------------------- GL_EXT_shader_image_load_store -------------------- */ - -#ifndef GL_EXT_shader_image_load_store -#define GL_EXT_shader_image_load_store 1 - -#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 -#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 -#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 -#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 -#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 -#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 -#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 -#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 -#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 -#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 -#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 -#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 -#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 -#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 -#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A -#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B -#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C -#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D -#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E -#define GL_IMAGE_1D_EXT 0x904C -#define GL_IMAGE_2D_EXT 0x904D -#define GL_IMAGE_3D_EXT 0x904E -#define GL_IMAGE_2D_RECT_EXT 0x904F -#define GL_IMAGE_CUBE_EXT 0x9050 -#define GL_IMAGE_BUFFER_EXT 0x9051 -#define GL_IMAGE_1D_ARRAY_EXT 0x9052 -#define GL_IMAGE_2D_ARRAY_EXT 0x9053 -#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 -#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 -#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 -#define GL_INT_IMAGE_1D_EXT 0x9057 -#define GL_INT_IMAGE_2D_EXT 0x9058 -#define GL_INT_IMAGE_3D_EXT 0x9059 -#define GL_INT_IMAGE_2D_RECT_EXT 0x905A -#define GL_INT_IMAGE_CUBE_EXT 0x905B -#define GL_INT_IMAGE_BUFFER_EXT 0x905C -#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D -#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E -#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F -#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 -#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 -#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 -#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 -#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 -#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 -#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 -#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 -#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 -#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 -#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A -#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B -#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C -#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D -#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E -#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF - -typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); -typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); - -#define glBindImageTextureEXT GLEW_GET_FUN(__glewBindImageTextureEXT) -#define glMemoryBarrierEXT GLEW_GET_FUN(__glewMemoryBarrierEXT) - -#define GLEW_EXT_shader_image_load_store GLEW_GET_VAR(__GLEW_EXT_shader_image_load_store) - -#endif /* GL_EXT_shader_image_load_store */ - -/* -------------------------- GL_EXT_shadow_funcs -------------------------- */ - -#ifndef GL_EXT_shadow_funcs -#define GL_EXT_shadow_funcs 1 - -#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs) - -#endif /* GL_EXT_shadow_funcs */ - -/* --------------------- GL_EXT_shared_texture_palette --------------------- */ - -#ifndef GL_EXT_shared_texture_palette -#define GL_EXT_shared_texture_palette 1 - -#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB - -#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette) - -#endif /* GL_EXT_shared_texture_palette */ - -/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */ - -#ifndef GL_EXT_stencil_clear_tag -#define GL_EXT_stencil_clear_tag 1 - -#define GL_STENCIL_TAG_BITS_EXT 0x88F2 -#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 - -#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag) - -#endif /* GL_EXT_stencil_clear_tag */ - -/* ------------------------ GL_EXT_stencil_two_side ------------------------ */ - -#ifndef GL_EXT_stencil_two_side -#define GL_EXT_stencil_two_side 1 - -#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 -#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 - -typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); - -#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT) - -#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side) - -#endif /* GL_EXT_stencil_two_side */ - -/* -------------------------- GL_EXT_stencil_wrap -------------------------- */ - -#ifndef GL_EXT_stencil_wrap -#define GL_EXT_stencil_wrap 1 - -#define GL_INCR_WRAP_EXT 0x8507 -#define GL_DECR_WRAP_EXT 0x8508 - -#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap) - -#endif /* GL_EXT_stencil_wrap */ - -/* --------------------------- GL_EXT_subtexture --------------------------- */ - -#ifndef GL_EXT_subtexture -#define GL_EXT_subtexture 1 - -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); - -#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) -#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) -#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT) - -#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture) - -#endif /* GL_EXT_subtexture */ - -/* ----------------------------- GL_EXT_texture ---------------------------- */ - -#ifndef GL_EXT_texture -#define GL_EXT_texture 1 - -#define GL_ALPHA4_EXT 0x803B -#define GL_ALPHA8_EXT 0x803C -#define GL_ALPHA12_EXT 0x803D -#define GL_ALPHA16_EXT 0x803E -#define GL_LUMINANCE4_EXT 0x803F -#define GL_LUMINANCE8_EXT 0x8040 -#define GL_LUMINANCE12_EXT 0x8041 -#define GL_LUMINANCE16_EXT 0x8042 -#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 -#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 -#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 -#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 -#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 -#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 -#define GL_INTENSITY_EXT 0x8049 -#define GL_INTENSITY4_EXT 0x804A -#define GL_INTENSITY8_EXT 0x804B -#define GL_INTENSITY12_EXT 0x804C -#define GL_INTENSITY16_EXT 0x804D -#define GL_RGB2_EXT 0x804E -#define GL_RGB4_EXT 0x804F -#define GL_RGB5_EXT 0x8050 -#define GL_RGB8_EXT 0x8051 -#define GL_RGB10_EXT 0x8052 -#define GL_RGB12_EXT 0x8053 -#define GL_RGB16_EXT 0x8054 -#define GL_RGBA2_EXT 0x8055 -#define GL_RGBA4_EXT 0x8056 -#define GL_RGB5_A1_EXT 0x8057 -#define GL_RGBA8_EXT 0x8058 -#define GL_RGB10_A2_EXT 0x8059 -#define GL_RGBA12_EXT 0x805A -#define GL_RGBA16_EXT 0x805B -#define GL_TEXTURE_RED_SIZE_EXT 0x805C -#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D -#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E -#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F -#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 -#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 -#define GL_REPLACE_EXT 0x8062 -#define GL_PROXY_TEXTURE_1D_EXT 0x8063 -#define GL_PROXY_TEXTURE_2D_EXT 0x8064 - -#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture) - -#endif /* GL_EXT_texture */ - -/* ---------------------------- GL_EXT_texture3D --------------------------- */ - -#ifndef GL_EXT_texture3D -#define GL_EXT_texture3D 1 - -#define GL_PACK_SKIP_IMAGES_EXT 0x806B -#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C -#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D -#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E -#define GL_TEXTURE_3D_EXT 0x806F -#define GL_PROXY_TEXTURE_3D_EXT 0x8070 -#define GL_TEXTURE_DEPTH_EXT 0x8071 -#define GL_TEXTURE_WRAP_R_EXT 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 - -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); - -#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) - -#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D) - -#endif /* GL_EXT_texture3D */ - -/* -------------------------- GL_EXT_texture_array ------------------------- */ - -#ifndef GL_EXT_texture_array -#define GL_EXT_texture_array 1 - -#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E -#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF -#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 -#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 -#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A -#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B -#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C -#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D - -typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); - -#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT) - -#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array) - -#endif /* GL_EXT_texture_array */ - -/* ---------------------- GL_EXT_texture_buffer_object --------------------- */ - -#ifndef GL_EXT_texture_buffer_object -#define GL_EXT_texture_buffer_object 1 - -#define GL_TEXTURE_BUFFER_EXT 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D -#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E - -typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); - -#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT) - -#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object) - -#endif /* GL_EXT_texture_buffer_object */ - -/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */ - -#ifndef GL_EXT_texture_compression_dxt1 -#define GL_EXT_texture_compression_dxt1 1 - -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 - -#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1) - -#endif /* GL_EXT_texture_compression_dxt1 */ - -/* -------------------- GL_EXT_texture_compression_latc -------------------- */ - -#ifndef GL_EXT_texture_compression_latc -#define GL_EXT_texture_compression_latc 1 - -#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 -#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 -#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 -#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 - -#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc) - -#endif /* GL_EXT_texture_compression_latc */ - -/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */ - -#ifndef GL_EXT_texture_compression_rgtc -#define GL_EXT_texture_compression_rgtc 1 - -#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE - -#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc) - -#endif /* GL_EXT_texture_compression_rgtc */ - -/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */ - -#ifndef GL_EXT_texture_compression_s3tc -#define GL_EXT_texture_compression_s3tc 1 - -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - -#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc) - -#endif /* GL_EXT_texture_compression_s3tc */ - -/* ------------------------ GL_EXT_texture_cube_map ------------------------ */ - -#ifndef GL_EXT_texture_cube_map -#define GL_EXT_texture_cube_map 1 - -#define GL_NORMAL_MAP_EXT 0x8511 -#define GL_REFLECTION_MAP_EXT 0x8512 -#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C - -#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map) - -#endif /* GL_EXT_texture_cube_map */ - -/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */ - -#ifndef GL_EXT_texture_edge_clamp -#define GL_EXT_texture_edge_clamp 1 - -#define GL_CLAMP_TO_EDGE_EXT 0x812F - -#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp) - -#endif /* GL_EXT_texture_edge_clamp */ - -/* --------------------------- GL_EXT_texture_env -------------------------- */ - -#ifndef GL_EXT_texture_env -#define GL_EXT_texture_env 1 - -#define GL_TEXTURE_ENV0_EXT 0 -#define GL_ENV_BLEND_EXT 0 -#define GL_TEXTURE_ENV_SHIFT_EXT 0 -#define GL_ENV_REPLACE_EXT 0 -#define GL_ENV_ADD_EXT 0 -#define GL_ENV_SUBTRACT_EXT 0 -#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 -#define GL_ENV_REVERSE_SUBTRACT_EXT 0 -#define GL_ENV_REVERSE_BLEND_EXT 0 -#define GL_ENV_COPY_EXT 0 -#define GL_ENV_MODULATE_EXT 0 - -#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env) - -#endif /* GL_EXT_texture_env */ - -/* ------------------------- GL_EXT_texture_env_add ------------------------ */ - -#ifndef GL_EXT_texture_env_add -#define GL_EXT_texture_env_add 1 - -#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add) - -#endif /* GL_EXT_texture_env_add */ - -/* ----------------------- GL_EXT_texture_env_combine ---------------------- */ - -#ifndef GL_EXT_texture_env_combine -#define GL_EXT_texture_env_combine 1 - -#define GL_COMBINE_EXT 0x8570 -#define GL_COMBINE_RGB_EXT 0x8571 -#define GL_COMBINE_ALPHA_EXT 0x8572 -#define GL_RGB_SCALE_EXT 0x8573 -#define GL_ADD_SIGNED_EXT 0x8574 -#define GL_INTERPOLATE_EXT 0x8575 -#define GL_CONSTANT_EXT 0x8576 -#define GL_PRIMARY_COLOR_EXT 0x8577 -#define GL_PREVIOUS_EXT 0x8578 -#define GL_SOURCE0_RGB_EXT 0x8580 -#define GL_SOURCE1_RGB_EXT 0x8581 -#define GL_SOURCE2_RGB_EXT 0x8582 -#define GL_SOURCE0_ALPHA_EXT 0x8588 -#define GL_SOURCE1_ALPHA_EXT 0x8589 -#define GL_SOURCE2_ALPHA_EXT 0x858A -#define GL_OPERAND0_RGB_EXT 0x8590 -#define GL_OPERAND1_RGB_EXT 0x8591 -#define GL_OPERAND2_RGB_EXT 0x8592 -#define GL_OPERAND0_ALPHA_EXT 0x8598 -#define GL_OPERAND1_ALPHA_EXT 0x8599 -#define GL_OPERAND2_ALPHA_EXT 0x859A - -#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine) - -#endif /* GL_EXT_texture_env_combine */ - -/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */ - -#ifndef GL_EXT_texture_env_dot3 -#define GL_EXT_texture_env_dot3 1 - -#define GL_DOT3_RGB_EXT 0x8740 -#define GL_DOT3_RGBA_EXT 0x8741 - -#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3) - -#endif /* GL_EXT_texture_env_dot3 */ - -/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */ - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_EXT_texture_filter_anisotropic 1 - -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - -#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic) - -#endif /* GL_EXT_texture_filter_anisotropic */ - -/* ------------------------- GL_EXT_texture_integer ------------------------ */ - -#ifndef GL_EXT_texture_integer -#define GL_EXT_texture_integer 1 - -#define GL_RGBA32UI_EXT 0x8D70 -#define GL_RGB32UI_EXT 0x8D71 -#define GL_ALPHA32UI_EXT 0x8D72 -#define GL_INTENSITY32UI_EXT 0x8D73 -#define GL_LUMINANCE32UI_EXT 0x8D74 -#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 -#define GL_RGBA16UI_EXT 0x8D76 -#define GL_RGB16UI_EXT 0x8D77 -#define GL_ALPHA16UI_EXT 0x8D78 -#define GL_INTENSITY16UI_EXT 0x8D79 -#define GL_LUMINANCE16UI_EXT 0x8D7A -#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B -#define GL_RGBA8UI_EXT 0x8D7C -#define GL_RGB8UI_EXT 0x8D7D -#define GL_ALPHA8UI_EXT 0x8D7E -#define GL_INTENSITY8UI_EXT 0x8D7F -#define GL_LUMINANCE8UI_EXT 0x8D80 -#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 -#define GL_RGBA32I_EXT 0x8D82 -#define GL_RGB32I_EXT 0x8D83 -#define GL_ALPHA32I_EXT 0x8D84 -#define GL_INTENSITY32I_EXT 0x8D85 -#define GL_LUMINANCE32I_EXT 0x8D86 -#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 -#define GL_RGBA16I_EXT 0x8D88 -#define GL_RGB16I_EXT 0x8D89 -#define GL_ALPHA16I_EXT 0x8D8A -#define GL_INTENSITY16I_EXT 0x8D8B -#define GL_LUMINANCE16I_EXT 0x8D8C -#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D -#define GL_RGBA8I_EXT 0x8D8E -#define GL_RGB8I_EXT 0x8D8F -#define GL_ALPHA8I_EXT 0x8D90 -#define GL_INTENSITY8I_EXT 0x8D91 -#define GL_LUMINANCE8I_EXT 0x8D92 -#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 -#define GL_RED_INTEGER_EXT 0x8D94 -#define GL_GREEN_INTEGER_EXT 0x8D95 -#define GL_BLUE_INTEGER_EXT 0x8D96 -#define GL_ALPHA_INTEGER_EXT 0x8D97 -#define GL_RGB_INTEGER_EXT 0x8D98 -#define GL_RGBA_INTEGER_EXT 0x8D99 -#define GL_BGR_INTEGER_EXT 0x8D9A -#define GL_BGRA_INTEGER_EXT 0x8D9B -#define GL_LUMINANCE_INTEGER_EXT 0x8D9C -#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D -#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E - -typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); -typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); -typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); -typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); - -#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT) -#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT) -#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT) -#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT) -#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT) -#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT) - -#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer) - -#endif /* GL_EXT_texture_integer */ - -/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */ - -#ifndef GL_EXT_texture_lod_bias -#define GL_EXT_texture_lod_bias 1 - -#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD -#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 -#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 - -#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias) - -#endif /* GL_EXT_texture_lod_bias */ - -/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */ - -#ifndef GL_EXT_texture_mirror_clamp -#define GL_EXT_texture_mirror_clamp 1 - -#define GL_MIRROR_CLAMP_EXT 0x8742 -#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 -#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 - -#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp) - -#endif /* GL_EXT_texture_mirror_clamp */ - -/* ------------------------- GL_EXT_texture_object ------------------------- */ - -#ifndef GL_EXT_texture_object -#define GL_EXT_texture_object 1 - -#define GL_TEXTURE_PRIORITY_EXT 0x8066 -#define GL_TEXTURE_RESIDENT_EXT 0x8067 -#define GL_TEXTURE_1D_BINDING_EXT 0x8068 -#define GL_TEXTURE_2D_BINDING_EXT 0x8069 -#define GL_TEXTURE_3D_BINDING_EXT 0x806A - -typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences); -typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); -typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures); -typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures); -typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); -typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities); - -#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT) -#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT) -#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT) -#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT) -#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT) -#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT) - -#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object) - -#endif /* GL_EXT_texture_object */ - -/* --------------------- GL_EXT_texture_perturb_normal --------------------- */ - -#ifndef GL_EXT_texture_perturb_normal -#define GL_EXT_texture_perturb_normal 1 - -#define GL_PERTURB_EXT 0x85AE -#define GL_TEXTURE_NORMAL_EXT 0x85AF - -typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); - -#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT) - -#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal) - -#endif /* GL_EXT_texture_perturb_normal */ - -/* ------------------------ GL_EXT_texture_rectangle ----------------------- */ - -#ifndef GL_EXT_texture_rectangle -#define GL_EXT_texture_rectangle 1 - -#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 - -#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle) - -#endif /* GL_EXT_texture_rectangle */ - -/* -------------------------- GL_EXT_texture_sRGB -------------------------- */ - -#ifndef GL_EXT_texture_sRGB -#define GL_EXT_texture_sRGB 1 - -#define GL_SRGB_EXT 0x8C40 -#define GL_SRGB8_EXT 0x8C41 -#define GL_SRGB_ALPHA_EXT 0x8C42 -#define GL_SRGB8_ALPHA8_EXT 0x8C43 -#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 -#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 -#define GL_SLUMINANCE_EXT 0x8C46 -#define GL_SLUMINANCE8_EXT 0x8C47 -#define GL_COMPRESSED_SRGB_EXT 0x8C48 -#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 -#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A -#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B -#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F - -#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB) - -#endif /* GL_EXT_texture_sRGB */ - -/* ----------------------- GL_EXT_texture_sRGB_decode ---------------------- */ - -#ifndef GL_EXT_texture_sRGB_decode -#define GL_EXT_texture_sRGB_decode 1 - -#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 -#define GL_DECODE_EXT 0x8A49 -#define GL_SKIP_DECODE_EXT 0x8A4A - -#define GLEW_EXT_texture_sRGB_decode GLEW_GET_VAR(__GLEW_EXT_texture_sRGB_decode) - -#endif /* GL_EXT_texture_sRGB_decode */ - -/* --------------------- GL_EXT_texture_shared_exponent -------------------- */ - -#ifndef GL_EXT_texture_shared_exponent -#define GL_EXT_texture_shared_exponent 1 - -#define GL_RGB9_E5_EXT 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E -#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F - -#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent) - -#endif /* GL_EXT_texture_shared_exponent */ - -/* -------------------------- GL_EXT_texture_snorm ------------------------- */ - -#ifndef GL_EXT_texture_snorm -#define GL_EXT_texture_snorm 1 - -#define GL_RED_SNORM 0x8F90 -#define GL_RG_SNORM 0x8F91 -#define GL_RGB_SNORM 0x8F92 -#define GL_RGBA_SNORM 0x8F93 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGB8_SNORM 0x8F96 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_R16_SNORM 0x8F98 -#define GL_RG16_SNORM 0x8F99 -#define GL_RGB16_SNORM 0x8F9A -#define GL_RGBA16_SNORM 0x8F9B -#define GL_SIGNED_NORMALIZED 0x8F9C -#define GL_ALPHA_SNORM 0x9010 -#define GL_LUMINANCE_SNORM 0x9011 -#define GL_LUMINANCE_ALPHA_SNORM 0x9012 -#define GL_INTENSITY_SNORM 0x9013 -#define GL_ALPHA8_SNORM 0x9014 -#define GL_LUMINANCE8_SNORM 0x9015 -#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 -#define GL_INTENSITY8_SNORM 0x9017 -#define GL_ALPHA16_SNORM 0x9018 -#define GL_LUMINANCE16_SNORM 0x9019 -#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A -#define GL_INTENSITY16_SNORM 0x901B - -#define GLEW_EXT_texture_snorm GLEW_GET_VAR(__GLEW_EXT_texture_snorm) - -#endif /* GL_EXT_texture_snorm */ - -/* ------------------------- GL_EXT_texture_swizzle ------------------------ */ - -#ifndef GL_EXT_texture_swizzle -#define GL_EXT_texture_swizzle 1 - -#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 -#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 -#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 -#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 -#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 - -#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle) - -#endif /* GL_EXT_texture_swizzle */ - -/* --------------------------- GL_EXT_timer_query -------------------------- */ - -#ifndef GL_EXT_timer_query -#define GL_EXT_timer_query 1 - -#define GL_TIME_ELAPSED_EXT 0x88BF - -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); -typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); - -#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT) -#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT) - -#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query) - -#endif /* GL_EXT_timer_query */ - -/* ----------------------- GL_EXT_transform_feedback ----------------------- */ - -#ifndef GL_EXT_transform_feedback -#define GL_EXT_transform_feedback 1 - -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 -#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 -#define GL_RASTERIZER_DISCARD_EXT 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B -#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C -#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F - -typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); -typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); -typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name); -typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode); - -#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT) -#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT) -#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT) -#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT) -#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT) -#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT) -#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT) - -#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback) - -#endif /* GL_EXT_transform_feedback */ - -/* -------------------------- GL_EXT_vertex_array -------------------------- */ - -#ifndef GL_EXT_vertex_array -#define GL_EXT_vertex_array 1 - -#define GL_DOUBLE_EXT 0x140A -#define GL_VERTEX_ARRAY_EXT 0x8074 -#define GL_NORMAL_ARRAY_EXT 0x8075 -#define GL_COLOR_ARRAY_EXT 0x8076 -#define GL_INDEX_ARRAY_EXT 0x8077 -#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 -#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 -#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A -#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B -#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C -#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D -#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E -#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F -#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 -#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 -#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 -#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 -#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 -#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 -#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 -#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 -#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 -#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 -#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A -#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B -#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C -#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D -#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E -#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F -#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 -#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 -#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 -#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 - -typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); -typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); -typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); -typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); - -#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) -#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) -#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT) -#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT) -#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT) -#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT) -#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT) -#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT) - -#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array) - -#endif /* GL_EXT_vertex_array */ - -/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */ - -#ifndef GL_EXT_vertex_array_bgra -#define GL_EXT_vertex_array_bgra 1 - -#define GL_BGRA 0x80E1 - -#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra) - -#endif /* GL_EXT_vertex_array_bgra */ - -/* ----------------------- GL_EXT_vertex_attrib_64bit ---------------------- */ - -#ifndef GL_EXT_vertex_attrib_64bit -#define GL_EXT_vertex_attrib_64bit 1 - -#define GL_DOUBLE_MAT2_EXT 0x8F46 -#define GL_DOUBLE_MAT3_EXT 0x8F47 -#define GL_DOUBLE_MAT4_EXT 0x8F48 -#define GL_DOUBLE_MAT2x3_EXT 0x8F49 -#define GL_DOUBLE_MAT2x4_EXT 0x8F4A -#define GL_DOUBLE_MAT3x2_EXT 0x8F4B -#define GL_DOUBLE_MAT3x4_EXT 0x8F4C -#define GL_DOUBLE_MAT4x2_EXT 0x8F4D -#define GL_DOUBLE_MAT4x3_EXT 0x8F4E -#define GL_DOUBLE_VEC2_EXT 0x8FFC -#define GL_DOUBLE_VEC3_EXT 0x8FFD -#define GL_DOUBLE_VEC4_EXT 0x8FFE - -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); - -#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT) -#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT) -#define glVertexAttribL1dEXT GLEW_GET_FUN(__glewVertexAttribL1dEXT) -#define glVertexAttribL1dvEXT GLEW_GET_FUN(__glewVertexAttribL1dvEXT) -#define glVertexAttribL2dEXT GLEW_GET_FUN(__glewVertexAttribL2dEXT) -#define glVertexAttribL2dvEXT GLEW_GET_FUN(__glewVertexAttribL2dvEXT) -#define glVertexAttribL3dEXT GLEW_GET_FUN(__glewVertexAttribL3dEXT) -#define glVertexAttribL3dvEXT GLEW_GET_FUN(__glewVertexAttribL3dvEXT) -#define glVertexAttribL4dEXT GLEW_GET_FUN(__glewVertexAttribL4dEXT) -#define glVertexAttribL4dvEXT GLEW_GET_FUN(__glewVertexAttribL4dvEXT) -#define glVertexAttribLPointerEXT GLEW_GET_FUN(__glewVertexAttribLPointerEXT) - -#define GLEW_EXT_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_EXT_vertex_attrib_64bit) - -#endif /* GL_EXT_vertex_attrib_64bit */ - -/* -------------------------- GL_EXT_vertex_shader ------------------------- */ - -#ifndef GL_EXT_vertex_shader -#define GL_EXT_vertex_shader 1 - -#define GL_VERTEX_SHADER_EXT 0x8780 -#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 -#define GL_OP_INDEX_EXT 0x8782 -#define GL_OP_NEGATE_EXT 0x8783 -#define GL_OP_DOT3_EXT 0x8784 -#define GL_OP_DOT4_EXT 0x8785 -#define GL_OP_MUL_EXT 0x8786 -#define GL_OP_ADD_EXT 0x8787 -#define GL_OP_MADD_EXT 0x8788 -#define GL_OP_FRAC_EXT 0x8789 -#define GL_OP_MAX_EXT 0x878A -#define GL_OP_MIN_EXT 0x878B -#define GL_OP_SET_GE_EXT 0x878C -#define GL_OP_SET_LT_EXT 0x878D -#define GL_OP_CLAMP_EXT 0x878E -#define GL_OP_FLOOR_EXT 0x878F -#define GL_OP_ROUND_EXT 0x8790 -#define GL_OP_EXP_BASE_2_EXT 0x8791 -#define GL_OP_LOG_BASE_2_EXT 0x8792 -#define GL_OP_POWER_EXT 0x8793 -#define GL_OP_RECIP_EXT 0x8794 -#define GL_OP_RECIP_SQRT_EXT 0x8795 -#define GL_OP_SUB_EXT 0x8796 -#define GL_OP_CROSS_PRODUCT_EXT 0x8797 -#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 -#define GL_OP_MOV_EXT 0x8799 -#define GL_OUTPUT_VERTEX_EXT 0x879A -#define GL_OUTPUT_COLOR0_EXT 0x879B -#define GL_OUTPUT_COLOR1_EXT 0x879C -#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D -#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E -#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F -#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 -#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 -#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 -#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 -#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 -#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 -#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 -#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 -#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 -#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 -#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA -#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB -#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC -#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD -#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE -#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF -#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 -#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 -#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 -#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 -#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 -#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 -#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 -#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 -#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 -#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 -#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA -#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB -#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC -#define GL_OUTPUT_FOG_EXT 0x87BD -#define GL_SCALAR_EXT 0x87BE -#define GL_VECTOR_EXT 0x87BF -#define GL_MATRIX_EXT 0x87C0 -#define GL_VARIANT_EXT 0x87C1 -#define GL_INVARIANT_EXT 0x87C2 -#define GL_LOCAL_CONSTANT_EXT 0x87C3 -#define GL_LOCAL_EXT 0x87C4 -#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 -#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 -#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 -#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 -#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE -#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF -#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 -#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 -#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 -#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 -#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 -#define GL_X_EXT 0x87D5 -#define GL_Y_EXT 0x87D6 -#define GL_Z_EXT 0x87D7 -#define GL_W_EXT 0x87D8 -#define GL_NEGATIVE_X_EXT 0x87D9 -#define GL_NEGATIVE_Y_EXT 0x87DA -#define GL_NEGATIVE_Z_EXT 0x87DB -#define GL_NEGATIVE_W_EXT 0x87DC -#define GL_ZERO_EXT 0x87DD -#define GL_ONE_EXT 0x87DE -#define GL_NEGATIVE_ONE_EXT 0x87DF -#define GL_NORMALIZED_RANGE_EXT 0x87E0 -#define GL_FULL_RANGE_EXT 0x87E1 -#define GL_CURRENT_VERTEX_EXT 0x87E2 -#define GL_MVP_MATRIX_EXT 0x87E3 -#define GL_VARIANT_VALUE_EXT 0x87E4 -#define GL_VARIANT_DATATYPE_EXT 0x87E5 -#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 -#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 -#define GL_VARIANT_ARRAY_EXT 0x87E8 -#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 -#define GL_INVARIANT_VALUE_EXT 0x87EA -#define GL_INVARIANT_DATATYPE_EXT 0x87EB -#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC -#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED - -typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void); -typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); -typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); -typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value); -typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); -typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); -typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void); -typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); -typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components); -typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); -typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); -typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); -typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); -typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); -typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); -typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); -typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data); -typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); -typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); -typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); -typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); -typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); -typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); -typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); -typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); -typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr); -typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr); -typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); - -#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT) -#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT) -#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT) -#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT) -#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT) -#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT) -#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT) -#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT) -#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT) -#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT) -#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT) -#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT) -#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT) -#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT) -#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT) -#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT) -#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT) -#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT) -#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT) -#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT) -#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT) -#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT) -#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT) -#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT) -#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT) -#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT) -#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT) -#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT) -#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT) -#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT) -#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT) -#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT) -#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT) -#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT) -#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT) -#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT) -#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT) -#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT) -#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT) -#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT) -#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT) -#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT) - -#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader) - -#endif /* GL_EXT_vertex_shader */ - -/* ------------------------ GL_EXT_vertex_weighting ------------------------ */ - -#ifndef GL_EXT_vertex_weighting -#define GL_EXT_vertex_weighting 1 - -#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 -#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6 -#define GL_MODELVIEW0_EXT 0x1700 -#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 -#define GL_MODELVIEW1_MATRIX_EXT 0x8506 -#define GL_VERTEX_WEIGHTING_EXT 0x8509 -#define GL_MODELVIEW1_EXT 0x850A -#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B -#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C -#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D -#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E -#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F -#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 - -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); - -#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT) -#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT) -#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT) - -#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting) - -#endif /* GL_EXT_vertex_weighting */ - -/* ------------------------- GL_EXT_x11_sync_object ------------------------ */ - -#ifndef GL_EXT_x11_sync_object -#define GL_EXT_x11_sync_object 1 - -#define GL_SYNC_X11_FENCE_EXT 0x90E1 - -typedef GLsync (GLAPIENTRY * PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags); - -#define glImportSyncEXT GLEW_GET_FUN(__glewImportSyncEXT) - -#define GLEW_EXT_x11_sync_object GLEW_GET_VAR(__GLEW_EXT_x11_sync_object) - -#endif /* GL_EXT_x11_sync_object */ - -/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */ - -#ifndef GL_GREMEDY_frame_terminator -#define GL_GREMEDY_frame_terminator 1 - -typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); - -#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY) - -#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator) - -#endif /* GL_GREMEDY_frame_terminator */ - -/* ------------------------ GL_GREMEDY_string_marker ----------------------- */ - -#ifndef GL_GREMEDY_string_marker -#define GL_GREMEDY_string_marker 1 - -typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string); - -#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) - -#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker) - -#endif /* GL_GREMEDY_string_marker */ - -/* --------------------- GL_HP_convolution_border_modes -------------------- */ - -#ifndef GL_HP_convolution_border_modes -#define GL_HP_convolution_border_modes 1 - -#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes) - -#endif /* GL_HP_convolution_border_modes */ - -/* ------------------------- GL_HP_image_transform ------------------------- */ - -#ifndef GL_HP_image_transform -#define GL_HP_image_transform 1 - -typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param); -typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param); -typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); - -#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP) -#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP) -#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP) -#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP) -#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP) -#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP) - -#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform) - -#endif /* GL_HP_image_transform */ - -/* -------------------------- GL_HP_occlusion_test ------------------------- */ - -#ifndef GL_HP_occlusion_test -#define GL_HP_occlusion_test 1 - -#define GL_OCCLUSION_TEST_HP 0x8165 -#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 - -#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test) - -#endif /* GL_HP_occlusion_test */ - -/* ------------------------- GL_HP_texture_lighting ------------------------ */ - -#ifndef GL_HP_texture_lighting -#define GL_HP_texture_lighting 1 - -#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting) - -#endif /* GL_HP_texture_lighting */ - -/* --------------------------- GL_IBM_cull_vertex -------------------------- */ - -#ifndef GL_IBM_cull_vertex -#define GL_IBM_cull_vertex 1 - -#define GL_CULL_VERTEX_IBM 103050 - -#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex) - -#endif /* GL_IBM_cull_vertex */ - -/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */ - -#ifndef GL_IBM_multimode_draw_arrays -#define GL_IBM_multimode_draw_arrays 1 - -typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); -typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride); - -#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM) -#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM) - -#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays) - -#endif /* GL_IBM_multimode_draw_arrays */ - -/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */ - -#ifndef GL_IBM_rasterpos_clip -#define GL_IBM_rasterpos_clip 1 - -#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010 - -#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip) - -#endif /* GL_IBM_rasterpos_clip */ - -/* --------------------------- GL_IBM_static_data -------------------------- */ - -#ifndef GL_IBM_static_data -#define GL_IBM_static_data 1 - -#define GL_ALL_STATIC_DATA_IBM 103060 -#define GL_STATIC_VERTEX_ARRAY_IBM 103061 - -#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data) - -#endif /* GL_IBM_static_data */ - -/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */ - -#ifndef GL_IBM_texture_mirrored_repeat -#define GL_IBM_texture_mirrored_repeat 1 - -#define GL_MIRRORED_REPEAT_IBM 0x8370 - -#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat) - -#endif /* GL_IBM_texture_mirrored_repeat */ - -/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */ - -#ifndef GL_IBM_vertex_array_lists -#define GL_IBM_vertex_array_lists 1 - -#define GL_VERTEX_ARRAY_LIST_IBM 103070 -#define GL_NORMAL_ARRAY_LIST_IBM 103071 -#define GL_COLOR_ARRAY_LIST_IBM 103072 -#define GL_INDEX_ARRAY_LIST_IBM 103073 -#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 -#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 -#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 -#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 -#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 -#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 -#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 -#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 -#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 -#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 -#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 -#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 - -typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); - -#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM) -#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM) -#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM) -#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM) -#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM) -#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM) -#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM) -#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM) - -#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists) - -#endif /* GL_IBM_vertex_array_lists */ - -/* -------------------------- GL_INGR_color_clamp -------------------------- */ - -#ifndef GL_INGR_color_clamp -#define GL_INGR_color_clamp 1 - -#define GL_RED_MIN_CLAMP_INGR 0x8560 -#define GL_GREEN_MIN_CLAMP_INGR 0x8561 -#define GL_BLUE_MIN_CLAMP_INGR 0x8562 -#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 -#define GL_RED_MAX_CLAMP_INGR 0x8564 -#define GL_GREEN_MAX_CLAMP_INGR 0x8565 -#define GL_BLUE_MAX_CLAMP_INGR 0x8566 -#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 - -#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp) - -#endif /* GL_INGR_color_clamp */ - -/* ------------------------- GL_INGR_interlace_read ------------------------ */ - -#ifndef GL_INGR_interlace_read -#define GL_INGR_interlace_read 1 - -#define GL_INTERLACE_READ_INGR 0x8568 - -#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read) - -#endif /* GL_INGR_interlace_read */ - -/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */ - -#ifndef GL_INTEL_parallel_arrays -#define GL_INTEL_parallel_arrays 1 - -#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 -#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 -#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 -#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 -#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 - -typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); -typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer); -typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); - -#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL) -#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL) -#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL) -#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL) - -#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays) - -#endif /* GL_INTEL_parallel_arrays */ - -/* ------------------------ GL_INTEL_texture_scissor ----------------------- */ - -#ifndef GL_INTEL_texture_scissor -#define GL_INTEL_texture_scissor 1 - -typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc); -typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh); - -#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL) -#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL) - -#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor) - -#endif /* GL_INTEL_texture_scissor */ - -/* -------------------------- GL_KTX_buffer_region ------------------------- */ - -#ifndef GL_KTX_buffer_region -#define GL_KTX_buffer_region 1 - -#define GL_KTX_FRONT_REGION 0x0 -#define GL_KTX_BACK_REGION 0x1 -#define GL_KTX_Z_REGION 0x2 -#define GL_KTX_STENCIL_REGION 0x3 - -typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void); -typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region); -typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); -typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region); -typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); - -#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT) -#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT) -#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT) -#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT) -#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT) - -#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region) - -#endif /* GL_KTX_buffer_region */ - -/* ------------------------- GL_MESAX_texture_stack ------------------------ */ - -#ifndef GL_MESAX_texture_stack -#define GL_MESAX_texture_stack 1 - -#define GL_TEXTURE_1D_STACK_MESAX 0x8759 -#define GL_TEXTURE_2D_STACK_MESAX 0x875A -#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B -#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C -#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D -#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E - -#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack) - -#endif /* GL_MESAX_texture_stack */ - -/* -------------------------- GL_MESA_pack_invert -------------------------- */ - -#ifndef GL_MESA_pack_invert -#define GL_MESA_pack_invert 1 - -#define GL_PACK_INVERT_MESA 0x8758 - -#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert) - -#endif /* GL_MESA_pack_invert */ - -/* ------------------------- GL_MESA_resize_buffers ------------------------ */ - -#ifndef GL_MESA_resize_buffers -#define GL_MESA_resize_buffers 1 - -typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); - -#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA) - -#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers) - -#endif /* GL_MESA_resize_buffers */ - -/* --------------------------- GL_MESA_window_pos -------------------------- */ - -#ifndef GL_MESA_window_pos -#define GL_MESA_window_pos 1 - -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); - -#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA) -#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA) -#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA) -#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA) -#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA) -#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA) -#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA) -#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA) -#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA) -#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA) -#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA) -#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA) -#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA) -#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA) -#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA) -#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA) -#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA) -#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA) -#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA) -#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA) -#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA) -#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA) -#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA) -#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA) - -#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos) - -#endif /* GL_MESA_window_pos */ - -/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */ - -#ifndef GL_MESA_ycbcr_texture -#define GL_MESA_ycbcr_texture 1 - -#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB -#define GL_YCBCR_MESA 0x8757 - -#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture) - -#endif /* GL_MESA_ycbcr_texture */ - -/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */ - -#ifndef GL_NVX_gpu_memory_info -#define GL_NVX_gpu_memory_info 1 - -#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 -#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 -#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 -#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A -#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B - -#define GLEW_NVX_gpu_memory_info GLEW_GET_VAR(__GLEW_NVX_gpu_memory_info) - -#endif /* GL_NVX_gpu_memory_info */ - -/* --------------------------- GL_NV_blend_square -------------------------- */ - -#ifndef GL_NV_blend_square -#define GL_NV_blend_square 1 - -#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square) - -#endif /* GL_NV_blend_square */ - -/* ------------------------ GL_NV_conditional_render ----------------------- */ - -#ifndef GL_NV_conditional_render -#define GL_NV_conditional_render 1 - -#define GL_QUERY_WAIT_NV 0x8E13 -#define GL_QUERY_NO_WAIT_NV 0x8E14 -#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 -#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 - -typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); -typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void); - -#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV) -#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV) - -#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render) - -#endif /* GL_NV_conditional_render */ - -/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */ - -#ifndef GL_NV_copy_depth_to_color -#define GL_NV_copy_depth_to_color 1 - -#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E -#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F - -#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color) - -#endif /* GL_NV_copy_depth_to_color */ - -/* ---------------------------- GL_NV_copy_image --------------------------- */ - -#ifndef GL_NV_copy_image -#define GL_NV_copy_image 1 - -typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); - -#define glCopyImageSubDataNV GLEW_GET_FUN(__glewCopyImageSubDataNV) - -#define GLEW_NV_copy_image GLEW_GET_VAR(__GLEW_NV_copy_image) - -#endif /* GL_NV_copy_image */ - -/* ------------------------ GL_NV_depth_buffer_float ----------------------- */ - -#ifndef GL_NV_depth_buffer_float -#define GL_NV_depth_buffer_float 1 - -#define GL_DEPTH_COMPONENT32F_NV 0x8DAB -#define GL_DEPTH32F_STENCIL8_NV 0x8DAC -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD -#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF - -typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); -typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); -typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); - -#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV) -#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV) -#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV) - -#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float) - -#endif /* GL_NV_depth_buffer_float */ - -/* --------------------------- GL_NV_depth_clamp --------------------------- */ - -#ifndef GL_NV_depth_clamp -#define GL_NV_depth_clamp 1 - -#define GL_DEPTH_CLAMP_NV 0x864F - -#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp) - -#endif /* GL_NV_depth_clamp */ - -/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */ - -#ifndef GL_NV_depth_range_unclamped -#define GL_NV_depth_range_unclamped 1 - -#define GL_SAMPLE_COUNT_BITS_NV 0x8864 -#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865 -#define GL_QUERY_RESULT_NV 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867 -#define GL_SAMPLE_COUNT_NV 0x8914 - -#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped) - -#endif /* GL_NV_depth_range_unclamped */ - -/* ---------------------------- GL_NV_evaluators --------------------------- */ - -#ifndef GL_NV_evaluators -#define GL_NV_evaluators 1 - -#define GL_EVAL_2D_NV 0x86C0 -#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 -#define GL_MAP_TESSELLATION_NV 0x86C2 -#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 -#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 -#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 -#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 -#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 -#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 -#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 -#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA -#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB -#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC -#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD -#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE -#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF -#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 -#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 -#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 -#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 -#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 -#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 -#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 -#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 - -typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); -typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points); -typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points); -typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); - -#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV) -#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV) -#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV) -#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV) -#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV) -#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV) -#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV) -#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV) -#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV) - -#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators) - -#endif /* GL_NV_evaluators */ - -/* ----------------------- GL_NV_explicit_multisample ---------------------- */ - -#ifndef GL_NV_explicit_multisample -#define GL_NV_explicit_multisample 1 - -#define GL_SAMPLE_POSITION_NV 0x8E50 -#define GL_SAMPLE_MASK_NV 0x8E51 -#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 -#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 -#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 -#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 -#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 -#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 -#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 -#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 - -typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val); -typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); - -#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV) -#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV) -#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV) - -#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample) - -#endif /* GL_NV_explicit_multisample */ - -/* ------------------------------ GL_NV_fence ------------------------------ */ - -#ifndef GL_NV_fence -#define GL_NV_fence 1 - -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 - -typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences); -typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); -typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences); -typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence); -typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); -typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); - -#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV) -#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV) -#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV) -#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV) -#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV) -#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV) -#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV) - -#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence) - -#endif /* GL_NV_fence */ - -/* --------------------------- GL_NV_float_buffer -------------------------- */ - -#ifndef GL_NV_float_buffer -#define GL_NV_float_buffer 1 - -#define GL_FLOAT_R_NV 0x8880 -#define GL_FLOAT_RG_NV 0x8881 -#define GL_FLOAT_RGB_NV 0x8882 -#define GL_FLOAT_RGBA_NV 0x8883 -#define GL_FLOAT_R16_NV 0x8884 -#define GL_FLOAT_R32_NV 0x8885 -#define GL_FLOAT_RG16_NV 0x8886 -#define GL_FLOAT_RG32_NV 0x8887 -#define GL_FLOAT_RGB16_NV 0x8888 -#define GL_FLOAT_RGB32_NV 0x8889 -#define GL_FLOAT_RGBA16_NV 0x888A -#define GL_FLOAT_RGBA32_NV 0x888B -#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C -#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D -#define GL_FLOAT_RGBA_MODE_NV 0x888E - -#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer) - -#endif /* GL_NV_float_buffer */ - -/* --------------------------- GL_NV_fog_distance -------------------------- */ - -#ifndef GL_NV_fog_distance -#define GL_NV_fog_distance 1 - -#define GL_FOG_DISTANCE_MODE_NV 0x855A -#define GL_EYE_RADIAL_NV 0x855B -#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C - -#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance) - -#endif /* GL_NV_fog_distance */ - -/* ------------------------- GL_NV_fragment_program ------------------------ */ - -#ifndef GL_NV_fragment_program -#define GL_NV_fragment_program 1 - -#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 -#define GL_FRAGMENT_PROGRAM_NV 0x8870 -#define GL_MAX_TEXTURE_COORDS_NV 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 -#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 -#define GL_PROGRAM_ERROR_STRING_NV 0x8874 - -typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]); -typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]); - -#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV) -#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV) -#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV) -#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV) -#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV) -#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV) - -#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program) - -#endif /* GL_NV_fragment_program */ - -/* ------------------------ GL_NV_fragment_program2 ------------------------ */ - -#ifndef GL_NV_fragment_program2 -#define GL_NV_fragment_program2 1 - -#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 -#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 -#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 -#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 -#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 - -#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2) - -#endif /* GL_NV_fragment_program2 */ - -/* ------------------------ GL_NV_fragment_program4 ------------------------ */ - -#ifndef GL_NV_fragment_program4 -#define GL_NV_fragment_program4 1 - -#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4) - -#endif /* GL_NV_fragment_program4 */ - -/* --------------------- GL_NV_fragment_program_option --------------------- */ - -#ifndef GL_NV_fragment_program_option -#define GL_NV_fragment_program_option 1 - -#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option) - -#endif /* GL_NV_fragment_program_option */ - -/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */ - -#ifndef GL_NV_framebuffer_multisample_coverage -#define GL_NV_framebuffer_multisample_coverage 1 - -#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB -#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 -#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 -#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 - -typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); - -#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV) - -#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage) - -#endif /* GL_NV_framebuffer_multisample_coverage */ - -/* ------------------------ GL_NV_geometry_program4 ------------------------ */ - -#ifndef GL_NV_geometry_program4 -#define GL_NV_geometry_program4 1 - -#define GL_GEOMETRY_PROGRAM_NV 0x8C26 -#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 -#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 - -typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); - -#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV) - -#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4) - -#endif /* GL_NV_geometry_program4 */ - -/* ------------------------- GL_NV_geometry_shader4 ------------------------ */ - -#ifndef GL_NV_geometry_shader4 -#define GL_NV_geometry_shader4 1 - -#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4) - -#endif /* GL_NV_geometry_shader4 */ - -/* --------------------------- GL_NV_gpu_program4 -------------------------- */ - -#ifndef GL_NV_gpu_program4 -#define GL_NV_gpu_program4 1 - -#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 -#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 -#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 -#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 -#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 -#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 -#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 - -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); - -#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV) -#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV) -#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV) -#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV) -#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV) -#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV) -#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV) -#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV) -#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV) -#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV) -#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV) -#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV) - -#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4) - -#endif /* GL_NV_gpu_program4 */ - -/* --------------------------- GL_NV_gpu_program5 -------------------------- */ - -#ifndef GL_NV_gpu_program5 -#define GL_NV_gpu_program5 1 - -#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C -#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D -#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E -#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F - -#define GLEW_NV_gpu_program5 GLEW_GET_VAR(__GLEW_NV_gpu_program5) - -#endif /* GL_NV_gpu_program5 */ - -/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */ - -#ifndef GL_NV_gpu_program_fp64 -#define GL_NV_gpu_program_fp64 1 - -#define GLEW_NV_gpu_program_fp64 GLEW_GET_VAR(__GLEW_NV_gpu_program_fp64) - -#endif /* GL_NV_gpu_program_fp64 */ - -/* --------------------------- GL_NV_gpu_shader5 --------------------------- */ - -#ifndef GL_NV_gpu_shader5 -#define GL_NV_gpu_shader5 1 - -#define GL_INT64_NV 0x140E -#define GL_UNSIGNED_INT64_NV 0x140F -#define GL_INT8_NV 0x8FE0 -#define GL_INT8_VEC2_NV 0x8FE1 -#define GL_INT8_VEC3_NV 0x8FE2 -#define GL_INT8_VEC4_NV 0x8FE3 -#define GL_INT16_NV 0x8FE4 -#define GL_INT16_VEC2_NV 0x8FE5 -#define GL_INT16_VEC3_NV 0x8FE6 -#define GL_INT16_VEC4_NV 0x8FE7 -#define GL_INT64_VEC2_NV 0x8FE9 -#define GL_INT64_VEC3_NV 0x8FEA -#define GL_INT64_VEC4_NV 0x8FEB -#define GL_UNSIGNED_INT8_NV 0x8FEC -#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED -#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE -#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF -#define GL_UNSIGNED_INT16_NV 0x8FF0 -#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 -#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 -#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 -#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 -#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 -#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 -#define GL_FLOAT16_NV 0x8FF8 -#define GL_FLOAT16_VEC2_NV 0x8FF9 -#define GL_FLOAT16_VEC3_NV 0x8FFA -#define GL_FLOAT16_VEC4_NV 0x8FFB - -typedef void (GLAPIENTRY * PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT* params); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); -typedef void (GLAPIENTRY * PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); -typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); -typedef void (GLAPIENTRY * PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); -typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); -typedef void (GLAPIENTRY * PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -typedef void (GLAPIENTRY * PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); - -#define glGetUniformi64vNV GLEW_GET_FUN(__glewGetUniformi64vNV) -#define glGetUniformui64vNV GLEW_GET_FUN(__glewGetUniformui64vNV) -#define glProgramUniform1i64NV GLEW_GET_FUN(__glewProgramUniform1i64NV) -#define glProgramUniform1i64vNV GLEW_GET_FUN(__glewProgramUniform1i64vNV) -#define glProgramUniform1ui64NV GLEW_GET_FUN(__glewProgramUniform1ui64NV) -#define glProgramUniform1ui64vNV GLEW_GET_FUN(__glewProgramUniform1ui64vNV) -#define glProgramUniform2i64NV GLEW_GET_FUN(__glewProgramUniform2i64NV) -#define glProgramUniform2i64vNV GLEW_GET_FUN(__glewProgramUniform2i64vNV) -#define glProgramUniform2ui64NV GLEW_GET_FUN(__glewProgramUniform2ui64NV) -#define glProgramUniform2ui64vNV GLEW_GET_FUN(__glewProgramUniform2ui64vNV) -#define glProgramUniform3i64NV GLEW_GET_FUN(__glewProgramUniform3i64NV) -#define glProgramUniform3i64vNV GLEW_GET_FUN(__glewProgramUniform3i64vNV) -#define glProgramUniform3ui64NV GLEW_GET_FUN(__glewProgramUniform3ui64NV) -#define glProgramUniform3ui64vNV GLEW_GET_FUN(__glewProgramUniform3ui64vNV) -#define glProgramUniform4i64NV GLEW_GET_FUN(__glewProgramUniform4i64NV) -#define glProgramUniform4i64vNV GLEW_GET_FUN(__glewProgramUniform4i64vNV) -#define glProgramUniform4ui64NV GLEW_GET_FUN(__glewProgramUniform4ui64NV) -#define glProgramUniform4ui64vNV GLEW_GET_FUN(__glewProgramUniform4ui64vNV) -#define glUniform1i64NV GLEW_GET_FUN(__glewUniform1i64NV) -#define glUniform1i64vNV GLEW_GET_FUN(__glewUniform1i64vNV) -#define glUniform1ui64NV GLEW_GET_FUN(__glewUniform1ui64NV) -#define glUniform1ui64vNV GLEW_GET_FUN(__glewUniform1ui64vNV) -#define glUniform2i64NV GLEW_GET_FUN(__glewUniform2i64NV) -#define glUniform2i64vNV GLEW_GET_FUN(__glewUniform2i64vNV) -#define glUniform2ui64NV GLEW_GET_FUN(__glewUniform2ui64NV) -#define glUniform2ui64vNV GLEW_GET_FUN(__glewUniform2ui64vNV) -#define glUniform3i64NV GLEW_GET_FUN(__glewUniform3i64NV) -#define glUniform3i64vNV GLEW_GET_FUN(__glewUniform3i64vNV) -#define glUniform3ui64NV GLEW_GET_FUN(__glewUniform3ui64NV) -#define glUniform3ui64vNV GLEW_GET_FUN(__glewUniform3ui64vNV) -#define glUniform4i64NV GLEW_GET_FUN(__glewUniform4i64NV) -#define glUniform4i64vNV GLEW_GET_FUN(__glewUniform4i64vNV) -#define glUniform4ui64NV GLEW_GET_FUN(__glewUniform4ui64NV) -#define glUniform4ui64vNV GLEW_GET_FUN(__glewUniform4ui64vNV) - -#define GLEW_NV_gpu_shader5 GLEW_GET_VAR(__GLEW_NV_gpu_shader5) - -#endif /* GL_NV_gpu_shader5 */ - -/* ---------------------------- GL_NV_half_float --------------------------- */ - -#ifndef GL_NV_half_float -#define GL_NV_half_float 1 - -#define GL_HALF_FLOAT_NV 0x140B - -typedef unsigned short GLhalf; - -typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); -typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha); -typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog); -typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz); -typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s); -typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r); -typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q); -typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y); -typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z); -typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w); -typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight); -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight); - -#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV) -#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV) -#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV) -#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV) -#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV) -#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV) -#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV) -#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV) -#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV) -#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV) -#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV) -#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV) -#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV) -#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV) -#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV) -#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV) -#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV) -#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV) -#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV) -#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV) -#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV) -#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV) -#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV) -#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV) -#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV) -#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV) -#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV) -#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV) -#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV) -#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV) -#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV) -#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV) -#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV) -#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV) -#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV) -#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV) -#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV) -#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV) -#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV) -#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV) -#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV) -#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV) -#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV) -#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV) -#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV) -#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV) - -#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float) - -#endif /* GL_NV_half_float */ - -/* ------------------------ GL_NV_light_max_exponent ----------------------- */ - -#ifndef GL_NV_light_max_exponent -#define GL_NV_light_max_exponent 1 - -#define GL_MAX_SHININESS_NV 0x8504 -#define GL_MAX_SPOT_EXPONENT_NV 0x8505 - -#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent) - -#endif /* GL_NV_light_max_exponent */ - -/* ----------------------- GL_NV_multisample_coverage ---------------------- */ - -#ifndef GL_NV_multisample_coverage -#define GL_NV_multisample_coverage 1 - -#define GL_COVERAGE_SAMPLES_NV 0x80A9 -#define GL_COLOR_SAMPLES_NV 0x8E20 - -#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage) - -#endif /* GL_NV_multisample_coverage */ - -/* --------------------- GL_NV_multisample_filter_hint --------------------- */ - -#ifndef GL_NV_multisample_filter_hint -#define GL_NV_multisample_filter_hint 1 - -#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 - -#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint) - -#endif /* GL_NV_multisample_filter_hint */ - -/* ------------------------- GL_NV_occlusion_query ------------------------- */ - -#ifndef GL_NV_occlusion_query -#define GL_NV_occlusion_query 1 - -#define GL_PIXEL_COUNTER_BITS_NV 0x8864 -#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 -#define GL_PIXEL_COUNT_NV 0x8866 -#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 - -typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids); -typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void); -typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids); -typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); - -#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV) -#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV) -#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV) -#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV) -#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV) -#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV) -#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV) - -#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query) - -#endif /* GL_NV_occlusion_query */ - -/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */ - -#ifndef GL_NV_packed_depth_stencil -#define GL_NV_packed_depth_stencil 1 - -#define GL_DEPTH_STENCIL_NV 0x84F9 -#define GL_UNSIGNED_INT_24_8_NV 0x84FA - -#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil) - -#endif /* GL_NV_packed_depth_stencil */ - -/* --------------------- GL_NV_parameter_buffer_object --------------------- */ - -#ifndef GL_NV_parameter_buffer_object -#define GL_NV_parameter_buffer_object 1 - -#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 -#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 -#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 -#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 -#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 - -typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); -typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); - -#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV) -#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV) -#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV) - -#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object) - -#endif /* GL_NV_parameter_buffer_object */ - -/* --------------------- GL_NV_parameter_buffer_object2 -------------------- */ - -#ifndef GL_NV_parameter_buffer_object2 -#define GL_NV_parameter_buffer_object2 1 - -#define GLEW_NV_parameter_buffer_object2 GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object2) - -#endif /* GL_NV_parameter_buffer_object2 */ - -/* ------------------------- GL_NV_pixel_data_range ------------------------ */ - -#ifndef GL_NV_pixel_data_range -#define GL_NV_pixel_data_range 1 - -#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 -#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 -#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A -#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B -#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C -#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D - -typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer); - -#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) -#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) - -#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range) - -#endif /* GL_NV_pixel_data_range */ - -/* --------------------------- GL_NV_point_sprite -------------------------- */ - -#ifndef GL_NV_point_sprite -#define GL_NV_point_sprite 1 - -#define GL_POINT_SPRITE_NV 0x8861 -#define GL_COORD_REPLACE_NV 0x8862 -#define GL_POINT_SPRITE_R_MODE_NV 0x8863 - -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params); - -#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV) -#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV) - -#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite) - -#endif /* GL_NV_point_sprite */ - -/* -------------------------- GL_NV_present_video -------------------------- */ - -#ifndef GL_NV_present_video -#define GL_NV_present_video 1 - -#define GL_FRAME_NV 0x8E26 -#define GL_FIELDS_NV 0x8E27 -#define GL_CURRENT_TIME_NV 0x8E28 -#define GL_NUM_FILL_STREAMS_NV 0x8E29 -#define GL_PRESENT_TIME_NV 0x8E2A -#define GL_PRESENT_DURATION_NV 0x8E2B - -typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params); -typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params); -typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params); -typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); -typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); - -#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV) -#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV) -#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV) -#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV) -#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV) -#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV) - -#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video) - -#endif /* GL_NV_present_video */ - -/* ------------------------ GL_NV_primitive_restart ------------------------ */ - -#ifndef GL_NV_primitive_restart -#define GL_NV_primitive_restart 1 - -#define GL_PRIMITIVE_RESTART_NV 0x8558 -#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 - -typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); -typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void); - -#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV) -#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV) - -#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart) - -#endif /* GL_NV_primitive_restart */ - -/* ------------------------ GL_NV_register_combiners ----------------------- */ - -#ifndef GL_NV_register_combiners -#define GL_NV_register_combiners 1 - -#define GL_REGISTER_COMBINERS_NV 0x8522 -#define GL_VARIABLE_A_NV 0x8523 -#define GL_VARIABLE_B_NV 0x8524 -#define GL_VARIABLE_C_NV 0x8525 -#define GL_VARIABLE_D_NV 0x8526 -#define GL_VARIABLE_E_NV 0x8527 -#define GL_VARIABLE_F_NV 0x8528 -#define GL_VARIABLE_G_NV 0x8529 -#define GL_CONSTANT_COLOR0_NV 0x852A -#define GL_CONSTANT_COLOR1_NV 0x852B -#define GL_PRIMARY_COLOR_NV 0x852C -#define GL_SECONDARY_COLOR_NV 0x852D -#define GL_SPARE0_NV 0x852E -#define GL_SPARE1_NV 0x852F -#define GL_DISCARD_NV 0x8530 -#define GL_E_TIMES_F_NV 0x8531 -#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 -#define GL_UNSIGNED_IDENTITY_NV 0x8536 -#define GL_UNSIGNED_INVERT_NV 0x8537 -#define GL_EXPAND_NORMAL_NV 0x8538 -#define GL_EXPAND_NEGATE_NV 0x8539 -#define GL_HALF_BIAS_NORMAL_NV 0x853A -#define GL_HALF_BIAS_NEGATE_NV 0x853B -#define GL_SIGNED_IDENTITY_NV 0x853C -#define GL_SIGNED_NEGATE_NV 0x853D -#define GL_SCALE_BY_TWO_NV 0x853E -#define GL_SCALE_BY_FOUR_NV 0x853F -#define GL_SCALE_BY_ONE_HALF_NV 0x8540 -#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 -#define GL_COMBINER_INPUT_NV 0x8542 -#define GL_COMBINER_MAPPING_NV 0x8543 -#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 -#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 -#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 -#define GL_COMBINER_MUX_SUM_NV 0x8547 -#define GL_COMBINER_SCALE_NV 0x8548 -#define GL_COMBINER_BIAS_NV 0x8549 -#define GL_COMBINER_AB_OUTPUT_NV 0x854A -#define GL_COMBINER_CD_OUTPUT_NV 0x854B -#define GL_COMBINER_SUM_OUTPUT_NV 0x854C -#define GL_MAX_GENERAL_COMBINERS_NV 0x854D -#define GL_NUM_GENERAL_COMBINERS_NV 0x854E -#define GL_COLOR_SUM_CLAMP_NV 0x854F -#define GL_COMBINER0_NV 0x8550 -#define GL_COMBINER1_NV 0x8551 -#define GL_COMBINER2_NV 0x8552 -#define GL_COMBINER3_NV 0x8553 -#define GL_COMBINER4_NV 0x8554 -#define GL_COMBINER5_NV 0x8555 -#define GL_COMBINER6_NV 0x8556 -#define GL_COMBINER7_NV 0x8557 - -typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); -typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params); - -#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV) -#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV) -#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV) -#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV) -#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV) -#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV) -#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV) -#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV) -#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV) -#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV) -#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV) -#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV) -#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV) - -#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners) - -#endif /* GL_NV_register_combiners */ - -/* ----------------------- GL_NV_register_combiners2 ----------------------- */ - -#ifndef GL_NV_register_combiners2 -#define GL_NV_register_combiners2 1 - -#define GL_PER_STAGE_CONSTANTS_NV 0x8535 - -typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params); - -#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV) -#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV) - -#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2) - -#endif /* GL_NV_register_combiners2 */ - -/* ------------------------ GL_NV_shader_buffer_load ----------------------- */ - -#ifndef GL_NV_shader_buffer_load -#define GL_NV_shader_buffer_load 1 - -#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D -#define GL_GPU_ADDRESS_NV 0x8F34 -#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 - -typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT* params); -typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT* result); -typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT* params); -typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); -typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); -typedef void (GLAPIENTRY * PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); -typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); -typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); -typedef void (GLAPIENTRY * PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); -typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); - -#define glGetBufferParameterui64vNV GLEW_GET_FUN(__glewGetBufferParameterui64vNV) -#define glGetIntegerui64vNV GLEW_GET_FUN(__glewGetIntegerui64vNV) -#define glGetNamedBufferParameterui64vNV GLEW_GET_FUN(__glewGetNamedBufferParameterui64vNV) -#define glIsBufferResidentNV GLEW_GET_FUN(__glewIsBufferResidentNV) -#define glIsNamedBufferResidentNV GLEW_GET_FUN(__glewIsNamedBufferResidentNV) -#define glMakeBufferNonResidentNV GLEW_GET_FUN(__glewMakeBufferNonResidentNV) -#define glMakeBufferResidentNV GLEW_GET_FUN(__glewMakeBufferResidentNV) -#define glMakeNamedBufferNonResidentNV GLEW_GET_FUN(__glewMakeNamedBufferNonResidentNV) -#define glMakeNamedBufferResidentNV GLEW_GET_FUN(__glewMakeNamedBufferResidentNV) -#define glProgramUniformui64NV GLEW_GET_FUN(__glewProgramUniformui64NV) -#define glProgramUniformui64vNV GLEW_GET_FUN(__glewProgramUniformui64vNV) -#define glUniformui64NV GLEW_GET_FUN(__glewUniformui64NV) -#define glUniformui64vNV GLEW_GET_FUN(__glewUniformui64vNV) - -#define GLEW_NV_shader_buffer_load GLEW_GET_VAR(__GLEW_NV_shader_buffer_load) - -#endif /* GL_NV_shader_buffer_load */ - -/* ---------------------- GL_NV_tessellation_program5 ---------------------- */ - -#ifndef GL_NV_tessellation_program5 -#define GL_NV_tessellation_program5 1 - -#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 -#define GL_TESS_CONTROL_PROGRAM_NV 0x891E -#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F -#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74 -#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75 - -#define GLEW_NV_tessellation_program5 GLEW_GET_VAR(__GLEW_NV_tessellation_program5) - -#endif /* GL_NV_tessellation_program5 */ - -/* -------------------------- GL_NV_texgen_emboss -------------------------- */ - -#ifndef GL_NV_texgen_emboss -#define GL_NV_texgen_emboss 1 - -#define GL_EMBOSS_LIGHT_NV 0x855D -#define GL_EMBOSS_CONSTANT_NV 0x855E -#define GL_EMBOSS_MAP_NV 0x855F - -#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss) - -#endif /* GL_NV_texgen_emboss */ - -/* ------------------------ GL_NV_texgen_reflection ------------------------ */ - -#ifndef GL_NV_texgen_reflection -#define GL_NV_texgen_reflection 1 - -#define GL_NORMAL_MAP_NV 0x8511 -#define GL_REFLECTION_MAP_NV 0x8512 - -#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection) - -#endif /* GL_NV_texgen_reflection */ - -/* ------------------------- GL_NV_texture_barrier ------------------------- */ - -#ifndef GL_NV_texture_barrier -#define GL_NV_texture_barrier 1 - -typedef void (GLAPIENTRY * PFNGLTEXTUREBARRIERNVPROC) (void); - -#define glTextureBarrierNV GLEW_GET_FUN(__glewTextureBarrierNV) - -#define GLEW_NV_texture_barrier GLEW_GET_VAR(__GLEW_NV_texture_barrier) - -#endif /* GL_NV_texture_barrier */ - -/* --------------------- GL_NV_texture_compression_vtc --------------------- */ - -#ifndef GL_NV_texture_compression_vtc -#define GL_NV_texture_compression_vtc 1 - -#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc) - -#endif /* GL_NV_texture_compression_vtc */ - -/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */ - -#ifndef GL_NV_texture_env_combine4 -#define GL_NV_texture_env_combine4 1 - -#define GL_COMBINE4_NV 0x8503 -#define GL_SOURCE3_RGB_NV 0x8583 -#define GL_SOURCE3_ALPHA_NV 0x858B -#define GL_OPERAND3_RGB_NV 0x8593 -#define GL_OPERAND3_ALPHA_NV 0x859B - -#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4) - -#endif /* GL_NV_texture_env_combine4 */ - -/* ---------------------- GL_NV_texture_expand_normal ---------------------- */ - -#ifndef GL_NV_texture_expand_normal -#define GL_NV_texture_expand_normal 1 - -#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F - -#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal) - -#endif /* GL_NV_texture_expand_normal */ - -/* ----------------------- GL_NV_texture_multisample ----------------------- */ - -#ifndef GL_NV_texture_multisample -#define GL_NV_texture_multisample 1 - -#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045 -#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046 - -typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - -#define glTexImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage2DMultisampleCoverageNV) -#define glTexImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage3DMultisampleCoverageNV) -#define glTextureImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage2DMultisampleCoverageNV) -#define glTextureImage2DMultisampleNV GLEW_GET_FUN(__glewTextureImage2DMultisampleNV) -#define glTextureImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage3DMultisampleCoverageNV) -#define glTextureImage3DMultisampleNV GLEW_GET_FUN(__glewTextureImage3DMultisampleNV) - -#define GLEW_NV_texture_multisample GLEW_GET_VAR(__GLEW_NV_texture_multisample) - -#endif /* GL_NV_texture_multisample */ - -/* ------------------------ GL_NV_texture_rectangle ------------------------ */ - -#ifndef GL_NV_texture_rectangle -#define GL_NV_texture_rectangle 1 - -#define GL_TEXTURE_RECTANGLE_NV 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 - -#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle) - -#endif /* GL_NV_texture_rectangle */ - -/* -------------------------- GL_NV_texture_shader ------------------------- */ - -#ifndef GL_NV_texture_shader -#define GL_NV_texture_shader 1 - -#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C -#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D -#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E -#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 -#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA -#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB -#define GL_DSDT_MAG_INTENSITY_NV 0x86DC -#define GL_SHADER_CONSISTENT_NV 0x86DD -#define GL_TEXTURE_SHADER_NV 0x86DE -#define GL_SHADER_OPERATION_NV 0x86DF -#define GL_CULL_MODES_NV 0x86E0 -#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1 -#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 -#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 -#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 -#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 -#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 -#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 -#define GL_CONST_EYE_NV 0x86E5 -#define GL_PASS_THROUGH_NV 0x86E6 -#define GL_CULL_FRAGMENT_NV 0x86E7 -#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 -#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 -#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA -#define GL_DOT_PRODUCT_NV 0x86EC -#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED -#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE -#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 -#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 -#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 -#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 -#define GL_HILO_NV 0x86F4 -#define GL_DSDT_NV 0x86F5 -#define GL_DSDT_MAG_NV 0x86F6 -#define GL_DSDT_MAG_VIB_NV 0x86F7 -#define GL_HILO16_NV 0x86F8 -#define GL_SIGNED_HILO_NV 0x86F9 -#define GL_SIGNED_HILO16_NV 0x86FA -#define GL_SIGNED_RGBA_NV 0x86FB -#define GL_SIGNED_RGBA8_NV 0x86FC -#define GL_SIGNED_RGB_NV 0x86FE -#define GL_SIGNED_RGB8_NV 0x86FF -#define GL_SIGNED_LUMINANCE_NV 0x8701 -#define GL_SIGNED_LUMINANCE8_NV 0x8702 -#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 -#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 -#define GL_SIGNED_ALPHA_NV 0x8705 -#define GL_SIGNED_ALPHA8_NV 0x8706 -#define GL_SIGNED_INTENSITY_NV 0x8707 -#define GL_SIGNED_INTENSITY8_NV 0x8708 -#define GL_DSDT8_NV 0x8709 -#define GL_DSDT8_MAG8_NV 0x870A -#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B -#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C -#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D -#define GL_HI_SCALE_NV 0x870E -#define GL_LO_SCALE_NV 0x870F -#define GL_DS_SCALE_NV 0x8710 -#define GL_DT_SCALE_NV 0x8711 -#define GL_MAGNITUDE_SCALE_NV 0x8712 -#define GL_VIBRANCE_SCALE_NV 0x8713 -#define GL_HI_BIAS_NV 0x8714 -#define GL_LO_BIAS_NV 0x8715 -#define GL_DS_BIAS_NV 0x8716 -#define GL_DT_BIAS_NV 0x8717 -#define GL_MAGNITUDE_BIAS_NV 0x8718 -#define GL_VIBRANCE_BIAS_NV 0x8719 -#define GL_TEXTURE_BORDER_VALUES_NV 0x871A -#define GL_TEXTURE_HI_SIZE_NV 0x871B -#define GL_TEXTURE_LO_SIZE_NV 0x871C -#define GL_TEXTURE_DS_SIZE_NV 0x871D -#define GL_TEXTURE_DT_SIZE_NV 0x871E -#define GL_TEXTURE_MAG_SIZE_NV 0x871F - -#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader) - -#endif /* GL_NV_texture_shader */ - -/* ------------------------- GL_NV_texture_shader2 ------------------------- */ - -#ifndef GL_NV_texture_shader2 -#define GL_NV_texture_shader2 1 - -#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA -#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB -#define GL_DSDT_MAG_INTENSITY_NV 0x86DC -#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF -#define GL_HILO_NV 0x86F4 -#define GL_DSDT_NV 0x86F5 -#define GL_DSDT_MAG_NV 0x86F6 -#define GL_DSDT_MAG_VIB_NV 0x86F7 -#define GL_HILO16_NV 0x86F8 -#define GL_SIGNED_HILO_NV 0x86F9 -#define GL_SIGNED_HILO16_NV 0x86FA -#define GL_SIGNED_RGBA_NV 0x86FB -#define GL_SIGNED_RGBA8_NV 0x86FC -#define GL_SIGNED_RGB_NV 0x86FE -#define GL_SIGNED_RGB8_NV 0x86FF -#define GL_SIGNED_LUMINANCE_NV 0x8701 -#define GL_SIGNED_LUMINANCE8_NV 0x8702 -#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 -#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 -#define GL_SIGNED_ALPHA_NV 0x8705 -#define GL_SIGNED_ALPHA8_NV 0x8706 -#define GL_SIGNED_INTENSITY_NV 0x8707 -#define GL_SIGNED_INTENSITY8_NV 0x8708 -#define GL_DSDT8_NV 0x8709 -#define GL_DSDT8_MAG8_NV 0x870A -#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B -#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C -#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D - -#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2) - -#endif /* GL_NV_texture_shader2 */ - -/* ------------------------- GL_NV_texture_shader3 ------------------------- */ - -#ifndef GL_NV_texture_shader3 -#define GL_NV_texture_shader3 1 - -#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 -#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 -#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 -#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 -#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 -#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 -#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 -#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 -#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 -#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 -#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A -#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B -#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C -#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D -#define GL_HILO8_NV 0x885E -#define GL_SIGNED_HILO8_NV 0x885F -#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 - -#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3) - -#endif /* GL_NV_texture_shader3 */ - -/* ------------------------ GL_NV_transform_feedback ----------------------- */ - -#ifndef GL_NV_transform_feedback -#define GL_NV_transform_feedback 1 - -#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 -#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 -#define GL_TEXTURE_COORD_NV 0x8C79 -#define GL_CLIP_DISTANCE_NV 0x8C7A -#define GL_VERTEX_ID_NV 0x8C7B -#define GL_PRIMITIVE_ID_NV 0x8C7C -#define GL_GENERIC_ATTRIB_NV 0x8C7D -#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 -#define GL_ACTIVE_VARYINGS_NV 0x8C81 -#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 -#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 -#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 -#define GL_PRIMITIVES_GENERATED_NV 0x8C87 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 -#define GL_RASTERIZER_DISCARD_NV 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B -#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C -#define GL_SEPARATE_ATTRIBS_NV 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F - -typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); -typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); -typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); -typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); -typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); -typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); -typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); -typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); - -#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV) -#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV) -#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV) -#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV) -#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV) -#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV) -#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV) -#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV) -#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV) -#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV) -#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV) - -#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback) - -#endif /* GL_NV_transform_feedback */ - -/* ----------------------- GL_NV_transform_feedback2 ----------------------- */ - -#ifndef GL_NV_transform_feedback2 -#define GL_NV_transform_feedback2 1 - -#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 -#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 -#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 - -typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); -typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint* ids); -typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); -typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint* ids); -typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void); -typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void); - -#define glBindTransformFeedbackNV GLEW_GET_FUN(__glewBindTransformFeedbackNV) -#define glDeleteTransformFeedbacksNV GLEW_GET_FUN(__glewDeleteTransformFeedbacksNV) -#define glDrawTransformFeedbackNV GLEW_GET_FUN(__glewDrawTransformFeedbackNV) -#define glGenTransformFeedbacksNV GLEW_GET_FUN(__glewGenTransformFeedbacksNV) -#define glIsTransformFeedbackNV GLEW_GET_FUN(__glewIsTransformFeedbackNV) -#define glPauseTransformFeedbackNV GLEW_GET_FUN(__glewPauseTransformFeedbackNV) -#define glResumeTransformFeedbackNV GLEW_GET_FUN(__glewResumeTransformFeedbackNV) - -#define GLEW_NV_transform_feedback2 GLEW_GET_VAR(__GLEW_NV_transform_feedback2) - -#endif /* GL_NV_transform_feedback2 */ - -/* -------------------------- GL_NV_vdpau_interop -------------------------- */ - -#ifndef GL_NV_vdpau_interop -#define GL_NV_vdpau_interop 1 - -#define GL_SURFACE_STATE_NV 0x86EB -#define GL_SURFACE_REGISTERED_NV 0x86FD -#define GL_SURFACE_MAPPED_NV 0x8700 -#define GL_WRITE_DISCARD_NV 0x88BE - -typedef GLintptr GLvdpauSurfaceNV; - -typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void); -typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values); -typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress); -typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); -typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces); -typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -typedef void (GLAPIENTRY * PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); -typedef void (GLAPIENTRY * PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV* surfaces); -typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); - -#define glVDPAUFiniNV GLEW_GET_FUN(__glewVDPAUFiniNV) -#define glVDPAUGetSurfaceivNV GLEW_GET_FUN(__glewVDPAUGetSurfaceivNV) -#define glVDPAUInitNV GLEW_GET_FUN(__glewVDPAUInitNV) -#define glVDPAUIsSurfaceNV GLEW_GET_FUN(__glewVDPAUIsSurfaceNV) -#define glVDPAUMapSurfacesNV GLEW_GET_FUN(__glewVDPAUMapSurfacesNV) -#define glVDPAURegisterOutputSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterOutputSurfaceNV) -#define glVDPAURegisterVideoSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterVideoSurfaceNV) -#define glVDPAUSurfaceAccessNV GLEW_GET_FUN(__glewVDPAUSurfaceAccessNV) -#define glVDPAUUnmapSurfacesNV GLEW_GET_FUN(__glewVDPAUUnmapSurfacesNV) -#define glVDPAUUnregisterSurfaceNV GLEW_GET_FUN(__glewVDPAUUnregisterSurfaceNV) - -#define GLEW_NV_vdpau_interop GLEW_GET_VAR(__GLEW_NV_vdpau_interop) - -#endif /* GL_NV_vdpau_interop */ - -/* ------------------------ GL_NV_vertex_array_range ----------------------- */ - -#ifndef GL_NV_vertex_array_range -#define GL_NV_vertex_array_range 1 - -#define GL_VERTEX_ARRAY_RANGE_NV 0x851D -#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E -#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F -#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 -#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 - -typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer); - -#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) -#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) - -#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range) - -#endif /* GL_NV_vertex_array_range */ - -/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */ - -#ifndef GL_NV_vertex_array_range2 -#define GL_NV_vertex_array_range2 1 - -#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 - -#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2) - -#endif /* GL_NV_vertex_array_range2 */ - -/* ------------------- GL_NV_vertex_attrib_integer_64bit ------------------- */ - -#ifndef GL_NV_vertex_attrib_integer_64bit -#define GL_NV_vertex_attrib_integer_64bit 1 - -#define GL_INT64_NV 0x140E -#define GL_UNSIGNED_INT64_NV 0x140F - -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT* params); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); - -#define glGetVertexAttribLi64vNV GLEW_GET_FUN(__glewGetVertexAttribLi64vNV) -#define glGetVertexAttribLui64vNV GLEW_GET_FUN(__glewGetVertexAttribLui64vNV) -#define glVertexAttribL1i64NV GLEW_GET_FUN(__glewVertexAttribL1i64NV) -#define glVertexAttribL1i64vNV GLEW_GET_FUN(__glewVertexAttribL1i64vNV) -#define glVertexAttribL1ui64NV GLEW_GET_FUN(__glewVertexAttribL1ui64NV) -#define glVertexAttribL1ui64vNV GLEW_GET_FUN(__glewVertexAttribL1ui64vNV) -#define glVertexAttribL2i64NV GLEW_GET_FUN(__glewVertexAttribL2i64NV) -#define glVertexAttribL2i64vNV GLEW_GET_FUN(__glewVertexAttribL2i64vNV) -#define glVertexAttribL2ui64NV GLEW_GET_FUN(__glewVertexAttribL2ui64NV) -#define glVertexAttribL2ui64vNV GLEW_GET_FUN(__glewVertexAttribL2ui64vNV) -#define glVertexAttribL3i64NV GLEW_GET_FUN(__glewVertexAttribL3i64NV) -#define glVertexAttribL3i64vNV GLEW_GET_FUN(__glewVertexAttribL3i64vNV) -#define glVertexAttribL3ui64NV GLEW_GET_FUN(__glewVertexAttribL3ui64NV) -#define glVertexAttribL3ui64vNV GLEW_GET_FUN(__glewVertexAttribL3ui64vNV) -#define glVertexAttribL4i64NV GLEW_GET_FUN(__glewVertexAttribL4i64NV) -#define glVertexAttribL4i64vNV GLEW_GET_FUN(__glewVertexAttribL4i64vNV) -#define glVertexAttribL4ui64NV GLEW_GET_FUN(__glewVertexAttribL4ui64NV) -#define glVertexAttribL4ui64vNV GLEW_GET_FUN(__glewVertexAttribL4ui64vNV) -#define glVertexAttribLFormatNV GLEW_GET_FUN(__glewVertexAttribLFormatNV) - -#define GLEW_NV_vertex_attrib_integer_64bit GLEW_GET_VAR(__GLEW_NV_vertex_attrib_integer_64bit) - -#endif /* GL_NV_vertex_attrib_integer_64bit */ - -/* ------------------- GL_NV_vertex_buffer_unified_memory ------------------ */ - -#ifndef GL_NV_vertex_buffer_unified_memory -#define GL_NV_vertex_buffer_unified_memory 1 - -#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E -#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F -#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 -#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 -#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 -#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 -#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 -#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 -#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 -#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 -#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 -#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 -#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A -#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B -#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C -#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D -#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E -#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F -#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 -#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 -#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 -#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 -#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 -#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 -#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 - -typedef void (GLAPIENTRY * PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); -typedef void (GLAPIENTRY * PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); -typedef void (GLAPIENTRY * PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT result[]); -typedef void (GLAPIENTRY * PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); - -#define glBufferAddressRangeNV GLEW_GET_FUN(__glewBufferAddressRangeNV) -#define glColorFormatNV GLEW_GET_FUN(__glewColorFormatNV) -#define glEdgeFlagFormatNV GLEW_GET_FUN(__glewEdgeFlagFormatNV) -#define glFogCoordFormatNV GLEW_GET_FUN(__glewFogCoordFormatNV) -#define glGetIntegerui64i_vNV GLEW_GET_FUN(__glewGetIntegerui64i_vNV) -#define glIndexFormatNV GLEW_GET_FUN(__glewIndexFormatNV) -#define glNormalFormatNV GLEW_GET_FUN(__glewNormalFormatNV) -#define glSecondaryColorFormatNV GLEW_GET_FUN(__glewSecondaryColorFormatNV) -#define glTexCoordFormatNV GLEW_GET_FUN(__glewTexCoordFormatNV) -#define glVertexAttribFormatNV GLEW_GET_FUN(__glewVertexAttribFormatNV) -#define glVertexAttribIFormatNV GLEW_GET_FUN(__glewVertexAttribIFormatNV) -#define glVertexFormatNV GLEW_GET_FUN(__glewVertexFormatNV) - -#define GLEW_NV_vertex_buffer_unified_memory GLEW_GET_VAR(__GLEW_NV_vertex_buffer_unified_memory) - -#endif /* GL_NV_vertex_buffer_unified_memory */ - -/* -------------------------- GL_NV_vertex_program ------------------------- */ - -#ifndef GL_NV_vertex_program -#define GL_NV_vertex_program 1 - -#define GL_VERTEX_PROGRAM_NV 0x8620 -#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 -#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 -#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 -#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 -#define GL_CURRENT_ATTRIB_NV 0x8626 -#define GL_PROGRAM_LENGTH_NV 0x8627 -#define GL_PROGRAM_STRING_NV 0x8628 -#define GL_MODELVIEW_PROJECTION_NV 0x8629 -#define GL_IDENTITY_NV 0x862A -#define GL_INVERSE_NV 0x862B -#define GL_TRANSPOSE_NV 0x862C -#define GL_INVERSE_TRANSPOSE_NV 0x862D -#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E -#define GL_MAX_TRACK_MATRICES_NV 0x862F -#define GL_MATRIX0_NV 0x8630 -#define GL_MATRIX1_NV 0x8631 -#define GL_MATRIX2_NV 0x8632 -#define GL_MATRIX3_NV 0x8633 -#define GL_MATRIX4_NV 0x8634 -#define GL_MATRIX5_NV 0x8635 -#define GL_MATRIX6_NV 0x8636 -#define GL_MATRIX7_NV 0x8637 -#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 -#define GL_CURRENT_MATRIX_NV 0x8641 -#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 -#define GL_PROGRAM_PARAMETER_NV 0x8644 -#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 -#define GL_PROGRAM_TARGET_NV 0x8646 -#define GL_PROGRAM_RESIDENT_NV 0x8647 -#define GL_TRACK_MATRIX_NV 0x8648 -#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 -#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A -#define GL_PROGRAM_ERROR_POSITION_NV 0x864B -#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 -#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 -#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 -#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 -#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 -#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 -#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 -#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 -#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 -#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 -#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A -#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B -#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C -#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D -#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E -#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F -#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 -#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 -#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 -#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 -#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 -#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 -#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 -#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 -#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 -#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 -#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A -#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B -#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C -#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D -#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E -#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F -#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 -#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 -#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 -#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 -#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 -#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 -#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 -#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 -#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 -#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 -#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A -#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B -#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C -#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D -#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E -#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F - -typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences); -typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); -typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids); -typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params); -typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); -typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids); -typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v); - -#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV) -#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV) -#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV) -#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV) -#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV) -#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV) -#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV) -#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV) -#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV) -#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV) -#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV) -#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV) -#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV) -#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV) -#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV) -#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV) -#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV) -#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV) -#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV) -#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV) -#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV) -#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV) -#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV) -#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV) -#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV) -#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV) -#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV) -#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV) -#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV) -#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV) -#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV) -#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV) -#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV) -#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV) -#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV) -#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV) -#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV) -#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV) -#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV) -#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV) -#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV) -#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV) -#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV) -#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV) -#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV) -#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV) -#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV) -#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV) -#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV) -#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV) -#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV) -#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV) -#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV) -#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV) -#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV) -#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV) -#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV) -#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV) -#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV) -#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV) -#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV) -#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV) -#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV) -#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV) - -#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program) - -#endif /* GL_NV_vertex_program */ - -/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */ - -#ifndef GL_NV_vertex_program1_1 -#define GL_NV_vertex_program1_1 1 - -#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1) - -#endif /* GL_NV_vertex_program1_1 */ - -/* ------------------------- GL_NV_vertex_program2 ------------------------- */ - -#ifndef GL_NV_vertex_program2 -#define GL_NV_vertex_program2 1 - -#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2) - -#endif /* GL_NV_vertex_program2 */ - -/* ---------------------- GL_NV_vertex_program2_option --------------------- */ - -#ifndef GL_NV_vertex_program2_option -#define GL_NV_vertex_program2_option 1 - -#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 -#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 - -#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option) - -#endif /* GL_NV_vertex_program2_option */ - -/* ------------------------- GL_NV_vertex_program3 ------------------------- */ - -#ifndef GL_NV_vertex_program3 -#define GL_NV_vertex_program3 1 - -#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C - -#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3) - -#endif /* GL_NV_vertex_program3 */ - -/* ------------------------- GL_NV_vertex_program4 ------------------------- */ - -#ifndef GL_NV_vertex_program4 -#define GL_NV_vertex_program4 1 - -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD - -#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4) - -#endif /* GL_NV_vertex_program4 */ - -/* -------------------------- GL_NV_video_capture -------------------------- */ - -#ifndef GL_NV_video_capture -#define GL_NV_video_capture 1 - -#define GL_VIDEO_BUFFER_NV 0x9020 -#define GL_VIDEO_BUFFER_BINDING_NV 0x9021 -#define GL_FIELD_UPPER_NV 0x9022 -#define GL_FIELD_LOWER_NV 0x9023 -#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024 -#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025 -#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026 -#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027 -#define GL_VIDEO_BUFFER_PITCH_NV 0x9028 -#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029 -#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A -#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B -#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C -#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D -#define GL_PARTIAL_SUCCESS_NV 0x902E -#define GL_SUCCESS_NV 0x902F -#define GL_FAILURE_NV 0x9030 -#define GL_YCBYCR8_422_NV 0x9031 -#define GL_YCBAYCR8A_4224_NV 0x9032 -#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033 -#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034 -#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035 -#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036 -#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037 -#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038 -#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039 -#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A -#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B -#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C - -typedef void (GLAPIENTRY * PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot); -typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); -typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); -typedef void (GLAPIENTRY * PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot); -typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint* params); -typedef GLenum (GLAPIENTRY * PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint* sequence_num, GLuint64EXT *capture_time); -typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble* params); -typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint* params); - -#define glBeginVideoCaptureNV GLEW_GET_FUN(__glewBeginVideoCaptureNV) -#define glBindVideoCaptureStreamBufferNV GLEW_GET_FUN(__glewBindVideoCaptureStreamBufferNV) -#define glBindVideoCaptureStreamTextureNV GLEW_GET_FUN(__glewBindVideoCaptureStreamTextureNV) -#define glEndVideoCaptureNV GLEW_GET_FUN(__glewEndVideoCaptureNV) -#define glGetVideoCaptureStreamdvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamdvNV) -#define glGetVideoCaptureStreamfvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamfvNV) -#define glGetVideoCaptureStreamivNV GLEW_GET_FUN(__glewGetVideoCaptureStreamivNV) -#define glGetVideoCaptureivNV GLEW_GET_FUN(__glewGetVideoCaptureivNV) -#define glVideoCaptureNV GLEW_GET_FUN(__glewVideoCaptureNV) -#define glVideoCaptureStreamParameterdvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterdvNV) -#define glVideoCaptureStreamParameterfvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterfvNV) -#define glVideoCaptureStreamParameterivNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterivNV) - -#define GLEW_NV_video_capture GLEW_GET_VAR(__GLEW_NV_video_capture) - -#endif /* GL_NV_video_capture */ - -/* ------------------------ GL_OES_byte_coordinates ------------------------ */ - -#ifndef GL_OES_byte_coordinates -#define GL_OES_byte_coordinates 1 - -#define GL_BYTE 0x1400 - -#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates) - -#endif /* GL_OES_byte_coordinates */ - -/* ------------------- GL_OES_compressed_paletted_texture ------------------ */ - -#ifndef GL_OES_compressed_paletted_texture -#define GL_OES_compressed_paletted_texture 1 - -#define GL_PALETTE4_RGB8_OES 0x8B90 -#define GL_PALETTE4_RGBA8_OES 0x8B91 -#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 -#define GL_PALETTE4_RGBA4_OES 0x8B93 -#define GL_PALETTE4_RGB5_A1_OES 0x8B94 -#define GL_PALETTE8_RGB8_OES 0x8B95 -#define GL_PALETTE8_RGBA8_OES 0x8B96 -#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 -#define GL_PALETTE8_RGBA4_OES 0x8B98 -#define GL_PALETTE8_RGB5_A1_OES 0x8B99 - -#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture) - -#endif /* GL_OES_compressed_paletted_texture */ - -/* --------------------------- GL_OES_read_format -------------------------- */ - -#ifndef GL_OES_read_format -#define GL_OES_read_format 1 - -#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B - -#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format) - -#endif /* GL_OES_read_format */ - -/* ------------------------ GL_OES_single_precision ------------------------ */ - -#ifndef GL_OES_single_precision -#define GL_OES_single_precision 1 - -typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth); -typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation); -typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); -typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); -typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation); -typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); - -#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES) -#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES) -#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES) -#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES) -#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES) -#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES) - -#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision) - -#endif /* GL_OES_single_precision */ - -/* ---------------------------- GL_OML_interlace --------------------------- */ - -#ifndef GL_OML_interlace -#define GL_OML_interlace 1 - -#define GL_INTERLACE_OML 0x8980 -#define GL_INTERLACE_READ_OML 0x8981 - -#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace) - -#endif /* GL_OML_interlace */ - -/* ---------------------------- GL_OML_resample ---------------------------- */ - -#ifndef GL_OML_resample -#define GL_OML_resample 1 - -#define GL_PACK_RESAMPLE_OML 0x8984 -#define GL_UNPACK_RESAMPLE_OML 0x8985 -#define GL_RESAMPLE_REPLICATE_OML 0x8986 -#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 -#define GL_RESAMPLE_AVERAGE_OML 0x8988 -#define GL_RESAMPLE_DECIMATE_OML 0x8989 - -#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample) - -#endif /* GL_OML_resample */ - -/* ---------------------------- GL_OML_subsample --------------------------- */ - -#ifndef GL_OML_subsample -#define GL_OML_subsample 1 - -#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 -#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 - -#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample) - -#endif /* GL_OML_subsample */ - -/* --------------------------- GL_PGI_misc_hints --------------------------- */ - -#ifndef GL_PGI_misc_hints -#define GL_PGI_misc_hints 1 - -#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000 -#define GL_CONSERVE_MEMORY_HINT_PGI 107005 -#define GL_RECLAIM_MEMORY_HINT_PGI 107006 -#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010 -#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011 -#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012 -#define GL_ALWAYS_FAST_HINT_PGI 107020 -#define GL_ALWAYS_SOFT_HINT_PGI 107021 -#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022 -#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023 -#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024 -#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025 -#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030 -#define GL_STRICT_LIGHTING_HINT_PGI 107031 -#define GL_STRICT_SCISSOR_HINT_PGI 107032 -#define GL_FULL_STIPPLE_HINT_PGI 107033 -#define GL_CLIP_NEAR_HINT_PGI 107040 -#define GL_CLIP_FAR_HINT_PGI 107041 -#define GL_WIDE_LINE_HINT_PGI 107042 -#define GL_BACK_NORMALS_HINT_PGI 107043 - -#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints) - -#endif /* GL_PGI_misc_hints */ - -/* -------------------------- GL_PGI_vertex_hints -------------------------- */ - -#ifndef GL_PGI_vertex_hints -#define GL_PGI_vertex_hints 1 - -#define GL_VERTEX23_BIT_PGI 0x00000004 -#define GL_VERTEX4_BIT_PGI 0x00000008 -#define GL_COLOR3_BIT_PGI 0x00010000 -#define GL_COLOR4_BIT_PGI 0x00020000 -#define GL_EDGEFLAG_BIT_PGI 0x00040000 -#define GL_INDEX_BIT_PGI 0x00080000 -#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 -#define GL_VERTEX_DATA_HINT_PGI 107050 -#define GL_VERTEX_CONSISTENT_HINT_PGI 107051 -#define GL_MATERIAL_SIDE_HINT_PGI 107052 -#define GL_MAX_VERTEX_HINT_PGI 107053 -#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 -#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 -#define GL_MAT_EMISSION_BIT_PGI 0x00800000 -#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 -#define GL_MAT_SHININESS_BIT_PGI 0x02000000 -#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 -#define GL_NORMAL_BIT_PGI 0x08000000 -#define GL_TEXCOORD1_BIT_PGI 0x10000000 -#define GL_TEXCOORD2_BIT_PGI 0x20000000 -#define GL_TEXCOORD3_BIT_PGI 0x40000000 -#define GL_TEXCOORD4_BIT_PGI 0x80000000 - -#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints) - -#endif /* GL_PGI_vertex_hints */ - -/* ----------------------- GL_REND_screen_coordinates ---------------------- */ - -#ifndef GL_REND_screen_coordinates -#define GL_REND_screen_coordinates 1 - -#define GL_SCREEN_COORDINATES_REND 0x8490 -#define GL_INVERTED_SCREEN_W_REND 0x8491 - -#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates) - -#endif /* GL_REND_screen_coordinates */ - -/* ------------------------------- GL_S3_s3tc ------------------------------ */ - -#ifndef GL_S3_s3tc -#define GL_S3_s3tc 1 - -#define GL_RGB_S3TC 0x83A0 -#define GL_RGB4_S3TC 0x83A1 -#define GL_RGBA_S3TC 0x83A2 -#define GL_RGBA4_S3TC 0x83A3 -#define GL_RGBA_DXT5_S3TC 0x83A4 -#define GL_RGBA4_DXT5_S3TC 0x83A5 - -#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc) - -#endif /* GL_S3_s3tc */ - -/* -------------------------- GL_SGIS_color_range -------------------------- */ - -#ifndef GL_SGIS_color_range -#define GL_SGIS_color_range 1 - -#define GL_EXTENDED_RANGE_SGIS 0x85A5 -#define GL_MIN_RED_SGIS 0x85A6 -#define GL_MAX_RED_SGIS 0x85A7 -#define GL_MIN_GREEN_SGIS 0x85A8 -#define GL_MAX_GREEN_SGIS 0x85A9 -#define GL_MIN_BLUE_SGIS 0x85AA -#define GL_MAX_BLUE_SGIS 0x85AB -#define GL_MIN_ALPHA_SGIS 0x85AC -#define GL_MAX_ALPHA_SGIS 0x85AD - -#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range) - -#endif /* GL_SGIS_color_range */ - -/* ------------------------- GL_SGIS_detail_texture ------------------------ */ - -#ifndef GL_SGIS_detail_texture -#define GL_SGIS_detail_texture 1 - -typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); -typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points); - -#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS) -#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS) - -#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture) - -#endif /* GL_SGIS_detail_texture */ - -/* -------------------------- GL_SGIS_fog_function ------------------------- */ - -#ifndef GL_SGIS_fog_function -#define GL_SGIS_fog_function 1 - -typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points); -typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points); - -#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS) -#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS) - -#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function) - -#endif /* GL_SGIS_fog_function */ - -/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */ - -#ifndef GL_SGIS_generate_mipmap -#define GL_SGIS_generate_mipmap 1 - -#define GL_GENERATE_MIPMAP_SGIS 0x8191 -#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 - -#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap) - -#endif /* GL_SGIS_generate_mipmap */ - -/* -------------------------- GL_SGIS_multisample -------------------------- */ - -#ifndef GL_SGIS_multisample -#define GL_SGIS_multisample 1 - -#define GL_MULTISAMPLE_SGIS 0x809D -#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F -#define GL_SAMPLE_MASK_SGIS 0x80A0 -#define GL_1PASS_SGIS 0x80A1 -#define GL_2PASS_0_SGIS 0x80A2 -#define GL_2PASS_1_SGIS 0x80A3 -#define GL_4PASS_0_SGIS 0x80A4 -#define GL_4PASS_1_SGIS 0x80A5 -#define GL_4PASS_2_SGIS 0x80A6 -#define GL_4PASS_3_SGIS 0x80A7 -#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 -#define GL_SAMPLES_SGIS 0x80A9 -#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA -#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB -#define GL_SAMPLE_PATTERN_SGIS 0x80AC -#define GL_MULTISAMPLE_BIT_EXT 0x20000000 - -typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); -typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); - -#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS) -#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS) - -#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample) - -#endif /* GL_SGIS_multisample */ - -/* ------------------------- GL_SGIS_pixel_texture ------------------------- */ - -#ifndef GL_SGIS_pixel_texture -#define GL_SGIS_pixel_texture 1 - -#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture) - -#endif /* GL_SGIS_pixel_texture */ - -/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */ - -#ifndef GL_SGIS_point_line_texgen -#define GL_SGIS_point_line_texgen 1 - -#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 -#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 -#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 -#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 -#define GL_EYE_POINT_SGIS 0x81F4 -#define GL_OBJECT_POINT_SGIS 0x81F5 -#define GL_EYE_LINE_SGIS 0x81F6 -#define GL_OBJECT_LINE_SGIS 0x81F7 - -#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen) - -#endif /* GL_SGIS_point_line_texgen */ - -/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */ - -#ifndef GL_SGIS_sharpen_texture -#define GL_SGIS_sharpen_texture 1 - -typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points); -typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); - -#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS) -#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS) - -#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture) - -#endif /* GL_SGIS_sharpen_texture */ - -/* --------------------------- GL_SGIS_texture4D --------------------------- */ - -#ifndef GL_SGIS_texture4D -#define GL_SGIS_texture4D 1 - -typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels); - -#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) -#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) - -#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D) - -#endif /* GL_SGIS_texture4D */ - -/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */ - -#ifndef GL_SGIS_texture_border_clamp -#define GL_SGIS_texture_border_clamp 1 - -#define GL_CLAMP_TO_BORDER_SGIS 0x812D - -#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp) - -#endif /* GL_SGIS_texture_border_clamp */ - -/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */ - -#ifndef GL_SGIS_texture_edge_clamp -#define GL_SGIS_texture_edge_clamp 1 - -#define GL_CLAMP_TO_EDGE_SGIS 0x812F - -#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp) - -#endif /* GL_SGIS_texture_edge_clamp */ - -/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */ - -#ifndef GL_SGIS_texture_filter4 -#define GL_SGIS_texture_filter4 1 - -typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights); -typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights); - -#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS) -#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS) - -#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4) - -#endif /* GL_SGIS_texture_filter4 */ - -/* -------------------------- GL_SGIS_texture_lod -------------------------- */ - -#ifndef GL_SGIS_texture_lod -#define GL_SGIS_texture_lod 1 - -#define GL_TEXTURE_MIN_LOD_SGIS 0x813A -#define GL_TEXTURE_MAX_LOD_SGIS 0x813B -#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C -#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D - -#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod) - -#endif /* GL_SGIS_texture_lod */ - -/* ------------------------- GL_SGIS_texture_select ------------------------ */ - -#ifndef GL_SGIS_texture_select -#define GL_SGIS_texture_select 1 - -#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select) - -#endif /* GL_SGIS_texture_select */ - -/* ----------------------------- GL_SGIX_async ----------------------------- */ - -#ifndef GL_SGIX_async -#define GL_SGIX_async 1 - -#define GL_ASYNC_MARKER_SGIX 0x8329 - -typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker); -typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); -typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp); -typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); -typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); -typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp); - -#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX) -#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX) -#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX) -#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX) -#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX) -#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX) - -#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async) - -#endif /* GL_SGIX_async */ - -/* ------------------------ GL_SGIX_async_histogram ------------------------ */ - -#ifndef GL_SGIX_async_histogram -#define GL_SGIX_async_histogram 1 - -#define GL_ASYNC_HISTOGRAM_SGIX 0x832C -#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D - -#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram) - -#endif /* GL_SGIX_async_histogram */ - -/* -------------------------- GL_SGIX_async_pixel -------------------------- */ - -#ifndef GL_SGIX_async_pixel -#define GL_SGIX_async_pixel 1 - -#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C -#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D -#define GL_ASYNC_READ_PIXELS_SGIX 0x835E -#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F -#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 -#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 - -#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel) - -#endif /* GL_SGIX_async_pixel */ - -/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */ - -#ifndef GL_SGIX_blend_alpha_minmax -#define GL_SGIX_blend_alpha_minmax 1 - -#define GL_ALPHA_MIN_SGIX 0x8320 -#define GL_ALPHA_MAX_SGIX 0x8321 - -#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax) - -#endif /* GL_SGIX_blend_alpha_minmax */ - -/* ---------------------------- GL_SGIX_clipmap ---------------------------- */ - -#ifndef GL_SGIX_clipmap -#define GL_SGIX_clipmap 1 - -#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap) - -#endif /* GL_SGIX_clipmap */ - -/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */ - -#ifndef GL_SGIX_convolution_accuracy -#define GL_SGIX_convolution_accuracy 1 - -#define GL_CONVOLUTION_HINT_SGIX 0x8316 - -#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy) - -#endif /* GL_SGIX_convolution_accuracy */ - -/* ------------------------- GL_SGIX_depth_texture ------------------------- */ - -#ifndef GL_SGIX_depth_texture -#define GL_SGIX_depth_texture 1 - -#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 -#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 -#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 - -#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture) - -#endif /* GL_SGIX_depth_texture */ - -/* -------------------------- GL_SGIX_flush_raster ------------------------- */ - -#ifndef GL_SGIX_flush_raster -#define GL_SGIX_flush_raster 1 - -typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); - -#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX) - -#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster) - -#endif /* GL_SGIX_flush_raster */ - -/* --------------------------- GL_SGIX_fog_offset -------------------------- */ - -#ifndef GL_SGIX_fog_offset -#define GL_SGIX_fog_offset 1 - -#define GL_FOG_OFFSET_SGIX 0x8198 -#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 - -#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset) - -#endif /* GL_SGIX_fog_offset */ - -/* -------------------------- GL_SGIX_fog_texture -------------------------- */ - -#ifndef GL_SGIX_fog_texture -#define GL_SGIX_fog_texture 1 - -#define GL_TEXTURE_FOG_SGIX 0 -#define GL_FOG_PATCHY_FACTOR_SGIX 0 -#define GL_FRAGMENT_FOG_SGIX 0 - -typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname); - -#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX) - -#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture) - -#endif /* GL_SGIX_fog_texture */ - -/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */ - -#ifndef GL_SGIX_fragment_specular_lighting -#define GL_SGIX_fragment_specular_lighting 1 - -typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param); -typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data); -typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data); - -#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX) -#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX) -#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX) -#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX) -#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX) -#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX) -#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX) -#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX) -#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX) -#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX) -#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX) -#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX) -#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX) -#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX) -#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX) -#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX) -#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX) - -#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting) - -#endif /* GL_SGIX_fragment_specular_lighting */ - -/* --------------------------- GL_SGIX_framezoom --------------------------- */ - -#ifndef GL_SGIX_framezoom -#define GL_SGIX_framezoom 1 - -typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); - -#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX) - -#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom) - -#endif /* GL_SGIX_framezoom */ - -/* --------------------------- GL_SGIX_interlace --------------------------- */ - -#ifndef GL_SGIX_interlace -#define GL_SGIX_interlace 1 - -#define GL_INTERLACE_SGIX 0x8094 - -#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace) - -#endif /* GL_SGIX_interlace */ - -/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */ - -#ifndef GL_SGIX_ir_instrument1 -#define GL_SGIX_ir_instrument1 1 - -#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1) - -#endif /* GL_SGIX_ir_instrument1 */ - -/* ------------------------- GL_SGIX_list_priority ------------------------- */ - -#ifndef GL_SGIX_list_priority -#define GL_SGIX_list_priority 1 - -#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority) - -#endif /* GL_SGIX_list_priority */ - -/* ------------------------- GL_SGIX_pixel_texture ------------------------- */ - -#ifndef GL_SGIX_pixel_texture -#define GL_SGIX_pixel_texture 1 - -typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); - -#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX) - -#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture) - -#endif /* GL_SGIX_pixel_texture */ - -/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */ - -#ifndef GL_SGIX_pixel_texture_bits -#define GL_SGIX_pixel_texture_bits 1 - -#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits) - -#endif /* GL_SGIX_pixel_texture_bits */ - -/* ------------------------ GL_SGIX_reference_plane ------------------------ */ - -#ifndef GL_SGIX_reference_plane -#define GL_SGIX_reference_plane 1 - -typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation); - -#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX) - -#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane) - -#endif /* GL_SGIX_reference_plane */ - -/* ---------------------------- GL_SGIX_resample --------------------------- */ - -#ifndef GL_SGIX_resample -#define GL_SGIX_resample 1 - -#define GL_PACK_RESAMPLE_SGIX 0x842E -#define GL_UNPACK_RESAMPLE_SGIX 0x842F -#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 -#define GL_RESAMPLE_REPLICATE_SGIX 0x8433 -#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434 - -#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample) - -#endif /* GL_SGIX_resample */ - -/* ----------------------------- GL_SGIX_shadow ---------------------------- */ - -#ifndef GL_SGIX_shadow -#define GL_SGIX_shadow 1 - -#define GL_TEXTURE_COMPARE_SGIX 0x819A -#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B -#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C -#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D - -#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow) - -#endif /* GL_SGIX_shadow */ - -/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */ - -#ifndef GL_SGIX_shadow_ambient -#define GL_SGIX_shadow_ambient 1 - -#define GL_SHADOW_AMBIENT_SGIX 0x80BF - -#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient) - -#endif /* GL_SGIX_shadow_ambient */ - -/* ----------------------------- GL_SGIX_sprite ---------------------------- */ - -#ifndef GL_SGIX_sprite -#define GL_SGIX_sprite 1 - -typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); -typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params); - -#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX) -#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX) -#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX) -#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX) - -#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite) - -#endif /* GL_SGIX_sprite */ - -/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */ - -#ifndef GL_SGIX_tag_sample_buffer -#define GL_SGIX_tag_sample_buffer 1 - -typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); - -#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX) - -#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer) - -#endif /* GL_SGIX_tag_sample_buffer */ - -/* ------------------------ GL_SGIX_texture_add_env ------------------------ */ - -#ifndef GL_SGIX_texture_add_env -#define GL_SGIX_texture_add_env 1 - -#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env) - -#endif /* GL_SGIX_texture_add_env */ - -/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */ - -#ifndef GL_SGIX_texture_coordinate_clamp -#define GL_SGIX_texture_coordinate_clamp 1 - -#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 -#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A -#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B - -#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp) - -#endif /* GL_SGIX_texture_coordinate_clamp */ - -/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */ - -#ifndef GL_SGIX_texture_lod_bias -#define GL_SGIX_texture_lod_bias 1 - -#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias) - -#endif /* GL_SGIX_texture_lod_bias */ - -/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */ - -#ifndef GL_SGIX_texture_multi_buffer -#define GL_SGIX_texture_multi_buffer 1 - -#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E - -#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer) - -#endif /* GL_SGIX_texture_multi_buffer */ - -/* ------------------------- GL_SGIX_texture_range ------------------------- */ - -#ifndef GL_SGIX_texture_range -#define GL_SGIX_texture_range 1 - -#define GL_RGB_SIGNED_SGIX 0x85E0 -#define GL_RGBA_SIGNED_SGIX 0x85E1 -#define GL_ALPHA_SIGNED_SGIX 0x85E2 -#define GL_LUMINANCE_SIGNED_SGIX 0x85E3 -#define GL_INTENSITY_SIGNED_SGIX 0x85E4 -#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5 -#define GL_RGB16_SIGNED_SGIX 0x85E6 -#define GL_RGBA16_SIGNED_SGIX 0x85E7 -#define GL_ALPHA16_SIGNED_SGIX 0x85E8 -#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9 -#define GL_INTENSITY16_SIGNED_SGIX 0x85EA -#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB -#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC -#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED -#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE -#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF -#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0 -#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1 -#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2 -#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3 -#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4 -#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5 -#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6 -#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7 -#define GL_MIN_LUMINANCE_SGIS 0x85F8 -#define GL_MAX_LUMINANCE_SGIS 0x85F9 -#define GL_MIN_INTENSITY_SGIS 0x85FA -#define GL_MAX_INTENSITY_SGIS 0x85FB - -#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range) - -#endif /* GL_SGIX_texture_range */ - -/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */ - -#ifndef GL_SGIX_texture_scale_bias -#define GL_SGIX_texture_scale_bias 1 - -#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 -#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A -#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B -#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C - -#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias) - -#endif /* GL_SGIX_texture_scale_bias */ - -/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */ - -#ifndef GL_SGIX_vertex_preclip -#define GL_SGIX_vertex_preclip 1 - -#define GL_VERTEX_PRECLIP_SGIX 0x83EE -#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF - -#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip) - -#endif /* GL_SGIX_vertex_preclip */ - -/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */ - -#ifndef GL_SGIX_vertex_preclip_hint -#define GL_SGIX_vertex_preclip_hint 1 - -#define GL_VERTEX_PRECLIP_SGIX 0x83EE -#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF - -#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint) - -#endif /* GL_SGIX_vertex_preclip_hint */ - -/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */ - -#ifndef GL_SGIX_ycrcb -#define GL_SGIX_ycrcb 1 - -#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb) - -#endif /* GL_SGIX_ycrcb */ - -/* -------------------------- GL_SGI_color_matrix -------------------------- */ - -#ifndef GL_SGI_color_matrix -#define GL_SGI_color_matrix 1 - -#define GL_COLOR_MATRIX_SGI 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA -#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB - -#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix) - -#endif /* GL_SGI_color_matrix */ - -/* --------------------------- GL_SGI_color_table -------------------------- */ - -#ifndef GL_SGI_color_table -#define GL_SGI_color_table 1 - -#define GL_COLOR_TABLE_SGI 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 -#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 -#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 -#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 -#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 -#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF - -typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table); -typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table); - -#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) -#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) -#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI) -#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI) -#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI) -#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI) -#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI) - -#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table) - -#endif /* GL_SGI_color_table */ - -/* ----------------------- GL_SGI_texture_color_table ---------------------- */ - -#ifndef GL_SGI_texture_color_table -#define GL_SGI_texture_color_table 1 - -#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC -#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD - -#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table) - -#endif /* GL_SGI_texture_color_table */ - -/* ------------------------- GL_SUNX_constant_data ------------------------- */ - -#ifndef GL_SUNX_constant_data -#define GL_SUNX_constant_data 1 - -#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 -#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 - -typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); - -#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX) - -#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data) - -#endif /* GL_SUNX_constant_data */ - -/* -------------------- GL_SUN_convolution_border_modes -------------------- */ - -#ifndef GL_SUN_convolution_border_modes -#define GL_SUN_convolution_border_modes 1 - -#define GL_WRAP_BORDER_SUN 0x81D4 - -#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes) - -#endif /* GL_SUN_convolution_border_modes */ - -/* -------------------------- GL_SUN_global_alpha -------------------------- */ - -#ifndef GL_SUN_global_alpha -#define GL_SUN_global_alpha 1 - -#define GL_GLOBAL_ALPHA_SUN 0x81D9 -#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA - -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); -typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); - -#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN) -#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN) -#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN) -#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN) -#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN) -#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN) -#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN) -#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN) - -#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha) - -#endif /* GL_SUN_global_alpha */ - -/* --------------------------- GL_SUN_mesh_array --------------------------- */ - -#ifndef GL_SUN_mesh_array -#define GL_SUN_mesh_array 1 - -#define GL_QUAD_MESH_SUN 0x8614 -#define GL_TRIANGLE_MESH_SUN 0x8615 - -#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array) - -#endif /* GL_SUN_mesh_array */ - -/* ------------------------ GL_SUN_read_video_pixels ----------------------- */ - -#ifndef GL_SUN_read_video_pixels -#define GL_SUN_read_video_pixels 1 - -typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); - -#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN) - -#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels) - -#endif /* GL_SUN_read_video_pixels */ - -/* --------------------------- GL_SUN_slice_accum -------------------------- */ - -#ifndef GL_SUN_slice_accum -#define GL_SUN_slice_accum 1 - -#define GL_SLICE_ACCUM_SUN 0x85CC - -#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum) - -#endif /* GL_SUN_slice_accum */ - -/* -------------------------- GL_SUN_triangle_list ------------------------- */ - -#ifndef GL_SUN_triangle_list -#define GL_SUN_triangle_list 1 - -#define GL_RESTART_SUN 0x01 -#define GL_REPLACE_MIDDLE_SUN 0x02 -#define GL_REPLACE_OLDEST_SUN 0x03 -#define GL_TRIANGLE_LIST_SUN 0x81D7 -#define GL_REPLACEMENT_CODE_SUN 0x81D8 -#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 -#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 -#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 -#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 -#define GL_R1UI_V3F_SUN 0x85C4 -#define GL_R1UI_C4UB_V3F_SUN 0x85C5 -#define GL_R1UI_C3F_V3F_SUN 0x85C6 -#define GL_R1UI_N3F_V3F_SUN 0x85C7 -#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 -#define GL_R1UI_T2F_V3F_SUN 0x85C9 -#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA -#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB - -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code); - -#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN) -#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN) -#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN) -#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN) -#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN) -#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN) -#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN) - -#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list) - -#endif /* GL_SUN_triangle_list */ - -/* ----------------------------- GL_SUN_vertex ----------------------------- */ - -#ifndef GL_SUN_vertex -#define GL_SUN_vertex 1 - -typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v); - -#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN) -#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN) -#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN) -#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN) -#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN) -#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN) -#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN) -#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN) -#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN) -#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN) -#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN) -#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN) -#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN) -#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN) -#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN) -#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN) -#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN) -#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN) -#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) -#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) -#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) -#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) -#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN) -#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN) -#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN) -#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN) -#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN) -#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN) -#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN) -#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN) -#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN) -#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN) -#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN) -#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN) -#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN) -#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN) -#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN) -#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN) -#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN) -#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN) - -#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex) - -#endif /* GL_SUN_vertex */ - -/* -------------------------- GL_WIN_phong_shading ------------------------- */ - -#ifndef GL_WIN_phong_shading -#define GL_WIN_phong_shading 1 - -#define GL_PHONG_WIN 0x80EA -#define GL_PHONG_HINT_WIN 0x80EB - -#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading) - -#endif /* GL_WIN_phong_shading */ - -/* -------------------------- GL_WIN_specular_fog -------------------------- */ - -#ifndef GL_WIN_specular_fog -#define GL_WIN_specular_fog 1 - -#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC - -#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog) - -#endif /* GL_WIN_specular_fog */ - -/* ---------------------------- GL_WIN_swap_hint --------------------------- */ - -#ifndef GL_WIN_swap_hint -#define GL_WIN_swap_hint 1 - -typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height); - -#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN) - -#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint) - -#endif /* GL_WIN_swap_hint */ - -/* ------------------------------------------------------------------------- */ - -#if defined(GLEW_MX) && defined(_WIN32) -#define GLEW_FUN_EXPORT -#else -#define GLEW_FUN_EXPORT GLEWAPI -#endif /* GLEW_MX */ - -#if defined(GLEW_MX) -#define GLEW_VAR_EXPORT -#else -#define GLEW_VAR_EXPORT GLEWAPI -#endif /* GLEW_MX */ - -#if defined(GLEW_MX) && defined(_WIN32) -struct GLEWContextStruct -{ -#endif /* GLEW_MX */ - -GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D; -GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements; -GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D; -GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D; - -GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture; -GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D; -GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage; -GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd; -GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf; -GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd; -GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv; -GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage; - -GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor; -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation; -GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate; -GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer; -GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd; -GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv; -GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf; -GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv; -GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays; -GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv; - -GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery; -GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer; -GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData; -GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData; -GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers; -GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries; -GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery; -GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers; -GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries; -GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv; -GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv; -GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData; -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv; -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv; -GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv; -GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer; -GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery; -GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer; -GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer; - -GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader; -GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation; -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate; -GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader; -GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram; -GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader; -GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram; -GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader; -GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader; -GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray; -GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers; -GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray; -GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib; -GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform; -GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders; -GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation; -GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog; -GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv; -GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog; -GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource; -GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv; -GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation; -GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv; -GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv; -GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram; -GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader; -GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram; -GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource; -GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate; -GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate; -GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate; -GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f; -GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv; -GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i; -GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv; -GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f; -GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv; -GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i; -GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv; -GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f; -GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv; -GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i; -GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv; -GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f; -GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv; -GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i; -GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv; -GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram; -GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer; - -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv; - -GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender; -GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback; -GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation; -GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor; -GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi; -GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv; -GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv; -GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv; -GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski; -GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei; -GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei; -GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender; -GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback; -GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v; -GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation; -GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi; -GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv; -GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv; -GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying; -GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv; -GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi; -GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv; -GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv; -GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings; -GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui; -GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv; -GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui; -GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv; -GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui; -GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv; -GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui; -GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer; - -GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced; -GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced; -GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex; -GLEW_FUN_EXPORT PFNGLTEXBUFFERPROC __glewTexBuffer; - -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture; -GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v; -GLEW_FUN_EXPORT PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v; - -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor; - -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei; -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIPROC __glewBlendEquationi; -GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei; -GLEW_FUN_EXPORT PFNGLBLENDFUNCIPROC __glewBlendFunci; -GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading; - -GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX; - -GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD; -GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD; -GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD; -GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD; - -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD; -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD; -GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD; -GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD; - -GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD; -GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD; -GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD; - -GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD; -GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD; -GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD; -GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD; -GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD; -GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD; -GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD; -GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD; -GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD; -GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD; -GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD; - -GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD; - -GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD; -GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD; - -GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE; -GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE; -GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE; -GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE; -GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE; - -GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE; -GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE; -GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE; -GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE; -GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE; -GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE; -GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE; -GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE; - -GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE; -GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE; - -GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE; -GLEW_FUN_EXPORT PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE; -GLEW_FUN_EXPORT PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE; - -GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE; -GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE; - -GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE; -GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE; -GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE; -GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE; - -GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE; - -GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE; -GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE; -GLEW_FUN_EXPORT PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE; -GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE; -GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE; -GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE; -GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE; - -GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf; -GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef; -GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat; -GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler; -GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary; - -GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed; -GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex; - -GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB; - -GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB; - -GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData; - -GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB; -GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB; -GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB; -GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB; - -GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB; - -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB; -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB; -GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB; -GLEW_FUN_EXPORT PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB; - -GLEW_FUN_EXPORT PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex; -GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex; -GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex; -GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex; - -GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect; -GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect; - -GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer; -GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer; -GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer; -GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus; -GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers; -GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer; -GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers; -GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers; -GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap; -GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv; -GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv; -GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer; -GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer; -GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage; -GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample; - -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB; - -GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary; -GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri; - -GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d; -GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv; -GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d; -GLEW_FUN_EXPORT PFNGLUNIFORM2DVPROC __glewUniform2dv; -GLEW_FUN_EXPORT PFNGLUNIFORM3DPROC __glewUniform3d; -GLEW_FUN_EXPORT PFNGLUNIFORM3DVPROC __glewUniform3dv; -GLEW_FUN_EXPORT PFNGLUNIFORM4DPROC __glewUniform4d; -GLEW_FUN_EXPORT PFNGLUNIFORM4DVPROC __glewUniform4dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv; - -GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable; -GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable; -GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv; -GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv; -GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable; -GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable; -GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D; -GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv; -GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter; -GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv; -GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv; -GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram; -GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv; -GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv; -GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax; -GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv; -GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv; -GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter; -GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram; -GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax; -GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram; -GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax; -GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D; - -GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB; -GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB; - -GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange; -GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange; - -GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB; -GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB; -GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB; -GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB; -GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB; - -GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB; - -GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB; -GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB; - -GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB; -GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB; -GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB; -GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB; -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB; -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB; -GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB; -GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB; - -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB; - -GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex; - -GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB; -GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB; -GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB; -GLEW_FUN_EXPORT PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB; -GLEW_FUN_EXPORT PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB; -GLEW_FUN_EXPORT PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB; -GLEW_FUN_EXPORT PFNGLGETNMAPIVARBPROC __glewGetnMapivARB; -GLEW_FUN_EXPORT PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB; -GLEW_FUN_EXPORT PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB; -GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB; -GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB; -GLEW_FUN_EXPORT PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB; -GLEW_FUN_EXPORT PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB; -GLEW_FUN_EXPORT PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB; -GLEW_FUN_EXPORT PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB; -GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB; -GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB; -GLEW_FUN_EXPORT PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB; -GLEW_FUN_EXPORT PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB; - -GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB; - -GLEW_FUN_EXPORT PFNGLBINDSAMPLERPROC __glewBindSampler; -GLEW_FUN_EXPORT PFNGLDELETESAMPLERSPROC __glewDeleteSamplers; -GLEW_FUN_EXPORT PFNGLGENSAMPLERSPROC __glewGenSamplers; -GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv; -GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv; -GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv; -GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv; -GLEW_FUN_EXPORT PFNGLISSAMPLERPROC __glewIsSampler; -GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv; -GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv; -GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf; -GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv; -GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri; -GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv; - -GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram; -GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline; -GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv; -GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines; -GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines; -GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog; -GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv; -GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv; -GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages; -GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline; - -GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB; -GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB; -GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB; -GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB; -GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB; -GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB; -GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB; -GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB; -GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB; -GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB; -GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB; -GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB; -GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB; -GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB; -GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB; -GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB; -GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB; -GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB; -GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB; -GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB; -GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB; -GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB; -GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB; -GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB; -GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB; -GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB; -GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB; -GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB; -GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB; -GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB; -GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB; -GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB; -GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB; -GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB; -GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB; -GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB; -GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB; - -GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName; -GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName; -GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv; -GLEW_FUN_EXPORT PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv; -GLEW_FUN_EXPORT PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex; -GLEW_FUN_EXPORT PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation; -GLEW_FUN_EXPORT PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv; -GLEW_FUN_EXPORT PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv; - -GLEW_FUN_EXPORT PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB; -GLEW_FUN_EXPORT PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB; -GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB; -GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB; -GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB; -GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB; - -GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync; -GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync; -GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync; -GLEW_FUN_EXPORT PFNGLGETINTEGER64VPROC __glewGetInteger64v; -GLEW_FUN_EXPORT PFNGLGETSYNCIVPROC __glewGetSynciv; -GLEW_FUN_EXPORT PFNGLISSYNCPROC __glewIsSync; -GLEW_FUN_EXPORT PFNGLWAITSYNCPROC __glewWaitSync; - -GLEW_FUN_EXPORT PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv; -GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri; - -GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB; - -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB; -GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB; - -GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv; -GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski; -GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample; -GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample; - -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v; -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v; -GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter; - -GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback; -GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks; -GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback; -GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks; -GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback; -GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback; -GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback; - -GLEW_FUN_EXPORT PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed; -GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream; -GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed; -GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv; - -GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB; -GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB; -GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB; -GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB; - -GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase; -GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange; -GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName; -GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv; -GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName; -GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv; -GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v; -GLEW_FUN_EXPORT PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex; -GLEW_FUN_EXPORT PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices; -GLEW_FUN_EXPORT PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding; - -GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray; -GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays; -GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays; -GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray; - -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer; - -GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB; -GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB; -GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB; -GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB; -GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB; -GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB; -GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB; -GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB; -GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB; -GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB; - -GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB; -GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB; -GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB; -GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB; -GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB; -GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB; -GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB; -GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB; -GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB; -GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB; -GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB; - -GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB; -GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB; -GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB; -GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB; -GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB; -GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB; -GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB; -GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB; -GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB; -GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB; -GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB; -GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB; -GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB; - -GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB; -GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB; -GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB; - -GLEW_FUN_EXPORT PFNGLCOLORP3UIPROC __glewColorP3ui; -GLEW_FUN_EXPORT PFNGLCOLORP3UIVPROC __glewColorP3uiv; -GLEW_FUN_EXPORT PFNGLCOLORP4UIPROC __glewColorP4ui; -GLEW_FUN_EXPORT PFNGLCOLORP4UIVPROC __glewColorP4uiv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv; -GLEW_FUN_EXPORT PFNGLNORMALP3UIPROC __glewNormalP3ui; -GLEW_FUN_EXPORT PFNGLNORMALP3UIVPROC __glewNormalP3uiv; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv; -GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui; -GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv; -GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui; -GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv; -GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui; -GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv; -GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui; -GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv; -GLEW_FUN_EXPORT PFNGLVERTEXP2UIPROC __glewVertexP2ui; -GLEW_FUN_EXPORT PFNGLVERTEXP2UIVPROC __glewVertexP2uiv; -GLEW_FUN_EXPORT PFNGLVERTEXP3UIPROC __glewVertexP3ui; -GLEW_FUN_EXPORT PFNGLVERTEXP3UIVPROC __glewVertexP3uiv; -GLEW_FUN_EXPORT PFNGLVERTEXP4UIPROC __glewVertexP4ui; -GLEW_FUN_EXPORT PFNGLVERTEXP4UIVPROC __glewVertexP4uiv; - -GLEW_FUN_EXPORT PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv; -GLEW_FUN_EXPORT PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed; -GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v; -GLEW_FUN_EXPORT PFNGLGETFLOATI_VPROC __glewGetFloati_v; -GLEW_FUN_EXPORT PFNGLSCISSORARRAYVPROC __glewScissorArrayv; -GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDPROC __glewScissorIndexed; -GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv; -GLEW_FUN_EXPORT PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv; -GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf; -GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv; - -GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB; - -GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI; - -GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI; -GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI; -GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI; - -GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI; -GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI; -GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI; -GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI; - -GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI; -GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI; -GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI; -GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI; -GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI; -GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI; -GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI; -GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI; -GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI; -GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI; -GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI; -GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI; -GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI; -GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI; - -GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI; -GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI; - -GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI; -GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI; - -GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI; -GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI; - -GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI; -GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI; -GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI; -GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI; -GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI; -GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI; -GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI; -GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI; -GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI; -GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI; -GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI; -GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI; - -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI; - -GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI; -GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI; -GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI; -GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI; -GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI; - -GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT; -GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT; -GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT; - -GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT; - -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT; - -GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT; - -GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT; - -GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT; -GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT; - -GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT; -GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT; - -GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT; -GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT; -GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT; -GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT; -GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT; -GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT; - -GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT; -GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT; - -GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; - -GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; -GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; - -GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT; - -GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT; -GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT; -GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT; -GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT; -GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT; -GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT; -GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT; -GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT; -GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT; -GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT; -GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT; -GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT; -GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT; -GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT; -GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT; -GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT; -GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT; -GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT; -GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT; -GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT; -GLEW_FUN_EXPORT PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT; -GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT; -GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT; -GLEW_FUN_EXPORT PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT; -GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT; -GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT; -GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT; -GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT; -GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT; -GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT; -GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT; -GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT; -GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT; -GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT; -GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT; -GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT; -GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT; -GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT; -GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT; -GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT; -GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT; -GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT; -GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT; -GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT; -GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT; -GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT; -GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT; -GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT; -GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT; -GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT; -GLEW_FUN_EXPORT PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT; -GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT; -GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT; -GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT; -GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT; -GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT; -GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT; -GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT; -GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT; -GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT; - -GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT; -GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT; -GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT; -GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT; -GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT; -GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT; - -GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT; -GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT; - -GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT; - -GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT; -GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT; -GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT; -GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT; -GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT; - -GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT; -GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT; - -GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT; - -GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT; - -GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT; -GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT; -GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT; -GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT; -GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT; -GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT; -GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT; -GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT; -GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT; -GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT; -GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT; -GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT; - -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT; -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT; - -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT; - -GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT; -GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT; -GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT; -GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT; - -GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT; -GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT; -GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT; -GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT; -GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT; -GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT; -GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT; -GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT; - -GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT; - -GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT; - -GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT; -GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT; -GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT; - -GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT; -GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT; - -GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT; -GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT; - -GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT; - -GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT; -GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT; -GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT; -GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT; -GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT; -GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT; - -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT; - -GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT; - -GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT; - -GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT; -GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT; - -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT; - -GLEW_FUN_EXPORT PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT; -GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT; -GLEW_FUN_EXPORT PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT; - -GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT; -GLEW_FUN_EXPORT PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT; - -GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT; - -GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT; -GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT; -GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT; - -GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT; - -GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT; - -GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT; - -GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT; -GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT; -GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT; -GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT; -GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT; -GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT; - -GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT; -GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT; -GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT; -GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT; -GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT; -GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT; - -GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT; - -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT; -GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT; - -GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT; -GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT; -GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT; -GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT; -GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT; -GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT; -GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT; - -GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT; -GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT; -GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT; -GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT; -GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT; -GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT; -GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT; -GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT; - -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT; - -GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT; -GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT; -GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT; -GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT; -GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT; -GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT; -GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT; -GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT; -GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT; -GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT; -GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT; -GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT; -GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT; -GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT; -GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT; -GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT; -GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT; -GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT; -GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT; -GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT; -GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT; -GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT; -GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT; -GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT; -GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT; -GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT; -GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT; -GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT; -GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT; -GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT; -GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT; -GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT; -GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT; -GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT; -GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT; -GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT; -GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT; -GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT; -GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT; -GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT; -GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT; -GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT; - -GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT; -GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT; -GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT; - -GLEW_FUN_EXPORT PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT; - -GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY; - -GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY; - -GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP; -GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP; -GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP; -GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP; -GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP; -GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP; - -GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM; -GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM; - -GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM; -GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM; -GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM; -GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM; -GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM; -GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM; -GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM; - -GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL; -GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; -GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; -GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; - -GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; -GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; - -GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT; -GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT; -GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT; -GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT; -GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT; - -GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA; - -GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA; -GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA; - -GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV; -GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV; - -GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV; - -GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV; -GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV; -GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV; - -GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV; -GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV; -GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV; -GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV; -GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV; -GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV; -GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV; - -GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV; -GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV; -GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV; - -GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV; -GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV; -GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV; -GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV; -GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV; -GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV; -GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV; - -GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV; -GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV; -GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV; -GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV; -GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV; -GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV; - -GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV; - -GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV; - -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV; - -GLEW_FUN_EXPORT PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV; -GLEW_FUN_EXPORT PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV; -GLEW_FUN_EXPORT PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV; - -GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV; -GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV; -GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV; -GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV; -GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV; -GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV; -GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV; -GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV; -GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV; -GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV; -GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV; -GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV; -GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV; -GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV; -GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV; -GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV; -GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV; -GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV; - -GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV; -GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV; -GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV; -GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV; -GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV; -GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV; -GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV; - -GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV; -GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV; - -GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV; -GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV; - -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV; -GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV; - -GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV; -GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV; -GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV; - -GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV; -GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV; - -GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV; -GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV; -GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV; -GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV; -GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV; -GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV; -GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV; -GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV; -GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV; -GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV; - -GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV; - -GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV; -GLEW_FUN_EXPORT PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV; -GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV; -GLEW_FUN_EXPORT PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV; -GLEW_FUN_EXPORT PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV; -GLEW_FUN_EXPORT PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV; -GLEW_FUN_EXPORT PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV; -GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV; -GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV; -GLEW_FUN_EXPORT PFNGLUNIFORMUI64NVPROC __glewUniformui64NV; -GLEW_FUN_EXPORT PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV; - -GLEW_FUN_EXPORT PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV; - -GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV; -GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV; -GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV; - -GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV; -GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV; -GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV; -GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV; -GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV; -GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV; -GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV; -GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV; -GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV; -GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV; -GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV; - -GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV; -GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV; -GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV; -GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV; -GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV; -GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV; -GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV; - -GLEW_FUN_EXPORT PFNGLVDPAUFININVPROC __glewVDPAUFiniNV; -GLEW_FUN_EXPORT PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV; -GLEW_FUN_EXPORT PFNGLVDPAUINITNVPROC __glewVDPAUInitNV; -GLEW_FUN_EXPORT PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV; -GLEW_FUN_EXPORT PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV; -GLEW_FUN_EXPORT PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV; -GLEW_FUN_EXPORT PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV; -GLEW_FUN_EXPORT PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV; -GLEW_FUN_EXPORT PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV; -GLEW_FUN_EXPORT PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV; - -GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV; -GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV; - -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV; - -GLEW_FUN_EXPORT PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV; -GLEW_FUN_EXPORT PFNGLCOLORFORMATNVPROC __glewColorFormatNV; -GLEW_FUN_EXPORT PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV; -GLEW_FUN_EXPORT PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV; -GLEW_FUN_EXPORT PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV; -GLEW_FUN_EXPORT PFNGLINDEXFORMATNVPROC __glewIndexFormatNV; -GLEW_FUN_EXPORT PFNGLNORMALFORMATNVPROC __glewNormalFormatNV; -GLEW_FUN_EXPORT PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV; -GLEW_FUN_EXPORT PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV; -GLEW_FUN_EXPORT PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV; - -GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV; -GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV; -GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV; -GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV; -GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV; -GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV; -GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV; -GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV; -GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV; -GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV; -GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV; -GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV; -GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV; -GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV; -GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV; -GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV; -GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV; - -GLEW_FUN_EXPORT PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV; -GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV; -GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV; -GLEW_FUN_EXPORT PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV; -GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV; -GLEW_FUN_EXPORT PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV; -GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV; -GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV; -GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV; - -GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES; -GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES; -GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES; -GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES; -GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES; -GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES; - -GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; -GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; - -GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS; -GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS; - -GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS; -GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS; - -GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS; -GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS; - -GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS; -GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS; - -GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS; -GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS; - -GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX; -GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX; -GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX; -GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX; -GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX; -GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX; - -GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX; - -GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX; - -GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX; -GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX; -GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX; - -GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX; - -GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX; - -GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX; - -GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX; -GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX; -GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX; -GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX; - -GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX; - -GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI; -GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI; -GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI; -GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI; -GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI; - -GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX; - -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN; -GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN; - -GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN; - -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN; - -GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN; -GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN; -GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN; -GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN; -GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN; -GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN; - -GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN; - -#if defined(GLEW_MX) && !defined(_WIN32) -struct GLEWContextStruct -{ -#endif /* GLEW_MX */ - -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2_1; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_1; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0; -GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1; -GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer; -GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_blend_minmax_factor; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles; -GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_object_purgeable; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_row_bytes; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators; -GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_get_program_binary; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader5; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map_array; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array; -GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos; -GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites; -GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3; -GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route; -GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_meminfo; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object; -GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_provoking_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB_decode; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_snorm; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_attrib_64bit; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting; -GLEW_VAR_EXPORT GLboolean __GLEW_EXT_x11_sync_object; -GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator; -GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker; -GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes; -GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform; -GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test; -GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting; -GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays; -GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip; -GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data; -GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; -GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; -GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; -GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; -GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; -GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; -GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; -GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert; -GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers; -GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos; -GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_coverage; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_barrier; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vdpau_interop; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_attrib_integer_64bit; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_buffer_unified_memory; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4; -GLEW_VAR_EXPORT GLboolean __GLEW_NV_video_capture; -GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates; -GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format; -GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision; -GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace; -GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample; -GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample; -GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints; -GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints; -GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; -GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint; -GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb; -GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix; -GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table; -GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table; -GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list; -GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex; -GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading; -GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog; -GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint; - -#ifdef GLEW_MX -}; /* GLEWContextStruct */ -#endif /* GLEW_MX */ - -/* ------------------------------------------------------------------------- */ - -/* error codes */ -#define GLEW_OK 0 -#define GLEW_NO_ERROR 0 -#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */ -#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* Need at least OpenGL 1.1 */ -#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* Need at least GLX 1.2 */ - -/* string codes */ -#define GLEW_VERSION 1 -#define GLEW_VERSION_MAJOR 2 -#define GLEW_VERSION_MINOR 3 -#define GLEW_VERSION_MICRO 4 - -/* API */ -#ifdef GLEW_MX - -typedef struct GLEWContextStruct GLEWContext; -GLEWAPI GLenum glewContextInit (GLEWContext* ctx); -GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name); - -#define glewInit() glewContextInit(glewGetContext()) -#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x) -#define glewIsExtensionSupported(x) glewIsSupported(x) - -#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x)) -#ifdef _WIN32 -# define GLEW_GET_FUN(x) glewGetContext()->x -#else -# define GLEW_GET_FUN(x) x -#endif - -#else /* GLEW_MX */ - -GLEWAPI GLenum glewInit (); -GLEWAPI GLboolean glewIsSupported (const char* name); -#define glewIsExtensionSupported(x) glewIsSupported(x) - -#define GLEW_GET_VAR(x) (*(const GLboolean*)&x) -#define GLEW_GET_FUN(x) x - -#endif /* GLEW_MX */ - -GLEWAPI GLboolean glewExperimental; -GLEWAPI GLboolean glewGetExtension (const char* name); -GLEWAPI const GLubyte* glewGetErrorString (GLenum error); -GLEWAPI const GLubyte* glewGetString (GLenum name); - -#ifdef __cplusplus -} -#endif - -#ifdef GLEW_APIENTRY_DEFINED -#undef GLEW_APIENTRY_DEFINED -#undef APIENTRY -#undef GLAPIENTRY -#define GLAPIENTRY -#endif - -#ifdef GLEW_CALLBACK_DEFINED -#undef GLEW_CALLBACK_DEFINED -#undef CALLBACK -#endif - -#ifdef GLEW_WINGDIAPI_DEFINED -#undef GLEW_WINGDIAPI_DEFINED -#undef WINGDIAPI -#endif - -#undef GLAPI -/* #undef GLEWAPI */ - -#endif /* __glew_h__ */ diff --git a/Code/Physics/Bullet Source/Glut/GL/glext.h b/Code/Physics/Bullet Source/Glut/GL/glext.h deleted file mode 100644 index 10c2bc0f..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/glext.h +++ /dev/null @@ -1,3326 +0,0 @@ -#ifndef __glext_h_ -#define __glext_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright 1998, 1999, 2000, 2001, NVIDIA Corporation. -** All rights Reserved. -** -** THE INFORMATION CONTAINED HEREIN IS PROPRIETARY AND CONFIDENTIAL TO -** NVIDIA, CORPORATION. USE, REPRODUCTION OR DISCLOSURE TO ANY THIRD PARTY -** IS SUBJECT TO WRITTEN PRE-APPROVAL BY NVIDIA, CORPORATION. -*/ - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 1.1 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: This software was created using the -** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has -** not been independently verified as being compliant with the OpenGL(R) -** version 1.2.1 Specification. -*/ - -#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) -#define WIN32_LEAN_AND_MEAN 1 -#include -#endif - -#ifndef APIENTRY -#define APIENTRY -#endif - -/*************************************************************/ - -/* Header file version number, required by OpenGL ABI for Linux */ -#define GL_GLEXT_VERSION 6 - -#ifndef GL_VERSION_1_2 -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 -#define GL_FUNC_ADD 0x8006 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_BLEND_EQUATION 0x8009 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_CONVOLUTION_1D 0x8010 -#define GL_CONVOLUTION_2D 0x8011 -#define GL_SEPARABLE_2D 0x8012 -#define GL_CONVOLUTION_BORDER_MODE 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS 0x8015 -#define GL_REDUCE 0x8016 -#define GL_CONVOLUTION_FORMAT 0x8017 -#define GL_CONVOLUTION_WIDTH 0x8018 -#define GL_CONVOLUTION_HEIGHT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 -#define GL_HISTOGRAM 0x8024 -#define GL_PROXY_HISTOGRAM 0x8025 -#define GL_HISTOGRAM_WIDTH 0x8026 -#define GL_HISTOGRAM_FORMAT 0x8027 -#define GL_HISTOGRAM_RED_SIZE 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C -#define GL_HISTOGRAM_SINK 0x802D -#define GL_MINMAX 0x802E -#define GL_MINMAX_FORMAT 0x802F -#define GL_MINMAX_SINK 0x8030 -#define GL_TABLE_TOO_LARGE 0x8031 -#define GL_UNSIGNED_BYTE_3_3_2 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_RESCALE_NORMAL 0x803A -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_COLOR_MATRIX 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA -#define GL_COLOR_TABLE 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 -#define GL_PROXY_COLOR_TABLE 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 -#define GL_COLOR_TABLE_SCALE 0x80D6 -#define GL_COLOR_TABLE_BIAS 0x80D7 -#define GL_COLOR_TABLE_FORMAT 0x80D8 -#define GL_COLOR_TABLE_WIDTH 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#endif - -#ifndef GL_ARB_multitexture -#define GL_TEXTURE0_ARB 0x84C0 -#define GL_TEXTURE1_ARB 0x84C1 -#define GL_TEXTURE2_ARB 0x84C2 -#define GL_TEXTURE3_ARB 0x84C3 -#define GL_TEXTURE4_ARB 0x84C4 -#define GL_TEXTURE5_ARB 0x84C5 -#define GL_TEXTURE6_ARB 0x84C6 -#define GL_TEXTURE7_ARB 0x84C7 -#define GL_TEXTURE8_ARB 0x84C8 -#define GL_TEXTURE9_ARB 0x84C9 -#define GL_TEXTURE10_ARB 0x84CA -#define GL_TEXTURE11_ARB 0x84CB -#define GL_TEXTURE12_ARB 0x84CC -#define GL_TEXTURE13_ARB 0x84CD -#define GL_TEXTURE14_ARB 0x84CE -#define GL_TEXTURE15_ARB 0x84CF -#define GL_TEXTURE16_ARB 0x84D0 -#define GL_TEXTURE17_ARB 0x84D1 -#define GL_TEXTURE18_ARB 0x84D2 -#define GL_TEXTURE19_ARB 0x84D3 -#define GL_TEXTURE20_ARB 0x84D4 -#define GL_TEXTURE21_ARB 0x84D5 -#define GL_TEXTURE22_ARB 0x84D6 -#define GL_TEXTURE23_ARB 0x84D7 -#define GL_TEXTURE24_ARB 0x84D8 -#define GL_TEXTURE25_ARB 0x84D9 -#define GL_TEXTURE26_ARB 0x84DA -#define GL_TEXTURE27_ARB 0x84DB -#define GL_TEXTURE28_ARB 0x84DC -#define GL_TEXTURE29_ARB 0x84DD -#define GL_TEXTURE30_ARB 0x84DE -#define GL_TEXTURE31_ARB 0x84DF -#define GL_ACTIVE_TEXTURE_ARB 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 -#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 -#endif - -#ifndef GL_ARB_transpose_matrix -#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 -#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 -#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 -#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 -#endif - -#ifndef GL_ARB_multisample -#define GL_MULTISAMPLE_ARB 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F -#define GL_SAMPLE_COVERAGE_ARB 0x80A0 -#define GL_SAMPLE_BUFFERS_ARB 0x80A8 -#define GL_SAMPLES_ARB 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB -#define GL_MULTISAMPLE_BIT_ARB 0x20000000 -#endif - -#ifndef GL_ARB_texture_cube_map -#define GL_NORMAL_MAP_ARB 0x8511 -#define GL_REFLECTION_MAP_ARB 0x8512 -#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C -#endif - -#ifndef GL_ARB_texture_compression -#define GL_COMPRESSED_ALPHA_ARB 0x84E9 -#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB -#define GL_COMPRESSED_INTENSITY_ARB 0x84EC -#define GL_COMPRESSED_RGB_ARB 0x84ED -#define GL_COMPRESSED_RGBA_ARB 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF -#define GL_TEXTURE_IMAGE_SIZE_ARB 0x86A0 -#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 -#endif - -#ifndef GL_EXT_abgr -#define GL_ABGR_EXT 0x8000 -#endif - -#ifndef GL_EXT_blend_color -#define GL_CONSTANT_COLOR_EXT 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 -#define GL_CONSTANT_ALPHA_EXT 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 -#define GL_BLEND_COLOR_EXT 0x8005 -#endif - -#ifndef GL_EXT_polygon_offset -#define GL_POLYGON_OFFSET_EXT 0x8037 -#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 -#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 -#endif - -#ifndef GL_EXT_texture -#define GL_ALPHA4_EXT 0x803B -#define GL_ALPHA8_EXT 0x803C -#define GL_ALPHA12_EXT 0x803D -#define GL_ALPHA16_EXT 0x803E -#define GL_LUMINANCE4_EXT 0x803F -#define GL_LUMINANCE8_EXT 0x8040 -#define GL_LUMINANCE12_EXT 0x8041 -#define GL_LUMINANCE16_EXT 0x8042 -#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 -#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 -#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 -#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 -#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 -#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 -#define GL_INTENSITY_EXT 0x8049 -#define GL_INTENSITY4_EXT 0x804A -#define GL_INTENSITY8_EXT 0x804B -#define GL_INTENSITY12_EXT 0x804C -#define GL_INTENSITY16_EXT 0x804D -#define GL_RGB2_EXT 0x804E -#define GL_RGB4_EXT 0x804F -#define GL_RGB5_EXT 0x8050 -#define GL_RGB8_EXT 0x8051 -#define GL_RGB10_EXT 0x8052 -#define GL_RGB12_EXT 0x8053 -#define GL_RGB16_EXT 0x8054 -#define GL_RGBA2_EXT 0x8055 -#define GL_RGBA4_EXT 0x8056 -#define GL_RGB5_A1_EXT 0x8057 -#define GL_RGBA8_EXT 0x8058 -#define GL_RGB10_A2_EXT 0x8059 -#define GL_RGBA12_EXT 0x805A -#define GL_RGBA16_EXT 0x805B -#define GL_TEXTURE_RED_SIZE_EXT 0x805C -#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D -#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E -#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F -#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 -#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 -#define GL_REPLACE_EXT 0x8062 -#define GL_PROXY_TEXTURE_1D_EXT 0x8063 -#define GL_PROXY_TEXTURE_2D_EXT 0x8064 -#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 -#endif - -#ifndef GL_EXT_texture3D -#define GL_PACK_SKIP_IMAGES 0x806B -#define GL_PACK_SKIP_IMAGES_EXT 0x806B -#define GL_PACK_IMAGE_HEIGHT 0x806C -#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_TEXTURE_3D_EXT 0x806F -#define GL_PROXY_TEXTURE_3D 0x8070 -#define GL_PROXY_TEXTURE_3D_EXT 0x8070 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_DEPTH_EXT 0x8071 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_TEXTURE_WRAP_R_EXT 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 -#endif - -#ifndef GL_SGIS_texture_filter4 -#define GL_FILTER4_SGIS 0x8146 -#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 -#endif - -#ifndef GL_EXT_subtexture -#endif - -#ifndef GL_EXT_copy_texture -#endif - -#ifndef GL_EXT_histogram -#define GL_HISTOGRAM_EXT 0x8024 -#define GL_PROXY_HISTOGRAM_EXT 0x8025 -#define GL_HISTOGRAM_WIDTH_EXT 0x8026 -#define GL_HISTOGRAM_FORMAT_EXT 0x8027 -#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C -#define GL_HISTOGRAM_SINK_EXT 0x802D -#define GL_MINMAX_EXT 0x802E -#define GL_MINMAX_FORMAT_EXT 0x802F -#define GL_MINMAX_SINK_EXT 0x8030 -#define GL_TABLE_TOO_LARGE_EXT 0x8031 -#endif - -#ifndef GL_EXT_convolution -#define GL_CONVOLUTION_1D_EXT 0x8010 -#define GL_CONVOLUTION_2D_EXT 0x8011 -#define GL_SEPARABLE_2D_EXT 0x8012 -#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 -#define GL_REDUCE_EXT 0x8016 -#define GL_CONVOLUTION_FORMAT_EXT 0x8017 -#define GL_CONVOLUTION_WIDTH_EXT 0x8018 -#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 -#endif - -#ifndef GL_SGI_color_matrix -#define GL_COLOR_MATRIX_SGI 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA -#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB -#endif - -#ifndef GL_SGI_color_table -#define GL_COLOR_TABLE_SGI 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 -#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 -#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 -#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 -#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 -#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF -#endif - -#ifndef GL_SGIS_pixel_texture -#define GL_PIXEL_TEXTURE_SGIS 0x8353 -#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 -#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 -#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 -#endif - -#ifndef GL_SGIX_pixel_texture -#define GL_PIXEL_TEX_BUM_SGIX 0x8139 -#define GL_PIXEL_TEX_BUM_MODE_SGIX 0x832B -#endif - -#ifndef GL_SGIS_texture4D -#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 -#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 -#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 -#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 -#define GL_TEXTURE_4D_SGIS 0x8134 -#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 -#define GL_TEXTURE_4DSIZE_SGIS 0x8136 -#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 -#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 -#define GL_TEXTURE_4D_BINDING_SGIS 0x814F -#endif - -#ifndef GL_SGI_texture_color_table -#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC -#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD -#endif - -#ifndef GL_EXT_cmyka -#define GL_CMYK_EXT 0x800C -#define GL_CMYKA_EXT 0x800D -#define GL_PACK_CMYK_HINT_EXT 0x800E -#define GL_UNPACK_CMYK_HINT_EXT 0x800F -#endif - -#ifndef GL_EXT_texture_object -#define GL_TEXTURE_PRIORITY_EXT 0x8066 -#define GL_TEXTURE_RESIDENT_EXT 0x8067 -#define GL_TEXTURE_1D_BINDING_EXT 0x8068 -#define GL_TEXTURE_2D_BINDING_EXT 0x8069 -#define GL_TEXTURE_3D_BINDING_EXT 0x806A -#endif - -#ifndef GL_SGIS_detail_texture -#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 -#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 -#define GL_LINEAR_DETAIL_SGIS 0x8097 -#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 -#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 -#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A -#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B -#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C -#endif - -#ifndef GL_SGIS_sharpen_texture -#define GL_LINEAR_SHARPEN_SGIS 0x80AD -#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE -#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF -#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 -#endif - -#ifndef GL_EXT_packed_pixels -#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 -#endif - -#ifndef GL_SGIS_texture_lod -#define GL_TEXTURE_MIN_LOD_SGIS 0x813A -#define GL_TEXTURE_MAX_LOD_SGIS 0x813B -#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C -#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D -#endif - -#ifndef GL_SGIS_multisample -#define GL_MULTISAMPLE_SGIS 0x809D -#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F -#define GL_SAMPLE_MASK_SGIS 0x80A0 -#define GL_1PASS_SGIS 0x80A1 -#define GL_2PASS_0_SGIS 0x80A2 -#define GL_2PASS_1_SGIS 0x80A3 -#define GL_4PASS_0_SGIS 0x80A4 -#define GL_4PASS_1_SGIS 0x80A5 -#define GL_4PASS_2_SGIS 0x80A6 -#define GL_4PASS_3_SGIS 0x80A7 -#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 -#define GL_SAMPLES_SGIS 0x80A9 -#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA -#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB -#define GL_SAMPLE_PATTERN_SGIS 0x80AC -#endif - -#ifndef GL_EXT_rescale_normal -#define GL_RESCALE_NORMAL_EXT 0x803A -#endif - -#ifndef GL_EXT_vertex_array -#define GL_VERTEX_ARRAY_EXT 0x8074 -#define GL_NORMAL_ARRAY_EXT 0x8075 -#define GL_COLOR_ARRAY_EXT 0x8076 -#define GL_INDEX_ARRAY_EXT 0x8077 -#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 -#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 -#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A -#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B -#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C -#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D -#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E -#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F -#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 -#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 -#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 -#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 -#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 -#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 -#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 -#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 -#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 -#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 -#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A -#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B -#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C -#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D -#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E -#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F -#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 -#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 -#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 -#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 -#endif - -#ifndef GL_EXT_misc_attribute -#endif - -#ifndef GL_SGIS_generate_mipmap -#define GL_GENERATE_MIPMAP_SGIS 0x8191 -#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 -#endif - -#ifndef GL_SGIX_clipmap -#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 -#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 -#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 -#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 -#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 -#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 -#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 -#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 -#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 -#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D -#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E -#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F -#endif - -#ifndef GL_SGIX_shadow -#define GL_TEXTURE_COMPARE_SGIX 0x819A -#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B -#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C -#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D -#endif - -#ifndef GL_SGIS_texture_edge_clamp -#define GL_CLAMP_TO_EDGE_SGIS 0x812F -#endif - -#ifndef GL_SGIS_texture_border_clamp -#define GL_CLAMP_TO_BORDER_SGIS 0x812D -#endif - -#ifndef GL_EXT_blend_minmax -#define GL_FUNC_ADD_EXT 0x8006 -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#define GL_BLEND_EQUATION_EXT 0x8009 -#endif - -#ifndef GL_EXT_blend_subtract -#define GL_FUNC_SUBTRACT_EXT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B -#endif - -#ifndef GL_EXT_blend_logic_op -#endif - -#ifndef GL_SGIX_interlace -#define GL_INTERLACE_SGIX 0x8094 -#endif - -#ifndef GL_SGIX_pixel_tiles -#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E -#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F -#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 -#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 -#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 -#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 -#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 -#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 -#endif - -#ifndef GL_SGIS_texture_select -#define GL_DUAL_ALPHA4_SGIS 0x8110 -#define GL_DUAL_ALPHA8_SGIS 0x8111 -#define GL_DUAL_ALPHA12_SGIS 0x8112 -#define GL_DUAL_ALPHA16_SGIS 0x8113 -#define GL_DUAL_LUMINANCE4_SGIS 0x8114 -#define GL_DUAL_LUMINANCE8_SGIS 0x8115 -#define GL_DUAL_LUMINANCE12_SGIS 0x8116 -#define GL_DUAL_LUMINANCE16_SGIS 0x8117 -#define GL_DUAL_INTENSITY4_SGIS 0x8118 -#define GL_DUAL_INTENSITY8_SGIS 0x8119 -#define GL_DUAL_INTENSITY12_SGIS 0x811A -#define GL_DUAL_INTENSITY16_SGIS 0x811B -#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C -#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D -#define GL_QUAD_ALPHA4_SGIS 0x811E -#define GL_QUAD_ALPHA8_SGIS 0x811F -#define GL_QUAD_LUMINANCE4_SGIS 0x8120 -#define GL_QUAD_LUMINANCE8_SGIS 0x8121 -#define GL_QUAD_INTENSITY4_SGIS 0x8122 -#define GL_QUAD_INTENSITY8_SGIS 0x8123 -#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 -#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 -#endif - -#ifndef GL_SGIX_sprite -#define GL_SPRITE_SGIX 0x8148 -#define GL_SPRITE_MODE_SGIX 0x8149 -#define GL_SPRITE_AXIS_SGIX 0x814A -#define GL_SPRITE_TRANSLATION_SGIX 0x814B -#define GL_SPRITE_AXIAL_SGIX 0x814C -#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D -#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E -#endif - -#ifndef GL_SGIX_texture_multi_buffer -#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E -#endif - -#ifndef GL_SGIS_point_parameters -#define GL_POINT_SIZE_MIN_EXT 0x8126 -#define GL_POINT_SIZE_MIN_SGIS 0x8126 -#define GL_POINT_SIZE_MAX_EXT 0x8127 -#define GL_POINT_SIZE_MAX_SGIS 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 -#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 -#define GL_DISTANCE_ATTENUATION_EXT 0x8129 -#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 -#endif - -#ifndef GL_SGIX_instruments -#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 -#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 -#endif - -#ifndef GL_SGIX_texture_scale_bias -#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 -#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A -#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B -#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C -#endif - -#ifndef GL_SGIX_framezoom -#define GL_FRAMEZOOM_SGIX 0x818B -#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C -#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D -#endif - -#ifndef GL_SGIX_tag_sample_buffer -#endif - -#ifndef GL_SGIX_reference_plane -#define GL_REFERENCE_PLANE_SGIX 0x817D -#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E -#endif - -#ifndef GL_SGIX_flush_raster -#endif - -#ifndef GL_SGIX_depth_texture -#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 -#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 -#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 -#endif - -#ifndef GL_SGIS_fog_function -#define GL_FOG_FUNC_SGIS 0x812A -#define GL_FOG_FUNC_POINTS_SGIS 0x812B -#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C -#endif - -#ifndef GL_SGIX_fog_offset -#define GL_FOG_OFFSET_SGIX 0x8198 -#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 -#endif - -#ifndef GL_HP_image_transform -#define GL_IMAGE_SCALE_X_HP 0x8155 -#define GL_IMAGE_SCALE_Y_HP 0x8156 -#define GL_IMAGE_TRANSLATE_X_HP 0x8157 -#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 -#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 -#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A -#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B -#define GL_IMAGE_MAG_FILTER_HP 0x815C -#define GL_IMAGE_MIN_FILTER_HP 0x815D -#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E -#define GL_CUBIC_HP 0x815F -#define GL_AVERAGE_HP 0x8160 -#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 -#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 -#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 -#endif - -#ifndef GL_HP_convolution_border_modes -#define GL_IGNORE_BORDER_HP 0x8150 -#define GL_CONSTANT_BORDER_HP 0x8151 -#define GL_REPLICATE_BORDER_HP 0x8153 -#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 -#endif - -#ifndef GL_INGR_palette_buffer -#endif - -#ifndef GL_SGIX_texture_add_env -#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE -#endif - -#ifndef GL_EXT_color_subtable -#endif - -#ifndef GL_PGI_vertex_hints -#define GL_VERTEX_DATA_HINT_PGI 0x1A22A -#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B -#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C -#define GL_MAX_VERTEX_HINT_PGI 0x1A22D -#define GL_COLOR3_BIT_PGI 0x00010000 -#define GL_COLOR4_BIT_PGI 0x00020000 -#define GL_EDGEFLAG_BIT_PGI 0x00040000 -#define GL_INDEX_BIT_PGI 0x00080000 -#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 -#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 -#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 -#define GL_MAT_EMISSION_BIT_PGI 0x00800000 -#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 -#define GL_MAT_SHININESS_BIT_PGI 0x02000000 -#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 -#define GL_NORMAL_BIT_PGI 0x08000000 -#define GL_TEXCOORD1_BIT_PGI 0x10000000 -#define GL_TEXCOORD2_BIT_PGI 0x20000000 -#define GL_TEXCOORD3_BIT_PGI 0x40000000 -#define GL_TEXCOORD4_BIT_PGI 0x80000000 -#define GL_VERTEX23_BIT_PGI 0x00000004 -#define GL_VERTEX4_BIT_PGI 0x00000008 -#endif - -#ifndef GL_PGI_misc_hints -#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 -#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD -#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE -#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 -#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 -#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 -#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C -#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D -#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E -#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F -#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 -#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 -#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 -#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 -#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 -#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 -#define GL_CLIP_NEAR_HINT_PGI 0x1A220 -#define GL_CLIP_FAR_HINT_PGI 0x1A221 -#define GL_WIDE_LINE_HINT_PGI 0x1A222 -#define GL_BACK_NORMALS_HINT_PGI 0x1A223 -#endif - -#ifndef GL_EXT_paletted_texture -#define GL_COLOR_INDEX1_EXT 0x80E2 -#define GL_COLOR_INDEX2_EXT 0x80E3 -#define GL_COLOR_INDEX4_EXT 0x80E4 -#define GL_COLOR_INDEX8_EXT 0x80E5 -#define GL_COLOR_INDEX12_EXT 0x80E6 -#define GL_COLOR_INDEX16_EXT 0x80E7 -#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED -#endif - -#ifndef GL_EXT_clip_volume_hint -#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 -#endif - -#ifndef GL_SGIX_list_priority -#define GL_LIST_PRIORITY_SGIX 0x8182 -#endif - -#ifndef GL_SGIX_ir_instrument1 -#define GL_IR_INSTRUMENT1_SGIX 0x817F -#endif - -#ifndef GL_SGIX_calligraphic_fragment -#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 -#endif - -#ifndef GL_SGIX_texture_lod_bias -#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E -#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F -#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 -#endif - -#ifndef GL_SGIX_shadow_ambient -#define GL_SHADOW_AMBIENT_SGIX 0x80BF -#endif - -#ifndef GL_EXT_index_texture -#endif - -#ifndef GL_EXT_index_material -#define GL_INDEX_MATERIAL_EXT 0x81B8 -#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 -#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA -#endif - -#ifndef GL_EXT_index_func -#define GL_INDEX_TEST_EXT 0x81B5 -#define GL_INDEX_TEST_FUNC_EXT 0x81B6 -#define GL_INDEX_TEST_REF_EXT 0x81B7 -#endif - -#ifndef GL_EXT_index_array_formats -#define GL_IUI_V2F_EXT 0x81AD -#define GL_IUI_V3F_EXT 0x81AE -#define GL_IUI_N3F_V2F_EXT 0x81AF -#define GL_IUI_N3F_V3F_EXT 0x81B0 -#define GL_T2F_IUI_V2F_EXT 0x81B1 -#define GL_T2F_IUI_V3F_EXT 0x81B2 -#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 -#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 -#endif - -#ifndef GL_EXT_compiled_vertex_array -#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 -#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 -#endif - -#ifndef GL_EXT_cull_vertex -#define GL_CULL_VERTEX_EXT 0x81AA -#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB -#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC -#endif - -#ifndef GL_SGIX_ycrcb -#define GL_YCRCB_422_SGIX 0x81BB -#define GL_YCRCB_444_SGIX 0x81BC -#endif - -#ifndef GL_SGIX_fragment_lighting -#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 -#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 -#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 -#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 -#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 -#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 -#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 -#define GL_LIGHT_ENV_MODE_SGIX 0x8407 -#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 -#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 -#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A -#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B -#define GL_FRAGMENT_LIGHT0_SGIX 0x840C -#define GL_FRAGMENT_LIGHT1_SGIX 0x840D -#define GL_FRAGMENT_LIGHT2_SGIX 0x840E -#define GL_FRAGMENT_LIGHT3_SGIX 0x840F -#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 -#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 -#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 -#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 -#endif - -#ifndef GL_IBM_rasterpos_clip -#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 -#endif - -#ifndef GL_HP_texture_lighting -#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 -#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 -#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 -#endif - -#ifndef GL_EXT_draw_range_elements -#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 -#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 -#endif - -#ifndef GL_WIN_phong_shading -#define GL_PHONG_WIN 0x80EA -#define GL_PHONG_HINT_WIN 0x80EB -#endif - -#ifndef GL_WIN_specular_fog -#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC -#endif - -#ifndef GL_EXT_light_texture -#define GL_FRAGMENT_MATERIAL_EXT 0x8349 -#define GL_FRAGMENT_NORMAL_EXT 0x834A -#define GL_FRAGMENT_COLOR_EXT 0x834C -#define GL_ATTENUATION_EXT 0x834D -#define GL_SHADOW_ATTENUATION_EXT 0x834E -#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F -#define GL_TEXTURE_LIGHT_EXT 0x8350 -#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 -#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 -/* reuse GL_FRAGMENT_DEPTH_EXT */ -#endif - -#ifndef GL_SGIX_blend_alpha_minmax -#define GL_ALPHA_MIN_SGIX 0x8320 -#define GL_ALPHA_MAX_SGIX 0x8321 -#endif - -#ifndef GL_EXT_bgra -#define GL_BGR_EXT 0x80E0 -#define GL_BGRA_EXT 0x80E1 -#endif - -#ifndef GL_INTEL_texture_scissor -#endif - -#ifndef GL_INTEL_parallel_arrays -#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 -#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 -#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 -#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 -#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 -#endif - -#ifndef GL_HP_occlusion_test -#define GL_OCCLUSION_TEST_HP 0x8165 -#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 -#endif - -#ifndef GL_EXT_pixel_transform -#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 -#define GL_PIXEL_MAG_FILTER_EXT 0x8331 -#define GL_PIXEL_MIN_FILTER_EXT 0x8332 -#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 -#define GL_CUBIC_EXT 0x8334 -#define GL_AVERAGE_EXT 0x8335 -#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 -#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 -#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 -#endif - -#ifndef GL_EXT_pixel_transform_color_table -#endif - -#ifndef GL_EXT_shared_texture_palette -#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB -#endif - -#ifndef GL_EXT_separate_specular_color -#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 -#define GL_SINGLE_COLOR_EXT 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA -#endif - -#ifndef GL_EXT_secondary_color -#define GL_COLOR_SUM_EXT 0x8458 -#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 -#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A -#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B -#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C -#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D -#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E -#endif - -#ifndef GL_EXT_texture_perturb_normal -#define GL_PERTURB_EXT 0x85AE -#define GL_TEXTURE_NORMAL_EXT 0x85AF -#endif - -#ifndef GL_EXT_multi_draw_arrays -#endif - -#ifndef GL_EXT_fog_coord -#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 -#define GL_FOG_COORDINATE_EXT 0x8451 -#define GL_FRAGMENT_DEPTH_EXT 0x8452 -#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 -#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 -#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 -#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 -#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 -#endif - -#ifndef GL_REND_screen_coordinates -#define GL_SCREEN_COORDINATES_REND 0x8490 -#define GL_INVERTED_SCREEN_W_REND 0x8491 -#endif - -#ifndef GL_EXT_coordinate_frame -#define GL_TANGENT_ARRAY_EXT 0x8439 -#define GL_BINORMAL_ARRAY_EXT 0x843A -#define GL_CURRENT_TANGENT_EXT 0x843B -#define GL_CURRENT_BINORMAL_EXT 0x843C -#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E -#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F -#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 -#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 -#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 -#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 -#define GL_MAP1_TANGENT_EXT 0x8444 -#define GL_MAP2_TANGENT_EXT 0x8445 -#define GL_MAP1_BINORMAL_EXT 0x8446 -#define GL_MAP2_BINORMAL_EXT 0x8447 -#endif - -#ifndef GL_EXT_texture_env_combine -#define GL_COMBINE_EXT 0x8570 -#define GL_COMBINE_RGB_EXT 0x8571 -#define GL_COMBINE_ALPHA_EXT 0x8572 -#define GL_RGB_SCALE_EXT 0x8573 -#define GL_ADD_SIGNED_EXT 0x8574 -#define GL_INTERPOLATE_EXT 0x8575 -#define GL_CONSTANT_EXT 0x8576 -#define GL_PRIMARY_COLOR_EXT 0x8577 -#define GL_PREVIOUS_EXT 0x8578 -#define GL_SOURCE0_RGB_EXT 0x8580 -#define GL_SOURCE1_RGB_EXT 0x8581 -#define GL_SOURCE2_RGB_EXT 0x8582 -#define GL_SOURCE3_RGB_EXT 0x8583 -#define GL_SOURCE4_RGB_EXT 0x8584 -#define GL_SOURCE5_RGB_EXT 0x8585 -#define GL_SOURCE6_RGB_EXT 0x8586 -#define GL_SOURCE7_RGB_EXT 0x8587 -#define GL_SOURCE0_ALPHA_EXT 0x8588 -#define GL_SOURCE1_ALPHA_EXT 0x8589 -#define GL_SOURCE2_ALPHA_EXT 0x858A -#define GL_SOURCE3_ALPHA_EXT 0x858B -#define GL_SOURCE4_ALPHA_EXT 0x858C -#define GL_SOURCE5_ALPHA_EXT 0x858D -#define GL_SOURCE6_ALPHA_EXT 0x858E -#define GL_SOURCE7_ALPHA_EXT 0x858F -#define GL_OPERAND0_RGB_EXT 0x8590 -#define GL_OPERAND1_RGB_EXT 0x8591 -#define GL_OPERAND2_RGB_EXT 0x8592 -#define GL_OPERAND3_RGB_EXT 0x8593 -#define GL_OPERAND4_RGB_EXT 0x8594 -#define GL_OPERAND5_RGB_EXT 0x8595 -#define GL_OPERAND6_RGB_EXT 0x8596 -#define GL_OPERAND7_RGB_EXT 0x8597 -#define GL_OPERAND0_ALPHA_EXT 0x8598 -#define GL_OPERAND1_ALPHA_EXT 0x8599 -#define GL_OPERAND2_ALPHA_EXT 0x859A -#define GL_OPERAND3_ALPHA_EXT 0x859B -#define GL_OPERAND4_ALPHA_EXT 0x859C -#define GL_OPERAND5_ALPHA_EXT 0x859D -#define GL_OPERAND6_ALPHA_EXT 0x859E -#define GL_OPERAND7_ALPHA_EXT 0x859F -#endif - -#ifndef GL_APPLE_specular_vector -#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 -#endif - -#ifndef GL_APPLE_transform_hint -#define GL_TRANSFORM_HINT_APPLE 0x85B1 -#endif - -#ifndef GL_SGIX_fog_scale -#define GL_FOG_SCALE_SGIX 0x81FC -#define GL_FOG_SCALE_VALUE_SGIX 0x81FD -#endif - -#ifndef GL_SUNX_constant_data -#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 -#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 -#endif - -#ifndef GL_SUN_global_alpha -#define GL_GLOBAL_ALPHA_SUN 0x81D9 -#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA -#endif - -#ifndef GL_SUN_triangle_list -#define GL_RESTART_SUN 0x01 -#define GL_REPLACE_MIDDLE_SUN 0x02 -#define GL_REPLACE_OLDEST_SUN 0x03 -#define GL_TRIANGLE_LIST_SUN 0x81D7 -#define GL_REPLACEMENT_CODE_SUN 0x81D8 -#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 -#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 -#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 -#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 -#define GL_R1UI_V3F_SUN 0x85C4 -#define GL_R1UI_C4UB_V3F_SUN 0x85C5 -#define GL_R1UI_C3F_V3F_SUN 0x85C6 -#define GL_R1UI_N3F_V3F_SUN 0x85C7 -#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 -#define GL_R1UI_T2F_V3F_SUN 0x85C9 -#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA -#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB -#endif - -#ifndef GL_SUN_vertex -#endif - -#ifndef GL_EXT_blend_func_separate -#define GL_BLEND_DST_RGB_EXT 0x80C8 -#define GL_BLEND_SRC_RGB_EXT 0x80C9 -#define GL_BLEND_DST_ALPHA_EXT 0x80CA -#define GL_BLEND_SRC_ALPHA_EXT 0x80CB -#endif - -#ifndef GL_INGR_color_clamp -#define GL_RED_MIN_CLAMP_INGR 0x8560 -#define GL_GREEN_MIN_CLAMP_INGR 0x8561 -#define GL_BLUE_MIN_CLAMP_INGR 0x8562 -#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 -#define GL_RED_MAX_CLAMP_INGR 0x8564 -#define GL_GREEN_MAX_CLAMP_INGR 0x8565 -#define GL_BLUE_MAX_CLAMP_INGR 0x8566 -#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 -#endif - -#ifndef GL_INGR_interlace_read -#define GL_INTERLACE_READ_INGR 0x8568 -#endif - -#ifndef GL_EXT_stencil_wrap -#define GL_INCR_WRAP_EXT 0x8507 -#define GL_DECR_WRAP_EXT 0x8508 -#endif - -#ifndef GL_EXT_422_pixels -#define GL_422_EXT 0x80CC -#define GL_422_REV_EXT 0x80CD -#define GL_422_AVERAGE_EXT 0x80CE -#define GL_422_REV_AVERAGE_EXT 0x80CF -#endif - -#ifndef GL_NV_texgen_reflection -#define GL_NORMAL_MAP_NV 0x8511 -#define GL_REFLECTION_MAP_NV 0x8512 -#endif - -#ifndef GL_EXT_texture_cube_map -#define GL_NORMAL_MAP_EXT 0x8511 -#define GL_REFLECTION_MAP_EXT 0x8512 -#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C -#endif - -#ifndef GL_SUN_convolution_border_modes -#define GL_WRAP_BORDER_SUN 0x81D4 -#endif - -#ifndef GL_EXT_texture_env_add -#endif - -#ifndef GL_EXT_texture_lod_bias -#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD -#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 -#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 -#endif - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -#endif - -#ifndef GL_EXT_vertex_weighting -#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH -#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 -#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX -#define GL_MODELVIEW_MATRIX1_EXT 0x8506 -#define GL_VERTEX_WEIGHTING_EXT 0x8509 -#define GL_MODELVIEW0_EXT GL_MODELVIEW -#define GL_MODELVIEW1_EXT 0x850A -#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B -#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C -#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D -#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E -#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F -#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 -#endif - -#ifndef GL_NV_light_max_exponent -#define GL_MAX_SHININESS_NV 0x8504 -#define GL_MAX_SPOT_EXPONENT_NV 0x8505 -#endif - -#ifndef GL_NV_vertex_array_range -#define GL_VERTEX_ARRAY_RANGE_NV 0x851D -#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E -#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F -#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 -#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 -#endif - -#ifndef GL_NV_vertex_array_range2 -#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 -#endif - -#ifndef GL_NV_register_combiners -#define GL_REGISTER_COMBINERS_NV 0x8522 -#define GL_VARIABLE_A_NV 0x8523 -#define GL_VARIABLE_B_NV 0x8524 -#define GL_VARIABLE_C_NV 0x8525 -#define GL_VARIABLE_D_NV 0x8526 -#define GL_VARIABLE_E_NV 0x8527 -#define GL_VARIABLE_F_NV 0x8528 -#define GL_VARIABLE_G_NV 0x8529 -#define GL_CONSTANT_COLOR0_NV 0x852A -#define GL_CONSTANT_COLOR1_NV 0x852B -#define GL_PRIMARY_COLOR_NV 0x852C -#define GL_SECONDARY_COLOR_NV 0x852D -#define GL_SPARE0_NV 0x852E -#define GL_SPARE1_NV 0x852F -#define GL_DISCARD_NV 0x8530 -#define GL_E_TIMES_F_NV 0x8531 -#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 -#define GL_UNSIGNED_IDENTITY_NV 0x8536 -#define GL_UNSIGNED_INVERT_NV 0x8537 -#define GL_EXPAND_NORMAL_NV 0x8538 -#define GL_EXPAND_NEGATE_NV 0x8539 -#define GL_HALF_BIAS_NORMAL_NV 0x853A -#define GL_HALF_BIAS_NEGATE_NV 0x853B -#define GL_SIGNED_IDENTITY_NV 0x853C -#define GL_SIGNED_NEGATE_NV 0x853D -#define GL_SCALE_BY_TWO_NV 0x853E -#define GL_SCALE_BY_FOUR_NV 0x853F -#define GL_SCALE_BY_ONE_HALF_NV 0x8540 -#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 -#define GL_COMBINER_INPUT_NV 0x8542 -#define GL_COMBINER_MAPPING_NV 0x8543 -#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 -#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 -#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 -#define GL_COMBINER_MUX_SUM_NV 0x8547 -#define GL_COMBINER_SCALE_NV 0x8548 -#define GL_COMBINER_BIAS_NV 0x8549 -#define GL_COMBINER_AB_OUTPUT_NV 0x854A -#define GL_COMBINER_CD_OUTPUT_NV 0x854B -#define GL_COMBINER_SUM_OUTPUT_NV 0x854C -#define GL_MAX_GENERAL_COMBINERS_NV 0x854D -#define GL_NUM_GENERAL_COMBINERS_NV 0x854E -#define GL_COLOR_SUM_CLAMP_NV 0x854F -#define GL_COMBINER0_NV 0x8550 -#define GL_COMBINER1_NV 0x8551 -#define GL_COMBINER2_NV 0x8552 -#define GL_COMBINER3_NV 0x8553 -#define GL_COMBINER4_NV 0x8554 -#define GL_COMBINER5_NV 0x8555 -#define GL_COMBINER6_NV 0x8556 -#define GL_COMBINER7_NV 0x8557 -/* reuse GL_TEXTURE0_ARB */ -/* reuse GL_TEXTURE1_ARB */ -/* reuse GL_ZERO */ -/* reuse GL_NONE */ -/* reuse GL_FOG */ -#endif - -#ifndef GL_NV_fog_distance -#define GL_FOG_DISTANCE_MODE_NV 0x855A -#define GL_EYE_RADIAL_NV 0x855B -#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C -/* reuse GL_EYE_PLANE */ -#endif - -#ifndef GL_NV_texgen_emboss -#define GL_EMBOSS_LIGHT_NV 0x855D -#define GL_EMBOSS_CONSTANT_NV 0x855E -#define GL_EMBOSS_MAP_NV 0x855F -#endif - -#ifndef GL_NV_blend_square -#endif - -#ifndef GL_NV_texture_env_combine4 -#define GL_COMBINE4_NV 0x8503 -#define GL_SOURCE3_RGB_NV 0x8583 -#define GL_SOURCE3_ALPHA_NV 0x858B -#define GL_OPERAND3_RGB_NV 0x8593 -#define GL_OPERAND3_ALPHA_NV 0x859B -#endif - - -#ifndef GL_MESA_resize_buffers -#endif - -#ifndef GL_MESA_window_pos -#endif - -#ifndef GL_EXT_texture_compression_s3tc -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#endif - -#ifndef GL_IBM_cull_vertex -#define GL_CULL_VERTEX_IBM 103050 -#endif - -#ifndef GL_IBM_multimode_draw_arrays -#endif - -#ifndef GL_IBM_vertex_array_lists -#define GL_VERTEX_ARRAY_LIST_IBM 103070 -#define GL_NORMAL_ARRAY_LIST_IBM 103071 -#define GL_COLOR_ARRAY_LIST_IBM 103072 -#define GL_INDEX_ARRAY_LIST_IBM 103073 -#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 -#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 -#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 -#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 -#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 -#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 -#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 -#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 -#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 -#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 -#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 -#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 -#endif - -#ifndef GL_SGIX_subsample -#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 -#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 -#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 -#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 -#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 -#endif - -#ifndef GL_SGIX_ycrcb_subsample -#endif - -#ifndef GL_SGIX_ycrcba -#define GL_YCRCB_SGIX 0x8318 -#define GL_YCRCBA_SGIX 0x8319 -#endif - -#ifndef GL_SGI_depth_pass_instrument -#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 -#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 -#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 -#endif - -#ifndef GL_3DFX_texture_compression_FXT1 -#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 -#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 -#endif - -#ifndef GL_3DFX_multisample -#define GL_MULTISAMPLE_3DFX 0x86B2 -#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 -#define GL_SAMPLES_3DFX 0x86B4 -#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 -#endif - -#ifndef GL_3DFX_tbuffer -#endif - -#ifndef GL_EXT_multisample -#define GL_MULTISAMPLE_EXT 0x809D -#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F -#define GL_SAMPLE_MASK_EXT 0x80A0 -#define GL_1PASS_EXT 0x80A1 -#define GL_2PASS_0_EXT 0x80A2 -#define GL_2PASS_1_EXT 0x80A3 -#define GL_4PASS_0_EXT 0x80A4 -#define GL_4PASS_1_EXT 0x80A5 -#define GL_4PASS_2_EXT 0x80A6 -#define GL_4PASS_3_EXT 0x80A7 -#define GL_SAMPLE_BUFFERS_EXT 0x80A8 -#define GL_SAMPLES_EXT 0x80A9 -#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA -#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB -#define GL_SAMPLE_PATTERN_EXT 0x80AC -#endif - -#ifndef GL_SGIX_vertex_preclip -#define GL_VERTEX_PRECLIP_SGIX 0x83EE -#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF -#endif - -#ifndef GL_SGIX_convolution_accuracy -#define GL_CONVOLUTION_HINT_SGIX 0x8316 -#endif - -#ifndef GL_SGIX_resample -#define GL_PACK_RESAMPLE_SGIX 0x842C -#define GL_UNPACK_RESAMPLE_SGIX 0x842D -#define GL_RESAMPLE_REPLICATE_SGIX 0x842E -#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F -#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 -#endif - -#ifndef GL_SGIS_point_line_texgen -#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 -#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 -#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 -#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 -#define GL_EYE_POINT_SGIS 0x81F4 -#define GL_OBJECT_POINT_SGIS 0x81F5 -#define GL_EYE_LINE_SGIS 0x81F6 -#define GL_OBJECT_LINE_SGIS 0x81F7 -#endif - -#ifndef GL_SGIS_texture_color_mask -#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF -#endif - - -/*************************************************************/ - -#ifndef GL_VERSION_1_2 -#define GL_VERSION_1_2 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf); -extern void APIENTRY glBlendEquation (GLenum); -extern void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); -extern void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *); -extern void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei); -extern void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *); -extern void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei); -extern void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat); -extern void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint); -extern void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *); -extern void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei); -extern void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); -extern void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *); -extern void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); -extern void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); -extern void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *); -extern void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *); -extern void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean); -extern void APIENTRY glMinmax (GLenum, GLenum, GLboolean); -extern void APIENTRY glResetHistogram (GLenum); -extern void APIENTRY glResetMinmax (GLenum); -extern void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -typedef void (APIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); -typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -typedef void (APIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); -typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); -typedef void (APIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -typedef void (APIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); -typedef void (APIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); -typedef void (APIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); -typedef void (APIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif - -#ifndef GL_ARB_multitexture -#define GL_ARB_multitexture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glActiveTextureARB (GLenum); -extern void APIENTRY glClientActiveTextureARB (GLenum); -extern void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble); -extern void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *); -extern void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat); -extern void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *); -extern void APIENTRY glMultiTexCoord1iARB (GLenum, GLint); -extern void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *); -extern void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort); -extern void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *); -extern void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble); -extern void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *); -extern void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat); -extern void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *); -extern void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint); -extern void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *); -extern void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort); -extern void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *); -extern void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble); -extern void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *); -extern void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *); -extern void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint); -extern void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *); -extern void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort); -extern void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *); -extern void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); -extern void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *); -extern void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *); -extern void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint); -extern void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *); -extern void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort); -extern void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); -typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); -typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); -typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); -#endif - -#ifndef GL_ARB_transpose_matrix -#define GL_ARB_transpose_matrix 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *); -extern void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *); -extern void APIENTRY glMultTransposeMatrixfARB (const GLfloat *); -extern void APIENTRY glMultTransposeMatrixdARB (const GLdouble *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); -typedef void (APIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); -typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); -typedef void (APIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); -#endif - -#ifndef GL_ARB_multisample -#define GL_ARB_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glSampleCoverageARB (GLclampf, GLboolean); -extern void APIENTRY glSamplePassARB (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); -typedef void (APIENTRY * PFNGLSAMPLEPASSARBPROC) (GLenum pass); -#endif - -#ifndef GL_ARB_texture_env_add -#define GL_ARB_texture_env_add 1 -#endif - -#ifndef GL_ARB_texture_cube_map -#define GL_ARB_texture_cube_map 1 -#endif - -#ifndef GL_ARB_texture_compression -#define GL_ARB_texture_compression 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); -extern void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); -extern void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); -extern void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); -extern void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); -extern void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); -extern void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, void *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img); -#endif - -#ifndef GL_EXT_abgr -#define GL_EXT_abgr 1 -#endif - -#ifndef GL_EXT_blend_color -#define GL_EXT_blend_color 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -#endif - -#ifndef GL_EXT_polygon_offset -#define GL_EXT_polygon_offset 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); -#endif - -#ifndef GL_EXT_texture -#define GL_EXT_texture 1 -#endif - -#ifndef GL_EXT_texture3D -#define GL_EXT_texture3D 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -#endif - -#ifndef GL_SGIS_texture_filter4 -#define GL_SGIS_texture_filter4 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *); -extern void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); -typedef void (APIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); -#endif - -#ifndef GL_EXT_subtexture -#define GL_EXT_subtexture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -#endif - -#ifndef GL_EXT_copy_texture -#define GL_EXT_copy_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); -extern void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); -extern void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei); -extern void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); -extern void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (APIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif - -#ifndef GL_EXT_histogram -#define GL_EXT_histogram 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *); -extern void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *); -extern void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean); -extern void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean); -extern void APIENTRY glResetHistogramEXT (GLenum); -extern void APIENTRY glResetMinmaxEXT (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -typedef void (APIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); -typedef void (APIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); -typedef void (APIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); -#endif - -#ifndef GL_EXT_convolution -#define GL_EXT_convolution 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat); -extern void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint); -extern void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *); -extern void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei); -extern void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); -extern void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *); -extern void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); -extern void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); -typedef void (APIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); -typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -typedef void (APIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); -#endif - -#ifndef GL_EXT_color_matrix -#define GL_EXT_color_matrix 1 -#endif - -#ifndef GL_SGI_color_table -#define GL_SGI_color_table 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *); -extern void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei); -extern void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); -#endif - -#ifndef GL_SGIX_pixel_texture -#define GL_SGIX_pixel_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glPixelTexGenSGIX (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); -#endif - -#ifndef GL_SGIS_pixel_texture -#define GL_SGIS_pixel_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint); -extern void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *); -extern void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat); -extern void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *); -extern void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *); -extern void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); -#endif - -#ifndef GL_SGIS_texture4D -#define GL_SGIS_texture4D 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); -#endif - -#ifndef GL_SGI_texture_color_table -#define GL_SGI_texture_color_table 1 -#endif - -#ifndef GL_EXT_cmyka -#define GL_EXT_cmyka 1 -#endif - -#ifndef GL_EXT_texture_object -#define GL_EXT_texture_object 1 -#ifdef GL_GLEXT_PROTOTYPES -extern GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *); -extern void APIENTRY glBindTextureEXT (GLenum, GLuint); -extern void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *); -extern void APIENTRY glGenTexturesEXT (GLsizei, GLuint *); -extern GLboolean APIENTRY glIsTextureEXT (GLuint); -extern void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLboolean (APIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); -typedef void (APIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); -typedef void (APIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); -typedef void (APIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); -typedef GLboolean (APIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); -typedef void (APIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); -#endif - -#ifndef GL_SGIS_detail_texture -#define GL_SGIS_detail_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *); -extern void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); -typedef void (APIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); -#endif - -#ifndef GL_SGIS_sharpen_texture -#define GL_SGIS_sharpen_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *); -extern void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); -typedef void (APIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); -#endif - -#ifndef GL_EXT_packed_pixels -#define GL_EXT_packed_pixels 1 -#endif - -#ifndef GL_SGIS_texture_lod -#define GL_SGIS_texture_lod 1 -#endif - -#ifndef GL_SGIS_multisample -#define GL_SGIS_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean); -extern void APIENTRY glSamplePatternSGIS (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); -typedef void (APIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); -#endif - -#ifndef GL_EXT_rescale_normal -#define GL_EXT_rescale_normal 1 -#endif - -#ifndef GL_EXT_vertex_array -#define GL_EXT_vertex_array 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glArrayElementEXT (GLint); -extern void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); -extern void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei); -extern void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *); -extern void APIENTRY glGetPointervEXT (GLenum, GLvoid* *); -extern void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); -extern void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); -extern void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); -extern void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); -typedef void (APIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); -typedef void (APIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); -typedef void (APIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); -typedef void (APIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -#endif - -#ifndef GL_EXT_misc_attribute -#define GL_EXT_misc_attribute 1 -#endif - -#ifndef GL_SGIS_generate_mipmap -#define GL_SGIS_generate_mipmap 1 -#endif - -#ifndef GL_SGIX_clipmap -#define GL_SGIX_clipmap 1 -#endif - -#ifndef GL_SGIX_shadow -#define GL_SGIX_shadow 1 -#endif - -#ifndef GL_SGIS_texture_edge_clamp -#define GL_SGIS_texture_edge_clamp 1 -#endif - -#ifndef GL_SGIS_texture_border_clamp -#define GL_SGIS_texture_border_clamp 1 -#endif - -#ifndef GL_EXT_blend_minmax -#define GL_EXT_blend_minmax 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glBlendEquationEXT (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); -#endif - -#ifndef GL_EXT_blend_subtract -#define GL_EXT_blend_subtract 1 -#endif - -#ifndef GL_EXT_blend_logic_op -#define GL_EXT_blend_logic_op 1 -#endif - -#ifndef GL_SGIX_interlace -#define GL_SGIX_interlace 1 -#endif - -#ifndef GL_SGIX_pixel_tiles -#define GL_SGIX_pixel_tiles 1 -#endif - -#ifndef GL_SGIX_texture_select -#define GL_SGIX_texture_select 1 -#endif - -#ifndef GL_SGIX_sprite -#define GL_SGIX_sprite 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat); -extern void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *); -extern void APIENTRY glSpriteParameteriSGIX (GLenum, GLint); -extern void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); -#endif - -#ifndef GL_SGIX_texture_multi_buffer -#define GL_SGIX_texture_multi_buffer 1 -#endif - -#ifndef GL_EXT_point_parameters -#define GL_EXT_point_parameters 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glPointParameterfEXT (GLenum, GLfloat); -extern void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); -extern void APIENTRY glPointParameterfSGIS (GLenum, GLfloat); -extern void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); -#endif - -#ifndef GL_SGIX_instruments -#define GL_SGIX_instruments 1 -#ifdef GL_GLEXT_PROTOTYPES -extern GLint APIENTRY glGetInstrumentsSGIX (void); -extern void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *); -extern GLint APIENTRY glPollInstrumentsSGIX (GLint *); -extern void APIENTRY glReadInstrumentsSGIX (GLint); -extern void APIENTRY glStartInstrumentsSGIX (void); -extern void APIENTRY glStopInstrumentsSGIX (GLint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLint (APIENTRY * PFNGLGETINSTRUMENTSSGIXPROC) (void); -typedef void (APIENTRY * PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); -typedef GLint (APIENTRY * PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); -typedef void (APIENTRY * PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); -typedef void (APIENTRY * PFNGLSTARTINSTRUMENTSSGIXPROC) (void); -typedef void (APIENTRY * PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); -#endif - -#ifndef GL_SGIX_texture_scale_bias -#define GL_SGIX_texture_scale_bias 1 -#endif - -#ifndef GL_SGIX_framezoom -#define GL_SGIX_framezoom 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFrameZoomSGIX (GLint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); -#endif - -#ifndef GL_SGIX_tag_sample_buffer -#define GL_SGIX_tag_sample_buffer 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTagSampleBufferSGIX (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); -#endif - -#ifndef GL_SGIX_reference_plane -#define GL_SGIX_reference_plane 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glReferencePlaneSGIX (const GLdouble *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); -#endif - -#ifndef GL_SGIX_flush_raster -#define GL_SGIX_flush_raster 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFlushRasterSGIX (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); -#endif - -#ifndef GL_SGIX_depth_texture -#define GL_SGIX_depth_texture 1 -#endif - -#ifndef GL_SGIS_fog_function -#define GL_SGIS_fog_function 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *); -extern void APIENTRY glGetFogFuncSGIS (const GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); -typedef void (APIENTRY * PFNGLGETFOGFUNCSGISPROC) (const GLfloat *points); -#endif - -#ifndef GL_SGIX_fog_offset -#define GL_SGIX_fog_offset 1 -#endif - -#ifndef GL_HP_image_transform -#define GL_HP_image_transform 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint); -extern void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat); -extern void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *); -extern void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *); -extern void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); -#endif - -#ifndef GL_HP_convolution_border_modes -#define GL_HP_convolution_border_modes 1 -#endif - -#ifndef GL_SGIX_texture_add_env -#define GL_SGIX_texture_add_env 1 -#endif - -#ifndef GL_EXT_color_subtable -#define GL_EXT_color_subtable 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -typedef void (APIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -#endif - -#ifndef GL_PGI_vertex_hints -#define GL_PGI_vertex_hints 1 -#endif - -#ifndef GL_PGI_misc_hints -#define GL_PGI_misc_hints 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glHintPGI (GLenum, GLint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLHINTPGIPROC) (GLenum target, GLint mode); -#endif - -#ifndef GL_EXT_paletted_texture -#define GL_EXT_paletted_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); -extern void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *); -extern void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *); -extern void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (APIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -#endif - -#ifndef GL_EXT_clip_volume_hint -#define GL_EXT_clip_volume_hint 1 -#endif - -#ifndef GL_SGIX_list_priority -#define GL_SGIX_list_priority 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *); -extern void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *); -extern void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat); -extern void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *); -extern void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint); -extern void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); -#endif - -#ifndef GL_SGIX_ir_instrument1 -#define GL_SGIX_ir_instrument1 1 -#endif - -#ifndef GL_SGIX_calligraphic_fragment -#define GL_SGIX_calligraphic_fragment 1 -#endif - -#ifndef GL_SGIX_texture_lod_bias -#define GL_SGIX_texture_lod_bias 1 -#endif - -#ifndef GL_SGIX_shadow_ambient -#define GL_SGIX_shadow_ambient 1 -#endif - -#ifndef GL_EXT_index_texture -#define GL_EXT_index_texture 1 -#endif - -#ifndef GL_EXT_index_material -#define GL_EXT_index_material 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glIndexMaterialEXT (GLenum, GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); -#endif - -#ifndef GL_EXT_index_func -#define GL_EXT_index_func 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glIndexFuncEXT (GLenum, GLclampf); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); -#endif - -#ifndef GL_EXT_index_array_formats -#define GL_EXT_index_array_formats 1 -#endif - -#ifndef GL_EXT_compiled_vertex_array -#define GL_EXT_compiled_vertex_array 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glLockArraysEXT (GLint, GLsizei); -extern void APIENTRY glUnlockArraysEXT (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); -typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); -#endif - -#ifndef GL_EXT_cull_vertex -#define GL_EXT_cull_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *); -extern void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); -typedef void (APIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); -#endif - -#ifndef GL_SGIX_ycrcb -#define GL_SGIX_ycrcb 1 -#endif - -#ifndef GL_SGIX_fragment_lighting -#define GL_SGIX_fragment_lighting 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum); -extern void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat); -extern void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint); -extern void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *); -extern void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat); -extern void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *); -extern void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint); -extern void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *); -extern void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat); -extern void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *); -extern void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint); -extern void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *); -extern void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *); -extern void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *); -extern void APIENTRY glLightEnviSGIX (GLenum, GLint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); -#endif - -#ifndef GL_IBM_rasterpos_clip -#define GL_IBM_rasterpos_clip 1 -#endif - -#ifndef GL_HP_texture_lighting -#define GL_HP_texture_lighting 1 -#endif - -#ifndef GL_EXT_draw_range_elements -#define GL_EXT_draw_range_elements 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -#endif - -#ifndef GL_WIN_phong_shading -#define GL_WIN_phong_shading 1 -#endif - -#ifndef GL_WIN_specular_fog -#define GL_WIN_specular_fog 1 -#endif - -#ifndef GL_EXT_light_texture -#define GL_EXT_light_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glApplyTextureEXT (GLenum); -extern void APIENTRY glTextureLightEXT (GLenum); -extern void APIENTRY glTextureMaterialEXT (GLenum, GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); -typedef void (APIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); -typedef void (APIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); -#endif - -#ifndef GL_SGIX_blend_alpha_minmax -#define GL_SGIX_blend_alpha_minmax 1 -#endif - -#ifndef GL_EXT_bgra -#define GL_EXT_bgra 1 -#endif - -#ifndef GL_INTEL_parallel_arrays -#define GL_INTEL_parallel_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *); -extern void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *); -extern void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *); -extern void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); -typedef void (APIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); -typedef void (APIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); -typedef void (APIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); -#endif - -#ifndef GL_HP_occlusion_test -#define GL_HP_occlusion_test 1 -#endif - -#ifndef GL_EXT_pixel_transform -#define GL_EXT_pixel_transform 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint); -extern void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat); -extern void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *); -extern void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); -#endif - -#ifndef GL_EXT_pixel_transform_color_table -#define GL_EXT_pixel_transform_color_table 1 -#endif - -#ifndef GL_EXT_shared_texture_palette -#define GL_EXT_shared_texture_palette 1 -#endif - -#ifndef GL_EXT_separate_specular_color -#define GL_EXT_separate_specular_color 1 -#endif - -#ifndef GL_EXT_secondary_color -#define GL_EXT_secondary_color 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte); -extern void APIENTRY glSecondaryColor3bvEXT (const GLbyte *); -extern void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble); -extern void APIENTRY glSecondaryColor3dvEXT (const GLdouble *); -extern void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat); -extern void APIENTRY glSecondaryColor3fvEXT (const GLfloat *); -extern void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint); -extern void APIENTRY glSecondaryColor3ivEXT (const GLint *); -extern void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort); -extern void APIENTRY glSecondaryColor3svEXT (const GLshort *); -extern void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte); -extern void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *); -extern void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint); -extern void APIENTRY glSecondaryColor3uivEXT (const GLuint *); -extern void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort); -extern void APIENTRY glSecondaryColor3usvEXT (const GLushort *); -extern void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); -typedef void (APIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); -typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); -#endif - -#ifndef GL_EXT_texture_perturb_normal -#define GL_EXT_texture_perturb_normal 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTextureNormalEXT (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); -#endif - -#ifndef GL_EXT_multi_draw_arrays -#define GL_EXT_multi_draw_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); -extern void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -typedef void (APIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -#endif - -#ifndef GL_EXT_fog_coord -#define GL_EXT_fog_coord 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFogCoordfEXT (GLfloat); -extern void APIENTRY glFogCoordfvEXT (const GLfloat *); -extern void APIENTRY glFogCoorddEXT (GLdouble); -extern void APIENTRY glFogCoorddvEXT (const GLdouble *); -extern void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); -typedef void (APIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); -typedef void (APIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); -typedef void (APIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); -typedef void (APIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_REND_screen_coordinates -#define GL_REND_screen_coordinates 1 -#endif - -#ifndef GL_EXT_coordinate_frame -#define GL_EXT_coordinate_frame 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte); -extern void APIENTRY glTangent3bvEXT (const GLbyte *); -extern void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble); -extern void APIENTRY glTangent3dvEXT (const GLdouble *); -extern void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTangent3fvEXT (const GLfloat *); -extern void APIENTRY glTangent3iEXT (GLint, GLint, GLint); -extern void APIENTRY glTangent3ivEXT (const GLint *); -extern void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort); -extern void APIENTRY glTangent3svEXT (const GLshort *); -extern void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte); -extern void APIENTRY glBinormal3bvEXT (const GLbyte *); -extern void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble); -extern void APIENTRY glBinormal3dvEXT (const GLdouble *); -extern void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat); -extern void APIENTRY glBinormal3fvEXT (const GLfloat *); -extern void APIENTRY glBinormal3iEXT (GLint, GLint, GLint); -extern void APIENTRY glBinormal3ivEXT (const GLint *); -extern void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort); -extern void APIENTRY glBinormal3svEXT (const GLshort *); -extern void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *); -extern void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); -typedef void (APIENTRY * PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); -typedef void (APIENTRY * PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); -typedef void (APIENTRY * PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); -typedef void (APIENTRY * PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); -typedef void (APIENTRY * PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); -typedef void (APIENTRY * PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); -typedef void (APIENTRY * PFNGLTANGENT3IVEXTPROC) (const GLint *v); -typedef void (APIENTRY * PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); -typedef void (APIENTRY * PFNGLTANGENT3SVEXTPROC) (const GLshort *v); -typedef void (APIENTRY * PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); -typedef void (APIENTRY * PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); -typedef void (APIENTRY * PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); -typedef void (APIENTRY * PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); -typedef void (APIENTRY * PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); -typedef void (APIENTRY * PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); -typedef void (APIENTRY * PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); -typedef void (APIENTRY * PFNGLBINORMAL3IVEXTPROC) (const GLint *v); -typedef void (APIENTRY * PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); -typedef void (APIENTRY * PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); -typedef void (APIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_EXT_texture_env_combine -#define GL_EXT_texture_env_combine 1 -#endif - -#ifndef GL_APPLE_specular_vector -#define GL_APPLE_specular_vector 1 -#endif - -#ifndef GL_APPLE_transform_hint -#define GL_APPLE_transform_hint 1 -#endif - -#ifndef GL_SGIX_fog_scale -#define GL_SGIX_fog_scale 1 -#endif - -#ifndef GL_SUNX_constant_data -#define GL_SUNX_constant_data 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFinishTextureSUNX (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); -#endif - -#ifndef GL_SUN_global_alpha -#define GL_SUN_global_alpha 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glGlobalAlphaFactorbSUN (GLbyte); -extern void APIENTRY glGlobalAlphaFactorsSUN (GLshort); -extern void APIENTRY glGlobalAlphaFactoriSUN (GLint); -extern void APIENTRY glGlobalAlphaFactorfSUN (GLfloat); -extern void APIENTRY glGlobalAlphaFactordSUN (GLdouble); -extern void APIENTRY glGlobalAlphaFactorubSUN (GLubyte); -extern void APIENTRY glGlobalAlphaFactorusSUN (GLushort); -extern void APIENTRY glGlobalAlphaFactoruiSUN (GLuint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); -typedef void (APIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); -#endif - -#ifndef GL_SUN_triangle_list -#define GL_SUN_triangle_list 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glReplacementCodeuiSUN (GLuint); -extern void APIENTRY glReplacementCodeusSUN (GLushort); -extern void APIENTRY glReplacementCodeubSUN (GLubyte); -extern void APIENTRY glReplacementCodeuivSUN (const GLuint *); -extern void APIENTRY glReplacementCodeusvSUN (const GLushort *); -extern void APIENTRY glReplacementCodeubvSUN (const GLubyte *); -extern void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); -#endif - -#ifndef GL_SUN_vertex -#define GL_SUN_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat); -extern void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *); -extern void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *); -extern void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *); -extern void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *); -extern void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *); -extern void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *); -extern void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *); -extern void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLenum *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLenum, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLenum *, const GLubyte *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *); -extern void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLenum, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLenum *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); -typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLenum rc, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLenum rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLenum *rc, const GLubyte *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLenum rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *c, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLenum rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLenum *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -#endif - -#ifndef GL_EXT_blend_func_separate -#define GL_EXT_blend_func_separate 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -#endif - -#ifndef GL_INGR_color_clamp -#define GL_INGR_color_clamp 1 -#endif - -#ifndef GL_INGR_interlace_read -#define GL_INGR_interlace_read 1 -#endif - -#ifndef GL_EXT_stencil_wrap -#define GL_EXT_stencil_wrap 1 -#endif - -#ifndef GL_EXT_422_pixels -#define GL_EXT_422_pixels 1 -#endif - -#ifndef GL_NV_texgen_reflection -#define GL_NV_texgen_reflection 1 -#endif - -#ifndef GL_SUN_convolution_border_modes -#define GL_SUN_convolution_border_modes 1 -#endif - -#ifndef GL_EXT_texture_env_add -#define GL_EXT_texture_env_add 1 -#endif - -#ifndef GL_EXT_texture_lod_bias -#define GL_EXT_texture_lod_bias 1 -#endif - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_EXT_texture_filter_anisotropic 1 -#endif - -#ifndef GL_EXT_vertex_weighting -#define GL_EXT_vertex_weighting 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glVertexWeightfEXT (GLfloat); -extern void APIENTRY glVertexWeightfvEXT (const GLfloat *); -extern void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); -typedef void (APIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); -typedef void (APIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_NV_light_max_exponent -#define GL_NV_light_max_exponent 1 -#endif - -#ifndef GL_NV_vertex_array_range -#define GL_NV_vertex_array_range 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glFlushVertexArrayRangeNV (void); -extern void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); -typedef void (APIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei size, const GLvoid *pointer); -#endif - -#ifndef GL_NV_vertex_array_range2 -#define GL_NV_vertex_array_range2 1 -#endif - -#ifndef GL_NV_register_combiners -#define GL_NV_register_combiners 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *); -extern void APIENTRY glCombinerParameterfNV (GLenum, GLfloat); -extern void APIENTRY glCombinerParameterivNV (GLenum, const GLint *); -extern void APIENTRY glCombinerParameteriNV (GLenum, GLint); -extern void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); -extern void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); -extern void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum); -extern void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *); -extern void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *); -extern void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *); -extern void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); -typedef void (APIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -typedef void (APIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); -typedef void (APIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); -#endif - -#ifndef GL_NV_fog_distance -#define GL_NV_fog_distance 1 -#endif - -#ifndef GL_NV_texgen_emboss -#define GL_NV_texgen_emboss 1 -#endif - -#ifndef GL_NV_blend_square -#define GL_NV_blend_square 1 -#endif - -#ifndef GL_NV_texture_env_combine4 -#define GL_NV_texture_env_combine4 1 -#endif - -#ifndef GL_MESA_resize_buffers -#define GL_MESA_resize_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glResizeBuffersMESA (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); -#endif - -#ifndef GL_MESA_window_pos -#define GL_MESA_window_pos 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble); -extern void APIENTRY glWindowPos2dvMESA (const GLdouble *); -extern void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat); -extern void APIENTRY glWindowPos2fvMESA (const GLfloat *); -extern void APIENTRY glWindowPos2iMESA (GLint, GLint); -extern void APIENTRY glWindowPos2ivMESA (const GLint *); -extern void APIENTRY glWindowPos2sMESA (GLshort, GLshort); -extern void APIENTRY glWindowPos2svMESA (const GLshort *); -extern void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble); -extern void APIENTRY glWindowPos3dvMESA (const GLdouble *); -extern void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat); -extern void APIENTRY glWindowPos3fvMESA (const GLfloat *); -extern void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint); -extern void APIENTRY glWindowPos3ivMESA (const GLint *); -extern void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort); -extern void APIENTRY glWindowPos3svMESA (const GLshort *); -extern void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble); -extern void APIENTRY glWindowPos4dvMESA (const GLdouble *); -extern void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat); -extern void APIENTRY glWindowPos4fvMESA (const GLfloat *); -extern void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint); -extern void APIENTRY glWindowPos4ivMESA (const GLint *); -extern void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort); -extern void APIENTRY glWindowPos4svMESA (const GLshort *); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); -typedef void (APIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); -typedef void (APIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); -typedef void (APIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); -typedef void (APIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); -typedef void (APIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); -typedef void (APIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); -typedef void (APIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); -typedef void (APIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); -typedef void (APIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); -typedef void (APIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); -typedef void (APIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); -typedef void (APIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); -typedef void (APIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); -typedef void (APIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); -typedef void (APIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); -typedef void (APIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); -typedef void (APIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); -#endif - -#ifndef GL_IBM_cull_vertex -#define GL_IBM_cull_vertex 1 -#endif - -#ifndef GL_IBM_multimode_draw_arrays -#define GL_IBM_multimode_draw_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glMultiModeDrawArraysIBM (GLenum, const GLint *, const GLsizei *, GLsizei, GLint); -extern void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* *, GLsizei, GLint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); -typedef void (APIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, GLint modestride); -#endif - -#ifndef GL_IBM_vertex_array_lists -#define GL_IBM_vertex_array_lists 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); -extern void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); -extern void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint); -extern void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); -extern void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); -extern void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); -extern void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); -extern void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -#endif - -#ifndef GL_SGIX_subsample -#define GL_SGIX_subsample 1 -#endif - -#ifndef GL_SGIX_ycrcba -#define GL_SGIX_ycrcba 1 -#endif - -#ifndef GL_SGIX_ycrcb_subsample -#define GL_SGIX_ycrcb_subsample 1 -#endif - -#ifndef GL_SGIX_depth_pass_instrument -#define GL_SGIX_depth_pass_instrument 1 -#endif - -#ifndef GL_3DFX_texture_compression_FXT1 -#define GL_3DFX_texture_compression_FXT1 1 -#endif - -#ifndef GL_3DFX_multisample -#define GL_3DFX_multisample 1 -#endif - -#ifndef GL_3DFX_tbuffer -#define GL_3DFX_tbuffer 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTbufferMask3DFX (GLuint); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); -#endif - -#ifndef GL_EXT_multisample -#define GL_EXT_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glSampleMaskEXT (GLclampf, GLboolean); -extern void APIENTRY glSamplePatternEXT (GLenum); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); -typedef void (APIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); -#endif - -#ifndef GL_SGI_vertex_preclip -#define GL_SGI_vertex_preclip 1 -#endif - -#ifndef GL_SGIX_convolution_accuracy -#define GL_SGIX_convolution_accuracy 1 -#endif - -#ifndef GL_SGIX_resample -#define GL_SGIX_resample 1 -#endif - -#ifndef GL_SGIS_point_line_texgen -#define GL_SGIS_point_line_texgen 1 -#endif - -#ifndef GL_SGIS_texture_color_mask -#define GL_SGIS_texture_color_mask 1 -#ifdef GL_GLEXT_PROTOTYPES -extern void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRY * PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -#endif - - - -/* added by Cass -- this part will be auto-generated in the future*/ - -#ifndef GL_EXT_texture_compression_s3tc -#define GL_EXT_texture_compression_s3tc 1 -#endif - -/* Extensions */ -#define GL_ARB_texture_border_clamp 1 -#define GL_ARB_texture_env_combine 1 -#define GL_ARB_texture_env_dot3 1 -#define GL_EXT_texture_env_dot3 1 -#define GL_IBM_texture_mirrored_repeat 1 -#define GL_NV_evaluators 1 -#define GL_NV_fence 1 -#define GL_NV_multisample_filter_hint 1 -#define GL_NV_packed_depth_stencil 1 -#define GL_NV_register_combiners2 1 -#define GL_NV_texture_compression_vtc 1 -#define GL_NV_texture_rectangle 1 -#define GL_NV_texture_shader 1 -#define GL_NV_texture_shader2 1 -#define GL_NV_vertex_program 1 -#define GL_NV_point_sprite 1 -#define GL_NV_occlusion_query 1 - -/* ARB_texture_border_clamp */ -#define GL_CLAMP_TO_BORDER_ARB 0x812D - -/* ARB_texture_env_combine */ -#define GL_COMBINE_ARB 0x8570 -#define GL_COMBINE_RGB_ARB 0x8571 -#define GL_COMBINE_ALPHA_ARB 0x8572 -#define GL_RGB_SCALE_ARB 0x8573 -#define GL_ADD_SIGNED_ARB 0x8574 -#define GL_INTERPOLATE_ARB 0x8575 -#define GL_CONSTANT_ARB 0x8576 -#define GL_PRIMARY_COLOR_ARB 0x8577 -#define GL_PREVIOUS_ARB 0x8578 -#define GL_SOURCE0_RGB_ARB 0x8580 -#define GL_SOURCE1_RGB_ARB 0x8581 -#define GL_SOURCE2_RGB_ARB 0x8582 -#define GL_SOURCE0_ALPHA_ARB 0x8588 -#define GL_SOURCE1_ALPHA_ARB 0x8589 -#define GL_SOURCE2_ALPHA_ARB 0x858A -#define GL_OPERAND0_RGB_ARB 0x8590 -#define GL_OPERAND1_RGB_ARB 0x8591 -#define GL_OPERAND2_RGB_ARB 0x8592 -#define GL_OPERAND0_ALPHA_ARB 0x8598 -#define GL_OPERAND1_ALPHA_ARB 0x8599 -#define GL_OPERAND2_ALPHA_ARB 0x859A -#define GL_SUBTRACT_ARB 0x84E7 - -/* ARB_texture_env_dot3 */ -#define GL_DOT3_RGB_ARB 0x86AE -#define GL_DOT3_RGBA_ARB 0x86AF - -/* EXT_texture_env_dot3 */ -#define GL_DOT3_RGB_EXT 0x8740 -#define GL_DOT3_RGBA_EXT 0x8741 - -/* IBM_texture_mirrored_repeat */ -#define GL_MIRRORED_REPEAT_IBM 0x8370 - -/* NV_vertex_program */ -#define GL_VERTEX_PROGRAM_NV 0x8620 -#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 -#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 -#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 -#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 -#define GL_CURRENT_ATTRIB_NV 0x8626 -#define GL_PROGRAM_LENGTH_NV 0x8627 -#define GL_PROGRAM_STRING_NV 0x8628 -#define GL_MODELVIEW_PROJECTION_NV 0x8629 -#define GL_IDENTITY_NV 0x862A -#define GL_INVERSE_NV 0x862B -#define GL_TRANSPOSE_NV 0x862C -#define GL_INVERSE_TRANSPOSE_NV 0x862D -#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E -#define GL_MAX_TRACK_MATRICES_NV 0x862F -#define GL_MATRIX0_NV 0x8630 -#define GL_MATRIX1_NV 0x8631 -#define GL_MATRIX2_NV 0x8632 -#define GL_MATRIX3_NV 0x8633 -#define GL_MATRIX4_NV 0x8634 -#define GL_MATRIX5_NV 0x8635 -#define GL_MATRIX6_NV 0x8636 -#define GL_MATRIX7_NV 0x8637 -#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 -#define GL_CURRENT_MATRIX_NV 0x8641 -#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 -#define GL_PROGRAM_PARAMETER_NV 0x8644 -#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 -#define GL_PROGRAM_TARGET_NV 0x8646 -#define GL_PROGRAM_RESIDENT_NV 0x8647 -#define GL_TRACK_MATRIX_NV 0x8648 -#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 -#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A -#define GL_PROGRAM_ERROR_POSITION_NV 0x864B -#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 -#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 -#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 -#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 -#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 -#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 -#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 -#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 -#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 -#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 -#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A -#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B -#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C -#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D -#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E -#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F -#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 -#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 -#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 -#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 -#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 -#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 -#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 -#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 -#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 -#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 -#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A -#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B -#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C -#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D -#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E -#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F -#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 -#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 -#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 -#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 -#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 -#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 -#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 -#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 -#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 -#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 -#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A -#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B -#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C -#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D -#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E -#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F - -/* NV_evaluators */ -#define GL_EVAL_2D_NV 0x86C0 -#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 -#define GL_MAP_TESSELLATION_NV 0x86C2 -#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 -#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 -#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 -#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 -#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 -#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 -#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 -#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA -#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB -#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC -#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD -#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE -#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF -#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 -#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 -#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 -#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 -#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 -#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 -#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 -#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 - -/* NV_fence */ -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 - -/* NV_occlusion_query */ -#define GL_PIXEL_COUNTER_BITS_NV 0x8864 -#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 -#define GL_PIXEL_COUNT_NV 0x8866 -#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 - -/* NV_point_sprite */ -#define GL_POINT_SPRITE_NV 0x8861 -#define GL_COORD_REPLACE_NV 0x8862 -#define GL_POINT_SPRITE_R_MODE_NV 0x8863 - -/* NV_texture_rectangle */ -#define GL_TEXTURE_RECTANGLE_NV 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 - -/* NV_texture_shader */ -#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C -#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D -#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E -#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 -#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA -#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB -#define GL_DSDT_MAG_INTENSITY_NV 0x86DC -#define GL_SHADER_CONSISTENT_NV 0x86DD -#define GL_TEXTURE_SHADER_NV 0x86DE -#define GL_SHADER_OPERATION_NV 0x86DF -#define GL_CULL_MODES_NV 0x86E0 -#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 -#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 -#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 -#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV -#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV -#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV -#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 -#define GL_CONST_EYE_NV 0x86E5 -#define GL_PASS_THROUGH_NV 0x86E6 -#define GL_CULL_FRAGMENT_NV 0x86E7 -#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 -#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 -#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA -#define GL_ISOTROPIC_BRDF_NV 0x86EB -#define GL_DOT_PRODUCT_NV 0x86EC -#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED -#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE -#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF -#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 -#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 -#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 -#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 -#define GL_HILO_NV 0x86F4 -#define GL_DSDT_NV 0x86F5 -#define GL_DSDT_MAG_NV 0x86F6 -#define GL_DSDT_MAG_VIB_NV 0x86F7 -#define GL_HILO16_NV 0x86F8 -#define GL_SIGNED_HILO_NV 0x86F9 -#define GL_SIGNED_HILO16_NV 0x86FA -#define GL_SIGNED_RGBA_NV 0x86FB -#define GL_SIGNED_RGBA8_NV 0x86FC -#define GL_SIGNED_RGB_NV 0x86FE -#define GL_SIGNED_RGB8_NV 0x86FF -#define GL_SIGNED_LUMINANCE_NV 0x8701 -#define GL_SIGNED_LUMINANCE8_NV 0x8702 -#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 -#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 -#define GL_SIGNED_ALPHA_NV 0x8705 -#define GL_SIGNED_ALPHA8_NV 0x8706 -#define GL_SIGNED_INTENSITY_NV 0x8707 -#define GL_SIGNED_INTENSITY8_NV 0x8708 -#define GL_DSDT8_NV 0x8709 -#define GL_DSDT8_MAG8_NV 0x870A -#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B -#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C -#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D -#define GL_HI_SCALE_NV 0x870E -#define GL_LO_SCALE_NV 0x870F -#define GL_DS_SCALE_NV 0x8710 -#define GL_DT_SCALE_NV 0x8711 -#define GL_MAGNITUDE_SCALE_NV 0x8712 -#define GL_VIBRANCE_SCALE_NV 0x8713 -#define GL_HI_BIAS_NV 0x8714 -#define GL_LO_BIAS_NV 0x8715 -#define GL_DS_BIAS_NV 0x8716 -#define GL_DT_BIAS_NV 0x8717 -#define GL_MAGNITUDE_BIAS_NV 0x8718 -#define GL_VIBRANCE_BIAS_NV 0x8719 -#define GL_TEXTURE_BORDER_VALUES_NV 0x871A -#define GL_TEXTURE_HI_SIZE_NV 0x871B -#define GL_TEXTURE_LO_SIZE_NV 0x871C -#define GL_TEXTURE_DS_SIZE_NV 0x871D -#define GL_TEXTURE_DT_SIZE_NV 0x871E -#define GL_TEXTURE_MAG_SIZE_NV 0x871F - -/* NV_texture_shader2 */ -#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF - -/* NV_register_combiners2 */ -#define GL_PER_STAGE_CONSTANTS_NV 0x8535 - -/* NV_packed_depth_stencil */ -#define GL_DEPTH_STENCIL_NV 0x84F9 -#define GL_UNSIGNED_INT_24_8_NV 0x84FA - -/* NV_multisample_filter_hint */ -#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 - -/* NV_texture_compression_vtc */ - -/* NV_vertex_program */ -typedef GLboolean (APIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); -typedef void (APIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); -typedef void (APIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); -typedef void (APIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); -typedef void (APIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); -typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); -typedef void (APIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); -typedef GLboolean (APIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); -typedef void (APIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); -typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); -typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); -typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); -typedef void (APIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); -typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); -typedef void (APIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); -typedef void (APIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); -typedef void (APIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (APIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (APIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); -typedef void (APIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (APIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); - -/* NV_evaluators */ -typedef void (APIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); -typedef void (APIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); -typedef void (APIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); - -/* NV_fence */ -typedef void (APIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); -typedef void (APIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); -typedef GLboolean (APIENTRY * PFNGLISFENCENVPROC) (GLuint fence); -typedef GLboolean (APIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); -typedef void (APIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); -typedef void (APIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); - -/* NV_occlusion_query */ -typedef void (APIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); -typedef void (APIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); -typedef void (APIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); -typedef void (APIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); -typedef void (APIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (GLvoid); -typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (APIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); - -/* NV_point_sprite */ -typedef void (APIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, int param); -typedef void (APIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const int *params); - -/* NV_register_combiners2 */ -typedef void (APIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); -typedef void (APIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Code/Physics/Bullet Source/Glut/GL/glut.h b/Code/Physics/Bullet Source/Glut/GL/glut.h deleted file mode 100644 index 612f3327..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/glut.h +++ /dev/null @@ -1,607 +0,0 @@ -#ifndef __glut_h__ -#define __glut_h__ - -/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ - -/* This program is freely distributable without licensing fees and is - provided without guarantee or warrantee expressed or implied. This - program is -not- in the public domain. */ - -#if defined(_WIN32) - -/* GLUT 3.7 now tries to avoid including - to avoid name space pollution, but Win32's - needs APIENTRY and WINGDIAPI defined properly. */ -# if 0 -# define WIN32_LEAN_AND_MEAN -# include -# else - /* XXX This is from Win32's */ -# ifndef APIENTRY -# define GLUT_APIENTRY_DEFINED -# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) -# define APIENTRY __stdcall -# else -# define APIENTRY -# endif -# endif - /* XXX This is from Win32's */ -# ifndef CALLBACK -# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) -# define CALLBACK __stdcall -# else -# define CALLBACK -# endif -# endif - /* XXX This is from Win32's and */ -# ifndef WINGDIAPI -# define GLUT_WINGDIAPI_DEFINED -# define WINGDIAPI __declspec(dllimport) -# endif - /* XXX This is from Win32's */ -# ifndef _WCHAR_T_DEFINED -/* MinGW32 chokes on the next line */ -#ifndef __MINGW32__ -typedef unsigned short int wchar_t; -#endif //__MINGW32__ -# define _WCHAR_T_DEFINED -# endif -# endif - -#pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ -#pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ -#pragma comment (lib, "glu32.lib") /* link with OpenGL Utility lib */ - -#ifdef _WIN64 -#pragma message("Note: including lib: glut64.lib\n") -#pragma comment (lib, "glut64.lib") /* link with Win32 GLUT lib */ -#else -#pragma message("Note: including lib: glut32.lib\n") -#pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ -#endif - -#pragma warning (disable:4244) /* Disable bogus conversion warnings. */ -#pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ - -#endif - -#include -#include - -/* define APIENTRY and CALLBACK to null string if we aren't on Win32 */ -#if !defined(_WIN32) -#define APIENTRY -#define GLUT_APIENTRY_DEFINED -#define CALLBACK -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - GLUT API revision history: - - GLUT_API_VERSION is updated to reflect incompatible GLUT - API changes (interface changes, semantic changes, deletions, - or additions). - - GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 - - GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, - extension. Supports new input devices like tablet, dial and button - box, and Spaceball. Easy to query OpenGL extensions. - - GLUT_API_VERSION=3 glutMenuStatus added. - - GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, - glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic - video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, - glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, - glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). -**/ -#ifndef GLUT_API_VERSION /* allow this to be overriden */ -//#define GLUT_API_VERSION 3 -#define GLUT_API_VERSION 4 -#endif - -/** - GLUT implementation revision history: - - GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT - API revisions and implementation revisions (ie, bug fixes). - - GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of - GLUT Xlib-based implementation. 11/29/94 - - GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of - GLUT Xlib-based implementation providing GLUT version 2 - interfaces. - - GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 - - GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 - - GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 - - GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 - - GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner - and video resize. 1/3/97 - - GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. - - GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. - - GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. - - GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 release with GameGLUT support. -**/ -#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ -#define GLUT_XLIB_IMPLEMENTATION 13 -#endif - -/* Display mode bit masks. */ -#define GLUT_RGB 0 -#define GLUT_RGBA GLUT_RGB -#define GLUT_INDEX 1 -#define GLUT_SINGLE 0 -#define GLUT_DOUBLE 2 -#define GLUT_ACCUM 4 -#define GLUT_ALPHA 8 -#define GLUT_DEPTH 16 -#define GLUT_STENCIL 32 -#if (GLUT_API_VERSION >= 2) -#define GLUT_MULTISAMPLE 128 -#define GLUT_STEREO 256 -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_LUMINANCE 512 -#endif - -/* Mouse buttons. */ -#define GLUT_LEFT_BUTTON 0 -#define GLUT_MIDDLE_BUTTON 1 -#define GLUT_RIGHT_BUTTON 2 - -/* Mouse button state. */ -#define GLUT_DOWN 0 -#define GLUT_UP 1 - -#if (GLUT_API_VERSION >= 2) -/* function keys */ -#define GLUT_KEY_F1 1 -#define GLUT_KEY_F2 2 -#define GLUT_KEY_F3 3 -#define GLUT_KEY_F4 4 -#define GLUT_KEY_F5 5 -#define GLUT_KEY_F6 6 -#define GLUT_KEY_F7 7 -#define GLUT_KEY_F8 8 -#define GLUT_KEY_F9 9 -#define GLUT_KEY_F10 10 -#define GLUT_KEY_F11 11 -#define GLUT_KEY_F12 12 -/* directional keys */ -#define GLUT_KEY_LEFT 100 -#define GLUT_KEY_UP 101 -#define GLUT_KEY_RIGHT 102 -#define GLUT_KEY_DOWN 103 -#define GLUT_KEY_PAGE_UP 104 -#define GLUT_KEY_PAGE_DOWN 105 -#define GLUT_KEY_HOME 106 -#define GLUT_KEY_END 107 -#define GLUT_KEY_INSERT 108 -#endif - -/* Entry/exit state. */ -#define GLUT_LEFT 0 -#define GLUT_ENTERED 1 - -/* Menu usage state. */ -#define GLUT_MENU_NOT_IN_USE 0 -#define GLUT_MENU_IN_USE 1 - -/* Visibility state. */ -#define GLUT_NOT_VISIBLE 0 -#define GLUT_VISIBLE 1 - -/* Window status state. */ -#define GLUT_HIDDEN 0 -#define GLUT_FULLY_RETAINED 1 -#define GLUT_PARTIALLY_RETAINED 2 -#define GLUT_FULLY_COVERED 3 - -/* Color index component selection values. */ -#define GLUT_RED 0 -#define GLUT_GREEN 1 -#define GLUT_BLUE 2 - -/* Layers for use. */ -#define GLUT_NORMAL 0 -#define GLUT_OVERLAY 1 - -#if defined(_WIN32) -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN ((void*)0) -#define GLUT_STROKE_MONO_ROMAN ((void*)1) - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 ((void*)2) -#define GLUT_BITMAP_8_BY_13 ((void*)3) -#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) -#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 ((void*)6) -#define GLUT_BITMAP_HELVETICA_12 ((void*)7) -#define GLUT_BITMAP_HELVETICA_18 ((void*)8) -#endif -#else -/* Stroke font opaque addresses (use constants instead in source code). */ -extern void *glutStrokeRoman; -extern void *glutStrokeMonoRoman; - -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN (&glutStrokeRoman) -#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) - -/* Bitmap font opaque addresses (use constants instead in source code). */ -extern void *glutBitmap9By15; -extern void *glutBitmap8By13; -extern void *glutBitmapTimesRoman10; -extern void *glutBitmapTimesRoman24; -extern void *glutBitmapHelvetica10; -extern void *glutBitmapHelvetica12; -extern void *glutBitmapHelvetica18; - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) -#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) -#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) -#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) -#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) -#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) -#endif -#endif - -/* glutGet parameters. */ -#define GLUT_WINDOW_X 100 -#define GLUT_WINDOW_Y 101 -#define GLUT_WINDOW_WIDTH 102 -#define GLUT_WINDOW_HEIGHT 103 -#define GLUT_WINDOW_BUFFER_SIZE 104 -#define GLUT_WINDOW_STENCIL_SIZE 105 -#define GLUT_WINDOW_DEPTH_SIZE 106 -#define GLUT_WINDOW_RED_SIZE 107 -#define GLUT_WINDOW_GREEN_SIZE 108 -#define GLUT_WINDOW_BLUE_SIZE 109 -#define GLUT_WINDOW_ALPHA_SIZE 110 -#define GLUT_WINDOW_ACCUM_RED_SIZE 111 -#define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 -#define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 -#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 -#define GLUT_WINDOW_DOUBLEBUFFER 115 -#define GLUT_WINDOW_RGBA 116 -#define GLUT_WINDOW_PARENT 117 -#define GLUT_WINDOW_NUM_CHILDREN 118 -#define GLUT_WINDOW_COLORMAP_SIZE 119 -#if (GLUT_API_VERSION >= 2) -#define GLUT_WINDOW_NUM_SAMPLES 120 -#define GLUT_WINDOW_STEREO 121 -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_WINDOW_CURSOR 122 -#endif -#define GLUT_SCREEN_WIDTH 200 -#define GLUT_SCREEN_HEIGHT 201 -#define GLUT_SCREEN_WIDTH_MM 202 -#define GLUT_SCREEN_HEIGHT_MM 203 -#define GLUT_MENU_NUM_ITEMS 300 -#define GLUT_DISPLAY_MODE_POSSIBLE 400 -#define GLUT_INIT_WINDOW_X 500 -#define GLUT_INIT_WINDOW_Y 501 -#define GLUT_INIT_WINDOW_WIDTH 502 -#define GLUT_INIT_WINDOW_HEIGHT 503 -#define GLUT_INIT_DISPLAY_MODE 504 -#if (GLUT_API_VERSION >= 2) -#define GLUT_ELAPSED_TIME 700 -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_WINDOW_FORMAT_ID 123 -#endif - -#if (GLUT_API_VERSION >= 2) -/* glutDeviceGet parameters. */ -#define GLUT_HAS_KEYBOARD 600 -#define GLUT_HAS_MOUSE 601 -#define GLUT_HAS_SPACEBALL 602 -#define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 -#define GLUT_HAS_TABLET 604 -#define GLUT_NUM_MOUSE_BUTTONS 605 -#define GLUT_NUM_SPACEBALL_BUTTONS 606 -#define GLUT_NUM_BUTTON_BOX_BUTTONS 607 -#define GLUT_NUM_DIALS 608 -#define GLUT_NUM_TABLET_BUTTONS 609 -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_DEVICE_IGNORE_KEY_REPEAT 610 -#define GLUT_DEVICE_KEY_REPEAT 611 -#define GLUT_HAS_JOYSTICK 612 -#define GLUT_OWNS_JOYSTICK 613 -#define GLUT_JOYSTICK_BUTTONS 614 -#define GLUT_JOYSTICK_AXES 615 -#define GLUT_JOYSTICK_POLL_RATE 616 -#endif - -#if (GLUT_API_VERSION >= 3) -/* glutLayerGet parameters. */ -#define GLUT_OVERLAY_POSSIBLE 800 -#define GLUT_LAYER_IN_USE 801 -#define GLUT_HAS_OVERLAY 802 -#define GLUT_TRANSPARENT_INDEX 803 -#define GLUT_NORMAL_DAMAGED 804 -#define GLUT_OVERLAY_DAMAGED 805 - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* glutVideoResizeGet parameters. */ -#define GLUT_VIDEO_RESIZE_POSSIBLE 900 -#define GLUT_VIDEO_RESIZE_IN_USE 901 -#define GLUT_VIDEO_RESIZE_X_DELTA 902 -#define GLUT_VIDEO_RESIZE_Y_DELTA 903 -#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 -#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 -#define GLUT_VIDEO_RESIZE_X 906 -#define GLUT_VIDEO_RESIZE_Y 907 -#define GLUT_VIDEO_RESIZE_WIDTH 908 -#define GLUT_VIDEO_RESIZE_HEIGHT 909 -#endif - -/* glutUseLayer parameters. */ -#define GLUT_NORMAL 0 -#define GLUT_OVERLAY 1 - -/* glutGetModifiers return mask. */ -#define GLUT_ACTIVE_SHIFT 1 -#define GLUT_ACTIVE_CTRL 2 -#define GLUT_ACTIVE_ALT 4 - -/* glutSetCursor parameters. */ -/* Basic arrows. */ -#define GLUT_CURSOR_RIGHT_ARROW 0 -#define GLUT_CURSOR_LEFT_ARROW 1 -/* Symbolic cursor shapes. */ -#define GLUT_CURSOR_INFO 2 -#define GLUT_CURSOR_DESTROY 3 -#define GLUT_CURSOR_HELP 4 -#define GLUT_CURSOR_CYCLE 5 -#define GLUT_CURSOR_SPRAY 6 -#define GLUT_CURSOR_WAIT 7 -#define GLUT_CURSOR_TEXT 8 -#define GLUT_CURSOR_CROSSHAIR 9 -/* Directional cursors. */ -#define GLUT_CURSOR_UP_DOWN 10 -#define GLUT_CURSOR_LEFT_RIGHT 11 -/* Sizing cursors. */ -#define GLUT_CURSOR_TOP_SIDE 12 -#define GLUT_CURSOR_BOTTOM_SIDE 13 -#define GLUT_CURSOR_LEFT_SIDE 14 -#define GLUT_CURSOR_RIGHT_SIDE 15 -#define GLUT_CURSOR_TOP_LEFT_CORNER 16 -#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 -#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 -#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 -/* Inherit from parent window. */ -#define GLUT_CURSOR_INHERIT 100 -/* Blank cursor. */ -#define GLUT_CURSOR_NONE 101 -/* Fullscreen crosshair (if available). */ -#define GLUT_CURSOR_FULL_CROSSHAIR 102 -#endif - -/* GLUT initialization sub-API. */ -extern void APIENTRY glutInit(int *argcp, char **argv); -extern void APIENTRY glutInitDisplayMode(unsigned int mode); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -extern void APIENTRY glutInitDisplayString(const char *string); -#endif -extern void APIENTRY glutInitWindowPosition(int x, int y); -extern void APIENTRY glutInitWindowSize(int width, int height); -extern void APIENTRY glutMainLoop(void); - -/* GLUT window sub-API. */ -extern int APIENTRY glutCreateWindow(const char *title); -extern int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); -extern void APIENTRY glutDestroyWindow(int win); -extern void APIENTRY glutPostRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -extern void APIENTRY glutPostWindowRedisplay(int win); -#endif -extern void APIENTRY glutSwapBuffers(void); -extern int APIENTRY glutGetWindow(void); -extern void APIENTRY glutSetWindow(int win); -extern void APIENTRY glutSetWindowTitle(const char *title); -extern void APIENTRY glutSetIconTitle(const char *title); -extern void APIENTRY glutPositionWindow(int x, int y); -extern void APIENTRY glutReshapeWindow(int width, int height); -extern void APIENTRY glutPopWindow(void); -extern void APIENTRY glutPushWindow(void); -extern void APIENTRY glutIconifyWindow(void); -extern void APIENTRY glutShowWindow(void); -extern void APIENTRY glutHideWindow(void); -#if (GLUT_API_VERSION >= 3) -extern void APIENTRY glutFullScreen(void); -extern void APIENTRY glutSetCursor(int cursor); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -extern void APIENTRY glutWarpPointer(int x, int y); -#endif - -/* GLUT overlay sub-API. */ -extern void APIENTRY glutEstablishOverlay(void); -extern void APIENTRY glutRemoveOverlay(void); -extern void APIENTRY glutUseLayer(GLenum layer); -extern void APIENTRY glutPostOverlayRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -extern void APIENTRY glutPostWindowOverlayRedisplay(int win); -#endif -extern void APIENTRY glutShowOverlay(void); -extern void APIENTRY glutHideOverlay(void); -#endif - -/* GLUT menu sub-API. */ -extern int APIENTRY glutCreateMenu(void (*)(int)); -extern void APIENTRY glutDestroyMenu(int menu); -extern int APIENTRY glutGetMenu(void); -extern void APIENTRY glutSetMenu(int menu); -extern void APIENTRY glutAddMenuEntry(const char *label, int value); -extern void APIENTRY glutAddSubMenu(const char *label, int submenu); -extern void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); -extern void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); -extern void APIENTRY glutRemoveMenuItem(int item); -extern void APIENTRY glutAttachMenu(int button); -extern void APIENTRY glutDetachMenu(int button); - -/* GLUT window callback sub-API. */ -extern void APIENTRY glutDisplayFunc(void (*func)(void)); -extern void APIENTRY glutReshapeFunc(void (*func)(int width, int height)); -extern void APIENTRY glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)); -extern void APIENTRY glutMouseFunc(void (*func)(int button, int state, int x, int y)); -extern void APIENTRY glutMotionFunc(void (*func)(int x, int y)); -extern void APIENTRY glutPassiveMotionFunc(void (*func)(int x, int y)); -extern void APIENTRY glutEntryFunc(void (*func)(int state)); -extern void APIENTRY glutVisibilityFunc(void (*func)(int state)); -extern void APIENTRY glutIdleFunc(void (*func)(void)); -extern void APIENTRY glutTimerFunc(unsigned int millis, void (*func)(int value), int value); -extern void APIENTRY glutMenuStateFunc(void (*func)(int state)); -#if (GLUT_API_VERSION >= 2) -extern void APIENTRY glutSpecialFunc(void (*func)(int key, int x, int y)); -extern void APIENTRY glutSpaceballMotionFunc(void (*func)(int x, int y, int z)); -extern void APIENTRY glutSpaceballRotateFunc(void (*func)(int x, int y, int z)); -extern void APIENTRY glutSpaceballButtonFunc(void (*func)(int button, int state)); -extern void APIENTRY glutButtonBoxFunc(void (*func)(int button, int state)); -extern void APIENTRY glutDialsFunc(void (*func)(int dial, int value)); -extern void APIENTRY glutTabletMotionFunc(void (*func)(int x, int y)); -extern void APIENTRY glutTabletButtonFunc(void (*func)(int button, int state, int x, int y)); -#if (GLUT_API_VERSION >= 3) -extern void APIENTRY glutMenuStatusFunc(void (*func)(int status, int x, int y)); -extern void APIENTRY glutOverlayDisplayFunc(void (*func)(void)); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -extern void APIENTRY glutWindowStatusFunc(void (*func)(int state)); -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -extern void APIENTRY glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y)); -extern void APIENTRY glutSpecialUpFunc(void (*func)(int key, int x, int y)); -extern void APIENTRY glutJoystickFunc(void (*func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); -#endif -#endif -#endif - -/* GLUT color index sub-API. */ -extern void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); -extern GLfloat APIENTRY glutGetColor(int ndx, int component); -extern void APIENTRY glutCopyColormap(int win); - -/* GLUT state retrieval sub-API. */ -extern int APIENTRY glutGet(GLenum type); -extern int APIENTRY glutDeviceGet(GLenum type); -#if (GLUT_API_VERSION >= 2) -/* GLUT extension support sub-API */ -extern int APIENTRY glutExtensionSupported(const char *name); -#endif -#if (GLUT_API_VERSION >= 3) -extern int APIENTRY glutGetModifiers(void); -extern int APIENTRY glutLayerGet(GLenum type); -#endif - -/* GLUT font sub-API */ -extern void APIENTRY glutBitmapCharacter(void *font, int character); -extern int APIENTRY glutBitmapWidth(void *font, int character); -extern void APIENTRY glutStrokeCharacter(void *font, int character); -extern int APIENTRY glutStrokeWidth(void *font, int character); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -extern int APIENTRY glutBitmapLength(void *font, const unsigned char *string); -extern int APIENTRY glutStrokeLength(void *font, const unsigned char *string); -#endif - -/* GLUT pre-built models sub-API */ -extern void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); -extern void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); -extern void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -extern void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -extern void APIENTRY glutWireCube(GLdouble size); -extern void APIENTRY glutSolidCube(GLdouble size); -extern void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -extern void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -extern void APIENTRY glutWireDodecahedron(void); -extern void APIENTRY glutSolidDodecahedron(void); -extern void APIENTRY glutWireTeapot(GLdouble size); -extern void APIENTRY glutSolidTeapot(GLdouble size); -extern void APIENTRY glutWireOctahedron(void); -extern void APIENTRY glutSolidOctahedron(void); -extern void APIENTRY glutWireTetrahedron(void); -extern void APIENTRY glutSolidTetrahedron(void); -extern void APIENTRY glutWireIcosahedron(void); -extern void APIENTRY glutSolidIcosahedron(void); - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* GLUT video resize sub-API. */ -extern int APIENTRY glutVideoResizeGet(GLenum param); -extern void APIENTRY glutSetupVideoResizing(void); -extern void APIENTRY glutStopVideoResizing(void); -extern void APIENTRY glutVideoResize(int x, int y, int width, int height); -extern void APIENTRY glutVideoPan(int x, int y, int width, int height); - -/* GLUT debugging sub-API. */ -extern void APIENTRY glutReportErrors(void); -#endif - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -/* GLUT device control sub-API. */ -/* glutSetKeyRepeat modes. */ -#define GLUT_KEY_REPEAT_OFF 0 -#define GLUT_KEY_REPEAT_ON 1 -#define GLUT_KEY_REPEAT_DEFAULT 2 - -/* Joystick button masks. */ -#define GLUT_JOYSTICK_BUTTON_A 1 -#define GLUT_JOYSTICK_BUTTON_B 2 -#define GLUT_JOYSTICK_BUTTON_C 4 -#define GLUT_JOYSTICK_BUTTON_D 8 - -extern void APIENTRY glutIgnoreKeyRepeat(int ignore); -extern void APIENTRY glutSetKeyRepeat(int repeatMode); -extern void APIENTRY glutForceJoystickFunc(void); - -/* GLUT game mode sub-API. */ -/* glutGameModeGet. */ -#define GLUT_GAME_MODE_ACTIVE 0 -#define GLUT_GAME_MODE_POSSIBLE 1 -#define GLUT_GAME_MODE_WIDTH 2 -#define GLUT_GAME_MODE_HEIGHT 3 -#define GLUT_GAME_MODE_PIXEL_DEPTH 4 -#define GLUT_GAME_MODE_REFRESH_RATE 5 -#define GLUT_GAME_MODE_DISPLAY_CHANGED 6 - -extern void APIENTRY glutGameModeString(const char *string); -extern int APIENTRY glutEnterGameMode(void); -extern void APIENTRY glutLeaveGameMode(void); -extern int APIENTRY glutGameModeGet(GLenum mode); -#endif - -#ifdef __cplusplus -} - -#endif - -#ifdef GLUT_APIENTRY_DEFINED -# undef GLUT_APIENTRY_DEFINED -# undef APIENTRY -#endif - -#ifdef GLUT_WINGDIAPI_DEFINED -# undef GLUT_WINGDIAPI_DEFINED -# undef WINGDIAPI -#endif - -#endif /* __glut_h__ */ diff --git a/Code/Physics/Bullet Source/Glut/GL/glxew.h b/Code/Physics/Bullet Source/Glut/GL/glxew.h deleted file mode 100644 index 6d249f73..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/glxew.h +++ /dev/null @@ -1,1587 +0,0 @@ -/* -** The OpenGL Extension Wrangler Library -** Copyright (C) 2002-2008, Milan Ikits -** Copyright (C) 2002-2008, Marcelo E. Magallon -** Copyright (C) 2002, Lev Povalahev -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** * The name of the author may be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -** THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* - * Mesa 3-D graphics library - * Version: 7.0 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* -** Copyright (c) 2007 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -#ifndef __glxew_h__ -#define __glxew_h__ -#define __GLXEW_H__ - -#ifdef __glxext_h_ -#error glxext.h included before glxew.h -#endif - -#if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__) -#error glx.h included before glxew.h -#endif - -#define __glxext_h_ - -#define GLX_H -#define __GLX_glx_h__ -#define __glx_h__ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ---------------------------- GLX_VERSION_1_0 --------------------------- */ - -#ifndef GLX_VERSION_1_0 -#define GLX_VERSION_1_0 1 - -#define GLX_USE_GL 1 -#define GLX_BUFFER_SIZE 2 -#define GLX_LEVEL 3 -#define GLX_RGBA 4 -#define GLX_DOUBLEBUFFER 5 -#define GLX_STEREO 6 -#define GLX_AUX_BUFFERS 7 -#define GLX_RED_SIZE 8 -#define GLX_GREEN_SIZE 9 -#define GLX_BLUE_SIZE 10 -#define GLX_ALPHA_SIZE 11 -#define GLX_DEPTH_SIZE 12 -#define GLX_STENCIL_SIZE 13 -#define GLX_ACCUM_RED_SIZE 14 -#define GLX_ACCUM_GREEN_SIZE 15 -#define GLX_ACCUM_BLUE_SIZE 16 -#define GLX_ACCUM_ALPHA_SIZE 17 -#define GLX_BAD_SCREEN 1 -#define GLX_BAD_ATTRIBUTE 2 -#define GLX_NO_EXTENSION 3 -#define GLX_BAD_VISUAL 4 -#define GLX_BAD_CONTEXT 5 -#define GLX_BAD_VALUE 6 -#define GLX_BAD_ENUM 7 - -typedef XID GLXDrawable; -typedef XID GLXPixmap; -#ifdef __sun -typedef struct __glXContextRec *GLXContext; -#else -typedef struct __GLXcontextRec *GLXContext; -#endif - -typedef unsigned int GLXVideoDeviceNV; - -extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase); -extern Bool glXQueryVersion (Display *dpy, int *major, int *minor); -extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value); -extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList); -extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap); -extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix); -extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); -extern void glXDestroyContext (Display *dpy, GLXContext ctx); -extern Bool glXIsDirect (Display *dpy, GLXContext ctx); -extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask); -extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx); -extern GLXContext glXGetCurrentContext (void); -extern GLXDrawable glXGetCurrentDrawable (void); -extern void glXWaitGL (void); -extern void glXWaitX (void); -extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable); -extern void glXUseXFont (Font font, int first, int count, int listBase); - -#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0) - -#endif /* GLX_VERSION_1_0 */ - -/* ---------------------------- GLX_VERSION_1_1 --------------------------- */ - -#ifndef GLX_VERSION_1_1 -#define GLX_VERSION_1_1 - -#define GLX_VENDOR 0x1 -#define GLX_VERSION 0x2 -#define GLX_EXTENSIONS 0x3 - -extern const char* glXQueryExtensionsString (Display *dpy, int screen); -extern const char* glXGetClientString (Display *dpy, int name); -extern const char* glXQueryServerString (Display *dpy, int screen, int name); - -#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1) - -#endif /* GLX_VERSION_1_1 */ - -/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */ - -#ifndef GLX_VERSION_1_2 -#define GLX_VERSION_1_2 1 - -typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void); - -#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay) - -#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2) - -#endif /* GLX_VERSION_1_2 */ - -/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */ - -#ifndef GLX_VERSION_1_3 -#define GLX_VERSION_1_3 1 - -#define GLX_RGBA_BIT 0x00000001 -#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 -#define GLX_WINDOW_BIT 0x00000001 -#define GLX_COLOR_INDEX_BIT 0x00000002 -#define GLX_PIXMAP_BIT 0x00000002 -#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 -#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 -#define GLX_PBUFFER_BIT 0x00000004 -#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 -#define GLX_AUX_BUFFERS_BIT 0x00000010 -#define GLX_CONFIG_CAVEAT 0x20 -#define GLX_DEPTH_BUFFER_BIT 0x00000020 -#define GLX_X_VISUAL_TYPE 0x22 -#define GLX_TRANSPARENT_TYPE 0x23 -#define GLX_TRANSPARENT_INDEX_VALUE 0x24 -#define GLX_TRANSPARENT_RED_VALUE 0x25 -#define GLX_TRANSPARENT_GREEN_VALUE 0x26 -#define GLX_TRANSPARENT_BLUE_VALUE 0x27 -#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 -#define GLX_STENCIL_BUFFER_BIT 0x00000040 -#define GLX_ACCUM_BUFFER_BIT 0x00000080 -#define GLX_NONE 0x8000 -#define GLX_SLOW_CONFIG 0x8001 -#define GLX_TRUE_COLOR 0x8002 -#define GLX_DIRECT_COLOR 0x8003 -#define GLX_PSEUDO_COLOR 0x8004 -#define GLX_STATIC_COLOR 0x8005 -#define GLX_GRAY_SCALE 0x8006 -#define GLX_STATIC_GRAY 0x8007 -#define GLX_TRANSPARENT_RGB 0x8008 -#define GLX_TRANSPARENT_INDEX 0x8009 -#define GLX_VISUAL_ID 0x800B -#define GLX_SCREEN 0x800C -#define GLX_NON_CONFORMANT_CONFIG 0x800D -#define GLX_DRAWABLE_TYPE 0x8010 -#define GLX_RENDER_TYPE 0x8011 -#define GLX_X_RENDERABLE 0x8012 -#define GLX_FBCONFIG_ID 0x8013 -#define GLX_RGBA_TYPE 0x8014 -#define GLX_COLOR_INDEX_TYPE 0x8015 -#define GLX_MAX_PBUFFER_WIDTH 0x8016 -#define GLX_MAX_PBUFFER_HEIGHT 0x8017 -#define GLX_MAX_PBUFFER_PIXELS 0x8018 -#define GLX_PRESERVED_CONTENTS 0x801B -#define GLX_LARGEST_PBUFFER 0x801C -#define GLX_WIDTH 0x801D -#define GLX_HEIGHT 0x801E -#define GLX_EVENT_MASK 0x801F -#define GLX_DAMAGED 0x8020 -#define GLX_SAVED 0x8021 -#define GLX_WINDOW 0x8022 -#define GLX_PBUFFER 0x8023 -#define GLX_PBUFFER_HEIGHT 0x8040 -#define GLX_PBUFFER_WIDTH 0x8041 -#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 -#define GLX_DONT_CARE 0xFFFFFFFF - -typedef XID GLXFBConfigID; -typedef XID GLXPbuffer; -typedef XID GLXWindow; -typedef struct __GLXFBConfigRec *GLXFBConfig; - -typedef struct { - int event_type; - int draw_type; - unsigned long serial; - Bool send_event; - Display *display; - GLXDrawable drawable; - unsigned int buffer_mask; - unsigned int aux_buffer; - int x, y; - int width, height; - int count; -} GLXPbufferClobberEvent; -typedef union __GLXEvent { - GLXPbufferClobberEvent glxpbufferclobber; - long pad[24]; -} GLXEvent; - -typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); -typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); -typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); -typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); -typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); -typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); -typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); -typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); -typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); -typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); -typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); -typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); -typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); -typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); -typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); -typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); -typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); - -#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig) -#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext) -#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer) -#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap) -#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow) -#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer) -#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap) -#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow) -#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable) -#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib) -#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs) -#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent) -#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig) -#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent) -#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext) -#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable) -#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent) - -#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3) - -#endif /* GLX_VERSION_1_3 */ - -/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */ - -#ifndef GLX_VERSION_1_4 -#define GLX_VERSION_1_4 1 - -#define GLX_SAMPLE_BUFFERS 100000 -#define GLX_SAMPLES 100001 - -extern void ( * glXGetProcAddress (const GLubyte *procName)) (void); - -#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4) - -#endif /* GLX_VERSION_1_4 */ - -/* -------------------------- GLX_3DFX_multisample ------------------------- */ - -#ifndef GLX_3DFX_multisample -#define GLX_3DFX_multisample 1 - -#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 -#define GLX_SAMPLES_3DFX 0x8051 - -#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample) - -#endif /* GLX_3DFX_multisample */ - -/* ------------------------ GLX_AMD_gpu_association ------------------------ */ - -#ifndef GLX_AMD_gpu_association -#define GLX_AMD_gpu_association 1 - -#define GLX_GPU_VENDOR_AMD 0x1F00 -#define GLX_GPU_RENDERER_STRING_AMD 0x1F01 -#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 -#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 -#define GLX_GPU_RAM_AMD 0x21A3 -#define GLX_GPU_CLOCK_AMD 0x21A4 -#define GLX_GPU_NUM_PIPES_AMD 0x21A5 -#define GLX_GPU_NUM_SIMD_AMD 0x21A6 -#define GLX_GPU_NUM_RB_AMD 0x21A7 -#define GLX_GPU_NUM_SPI_AMD 0x21A8 - -#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association) - -#endif /* GLX_AMD_gpu_association */ - -/* ------------------------- GLX_ARB_create_context ------------------------ */ - -#ifndef GLX_ARB_create_context -#define GLX_ARB_create_context 1 - -#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define GLX_CONTEXT_FLAGS_ARB 0x2094 - -typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); - -#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB) - -#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context) - -#endif /* GLX_ARB_create_context */ - -/* --------------------- GLX_ARB_create_context_profile -------------------- */ - -#ifndef GLX_ARB_create_context_profile -#define GLX_ARB_create_context_profile 1 - -#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 - -#define GLXEW_ARB_create_context_profile GLXEW_GET_VAR(__GLXEW_ARB_create_context_profile) - -#endif /* GLX_ARB_create_context_profile */ - -/* ------------------- GLX_ARB_create_context_robustness ------------------- */ - -#ifndef GLX_ARB_create_context_robustness -#define GLX_ARB_create_context_robustness 1 - -#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 -#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 -#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 - -#define GLXEW_ARB_create_context_robustness GLXEW_GET_VAR(__GLXEW_ARB_create_context_robustness) - -#endif /* GLX_ARB_create_context_robustness */ - -/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */ - -#ifndef GLX_ARB_fbconfig_float -#define GLX_ARB_fbconfig_float 1 - -#define GLX_RGBA_FLOAT_BIT 0x00000004 -#define GLX_RGBA_FLOAT_TYPE 0x20B9 - -#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float) - -#endif /* GLX_ARB_fbconfig_float */ - -/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */ - -#ifndef GLX_ARB_framebuffer_sRGB -#define GLX_ARB_framebuffer_sRGB 1 - -#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 - -#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB) - -#endif /* GLX_ARB_framebuffer_sRGB */ - -/* ------------------------ GLX_ARB_get_proc_address ----------------------- */ - -#ifndef GLX_ARB_get_proc_address -#define GLX_ARB_get_proc_address 1 - -extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void); - -#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address) - -#endif /* GLX_ARB_get_proc_address */ - -/* -------------------------- GLX_ARB_multisample -------------------------- */ - -#ifndef GLX_ARB_multisample -#define GLX_ARB_multisample 1 - -#define GLX_SAMPLE_BUFFERS_ARB 100000 -#define GLX_SAMPLES_ARB 100001 - -#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample) - -#endif /* GLX_ARB_multisample */ - -/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */ - -#ifndef GLX_ARB_vertex_buffer_object -#define GLX_ARB_vertex_buffer_object 1 - -#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095 - -#define GLXEW_ARB_vertex_buffer_object GLXEW_GET_VAR(__GLXEW_ARB_vertex_buffer_object) - -#endif /* GLX_ARB_vertex_buffer_object */ - -/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */ - -#ifndef GLX_ATI_pixel_format_float -#define GLX_ATI_pixel_format_float 1 - -#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100 - -#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float) - -#endif /* GLX_ATI_pixel_format_float */ - -/* ------------------------- GLX_ATI_render_texture ------------------------ */ - -#ifndef GLX_ATI_render_texture -#define GLX_ATI_render_texture 1 - -#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800 -#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801 -#define GLX_TEXTURE_FORMAT_ATI 0x9802 -#define GLX_TEXTURE_TARGET_ATI 0x9803 -#define GLX_MIPMAP_TEXTURE_ATI 0x9804 -#define GLX_TEXTURE_RGB_ATI 0x9805 -#define GLX_TEXTURE_RGBA_ATI 0x9806 -#define GLX_NO_TEXTURE_ATI 0x9807 -#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808 -#define GLX_TEXTURE_1D_ATI 0x9809 -#define GLX_TEXTURE_2D_ATI 0x980A -#define GLX_MIPMAP_LEVEL_ATI 0x980B -#define GLX_CUBE_MAP_FACE_ATI 0x980C -#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D -#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E -#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F -#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810 -#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811 -#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812 -#define GLX_FRONT_LEFT_ATI 0x9813 -#define GLX_FRONT_RIGHT_ATI 0x9814 -#define GLX_BACK_LEFT_ATI 0x9815 -#define GLX_BACK_RIGHT_ATI 0x9816 -#define GLX_AUX0_ATI 0x9817 -#define GLX_AUX1_ATI 0x9818 -#define GLX_AUX2_ATI 0x9819 -#define GLX_AUX3_ATI 0x981A -#define GLX_AUX4_ATI 0x981B -#define GLX_AUX5_ATI 0x981C -#define GLX_AUX6_ATI 0x981D -#define GLX_AUX7_ATI 0x981E -#define GLX_AUX8_ATI 0x981F -#define GLX_AUX9_ATI 0x9820 -#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821 -#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822 - -typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); -typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list); -typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); - -#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI) -#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI) -#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI) - -#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture) - -#endif /* GLX_ATI_render_texture */ - -/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */ - -#ifndef GLX_EXT_create_context_es2_profile -#define GLX_EXT_create_context_es2_profile 1 - -#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 - -#define GLXEW_EXT_create_context_es2_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es2_profile) - -#endif /* GLX_EXT_create_context_es2_profile */ - -/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */ - -#ifndef GLX_EXT_fbconfig_packed_float -#define GLX_EXT_fbconfig_packed_float 1 - -#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 -#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 - -#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float) - -#endif /* GLX_EXT_fbconfig_packed_float */ - -/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */ - -#ifndef GLX_EXT_framebuffer_sRGB -#define GLX_EXT_framebuffer_sRGB 1 - -#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 - -#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB) - -#endif /* GLX_EXT_framebuffer_sRGB */ - -/* ------------------------- GLX_EXT_import_context ------------------------ */ - -#ifndef GLX_EXT_import_context -#define GLX_EXT_import_context 1 - -#define GLX_SHARE_CONTEXT_EXT 0x800A -#define GLX_VISUAL_ID_EXT 0x800B -#define GLX_SCREEN_EXT 0x800C - -typedef XID GLXContextID; - -typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context); -typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); -typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID); -typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value); - -#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT) -#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT) -#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT) -#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT) - -#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context) - -#endif /* GLX_EXT_import_context */ - -/* -------------------------- GLX_EXT_scene_marker ------------------------- */ - -#ifndef GLX_EXT_scene_marker -#define GLX_EXT_scene_marker 1 - -#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker) - -#endif /* GLX_EXT_scene_marker */ - -/* -------------------------- GLX_EXT_swap_control ------------------------- */ - -#ifndef GLX_EXT_swap_control -#define GLX_EXT_swap_control 1 - -#define GLX_SWAP_INTERVAL_EXT 0x20F1 -#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 - -typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval); - -#define glXSwapIntervalEXT GLXEW_GET_FUN(__glewXSwapIntervalEXT) - -#define GLXEW_EXT_swap_control GLXEW_GET_VAR(__GLXEW_EXT_swap_control) - -#endif /* GLX_EXT_swap_control */ - -/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */ - -#ifndef GLX_EXT_texture_from_pixmap -#define GLX_EXT_texture_from_pixmap 1 - -#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 -#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 -#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 -#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 -#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 -#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 -#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 -#define GLX_Y_INVERTED_EXT 0x20D4 -#define GLX_TEXTURE_FORMAT_EXT 0x20D5 -#define GLX_TEXTURE_TARGET_EXT 0x20D6 -#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 -#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 -#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 -#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA -#define GLX_TEXTURE_1D_EXT 0x20DB -#define GLX_TEXTURE_2D_EXT 0x20DC -#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD -#define GLX_FRONT_LEFT_EXT 0x20DE -#define GLX_FRONT_RIGHT_EXT 0x20DF -#define GLX_BACK_LEFT_EXT 0x20E0 -#define GLX_BACK_RIGHT_EXT 0x20E1 -#define GLX_AUX0_EXT 0x20E2 -#define GLX_AUX1_EXT 0x20E3 -#define GLX_AUX2_EXT 0x20E4 -#define GLX_AUX3_EXT 0x20E5 -#define GLX_AUX4_EXT 0x20E6 -#define GLX_AUX5_EXT 0x20E7 -#define GLX_AUX6_EXT 0x20E8 -#define GLX_AUX7_EXT 0x20E9 -#define GLX_AUX8_EXT 0x20EA -#define GLX_AUX9_EXT 0x20EB - -typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list); -typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer); - -#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT) -#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT) - -#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap) - -#endif /* GLX_EXT_texture_from_pixmap */ - -/* -------------------------- GLX_EXT_visual_info -------------------------- */ - -#ifndef GLX_EXT_visual_info -#define GLX_EXT_visual_info 1 - -#define GLX_X_VISUAL_TYPE_EXT 0x22 -#define GLX_TRANSPARENT_TYPE_EXT 0x23 -#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 -#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 -#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 -#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 -#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 -#define GLX_NONE_EXT 0x8000 -#define GLX_TRUE_COLOR_EXT 0x8002 -#define GLX_DIRECT_COLOR_EXT 0x8003 -#define GLX_PSEUDO_COLOR_EXT 0x8004 -#define GLX_STATIC_COLOR_EXT 0x8005 -#define GLX_GRAY_SCALE_EXT 0x8006 -#define GLX_STATIC_GRAY_EXT 0x8007 -#define GLX_TRANSPARENT_RGB_EXT 0x8008 -#define GLX_TRANSPARENT_INDEX_EXT 0x8009 - -#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info) - -#endif /* GLX_EXT_visual_info */ - -/* ------------------------- GLX_EXT_visual_rating ------------------------- */ - -#ifndef GLX_EXT_visual_rating -#define GLX_EXT_visual_rating 1 - -#define GLX_VISUAL_CAVEAT_EXT 0x20 -#define GLX_SLOW_VISUAL_EXT 0x8001 -#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D - -#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating) - -#endif /* GLX_EXT_visual_rating */ - -/* -------------------------- GLX_INTEL_swap_event ------------------------- */ - -#ifndef GLX_INTEL_swap_event -#define GLX_INTEL_swap_event 1 - -#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180 -#define GLX_COPY_COMPLETE_INTEL 0x8181 -#define GLX_FLIP_COMPLETE_INTEL 0x8182 -#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000 - -#define GLXEW_INTEL_swap_event GLXEW_GET_VAR(__GLXEW_INTEL_swap_event) - -#endif /* GLX_INTEL_swap_event */ - -/* -------------------------- GLX_MESA_agp_offset -------------------------- */ - -#ifndef GLX_MESA_agp_offset -#define GLX_MESA_agp_offset 1 - -typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer); - -#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA) - -#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset) - -#endif /* GLX_MESA_agp_offset */ - -/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */ - -#ifndef GLX_MESA_copy_sub_buffer -#define GLX_MESA_copy_sub_buffer 1 - -typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height); - -#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA) - -#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer) - -#endif /* GLX_MESA_copy_sub_buffer */ - -/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */ - -#ifndef GLX_MESA_pixmap_colormap -#define GLX_MESA_pixmap_colormap 1 - -typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); - -#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA) - -#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap) - -#endif /* GLX_MESA_pixmap_colormap */ - -/* ------------------------ GLX_MESA_release_buffers ----------------------- */ - -#ifndef GLX_MESA_release_buffers -#define GLX_MESA_release_buffers 1 - -typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d); - -#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA) - -#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers) - -#endif /* GLX_MESA_release_buffers */ - -/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */ - -#ifndef GLX_MESA_set_3dfx_mode -#define GLX_MESA_set_3dfx_mode 1 - -#define GLX_3DFX_WINDOW_MODE_MESA 0x1 -#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 - -typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode); - -#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA) - -#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode) - -#endif /* GLX_MESA_set_3dfx_mode */ - -/* ------------------------- GLX_MESA_swap_control ------------------------- */ - -#ifndef GLX_MESA_swap_control -#define GLX_MESA_swap_control 1 - -typedef int ( * PFNGLXGETSWAPINTERVALMESAPROC) (void); -typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval); - -#define glXGetSwapIntervalMESA GLXEW_GET_FUN(__glewXGetSwapIntervalMESA) -#define glXSwapIntervalMESA GLXEW_GET_FUN(__glewXSwapIntervalMESA) - -#define GLXEW_MESA_swap_control GLXEW_GET_VAR(__GLXEW_MESA_swap_control) - -#endif /* GLX_MESA_swap_control */ - -/* --------------------------- GLX_NV_copy_image --------------------------- */ - -#ifndef GLX_NV_copy_image -#define GLX_NV_copy_image 1 - -typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); - -#define glXCopyImageSubDataNV GLXEW_GET_FUN(__glewXCopyImageSubDataNV) - -#define GLXEW_NV_copy_image GLXEW_GET_VAR(__GLXEW_NV_copy_image) - -#endif /* GLX_NV_copy_image */ - -/* -------------------------- GLX_NV_float_buffer -------------------------- */ - -#ifndef GLX_NV_float_buffer -#define GLX_NV_float_buffer 1 - -#define GLX_FLOAT_COMPONENTS_NV 0x20B0 - -#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer) - -#endif /* GLX_NV_float_buffer */ - -/* ---------------------- GLX_NV_multisample_coverage ---------------------- */ - -#ifndef GLX_NV_multisample_coverage -#define GLX_NV_multisample_coverage 1 - -#define GLX_COLOR_SAMPLES_NV 0x20B3 -#define GLX_COVERAGE_SAMPLES_NV 100001 - -#define GLXEW_NV_multisample_coverage GLXEW_GET_VAR(__GLXEW_NV_multisample_coverage) - -#endif /* GLX_NV_multisample_coverage */ - -/* -------------------------- GLX_NV_present_video ------------------------- */ - -#ifndef GLX_NV_present_video -#define GLX_NV_present_video 1 - -#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 - -typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); -typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements); - -#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV) -#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV) - -#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video) - -#endif /* GLX_NV_present_video */ - -/* --------------------------- GLX_NV_swap_group --------------------------- */ - -#ifndef GLX_NV_swap_group -#define GLX_NV_swap_group 1 - -typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier); -typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group); -typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count); -typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); -typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); -typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen); - -#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV) -#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV) -#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV) -#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV) -#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV) -#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV) - -#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group) - -#endif /* GLX_NV_swap_group */ - -/* ----------------------- GLX_NV_vertex_array_range ----------------------- */ - -#ifndef GLX_NV_vertex_array_range -#define GLX_NV_vertex_array_range 1 - -typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); -typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer); - -#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV) -#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV) - -#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range) - -#endif /* GLX_NV_vertex_array_range */ - -/* -------------------------- GLX_NV_video_capture ------------------------- */ - -#ifndef GLX_NV_video_capture -#define GLX_NV_video_capture 1 - -#define GLX_DEVICE_ID_NV 0x20CD -#define GLX_UNIQUE_ID_NV 0x20CE -#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF - -typedef XID GLXVideoCaptureDeviceNV; - -typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (Display* dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device); -typedef GLXVideoCaptureDeviceNV * ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (Display* dpy, int screen, int *nelements); -typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); -typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value); -typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); - -#define glXBindVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXBindVideoCaptureDeviceNV) -#define glXEnumerateVideoCaptureDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoCaptureDevicesNV) -#define glXLockVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXLockVideoCaptureDeviceNV) -#define glXQueryVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXQueryVideoCaptureDeviceNV) -#define glXReleaseVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoCaptureDeviceNV) - -#define GLXEW_NV_video_capture GLXEW_GET_VAR(__GLXEW_NV_video_capture) - -#endif /* GLX_NV_video_capture */ - -/* -------------------------- GLX_NV_video_output -------------------------- */ - -#ifndef GLX_NV_video_output -#define GLX_NV_video_output 1 - -#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 -#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 -#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 -#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 -#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 -#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 -#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 -#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA -#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB -#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC - -typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); -typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); -typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); -typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice); -typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf); -typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); - -#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV) -#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV) -#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV) -#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV) -#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV) -#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV) - -#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output) - -#endif /* GLX_NV_video_output */ - -/* -------------------------- GLX_OML_swap_method -------------------------- */ - -#ifndef GLX_OML_swap_method -#define GLX_OML_swap_method 1 - -#define GLX_SWAP_METHOD_OML 0x8060 -#define GLX_SWAP_EXCHANGE_OML 0x8061 -#define GLX_SWAP_COPY_OML 0x8062 -#define GLX_SWAP_UNDEFINED_OML 0x8063 - -#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method) - -#endif /* GLX_OML_swap_method */ - -/* -------------------------- GLX_OML_sync_control ------------------------- */ - -#ifndef GLX_OML_sync_control -#define GLX_OML_sync_control 1 - -typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator); -typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc); -typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); -typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc); -typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc); - -#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML) -#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML) -#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML) -#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML) -#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML) - -#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control) - -#endif /* GLX_OML_sync_control */ - -/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */ - -#ifndef GLX_SGIS_blended_overlay -#define GLX_SGIS_blended_overlay 1 - -#define GLX_BLENDED_RGBA_SGIS 0x8025 - -#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay) - -#endif /* GLX_SGIS_blended_overlay */ - -/* -------------------------- GLX_SGIS_color_range ------------------------- */ - -#ifndef GLX_SGIS_color_range -#define GLX_SGIS_color_range 1 - -#define GLX_MIN_RED_SGIS 0 -#define GLX_MAX_GREEN_SGIS 0 -#define GLX_MIN_BLUE_SGIS 0 -#define GLX_MAX_ALPHA_SGIS 0 -#define GLX_MIN_GREEN_SGIS 0 -#define GLX_MIN_ALPHA_SGIS 0 -#define GLX_MAX_RED_SGIS 0 -#define GLX_EXTENDED_RANGE_SGIS 0 -#define GLX_MAX_BLUE_SGIS 0 - -#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range) - -#endif /* GLX_SGIS_color_range */ - -/* -------------------------- GLX_SGIS_multisample ------------------------- */ - -#ifndef GLX_SGIS_multisample -#define GLX_SGIS_multisample 1 - -#define GLX_SAMPLE_BUFFERS_SGIS 100000 -#define GLX_SAMPLES_SGIS 100001 - -#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample) - -#endif /* GLX_SGIS_multisample */ - -/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */ - -#ifndef GLX_SGIS_shared_multisample -#define GLX_SGIS_shared_multisample 1 - -#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 -#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 - -#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample) - -#endif /* GLX_SGIS_shared_multisample */ - -/* --------------------------- GLX_SGIX_fbconfig --------------------------- */ - -#ifndef GLX_SGIX_fbconfig -#define GLX_SGIX_fbconfig 1 - -#define GLX_WINDOW_BIT_SGIX 0x00000001 -#define GLX_RGBA_BIT_SGIX 0x00000001 -#define GLX_PIXMAP_BIT_SGIX 0x00000002 -#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 -#define GLX_SCREEN_EXT 0x800C -#define GLX_DRAWABLE_TYPE_SGIX 0x8010 -#define GLX_RENDER_TYPE_SGIX 0x8011 -#define GLX_X_RENDERABLE_SGIX 0x8012 -#define GLX_FBCONFIG_ID_SGIX 0x8013 -#define GLX_RGBA_TYPE_SGIX 0x8014 -#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 - -typedef XID GLXFBConfigIDSGIX; -typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; - -typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); -typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); -typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap); -typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value); -typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis); -typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config); - -#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX) -#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX) -#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX) -#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX) -#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX) -#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX) - -#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig) - -#endif /* GLX_SGIX_fbconfig */ - -/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */ - -#ifndef GLX_SGIX_hyperpipe -#define GLX_SGIX_hyperpipe 1 - -#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 -#define GLX_PIPE_RECT_SGIX 0x00000001 -#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 -#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 -#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 -#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 -#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 -#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 -#define GLX_BAD_HYPERPIPE_SGIX 92 -#define GLX_HYPERPIPE_ID_SGIX 0x8030 - -typedef struct { - char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; - int networkId; -} GLXHyperpipeNetworkSGIX; -typedef struct { - char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; - int XOrigin; - int YOrigin; - int maxHeight; - int maxWidth; -} GLXPipeRectLimits; -typedef struct { - char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; - int channel; - unsigned int participationType; - int timeSlice; -} GLXHyperpipeConfigSGIX; -typedef struct { - char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; - int srcXOrigin; - int srcYOrigin; - int srcWidth; - int srcHeight; - int destXOrigin; - int destYOrigin; - int destWidth; - int destHeight; -} GLXPipeRect; - -typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId); -typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId); -typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList); -typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); -typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); -typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); -typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes); -typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes); - -#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX) -#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX) -#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX) -#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX) -#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX) -#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX) -#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX) -#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX) - -#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe) - -#endif /* GLX_SGIX_hyperpipe */ - -/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */ - -#ifndef GLX_SGIX_pbuffer -#define GLX_SGIX_pbuffer 1 - -#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 -#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 -#define GLX_PBUFFER_BIT_SGIX 0x00000004 -#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 -#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 -#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 -#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 -#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 -#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 -#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 -#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 -#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 -#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 -#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 -#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A -#define GLX_PRESERVED_CONTENTS_SGIX 0x801B -#define GLX_LARGEST_PBUFFER_SGIX 0x801C -#define GLX_WIDTH_SGIX 0x801D -#define GLX_HEIGHT_SGIX 0x801E -#define GLX_EVENT_MASK_SGIX 0x801F -#define GLX_DAMAGED_SGIX 0x8020 -#define GLX_SAVED_SGIX 0x8021 -#define GLX_WINDOW_SGIX 0x8022 -#define GLX_PBUFFER_SGIX 0x8023 -#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 - -typedef XID GLXPbufferSGIX; -typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX; - -typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list); -typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf); -typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask); -typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); -typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask); - -#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX) -#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX) -#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX) -#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX) -#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX) - -#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer) - -#endif /* GLX_SGIX_pbuffer */ - -/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */ - -#ifndef GLX_SGIX_swap_barrier -#define GLX_SGIX_swap_barrier 1 - -typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); -typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); - -#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX) -#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX) - -#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier) - -#endif /* GLX_SGIX_swap_barrier */ - -/* -------------------------- GLX_SGIX_swap_group -------------------------- */ - -#ifndef GLX_SGIX_swap_group -#define GLX_SGIX_swap_group 1 - -typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); - -#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX) - -#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group) - -#endif /* GLX_SGIX_swap_group */ - -/* ------------------------- GLX_SGIX_video_resize ------------------------- */ - -#ifndef GLX_SGIX_video_resize -#define GLX_SGIX_video_resize 1 - -#define GLX_SYNC_FRAME_SGIX 0x00000000 -#define GLX_SYNC_SWAP_SGIX 0x00000001 - -typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window); -typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h); -typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype); -typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h); -typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); - -#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX) -#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX) -#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX) -#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX) -#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX) - -#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize) - -#endif /* GLX_SGIX_video_resize */ - -/* ---------------------- GLX_SGIX_visual_select_group --------------------- */ - -#ifndef GLX_SGIX_visual_select_group -#define GLX_SGIX_visual_select_group 1 - -#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 - -#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group) - -#endif /* GLX_SGIX_visual_select_group */ - -/* ---------------------------- GLX_SGI_cushion ---------------------------- */ - -#ifndef GLX_SGI_cushion -#define GLX_SGI_cushion 1 - -typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion); - -#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI) - -#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion) - -#endif /* GLX_SGI_cushion */ - -/* ----------------------- GLX_SGI_make_current_read ----------------------- */ - -#ifndef GLX_SGI_make_current_read -#define GLX_SGI_make_current_read 1 - -typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); -typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); - -#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI) -#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI) - -#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read) - -#endif /* GLX_SGI_make_current_read */ - -/* -------------------------- GLX_SGI_swap_control ------------------------- */ - -#ifndef GLX_SGI_swap_control -#define GLX_SGI_swap_control 1 - -typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); - -#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI) - -#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control) - -#endif /* GLX_SGI_swap_control */ - -/* --------------------------- GLX_SGI_video_sync -------------------------- */ - -#ifndef GLX_SGI_video_sync -#define GLX_SGI_video_sync 1 - -typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int* count); -typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count); - -#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI) -#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI) - -#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync) - -#endif /* GLX_SGI_video_sync */ - -/* --------------------- GLX_SUN_get_transparent_index --------------------- */ - -#ifndef GLX_SUN_get_transparent_index -#define GLX_SUN_get_transparent_index 1 - -typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex); - -#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN) - -#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index) - -#endif /* GLX_SUN_get_transparent_index */ - -/* -------------------------- GLX_SUN_video_resize ------------------------- */ - -#ifndef GLX_SUN_video_resize -#define GLX_SUN_video_resize 1 - -#define GLX_VIDEO_RESIZE_SUN 0x8171 -#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD - -typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor); -typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor); - -#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN) -#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN) - -#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize) - -#endif /* GLX_SUN_video_resize */ - -/* ------------------------------------------------------------------------- */ - -#ifdef GLEW_MX -#define GLXEW_EXPORT -#else -#define GLXEW_EXPORT extern -#endif /* GLEW_MX */ - -extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; - -extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; -extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; -extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; -extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; -extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow; -extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; -extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; -extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; -extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; -extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; -extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; -extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; -extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; -extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; -extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext; -extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; -extern PFNGLXSELECTEVENTPROC __glewXSelectEvent; - -extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; - -extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; -extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; -extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; - -extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; -extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; -extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; -extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; - -extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT; - -extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; -extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; - -extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; - -extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; - -extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; - -extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; - -extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; - -extern PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA; -extern PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA; - -extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; - -extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; -extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; - -extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; -extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; -extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; -extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; -extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; -extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; - -extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; -extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; - -extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV; -extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV; -extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV; -extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV; -extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV; - -extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; -extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; -extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; -extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; -extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; -extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; - -extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; -extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; -extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; -extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; -extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; - -extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; -extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; -extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; -extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; -extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; -extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; - -extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; -extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; -extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; -extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; -extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; -extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; -extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; -extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; - -extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; -extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; -extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; -extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; -extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; - -extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; -extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; - -extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; - -extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; -extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; -extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; -extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; -extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; - -extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI; - -extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; -extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; - -extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; - -extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; -extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; - -extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; - -extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; -extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; - -#if defined(GLEW_MX) -struct GLXEWContextStruct -{ -#endif /* GLEW_MX */ - -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4; -GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample; -GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association; -GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context; -GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile; -GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness; -GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; -GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; -GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address; -GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample; -GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object; -GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; -GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture; -GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile; -GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; -GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; -GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context; -GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker; -GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control; -GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; -GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info; -GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating; -GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event; -GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset; -GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; -GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; -GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers; -GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; -GLXEW_EXPORT GLboolean __GLXEW_MESA_swap_control; -GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image; -GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer; -GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage; -GLXEW_EXPORT GLboolean __GLXEW_NV_present_video; -GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group; -GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range; -GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture; -GLXEW_EXPORT GLboolean __GLXEW_NV_video_output; -GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method; -GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; -GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion; -GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read; -GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control; -GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync; -GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; -GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; - -#ifdef GLEW_MX -}; /* GLXEWContextStruct */ -#endif /* GLEW_MX */ - -/* ------------------------------------------------------------------------ */ - -#ifdef GLEW_MX - -typedef struct GLXEWContextStruct GLXEWContext; -extern GLenum glxewContextInit (GLXEWContext* ctx); -extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name); - -#define glxewInit() glxewContextInit(glxewGetContext()) -#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x) - -#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x)) -#define GLXEW_GET_FUN(x) x - -#else /* GLEW_MX */ - -#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x) -#define GLXEW_GET_FUN(x) x - -extern GLboolean glxewIsSupported (const char* name); - -#endif /* GLEW_MX */ - -extern GLboolean glxewGetExtension (const char* name); - -#ifdef __cplusplus -} -#endif - -#endif /* __glxew_h__ */ diff --git a/Code/Physics/Bullet Source/Glut/GL/glxext.h b/Code/Physics/Bullet Source/Glut/GL/glxext.h deleted file mode 100644 index b3de958d..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/glxext.h +++ /dev/null @@ -1,546 +0,0 @@ -#ifndef __glxext_h_ -#define __glxext_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 1.1 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: This software was created using the -** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has -** not been independently verified as being compliant with the OpenGL(R) -** version 1.2.1 Specification. -*/ - -#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) -#define WIN32_LEAN_AND_MEAN 1 -#include -#else -#include -#endif - -#ifndef APIENTRY -#define APIENTRY -#endif - - -/*************************************************************/ - -/* Header file version number, required by OpenGL ABI for Linux */ -#define GLX_GLXEXT_VERSION 2 - -#ifndef GLX_VERSION_1_3 -#define GLX_WINDOW_BIT 0x00000001 -#define GLX_PIXMAP_BIT 0x00000002 -#define GLX_PBUFFER_BIT 0x00000004 -#define GLX_RGBA_BIT 0x00000001 -#define GLX_COLOR_INDEX_BIT 0x00000002 -#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 -#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 -#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 -#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 -#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 -#define GLX_AUX_BUFFERS_BIT 0x00000010 -#define GLX_DEPTH_BUFFER_BIT 0x00000020 -#define GLX_STENCIL_BUFFER_BIT 0x00000040 -#define GLX_ACCUM_BUFFER_BIT 0x00000080 -#define GLX_CONFIG_CAVEAT 0x20 -#define GLX_X_VISUAL_TYPE 0x22 -#define GLX_TRANSPARENT_TYPE 0x23 -#define GLX_TRANSPARENT_INDEX_VALUE 0x24 -#define GLX_TRANSPARENT_RED_VALUE 0x25 -#define GLX_TRANSPARENT_GREEN_VALUE 0x26 -#define GLX_TRANSPARENT_BLUE_VALUE 0x27 -#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 -#define GLX_DONT_CARE 0xFFFFFFFF -#define GLX_NONE 0x8000 -#define GLX_SLOW_CONFIG 0x8001 -#define GLX_TRUE_COLOR 0x8002 -#define GLX_DIRECT_COLOR 0x8003 -#define GLX_PSEUDO_COLOR 0x8004 -#define GLX_STATIC_COLOR 0x8005 -#define GLX_GRAY_SCALE 0x8006 -#define GLX_STATIC_GRAY 0x8007 -#define GLX_TRANSPARENT_RGB 0x8008 -#define GLX_TRANSPARENT_INDEX 0x8009 -#define GLX_VISUAL_ID 0x800B -#define GLX_SCREEN 0x800C -#define GLX_NON_CONFORMANT_CONFIG 0x800D -#define GLX_DRAWABLE_TYPE 0x8010 -#define GLX_RENDER_TYPE 0x8011 -#define GLX_X_RENDERABLE 0x8012 -#define GLX_FBCONFIG_ID 0x8013 -#define GLX_RGBA_TYPE 0x8014 -#define GLX_COLOR_INDEX_TYPE 0x8015 -#define GLX_MAX_PBUFFER_WIDTH 0x8016 -#define GLX_MAX_PBUFFER_HEIGHT 0x8017 -#define GLX_MAX_PBUFFER_PIXELS 0x8018 -#define GLX_PRESERVED_CONTENTS 0x801B -#define GLX_LARGEST_PBUFFER 0x801C -#define GLX_WIDTH 0x801D -#define GLX_HEIGHT 0x801E -#define GLX_EVENT_MASK 0x801F -#define GLX_DAMAGED 0x8020 -#define GLX_SAVED 0x8021 -#define GLX_WINDOW 0x8022 -#define GLX_PBUFFER 0x8023 -#define GLX_PBUFFER_HEIGHT 0x8040 -#define GLX_PBUFFER_WIDTH 0x8041 -#endif - -#ifndef GLX_EXT_visual_info -#define GLX_X_VISUAL_TYPE_EXT 0x22 -#define GLX_TRANSPARENT_TYPE_EXT 0x23 -#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 -#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 -#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 -#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 -#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 -#define GLX_NONE_EXT 0x8000 -#define GLX_TRUE_COLOR_EXT 0x8002 -#define GLX_DIRECT_COLOR_EXT 0x8003 -#define GLX_PSEUDO_COLOR_EXT 0x8004 -#define GLX_STATIC_COLOR_EXT 0x8005 -#define GLX_GRAY_SCALE_EXT 0x8006 -#define GLX_STATIC_GRAY_EXT 0x8007 -#define GLX_TRANSPARENT_RGB_EXT 0x8008 -#define GLX_TRANSPARENT_INDEX_EXT 0x8009 -#endif - -#ifndef GLX_SGI_swap_control -#endif - -#ifndef GLX_SGI_video_sync -#endif - -#ifndef GLX_SGI_make_current_read -#endif - -#ifndef GLX_SGIX_video_source -#endif - -#ifndef GLX_EXT_visual_rating -#define GLX_VISUAL_CAVEAT_EXT 0x20 -#define GLX_SLOW_VISUAL_EXT 0x8001 -#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D -/* reuse GLX_NONE_EXT */ -#endif - -#ifndef GLX_EXT_import_context -#define GLX_SHARE_CONTEXT_EXT 0x800A -#define GLX_VISUAL_ID_EXT 0x800B -#define GLX_SCREEN_EXT 0x800C -#endif - -#ifndef GLX_SGIX_fbconfig -#define GLX_WINDOW_BIT_SGIX 0x00000001 -#define GLX_PIXMAP_BIT_SGIX 0x00000002 -#define GLX_RGBA_BIT_SGIX 0x00000001 -#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 -#define GLX_DRAWABLE_TYPE_SGIX 0x8010 -#define GLX_RENDER_TYPE_SGIX 0x8011 -#define GLX_X_RENDERABLE_SGIX 0x8012 -#define GLX_FBCONFIG_ID_SGIX 0x8013 -#define GLX_RGBA_TYPE_SGIX 0x8014 -#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 -/* reuse GLX_SCREEN_EXT */ -#endif - -#ifndef GLX_SGIX_pbuffer -#define GLX_PBUFFER_BIT_SGIX 0x00000004 -#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 -#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 -#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 -#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 -#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 -#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 -#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 -#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 -#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 -#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 -#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 -#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 -#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 -#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 -#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A -#define GLX_PRESERVED_CONTENTS_SGIX 0x801B -#define GLX_LARGEST_PBUFFER_SGIX 0x801C -#define GLX_WIDTH_SGIX 0x801D -#define GLX_HEIGHT_SGIX 0x801E -#define GLX_EVENT_MASK_SGIX 0x801F -#define GLX_DAMAGED_SGIX 0x8020 -#define GLX_SAVED_SGIX 0x8021 -#define GLX_WINDOW_SGIX 0x8022 -#define GLX_PBUFFER_SGIX 0x8023 -#endif - -#ifndef GLX_SGI_cushion -#endif - -#ifndef GLX_SGIX_video_resize -#define GLX_SYNC_FRAME_SGIX 0x00000000 -#define GLX_SYNC_SWAP_SGIX 0x00000001 -#endif - -#ifndef GLX_SGIX_dmbuffer -#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 -#endif - -#ifndef GLX_SGIX_swap_group -#endif - -#ifndef GLX_SGIX_swap_barrier -#endif - -#ifndef GLX_SGIS_blended_overlay -#define GLX_BLENDED_RGBA_SGIS 0x8025 -#endif - -#ifndef GLX_SGIS_shared_multisample -#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 -#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 -#endif - -#ifndef GLX_SUN_get_transparent_index -#endif - -#ifndef GLX_3DFX_multisample -#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 -#define GLX_SAMPLES_3DFX 0x8051 -#endif - -#ifndef GLX_MESA_copy_sub_buffer -#endif - -#ifndef GLX_MESA_pixmap_colormap -#endif - -#ifndef GLX_MESA_release_buffers -#endif - -#ifndef GLX_MESA_set_3dfx_mode -#define GLX_3DFX_WINDOW_MODE_MESA 0x1 -#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 -#endif - - -/*************************************************************/ - -#ifndef GLX_ARB_get_proc_address -typedef void (*__GLXextFuncPtr)(); -#endif - -#ifndef GLX_SGIX_video_source -typedef XID GLXVideoSourceSGIX; -#endif - -#ifndef GLX_SGIX_fbconfig -typedef XID GLXFBConfigIDSGIX; -typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; -#endif - -#ifndef GLX_SGIX_pbuffer -typedef XID GLXPbufferSGIX; -typedef struct { - int type; - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* true if this came for SendEvent request */ - Display *display; /* display the event was read from */ - GLXDrawable drawable; /* i.d. of Drawable */ - int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ - int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ - unsigned int mask; /* mask indicating which buffers are affected*/ - int x, y; - int width, height; - int count; /* if nonzero, at least this many more */ -} GLXBufferClobberEventSGIX; -#endif - -#ifdef GL_NV_vertex_array_range -#ifndef PFNGLXALLOCATEMEMORYNVPROC -#ifdef GLX_GLXEXT_PROTOTYPES -extern void *glXAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); -#endif -typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei, GLfloat, GLfloat, GLfloat); -#endif -#ifndef PFNGLXFREEMEMORYNVPROC -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXFreeMemoryNV (void *); -#endif -typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *); -#endif -#endif - -#ifndef GLX_VERSION_1_3 -#define GLX_VERSION_1_3 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern GLXFBConfig * glXGetFBConfigs (Display *, int, int *); -extern GLXFBConfig * glXChooseFBConfig (Display *, int, const int *, int *); -extern int glXGetFBConfigAttrib (Display *, GLXFBConfig, int, int *); -extern XVisualInfo * glXGetVisualFromFBConfig (Display *, GLXFBConfig); -extern GLXWindow glXCreateWindow (Display *, GLXFBConfig, Window, const int *); -extern void glXDestroyWindow (Display *, GLXWindow); -extern GLXPixmap glXCreatePixmap (Display *, GLXFBConfig, Pixmap, const int *); -extern void glXDestroyPixmap (Display *, GLXPixmap); -extern GLXPbuffer glXCreatePbuffer (Display *, GLXFBConfig, const int *); -extern void glXDestroyPbuffer (Display *, GLXPbuffer); -extern void glXQueryDrawable (Display *, GLXDrawable, int, unsigned int *); -extern GLXContext glXCreateNewContext (Display *, GLXFBConfig, int, GLXContext, Bool); -extern Bool glXMakeContextCurrent (Display *, GLXDrawable, GLXDrawable, GLXContext); -extern GLXDrawable glXGetCurrentReadDrawable (void); -extern Display * glXGetCurrentDisplay (void); -extern int glXQueryContext (Display *, GLXContext, int, int *); -extern void glXSelectEvent (Display *, GLXDrawable, unsigned long); -extern void glXGetSelectedEvent (Display *, GLXDrawable, unsigned long *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXFBConfig * ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); -typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); -typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); -typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); -typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); -typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); -typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); -typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); -typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); -typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); -typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); -typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); -typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); -typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); -typedef Display * ( * PFNGLXGETCURRENTDISPLAYPROC) (void); -typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); -typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); -typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); -#endif - -#ifndef GLX_ARB_get_proc_address -#define GLX_ARB_get_proc_address 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); -#endif - -#ifndef GLX_SGIS_multisample -#define GLX_SGIS_multisample 1 -#endif - -#ifndef GLX_EXT_visual_info -#define GLX_EXT_visual_info 1 -#endif - -#ifndef GLX_SGI_swap_control -#define GLX_SGI_swap_control 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXSwapIntervalSGI (int); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); -#endif - -#ifndef GLX_SGI_video_sync -#define GLX_SGI_video_sync 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXGetVideoSyncSGI (unsigned int *); -extern int glXWaitVideoSyncSGI (int, int, unsigned int *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count); -typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count); -#endif - -#ifndef GLX_SGI_make_current_read -#define GLX_SGI_make_current_read 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXMakeCurrentReadSGI (Display *, GLXDrawable, GLXDrawable, GLXContext); -extern GLXDrawable glXGetCurrentReadDrawableSGI (void); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); -typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); -#endif - -#ifdef _VL_H -#ifndef GLX_SGIX_video_source -#define GLX_SGIX_video_source 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (Display *, int, VLServer, VLPath, int, VLNode); -extern void glXDestroyGLXVideoSourceSGIX (Display *, GLXVideoSourceSGIX); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXVideoSourceSGIX ( * PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); -typedef void ( * PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (Display *dpy, GLXVideoSourceSGIX glxvideosource); -#endif - -#endif /* _VL_H */ -#ifndef GLX_EXT_visual_rating -#define GLX_EXT_visual_rating 1 -#endif - -#ifndef GLX_EXT_import_context -#define GLX_EXT_import_context 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Display * glXGetCurrentDisplayEXT (void); -extern int glXQueryContextInfoEXT (Display *, GLXContext, int, int *); -extern GLXContextID glXGetContextIDEXT (GLXContext); -extern GLXContext glXImportContextEXT (Display *, GLXContextID); -extern void glXFreeContextEXT (Display *, GLXContext); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Display * ( * PFNGLXGETCURRENTDISPLAYEXTPROC) (void); -typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display *dpy, GLXContext context, int attribute, int *value); -typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (GLXContext context); -typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display *dpy, GLXContextID contextID); -typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display *dpy, GLXContext context); -#endif - -#ifndef GLX_SGIX_fbconfig -#define GLX_SGIX_fbconfig 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXGetFBConfigAttribSGIX (Display *, GLXFBConfigSGIX, int, int *); -extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (Display *, int, int *, int *); -extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (Display *, GLXFBConfigSGIX, Pixmap); -extern GLXContext glXCreateContextWithConfigSGIX (Display *, GLXFBConfigSGIX, int, GLXContext, Bool); -extern XVisualInfo * glXGetVisualFromFBConfigSGIX (Display *, GLXFBConfigSGIX); -extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (Display *, XVisualInfo *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); -typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements); -typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); -typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); -typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config); -typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display *dpy, XVisualInfo *vis); -#endif - -#ifndef GLX_SGIX_pbuffer -#define GLX_SGIX_pbuffer 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); -extern void glXDestroyGLXPbufferSGIX (Display *, GLXPbufferSGIX); -extern int glXQueryGLXPbufferSGIX (Display *, GLXPbufferSGIX, int, unsigned int *); -extern void glXSelectEventSGIX (Display *, GLXDrawable, unsigned long); -extern void glXGetSelectedEventSGIX (Display *, GLXDrawable, unsigned long *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXPbufferSGIX ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); -typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf); -typedef int ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); -typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long mask); -typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long *mask); -#endif - -#ifndef GLX_SGI_cushion -#define GLX_SGI_cushion 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXCushionSGI (Display *, Window, float); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void ( * PFNGLXCUSHIONSGIPROC) (Display *dpy, Window window, float cushion); -#endif - -#ifndef GLX_SGIX_video_resize -#define GLX_SGIX_video_resize 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXBindChannelToWindowSGIX (Display *, int, int, Window); -extern int glXChannelRectSGIX (Display *, int, int, int, int, int, int); -extern int glXQueryChannelRectSGIX (Display *, int, int, int *, int *, int *, int *); -extern int glXQueryChannelDeltasSGIX (Display *, int, int, int *, int *, int *, int *); -extern int glXChannelRectSyncSGIX (Display *, int, int, GLenum); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display *display, int screen, int channel, Window window); -typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int x, int y, int w, int h); -typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); -typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display *display, int screen, int channel, int *x, int *y, int *w, int *h); -typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display *display, int screen, int channel, GLenum synctype); -#endif - -#ifdef _DM_BUFFER_H_ -#ifndef GLX_SGIX_dmbuffer -#define GLX_SGIX_dmbuffer 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXAssociateDMPbufferSGIX (Display *, GLXPbufferSGIX, DMparams *, DMbuffer); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool ( * PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); -#endif - -#endif /* _DM_BUFFER_H_ */ -#ifndef GLX_SGIX_swap_group -#define GLX_SGIX_swap_group 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); -#endif - -#ifndef GLX_SGIX_swap_barrier -#define GLX_SGIX_swap_barrier 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXBindSwapBarrierSGIX (Display *, GLXDrawable, int); -extern Bool glXQueryMaxSwapBarriersSGIX (Display *, int, int *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); -typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); -#endif - -#ifndef GLX_SUN_get_transparent_index -#define GLX_SUN_get_transparent_index 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Status glXGetTransparentIndexSUN (Display *, Window, Window, long *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display *dpy, Window overlay, Window underlay, long *pTransparentIndex); -#endif - -#ifndef GLX_MESA_copy_sub_buffer -#define GLX_MESA_copy_sub_buffer 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXCopySubBufferMESA (Display *, GLXDrawable, int, int, int, int); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); -#endif - -#ifndef GLX_MESA_pixmap_colormap -#define GLX_MESA_pixmap_colormap 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern GLXPixmap glXCreateGLXPixmapMESA (Display *, XVisualInfo *, Pixmap, Colormap); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); -#endif - -#ifndef GLX_MESA_release_buffers -#define GLX_MESA_release_buffers 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXReleaseBuffersMESA (Display *, GLXDrawable); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display *dpy, GLXDrawable drawable); -#endif - -#ifndef GLX_MESA_set_3dfx_mode -#define GLX_MESA_set_3dfx_mode 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXSet3DfxModeMESA (int); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool ( * PFNGLXSET3DFXMODEMESAPROC) (int mode); -#endif - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Code/Physics/Bullet Source/Glut/GL/wglew.h b/Code/Physics/Bullet Source/Glut/GL/wglew.h deleted file mode 100644 index 05f054fc..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/wglew.h +++ /dev/null @@ -1,1363 +0,0 @@ -/* -** The OpenGL Extension Wrangler Library -** Copyright (C) 2002-2008, Milan Ikits -** Copyright (C) 2002-2008, Marcelo E. Magallon -** Copyright (C) 2002, Lev Povalahev -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** * The name of the author may be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -** THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* -** Copyright (c) 2007 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -#ifndef __wglew_h__ -#define __wglew_h__ -#define __WGLEW_H__ - -#ifdef __wglext_h_ -#error wglext.h included before wglew.h -#endif - -#define __wglext_h_ - -#if !defined(WINAPI) -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif -#include -# undef WIN32_LEAN_AND_MEAN -#endif - -/* - * GLEW_STATIC needs to be set when using the static version. - * GLEW_BUILD is set when building the DLL version. - */ -#ifdef GLEW_STATIC -# define GLEWAPI extern -#else -# ifdef GLEW_BUILD -# define GLEWAPI extern __declspec(dllexport) -# else -# define GLEWAPI extern __declspec(dllimport) -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* -------------------------- WGL_3DFX_multisample ------------------------- */ - -#ifndef WGL_3DFX_multisample -#define WGL_3DFX_multisample 1 - -#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 -#define WGL_SAMPLES_3DFX 0x2061 - -#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample) - -#endif /* WGL_3DFX_multisample */ - -/* ------------------------- WGL_3DL_stereo_control ------------------------ */ - -#ifndef WGL_3DL_stereo_control -#define WGL_3DL_stereo_control 1 - -#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 -#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 -#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 -#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 - -typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); - -#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL) - -#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control) - -#endif /* WGL_3DL_stereo_control */ - -/* ------------------------ WGL_AMD_gpu_association ------------------------ */ - -#ifndef WGL_AMD_gpu_association -#define WGL_AMD_gpu_association 1 - -#define WGL_GPU_VENDOR_AMD 0x1F00 -#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 -#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 -#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 -#define WGL_GPU_RAM_AMD 0x21A3 -#define WGL_GPU_CLOCK_AMD 0x21A4 -#define WGL_GPU_NUM_PIPES_AMD 0x21A5 -#define WGL_GPU_NUM_SIMD_AMD 0x21A6 -#define WGL_GPU_NUM_RB_AMD 0x21A7 -#define WGL_GPU_NUM_SPI_AMD 0x21A8 - -typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); -typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int* attribList); -typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); -typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); -typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); -typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT* ids); -typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void* data); -typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); - -#define wglBlitContextFramebufferAMD WGLEW_GET_FUN(__wglewBlitContextFramebufferAMD) -#define wglCreateAssociatedContextAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAMD) -#define wglCreateAssociatedContextAttribsAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAttribsAMD) -#define wglDeleteAssociatedContextAMD WGLEW_GET_FUN(__wglewDeleteAssociatedContextAMD) -#define wglGetContextGPUIDAMD WGLEW_GET_FUN(__wglewGetContextGPUIDAMD) -#define wglGetCurrentAssociatedContextAMD WGLEW_GET_FUN(__wglewGetCurrentAssociatedContextAMD) -#define wglGetGPUIDsAMD WGLEW_GET_FUN(__wglewGetGPUIDsAMD) -#define wglGetGPUInfoAMD WGLEW_GET_FUN(__wglewGetGPUInfoAMD) -#define wglMakeAssociatedContextCurrentAMD WGLEW_GET_FUN(__wglewMakeAssociatedContextCurrentAMD) - -#define WGLEW_AMD_gpu_association WGLEW_GET_VAR(__WGLEW_AMD_gpu_association) - -#endif /* WGL_AMD_gpu_association */ - -/* ------------------------- WGL_ARB_buffer_region ------------------------- */ - -#ifndef WGL_ARB_buffer_region -#define WGL_ARB_buffer_region 1 - -#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 -#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 -#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 -#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 - -typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); -typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); -typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); -typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); - -#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB) -#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB) -#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB) -#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB) - -#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region) - -#endif /* WGL_ARB_buffer_region */ - -/* ------------------------- WGL_ARB_create_context ------------------------ */ - -#ifndef WGL_ARB_create_context -#define WGL_ARB_create_context 1 - -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define ERROR_INVALID_VERSION_ARB 0x2095 -#define ERROR_INVALID_PROFILE_ARB 0x2096 - -typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); - -#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB) - -#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context) - -#endif /* WGL_ARB_create_context */ - -/* --------------------- WGL_ARB_create_context_profile -------------------- */ - -#ifndef WGL_ARB_create_context_profile -#define WGL_ARB_create_context_profile 1 - -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 - -#define WGLEW_ARB_create_context_profile WGLEW_GET_VAR(__WGLEW_ARB_create_context_profile) - -#endif /* WGL_ARB_create_context_profile */ - -/* ------------------- WGL_ARB_create_context_robustness ------------------- */ - -#ifndef WGL_ARB_create_context_robustness -#define WGL_ARB_create_context_robustness 1 - -#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 -#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 -#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 - -#define WGLEW_ARB_create_context_robustness WGLEW_GET_VAR(__WGLEW_ARB_create_context_robustness) - -#endif /* WGL_ARB_create_context_robustness */ - -/* ----------------------- WGL_ARB_extensions_string ----------------------- */ - -#ifndef WGL_ARB_extensions_string -#define WGL_ARB_extensions_string 1 - -typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); - -#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB) - -#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string) - -#endif /* WGL_ARB_extensions_string */ - -/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */ - -#ifndef WGL_ARB_framebuffer_sRGB -#define WGL_ARB_framebuffer_sRGB 1 - -#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 - -#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB) - -#endif /* WGL_ARB_framebuffer_sRGB */ - -/* ----------------------- WGL_ARB_make_current_read ----------------------- */ - -#ifndef WGL_ARB_make_current_read -#define WGL_ARB_make_current_read 1 - -#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 -#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 - -typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID); -typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); - -#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB) -#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB) - -#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read) - -#endif /* WGL_ARB_make_current_read */ - -/* -------------------------- WGL_ARB_multisample -------------------------- */ - -#ifndef WGL_ARB_multisample -#define WGL_ARB_multisample 1 - -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 - -#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample) - -#endif /* WGL_ARB_multisample */ - -/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */ - -#ifndef WGL_ARB_pbuffer -#define WGL_ARB_pbuffer 1 - -#define WGL_DRAW_TO_PBUFFER_ARB 0x202D -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 - -DECLARE_HANDLE(HPBUFFERARB); - -typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); -typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); -typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); -typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue); -typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); - -#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB) -#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB) -#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB) -#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB) -#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB) - -#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer) - -#endif /* WGL_ARB_pbuffer */ - -/* -------------------------- WGL_ARB_pixel_format ------------------------- */ - -#ifndef WGL_ARB_pixel_format -#define WGL_ARB_pixel_format 1 - -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B - -typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues); - -#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB) -#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB) -#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB) - -#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format) - -#endif /* WGL_ARB_pixel_format */ - -/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */ - -#ifndef WGL_ARB_pixel_format_float -#define WGL_ARB_pixel_format_float 1 - -#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 - -#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float) - -#endif /* WGL_ARB_pixel_format_float */ - -/* ------------------------- WGL_ARB_render_texture ------------------------ */ - -#ifndef WGL_ARB_render_texture -#define WGL_ARB_render_texture 1 - -#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 -#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 -#define WGL_TEXTURE_FORMAT_ARB 0x2072 -#define WGL_TEXTURE_TARGET_ARB 0x2073 -#define WGL_MIPMAP_TEXTURE_ARB 0x2074 -#define WGL_TEXTURE_RGB_ARB 0x2075 -#define WGL_TEXTURE_RGBA_ARB 0x2076 -#define WGL_NO_TEXTURE_ARB 0x2077 -#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 -#define WGL_TEXTURE_1D_ARB 0x2079 -#define WGL_TEXTURE_2D_ARB 0x207A -#define WGL_MIPMAP_LEVEL_ARB 0x207B -#define WGL_CUBE_MAP_FACE_ARB 0x207C -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 -#define WGL_FRONT_LEFT_ARB 0x2083 -#define WGL_FRONT_RIGHT_ARB 0x2084 -#define WGL_BACK_LEFT_ARB 0x2085 -#define WGL_BACK_RIGHT_ARB 0x2086 -#define WGL_AUX0_ARB 0x2087 -#define WGL_AUX1_ARB 0x2088 -#define WGL_AUX2_ARB 0x2089 -#define WGL_AUX3_ARB 0x208A -#define WGL_AUX4_ARB 0x208B -#define WGL_AUX5_ARB 0x208C -#define WGL_AUX6_ARB 0x208D -#define WGL_AUX7_ARB 0x208E -#define WGL_AUX8_ARB 0x208F -#define WGL_AUX9_ARB 0x2090 - -typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); -typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); -typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList); - -#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB) -#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB) -#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB) - -#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture) - -#endif /* WGL_ARB_render_texture */ - -/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */ - -#ifndef WGL_ATI_pixel_format_float -#define WGL_ATI_pixel_format_float 1 - -#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 -#define GL_RGBA_FLOAT_MODE_ATI 0x8820 -#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 - -#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float) - -#endif /* WGL_ATI_pixel_format_float */ - -/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */ - -#ifndef WGL_ATI_render_texture_rectangle -#define WGL_ATI_render_texture_rectangle 1 - -#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5 - -#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle) - -#endif /* WGL_ATI_render_texture_rectangle */ - -/* ------------------- WGL_EXT_create_context_es2_profile ------------------ */ - -#ifndef WGL_EXT_create_context_es2_profile -#define WGL_EXT_create_context_es2_profile 1 - -#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 - -#define WGLEW_EXT_create_context_es2_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es2_profile) - -#endif /* WGL_EXT_create_context_es2_profile */ - -/* -------------------------- WGL_EXT_depth_float -------------------------- */ - -#ifndef WGL_EXT_depth_float -#define WGL_EXT_depth_float 1 - -#define WGL_DEPTH_FLOAT_EXT 0x2040 - -#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float) - -#endif /* WGL_EXT_depth_float */ - -/* ---------------------- WGL_EXT_display_color_table ---------------------- */ - -#ifndef WGL_EXT_display_color_table -#define WGL_EXT_display_color_table 1 - -typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); -typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); -typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); -typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length); - -#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT) -#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT) -#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT) -#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT) - -#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table) - -#endif /* WGL_EXT_display_color_table */ - -/* ----------------------- WGL_EXT_extensions_string ----------------------- */ - -#ifndef WGL_EXT_extensions_string -#define WGL_EXT_extensions_string 1 - -typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); - -#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT) - -#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string) - -#endif /* WGL_EXT_extensions_string */ - -/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */ - -#ifndef WGL_EXT_framebuffer_sRGB -#define WGL_EXT_framebuffer_sRGB 1 - -#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 - -#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB) - -#endif /* WGL_EXT_framebuffer_sRGB */ - -/* ----------------------- WGL_EXT_make_current_read ----------------------- */ - -#ifndef WGL_EXT_make_current_read -#define WGL_EXT_make_current_read 1 - -#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 - -typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID); -typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); - -#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT) -#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT) - -#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read) - -#endif /* WGL_EXT_make_current_read */ - -/* -------------------------- WGL_EXT_multisample -------------------------- */ - -#ifndef WGL_EXT_multisample -#define WGL_EXT_multisample 1 - -#define WGL_SAMPLE_BUFFERS_EXT 0x2041 -#define WGL_SAMPLES_EXT 0x2042 - -#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample) - -#endif /* WGL_EXT_multisample */ - -/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */ - -#ifndef WGL_EXT_pbuffer -#define WGL_EXT_pbuffer 1 - -#define WGL_DRAW_TO_PBUFFER_EXT 0x202D -#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E -#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 -#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 -#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 -#define WGL_PBUFFER_LARGEST_EXT 0x2033 -#define WGL_PBUFFER_WIDTH_EXT 0x2034 -#define WGL_PBUFFER_HEIGHT_EXT 0x2035 - -DECLARE_HANDLE(HPBUFFEREXT); - -typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); -typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); -typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); -typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue); -typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); - -#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT) -#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT) -#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT) -#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT) -#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT) - -#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer) - -#endif /* WGL_EXT_pbuffer */ - -/* -------------------------- WGL_EXT_pixel_format ------------------------- */ - -#ifndef WGL_EXT_pixel_format -#define WGL_EXT_pixel_format 1 - -#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 -#define WGL_DRAW_TO_WINDOW_EXT 0x2001 -#define WGL_DRAW_TO_BITMAP_EXT 0x2002 -#define WGL_ACCELERATION_EXT 0x2003 -#define WGL_NEED_PALETTE_EXT 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 -#define WGL_SWAP_METHOD_EXT 0x2007 -#define WGL_NUMBER_OVERLAYS_EXT 0x2008 -#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 -#define WGL_TRANSPARENT_EXT 0x200A -#define WGL_TRANSPARENT_VALUE_EXT 0x200B -#define WGL_SHARE_DEPTH_EXT 0x200C -#define WGL_SHARE_STENCIL_EXT 0x200D -#define WGL_SHARE_ACCUM_EXT 0x200E -#define WGL_SUPPORT_GDI_EXT 0x200F -#define WGL_SUPPORT_OPENGL_EXT 0x2010 -#define WGL_DOUBLE_BUFFER_EXT 0x2011 -#define WGL_STEREO_EXT 0x2012 -#define WGL_PIXEL_TYPE_EXT 0x2013 -#define WGL_COLOR_BITS_EXT 0x2014 -#define WGL_RED_BITS_EXT 0x2015 -#define WGL_RED_SHIFT_EXT 0x2016 -#define WGL_GREEN_BITS_EXT 0x2017 -#define WGL_GREEN_SHIFT_EXT 0x2018 -#define WGL_BLUE_BITS_EXT 0x2019 -#define WGL_BLUE_SHIFT_EXT 0x201A -#define WGL_ALPHA_BITS_EXT 0x201B -#define WGL_ALPHA_SHIFT_EXT 0x201C -#define WGL_ACCUM_BITS_EXT 0x201D -#define WGL_ACCUM_RED_BITS_EXT 0x201E -#define WGL_ACCUM_GREEN_BITS_EXT 0x201F -#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 -#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 -#define WGL_DEPTH_BITS_EXT 0x2022 -#define WGL_STENCIL_BITS_EXT 0x2023 -#define WGL_AUX_BUFFERS_EXT 0x2024 -#define WGL_NO_ACCELERATION_EXT 0x2025 -#define WGL_GENERIC_ACCELERATION_EXT 0x2026 -#define WGL_FULL_ACCELERATION_EXT 0x2027 -#define WGL_SWAP_EXCHANGE_EXT 0x2028 -#define WGL_SWAP_COPY_EXT 0x2029 -#define WGL_SWAP_UNDEFINED_EXT 0x202A -#define WGL_TYPE_RGBA_EXT 0x202B -#define WGL_TYPE_COLORINDEX_EXT 0x202C - -typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues); - -#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT) -#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT) -#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT) - -#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format) - -#endif /* WGL_EXT_pixel_format */ - -/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */ - -#ifndef WGL_EXT_pixel_format_packed_float -#define WGL_EXT_pixel_format_packed_float 1 - -#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 - -#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float) - -#endif /* WGL_EXT_pixel_format_packed_float */ - -/* -------------------------- WGL_EXT_swap_control ------------------------- */ - -#ifndef WGL_EXT_swap_control -#define WGL_EXT_swap_control 1 - -typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); -typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); - -#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT) -#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT) - -#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control) - -#endif /* WGL_EXT_swap_control */ - -/* --------------------- WGL_I3D_digital_video_control --------------------- */ - -#ifndef WGL_I3D_digital_video_control -#define WGL_I3D_digital_video_control 1 - -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 -#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 -#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 - -typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); -typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); - -#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D) -#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D) - -#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control) - -#endif /* WGL_I3D_digital_video_control */ - -/* ----------------------------- WGL_I3D_gamma ----------------------------- */ - -#ifndef WGL_I3D_gamma -#define WGL_I3D_gamma 1 - -#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E -#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F - -typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue); -typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); -typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue); -typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); - -#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D) -#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D) -#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D) -#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D) - -#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma) - -#endif /* WGL_I3D_gamma */ - -/* ---------------------------- WGL_I3D_genlock ---------------------------- */ - -#ifndef WGL_I3D_genlock -#define WGL_I3D_genlock 1 - -#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 -#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 -#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 -#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 -#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 -#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 -#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A -#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B -#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C - -typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); -typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); -typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); -typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); -typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); -typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); -typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate); -typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay); -typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge); -typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource); -typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag); -typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay); - -#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D) -#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D) -#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D) -#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D) -#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D) -#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D) -#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D) -#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D) -#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D) -#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D) -#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D) -#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D) - -#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock) - -#endif /* WGL_I3D_genlock */ - -/* -------------------------- WGL_I3D_image_buffer ------------------------- */ - -#ifndef WGL_I3D_image_buffer -#define WGL_I3D_image_buffer 1 - -#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 -#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 - -typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count); -typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); -typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); -typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count); - -#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D) -#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D) -#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D) -#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D) - -#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer) - -#endif /* WGL_I3D_image_buffer */ - -/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */ - -#ifndef WGL_I3D_swap_frame_lock -#define WGL_I3D_swap_frame_lock 1 - -typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID); -typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID); -typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag); -typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag); - -#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D) -#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D) -#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D) -#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D) - -#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock) - -#endif /* WGL_I3D_swap_frame_lock */ - -/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */ - -#ifndef WGL_I3D_swap_frame_usage -#define WGL_I3D_swap_frame_usage 1 - -typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); -typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); -typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage); -typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); - -#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D) -#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D) -#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D) -#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D) - -#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage) - -#endif /* WGL_I3D_swap_frame_usage */ - -/* --------------------------- WGL_NV_DX_interop --------------------------- */ - -#ifndef WGL_NV_DX_interop -#define WGL_NV_DX_interop 1 - -#define WGL_ACCESS_READ_ONLY_NV 0x0000 -#define WGL_ACCESS_READ_WRITE_NV 0x0001 -#define WGL_ACCESS_WRITE_DISCARD_NV 0x0002 - -typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); -typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); -typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); -typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice); -typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); -typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle); -typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); -typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); - -#define wglDXCloseDeviceNV WGLEW_GET_FUN(__wglewDXCloseDeviceNV) -#define wglDXLockObjectsNV WGLEW_GET_FUN(__wglewDXLockObjectsNV) -#define wglDXObjectAccessNV WGLEW_GET_FUN(__wglewDXObjectAccessNV) -#define wglDXOpenDeviceNV WGLEW_GET_FUN(__wglewDXOpenDeviceNV) -#define wglDXRegisterObjectNV WGLEW_GET_FUN(__wglewDXRegisterObjectNV) -#define wglDXSetResourceShareHandleNV WGLEW_GET_FUN(__wglewDXSetResourceShareHandleNV) -#define wglDXUnlockObjectsNV WGLEW_GET_FUN(__wglewDXUnlockObjectsNV) -#define wglDXUnregisterObjectNV WGLEW_GET_FUN(__wglewDXUnregisterObjectNV) - -#define WGLEW_NV_DX_interop WGLEW_GET_VAR(__WGLEW_NV_DX_interop) - -#endif /* WGL_NV_DX_interop */ - -/* --------------------------- WGL_NV_copy_image --------------------------- */ - -#ifndef WGL_NV_copy_image -#define WGL_NV_copy_image 1 - -typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); - -#define wglCopyImageSubDataNV WGLEW_GET_FUN(__wglewCopyImageSubDataNV) - -#define WGLEW_NV_copy_image WGLEW_GET_VAR(__WGLEW_NV_copy_image) - -#endif /* WGL_NV_copy_image */ - -/* -------------------------- WGL_NV_float_buffer -------------------------- */ - -#ifndef WGL_NV_float_buffer -#define WGL_NV_float_buffer 1 - -#define WGL_FLOAT_COMPONENTS_NV 0x20B0 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 -#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 -#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 -#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 -#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 - -#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer) - -#endif /* WGL_NV_float_buffer */ - -/* -------------------------- WGL_NV_gpu_affinity -------------------------- */ - -#ifndef WGL_NV_gpu_affinity -#define WGL_NV_gpu_affinity 1 - -#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 -#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 - -DECLARE_HANDLE(HGPUNV); -typedef struct _GPU_DEVICE { - DWORD cb; - CHAR DeviceName[32]; - CHAR DeviceString[128]; - DWORD Flags; - RECT rcVirtualScreen; -} GPU_DEVICE, *PGPU_DEVICE; - -typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); -typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); -typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); -typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); -typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); - -#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV) -#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV) -#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV) -#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV) -#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV) - -#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity) - -#endif /* WGL_NV_gpu_affinity */ - -/* ---------------------- WGL_NV_multisample_coverage ---------------------- */ - -#ifndef WGL_NV_multisample_coverage -#define WGL_NV_multisample_coverage 1 - -#define WGL_COVERAGE_SAMPLES_NV 0x2042 -#define WGL_COLOR_SAMPLES_NV 0x20B9 - -#define WGLEW_NV_multisample_coverage WGLEW_GET_VAR(__WGLEW_NV_multisample_coverage) - -#endif /* WGL_NV_multisample_coverage */ - -/* -------------------------- WGL_NV_present_video ------------------------- */ - -#ifndef WGL_NV_present_video -#define WGL_NV_present_video 1 - -#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 - -DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); - -typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList); -typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList); -typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue); - -#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV) -#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV) -#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV) - -#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video) - -#endif /* WGL_NV_present_video */ - -/* ---------------------- WGL_NV_render_depth_texture ---------------------- */ - -#ifndef WGL_NV_render_depth_texture -#define WGL_NV_render_depth_texture 1 - -#define WGL_NO_TEXTURE_ARB 0x2077 -#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 -#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 -#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 -#define WGL_DEPTH_COMPONENT_NV 0x20A7 - -#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture) - -#endif /* WGL_NV_render_depth_texture */ - -/* -------------------- WGL_NV_render_texture_rectangle -------------------- */ - -#ifndef WGL_NV_render_texture_rectangle -#define WGL_NV_render_texture_rectangle 1 - -#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 -#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 - -#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle) - -#endif /* WGL_NV_render_texture_rectangle */ - -/* --------------------------- WGL_NV_swap_group --------------------------- */ - -#ifndef WGL_NV_swap_group -#define WGL_NV_swap_group 1 - -typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); -typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); -typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count); -typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers); -typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group, GLuint *barrier); -typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); - -#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV) -#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV) -#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV) -#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV) -#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV) -#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV) - -#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group) - -#endif /* WGL_NV_swap_group */ - -/* ----------------------- WGL_NV_vertex_array_range ----------------------- */ - -#ifndef WGL_NV_vertex_array_range -#define WGL_NV_vertex_array_range 1 - -typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); -typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); - -#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV) -#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV) - -#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range) - -#endif /* WGL_NV_vertex_array_range */ - -/* -------------------------- WGL_NV_video_capture ------------------------- */ - -#ifndef WGL_NV_video_capture -#define WGL_NV_video_capture 1 - -#define WGL_UNIQUE_ID_NV 0x20CE -#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF - -DECLARE_HANDLE(HVIDEOINPUTDEVICENV); - -typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); -typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList); -typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); -typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue); -typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); - -#define wglBindVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewBindVideoCaptureDeviceNV) -#define wglEnumerateVideoCaptureDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoCaptureDevicesNV) -#define wglLockVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewLockVideoCaptureDeviceNV) -#define wglQueryVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewQueryVideoCaptureDeviceNV) -#define wglReleaseVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoCaptureDeviceNV) - -#define WGLEW_NV_video_capture WGLEW_GET_VAR(__WGLEW_NV_video_capture) - -#endif /* WGL_NV_video_capture */ - -/* -------------------------- WGL_NV_video_output -------------------------- */ - -#ifndef WGL_NV_video_output -#define WGL_NV_video_output 1 - -#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 -#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 -#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 -#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 -#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 -#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 -#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 -#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 -#define WGL_VIDEO_OUT_FRAME 0x20C8 -#define WGL_VIDEO_OUT_FIELD_1 0x20C9 -#define WGL_VIDEO_OUT_FIELD_2 0x20CA -#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB -#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC - -DECLARE_HANDLE(HPVIDEODEV); - -typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); -typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice); -typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); -typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); -typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); -typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock); - -#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV) -#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV) -#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV) -#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV) -#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV) -#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV) - -#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output) - -#endif /* WGL_NV_video_output */ - -/* -------------------------- WGL_OML_sync_control ------------------------- */ - -#ifndef WGL_OML_sync_control -#define WGL_OML_sync_control 1 - -typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator); -typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc); -typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); -typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); -typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc); -typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc); - -#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML) -#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML) -#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML) -#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML) -#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML) -#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML) - -#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control) - -#endif /* WGL_OML_sync_control */ - -/* ------------------------------------------------------------------------- */ - -#ifdef GLEW_MX -#define WGLEW_EXPORT -#else -#define WGLEW_EXPORT GLEWAPI -#endif /* GLEW_MX */ - -#ifdef GLEW_MX -struct WGLEWContextStruct -{ -#endif /* GLEW_MX */ - -WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; - -WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD; -WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD; -WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD; -WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD; -WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD; -WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD; -WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD; -WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD; -WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD; - -WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; -WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; -WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; -WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; - -WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; - -WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; - -WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; -WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; - -WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; -WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; -WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; -WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; -WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; - -WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; - -WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; -WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; -WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; - -WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; - -WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; - -WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; -WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; - -WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; -WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; -WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; -WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; -WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; - -WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; - -WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; -WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; - -WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; -WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; - -WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; -WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; -WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; -WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; - -WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; -WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; -WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; -WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; -WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; -WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; -WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; -WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; - -WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; -WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; -WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; -WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; - -WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; -WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; -WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; -WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; - -WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; -WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; -WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; -WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; - -WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV; -WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV; -WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV; -WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV; -WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV; -WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV; -WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV; -WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; - -WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; - -WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; -WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; -WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; -WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; -WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; - -WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; -WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; -WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; - -WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; -WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; -WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; -WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; -WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; -WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; - -WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; -WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; - -WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV; -WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV; - -WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; -WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; -WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; -WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; -WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; -WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; - -WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; -WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; -WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; -WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; -WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; -WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; -WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample; -WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control; -WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association; -WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region; -WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context; -WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile; -WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness; -WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string; -WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; -WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read; -WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample; -WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer; -WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format; -WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; -WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture; -WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; -WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; -WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile; -WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float; -WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table; -WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string; -WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; -WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read; -WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample; -WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer; -WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format; -WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; -WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control; -WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control; -WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma; -WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock; -WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer; -WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; -WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; -WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop; -WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image; -WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer; -WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity; -WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage; -WGLEW_EXPORT GLboolean __WGLEW_NV_present_video; -WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture; -WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; -WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group; -WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range; -WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture; -WGLEW_EXPORT GLboolean __WGLEW_NV_video_output; -WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; - -#ifdef GLEW_MX -}; /* WGLEWContextStruct */ -#endif /* GLEW_MX */ - -/* ------------------------------------------------------------------------- */ - -#ifdef GLEW_MX - -typedef struct WGLEWContextStruct WGLEWContext; -GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx); -GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name); - -#define wglewInit() wglewContextInit(wglewGetContext()) -#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x) - -#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x)) -#define WGLEW_GET_FUN(x) wglewGetContext()->x - -#else /* GLEW_MX */ - -#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x) -#define WGLEW_GET_FUN(x) x - -GLEWAPI GLboolean wglewIsSupported (const char* name); - -#endif /* GLEW_MX */ - -GLEWAPI GLboolean wglewGetExtension (const char* name); - -#ifdef __cplusplus -} -#endif - -#undef GLEWAPI - -#endif /* __wglew_h__ */ diff --git a/Code/Physics/Bullet Source/Glut/GL/wglext.h b/Code/Physics/Bullet Source/Glut/GL/wglext.h deleted file mode 100644 index 8c6192c2..00000000 --- a/Code/Physics/Bullet Source/Glut/GL/wglext.h +++ /dev/null @@ -1,466 +0,0 @@ -#ifndef __wglext_h_ -#define __wglext_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 1.1 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: This software was created using the -** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has -** not been independently verified as being compliant with the OpenGL(R) -** version 1.2.1 Specification. -*/ - -#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) -#define WIN32_LEAN_AND_MEAN 1 -#include -#endif - -#ifndef APIENTRY -#define APIENTRY -#endif - -/*************************************************************/ - -/* Header file version number */ -#define WGL_WGLEXT_VERSION 1 - -#ifndef WGL_ARB_buffer_region -#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 -#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 -#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 -#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 -#endif - -#ifndef WGL_ARB_extensions_string -#endif - -#ifndef WGL_ARB_pixel_format -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -#endif - -#ifndef WGL_ARB_make_current_read -#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 -#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 -#endif - -#ifndef WGL_ARB_pbuffer -#define WGL_DRAW_TO_PBUFFER_ARB 0x202D -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 -#endif - -#ifndef WGL_ARB_render_texture -#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 -#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 -#define WGL_TEXTURE_FORMAT_ARB 0x2072 -#define WGL_TEXTURE_TARGET_ARB 0x2073 -#define WGL_MIPMAP_TEXTURE_ARB 0x2074 -#define WGL_TEXTURE_RGB_ARB 0x2075 -#define WGL_TEXTURE_RGBA_ARB 0x2076 -#define WGL_NO_TEXTURE_ARB 0x2077 -#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 -#define WGL_TEXTURE_1D_ARB 0x2079 -#define WGL_TEXTURE_2D_ARB 0x207A -#define WGL_MIPMAP_LEVEL_ARB 0x207B -#define WGL_CUBE_MAP_FACE_ARB 0x207C -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 -#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 -#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 -#define WGL_FRONT_LEFT_ARB 0x2083 -#define WGL_FRONT_RIGHT_ARB 0x2084 -#define WGL_BACK_LEFT_ARB 0x2085 -#define WGL_BACK_RIGHT_ARB 0x2086 -#define WGL_AUX0_ARB 0x2087 -#define WGL_AUX1_ARB 0x2088 -#define WGL_AUX2_ARB 0x2089 -#define WGL_AUX3_ARB 0x208A -#define WGL_AUX4_ARB 0x208B -#define WGL_AUX5_ARB 0x208C -#define WGL_AUX6_ARB 0x208D -#define WGL_AUX7_ARB 0x208E -#define WGL_AUX8_ARB 0x208F -#define WGL_AUX9_ARB 0x2090 -#endif - -#ifndef WGL_EXT_make_current_read -#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 -#endif - -#ifndef WGL_EXT_pixel_format -#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 -#define WGL_DRAW_TO_WINDOW_EXT 0x2001 -#define WGL_DRAW_TO_BITMAP_EXT 0x2002 -#define WGL_ACCELERATION_EXT 0x2003 -#define WGL_NEED_PALETTE_EXT 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 -#define WGL_SWAP_METHOD_EXT 0x2007 -#define WGL_NUMBER_OVERLAYS_EXT 0x2008 -#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 -#define WGL_TRANSPARENT_EXT 0x200A -#define WGL_TRANSPARENT_VALUE_EXT 0x200B -#define WGL_SHARE_DEPTH_EXT 0x200C -#define WGL_SHARE_STENCIL_EXT 0x200D -#define WGL_SHARE_ACCUM_EXT 0x200E -#define WGL_SUPPORT_GDI_EXT 0x200F -#define WGL_SUPPORT_OPENGL_EXT 0x2010 -#define WGL_DOUBLE_BUFFER_EXT 0x2011 -#define WGL_STEREO_EXT 0x2012 -#define WGL_PIXEL_TYPE_EXT 0x2013 -#define WGL_COLOR_BITS_EXT 0x2014 -#define WGL_RED_BITS_EXT 0x2015 -#define WGL_RED_SHIFT_EXT 0x2016 -#define WGL_GREEN_BITS_EXT 0x2017 -#define WGL_GREEN_SHIFT_EXT 0x2018 -#define WGL_BLUE_BITS_EXT 0x2019 -#define WGL_BLUE_SHIFT_EXT 0x201A -#define WGL_ALPHA_BITS_EXT 0x201B -#define WGL_ALPHA_SHIFT_EXT 0x201C -#define WGL_ACCUM_BITS_EXT 0x201D -#define WGL_ACCUM_RED_BITS_EXT 0x201E -#define WGL_ACCUM_GREEN_BITS_EXT 0x201F -#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 -#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 -#define WGL_DEPTH_BITS_EXT 0x2022 -#define WGL_STENCIL_BITS_EXT 0x2023 -#define WGL_AUX_BUFFERS_EXT 0x2024 -#define WGL_NO_ACCELERATION_EXT 0x2025 -#define WGL_GENERIC_ACCELERATION_EXT 0x2026 -#define WGL_FULL_ACCELERATION_EXT 0x2027 -#define WGL_SWAP_EXCHANGE_EXT 0x2028 -#define WGL_SWAP_COPY_EXT 0x2029 -#define WGL_SWAP_UNDEFINED_EXT 0x202A -#define WGL_TYPE_RGBA_EXT 0x202B -#define WGL_TYPE_COLORINDEX_EXT 0x202C -#endif - -#ifndef WGL_EXT_pbuffer -#define WGL_DRAW_TO_PBUFFER_EXT 0x202D -#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E -#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 -#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 -#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 -#define WGL_PBUFFER_LARGEST_EXT 0x2033 -#define WGL_PBUFFER_WIDTH_EXT 0x2034 -#define WGL_PBUFFER_HEIGHT_EXT 0x2035 -#endif - -#ifndef WGL_EXT_depth_float -#define WGL_DEPTH_FLOAT_EXT 0x2040 -#endif - -#ifndef WGL_NV_render_texture_rectangle -#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 -#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 -#endif - -#ifndef WGL_NV_render_depth_texture -#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 -#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 -#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 -#define WGL_DEPTH_COMPONENT_NV 0x20A7 -#endif - -#ifndef WGL_3DFX_multisample -#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 -#define WGL_SAMPLES_3DFX 0x2061 -#endif - -#ifndef WGL_EXT_multisample -#define WGL_SAMPLE_BUFFERS_EXT 0x2041 -#define WGL_SAMPLES_EXT 0x2042 -#endif - -#ifndef WGL_I3D_unknown_genlock_extension_name -#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 -#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 -#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 -#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 -#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 -#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 -#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A -#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B -#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C -#endif - -#ifndef WGL_I3D_unknown_gamma_extension_name -#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E -#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F -#endif - -#ifndef WGL_I3D_unknown_digital_video_cursor_extension_name -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 -#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 -#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 -#endif - - -/*************************************************************/ - -#ifndef WGL_ARB_pbuffer -DECLARE_HANDLE(HPBUFFERARB); -#endif -#ifndef WGL_EXT_pbuffer -DECLARE_HANDLE(HPBUFFEREXT); -#endif - -#ifndef WGL_ARB_buffer_region -#define WGL_ARB_buffer_region 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); -extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); -extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); -extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); -typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); -typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); -typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); -#endif - -#ifndef WGL_ARB_extensions_string -#define WGL_ARB_extensions_string 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern const char * WINAPI wglGetExtensionsStringARB (HDC); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); -#endif - -#ifndef WGL_ARB_pixel_format -#define WGL_ARB_pixel_format 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); -extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); -extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); -typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -#endif - -#ifndef WGL_ARB_make_current_read -#define WGL_ARB_make_current_read 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); -extern HDC WINAPI wglGetCurrentReadDCARB (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); -typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); -#endif - -#ifndef WGL_ARB_pbuffer -#define WGL_ARB_pbuffer 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); -extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); -extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); -extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); -extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); -typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); -typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); -typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); -typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); -#endif - -#ifndef WGL_EXT_display_color_table -#define WGL_EXT_display_color_table 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); -extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); -extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); -extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); -typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); -typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); -typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); -#endif - -#ifndef WGL_EXT_extensions_string -#define WGL_EXT_extensions_string 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern const char * WINAPI wglGetExtensionsStringEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); -#endif - -#ifndef WGL_EXT_make_current_read -#define WGL_EXT_make_current_read 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); -extern HDC WINAPI wglGetCurrentReadDCEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); -typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); -#endif - -#ifndef WGL_EXT_pbuffer -#define WGL_EXT_pbuffer 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); -extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); -extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); -extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); -extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); -typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); -typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); -typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); -typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); -#endif - -#ifndef WGL_EXT_pixel_format -#define WGL_EXT_pixel_format 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); -extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); -extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); -typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -#endif - -#ifndef WGL_EXT_swap_control -#define WGL_EXT_swap_control 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglSwapIntervalEXT (int); -extern int WINAPI wglGetSwapIntervalEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); -typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); -#endif - -#ifndef WGL_WGL_EXT_depth_float -#define WGL_WGL_EXT_depth_float 1 -#endif - -#ifndef WGL_WGL_3DFX_multisample -#define WGL_WGL_3DFX_multisample 1 -#endif - -#ifndef WGL_WGL_EXT_multisample -#define WGL_WGL_EXT_multisample 1 -#endif - -/* added by Cass -- but this should already be in here! */ -#ifndef WGL_NV_allocate_memory -#define WGL_NV_allocate_memory 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern void * wglAllocateMemoryNV(int size, float readfreq, float writefreq, float priority); -extern void wglFreeMemoryNV(void * pointer); -#endif -typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); -typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); -#endif - -/* WGL_ARB_render_texture */ -#ifndef WGL_ARB_render_texture -#define WGL_ARB_render_texture 1 -typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); -typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); -typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList); -#endif - -#ifndef WGL_NV_render_texture_rectangle -#define WGL_NV_render_texture_rectangle 1 -#endif - -#ifndef WGL_NV_render_depth_texture -#define WGL_NV_render_depth_texture 1 -#endif - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/Code/Physics/Bullet Source/Glut/btGlutInclude.h b/Code/Physics/Bullet Source/Glut/btGlutInclude.h deleted file mode 100644 index d79cb565..00000000 --- a/Code/Physics/Bullet Source/Glut/btGlutInclude.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_GLUT_INCLUDE_H -#define BT_GLUT_INCLUDE_H - - -#ifdef _WIN32//for glut.h -#include -#endif - -//think different -#if defined(__APPLE__) && !defined (VMDMESA) -#include -#include -#include -#include -#else - - -#ifdef _WINDOWS -#include -#include -#include -#else -#include -#include -#endif //_WINDOWS -#endif //APPLE - -#endif //BT_GLUT_INCLUDE_H diff --git a/Code/Physics/Bullet Source/INSTALL b/Code/Physics/Bullet Source/INSTALL deleted file mode 100644 index 0f42fb52..00000000 --- a/Code/Physics/Bullet Source/INSTALL +++ /dev/null @@ -1,111 +0,0 @@ -Bullet Collision Detection and Physics Library - -See also http://bulletphysics.org/mediawiki-1.5.8/index.php/Creating_a_project_from_scratch - -** Windows Compilation ** - - Open the Microsoft Visual Studio solution in msvc/20xx/BULLET_PHYSICS.sln - -Alternatively, use CMake to autogenerate a build system for Windows: - - - Download/install CMake from www.cmake.org or package manager - - Use cmake-gui or - - List available build systems by running 'cmake' in the Bullet root folder - - Use cmake-gui - - Create a build system using the -G option for example: - - cmake . -G "Visual Studio 9 2008" or - cmake . -G "Visual Studio 9 2008 Win64" - - -** Linux Compilation ** - - - Download/install CMake from www.cmake.org or package manager - CMake is like autoconf in that it will create build scripts which are then - used for the actual compilation - - - List available build systems by running 'cmake' in the Bullet root folder - - Create a build system using the -G option for example: - - cmake . -G "Unix Makefiles" - - - There are some options for cmake builds: - BUILD_SHARED_LIBS: default 'OFF', set to 'ON' to build .so libraries - BUILD_EXTRAS: default 'ON', compiles additional libraries in 'Extras' - BUILD_DEMOS: default 'ON', compiles applications found in 'Demos' - CMAKE_INSTALL_PREFIX: default '/usr/local', the installation path. - CMAKE_INSTALL_RPATH: if you install outside a standard ld search path, - then you should set this to the installation lib path. - CMAKE_BUILD_TYPE: default 'Release', can include debug symbols with - either 'Debug' or 'RelWithDebInfo'. - Other options may be discovered by 'cmake --help-variable-list' and - 'cmake --help-variable OPTION' - - - Run 'cmake' with desired options of the form -DOPTION=VALUE - By default this will create the usual Makefile build system, but CMake can - also produce Eclipse or KDevelop project files. See 'cmake --help' to see - what "generators" are available in your environment, selected via '-G'. - For example: - cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RelWithDebugInfo - - - Assuming using the default Makefile output from cmake, run 'make' to - build, and then 'make install' if you wish to install. - - -** Mac OS X Compilation ** - - - Download/install CMake from www.cmake.org or package manager - CMake is like autoconf in that it will create build scripts which are then - used for the actual compilation - - - List available build systems by running 'cmake' in the Bullet root folder - - Create a build system using the -G option for example: - - cmake . -G Xcode - cmake . -G "Unix Makefiles" - - - There are some options for cmake builds: - BUILD_SHARED_LIBS: default 'OFF', set to 'ON' to build .dylib libraries - BUILD_EXTRAS: default 'ON', compiles additional libraries in 'Extras' - BUILD_DEMOS: default 'ON', compiles applications found in 'Demos' - CMAKE_INSTALL_PREFIX: default '/usr/local', the installation path. - CMAKE_INSTALL_NAME_DIR: if you install outside a standard ld search - path, then you should set this to the installation lib/framework path. - CMAKE_OSX_ARCHITECTURES: defaults to the native architecture, but can be - set to a semicolon separated list for fat binaries, e.g. ppc;i386;x86_64 - CMAKE_BUILD_TYPE: default 'Release', can include debug symbols with - either 'Debug' or 'RelWithDebInfo'. - - To build framework bundles: - FRAMEWORK: default 'OFF', also requires 'BUILD_SHARED_LIBS' set ON - If both FRAMEWORK and BUILD_SHARED_LIBS are set, will create - OS X style Framework Bundles which can be placed in - linked via the -framework gcc argument or drag into Xcode projects. - (If not framework, then UNIX style 'include' and 'lib' will be produced) - - Other options may be discovered by 'cmake --help-variable-list' and - 'cmake --help-variable OPTION' - - - Run 'cmake' with desired options of the form -DOPTION=VALUE - By default this will create the usual Makefile build system, but CMake can - also produce Eclipse or KDevelop project files. See 'cmake --help' to see - what "generators" are available in your environment, selected via '-G'. - For example: - cmake -DBUILD_SHARED_LIBS=ON -DFRAMEWORK=ON \ - -DCMAKE_INSTALL_PREFIX=/Library/Frameworks \ - -DCMAKE_INSTALL_NAME_DIR=/Library/Frameworks \ - -DCMAKE_OSX_ARCHITECTURES='ppc;i386;x86_64' \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo - - - Assuming using the default Makefile output from cmake, run 'make' to build - and then 'make install'. - - -** Alternative Mac OS X and Linux via autoconf/make ** - - at the command line: - ./autogen.sh - ./configure - make - - -** For more help, visit http://www.bulletphysics.org ** diff --git a/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt b/Code/Physics/Bullet Source/LinearMath/CMakeLists.txt similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt rename to Code/Physics/Bullet Source/LinearMath/CMakeLists.txt diff --git a/Code/Physics/Bullet Source/src/LinearMath/btAabbUtil2.h b/Code/Physics/Bullet Source/LinearMath/btAabbUtil2.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btAabbUtil2.h rename to Code/Physics/Bullet Source/LinearMath/btAabbUtil2.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.cpp b/Code/Physics/Bullet Source/LinearMath/btAlignedAllocator.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.cpp rename to Code/Physics/Bullet Source/LinearMath/btAlignedAllocator.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.h b/Code/Physics/Bullet Source/LinearMath/btAlignedAllocator.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btAlignedAllocator.h rename to Code/Physics/Bullet Source/LinearMath/btAlignedAllocator.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btAlignedObjectArray.h b/Code/Physics/Bullet Source/LinearMath/btAlignedObjectArray.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btAlignedObjectArray.h rename to Code/Physics/Bullet Source/LinearMath/btAlignedObjectArray.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btConvexHull.cpp b/Code/Physics/Bullet Source/LinearMath/btConvexHull.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btConvexHull.cpp rename to Code/Physics/Bullet Source/LinearMath/btConvexHull.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btConvexHull.h b/Code/Physics/Bullet Source/LinearMath/btConvexHull.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btConvexHull.h rename to Code/Physics/Bullet Source/LinearMath/btConvexHull.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.cpp b/Code/Physics/Bullet Source/LinearMath/btConvexHullComputer.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.cpp rename to Code/Physics/Bullet Source/LinearMath/btConvexHullComputer.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.h b/Code/Physics/Bullet Source/LinearMath/btConvexHullComputer.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btConvexHullComputer.h rename to Code/Physics/Bullet Source/LinearMath/btConvexHullComputer.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btDefaultMotionState.h b/Code/Physics/Bullet Source/LinearMath/btDefaultMotionState.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btDefaultMotionState.h rename to Code/Physics/Bullet Source/LinearMath/btDefaultMotionState.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.cpp b/Code/Physics/Bullet Source/LinearMath/btGeometryUtil.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.cpp rename to Code/Physics/Bullet Source/LinearMath/btGeometryUtil.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.h b/Code/Physics/Bullet Source/LinearMath/btGeometryUtil.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btGeometryUtil.h rename to Code/Physics/Bullet Source/LinearMath/btGeometryUtil.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btGrahamScan2dConvexHull.h b/Code/Physics/Bullet Source/LinearMath/btGrahamScan2dConvexHull.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btGrahamScan2dConvexHull.h rename to Code/Physics/Bullet Source/LinearMath/btGrahamScan2dConvexHull.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btHashMap.h b/Code/Physics/Bullet Source/LinearMath/btHashMap.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btHashMap.h rename to Code/Physics/Bullet Source/LinearMath/btHashMap.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btIDebugDraw.h b/Code/Physics/Bullet Source/LinearMath/btIDebugDraw.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btIDebugDraw.h rename to Code/Physics/Bullet Source/LinearMath/btIDebugDraw.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btList.h b/Code/Physics/Bullet Source/LinearMath/btList.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btList.h rename to Code/Physics/Bullet Source/LinearMath/btList.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btMatrix3x3.h b/Code/Physics/Bullet Source/LinearMath/btMatrix3x3.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btMatrix3x3.h rename to Code/Physics/Bullet Source/LinearMath/btMatrix3x3.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btMatrixX.h b/Code/Physics/Bullet Source/LinearMath/btMatrixX.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btMatrixX.h rename to Code/Physics/Bullet Source/LinearMath/btMatrixX.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btMinMax.h b/Code/Physics/Bullet Source/LinearMath/btMinMax.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btMinMax.h rename to Code/Physics/Bullet Source/LinearMath/btMinMax.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btMotionState.h b/Code/Physics/Bullet Source/LinearMath/btMotionState.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btMotionState.h rename to Code/Physics/Bullet Source/LinearMath/btMotionState.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.cpp b/Code/Physics/Bullet Source/LinearMath/btPolarDecomposition.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.cpp rename to Code/Physics/Bullet Source/LinearMath/btPolarDecomposition.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.h b/Code/Physics/Bullet Source/LinearMath/btPolarDecomposition.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btPolarDecomposition.h rename to Code/Physics/Bullet Source/LinearMath/btPolarDecomposition.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btPoolAllocator.h b/Code/Physics/Bullet Source/LinearMath/btPoolAllocator.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btPoolAllocator.h rename to Code/Physics/Bullet Source/LinearMath/btPoolAllocator.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btQuadWord.h b/Code/Physics/Bullet Source/LinearMath/btQuadWord.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btQuadWord.h rename to Code/Physics/Bullet Source/LinearMath/btQuadWord.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btQuaternion.h b/Code/Physics/Bullet Source/LinearMath/btQuaternion.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btQuaternion.h rename to Code/Physics/Bullet Source/LinearMath/btQuaternion.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btQuickprof.cpp b/Code/Physics/Bullet Source/LinearMath/btQuickprof.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btQuickprof.cpp rename to Code/Physics/Bullet Source/LinearMath/btQuickprof.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btQuickprof.h b/Code/Physics/Bullet Source/LinearMath/btQuickprof.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btQuickprof.h rename to Code/Physics/Bullet Source/LinearMath/btQuickprof.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btRandom.h b/Code/Physics/Bullet Source/LinearMath/btRandom.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btRandom.h rename to Code/Physics/Bullet Source/LinearMath/btRandom.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btScalar.h b/Code/Physics/Bullet Source/LinearMath/btScalar.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btScalar.h rename to Code/Physics/Bullet Source/LinearMath/btScalar.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btSerializer.cpp b/Code/Physics/Bullet Source/LinearMath/btSerializer.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btSerializer.cpp rename to Code/Physics/Bullet Source/LinearMath/btSerializer.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btSerializer.h b/Code/Physics/Bullet Source/LinearMath/btSerializer.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btSerializer.h rename to Code/Physics/Bullet Source/LinearMath/btSerializer.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btStackAlloc.h b/Code/Physics/Bullet Source/LinearMath/btStackAlloc.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btStackAlloc.h rename to Code/Physics/Bullet Source/LinearMath/btStackAlloc.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btTransform.h b/Code/Physics/Bullet Source/LinearMath/btTransform.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btTransform.h rename to Code/Physics/Bullet Source/LinearMath/btTransform.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btTransformUtil.h b/Code/Physics/Bullet Source/LinearMath/btTransformUtil.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btTransformUtil.h rename to Code/Physics/Bullet Source/LinearMath/btTransformUtil.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/btVector3.cpp b/Code/Physics/Bullet Source/LinearMath/btVector3.cpp similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btVector3.cpp rename to Code/Physics/Bullet Source/LinearMath/btVector3.cpp diff --git a/Code/Physics/Bullet Source/src/LinearMath/btVector3.h b/Code/Physics/Bullet Source/LinearMath/btVector3.h similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/btVector3.h rename to Code/Physics/Bullet Source/LinearMath/btVector3.h diff --git a/Code/Physics/Bullet Source/src/LinearMath/premake4.lua b/Code/Physics/Bullet Source/LinearMath/premake4.lua similarity index 100% rename from Code/Physics/Bullet Source/src/LinearMath/premake4.lua rename to Code/Physics/Bullet Source/LinearMath/premake4.lua diff --git a/Code/Physics/Bullet Source/Makefile.am b/Code/Physics/Bullet Source/Makefile.am deleted file mode 100644 index a9b97a8e..00000000 --- a/Code/Physics/Bullet Source/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -if CONDITIONAL_BUILD_DEMOS -SUBDIRS=src Extras Demos -else -SUBDIRS=src -endif -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = bullet.pc diff --git a/Code/Physics/Bullet Source/NEWS b/Code/Physics/Bullet Source/NEWS deleted file mode 100644 index dec9f0fd..00000000 --- a/Code/Physics/Bullet Source/NEWS +++ /dev/null @@ -1,5 +0,0 @@ - -For news, visit the Bullet Physics forums at -http://www.bulletphysics.org and http://bullet.googlecode.com - - diff --git a/Code/Physics/Bullet Source/README b/Code/Physics/Bullet Source/README deleted file mode 100644 index 1eda762c..00000000 --- a/Code/Physics/Bullet Source/README +++ /dev/null @@ -1,6 +0,0 @@ - -Bullet is a 3D Collision Detection and Rigid Body Dynamics Library for games and animation. -Free for commercial use, including Playstation 3, open source under the ZLib License. - -See the Bullet_User_Manual.pdf for more info and visit the Bullet Physics Forum at -http://bulletphysics.org diff --git a/Code/Physics/Bullet Source/RELEASING.TXT b/Code/Physics/Bullet Source/RELEASING.TXT deleted file mode 100644 index 49d6ba40..00000000 --- a/Code/Physics/Bullet Source/RELEASING.TXT +++ /dev/null @@ -1,36 +0,0 @@ -This document details the steps necessary to package a release of Bullet. - -1) Preparing for release: - -update VERSION in several places (/VERSION file, /CMakeLists.txt, /configure.ac, /src/LinearMath/btScalar.h, /src/LinearMath/btSerializer.h around line 441) -re-generate serialization structures, if they changed (/src/LinearMath/btSerializer.cpp using makesdna) -update ChangeLog with larger/important changes -regenerate MSVC project files using build/vs_all.bat -create a Subversion tag revision in bullet.googlecode.com/svn/tags/bullet- - -2) Generating the release .zip: -Do an SVN export on a Windows machine into the directory: bullet-X.YY -prepare a zip file containing the directory - -3) Generating the release .tar.gz: -Do an SVN export on a Unix machine into the directory: bullet-X.YY -prepare a .tar.gz file containing the directory - -4) Uploading release to google code: - -Google Code Bullet downloads URL: http://code.google.com/p/bullet/downloads/list - -Title of release should follow this guide line: Bullet Physics SDK (revision) - -It is better to upload the .tar.gz before the .zip so that the .zip appears first in the list - -If the release is an Alpha/Beta or RC the tags should be: Type-Source, OpSys-ALL -If the release is a final release the tags should be: Type-Source, OpSys-ALL, Featured - -5) Obsoleting old releases - -Edit the tags on old releases and add the 'Deprecated' tag - -6) Announcing final releases: - -Final release announcements are done here: http://bulletphysics.com/Bullet/phpBB3/viewforum.php?f=18 diff --git a/Code/Physics/Bullet Source/UseBullet.cmake b/Code/Physics/Bullet Source/UseBullet.cmake deleted file mode 100644 index 5ed94874..00000000 --- a/Code/Physics/Bullet Source/UseBullet.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -*- cmake -*- -# -# UseBullet.cmake -# - - -add_definitions ( ${BULLET_DEFINITIONS} ) -include_directories ( ${BULLET_INCLUDE_DIRS} ) -link_directories ( ${BULLET_LIBRARY_DIRS} ) - diff --git a/Code/Physics/Bullet Source/VERSION b/Code/Physics/Bullet Source/VERSION deleted file mode 100644 index 90c00fa3..00000000 --- a/Code/Physics/Bullet Source/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.82 diff --git a/Code/Physics/Bullet Source/acinclude.m4 b/Code/Physics/Bullet Source/acinclude.m4 deleted file mode 100644 index 0505895c..00000000 --- a/Code/Physics/Bullet Source/acinclude.m4 +++ /dev/null @@ -1,3054 +0,0 @@ -# checkbuild.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_SPLIT_TUPLE(TUPLE, OUTPUT-VARIABLES) -# Split a build-tuple into its component parts. A build tuple is -# constructed by CS_CREATE_TUPLE() and is comprised of compiler flags, -# linker flags, and library references. OUTPUT-VARIABLES is a -# comma-delimited list of shell variables which should receive the -# extracted compiler flags, linker flags, and library references, -# respectively. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_SPLIT_TUPLE], - [CS_SPLIT([$1], [cs_dummy,$2], [@]) - m4_map([_CS_SPLIT_TUPLE], [$2])]) - -AC_DEFUN([_CS_SPLIT_TUPLE], - [$1=`echo $$1 | sed 'y%@%:@% %'` - ]) - - - -#------------------------------------------------------------------------------ -# CS_CREATE_TUPLE([CFLAGS], [LFLAGS], [LIBS]) -# Construct a build-tuple which is comprised of compiler flags, linker -# flags, and library references. Build tuples are encoded so as to -# preserve whitespace in each component. This makes it possible for -# macros (such as CS_BUILD_IFELSE) which employ build tuples to accept -# whitespace-delimited lists of tuples, and for shell "for" statements to -# iterate over tuple lists without compromising whitespace embedded -# within individual flags or library references. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CREATE_TUPLE], [`echo @$1@$2@$3 | sed 'y% %@%:@%'`]) - - - -#------------------------------------------------------------------------------ -# CS_LANG_CFLAGS -# Return the literal string CFLAGS if the current language is C. Return -# the literal string CXXFLAGS if the current language is C++. Generic -# compiler test macros which need to modify or save the compiler flags -# can invoke this macro to get the name of the compiler flags environment -# variable (either CFLAGS or CXXFLAGS) depending upon the current -# language. For example: -# CS_LANG_CFLAGS="$CS_LANG_CFLAGS -Wall" -# With C, this expands to: -# CFLAGS="$CFLAGS -Wall" -# With C++, it expands to: -# CXXFLAGS="$CXXFLAGS -Wall" -#------------------------------------------------------------------------------ -AC_DEFUN([CS_LANG_CFLAGS], [AC_LANG_CASE([C], [CFLAGS], [C++], [CXXFLAGS])]) - - - -#------------------------------------------------------------------------------ -# CS_BUILD_IFELSE([PROGRAM], [FLAGS], [LANGUAGE], [ACTION-IF-BUILT], -# [ACTION-IF-NOT-BUILT], [OTHER-CFLAGS], [OTHER-LFLAGS], -# [OTHER-LIBS], [INHIBIT-OTHER-FLAGS], [ERROR-REGEX]) -# Try building a program using the supplied compiler flags, linker flags, -# and library references. PROGRAM is typically a program composed via -# AC_LANG_PROGRAM(). PROGRAM may be omitted if you are interested only -# in learning if the compiler or linker respects certain flags. LANGUAGE -# is typically either C or C++ and specifies which compiler to use for -# the test. If LANGUAGE is omitted, C is used. FLAGS is a whitespace -# delimited list of build tuples. Tuples are created with -# CS_CREATE_TUPLE() and are composed of up to three elements each. The -# first element represents compiler flags, the second linker flags, and -# the third libraries used when linking the program. Each tuple from -# FLAGS is attempted in order. If you want a build attempted with no -# special flags prior to builds with specialized flags, create an empty -# tuple with CS_CREATE_TUPLE() at the start of the FLAGS list. If the -# build is successful, then the shell variables cs_build_ok is set to -# "yes", cs_build_cflags, cs_build_lflags, and cs_build_libs are set to -# the tuple elements which resulted in the successful build, and -# ACTION-IF-BUILT is invoked. Upon successful build, no further tuples -# are consulted. If no tuple results in a successful build, then -# cs_build_ok is set to "no" and ACTION-IF-NOT-BUILT is invoked. -# OTHER-CFLAGS, OTHER-LFLAGS, and OTHER-LIBS specify additional compiler -# flags, linker flags, and libraries which should be used with each tuple -# build attempt. Upon successful build, these additional flags are also -# reflected in the variables cs_build_cflags, cs_build_lflags, and -# cs_build_libs unless INHIBIT-OTHER-FLAGS is a non-empty string. The -# optional ERROR-REGEX places an additional constraint upon the build -# check. If specified, ERROR-REGEX, which is a standard `grep' regular -# expression, is applied to output captured from the compiler and linker. -# If ERROR-REGEX matches, then the build is deemed a failure, and -# cs_build_ok is set to "no". This facility is useful for broken build -# tools which emit an error message yet still return success as a result. -# In such cases, it should be possible to detect the failure by scanning -# the tools' output. -# -# IMPLEMENTATION NOTES -# -# In Autoconf 2.57 and earlier, AC_LINK_IFELSE() invokes AC_TRY_EVAL(), -# which does not provide access to the captured output. To work around -# this limitation, we temporarily re-define AC_TRY_EVAL() as -# _AC_EVAL_STDERR(), which leaves the captured output in conftest.err -# (which we must also delete). In Autoconf 2.58, however, -# AC_LINK_IFELSE() instead already invokes _AC_EVAL_STDERR() on our -# behalf, however we must be careful to apply ERROR-REGEX within the -# invocation AC_LINK_IFELSE(), since AC_LINK_IFELSE() deletes -# conftest.err before it returns. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_BUILD_IFELSE], - [AC_LANG_PUSH(m4_default([$3],[C])) - cs_cflags_save="$CS_LANG_CFLAGS" - cs_lflags_save="$LDFLAGS" - cs_libs_save="$LIBS" - cs_build_ok=no - m4_ifval([$10], [m4_pushdef([AC_TRY_EVAL], [_AC_EVAL_STDERR]($$[1]))]) - - for cs_build_item in m4_default([$2],[CS_CREATE_TUPLE()]) - do - CS_SPLIT_TUPLE( - [$cs_build_item],[cs_cflags_test,cs_lflags_test,cs_libs_test]) - CS_LANG_CFLAGS="$cs_cflags_test $6 $cs_cflags_save" - LDFLAGS="$cs_lflags_test $7 $cs_lflags_save" - LIBS="$cs_libs_test $8 $cs_libs_save" - AC_LINK_IFELSE(m4_default([$1], [AC_LANG_PROGRAM([],[])]), - [m4_ifval([$10], - [AS_IF([AC_TRY_COMMAND( - [grep "AS_ESCAPE([$10])" conftest.err >/dev/null 2>&1])], - [cs_build_ok=no], [cs_build_ok=yes])], - [cs_build_ok=yes])]) - AS_IF([test $cs_build_ok = yes], [break]) - done - - m4_ifval([$10], [m4_popdef([AC_TRY_EVAL]) rm -f conftest.err]) - CS_LANG_CFLAGS=$cs_cflags_save - LDFLAGS=$cs_lflags_save - LIBS=$cs_libs_save - AC_LANG_POP(m4_default([$3],[C])) - - AS_IF([test $cs_build_ok = yes], - [cs_build_cflags=CS_TRIM([$cs_cflags_test[]m4_ifval([$9],[],[ $6])]) - cs_build_lflags=CS_TRIM([$cs_lflags_test[]m4_ifval([$9],[],[ $7])]) - cs_build_libs=CS_TRIM([$cs_libs_test[]m4_ifval([$9],[],[ $8])]) - $4], - [$5])]) - - - -#------------------------------------------------------------------------------ -# CS_CHECK_BUILD(MESSAGE, CACHE-VAR, [PROGRAM], [FLAGS], [LANGUAGE], -# [ACTION-IF-BUILT], [ACTION-IF-NOT-BUILT], [IGNORE-CACHE], -# [OTHER-CFLAGS], [OTHER-LFLAGS], [OTHER-LIBS], -# [INHIBIT-OTHER-FLAGS], [ERROR-REGEX]) -# Like CS_BUILD_IFELSE() but also prints "checking" and result messages, -# and optionally respects the cache. Sets CACHE-VAR to "yes" upon -# success, else "no" upon failure. Additionally, sets CACHE-VAR_cflags, -# CACHE-VAR_lflags, and CACHE-VAR_libs to the values which resulted in a -# successful build. If IGNORE-CACHE is "yes", then the cache variables -# are ignored upon entry to this macro, however they are still set to -# appropriate values upon exit. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_BUILD], - [AS_IF([test "$8" != yes], - [AC_CACHE_CHECK([$1], [$2], - [CS_BUILD_IFELSE([$3], [$4], [$5], - [$2=yes - $2_cflags=$cs_build_cflags - $2_lflags=$cs_build_lflags - $2_libs=$cs_build_libs], - [$2=no], [$9], [$10], [$11], [$12], [$13])])], - [AC_MSG_CHECKING([$1]) - CS_BUILD_IFELSE([$3], [$4], [$5], - [$2=yes - $2_cflags=$cs_build_cflags - $2_lflags=$cs_build_lflags - $2_libs=$cs_build_libs], - [$2=no], [$9], [$10], [$11], [$12], [$13]) - AC_MSG_RESULT([$$2])]) - AS_IF([test $$2 = yes], [$6], - [$2_cflags='' - $2_lflags='' - $2_libs='' - $7])]) - - - -#------------------------------------------------------------------------------ -# CS_CHECK_BUILD_FLAGS(MESSAGE, CACHE-VAR, FLAGS, [LANGUAGE], -# [ACTION-IF-RECOGNIZED], [ACTION-IF-NOT-RECOGNIZED], -# [OTHER-CFLAGS], [OTHER-LFLAGS], [OTHER-LIBS], -# [ERROR-REGEX]) -# Like CS_CHECK_BUILD(), but checks only if the compiler or linker -# recognizes a command-line option or options. MESSAGE is the "checking" -# message. CACHE-VAR is the shell cache variable which receives the flag -# or flags recognized by the compiler or linker. FLAGS is a -# whitespace-delimited list of build tuples created with -# CS_CREATE_TUPLE(). Each tuple from FLAGS is attempted in order until -# one is found which is recognized by the compiler. After that, no -# further flags are checked. LANGUAGE is typically either C or C++ and -# specifies which compiler to use for the test. If LANGUAGE is omitted, -# C is used. If a command-line option is recognized, then CACHE-VAR is -# set to the composite value of $cs_build_cflags, $cs_build_lflags, and -# $cs_build_libs of the FLAGS element which succeeded (not including the -# "other" flags) and ACTION-IF-RECOGNIZED is invoked. If no options are -# recognized, then CACHE-VAR is set to the empty string, and -# ACTION-IF-NOT-RECOGNIZED is invoked. As a convenience, in case -# comparing CACHE-VAR against the empty string to test for failure is -# undesirable, a second variable named CACHE-VAR_ok is set to the literal -# "no" upon failure, and to the same value as CACHE-VAR upon success. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_BUILD_FLAGS], - [AC_CACHE_CHECK([$1], [$2_ok], - [CS_BUILD_IFELSE([], [$3], [$4], - [$2=CS_TRIM([$cs_build_cflags $cs_build_lflags $cs_build_libs]) - $2_ok="$$2"], - [$2='' - $2_ok=no], [$7], [$8], [$9], [Y], [$10])]) - AS_IF([test "$$2_ok" != no], [$5], [$6])]) -#============================================================================== -# Copyright (C)2003-2006 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_COMMON_TOOLS_LINK -# Checks for common tools related to linking. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_COMMON_TOOLS_LINK], - [ - # The default RANLIB in Jambase is wrong on some platforms, and is also - # unsuitable during cross-compilation, so we set the value unconditionally - # (sixth argument of CS_EMIT_BUILD_PROPERTY). - AC_PROG_RANLIB - CS_EMIT_BUILD_PROPERTY([RANLIB], [$RANLIB], [], [], [], [Y]) - - CS_CHECK_TOOLS([DLLTOOL], [dlltool]) - CS_EMIT_BUILD_PROPERTY([CMD.DLLTOOL], [$DLLTOOL]) - - CS_CHECK_TOOLS([DLLWRAP], [dllwrap]) - CS_EMIT_BUILD_PROPERTY([CMD.DLLWRAP], [$DLLWRAP]) - - CS_CHECK_TOOLS([WINDRES], [windres]) - CS_EMIT_BUILD_PROPERTY([CMD.WINDRES], [$WINDRES]) - - CS_CHECK_TOOLS([STRINGS], [strings]) - CS_EMIT_BUILD_PROPERTY([CMD.STRINGS], [$STRINGS]) - - CS_CHECK_TOOLS([OBJCOPY], [objcopy]) - CS_EMIT_BUILD_PROPERTY([CMD.OBJCOPY], [$OBJCOPY]) - - CS_CHECK_LIBTOOL - CS_EMIT_BUILD_PROPERTY([LIBTOOL], [$LIBTOOL]) - CS_EMIT_BUILD_PROPERTY([APPLE_LIBTOOL], [$APPLE_LIBTOOL]) - ]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_COMMON_TOOLS_BASIC -# Checks for basic tools for building things. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_COMMON_TOOLS_BASIC], - [CS_CHECK_MKDIR - CS_EMIT_BUILD_PROPERTY([CMD.MKDIR], [$MKDIR]) - CS_EMIT_BUILD_PROPERTY([CMD.MKDIRS], [$MKDIRS]) - - CS_CHECK_PROGS([INSTALL], [install]) - CS_EMIT_BUILD_PROPERTY([INSTALL], [$INSTALL])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_COMMON_TOOLS_DOC_TEXINFO -# Checks for tools to generate documentation from texinfo files. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_COMMON_TOOLS_DOC_TEXINFO], - [CS_CHECK_PROGS([TEXI2DVI], [texi2dvi]) - CS_EMIT_BUILD_PROPERTY([CMD.TEXI2DVI], [$TEXI2DVI]) - - CS_CHECK_PROGS([TEXI2PDF], [texi2pdf]) - CS_EMIT_BUILD_PROPERTY([CMD.TEXI2PDF], [$TEXI2PDF]) - - CS_CHECK_PROGS([DVIPS], [dvips]) - CS_EMIT_BUILD_PROPERTY([CMD.DVIPS], [$DVIPS]) - - CS_CHECK_PROGS([DVIPDF], [dvipdf]) - CS_EMIT_BUILD_PROPERTY([CMD.DVIPDF], [$DVIPDF]) - - CS_CHECK_PROGS([MAKEINFO], [makeinfo]) - CS_EMIT_BUILD_PROPERTY([CMD.MAKEINFO], [$MAKEINFO])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_COMMON_TOOLS_DOC_DOXYGEN -# Checks for tools to generate source documentation via doxygen. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_COMMON_TOOLS_DOC_DOXYGEN], - [CS_CHECK_PROGS([DOXYGEN], [doxygen]) - CS_EMIT_BUILD_PROPERTY([CMD.DOXYGEN], [$DOXYGEN]) - - CS_CHECK_TOOLS([DOT], [dot]) - CS_EMIT_BUILD_PROPERTY([CMD.DOT], [$DOT])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_COMMON_LIBS -# Check for typical required libraries (libm, libmx, libdl, libnsl). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_COMMON_LIBS], - [AC_LANG_PUSH([C]) - AC_CHECK_LIB([m], [pow], [cs_cv_libm_libs=-lm], [cs_cv_libm_libs=]) - AC_CHECK_LIB([m], [cosf], [cs_cv_libm_libs=-lm]) - AC_CHECK_LIB([mx], [cosf]) - AC_CHECK_LIB([dl], [dlopen], [cs_cv_libdl_libs=-ldl], [cs_cv_libdl_libs=]) - AC_CHECK_LIB([nsl], [gethostbyname]) - AC_LANG_POP([C])]) -# checkcppunit.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_CPPUNIT([EMITTER]) -# Check if CppUnit (http://cppunit.sourceforge.net/), the unit-testing -# framework is available. The shell variable cs_cv_libcppunit is set to -# "yes" if CppUnit is discovered, else "no". If available, then the -# variables cs_cv_libcppunit_cflags, cs_cv_libcppunit_lflags, and -# cs_cv_libcppunit_libs are set. If EMITTER is provided, then -# CS_EMIT_BUILD_RESULT() is invoked with EMITTER in order to record the -# results in an output file. As a convenience, if EMITTER is the literal -# value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s default emitter -# will be used. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_CPPUNIT], - [CS_CHECK_LIB_WITH([cppunit], - [AC_LANG_PROGRAM([[#include ]], - [CppUnit::TextUi::TestRunner r; r.run();])], - [], [C++]) - - AS_IF([test $cs_cv_libcppunit = yes], - [CS_CHECK_BUILD([if cppunit is sufficiently recent], - [cs_cv_libcppunit_recent], - [AC_LANG_PROGRAM( - [[#include ]], - [CppUnit::BriefTestProgressListener b; b.startTest(0);])], - [], [C++], - [CS_EMIT_BUILD_RESULT([cs_cv_libcppunit], [CPPUNIT], - CS_EMITTER_OPTIONAL([$1]))], [], [], - [$cs_cv_libcppunit_cflags], - [$cs_cv_libcppunit_lflags], - [$cs_cv_libcppunit_libs])])]) -# checklib.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003-2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# cs_lib_paths_default -# Whitespace delimited list of directory tuples in which to search, by -# default, for external libraries. Each list item can specify an -# include|library directory tuple (for example, "/usr/include|/usr/lib"), -# or a single directory (for example, "/usr"). If the second form is -# used, then "include" and "lib" subdirectories of the directory are -# searched. If the library resources are not found, then the directory -# itself is searched. Thus, "/proj" is shorthand for -# "/proj/include|/proj/lib /proj|/proj". -# -# Present Cases: -# /usr/local -- Not all compilers search here by default, so we specify -# it manually. -# /sw -- Fink, the MacOS/X manager of Unix packages, installs here by -# default. -# /opt/local -- DarwinPorts installs here by default. -#------------------------------------------------------------------------------ -m4_define([cs_lib_paths_default], - [/usr/local/include|/usr/local/lib \ - /sw/include|/sw/lib \ - /opt/local/include|/opt/local/lib \ - /opt/include|/opt/lib]) - - - -#------------------------------------------------------------------------------ -# cs_pkg_paths_default -# Comma delimited list of additional directories in which the -# `pkg-config' command should search for its `.pc' files. -# -# Present Cases: -# /usr/local/lib/pkgconfig -- Although a common location for .pc files -# installed by "make install", many `pkg-config' commands neglect -# to search here automatically. -# /sw/lib/pkgconfig -- Fink, the MacOS/X manager of Unix packages, -# installs .pc files here by default. -# /opt/local/lib/pkgconfig -- DarwinPorts installs .pc files here by -# default. -#------------------------------------------------------------------------------ -m4_define([cs_pkg_paths_default], - [/usr/local/lib/pkgconfig, - /sw/lib/pkgconfig, - /opt/local/lib/pkgconfig, - /opt/lib/pkgconfig]) - - - -#------------------------------------------------------------------------------ -# CS_CHECK_LIB_WITH(LIBRARY, PROGRAM, [SEARCH-LIST], [LANGUAGE], -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], [OTHER-CFLAGS], -# [OTHER-LFLAGS], [OTHER-LIBS], [ALIASES]) -# Very roughly similar in concept to AC_CHECK_LIB(), but allows caller to -# to provide list of directories in which to search for LIBRARY; allows -# user to override library location via --with-LIBRARY=dir; and consults -# `pkg-config' (if present) and `LIBRARY-config' (if present, i.e. -# `sdl-config') in order to obtain compiler and linker flags. LIBRARY is -# the name of the library or MacOS/X framework which is to be located -# (for example, "readline" for `libreadline.a' or `readline.framework'). -# PROGRAM, which is typically composed with AC_LANG_PROGRAM(), is a -# program which references at least one function or symbol in LIBRARY. -# SEARCH-LIST is a whitespace-delimited list of paths in which to search -# for the library and its header files, in addition to those searched by -# the compiler and linker by default, and those referenced by the -# cs_lib_paths_default macro. Each list item can specify an -# `include|library' directory tuple (for example, -# "/usr/include|/usr/lib"), or a single directory (for example, "/usr"). -# If the second form is used, then "include" and "lib" subdirectories of -# the directory are searched. If the library resources are not found, -# then the directory itself is searched. Thus, "/proj" is shorthand for -# "/proj/include|/proj/lib /proj|/proj". Items in the search list can -# include wildcards. SEARCH-LIST can be overridden by the user with the -# --with-LIBRARY=dir option, in which case only "dir/include|dir/lib" and -# "dir|dir" are searched. If SEARCH-LIST is omitted and the user did not -# override the search list via --with-LIBRARY=dir, then only the -# directories normally searched by the compiler and the directories -# mentioned via cs_lib_paths_default are searched. LANGUAGE is typically -# either C or C++ and specifies which compiler to use for the test. If -# LANGUAGE is omitted, C is used. OTHER-CFLAGS, OTHER-LFLAGS, and -# OTHER-LIBS can specify additional compiler flags, linker flags, and -# libraries needed to successfully link with LIBRARY. The optional -# ALIASES is a comma-delimited list of library names for which to search -# in case LIBRARY is not located (for example "[sdl1.2, sdl12]" for -# libsdl1.2.a, sdl1.2.framework, libsdl12.a, and sdl12.framework). If -# the library or one of its aliases is found and can be successfully -# linked into a program, then the shell cache variable cs_cv_libLIBRARY -# is set to "yes"; cs_cv_libLIBRARY_cflags, cs_cv_libLIBRARY_lflags, and -# cs_cv_libLIBRARY_libs are set, respectively, to the compiler flags -# (including OTHER-CFLAGS), linker flags (including OTHER-LFLAGS), and -# library references (including OTHER-LIBS) which resulted in a -# successful build; and ACTION-IF-FOUND is invoked. If the library was -# not found or was unlinkable, or if the user disabled the library via -# --without-LIBRARY, then cs_cv_libLIBRARY is set to "no" and -# ACTION-IF-NOT-FOUND is invoked. Note that the exported shell variable -# names are always composed from LIBRARY regardless of whether the test -# succeeded because the primary library was discovered or one of the -# aliases. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_LIB_WITH], - [AC_ARG_WITH([$1], [AC_HELP_STRING([--with-$1=dir], - [specify location of lib$1 if not detected automatically; searches - dir/include, dir/lib, and dir])]) - - # Backward compatibility: Recognize --with-lib$1 as alias for --with-$1. - AS_IF([test -n "$with_lib$1" && test -z "$with_$1"], - [with_$1="$with_lib$1"]) - - AS_IF([test -z "$with_$1"], [with_$1=yes]) - AS_IF([test "$with_$1" != no], - [# If --with-$1 value is same as cached value, then assume other - # cached values are also valid; otherwise, ignore all cached values. - AS_IF([test "$with_$1" != "$cs_cv_with_$1"], - [cs_ignore_cache=yes], [cs_ignore_cache=no]) - - cs_check_lib_flags='' - AS_IF([test $with_$1 = yes], - [m4_foreach([cs_check_lib_alias], [$1, $10], - [_CS_CHECK_LIB_PKG_CONFIG_FLAGS([cs_check_lib_flags], - cs_check_lib_alias) - _CS_CHECK_LIB_CONFIG_FLAGS([cs_check_lib_flags], - cs_check_lib_alias) - ])]) - - AS_IF([test $with_$1 != yes], - [cs_check_lib_paths=$with_$1], - [cs_check_lib_paths="| cs_lib_paths_default $3"]) - m4_foreach([cs_check_lib_alias], [$1, $10], - [_CS_CHECK_LIB_CREATE_FLAGS([cs_check_lib_flags], - cs_check_lib_alias, [$cs_check_lib_paths]) - ]) - - CS_CHECK_BUILD([for lib$1], [cs_cv_lib$1], [$2], [$cs_check_lib_flags], - [$4], [], [], [$cs_ignore_cache], [$7], [$8], [$9])], - [cs_cv_lib$1=no]) - - cs_cv_with_$1="$with_$1" - AS_IF([test "$cs_cv_lib$1" = yes], [$5], [$6])]) - - - -#------------------------------------------------------------------------------ -# CS_CHECK_PKG_CONFIG -# Check if the `pkg-config' command is available and reasonably recent. -# This program acts as a central repository of build flags for various -# packages. For example, to determine the compiler flags for FreeType2 -# use, "pkg-config --cflags freetype2"; and "pkg-config --libs freetype2" -# to determine the linker flags. If `pkg-config' is found and is -# sufficiently recent, PKG_CONFIG is set and AC_SUBST() invoked. -#------------------------------------------------------------------------------ -m4_define([CS_PKG_CONFIG_MIN], [0.9.0]) -AC_DEFUN([CS_CHECK_PKG_CONFIG], - [AS_IF([test "$cs_prog_pkg_config_checked" != yes], - [CS_CHECK_TOOLS([PKG_CONFIG], [pkg-config]) - _CS_CHECK_PKG_CONFIG_PREPARE_PATH - cs_prog_pkg_config_checked=yes]) - AS_IF([test -z "$cs_cv_prog_pkg_config_ok"], - [AS_IF([test -n "$PKG_CONFIG"], - [AS_IF([$PKG_CONFIG --atleast-pkgconfig-version=CS_PKG_CONFIG_MIN], - [cs_cv_prog_pkg_config_ok=yes], - [cs_cv_prog_pkg_config_ok=no])], - [cs_cv_prog_pkg_config_ok=no])])]) - -AC_DEFUN([_CS_CHECK_PKG_CONFIG_PREPARE_PATH], - [PKG_CONFIG_PATH="m4_foreach([cs_pkg_path], [cs_pkg_paths_default], - [cs_pkg_path$PATH_SEPARATOR])$PKG_CONFIG_PATH" - export PKG_CONFIG_PATH]) - - - -#------------------------------------------------------------------------------ -# _CS_CHECK_LIB_PKG_CONFIG_FLAGS(VARIABLE, LIBRARY) -# Helper macro for CS_CHECK_LIB_WITH(). Checks if `pkg-config' knows -# about LIBRARY and, if so, appends a build tuple consisting of the -# compiler and linker flags reported by `pkg-config' to the list of -# tuples stored in the shell variable VARIABLE. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_CHECK_LIB_PKG_CONFIG_FLAGS], - [CS_CHECK_PKG_CONFIG - AS_IF([test $cs_cv_prog_pkg_config_ok = yes], - [AC_CACHE_CHECK([if $PKG_CONFIG recognizes $2], [_CS_CLPCF_CVAR([$2])], - [AS_IF([$PKG_CONFIG --exists $2], - [_CS_CLPCF_CVAR([$2])=yes], [_CS_CLPCF_CVAR([$2])=no])]) - AS_IF([test $_CS_CLPCF_CVAR([$2]) = yes], - [_CS_CHECK_LIB_CONFIG_PROG_FLAGS([$1], [pkg_config_$2], - [$PKG_CONFIG], [$2])])])]) - -AC_DEFUN([_CS_CLPCF_CVAR], [AS_TR_SH([cs_cv_prog_pkg_config_$1])]) - - - -#------------------------------------------------------------------------------ -# _CS_CHECK_LIB_CONFIG_FLAGS(VARIABLE, LIBRARY) -# Helper macro for CS_CHECK_LIB_WITH(). Checks if `LIBRARY-config' -# (i.e. `sdl-config') exists and, if so, appends a build tuple consisting -# of the compiler and linker flags reported by `LIBRARY-config' to the -# list of tuples stored in the shell variable VARIABLE. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_CHECK_LIB_CONFIG_FLAGS], - [CS_CHECK_TOOLS(_CS_CLCF_SHVAR([$2]), [$2-config]) - AS_IF([test -n "$_CS_CLCF_SHVAR([$2])"], - [AS_IF([test -z "$_CS_CLCF_CVAR([$2])"], - [AS_IF([$_CS_CLCF_SHVAR([$2]) --cflags --libs >/dev/null 2>&1], - [_CS_CLCF_CVAR([$2])=yes], [_CS_CLCF_CVAR([$2])=no])]) - AS_IF([test $_CS_CLCF_CVAR([$2]) = yes], - [_CS_CHECK_LIB_CONFIG_PROG_FLAGS([$1], [config_$2], - [$_CS_CLCF_SHVAR([$2])])])])]) - -AC_DEFUN([_CS_CLCF_CVAR], [AS_TR_SH([cs_cv_prog_config_$1_ok])]) -AC_DEFUN([_CS_CLCF_SHVAR], [m4_toupper(AS_TR_SH([CONFIG_$1]))]) - - - -#------------------------------------------------------------------------------ -# _CS_CHECK_LIB_CONFIG_PROG_FLAGS(VARIABLE, TAG, CONFIG-PROGRAM, [ARGS]) -# Helper macro for _CS_CHECK_LIB_PKG_CONFIG_FLAGS() and -# _CS_CHECK_LIB_CONFIG_FLAGS(). CONFIG-PROGRAM is a command which -# responds to the --cflags and --libs options and returns suitable -# compiler and linker flags for some package. ARGS, if supplied, is -# passed to CONFIG-PROGRAM after the --cflags or --libs argument. The -# results of the --cflags and --libs options are packed into a build -# tuple and appended to the list of tuples stored in the shell variable -# VARIABLE. TAG is used to compose the name of the cache variable. A good -# choice for TAG is some unique combination of the library name and -# configuration program. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_CHECK_LIB_CONFIG_PROG_FLAGS], - [AS_IF([test -z "$_CS_CLCPF_CVAR([$2])"], - [cs_check_lib_cflag=CS_RUN_PATH_NORMALIZE([$3 --cflags $4]) - cs_check_lib_lflag='' - cs_check_lib_libs=CS_RUN_PATH_NORMALIZE([$3 --libs $4]) - _CS_CLCPF_CVAR([$2])=CS_CREATE_TUPLE( - [$cs_check_lib_cflag], - [$cs_check_lib_lflag], - [$cs_check_lib_libs])]) - $1="$$1 $_CS_CLCPF_CVAR([$2])"]) - -AC_DEFUN([_CS_CLCPF_CVAR], [AS_TR_SH([cs_cv_prog_$1_flags])]) - - - -#------------------------------------------------------------------------------ -# _CS_CHECK_LIB_CREATE_FLAGS(VARIABLE, LIBRARY, PATHS) -# Helper macro for CS_CHECK_LIB_WITH(). Constructs a list of build -# tuples suitable for CS_CHECK_BUILD() and appends the tuple list to the -# shell variable VARIABLE. LIBRARY and PATHS have the same meanings as -# the like-named arguments of CS_CHECK_LIB_WITH(). -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_CHECK_LIB_CREATE_FLAGS], - [for cs_lib_item in $3 - do - case $cs_lib_item in - *\|*) CS_SPLIT( - [$cs_lib_item], [cs_check_incdir,cs_check_libdir], [|]) - _CS_CHECK_LIB_CREATE_FLAG([$1], - [$cs_check_incdir], [$cs_check_libdir], [$2]) - ;; - *) _CS_CHECK_LIB_CREATE_FLAG([$1], - [$cs_lib_item/include], [$cs_lib_item/lib], [$2]) - _CS_CHECK_LIB_CREATE_FLAG( - [$1], [$cs_lib_item], [$cs_lib_item], [$2]) - ;; - esac - done]) - - - -#------------------------------------------------------------------------------ -# _CS_CHECK_LIB_CREATE_FLAG(VARIABLE, HEADER-DIR, LIBRARY-DIR, LIBRARY) -# Helper macro for _CS_CHECK_LIB_CREATE_FLAGS(). Constructs build tuples -# suitable for CS_CHECK_BUILD() for given header and library directories, -# and appends the tuples to the shell variable VARIABLE. Synthesizes -# tuples which check for LIBRARY as a MacOS/X framework, and a standard -# link library. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_CHECK_LIB_CREATE_FLAG], - [AS_IF([test -n "$2"], [cs_check_lib_cflag="-I$2"], [cs_check_lib_cflag='']) - AS_IF([test -n "$3"], [cs_check_lib_lflag="-L$3"], [cs_check_lib_lflag='']) - AS_IF([test -n "$4"], - [cs_check_lib_libs="-l$4" - cs_check_lib_framework="-framework $4"], - [cs_check_lib_libs='' - cs_check_lib_framework='']) - $1="$$1 - CS_CREATE_TUPLE( - [$cs_check_lib_cflag], - [$cs_check_lib_lflag], - [$cs_check_lib_framework]) - CS_CREATE_TUPLE( - [$cs_check_lib_cflag], - [$cs_check_lib_lflag], - [$cs_check_lib_libs])"]) -# checklibtool.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2004 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_LIBTOOL -# Find and identify the various implementations of libtool. In -# particular, this macro is aware of GNU libtool and Apple's libtool -# (which serves a completely different purpose). On MacOS/X, GNU libtool -# is typically named glibtool, however a user might also use Fink to -# install the unadorned libtool; and the Fink-installed version might -# shadow Apple's own libtool if it appears in the PATH before the Apple -# tool. This macro jumps through the necessary hoops to distinguish and -# locate the various implementations. Sets the shell variable LIBTOOL to -# the located GNU libtool (if any), and APPLE_LIBTOOL to the located -# Apple libtool. Invokes AC_SUBST() for LIBTOOL and APPLE_LIBTOOL. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_LIBTOOL], -[# GNU: Search for libtool before glibtool since Fink version is likely newer. -m4_define([cs_lt_path_gnu], - [/sw/bin$PATH_SEPARATOR/usr/local/bin$PATH_SEPARATOR$PATH]) -AS_IF([test -z "$LIBTOOL"], - [CS_CHECK_TOOLS([LIBTOOL_TEST], [libtool glibtool gnulibtool], [], - [cs_lt_path_gnu]) - AS_IF([test -n "$LIBTOOL_TEST"], - [CS_PATH_PROG([LIBTOOL_PATH], [$LIBTOOL_TEST], [], [cs_lt_path_gnu]) - CS_LIBTOOL_CLASSIFY([$LIBTOOL_PATH], - [LIBTOOL="$LIBTOOL_PATH"], - [AS_IF([test -z "$APPLE_LIBTOOL"], [APPLE_LIBTOOL="$LIBTOOL_PATH"]) - CS_CHECK_TOOLS([LIBTOOL], [glibtool gnulibtool])])])]) -AC_SUBST([LIBTOOL]) - -# Apple: Ensure that Apple libtool will be found before GNU libtool from Fink. -m4_define([cs_lt_path_apple],[/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH]) -AS_IF([test -z "$APPLE_LIBTOOL"], - [CS_PATH_PROG([CS_LT_APPLE], [libtool], [], [cs_lt_path_apple]) - CS_LIBTOOL_CLASSIFY([$CS_LT_APPLE], [], - [APPLE_LIBTOOL="$CS_LT_APPLE"])]) -AC_SUBST([APPLE_LIBTOOL])]) - -AC_DEFUN([CS_LIBTOOL_CLASSIFY], - [AS_IF([test -n "$1"], - [AC_MSG_CHECKING([classification of $1]) - CS_LIBTOOL_GNU_IFELSE([$1], - [AC_MSG_RESULT([gnu]) - $2], - [AC_MSG_RESULT([apple]) - $3])])]) - -AC_DEFUN([CS_LIBTOOL_GNU_IFELSE], - [AS_IF([AC_RUN_LOG([$1 --version 1>&2])], [$2], [$3])]) -#============================================================================== -# Copyright (C)2003-2006 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_OPENGL -# Check for OpenGL. -# -# IMPLEMENTATION NOTES -# -# Some Mesa installations require pthread, so pthread flags are employed if -# available. -# -# The check for opengl32 needs to precede other checks because Cygwin users -# often have Mesa installed, and Mesa's OpenGL library is compiled without the -# __stdcall flags which results in link errors, whereas Microsoft's native -# opengl32 works fine. Conversely, some Unix implementations have Wine -# installed (Windows emulation layer) which includes an opengl32.so library. -# We need to avoid detection of this library on Unix since it would cause an -# undesirable dependence upon Wine. -# -# Many OpenGL libraries on Unix already contain GLX, so there is no separate -# GLX library, thus we first check for GLX using the discovered OpenGL library -# before attempting to locate a separate GLX-specific library. -# -# On MacOS/X, some users have XFree86 installed which creates a link from -# /usr/include/GL to /usr/X11R6/include/GL. We want to ignore this directory -# and instead check for Apple's OpenGL.framework, if we are not cross-building -# for Darwin. We accomplish this by placing the OpenGL.framework test ahead of -# the other tests. -# -# At least one user (Jorrit) has a strange installation in which inclusion of -# fails if an int32 is not present, thus we must take this into -# account. -#------------------------------------------------------------------------------ -m4_define([cs_define_int32], - [[#if !HAVE_TYPE_INT32 - typedef long int32; - #endif - ]]) - -# CS_GL_INCLUDE(CPP-MACRO,FALLBACK,HEADER) -AC_DEFUN([CS_GL_INCLUDE], - [[#if HAVE_WINDOWS_H - #if !HAVE_TYPE_INT32 - typedef long int32; - #endif - #include - #endif - #ifndef CS_HEADER_GLOBAL - #define CS_HEADER_GLOBAL(X,Y) CS_HEADER_GLOBAL_COMPOSE(X,Y) - #define CS_HEADER_GLOBAL_COMPOSE(X,Y) - #endif - #ifdef $1 - #include CS_HEADER_GLOBAL($1,$3) - #else - #include <$2/$3> - #endif]]) - -AC_DEFUN([CS_CHECK_OPENGL], - [AC_REQUIRE([CS_CHECK_HOST]) - AC_REQUIRE([CS_CHECK_COMMON_LIBS]) - AC_REQUIRE([CS_CHECK_PTHREAD]) - AC_REQUIRE([AC_PATH_X]) - AC_REQUIRE([AC_PATH_XTRA]) - AC_CHECK_TYPE([int32], [AC_DEFINE([HAVE_TYPE_INT32], [], - [Whether the int32 type is available])], []) - AC_CHECK_HEADERS([windows.h], [], [], [cs_define_int32]) - - # Apply plaform-specific flags if necessary. - cs_gl_plat_cflags='' - cs_gl_plat_lflags='' - cs_gl_plat_libs='' - AS_IF([test -n "$cs_cv_libm_cflags$cs_cv_libm_lflags$cs_cv_libm_libs"], - [cs_gl_plat_cflags="$cs_cv_libm_cflags $cs_gl_plat_cflags" - cs_gl_plat_lflags="$cs_cv_libm_lflags $cs_gl_plat_lflags" - cs_gl_plat_libs="$cs_cv_libm_libs $cs_gl_plat_libs"]) - AS_IF([test $cs_cv_sys_pthread = yes], - [cs_gl_plat_cflags="$cs_cv_sys_pthread_cflags $cs_gl_plat_cflags" - cs_gl_plat_lflags="$cs_cv_sys_pthread_lflags $cs_gl_plat_lflags" - cs_gl_plat_libs="$cs_cv_sys_pthread_libs $cs_gl_plat_libs"]) - AS_IF([test "$no_x" != yes], - [cs_gl_plat_cflags="$X_CFLAGS $cs_gl_plat_cflags" - cs_gl_plat_lflags="$cs_gl_plat_lflags" - cs_gl_plat_libs=" - $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS $cs_gl_plat_libs"]) - - # Mesa requested? - AC_ARG_WITH([mesa], [AC_HELP_STRING([--with-mesa], - [use Mesa OpenGL library if available (default YES)])], - [], [with_mesa=yes]) - - AS_IF([test $with_mesa != no], - [cs_mesa_gl=CS_CREATE_TUPLE([],[],[-lMesaGL])]) - - # MacOS/X or Darwin? - AS_IF([test "x$cs_host_macosx" = "xyes"], - [cs_osx_gl=CS_CREATE_TUPLE([-DCS_OPENGL_PATH=OpenGL],[],[-framework OpenGL])]) - AS_IF([test "x$cs_host_macosx" = "xyes"], - [cs_gl_plat_lflags="$cs_plat_lflags -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"]) - - # Windows? - AS_IF([test $cs_host_family = windows], - [cs_win32_gl=CS_CREATE_TUPLE([],[],[-lopengl32])]) - - # Check for OpenGL. - CS_CHECK_BUILD([for OpenGL], [cs_cv_libgl], - [AC_LANG_PROGRAM([CS_GL_INCLUDE([CS_OPENGL_PATH],[GL],[gl.h])],[glEnd()])], - [$cs_win32_gl \ - $cs_osx_gl \ - CS_CREATE_TUPLE([],[],[-lGL]) \ - CS_CREATE_TUPLE([],[],[-lgl]) \ - $cs_mesa_gl], [], - [CS_EMIT_BUILD_RESULT([cs_cv_libgl], [GL])], [], [], - [$cs_gl_plat_cflags], [$cs_gl_plat_lflags], [$cs_gl_plat_libs])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_GLU -# Check for GLU. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_GLU], - [AC_REQUIRE([CS_CHECK_OPENGL]) - AS_IF([test $cs_cv_libgl = yes], - [AS_IF([test $with_mesa != no], - [cs_mesa_glu=CS_CREATE_TUPLE([],[],[-lMesaGLU])]) - - # MacOS/X or Darwin? - AS_IF([test "x$cs_host_macosx" = "xyes"], - [cs_osx_glu=CS_CREATE_TUPLE([-DCS_GLU_PATH=OpenGL],[],[-framework OpenGL])]) - - # Windows? - AS_IF([test $cs_host_family = windows], - [cs_win32_glu=CS_CREATE_TUPLE([],[],[-lglu32])]) - - # Check for GLU. - CS_CHECK_BUILD([for GLU], [cs_cv_libglu], - [AC_LANG_PROGRAM( - [CS_GL_INCLUDE([CS_GLU_PATH],[GL],[glu.h])], [gluNewQuadric()])], - [$cs_osx_glu \ - CS_CREATE_TUPLE() \ - $cs_win32_glu \ - CS_CREATE_TUPLE([],[],[-lGLU]) \ - CS_CREATE_TUPLE([],[],[-lglu]) \ - $cs_mesa_glu], [], - [CS_EMIT_BUILD_RESULT([cs_cv_libglu], [GLU])], [], [], - [$cs_cv_libgl_cflags], [$cs_cv_libgl_lflags], [$cs_cv_libgl_libs])])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_GLX -# Check for GLX. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_GLX], - [AC_REQUIRE([CS_CHECK_OPENGL]) - AS_IF([test $cs_cv_libgl = yes], - [AS_IF([test $with_mesa != no], - [cs_mesa_glx=CS_CREATE_TUPLE([],[],[-lMesaGLX])]) - - # Check for GLX. - AS_IF([test "$no_x" != yes], - [CS_CHECK_BUILD([for GLX], [cs_cv_libglx], - [AC_LANG_PROGRAM([[#include ]], [glXWaitGL()])], - [CS_CREATE_TUPLE() \ - CS_CREATE_TUPLE([],[],[-lGLX]) \ - CS_CREATE_TUPLE([],[],[-lglx]) \ - $cs_mesa_glx], [], - [CS_EMIT_BUILD_RESULT([cs_cv_libglx], [GLX])], [], [], - [$cs_cv_libgl_cflags], [$cs_cv_libgl_lflags], [$cs_cv_libgl_libs])])])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_GLXEXT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# Check for GLX extensions. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_GLXEXT], - [AC_REQUIRE([CS_CHECK_GLX]) - AS_IF([test x$cs_cv_libglx = "xyes"], - [# Check for GLX extensions. - CS_CHECK_BUILD([for GLX extensions], [cs_cv_libglx_extensions], - [AC_LANG_PROGRAM( - [[#define GLX_GLXEXT_PROTOTYPES - #include ]], - [glXGetProcAddressARB(0)])], - [CS_CREATE_TUPLE( - [$cs_cv_libglx_cflags], - [$cs_cv_libglx_lflags], - [$cs_cv_libglx_libs])], - [], [$1], [$2])])]) - - - -#------------------------------------------------------------------------------ -# CS_CHECK_GLUT -# Check for GLUT. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_GLUT], - [AC_REQUIRE([CS_CHECK_GLU]) - AS_IF([test x$cs_cv_libglu = "xyes"], - [# MacOS/X or Darwin? - AS_IF([test "x$cs_host_macosx" = "xyes"], - [cs_osx_glut=CS_CREATE_TUPLE([-DCS_GLUT_PATH=GLUT],[],[-framework GLUT])]) - - # Windows? - AS_IF([test $cs_host_family = windows], - [cs_win32_glut=CS_CREATE_TUPLE([],[],[-lglut32])]) - - # Check for GLUT. - CS_CHECK_BUILD([for GLUT], [cs_cv_libglut], - [AC_LANG_PROGRAM( - [CS_GL_INCLUDE([CS_GLUT_PATH],[GL],[glut.h])], [glutSwapBuffers()])], - [$cs_osx_glut \ - CS_CREATE_TUPLE() \ - $cs_win32_glut \ - CS_CREATE_TUPLE([],[],[-lGLUT]) \ - CS_CREATE_TUPLE([],[],[-lglut])], [], - [CS_EMIT_BUILD_RESULT([cs_cv_libglut], [GLUT])], [], [], - [$cs_cv_libgl_cflags $cs_cv_libglu_cflags], - [$cs_cv_libgl_lflags $cs_cv_libglu_lflags], - [$cs_cv_libgl_libs $cs_cv_libglu_libs])])]) - -# checkpic.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_COMPILER_PIC([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check if compiler can be instructed to produce -# position-independent-code (PIC). This feature is required by some -# platforms when building plugin modules and shared libraries. If -# LANGUAGE is not provided, then `C' is assumed (other options include -# `C++'). If CACHE-VAR is not provided, then it defaults to the name -# "cs_cv_prog_compiler_pic". If a PIC-enabling option (such as `-fPIC') -# is discovered, then it is assigned to CACHE-VAR and ACTION-IF-FOUND is -# invoked; otherwise the empty string is assigned to CACHE-VAR and -# ACTION-IF-NOT-FOUND is invoked. -# -# IMPLEMENTATION NOTES -# -# On some platforms (such as Windows), the -fPIC option is superfluous -# and emits a warning "-fPIC ignored for target (all code is position -# independent)", despite the fact that the compiler accepts the option -# and returns a success code. We want to re-interpret the warning as a -# failure in order to avoid unnecessary compiler diagnostics in case the -# client inserts the result of this check into CFLAGS, for instance. We -# do so by attempting to promote warnings to errors using the result of -# CS_COMPILER_ERRORS(). As an extra safe-guard, we also scan the compiler -# output for an appropriate diagnostic because some gcc warnings fail to -# promote to error status despite use of -Werror. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_PIC], - [CS_COMPILER_ERRORS([$1], - [m4_default([$2_werror],[cs_cv_prog_compiler_pic_werror])]) - CS_CHECK_BUILD_FLAGS( - [how to enable m4_default([$1],[C]) PIC generation], - [m4_default([$2],[cs_cv_prog_compiler_pic])], - [CS_CREATE_TUPLE([-fPIC])], [$1], [$3], [$4], - [m4_default([$$2_werror],[$cs_cv_prog_compiler_pic_werror])], [], [], - [fPIC])]) - -# Backward-compatiblity alias. -AC_DEFUN([CS_CHECK_COMPILER_PIC], [CS_COMPILER_PIC([$1],[$2],[$3],[$4])]) -# checkprog.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2004 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# cs_bin_paths_default -# Comma delimited list of additional directories in which tools and -# commands might be found. -# -# Present Cases: -# /usr/local/bin -- Although a common location for executables, it is -# now-and-then absent from the default PATH setting. -# /sw/bin -- Fink, the MacOS/X manager of Unix packages, installs -# executables here. -#------------------------------------------------------------------------------ -m4_define([cs_bin_paths_default], [/usr/local/bin, /sw/bin]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_PROG(VARIABLE, PROGRAM, VALUE-IF-FOUND, [VALUE-IF-NOT-FOUND], -# [PATH], [REJECT]) -# Simple wrapper for AC_CHECK_PROG() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_PROG], - [_CS_PROG_PATH_PREPARE - AC_CHECK_PROG([$1], [$2], [$3], [$4], - m4_ifval([$5], [_CS_PROG_CLIENT_PATH([$5])]), [$6])]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_PROGS(VARIABLE, PROGRAMS, [VALUE-IF-NOT-FOUND], [PATH]) -# Simple wrapper for AC_CHECK_PROGS() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_PROGS], - [_CS_PROG_PATH_PREPARE - AC_CHECK_PROGS([$1], [$2], [$3], - m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_TOOL(VARIABLE, TOOL, [VALUE-IF-NOT-FOUND], [PATH]) -# Simple wrapper for AC_CHECK_TOOL() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_TOOL], - [_CS_PROG_PATH_PREPARE - AC_CHECK_TOOL([$1], [$2], [$3], - m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_TOOLS(VARIABLE, TOOLS, [VALUE-IF-NOT-FOUND], [PATH]) -# Simple wrapper for AC_CHECK_TOOLS() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_TOOLS], - [_CS_PROG_PATH_PREPARE - AC_CHECK_TOOLS([$1], [$2], [$3], - m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) - - -#------------------------------------------------------------------------------ -# CS_PATH_PROG(VARIABLE, PROGRAM, [VALUE-IF-NOT-FOUND], [PATH]) -# Simple wrapper for AC_PATH_PROG() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_PATH_PROG], - [_CS_PROG_PATH_PREPARE - AC_PATH_PROG([$1], [$2], [$3], - m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) - - -#------------------------------------------------------------------------------ -# CS_PATH_PROGS(VARIABLE, PROGRAMS, [VALUE-IF-NOT-FOUND], [PATH]) -# Simple wrapper for AC_PATH_PROGS() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_PATH_PROGS], - [_CS_PROG_PATH_PREPARE - AC_PATH_PROGS([$1], [$2], [$3], - m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) - - -#------------------------------------------------------------------------------ -# CS_PATH_TOOL(VARIABLE, TOOL, [VALUE-IF-NOT-FOUND], [PATH]) -# Simple wrapper for AC_PATH_TOOL() which ensures that the search path -# is augmented by the directories mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_PATH_TOOL], - [_CS_PROG_PATH_PREPARE - AC_PATH_TOOL([$1], [$2], [$3], - m4_ifval([$4], [_CS_PROG_CLIENT_PATH([$4])]))]) - - -#------------------------------------------------------------------------------ -# _CS_PROG_PATH_PREPARE -# Ensure that the PATH environment variable mentions the set of -# directories listed in cs_bin_paths_default. These directories may not -# appear by default in the typical PATH, yet they might be common -# locations for tools and commands. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_PROG_PATH_PREPARE], - [AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE]) - AS_IF([test "$cs_prog_path_prepared" != yes], - [cs_prog_path_prepared=yes - PATH="$PATH[]m4_foreach([cs_bin_path], [cs_bin_paths_default], - [$PATH_SEPARATOR[]cs_bin_path])" - export PATH])]) - - -#------------------------------------------------------------------------------ -# _CS_PROG_CLIENT_PATH(CLIENT-PATH) -# Given a client-supplied replacement for PATH, augment the list by -# appending the locations mentioned in cs_bin_paths_default. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_PROG_CLIENT_PATH], - [AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE])dnl - $1[]m4_foreach([cs_bin_path], [cs_bin_paths_default], - [$PATH_SEPARATOR[]cs_bin_path])]) -# checkpthread.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003-2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_PTHREAD([REJECT-MASK]) -# Check for pthread. Also check if the pthread implementation supports -# the recursive and timed mutex extensions. (Timed mutexes are needed for -# the NPTL: New Posix Thread Library on GNU/Linux if the mutex is going -# to be used with any of the timed condition-wait functions.) The shell -# variable cs_cv_sys_pthread is set to "yes" if pthread is available, -# else "no". If available, then the variables cs_cv_sys_pthread_cflags, -# cs_cv_sys_pthread_lflags, and cs_cv_sys_pthread_libs are set. (As a -# convenience, these variables can be emitted to an output file with -# CS_EMIT_BUILD_RESULT() by passing "cs_cv_sys_pthread" as its CACHE-VAR -# argument.) If the recursive mutex extension is supported, then -# cs_cv_sys_pthread_mutex_recursive will be set with the literal name of -# the constant which must be passed to pthread_mutexattr_settype() to -# enable this feature. The constant name will be typically -# PTHREAD_MUTEX_RECURSIVE or PTHREAD_MUTEX_RECURSIVE_NP. If the recursive -# mutex extension is not available, then -# cs_cv_sys_pthread_mutex_recursive will be set to "no". If the timed -# mutex extension is supported, then cs_cv_sys_pthread_mutex_timed will -# be set with the literal name of the constant which must be passed to -# pthread_mutexattr_settype() to enable this feature. The constant name -# will be typically PTHREAD_MUTEX_TIMED or PTHREAD_MUTEX_TIMED_NP. If the -# timed mutex extension is not available, then -# cs_cv_sys_pthread_mutex_timed will be set to "no". REJECT-MASK can be -# used to limit the platforms on which the pthread test is performed. It -# is compared against $host_os; matches are rejected. If omitted, then -# the test is performed on all platforms. Examples: To avoid testing on -# Cygwin, use "cygwin*"; to avoid testing on Cygwin and AIX, use -# "cygwin*|aix*". -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_PTHREAD], - [AC_REQUIRE([AC_CANONICAL_HOST]) - case $host_os in - m4_ifval([$1], - [$1) - cs_cv_sys_pthread=no - ;; - ]) - *) - CS_CHECK_BUILD([for pthread], [cs_cv_sys_pthread], - [AC_LANG_PROGRAM( - [[#include - #include - void* worker(void* p) { (void)p; return p; }]], - [pthread_t tid; - sem_t sem; - pthread_create(&tid, 0, worker, 0); - sem_init(&sem, 0, 0); - sem_destroy(&sem);])], - [cs_pthread_flags]) - ;; - esac - _CS_CHECK_MUTEX_FEATURE([PTHREAD_MUTEX_RECURSIVE], - [cs_cv_sys_pthread_mutex_recursive], [for pthread recursive mutexes])]) - -# _CS_CHECK_MUTEX_FEATURE(FEATURE, CACHE-VAR, MESSAGE) -AC_DEFUN([_CS_CHECK_MUTEX_FEATURE], - [AS_IF([test $cs_cv_sys_pthread = yes], - [AC_CACHE_CHECK([$3], [$2], - [CS_BUILD_IFELSE( - [AC_LANG_PROGRAM( - [[#include ]], - [pthread_mutexattr_t attr; - pthread_mutexattr_settype(&attr, CS_MUTEX_FEATURE);])], - [CS_CREATE_TUPLE([-DCS_MUTEX_FEATURE=$1]) \ - CS_CREATE_TUPLE([-DCS_MUTEX_FEATURE=$1_NP])], - [], - [$2=`echo $cs_build_cflags | sed 's/.*\($1_*N*P*\).*/\1/'`], - [$2=no], - [$cs_cv_sys_pthread_cflags -D_GNU_SOURCE], - [$cs_cv_sys_pthread_lflags], - [$cs_cv_sys_pthread_libs])])], - [$2=no])]) - -#------------------------------------------------------------------------------ -# CS_CHECK_PTHREAD_ATFORK(CACHE-VAR) -# Checks whether the pthread library contains pthread_atfork(). Sets -# CACHE-VAR to "yes" or "no", according to the test result. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_PTHREAD_ATFORK], - [AS_IF([test $cs_cv_sys_pthread = yes], - [AC_CACHE_CHECK([for pthread_atfork support], [$1], - [CS_BUILD_IFELSE( - [AC_LANG_PROGRAM( - [[#include ]], - [pthread_atfork (0, 0, 0);])], - [], [], - [$1=yes], [$1=no], - [$cs_cv_sys_pthread_cflags -D_GNU_SOURCE], - [$cs_cv_sys_pthread_lflags], - [$cs_cv_sys_pthread_libs])])], - [$1=no])]) - -m4_define([cs_pthread_flags], - [CS_CREATE_TUPLE() \ - CS_CREATE_TUPLE([], [], [-lpthread]) \ - CS_CREATE_TUPLE([], [], [-lpthread -lrt]) \ - CS_CREATE_TUPLE([-pthread], [-pthread], []) \ - CS_CREATE_TUPLE([-pthread], [-pthread], [-lpthread]) \ - CS_CREATE_TUPLE([-pthread], [-pthread], [-lc_r])]) -# checktt2.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2004,2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_TEMPLATE_TOOLKIT2([EMITTER]) -# Check if Template Toolkit 2 (http://www.tt2.org/) is available. The -# shell variable cs_cv_perl_tt2 is set to "yes" if the package is -# discovered, else "no". Also sets the shell variable TTREE to the name -# path of the 'ttree' utility program and invokes AC_SUBST(). If EMITTER -# is provided and the package was discovered, then -# CS_EMIT_BUILD_PROPERTY() is invoked with EMITTER in order to record the -# value of the TTREE variable in an output file. As a convenience, if -# EMITTER is the literal value "emit" or "yes", then -# CS_EMIT_BUILD_RESULT()'s default emitter will be used. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_TEMPLATE_TOOLKIT2], - [CS_CHECK_PROGS([PERL], [perl5 perl]) - AS_IF([test -n "$PERL"], - [AC_CACHE_CHECK([for TemplateToolkit], [cs_cv_perl_tt2], - [AS_IF([AC_RUN_LOG( - [$PERL -M'Template 2.11' -MTemplate::Plugin -e 0 1>&2])], - [cs_cv_perl_tt2=yes], - [cs_cv_perl_tt2=no])]) - CS_PATH_PROGS([TTREE], [ttree]) - AS_IF([test $cs_cv_perl_tt2 = yes && test -n "$TTREE"], - [CS_EMIT_BUILD_PROPERTY([TTREE], [$TTREE], [], [], - CS_EMITTER_OPTIONAL([$1]))])])]) -# compiler.m4 -*- Autoconf -*- -#============================================================================= -# Copyright (C)2003 by Matze Braun -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================= - -#----------------------------------------------------------------------------- -# Detection of C and C++ compilers and setting flags -# -# CS_PROG_CC -# Detects the C compiler. Also takes care of the CFLAGS, CPPFLAGS and CC -# environment variables. This will filter out all -g and -O from the -# CFLAGS variable because Autoconf's -g and -O defaults are not always -# desired. This will also set the CMD.CC and COMPILER.CFLAGS variables -# in Jamconfig -# CS_PROG_CXX -# Detects the C++ compiler. Also takes care of the CXXFLAGS, CPPFLAGS -# and CXX environment variables. This will filter out all -g and -O from -# the CXXFLAGS variable because Autoconf's -g and -O defaults are not -# always desired. This will also set the CMD.C++ and COMPILER.C++FLAGS -# variables in Jamconfig -# CS_PROG_LINK -# Tries to determine a linker. This is done by checking if a C++ or -# Objecctive-C++ compiler is available in which case it is used for -# linking; otherwise the C or Objective-C compiler is used. This also -# sets the CMD.LINK and COMPILER.LFLAGS variables in Jamconfig and -# respects the LDFLAGS environment variable. Finally, checks if linker -# recognizes -shared and sets PLUGIN.LFLAGS; and checks if linker -# recognizes -soname and sets PLUGIN.LFLAGS.USE_SONAME to "yes". -#----------------------------------------------------------------------------- -AC_DEFUN([CS_PROG_CC],[ - CFLAGS="$CFLAGS" # Filter undesired flags - AS_IF([test -n "$CC"],[ - CS_EMIT_BUILD_PROPERTY([CMD.CC], [$CC]) - CS_EMIT_BUILD_PROPERTY([COMPILER.CFLAGS], [$CPPFLAGS $CFLAGS], [+]) - - # Check if compiler recognizes -pipe directive. - CS_EMIT_BUILD_FLAGS([if $CC accepts -pipe], [cs_cv_prog_cc_pipe], - [CS_CREATE_TUPLE([-pipe])], [C], [COMPILER.CFLAGS], [+]) - ]) -]) - -AC_DEFUN([CS_PROG_CXX],[ - CXXFLAGS="$CXXFLAGS" # Filter undesired flags - AS_IF([test -n "$CXX"],[ - CS_EMIT_BUILD_PROPERTY([CMD.C++], [$CXX]) - - CS_EMIT_BUILD_PROPERTY([COMPILER.C++FLAGS], [$CPPFLAGS $CXXFLAGS], [+]) - - # Check if compiler can be instructed to produce position-independent-code - # (PIC). This feature is required by some platforms when building plugin - # modules and shared libraries. - CS_COMPILER_PIC([C++], [cs_cv_prog_cxx_pic], - [CS_EMIT_BUILD_PROPERTY([COMPILER.C++FLAGS.PIC], - [$cs_cv_prog_cxx_pic])]) - ]) -]) - -AC_DEFUN([CS_PROG_LINK],[ - AC_REQUIRE([CS_PROG_CXX]) - AS_IF([test -n "$CXX"], - [CS_EMIT_BUILD_PROPERTY([CMD.LINK], [AS_ESCAPE([$(CMD.C++)])])], - [CS_EMIT_BUILD_PROPERTY([CMD.LINK], [AS_ESCAPE([$(CMD.CC)])])]) - - CS_EMIT_BUILD_PROPERTY([COMPILER.LFLAGS], [$LDFLAGS], [+]) - - # Check if compiler/linker recognizes -shared directive which is needed for - # linking plugin modules. Unfortunately, the Apple compiler (and possibly - # others) requires extra effort. Even though the compiler does not recognize - # the -shared option, it nevertheless returns a "success" result after emitting - # the warning "unrecognized option `-shared'". Worse, even -Werror fails to - # promote the warning to an error, so we must instead scan the compiler's - # output for an appropriate diagnostic. - CS_CHECK_BUILD_FLAGS([if -shared is accepted], [cs_cv_prog_link_shared], - [CS_CREATE_TUPLE([-shared $cs_cv_prog_cxx_pic])], [C++], - [CS_EMIT_BUILD_PROPERTY([PLUGIN.LFLAGS], [-shared], [+])], [], - [], [], [], [shared]) - - # Check if linker recognizes -soname which is used to assign a name internally - # to plugin modules. - CS_CHECK_BUILD([if -soname is accepted], [cs_cv_prog_link_soname], [], - [CS_CREATE_TUPLE([-Wl,-soname,foobar])], [C++], - [CS_EMIT_BUILD_PROPERTY([PLUGIN.LFLAGS.USE_SONAME], [yes])]) -]) -#------------------------------------------------------------------------------ -# Determine host platform. Recognized families: Unix, Windows, MacOS/X. -# Orginial Macros Copyright (C)2003 Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#------------------------------------------------------------------------------ - -#------------------------------------------------------------------------------ -# Determine host CPU. -# -# CS_CHECK_HOST_CPU -# Set the shell variable cs_host_cpu to a normalized form of the CPU name -# returned by config.guess/config.sub. Typically, Crystal Space's -# conception of CPU name is the same as that returned by -# config.guess/config.sub, but there may be exceptions as seen in the -# `case' statement. Also takes the normalized name, uppercases it to -# form a name suitable for the C preprocessor. Additionally sets the -# TARGET.PROCESSOR Jamconfig property. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_HOST_CPU], - [AC_REQUIRE([AC_CANONICAL_HOST]) - case $host_cpu in - [[Ii][3-9]86*|[Xx]86*]) cs_host_cpu=x86 ;; - *) cs_host_cpu=$host_cpu ;; - esac - cs_host_cpu_normalized="AS_TR_CPP([$cs_host_cpu])" - CS_JAMCONFIG_PROPERTY([TARGET.PROCESSOR], [$cs_host_cpu_normalized]) - ]) - - -#------------------------------------------------------------------------------ -# CS_CHECK_HOST -# Sets the shell variables cs_host_target cs_host_family, -# cs_host_os_normalized, and cs_host_os_normalized_uc. Emits appropriate -# CS_PLATFORM_UNIX, CS_PLATFORM_WIN32, CS_PLATFORM_MACOSX via -# AC_DEFINE(), and TARGET.OS and TARGET.OS.NORMALIZED to Jamconfig. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_HOST], - [AC_REQUIRE([AC_CANONICAL_HOST]) - CS_CHECK_HOST_CPU - cs_host_os_normalized='' - case $host_os in - mingw*|cygwin*) - cs_host_target=win32gcc - cs_host_family=windows - ;; - darwin*) - _CS_CHECK_HOST_DARWIN - ;; - *) - # Everything else is assumed to be Unix or Unix-like. - cs_host_target=unix - cs_host_family=unix - ;; - esac - - case $cs_host_family in - windows) - AC_DEFINE([CS_PLATFORM_WIN32], [], - [Define when compiling for Win32]) - AS_IF([test -z "$cs_host_os_normalized"], - [cs_host_os_normalized='Win32']) - ;; - unix) - AC_DEFINE([CS_PLATFORM_UNIX], [], - [Define when compiling for Unix and Unix-like (i.e. MacOS/X)]) - AS_IF([test -z "$cs_host_os_normalized"], - [cs_host_os_normalized='Unix']) - ;; - esac - - cs_host_os_normalized_uc="AS_TR_CPP([$cs_host_os_normalized])" - CS_JAMCONFIG_PROPERTY([TARGET.OS], [$cs_host_os_normalized_uc]) - CS_JAMCONFIG_PROPERTY([TARGET.OS.NORMALIZED], [$cs_host_os_normalized]) -]) - -AC_DEFUN([_CS_CHECK_HOST_DARWIN], - [AC_REQUIRE([CS_PROG_CC]) - AC_REQUIRE([CS_PROG_CXX]) - - # Both MacOS/X and Darwin are identified via $host_os as "darwin". We need - # a way to distinguish between the two. If Carbon.h is present, then - # assume MacOX/S; if not, assume Darwin. If --with-x=yes was invoked, and - # Carbon.h is present, then assume that user wants to cross-build for - # Darwin even though build host is MacOS/X. - # IMPLEMENTATION NOTE *1* - # The QuickTime 7.0 installer removes , which - # causes #include to fail unconditionally. Re-installing - # the QuickTime SDK should restore the header, however not all developers - # know to do this, so we work around the problem of the missing - # CarbonSound.h by #defining __CARBONSOUND__ in the test in order to - # prevent Carbon.h from attempting to #include the missing header. - # IMPLEMENTATION NOTE *2* - # At least one MacOS/X user switches between gcc 2.95 and gcc 3.3 with a - # script which toggles the values of CC, CXX, and CPP. Unfortunately, CPP - # was being set to run the preprocessor directly ("cpp", for instance) - # rather than running it via the compiler ("gcc -E", for instance). The - # problem with running the preprocessor directly is that __APPLE__ and - # __GNUC__ are not defined, which causes the Carbon.h check to fail. We - # avoid this problem by supplying a non-empty fourth argument to - # AC_CHECK_HEADER(), which causes it to test compile the header only (which - # is a more robust test), rather than also testing it via the preprocessor. - - AC_DEFINE([__CARBONSOUND__], [], - [Avoid problem caused by missing ]) - AC_CHECK_HEADER([Carbon/Carbon.h], - [cs_host_macosx=yes], [cs_host_macosx=no], [/* force compile */]) - - AS_IF([test $cs_host_macosx = yes], - [AC_MSG_CHECKING([for --with-x]) - AS_IF([test "${with_x+set}" = set && test "$with_x" = "yes"], - [AC_MSG_RESULT([yes (assume Darwin)]) - cs_host_macosx=no], - [AC_MSG_RESULT([no])])]) - - AS_IF([test $cs_host_macosx = yes], - [cs_host_target=macosx - cs_host_family=unix - cs_host_os_normalized='MacOS/X' - AC_DEFINE([CS_PLATFORM_MACOSX], [], - [Define when compiling for MacOS/X]) - - AC_CACHE_CHECK([for Objective-C compiler], [cs_cv_prog_objc], - [cs_cv_prog_objc="$CC"]) - CS_JAMCONFIG_PROPERTY([CMD.OBJC], [$cs_cv_prog_objc]) - AC_CACHE_CHECK([for Objective-C++ compiler], [cs_cv_prog_objcxx], - [cs_cv_prog_objcxx="$CXX"]) - CS_JAMCONFIG_PROPERTY([CMD.OBJC++], [$cs_cv_prog_objcxx])], - - [cs_host_target=unix - cs_host_family=unix])]) -# diagnose.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_MSG_ERROR(ERROR-DESCRIPTION, [EXIT-STATUS]) -# A convenience wrapper for AC_MSG_ERROR() which invokes AC_CACHE_SAVE() -# before aborting the script. Saving the cache should make subsequent -# re-invocations of the configure script faster once the user has -# corrected the problem(s) which caused the failure. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_MSG_ERROR], - [AC_CACHE_SAVE - AC_MSG_ERROR([$1], [$2])]) -# embed.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003,2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_META_INFO_EMBED([EMITTER], [GPL-OKAY]) -# Determine if plugin meta-information should be embedded or if it should -# exist in a stand-alone .csplugin file, and check if necessary tools and -# libraries are present. Sets the shell variable -# enable_meta_info_embedding to "yes" if the user requested embedding or -# if it was enabled by default; otherwise sets it to "no". -# -# If EMITTER is provided, then a subset of the following variables -# (depending upon platform and availability) are recorded by invoking -# CS_EMIT_BUILD_PROPERTY() with EMITTER. As a convenience, if EMITTER is -# the literal value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s -# default emitter will be used. -# -# EMBED_META := yes or no -# EMBED_META.CFLAGS := compiler flags -# EMBED_META.LFLAGS := linker flags -# CMD.WINDRES := windres.exe -# OBJCOPY.AVAILABLE := yes or no -# CMD.OBJCOPY := objcopy.exe -# LIBBFD.AVAILABLE := yes or no -# LIBBFD.CFLAGS := libbfd compiler flags -# LIBBFD.LFLAGS := libbfd linker flags -# ELF.AVAILABLE := yes or no -# -# In general, clients need only concern themselves with the various -# EMBED_META-related variables. For building plugin modules, utilize -# EMBED_META.CFLAGS when compiling, and EMBED_META.LFLAGS when linking. -# -# On Unix, when CS' own ELF metadata reader can't be used (because the -# necessary header file elf.h was not found) embedding is accomplished -# via libbfd, which carries a GPL license. Projects which carry licenses -# not compatible with GPL should consider carefully before enabling -# embedding on Unix. If your project is GPL-compatible, then set GPL-OKAY -# to "yes". This will indicate that it is safe to use libbfd if the ELF -# reader can not be used. If your project is not GPL-compatible, then -# set it to "no" in order to disable embedding on Unix if the ELF reader -# is not usable. (The user can still manually override the setting via -# the --enable-meta-info-embedding option.) -# -# IMPLEMENTATION NOTES -# -# Recent versions of Mingw supply libbfd and libiberty. Since Crystal -# Space uses native Win32 API for meta-information embedding on Windows, -# we do not require these libraries on Windows. More importantly, users -# do not want to see these GPL-licensed libraries appear in the link -# statement for plugin modules, thus we explicitly disable the libbfd -# test on Windows. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_META_INFO_EMBED], - [AC_REQUIRE([AC_CANONICAL_HOST]) - _CS_META_INFO_EMBED_ENABLE([$1], [$2]) - AS_IF([test $enable_meta_info_embedding = yes], - [_CS_META_INFO_EMBED_TOOLS([$1]) - AS_IF([test $cs_header_elf_h = yes], - [CS_EMIT_BUILD_PROPERTY([ELF.AVAILABLE], [yes], [], [], - CS_EMITTER_OPTIONAL([$1]))], - [case $host_os in - mingw*|cygwin*) ;; - *) - CS_CHECK_LIBBFD([$1], - [CS_EMIT_BUILD_PROPERTY([EMBED_META.CFLAGS], - [$cs_cv_libbfd_ok_cflags], [+], [], - CS_EMITTER_OPTIONAL([$1])) - CS_EMIT_BUILD_PROPERTY([EMBED_META.LFLAGS], - [$cs_cv_libbfd_ok_lflags $cs_cv_libbfd_ok_libs], - [+], [], CS_EMITTER_OPTIONAL([$1]))]) - ;; - esac])])]) - - -#------------------------------------------------------------------------------ -# _CS_META_INFO_EMBED_ENABLE([EMITTER], [GPL-OKAY]) -# Helper for CS_META_INFO_EMBED which adds an -# --enable-meta-info-embedding option to the configure script allowing -# the user to control embedding. Sets the shell variable -# enable_meta_info_embedding to yes or no. -# -# IMPLEMENTATION NOTES -# -# On Unix, embedding is enabled by default if elf.h is found and disabled -# by default unless overridden via GPL-OKAY because libbfd carries a GPL -# license which may be incompatible with a project's own license (such as -# LGPL). -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_META_INFO_EMBED_ENABLE], - [AC_REQUIRE([CS_CHECK_HOST]) - AC_CHECK_HEADERS([elf.h], [cs_header_elf_h=yes], [cs_header_elf_h=no]) - AC_MSG_CHECKING([whether to embed plugin meta-information]) - case $cs_host_target in - unix) AS_IF([test $cs_header_elf_h = yes], - [cs_embed_meta_info_default=yes], - [cs_embed_meta_info_default=m4_ifval([$2],[$2],[no])]) ;; - *) cs_embed_meta_info_default=yes ;; - esac - AC_ARG_ENABLE([meta-info-embedding], - [AC_HELP_STRING([--enable-meta-info-embedding], - [store plugin meta-information directly inside plugin modules if - supported by platform; if disabled, meta-information is stored in - stand-alone .csplugin files; this option is enabled by default for - non-Unix platforms and on Unix platforms with ELF-format object - files; it is disabled by default on Unix platforms if ELF is not - available and the project uses a non-GPL-compatible license (such - as LGPL) since the non-ELF Unix embedding technology requires the - GPL-licensed libbfd library; if ELF is not available, enable this - option on Unix only if you are certain you want a GPL-licensed - library infecting your project])], - [], [enable_meta_info_embedding=$cs_embed_meta_info_default]) - AC_MSG_RESULT([$enable_meta_info_embedding]) - CS_EMIT_BUILD_PROPERTY([EMBED_META], [$enable_meta_info_embedding], - [], [], CS_EMITTER_OPTIONAL([$1]))]) - - - -#------------------------------------------------------------------------------ -# _CS_META_INFO_EMBED_TOOLS([EMITTER]) -# Helper for CS_META_INFO_EMBED() which searches for tools required for -# plugin meta-info embedding. -#------------------------------------------------------------------------------ -AC_DEFUN([_CS_META_INFO_EMBED_TOOLS], - [CS_CHECK_TOOLS([WINDRES], [windres]) - CS_EMIT_BUILD_PROPERTY([CMD.WINDRES], [$WINDRES], [], [], - CS_EMITTER_OPTIONAL([$1])) - - CS_CHECK_TOOLS([OBJCOPY], [objcopy]) - AS_IF([test -n "$OBJCOPY"], - [CS_EMIT_BUILD_PROPERTY([OBJCOPY.AVAILABLE], [yes], [], [], - CS_EMITTER_OPTIONAL([$1])) - CS_EMIT_BUILD_PROPERTY([CMD.OBJCOPY], [$OBJCOPY], [], [], - CS_EMITTER_OPTIONAL([$1]))])]) - - - -#------------------------------------------------------------------------------ -# CS_CHECK_LIBBFD([EMITTER], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# Exhaustive check for a usable GPL-licensed libbfd, the Binary File -# Descriptor library, a component of binutils, which allows low-level -# manipulation of executable and object files. If EMITTER is provided, -# then the following variables are recorded by invoking -# CS_EMIT_BUILD_PROPERTY() with EMITTER. As a convenience, if EMITTER is -# the literal value "emit" or "yes", then CS_EMIT_BUILD_RESULT()'s -# default emitter will be used. -# -# LIBBFD.AVAILABLE := yes or no -# LIBBFD.CFLAGS := libbfd compiler flags -# LIBBFD.LFLAGS := libbfd linker flags -# -# The shell variable cs_cv_libbfd_ok is set to yes if a usable libbfd was -# discovered, else no. If found, the additional shell variables -# cs_cv_libbfd_ok_cflags, cs_cv_libbfd_ok_lflags, and -# cs_cv_libbfd_ok_libs are also set. -# -# WARNING -# -# libbfd carries a GPL license which is incompatible with the LGPL -# license of Crystal Space. Do not use this library with projects under -# less restrictive licenses, such as LGPL. -# -# IMPLEMENTATION NOTES -# -# It seems that some platforms have two version of libiberty installed: -# one from binutils and one from gcc. The binutils version resides in -# /usr/lib, whereas the gcc version resides in the gcc installation -# directory. The gcc version, by default, takes precedence at link time -# over the binutils version. Unfortunately, in broken cases, the gcc -# version of libiberty is missing htab_create_alloc() which is required -# by some libbfd functions. The extensive secondary check of libbfd -# catches this anomalous case of broken gcc libiberty. It turns out that -# it is possible to make the linker prefer the binutils version by -# specifying -L/usr/lib, thus the extensive test attempts to do so in an -# effort to resolve this unfortunate issue. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_LIBBFD], - [CS_CHECK_LIB_WITH([bfd], - [AC_LANG_PROGRAM([[#include ]], [bfd_init();])], - [], [], [], [], [], [], [-liberty]) - - AS_IF([test $cs_cv_libbfd = yes], - [CS_CHECK_BUILD([if libbfd is usable], [cs_cv_libbfd_ok], - [AC_LANG_PROGRAM([[#include ]], - [bfd* p; - asection* s; - bfd_init(); - p = bfd_openr(0,0); - bfd_check_format(p,bfd_object); - bfd_get_section_by_name(p,0); - bfd_section_size(p,s); - bfd_get_section_contents(p,s,0,0,0); - bfd_close(p);])], - [CS_CREATE_TUPLE() CS_CREATE_TUPLE([],[-L/usr/lib],[])], - [], [], [], [], - [$cs_cv_libbfd_cflags], - [$cs_cv_libbfd_lflags], - [$cs_cv_libbfd_libs])], - [cs_cv_libbfd_ok=no]) - - AS_IF([test $cs_cv_libbfd_ok = yes], - [CS_EMIT_BUILD_RESULT([cs_cv_libbfd_ok], [LIBBFD], - CS_EMITTER_OPTIONAL([$1])) - $2], - [$3])]) -# emit.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003-2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_EMIT_BUILD_PROPERTY(KEY, VALUE, [APPEND], [EMPTY-OKAY], [EMITTER], -# [UNCONDITIONAL]) -# A utility function which invokes an emitter to record the KEY/VALUE -# tuple if VALUE is not the empty string (after leading and trailing -# whitespace is stripped). If EMPTY-OKAY is not an empty string, then the -# property is emitted even if VALUE is empty; that is, it is emitted -# unconditionally. If APPEND is the empty string, then the emitter sets -# the key's value directly (though it may be overridden by the -# environment), otherwise the emitter appends VALUE to the existing value -# of the key. EMITTER is a macro name, such as CS_JAMCONFIG_PROPERTY or -# CS_MAKEFILE_PROPERTY, which performs the actual task of emitting the -# KEY/VALUE tuple; it should also accept APPEND as an optional third -# argument. If EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. Some -# emitters accept an optional fourth argument, UNCONDITIONAL, which -# instructs it to set KEY's value unconditionally, even if KEY already -# had been assigned a value via some other mechanism (such as imported -# from the environment, or from Jambase, in the case of -# CS_JAMCONFIG_PROPERTY). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_EMIT_BUILD_PROPERTY], - [cs_build_prop_val="$2" - cs_build_prop_val=CS_TRIM([$cs_build_prop_val]) - m4_ifval([$4], - [CS_JAMCONFIG_PROPERTY([$1], [$cs_build_prop_val], [$3])], - AS_IF([test -n "$cs_build_prop_val"], - [m4_default([$5],[CS_JAMCONFIG_PROPERTY])( - [$1], [$cs_build_prop_val], [$3], [$6])]))]) - - - -#------------------------------------------------------------------------------ -# CS_EMIT_BUILD_RESULT(CACHE-VAR, PREFIX, [EMITTER]) -# Record the results of CS_CHECK_BUILD() or CS_CHECK_LIB_WITH() via some -# emitter. If CACHE-VAR indicates that the build succeeded, then the -# following properties are emitted: -# -# PREFIX.AVAILABLE = yes -# PREFIX.CFLAGS = $CACHE-VAR_cflags -# PREFIX.LFLAGS = $CACHE-VAR_lflags $CACHE-VAR_libs -# -# EMITTER is a macro name, such as CS_JAMCONFIG_PROPERTY or -# CS_MAKEFILE_PROPERTY, which performs the actual task of emitting the -# KEY/VALUE tuple. If EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_EMIT_BUILD_RESULT], - [AS_IF([test "$$1" = yes], - [CS_EMIT_BUILD_PROPERTY([$2.AVAILABLE], [yes], [], [], [$3]) - CS_EMIT_BUILD_PROPERTY([$2.CFLAGS], [$$1_cflags], [], [], [$3]) - CS_EMIT_BUILD_PROPERTY([$2.LFLAGS], [$$1_lflags $$1_libs], - [], [], [$3])])]) - - - -#------------------------------------------------------------------------------ -# CS_EMIT_BUILD_FLAGS(MESSAGE, CACHE-VAR, FLAGS, [LANGUAGE], EMITTER-KEY, -# [APPEND], [ACTION-IF-RECOGNIZED], -# [ACTION-IF-NOT-RECOGNIZED], [EMITTER]) -# A convenience wrapper for CS_CHECK_BUILD_FLAGS() which also records the -# results via CS_EMIT_BUILD_PROPERTY(). Checks if the compiler or linker -# recognizes a command-line option. MESSAGE is the "checking" message. -# CACHE-VAR is the shell cache variable which receives the flag -# recognized by the compiler or linker, or "no" if the flag was not -# recognized. FLAGS is a whitespace- delimited list of build tuples -# created with CS_CREATE_TUPLE(). Each tuple from FLAGS is attempted in -# order until one is found which is recognized by the compiler. After -# that, no further flags are checked. LANGUAGE is typically either C or -# C++ and specifies which compiler to use for the test. If LANGUAGE is -# omitted, C is used. EMITTER-KEY is the name to pass as the emitter's -# "key" argument if a usable flag is encountered. If APPEND is not the -# empty string, then the discovered flag is appended to the existing -# value of the EMITTER-KEY. If the command-line option was recognized, -# then ACTION-IF-RECOGNIZED is invoked, otherwise -# ACTION-IF-NOT-RECOGNIZED is invoked. EMITTER is a macro name, such as -# CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, which performs the -# actual task of emitting the KEY/VALUE tuple; it should also accept -# APPEND as an optional third argument. If EMITTER is omitted, -# CS_JAMCONFIG_PROPERTY is used. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_EMIT_BUILD_FLAGS], - [CS_CHECK_BUILD_FLAGS([$1], [$2], [$3], [$4], - [CS_EMIT_BUILD_PROPERTY([$5], [$$2], [$6], [], [$9]) - $7], - [$8])]) - - - -#------------------------------------------------------------------------------ -# CS_EMITTER_OPTIONAL([EMITTER]) -# The CS_EMIT_FOO() macros optionally accept an emitter. If no emitter is -# supplied to those macros, then a default emitter is chosen. Other -# macros, however, which perform testing and optionally emit the results -# may wish to interpret an omitted EMITTER as a request not to emit the -# results. CS_EMITTER_OPTIONAL() is a convenience macro to help in these -# cases. It should be passed to one of the CS_EMIT_FOO() macros in place -# of the literal EMITTER argument. It functions by re-interpretating -# EMITTER as follows: -# -# - If EMITTER is omitted, then CS_NULL_EMITTER is returned, effectively -# disabling output by the CS_EMIT_FOO() macro. -# - If EMITTER is the literal string "emit" or "yes", then it returns an -# empty string, which signals to the CS_EMIT_FOO() macro that is should -# use its default emitter. -# - Any other value for EMITTER is passed along as-is to the -# CS_EMIT_FOO() macro. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_EMITTER_OPTIONAL], - [m4_case([$1], - [], [[CS_NULL_EMITTER]], - [emit], [], - [yes], [], - [[$1]])]) - - - -#------------------------------------------------------------------------------ -# CS_NULL_EMITTER(KEY, VALUE, [APPEND]) -# A do-nothing emitter suitable for use as the EMITTER argument of one of -# the CS_EMIT_FOO() macros. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_NULL_EMITTER], [: -]) - - - -#------------------------------------------------------------------------------ -# CS_SUBST_EMITTER(KEY, VALUE, [APPEND]) -# An emitter wrapped around AC_SUBST(). Invokes -# AC_SUBST(AS_TR_SH(KEY),VALUE). The APPEND argument is ignored. -# Suitable for use as the EMITTER argument of one of the CS_EMIT_FOO() -# macros. The call to AS_TR_SH() ensures that KEY is transformed into a -# valid shell variable. For instance, if a macro attempts to emit -# MYLIB.CFLAGS and MYLIB.LFLAGS via CS_SUBST_EMITTER(), then the names -# will be transformed to MYLIB_CFLAGS and MYLIB_LFLAGS, respectively, for -# the invocation of AC_SUBST(). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_SUBST_EMITTER], [AC_SUBST(AS_TR_SH([$1]),[$2])]) - - - -#------------------------------------------------------------------------------ -# CS_DEFINE_EMITTER(KEY, VALUE, [APPEND]) -# An emitter wrapped around AC_DEFINE_UNQUOTED(). Invokes -# AC_DEFINE_UNQUOTED(AS_TR_CPP(KEY),VALUE). The APPEND argument is -# ignored. Suitable for use as the EMITTER argument of one of the -# CS_EMIT_FOO() macros. The call to AS_TR_CPP() ensures that KEY is a -# well-formed token for the C-preprocessor. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_DEFINE_EMITTER], - [AC_DEFINE_UNQUOTED(AS_TR_CPP([$1]),[$2], - [Define when feature is available])]) -# headercache.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# Text cache facility for C-style #define properties. The cache is stored in -# the shell variable cs_header_text. -# -# CS_HEADER_APPEND(TEXT) -# Append text to the C header text cache. This is a cover for -# CS_TEXT_CACHE_APPEND(). -# -# CS_HEADER_PREPEND(TEXT) -# Prepend text to the C header text cache. This is a cover for -# CS_TEXT_CACHE_PREPEND(). -# -# CS_HEADER_PROPERTY(KEY, [VALUE]) -# Append a line of the form "#define KEY VALUE" to the C header text -# cache. If the VALUE argument is omitted, then the appended line has -# the simplified form "#define KEY". -# -# CS_HEADER_OUTPUT(FILENAME) -# Instruct config.status to write the C header text cache to the given -# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_HEADER_APPEND], [CS_TEXT_CACHE_APPEND([cs_header_text], [$1])]) -AC_DEFUN([CS_HEADER_PREPEND], [CS_TEXT_CACHE_PREPEND([cs_header_text], [$1])]) -AC_DEFUN([CS_HEADER_PROPERTY], -[CS_HEADER_APPEND([@%:@define $1[]m4_ifval([$2], [ $2], []) -])]) -AC_DEFUN([CS_HEADER_OUTPUT], [CS_TEXT_CACHE_OUTPUT([cs_header_text], [$1])]) -#----------------------------------------------------------------------------- -# installdirs.m4 (c) Matze Braun -# Macro for emitting the installation paths gathered by Autoconf. -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# CS_OUTPUT_INSTALLDIRS([EMITTER], [RAW-BACKSLASHES]) -# Emit installation directories collected by Autoconf. EMITTER is a macro -# name, such as CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, which performs -# the actual task of emitting the KEY/VALUE tuple. If EMITTER is omitted, -# CS_JAMCONFIG_PROPERTY is used. If RAW-BACKSLASHES is not provided, then -# backslashes in emitted values are each escaped with an additional -# backslash. If RAW-BACKSLASHES is not the null value, then backslashes are -# emitted raw. The following properties are emitted: -# -# prefix -# exec_prefix -# bindir -# sbindir -# libexecdir -# datadir -# sysconfdir -# sharedstatedir -# localstatedir -# libdir -# includedir -# oldincludedir -# infodir -# mandir -#----------------------------------------------------------------------------- -AC_DEFUN([CS_OUTPUT_INSTALLDIRS],[ -# Handle the case when no prefix is given, and the special case when a path -# contains more than 2 slashes, these paths seem to be correct but Jam fails -# on them. -AS_IF([test $prefix = NONE], - [cs_install_prefix="$ac_default_prefix"], - [cs_install_prefix=`echo "$prefix" | sed -e 's:///*:/:g'`]) -AS_IF([test $exec_prefix = NONE], - [cs_install_exec_prefix="AS_ESCAPE([$(prefix)])"], - [cs_install_exec_prefix=`echo "$exec_prefix" | sed -e 's:///*:/:g'`]) - -_CS_OUTPUT_INSTALL_DIRS([$1], [prefix], - [CS_PREPARE_INSTALLPATH([$cs_install_prefix], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [exec_prefix], - [CS_PREPARE_INSTALLPATH([$cs_install_exec_prefix], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [bindir], - [CS_PREPARE_INSTALLPATH([$bindir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [sbindir], - [CS_PREPARE_INSTALLPATH([$sbindir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [libexecdir], - [CS_PREPARE_INSTALLPATH([$libexecdir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [datadir], - [CS_PREPARE_INSTALLPATH([$datadir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [sysconfdir], - [CS_PREPARE_INSTALLPATH([$sysconfdir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [sharedstatedir], - [CS_PREPARE_INSTALLPATH([$sharedstatedir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [localstatedir], - [CS_PREPARE_INSTALLPATH([$localstatedir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [libdir], - [CS_PREPARE_INSTALLPATH([$libdir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [includedir], - [CS_PREPARE_INSTALLPATH([$includedir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [oldincludedir], - [CS_PREPARE_INSTALLPATH([$oldincludedir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [infodir], - [CS_PREPARE_INSTALLPATH([$infodir], [$2])]) -_CS_OUTPUT_INSTALL_DIRS([$1], [mandir], - [CS_PREPARE_INSTALLPATH([$mandir], [$2])]) -]) - -AC_DEFUN([_CS_OUTPUT_INSTALL_DIRS], - [m4_default([$1], [CS_JAMCONFIG_PROPERTY])([$2], [$3])]) - - -#----------------------------------------------------------------------------- -# CS_PREPARE_INSTALLPATH(VALUE, [RAW-BACKSLASHES]) -# Transform variable references of the form ${bla} to $(bla) in VALUE and -# correctly quotes backslashes. This is needed if you need to emit some of -# the paths from Autoconf. RAW-BACKSLASHES has the same meaning as in -# CS_OUTPUT_INSTALLDIRS. -#----------------------------------------------------------------------------- -AC_DEFUN([CS_PREPARE_INSTALLPATH], -[`echo "$1" | sed 's/\${\([[a-zA-Z_][a-zA-Z_]]*\)}/$(\1)/g;m4_ifval([$2], - [s/\\/\\\\/g], [s/\\\\/\\\\\\\\/g])'`]) -# jamcache.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# Text cache facility for Jam-style properties. The cache is stored in -# the shell variable cs_jamfile_text. -# -# CS_JAMCONFIG_APPEND(TEXT) -# Append text to the Jam text cache. This is a cover for -# CS_TEXT_CACHE_APPEND(). -# -# CS_JAMCONFIG_PREPEND(TEXT) -# Prepend text to the Jam text cache. This is a cover for -# CS_TEXT_CACHE_PREPEND(). -# -# CS_JAMCONFIG_PROPERTY(KEY, VALUE, [APPEND], [UNCONDITIONAL]) -# Append a line of the form "KEY ?= VALUE" to the Jam text cache. If the -# APPEND argument is not the empty string, then VALUE is appended to the -# existing value of KEY using the form "KEY += VALUE". If the -# UNCONDITIONAL argument is not empty, then the value of KEY is set -# unconditionally "KEY = VALUE", rather than via "KEY ?= VALUE". APPEND -# takes precedence over UNCONDITIONAL. Note that if VALUE references -# other Jam variables, for example $(OBJS), then be sure to protect the -# value with AS_ESCAPE(). For example: -# CS_JAMCONFIG_PROPERTY([ALLOBJS], [AS_ESCAPE([$(OBJS) $(LIBOBJS)])]) -# -# CS_JAMCONFIG_OUTPUT(FILENAME) -# Instruct config.status to write the Jam text cache to the given -# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_JAMCONFIG_APPEND], - [CS_TEXT_CACHE_APPEND([cs_jamconfig_text], [$1])]) -AC_DEFUN([CS_JAMCONFIG_PREPEND], - [CS_TEXT_CACHE_PREPEND([cs_jamconfig_text], [$1])]) -AC_DEFUN([CS_JAMCONFIG_PROPERTY], - [CS_JAMCONFIG_APPEND( - [$1 m4_ifval([$3], [+=], m4_ifval([$4], [=], [?=])) \"$2\" ; -])]) -AC_DEFUN([CS_JAMCONFIG_OUTPUT], - [CS_TEXT_CACHE_OUTPUT([cs_jamconfig_text], [$1])]) -# makecache.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# Text cache facility for makefile-style properties. The cache is stored in -# the shell variable cs_makefile_text. -# -# CS_MAKEFILE_APPEND(TEXT) -# Append text to the makefile text cache. This is a cover for -# CS_TEXT_CACHE_APPEND(). -# -# CS_MAKEFILE_PREPEND(TEXT) -# Prepend text to the makefile text cache. This is a cover for -# CS_TEXT_CACHE_PREPEND(). -# -# CS_MAKEFILE_PROPERTY(KEY, VALUE, [APPEND]) -# Append a line of the form "KEY = VALUE" to the makefile text cache. If -# the APPEND argument is not the empty string, then VALUE is appended to -# the existing value of KEY using the form "KEY += VALUE". Note that if -# VALUE references other makefile variables, for example $(OBJS), then be -# sure to protect the value with AS_ESCAPE(). For example: -# CS_MAKEFILE_PROPERTY([ALLOBJS], [AS_ESCAPE([$(OBJS) $(LIBOBJS)])]) -# -# CS_MAKEFILE_OUTPUT(FILENAME) -# Instruct config.status to write the makefile text cache to the given -# filename. This is a cover for CS_TEXT_CACHE_OUTPUT(). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_MAKEFILE_APPEND], - [CS_TEXT_CACHE_APPEND([cs_makefile_text], [$1])]) -AC_DEFUN([CS_MAKEFILE_PREPEND], - [CS_TEXT_CACHE_PREPEND([cs_makefile_text], [$1])]) -AC_DEFUN([CS_MAKEFILE_PROPERTY], - [CS_MAKEFILE_APPEND([$1 m4_ifval([$3], [+=], [=]) $2 -])]) -AC_DEFUN([CS_MAKEFILE_OUTPUT],[CS_TEXT_CACHE_OUTPUT([cs_makefile_text], [$1])]) -# mkdir.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_CHECK_MKDIR -# Determine how to create a directory and a directory tree. Sets the -# shell variable MKDIR to the command which creates a directory, and -# MKDIRS to the command which creates a directory tree. Invokes -# AC_SUBST() for MKDIR and MKDIRS. -# -# IMPLEMENTATION NOTES -# We need to know the exact commands, so that we can emit them, thus the -# AS_MKDIR_P function is not what we want to use here since it does not -# provide access to the commands (and might not even discover suitable -# commands). First try "mkdir -p", then try the older "mkdirs". -# Finally, if the mkdir command failed to recognize -p, then it might -# have created a directory named "-p", so clean up that bogus directory. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_CHECK_MKDIR], - [AC_CACHE_CHECK([how to create a directory], [cs_cv_shell_mkdir], - [cs_cv_shell_mkdir='mkdir']) - AC_SUBST([MKDIR], [$cs_cv_shell_mkdir]) - - AC_CACHE_CHECK([how to create a directory tree], [cs_cv_shell_mkdir_p], - [if $cs_cv_shell_mkdir -p . 2>/dev/null; then - cs_cv_shell_mkdir_p='mkdir -p' - elif mkdirs . 2>/dev/null; then - cs_cv_shell_mkdir_p='mkdirs' - fi - test -d ./-p && rmdir ./-p]) - AS_VAR_SET_IF([cs_cv_shell_mkdir_p], - [AC_SUBST([MKDIRS], [$cs_cv_shell_mkdir_p])], - [CS_MSG_ERROR([do not know how to create a directory tree])])]) - - - -#------------------------------------------------------------------------------ -# Replacement for AS_MKDIR_P() from m4sugar/m4sh.m4 which fixes two problems -# which are present in Autoconf 2.57 and probably all earlier 2.5x versions. -# This bug, along with a patch, was submitted to the Autoconf GNATS database by -# Eric Sunshine as #227 on 17-Dec-2002. The bogus "-p" directory bug was fixed -# for Autoconf 2.58 on 26-Sep-2003. The "mkdirs" optimization was not accepted -# (since it is unnecessary; it's only an optimization). -# -# 1) Removes bogus "-p" directory which the stock AS_MKDIR_P() leaves laying -# around in the working directory if the mkdir command does not recognize -# the -p option. -# 2) Takes advantage of the older "mkdirs" program if it exists and if "mkdir -# -p" does not work. -#------------------------------------------------------------------------------ -m4_defun([_AS_MKDIR_P_PREPARE], -[if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p' -elif mkdirs . 2>/dev/null; then - as_mkdir_p='mkdirs' -else - as_mkdir_p='' -fi -test -d ./-p && rmdir ./-p -])# _AS_MKDIR_P_PREPARE - -m4_define([AS_MKDIR_P], -[AS_REQUIRE([_$0_PREPARE])dnl -{ if test -n "$as_mkdir_p"; then - $as_mkdir_p $1 - else - as_dir=$1 - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`AS_DIRNAME("$as_dir")` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || AS_ERROR([cannot create directory $1]); } -])# AS_MKDIR_P -#============================================================================== -# packageinfo.m4 -# Macros for setting general info on the package, such as name and version -# numbers and propagate them to the generated make and Jam property files. -# -# Copyright (C)2003 by Matthias Braun -# Copyright (C)2003,2004 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== - -#------------------------------------------------------------------------------ -# CS_PACKAGEINFO([LONGNAME], [COPYRIGHT, [HOMEPAGE]) -# Set additional information for the package. Note that the version -# number of your application should only contain numbers, because on -# Windows you can only set numerical values in some of the file -# properties (such as versioninfo .rc files). -#------------------------------------------------------------------------------ -AC_DEFUN([CS_PACKAGEINFO], - [PACKAGE_LONGNAME="[$1]" - PACKAGE_COPYRIGHT="[$2]" - PACKAGE_HOMEPAGE="[$3]" -]) - - -#------------------------------------------------------------------------------ -# CS_EMIT_PACKAGEINFO([EMITTER]) -# Emit extended package information using the provided EMITTER. EMITTER -# is a macro name, such as CS_JAMCONFIG_PROPERTY or CS_MAKEFILE_PROPERTY, -# which performs the actual task of emitting the KEY/VALUE tuple. If -# EMITTER is omitted, CS_JAMCONFIG_PROPERTY is used. For backward -# compatibility, if EMITTER is the literal value "jam", then -# CS_JAMCONFIG_PROPERTY is used; if it is "make", then -# CS_MAKEFILE_PROPERTY is used; however use of these literal names is -# highly discouraged. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_EMIT_PACKAGEINFO], - [_CS_EMIT_PACKAGEINFO([$1], [PACKAGE_NAME], [$PACKAGE_NAME]) - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_VERSION], [$PACKAGE_VERSION]) - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_STRING], [$PACKAGE_STRING]) - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_BUGREPORT], [$PACKAGE_BUGREPORT]) - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_LONGNAME], [$PACKAGE_LONGNAME]) - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_HOMEPAGE], [$PACKAGE_HOMEPAGE]) - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_COPYRIGHT], [$PACKAGE_COPYRIGHT]) - for cs_veritem in m4_translit(AC_PACKAGE_VERSION, [.], [ ]); do - _CS_EMIT_PACKAGEINFO([$1], [PACKAGE_VERSION_LIST], [$cs_veritem], [+]) - done - ]) - -AC_DEFUN([_CS_EMIT_PACKAGEINFO], - [m4_case([$1], - [make], [CS_MAKEFILE_PROPERTY([$2], [$3], [$4])], - [jam], [CS_JAMCONFIG_PROPERTY([$2], [$3], [$4])], - [], [CS_JAMCONFIG_PROPERTY([$2], [$3], [$4])], - [$1([$2], [$3], [$4])])]) -# path.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2004 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_PATH_NORMALIZE(STRING) -# Normalize a pathname at run-time by transliterating Windows/DOS -# backslashes to forward slashes. Also collapses whitespace. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_PATH_NORMALIZE], -[`echo "x$1" | tr '\\\\' '/' | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) - - -#------------------------------------------------------------------------------ -# CS_RUN_PATH_NORMALIZE(COMMAND) -# Normalize the pathname emitted by COMMAND by transliterating -# Windows/DOS backslashes to forward slashes. Also collapses whitespace. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_RUN_PATH_NORMALIZE], -[`AC_RUN_LOG([$1]) | tr '\\\\' '/' | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) -############################################################################### -# progver.m4 -# Written by Norman Kramer -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -############################################################################### -# -# From the input pattern we create regular expressions we send through sed -# to extract the version information from the standard input to sed. -# Then we extract from the resulting version string subparts. -# The same happens with the supplied version string. It too is split into its -# subparts according to the pattern. -# Then the subparts from the gathered version string and the supplied one are -# compared. -# -# How does the pattern look like ? -# It is a sequence of 9s and _s and separators. -# 9 denotes a non empty sequence of digits. -# _ denotes a non empty sequence of characters from the class [a-zA-Z]. -# | everything behind is optional -# Everything else is treated as a separator. -# Consecutive 9s and _s are compressed to contain only one of each type. -# For instance "99_.9.__abc9_" will become "9_.9._abc9_". -# -# How we find the parts we compare ? -# From this transformed string we yield the parts we will later compare. -# We break up the string as follows: -# Any sequence of separators represent one breakup. Additional breakups are -# placed behind every 9 and _ . -# So the example from above will give: -# -# "99_.9.__abc9_" ===compress==> "9_.9._abc9_" ===breakup==> "9" "_" "9" "_" "9" "_" -# -# How we create the regular expressions ? -# We take the compressed pattern and quote every separator. -# The we replace the 9s with [0-9][0-9]* -# and the _s with [a-zA-Z][a-zA-Z]* . -# The above example will become: -# -# "99_.9.__abc9_" ===compress==> "9_.9._abc9_" ===rexify==> -# [0-9][0-9]*[a-zA-Z][a-zA-Z]*\.[0-9][0-9]*\.[a-zA-Z][a-zA-Z]*\a\b\c[0-9][0-9]*[a-zA-Z][a-zA-Z]* -# -# Voila. -# -# To yield the subparts from the string we additionally enclose the -# 9s and _s with \( and \). -# -############################################################################### - -# **************************************************************** -# ** helper definitions ** -# **************************************************************** -m4_define([CS_VCHK_RUNTH], [m4_pushdef([i], [$1])m4_if($1,0,,[CS_VCHK_RUNTH(m4_decr($1), [$2])][$2])m4_popdef([i])]) -m4_define([CS_VCHK_PREFIX], []) -m4_define([CS_VCHK_SUFFIX], []) -m4_define([CS_VCHK_GROUPPREFIX], [\(]) -m4_define([CS_VCHK_GROUPSUFFIX], [\)]) -m4_define([CS_VCHK_CHAR], [[[[a-zA-Z]]]]) -m4_define([CS_VCHK_DIGIT], [[[0-9]]]) -m4_define([CS_VCHK_SEQUENCE], [CS_VCHK_PREFIX[]CS_VCHK_SINGLE[]CS_VCHK_SINGLE[]*CS_VCHK_SUFFIX[]]) -m4_define([CS_VCHK_OPTSEQUENCE], [CS_VCHK_PREFIX[]CS_VCHK_SINGLE[]*CS_VCHK_SUFFIX[]]) -m4_define([CS_VCHK_REXSEQ], [m4_bpatsubst($1, [$2], [[]CS_VCHK_SEQUENCE[]])]) -m4_define([CS_VCHK_GROUPINGON], [m4_pushdef([CS_VCHK_PREFIX], [CS_VCHK_GROUPPREFIX])m4_pushdef([CS_VCHK_SUFFIX], [CS_VCHK_GROUPSUFFIX])]) -m4_define([CS_VCHK_GROUPINGOFF], [m4_popdef([CS_VCHK_SUFFIX])m4_popdef([CS_VCHK_PREFIX])]) -m4_define([CS_VCHK_OPTON], [m4_pushdef([CS_VCHK_SEQUENCE], [CS_VCHK_OPTSEQUENCE])]) -m4_define([CS_VCHK_OPTOFF], [m4_popdef([CS_VCHK_SEQUENCE])]) -m4_define([CS_VCHK_RMOPT], [CS_VCHK_RMCHAR([$1], m4_index([$1], [|]))]) -m4_define([CS_VCHK_RMCHAR], [m4_if($2,-1,[$1],m4_substr([$1], 0, $2)[]m4_substr([$1], m4_incr($2)))]) -m4_define([CS_VCHK_RMALL], [m4_translit([$1], [|], [])]) -m4_define([CS_VCHK_CUTOFF], [m4_if(m4_index($1,[|]),-1, [$1], [m4_substr($1, 0, m4_index($1,[|]))])]) -m4_define([CS_VCHK_CYCLEOPT], [ -m4_if($2,-1,, [m4_pushdef([i], CS_VCHK_CUTOFF([$1])) m4_pushdef([j], CS_VCHK_DUMMY_TAIL([$1])) CS_VCHK_CYCLEOPT( CS_VCHK_RMOPT([$1]), m4_index($1, [|]), [$3])$3 m4_popdef([i]) m4_popdef([j])]) -]) -m4_define([CS_VCHK_TAIL], [m4_if(m4_index($1,[|]),-1, [], [m4_substr($1, m4_incr(m4_index($1,[|])))])]) -m4_define([CS_VCHK_DUMMY_COMPRESS], [m4_bpatsubst(m4_bpatsubst([$1], [__*], [A]), [99*], [0])]) -m4_define([CS_VCHK_DUMMY_TAIL], [CS_VCHK_DUMMY_COMPRESS(m4_translit(CS_VCHK_TAIL([$1]), [|], []))]) - -# **************************************************************** -# ** FlagsOn / FlagsOff ** -# **************************************************************** -m4_define([CS_VCHK_FLAGSON], -[m4_if($#, 0, [], - $1, [], [], - [$1], [group], [CS_VCHK_GROUPINGON[]], - [$1], [opt], [CS_VCHK_OPTON[]])dnl -m4_if($#, 0, [], $1, [], [], [CS_VCHK_FLAGSON(m4_shift($@))])]) - -m4_define([CS_VCHK_FLAGSOFF], -[m4_if($#, 0, [], - $1, [], [], - $1, [group], [CS_VCHK_GROUPINGOFF[]], - [$1], [opt], [CS_VCHK_OPTOFF[]])dnl -m4_if($#, 0, [], $1, [], [], [CS_VCHK_FLAGSOFF(m4_shift($@))])]) - -# **************************************************************** -# ** rexify / sedify ** -# **************************************************************** -m4_define([CS_VCHK_REXIFY], -[m4_pushdef([CS_VCHK_SINGLE], [$1])dnl -CS_VCHK_FLAGSON(m4_shift(m4_shift(m4_shift($@))))dnl -CS_VCHK_REXSEQ([$3], [$2])dnl -CS_VCHK_FLAGSOFF(m4_shift(m4_shift(m4_shift($@))))dnl -m4_popdef([CS_VCHK_SINGLE])]) - -m4_define([CS_VCHK_QUOTESEP], [m4_bpatsubst($1, [[^9_]], [\\\&])]) - -m4_define([CS_VCHK_REXCHAR], [CS_VCHK_REXIFY([CS_VCHK_CHAR], [__*], $@)]) -m4_define([CS_VCHK_REXDIGIT], [CS_VCHK_REXIFY([CS_VCHK_DIGIT], [99*], $@)]) -m4_define([CS_VCHK_SEDIFY], [CS_VCHK_REXDIGIT([CS_VCHK_REXCHAR([CS_VCHK_QUOTESEP([$1])], m4_shift($@))], m4_shift($@))]) -m4_define([CS_VCHK_SEDEXPRALL], [/CS_VCHK_SEDIFY([$1])/!d;s/.*\(CS_VCHK_SEDIFY([$1])\).*/\1/;q]) -m4_define([CS_VCHK_SEDEXPRNTH], [/CS_VCHK_SEDIFY([$1])/!d;s/.*CS_VCHK_SEDIFY([$1],[group]).*/\$2/]) - -# **************************************************************** -# ** Pattern splitting ** -# **************************************************************** -m4_define([CS_VCHK_SPLITSEP], [CS_VCHK_REXIFY([s], [[^9_][^9_]*], $@)]) -m4_define([CS_VCHK_SPLITDIGIT], [CS_VCHK_REXIFY([d], [99*], $@)]) -m4_define([CS_VCHK_SPLITCHAR], [CS_VCHK_REXIFY([c], [__*], $@)]) - -# **************************************************************** -# ** return a list of 's' 'd' 'c' 'e' chars denoting the kind ** -# ** pattern parts: separator, digit, char, end ** -# **************************************************************** -m4_define([CS_VCHK_PATTERNLIST], [m4_pushdef([CS_VCHK_SEQUENCE], [CS_VCHK_SINGLE ])dnl -m4_translit(CS_VCHK_SPLITDIGIT([CS_VCHK_SPLITCHAR([CS_VCHK_SPLITSEP([$1])])]), [ ], m4_if([$2],[],[ ],[$2]))e[]dnl -m4_popdef([CS_VCHK_SEQUENCE])]) - -# **************************************************************** -# ** Build the shell commands we emit to the configure script. ** -# **************************************************************** -m4_define([CS_VCHK_PATCOUNT], [m4_len(m4_bpatsubst(CS_VCHK_PATTERNLIST([$1]), [[^dc]]))]) - -# **************************************************************************************** -# ** CS_VCHK_EXTRACTVERSION(EXTRACT_CALL, MIN_VERSION, PATTERN, PRGPREFIX, COMPARISION) ** -# **************************************************************************************** -m4_define([CS_VCHK_EXTRACTVERSION], -[cs_prog_$4_is_version= -cs_prog_$4_min_version= -cs_prog_$4_is_suffix= -cs_prog_$4_min_suffix= -cs_prog_$4_is_suffix_done= -cs_prog_$4_min_suffix_done= -CS_VCHK_CYCLEOPT([$3], [], -[test -z $cs_prog_$4_is_version && cs_prog_$4_is_version=`$1 | sed 'CS_VCHK_SEDEXPRALL([i])'` -test -n "$cs_prog_$4_is_version" && test -z $cs_prog_$4_is_suffix_done && { cs_prog_$4_is_suffix_done=yes ; cs_prog_$4_is_suffix=j ; } -]) -CS_VCHK_CYCLEOPT([$3], , -[test -z $cs_prog_$4_min_version && cs_prog_$4_min_version=`echo $2 | sed 'CS_VCHK_SEDEXPRALL([i])'` -test -n "$cs_prog_$4_min_version" && test -z $cs_prog_$4_min_suffix_done && { cs_prog_$4_min_suffix_done=yes ; cs_prog_$4_min_suffix=j ; } -]) -CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], - [cs_prog_$4_is_ver_[]i=`echo ${cs_prog_$4_is_version}${cs_prog_$4_is_suffix} | sed 'CS_VCHK_SEDEXPRNTH([CS_VCHK_RMALL([$3])], [i])'` -]) -CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], - [cs_prog_$4_min_ver_[]i=`echo $cs_prog_$4_min_version${cs_prog_$4_min_suffix} | sed 'CS_VCHK_SEDEXPRNTH([CS_VCHK_RMALL([$3])], [i])'` -]) -cs_cv_prog_$4_version_ok='' -CS_VCHK_RUNTH([CS_VCHK_PATCOUNT([$3])], -[test -z "$cs_cv_prog_$4_version_ok" && { expr "$cs_prog_$4_is_ver_[]i" "$5" "$cs_prog_$4_min_ver_[]i" >/dev/null || cs_cv_prog_$4_version_ok=no ; } -test -z "$cs_cv_prog_$4_version_ok" && { expr "$cs_prog_$4_min_ver_[]i" "$5" "$cs_prog_$4_is_ver_[]i" >/dev/null || cs_cv_prog_$4_version_ok=yes ; } -]) -AS_IF([test -z "$cs_cv_prog_$4_version_ok"], [cs_cv_prog_$4_version_ok=yes]) -cs_cv_prog_$4_version_ok_annotated="$cs_cv_prog_$4_version_ok" -AS_IF([test -n "$cs_prog_$4_is_version"], - [cs_cv_prog_$4_version_ok_annotated="$cs_cv_prog_$4_version_ok_annotated (version $cs_prog_$4_is_version)"]) -]) - -############################################################################## -# CS_CHECK_PROG_VERSION(PROG, EXTRACT_CALL, VERSION, PATTERN, -# [ACTION-IF-OKAY], [ACTION-IF-NOT-OKAY], [CMP]) -# Check the version of a program PROG. -# Version information is emitted by EXTRACT_CALL (for instance "bison -V"). -# The discovered program version is compared against VERSION. -# The pattern of the version string matches PATTERN -# The extracted version and the supplied version are compared with the CMP -# operator. i.e. EXTRACTED_VERSION CMP SUPPLIED_VERSION -# CMP defaults to >= if not specified. -# ACTION-IF-OKAY is invoked if comparision yields true, otherwise -# ACTION-IF-NOT-OKAY is invoked. -# -# PATTERN literals: 9 .. marks a non empty sequence of digits -# _ .. marks a non empty sequence of characters from [a-zA-Z] -# | .. everything behind is optional -# .. everything else is taken as separator - it is better -# to not try stuff like space, slash or comma. -# -# The test results in cs_cv_prog_PROG_version_ok being either yes or no. -############################################################################## -AC_DEFUN([CS_CHECK_PROG_VERSION], -[AC_CACHE_CHECK([if $1 version m4_default([$7],[>=]) $3], - [AS_TR_SH([cs_cv_prog_$1_version_ok_annotated])], - [CS_VCHK_EXTRACTVERSION([$2], [$3], [$4], AS_TR_SH([$1]), - m4_default([$7],[>=]))]) -AS_IF([test "$AS_TR_SH([cs_cv_prog_$1_version_ok])" = yes], [$5], [$6])]) -# qualify.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_SYMBOL_QUALIFIER(MESSAGE, CACHE-VAR, QUALIFIERS, [SYMBOL], [LANG], -# [ACTION-IF-ACCEPTED], [ACTION-IF-NOT-ACCEPTED]) -# Test if a symbol can be qualified by one of the elements of the -# comma-separated list of QUALIFIERS. Examples of qualifiers include -# __attribute__((deprecated)), __declspec(dllimport), etc. MESSAGE is the -# "checking" message. CACHE-VAR is the variable which receives the -# qualifier which succeeded, or the the literal "no" if none were -# accepted. SYMBOL is the symbol to which the qualifier should be -# applied. If omitted, then SYMBOL defaults to "void f();". LANG is the -# language of the test, typically "C" or "C++". It defaults to "C" if -# omitted. ACTION-IF-ACCEPTED is invoked after CACHE-VAR is set if one of -# the qualifiers is accepted, else ACTION-IF-NOT-ACCEPTED is invoked. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_SYMBOL_QUALIFIER], - [AC_CACHE_CHECK([$1], [$2], - [$2='no' - m4_foreach([cs_symbol_qualifier], [$3], - [AS_IF([test "$$2" = no], - [CS_BUILD_IFELSE( - [AC_LANG_PROGRAM( - [cs_symbol_qualifier m4_default([$4],[void f()]);], - [])], - [], [$5], [$2='cs_symbol_qualifier'], [$2='no'])])])]) - AS_IF([test $$2 != no], [$6], [$7])]) -# split.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_SPLIT(LINE, [OUTPUT-VARIABLES], [DELIMITER], [FILLER]) -# Split LINE into individual tokens. Tokens are delimited by DELIMITER, -# which is the space character if omitted. OUTPUT-VARIABLES is a -# comma-delimited list of shell variables which should receive the -# extracted tokens. If there are too few tokens to fill the output -# variables, then the excess variables will be assigned the empty string. -# If there are too few output variables, then the excess tokens will be -# ignored. If OUTPUT-VARIABLES is omitted, then the split tokens will be -# assigned to the shell meta-variables $1, $2, $3, etc. When -# OUTPUT-VARIABLES is omitted, FILLER is assigned to meta-variables in -# cases where DELIMITER delimits a zero-length token. FILLER defaults -# to "filler". For example, if DELIMITER is "+" and OUTPUT-VARIABLES is -# omitted, given the line "one++three", $1 will be "one", $2 will be -# "filler", and $3 will be "three". -#------------------------------------------------------------------------------ -AC_DEFUN([CS_SPLIT], - [m4_define([cs_split_filler], m4_default([$4],[filler])) - set cs_split_filler `echo "$1" | awk 'BEGIN { FS="m4_default([$3],[ ])" } - { for (i=1; i <= NF; ++i) - { if ($i == "") print "cs_split_filler"; else print $i } }'` - shift - m4_map([_CS_SPLIT], [$2])]) - -AC_DEFUN([_CS_SPLIT], - [AS_IF([test $[@%:@] -eq 0], [$1=''], - [AS_IF([test "$[1]" = cs_split_filler], [$1=''], [$1=$[1]]) - shift])]) -# textcache.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# Text cache facility. These macros provide a way to incrementally store -# arbitrary text in a shell variable, and to write the saved text to a file. -# -# CS_TEXT_CACHE_APPEND(VARIABLE, TEXT) -# Append text to the contents of the named shell variable. If the text -# contains references to shell variables (such as $foo), then those -# references will be expanded. If expansion is not desired, then protect -# the text with AS_ESCAPE(). -# -# CS_TEXT_CACHE_PREPEND(VARIABLE, TEXT) -# Prepend text to the contents of the named shell variable. If the text -# contains references to shell variables (such as $foo), then those -# references will be expanded. If expansion is not desired, then protect -# the text with AS_ESCAPE(). -# -# CS_TEXT_CACHE_OUTPUT(VARIABLE, FILENAME) -# Instruct config.status to write the contents of the named shell -# variable to the given filename. If the file resides in a directory, -# the directory will be created, if necessary. If the output file -# already exists, and if the cached text is identical to the contents of -# the existing file, then the existing file is left alone, thus its time -# stamp remains unmolested. This heuristic may help to minimize rebuilds -# when the file is listed as a dependency in a makefile. -# -# *NOTE* -# There is a bug in Autoconf 2.57 and probably all earlier 2.5x versions -# which results in errors if AC_CONFIG_COMMANDS is invoked for a `tag' -# which represents a file in a directory which does not yet exist. -# Unfortunately, even invoking AS_MKDIR_P in the `cmd' portion of -# AC_CONFIG_COMMANDS does not solve the problem because the generated -# configure script attempts to access information about the directory -# before AS_MKDIR_P has a chance to create it. This forces us to invoke -# AS_MKDIR_P in the third argument to AC_CONFIG_COMMANDS (the -# `init-cmds') rather than the second (the `cmds'). This is undesirable -# because it means that the directory will be created anytime -# config.status is invoked (even for a simple --help), rather than being -# created only when requested to output the text cache. This bug was -# submitted to the Autoconf GNATS database by Eric Sunshine as #228 on -# 27-Dec-2002. It was fixed for Autoconf 2.58 on 26-Sep-2003. The -# official fix makes the assumption that `tag' always represents a file -# (as opposed to some generic target), and creates the file's directory -# is not present. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_TEXT_CACHE_APPEND], [$1="${$1}$2"]) -AC_DEFUN([CS_TEXT_CACHE_PREPEND], [$1="$2${$1}"]) -AC_DEFUN([CS_TEXT_CACHE_OUTPUT], - [AC_CONFIG_COMMANDS([$2], - [echo $ECHO_N "$$1$ECHO_C" > $tmp/tcache - AS_IF([diff $2 $tmp/tcache >/dev/null 2>&1], - [AC_MSG_NOTICE([$2 is unchanged])], - [rm -f $2 - cp $tmp/tcache $2]) - rm -f $tmp/tcache], - [$1='$$1' - cs_dir=`AS_DIRNAME([$2])` - AS_ESCAPE(AS_MKDIR_P([$cs_dir]), [$`\])])]) -# trim.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2003 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_TRIM(STRING) -# Strip leading and trailing spaces from STRING and collapse internal -# runs of multiple spaces to a single space. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_TRIM], [`echo x$1 | sed 's/^x//;s/ */ /g;s/^ //;s/ $//'`]) -# warnings.m4 -*- Autoconf -*- -#============================================================================== -# Copyright (C)2005 by Eric Sunshine -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public -# License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, -# Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#============================================================================== -AC_PREREQ([2.56]) - -#------------------------------------------------------------------------------ -# CS_COMPILER_WARNINGS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check how to enable compilation warnings. If LANGUAGE is not provided, -# then `C' is assumed (other options include `C++'). If CACHE-VAR is not -# provided, then it defaults to the name -# "cs_cv_prog_compiler_enable_warnings". If an option for enabling -# warnings (such as `-Wall') is discovered, then it is assigned to -# CACHE-VAR and ACTION-IF-FOUND is invoked; otherwise the empty string is -# assigned to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. -# -# IMPLEMENTATION NOTES -# -# On some platforms, it is more appropriate to use -Wmost rather than -# -Wall even if the compiler understands both, thus we attempt -Wmost -# before -Wall. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_WARNINGS], - [CS_CHECK_BUILD_FLAGS( - [how to enable m4_default([$1],[C]) compilation warnings], - [m4_default([$2],[cs_cv_prog_compiler_enable_warnings])], - [CS_CREATE_TUPLE([-Wmost]) CS_CREATE_TUPLE([-Wall])], - [$1], [$3], [$4])]) - - - -#------------------------------------------------------------------------------ -# CS_COMPILER_ERRORS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check how to promote compilation diganostics from warning to error -# status. If LANGUAGE is not provided, then `C' is assumed (other options -# include `C++'). If CACHE-VAR is not provided, then it defaults to the -# name "cs_cv_prog_compiler_enable_errors". If an option for performing -# this promotion (such as `-Werror') is discovered, then it is assigned -# to CACHE-VAR and ACTION-IF-FOUND is invoked; otherwise the empty string -# is assigned to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_ERRORS], - [CS_CHECK_BUILD_FLAGS( - [how to treat m4_default([$1],[C]) warnings as errors], - [m4_default([$2],[cs_cv_prog_compiler_enable_errors])], - [CS_CREATE_TUPLE([-Werror])], [$1], [$3], [$4])]) - - - -#------------------------------------------------------------------------------ -# CS_COMPILER_IGNORE_UNUSED([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check how to instruct compiler to ignore unused variables and -# arguments. This option may be useful for code generated by tools, such -# as Swig, Bison, and Flex, over which the client has no control, yet -# wishes to compile without excessive diagnostic spew. If LANGUAGE is -# not provided, then `C' is assumed (other options include `C++'). If -# CACHE-VAR is not provided, then it defaults to the name -# "cs_cv_prog_compiler_ignore_unused". If an option (such as -# `-Wno-unused') is discovered, then it is assigned to CACHE-VAR and -# ACTION-IF-FOUND is invoked; otherwise the empty string is assigned to -# CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_IGNORE_UNUSED], - [CS_CHECK_BUILD_FLAGS( - [how to suppress m4_default([$1],[C]) unused variable warnings], - [m4_default([$2],[cs_cv_prog_compiler_ignore_unused])], - [CS_CREATE_TUPLE([-Wno-unused])], [$1], [$3], [$4])]) - - - -#------------------------------------------------------------------------------ -# CS_COMPILER_IGNORE_UNINITIALIZED([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check how to instruct compiler to ignore uninitialized variables. This -# option may be useful for code generated by tools, such as Swig, Bison, -# and Flex, over which the client has no control, yet wishes to compile -# without excessive diagnostic spew. If LANGUAGE is not provided, then -# `C' is assumed (other options include `C++'). If CACHE-VAR is not -# provided, then it defaults to the name -# "cs_cv_prog_compiler_ignore_uninitialized". If an option (such as -# `-Wno-uninitialized') is discovered, then it is assigned to CACHE-VAR -# and ACTION-IF-FOUND is invoked; otherwise the empty string is assigned -# to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_IGNORE_UNINITIALIZED], - [CS_CHECK_BUILD_FLAGS( - [how to suppress m4_default([$1],[C]) uninitialized warnings], - [m4_default([$2], - [cs_cv_prog_compiler_ignore_uninitialized_variables])], - [CS_CREATE_TUPLE([-Wno-uninitialized])], [$1], [$3], [$4])]) - - - -#------------------------------------------------------------------------------ -# CS_COMPILER_IGNORE_PRAGMAS([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check how to instruct compiler to ignore unrecognized #pragma -# directives. This option may be useful for code which contains -# unprotected #pragmas which are not understood by all compilers. If -# LANGUAGE is not provided, then `C' is assumed (other options include -# `C++'). If CACHE-VAR is not provided, then it defaults to the name -# "cs_cv_prog_compiler_ignore_unknown_pragmas". If an option (such as -# `-Wno-unknown-pragmas') is discovered, then it is assigned to CACHE-VAR -# and ACTION-IF-FOUND is invoked; otherwise the empty string is assigned -# to CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_IGNORE_PRAGMAS], - [CS_CHECK_BUILD_FLAGS( - [how to suppress m4_default([$1],[C]) unknown [#pragma] warnings], - [m4_default([$2],[cs_cv_prog_compiler_ignore_unknown_pragmas])], - [CS_CREATE_TUPLE([-Wno-unknown-pragmas])], [$1], [$3], [$4])]) - - - -#------------------------------------------------------------------------------ -# CS_COMPILER_IGNORE_LONG_DOUBLE([LANGUAGE], [CACHE-VAR], [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# Check how to instruct compiler to suppress warnings about `long double' -# usage. This option may be useful for code generated by tools, such as -# Swig, Bison, and Flex, over which the client has no control, yet wishes -# to compile without excessive diagnostic spew. If LANGUAGE is not -# provided, then `C' is assumed (other options include `C++'). If -# CACHE-VAR is not provided, then it defaults to the name -# "cs_cv_prog_compiler_ignore_long_double". If an option (such as -# `-Wno-long-double') is discovered, then it is assigned to CACHE-VAR and -# ACTION-IF-FOUND is invoked; otherwise the empty string is assigned to -# CACHE-VAR and ACTION-IF-NOT-FOUND is invoked. -#------------------------------------------------------------------------------ -AC_DEFUN([CS_COMPILER_IGNORE_LONG_DOUBLE], - [CS_CHECK_BUILD_FLAGS( - [how to suppress m4_default([$1],[C]) `long double' warnings], - [m4_default([$2],[cs_cv_prog_compiler_ignore_long_double])], - [CS_CREATE_TUPLE([-Wno-long-double])], [$1], [$3], [$4])]) diff --git a/Code/Physics/Bullet Source/autogen.sh b/Code/Physics/Bullet Source/autogen.sh deleted file mode 100644 index 35623fac..00000000 --- a/Code/Physics/Bullet Source/autogen.sh +++ /dev/null @@ -1,61 +0,0 @@ -#! /bin/sh - -if [ "$USER" = "root" ]; then - echo "*** You cannot do this as "$USER" please use a normal user account." - exit 1 -fi -if test ! -f configure.ac ; then - echo "*** Please invoke this script from directory containing configure.ac." - exit 1 -fi - -echo "running aclocal" -aclocal -rc=$? - -if test $rc -eq 0; then - echo "running libtool" - libtoolize --force --automake --copy - rc=$? -else - echo "An error occured, autogen.sh stopping." - exit $rc -fi - -if test $rc -eq 0; then - echo "libtool worked." -else - echo "libtool not found. trying glibtool." - glibtoolize --force --automake --copy - rc=$? -fi - -if test $rc -eq 0; then - echo "running automake" - automake --add-missing --copy - rc=$? -else - echo "An error occured, autogen.sh stopping." - exit $rc -fi - -if test $rc -eq 0; then - echo "running autoheader" - autoheader - rc=$? -else - echo "An error occured, autogen.sh stopping." - exit $rc -fi - -if test $rc -eq 0; then - echo "running autoconf" - autoconf - rc=$? -else - echo "An error occured, autogen.sh stopping." - exit $rc -fi - -echo "autogen.sh complete" -exit $rc diff --git a/Code/Physics/Bullet Source/src/btBulletCollisionCommon.h b/Code/Physics/Bullet Source/btBulletCollisionCommon.h similarity index 100% rename from Code/Physics/Bullet Source/src/btBulletCollisionCommon.h rename to Code/Physics/Bullet Source/btBulletCollisionCommon.h diff --git a/Code/Physics/Bullet Source/src/btBulletDynamicsCommon.h b/Code/Physics/Bullet Source/btBulletDynamicsCommon.h similarity index 100% rename from Code/Physics/Bullet Source/src/btBulletDynamicsCommon.h rename to Code/Physics/Bullet Source/btBulletDynamicsCommon.h diff --git a/Code/Physics/Bullet Source/bullet.pc.cmake b/Code/Physics/Bullet Source/bullet.pc.cmake deleted file mode 100644 index c5649d58..00000000 --- a/Code/Physics/Bullet Source/bullet.pc.cmake +++ /dev/null @@ -1,6 +0,0 @@ -Name: bullet -Description: Bullet Continuous Collision Detection and Physics Library -Requires: -Version: @BULLET_VERSION@ -Libs: -L@LIB_DESTINATION@ -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath -Cflags: @BULLET_DOUBLE_DEF@ -I@INCLUDE_INSTALL_DIR@ diff --git a/Code/Physics/Bullet Source/bullet.pc.in b/Code/Physics/Bullet Source/bullet.pc.in deleted file mode 100644 index ffcd4f36..00000000 --- a/Code/Physics/Bullet Source/bullet.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: bullet -Description: Bullet Continuous Collision Detection and Physics Library -Requires: -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lBulletSoftBody -lBulletDynamics -lBulletCollision -lLinearMath -Cflags: -I${includedir}/bullet diff --git a/Code/Physics/Bullet Source/bullet_logo.png b/Code/Physics/Bullet Source/bullet_logo.png deleted file mode 100644 index d3a1b4b5588fbed303a9a15051b560a26af5dde2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3380 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 KMNUMnLSTZl?!Ko0 diff --git a/Code/Physics/Bullet Source/config.h.in b/Code/Physics/Bullet Source/config.h.in deleted file mode 100644 index 11b564d0..00000000 --- a/Code/Physics/Bullet Source/config.h.in +++ /dev/null @@ -1,113 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - -/* Architecture is PowerPC */ -#undef ARCH_PPC - -/* Architecture is x86 */ -#undef ARCH_X86 - -/* Architecture is x86-64 */ -#undef ARCH_X86_64 - -/* Use the Apple OpenGL framework. */ -#undef HAVE_APPLE_OPENGL_FRAMEWORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_GL_GLEXT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_GL_GLUT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_GL_GLU_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_GL_GL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Platform is Apple */ -#undef PLATFORM_APPLE - -/* Platform is Linux */ -#undef PLATFORM_LINUX - -/* Platform is Win32 */ -#undef PLATFORM_WIN32 - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Version number of package */ -#undef VERSION - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif diff --git a/Code/Physics/Bullet Source/configure.ac b/Code/Physics/Bullet Source/configure.ac deleted file mode 100644 index 3e9780b8..00000000 --- a/Code/Physics/Bullet Source/configure.ac +++ /dev/null @@ -1,172 +0,0 @@ -#---------------------------------------------------------------------------- -# Autoconf input script. Invoke the ./autogen.sh script to generate a -# configure script from this file. -#---------------------------------------------------------------------------- -AC_PREREQ([2.54]) - -#---------------------------------------------------------------------------- -# Initialize Autoconf. -#---------------------------------------------------------------------------- -AC_INIT( - [bullet], - [2.82], - [erwin.coumans@gmail.com]) -AC_CANONICAL_HOST -AC_CONFIG_SRCDIR([configure.ac]) -AM_INIT_AUTOMAKE -AM_PROG_CC_C_O -AC_PROG_CXX -AC_PROG_LIBTOOL - -case "$host" in - *-*-mingw*|*-*-cygwin*) - AC_DEFINE(PLATFORM_WIN32, 1, [Platform is Win32]) - opengl_LIBS="-lunsupported_platform" - PLATFORM_STRING="Win32" - ;; - *-*-linux*) - AC_DEFINE(PLATFORM_LINUX, 1, [Platform is Linux]) - opengl_LIBS="-lGL -lGLU -lglut" - PLATFORM_STRING="Linux" - ;; - *-*-darwin*) - AC_MSG_WARN([Hello]) - AC_DEFINE(PLATFORM_APPLE, 1, [Platform is Apple]) - opengl_LIBS="-framework AGL -framework OpenGL -framework GLUT" - PLATFORM_STRING="Apple" - ;; - *) - AC_MSG_WARN([*** Please add $host to configure.ac checks!]) - ;; -esac -AC_SUBST(opengl_LIBS) - -case "$host" in - i?86-* | k?-* | athlon-* | pentium*-) - AC_DEFINE(ARCH_X86, 1, [Architecture is x86]) - ARCH_SPECIFIC_CFLAGS="" - ARCH_STRING="X86" - ;; - x86_64-*) - AC_DEFINE(ARCH_X86_64, 1, [Architecture is x86-64]) - ARCH_SPECIFIC_CFLAGS="-DUSE_ADDR64" - ARCH_STRING="X86-64" - ;; - ppc-* | powerpc-*) - AC_MSG_WARN([HI THERE!]) - AC_DEFINE(ARCH_PPC, 1, [Architecture is PowerPC]) - ARCH_SPECIFIC_CFLAGS="" - ARCH_STRING="PowerPC" - ;; - *) - AC_MSG_ERROR([Unknown Architecture]) - ;; -esac -AC_C_BIGENDIAN - - -#---------------------------------------------------------------------------- -# Setup for the configuration header. -#---------------------------------------------------------------------------- -AC_CONFIG_HEADERS([config.h]) -#---------------------------------------------------------------------------- -# Package configuration switches. -#---------------------------------------------------------------------------- -AC_ARG_ENABLE([multithreaded], - [AC_HELP_STRING([--enable-multithreaded], - [build BulletMultiThreaded (default NO)])], - [disable_multithreaded=no], [disable_multithreaded=yes]) -AC_MSG_CHECKING([BulletMultiThreaded]) -AS_IF([test "$disable_multithreaded" = yes], [build_multithreaded=no], [build_multithreaded=yes]) -AC_MSG_RESULT([$build_multithreaded]) -AM_CONDITIONAL([CONDITIONAL_BUILD_MULTITHREADED], [test "$build_multithreaded" = yes]) - -AC_ARG_ENABLE([demos], - [AS_HELP_STRING([--disable-demos], - [disable Bullet demos])], - [], - [enable_demos=yes]) -AM_CONDITIONAL([CONDITIONAL_BUILD_DEMOS], [false]) - -dnl Check for OpenGL and GLUT - - -case "$host" in - *-*-darwin*) - AC_DEFINE([HAVE_APPLE_OPENGL_FRAMEWORK], [1], - [Use the Apple OpenGL framework.]) - GL_LIBS="-framework GLUT -framework OpenGL -framework Carbon -framework AGL" - have_glut=yes - have_glu=yes - have_gl=yes - ;; - *) - have_gl_headers=yes - AC_CHECK_HEADERS(GL/gl.h GL/glu.h GL/glext.h GL/glut.h, , - [have_gl_headers=no], - [[#ifdef WIN32 - #include - #endif - #if HAVE_GL_GL_H - #include - #endif - #if HAVE_GL_GLU_H - #include - #endif - ]]) - have_gl=no - have_glu=no - have_glut=no - TEMP_LDFLAGS="$LDFLAGS" - AC_CHECK_LIB(GL, main, [GL_LIBS="-lGL"; have_gl=yes]) - AC_CHECK_LIB(GLU, main, [GL_LIBS="-lGLU $GL_LIBS"; have_glu=yes], , -lGL) - AC_CHECK_LIB(GLUT, main, [GL_LIBS="-lGLUT -LGLU $GL_LIBS"; have_glut=yes], ,-lGLUT) - AC_CHECK_LIB(opengl32, main, [GL_LIBS="-lopengl32"; have_gl=yes]) - AC_CHECK_LIB(glu32, main, [GL_LIBS="-lglu32 $GL_LIBS"; have_glu=yes], , -lopengl32) - LDFLAGS="$TEMP_LDFLAGS" - if test $have_gl = no -o $have_glu = no -o $have_gl_headers = no; then - if test x$enable_demos = xyes; then - AC_MSG_WARN([Demos and Extras will not be built because OpenGL and GLUT doesn't seem to work. See `config.log' for details.]) - fi - enable_demos=no - else - AC_MSG_NOTICE([Found OpenGL]) - fi - ;; -esac - - - -AC_SUBST(GL_LIBS) - - -if test "x$enable_demos" != xno; then - AC_MSG_NOTICE([Building Bullet demos]) - AM_CONDITIONAL([CONDITIONAL_BUILD_DEMOS],[true]) -fi - - - -AC_ARG_ENABLE([debug], - [AC_HELP_STRING([--enable-debug], - [build with debugging information (default NO)])], - [], [enable_debug=no]) - -AC_MSG_CHECKING([build mode]) -AS_IF([test $enable_debug = yes], [build_mode=debug], [build_mode=optimize]) -AC_MSG_RESULT([$build_mode]) - - - -CFLAGS="$ARCH_SPECIFIC_CFLAGS $CFLAGS" -CXXFLAGS="$ARCH_SPECIFIC_CFLAGS $CXXFLAGS $CFLAGS" -#---------------------------------------------------------------------------- -# Emit generated files. -#---------------------------------------------------------------------------- -AC_CONFIG_FILES([bullet.pc Makefile Demos/Makefile Demos/SoftDemo/Makefile Demos/AllBulletDemos/Makefile Demos/MultiThreadedDemo/Makefile Demos/OpenGL/Makefile Demos/ForkLiftDemo/Makefile Demos/FeatherstoneMultiBodyDemo/Makefile Demos/BasicDemo/Makefile Demos/CcdPhysicsDemo/Makefile Demos/VehicleDemo/Makefile Demos/TerrainDemo/Makefile src/Makefile Extras/Makefile]) -AC_OUTPUT - -AC_MSG_NOTICE([ - -Please type 'make' to build Bullet -]) diff --git a/Code/Physics/Bullet Source/convex0.bin b/Code/Physics/Bullet Source/convex0.bin deleted file mode 100644 index 83493fca3834f02b26c09a25e2a5d77f515bc876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 548 zcmY+ADNhA46oor8ovoRDGZ;`95*G8!n>IKc{{TmVCt*nt!w*0}o$qIttJ4 z0D>a~6!-SEq15#B&guD1rz2_&)1NO1YPeuij(T=*&hdm62Hi)L^G^sƒ—ª±·ÁÏÞÛ˹§Žvqttsh\ZTLC;49DIRSF>52449:?Jex† ¯ÅÒàææããàØÌ»­œ–’ŠŠyt‚u²œ‹xiYOC?KORm|x€zƒ‹’ž§µ¼¾¹²®¤ŽlWJSljWB/#',162-6CVl|”¬ºÅÊÑÜÜÊ°¡˜‘‹‘€ohlocQG;8?FROD=2284**:Lgt}¤²ÅÊÕÛßÕÓÑÌÁ°©«¦™†ŠƒŠ|x‡„ȳ¢ ›‡k^UMN_km}‹‘Œ„Œ‘’–¡¬·±«©ˆjULPb`T>% %(('(,5DP\q“¯ÀÌÐÕ×Ò¼¤ž£§¡›š•‹}€qTF8.0;6,+'""(-,,0:F@>AGO]o€‘­ÂÏ×ÑÌÉÁ´¶ÇÐÉþ·¯Ÿ‹}jP;,%! +:ALLKOU^krr‡Ÿª®©žys~•¡´º¾µº¾¿ËÓÜÔÀ¢ôôôïåÚÑ××Ð×ϼ¦—„mXXdg^Q[R>6329CE6*+*+)(#"!##'-5>IONHBGQj‡ž­¼ÄÍÌÊʼ´¸ÆÎÈÊȾª‚yiM6(## +?Nfƒ™¨·ÁÊÁ·µ±­°¿ÇÀÅËÁ¯ŽzucC+#$$!%4CGFFO`kmgdduƒ—¡”‡†€…‹—«´¸»ºÁÁÏÕÚØÏ»¯ûûúüûîçäààÞ̲Ÿ“yhWRORM:76(""$!&"!# %/1389DNQTLA>AWo†™¤®¸²²²¦¡¤¯µ­°·µ¦…qiW?+$%##$).?HEFNehffebsˆ”‘ƒ…‡›˜ª·¼¹ÄÏÏÓÑÓÐ̼³üÿýýü÷öñëåÚħ™€iWMOIA.&$ &-49?>CVbZPE=AGO^aghkmpxz|rou‰“¥¬¤¢­¾ÑÜ×ÎÁ±¬°®ìõùöó÷üöìØË·¥š™“qO;20*#  - (2?GP_noi_XZ]nvrx€ž ›­ÌÖÑÉÿ»°ž–“‡rk]L9##(.:@BIU[^qsmipwz~}vot~…’Ÿ¨¨«²ÂÔÜÐǺ¯œ£ãñôñêòöôåÏŵ¦›˜…mG0*# #+6DIRciid^bgqzvx†“Ÿ¡¤¼ØäæâÚÕÏɳ–Ž‰yi]RE-#,9CJJLTVZmppt~yyxrjir}Š›¥¯§¯ÃÎÕÏÀ¨›‡…ŠÍäêæàåæßÑËÀ´¤˜“~^C2!  ##(+07ARac\^cnzŠ’”“ž¨·ÊßèéëìåßÖ½œŒƒxl`RJ6 +1@GF;7:DLT[kpnpsund]cjl~”°¶¯²®¡Ž~wtoh¢¡®°¼º°¬¬£ª¡|vqeG*  -&8;1,/;JP[jqpt•§©ªª¯¶¯«·ÅÌÕÞÞÞáÚË°šŽˆˆrWHD7&#.78;=@B>658DIJY[dqpfhd^f`_i€› ¤Ÿ‚tikopŒ‹–›Ÿ¤œ™•…Ž‡vc^ZM;#  %4:979?O]`fnq}ŽŸ°·²­®©©¯¸ÄÒÙÛÛÚÚÒ¿«š“‘…~mVLF9.-16>?CFDDLKE?7:@BNRWa`emk^bZXYpŠ‘•‰vupjgi|x…€…Š†„zmabaTJE=9#  - - - (4<7GJJJKGFQSPD9?CGAIS]`jo_URMRVat…’tpefjuxw~yxx}|vshVLNPIA?=9$    "6B=AKRY^gqx…—±ÃÊÎĪ £«ÀÎÎÌÏØÜÍ¿³¬¦‘|ptnSA8;DMTY^\TTU[[ZM=DLOKV_a^bZQECIMONZu‡whgddnplqwpqt{ypj\KFA?:59;6$ %$)39?JTYVX^en ¼ÄÌÖÒ¿²«°ÄÎÐÍÌÛàÕÁ®•…ulnoYD64AO\gkhc]cjoiYDDNTZ^__QKHF<;AJNJ\jri]cjjpjaikhemxsujRBB=5-,.8>,!#-2/*+-10$".03AKNPKOY]g‚¡»ÂÐáàÓdz¬ºÄÊÑÔÖÖϲ™“”‡qimf]O?:HWdrvumkqolkXJOUWa[U[JFC>::=IEGXeqnhqmntrfc[XTYelniPG<91*,*387+%2<;5234981)#!!,206CONE?ALQ\v—°¼ËÜàÙÒ¿®­ºÃËÕÐÌÆ»«š’„posj]QHKbszƒ„Š†~xwvm^RXZ^`ROOJG@56AEFVbmbNB:81)*146>9++.-2DD96424:9872.-398?MXP>9?BGZu‘§²½Í×ØѲ­µ¼ÈÎÄÀÅ»¯›†uorj^SVbt‹“Ž“–‡‚‚}g][\fc[YRPOE13;ENT]\Q?6;=1)-;MUO@:@IVXX]VL=4435NqŸ¬¯¹¼°±¸»º¹¼ÀÄÄƾ°­¨¡ ˆyokegyš¬®¦œ‘™œ˜››‹vwwtxƒˆ~sab^\e]bf_[ZaT\fn{xok]Q(5:FVWSRNSOMDCJSSQOWU[ZZQKGFD83@QPOJEOV]Z`\QA620.0Gi†–Ÿ¦®©›’ž´»¹··¼ÁÀ²ª°µ´²¥—ƒ}{|Ž­º¶³«¡›œ¢§¡’‹€ƒˆ™—ˆqnkh_[ffbWQ\bifhnha_ZM$+8BCMW[TSWSLEJRVQUW]akaVXURQRJAJURONNVX\Y^bT@3322;Ni}†™˜’ˆ€Ž¤®¯««µ¸±¯®±µ¸µ§–”••™¢¸ÉÊÆ»µ š£¬§œ•Œ~‚Œš¡£˜‹{~xkZ^hf^XWcwp``]YTPUQ27?EJU\[W\``ZNNV_]`ceim__gjii`_XW]^XWZ``_^YXUOEFB=KZiux}}y{‚‚‰š¥¦¢§°±®°°¬«°ª¡œ˜™£©«¯½ÑÛâÙÊ®˜“›™‡€}}Œ’›¥ œŒ„‚zmph^^fot‹‚h[PPNNUP?DIO]e`aefjjhZLO]kmoljgkty…†~xg`bfb_cec]YJGIKKPMCJ^ikilifp€ƒ…–›˜˜£««© šž¢ š›Ÿ£±¾ÄËØäêèÖÁ¤•Žv€‡Ž‹Šœ«²¹© ™|qg^grvyw]IELYRRHHS[ipfquntmncRJYjqrslfvŠŽ“–˜Ž€oefjc_bXJA866J[nqk\R[gv„‰‰‰‘’†€Ž––›Ÿ°ÉÞæåêõóòéÕÁ§Žˆ‰“Ÿ¢¦®§§¬·¼»½¸¯¦…ldXKRS]s……{u~njffkz‚‹ŒŠ–•ƒugSJRW\aklkw|Š“¢¯º±ŸwjfkhWE8,""''-3006849BR`a`[RQ_wŒ”ŠŽ™–“‡y~‰¦¬ÄÖÛÜçôøñçʸ¥„†—¥©«¬¨ª±¶¿Åľµ¦|mdSJFUm‚€}||wyx\h‡•ŠˆŒ–ž›‰ql]MAFGQX\]kt•©¸Æ½«šŠ}qjcSFC1#"" "$+1.48604CNRRQPOZrˆ•”™¤Ÿ~njvžŸ£µËÕ×ãñ÷íÝ̽©•ŒŠ™©¬¤ ©¯´¹»ÄÄÇÆ·¥m\NN^n{{|}‰T^{‰’“•–œ¡zoreUIA=FMOTgu‡š³ÂÇż¬ ’|nbRLH6" $+-475106;@?@EHWnƒ“–œ¥Ÿˆwqgp‹—™¢²ÅÓÜæïòèÒÉø¦¥¡¤´®Ÿœ«²¯³¸ÅÆÇɽª’…w\RS`r|ˆƒ~y‚–`ezš¤¯«ž›™†zynm`OFCIJJP`|—¦»ÆÉÐÍÅ´œ€scUTL<,$"#,104;;6:;9;@EC?F½±¥–ŒˆŠˆŒ†ƒ•”œŸœ¢¨§«ÃÖÕÑÏÕßÜÙÎÎÌÏÓÔȱxme\O<7119?6.+))*,.009KZ``fmvƒ†zux{}¤£¦¸¹±²´®¦¨§¤›———‡wqz†‰ƒ†Ž’•šxp_XbYI:;@@:<:;BD?<½®¨šŠ~uz„ƒ~‡”Ÿ›¤©±¶½ÓÛÚ×ÏÐÜåçÜÙØÒÕÖɬyhYJA;3/2>@6.*'&$%*.2>S`dcer{xvzwuxƒ†š­±´´½Á»¸¹²¦˜› ¢ —ŽŠ‚ƒ“Ž‹‡‰‰{gd^WZUL>?>CDEEB@AA9°¨¦”€qq{yy~˜¤§¶¾ÄÊÐÞçæáÜÛâíòêáÙÑÖ̸™…vdQ@84--8>;4,(%! '/8CTiupmq|‡~rpptz‰‘¨¿ÂÊÎÌȾ²¯¯©˜–™ž¨¤“’–¦Ÿ›‘‡‚…zkXITVXOJ?DBKMNOMC?=9ª¦¥£œƒxs}xy€œ¨´ÁÈÑÕØãçìîììñõóìâÜÔÌ»©˜…ycG9/(#(7B:1,&$#(08GVk†‚‹‚oefo~‘™³ÉÎÓÚ×ÌÁ´ª©§™•›Ÿ¦£šŸ¡¨®¨§”ƒ{xgWE:DPUQMFEEOSSXVNGCEµ´°­ ƒy|„ˆˆŠ‘¦­»ÉÏÕØáéèñ÷ôó÷óëåÝÜØÊ°¡™†zb=.*%&&2B=53/+*1:FWgz‰˜š”Œ†‚vgeu‡‘›¨½ÐÙ×ÕÎĽ¼±¦¡•‘¡¥§¯²¬«¯·­¢¤—†vk]O>92/))&2DF;;;717BOd}‘ ©®¦–†~xnm|‡‹–¨ÁØÞÖÍÁ¶¶»¸¯¨œš¦«±¼º²®¹»®›”˜ŠxbXVJCDGPZUUZPLS]^PDKNX¹Èȳ¦‰…‹”””›«¾ÍÙÚÙáñïïõôéìèÙ×ÕÛÙDz–‡sWG;63-('7LM;48>:=IVlŽ§´µ¸¾²¡—Š„yqr|ƒ‰–®ÇÔÑɶ­¯°½À»­®»¾À¼±­©°·­–”‹w^SRRMKV][TZfeZWYXLELRXª·Ãƾ°™‰‡ˆ‡‘š«¸Ç×åæéñðïñìÞÜÚÌËÈËÌ¿­“v\G=772.+-:NN=36>=>N`xš±ÀÇÈô§›•‹vlou{‚‘ªÀÅ÷­ª±¼ÄÇÂÈÏÒм¥™œ§ª¤™‡}m_QLQ[^hifbgnvhZUTQOUYZ­¯´¹µªž…€‚”¨°ºÍáðõõöõðìä×ÑÎÁ¼¼Âǹ¢ZG:5350002>OQLDABDJ^u‡œ°ÄÊÅ·©šŒ‹†|vsqrx€‚•¯ºÀÀµ°¸¿ÈËÐÒÑÕÒº¤˜Œ™£¢~l\YRKOcpmhnqr{yhYXYTY\`dú®¨¢˜‹~u|‚—«¯½Îçô÷öôöðçÚÓÎÆ¿¸ºÅÅ­’kJ<5-)'&-6=EOVWOOSY_u‹’™¬ÀĶ¨‰„}{xyunr€…™³¾½µ´¿ÀÅÅËÌÈÇõª¢Œ–“‰yeRVVPSjwnfnw||l^aZRVXjoÎö¢““‘ƒyos™©±½ÏãïòðïóêÝÊÉÅ»¼»¿Á¾žxXD0+%!+@JLT[]YY]ir‡œ¢¢ª¸Ã·§ž“‡vrtxwrr}ƒ~ˆ¢¬°³´¹·´¹»¾½¹°ª§Ÿ“ˆ€‚ƒ€o]U^XZhx~~ywz€‚}ug_PNMUqpÇ·¡Š…†}utu–©±¼ÐØáæîðìáÓÅÈÇÁ¾¾½¹´—kP>,$$.=LYbfijiqˆ—ª°¯±ºÄ­œŽxpkktvv{}‚†|Š–¥°°«¥«±²¦˜•š—•‹wnof]UZc^dv{‡‰†‰Žzn^QGIPWmp¹²­¥”€}€ƒ‹™ ©´ÂÆÐÝìóíßÏÄÇËÌÈ¿»³ª’nUE4&)29J_hgmv€Ž”—¡­´·º¿Äų–‚m]^iqmhu„{uw{‡—§¦—‹‘ž¨ª—„†‘˜˜€scRR]glhemxŠ™ƒ‡t]JDCIU_pj¢•˜¡‰Œ‰‰‰‡Ÿž£¯±´ÁÕâîëÛƾ½ÃÈÆ¿¼±¤‘vcVE/+18FU_gmw†–Ÿ¡¦ª­®±³¸¿³—~iRP]d\S_prtolpw†ŒŒ~€Š”¡˜€€Ž”’ŽŠiTXiqsne`tŠ“’ŠshmdKDJ[mwrou~†‹“ˆ}}‹Œ•Ÿ£«¸ÇÔÚÜÑƽ»±±Ã¿º²¢Š}ujY8))127?CTdjy‚ˆ”š“˜››£ª¨«¬qP<9<=91>Ykkgehec`]Y]hs~‡~~‡‹†|pkcflhjwworz}zl^QB8458DZq}|]eŽˆŒŽ}mp|…Ž’•š§¸ÊÖÒÐËù¶¸¿º³§•„}uthJ3.9<>FLSafw‡—–“–•¥´¶®¦™…a=./121.9Sbfb\ROWXPIK[jdcgqxvsutttupeYWees„wwtoi]IJFA86F_r{VWr‹‘‹†‚n\`lx„“™¬ºÂº¿Ãº¦©´°¯§›‹†„nX?6>AAJW]enŽ‘‹‹“›¬¶·°¢˜€\>005534:@NZXQFHNNGA=?@K[msx‡‘“’ŽŠ†Œ™©´·±¡‘qTF=::720/081+-.17>>843-!#)./.489@CJTSJGWksxƒ†˜ ª¯­¡“||we\TPLUYZ\dBSdo„ƒkO:=EVn}|‡Š„{ŠŠˆ…{mdcgkxqmp|…‚wbPLIGS^femzvy‚‰‡„Œ—¦¯¦vbXOCFA96240**+&$$$" *50/4BVZVUer|”™©¯®»¸¨›‰Œˆo`RIGIPZ]d?LVcy~|p\JAKXm}„„}~…ƒ„ƒ€teXQPU^ZVYcw€}m`YTV[\`]aq{vutu}}€‡Š—Ÿš‰viXMGD>9><60%#./'-?TZ]_m‡Š›©´³µ½¹ª–‹€€iVGD@@IY]`=JUanfkgdUCHRcuƒƒyƒŒ„…‚uhXODEHGKLPSas}rkjddkigc^eywmc\ivƒ|ƒ’ŽqhWKJKH@EB8/' '+$*CX\`jt’—˜¥»Ã¼¾¹´§}pjm^F?<8;DTYa;FVaaW\dcTLFMYn|Œ”ŽƒzhXLKIIB74>ISYb:AO[STU\^[YOVZo|ŒŠ‰~uobMAEPO=8@FHJHLYnyzy€€{ofgoxxpjt}~|xtssn`ZYY\\]WKH7(#!%!!'-/:BMZahvv~•£¸ÆÅ÷¬®šƒskgXWKD<7DKP]b>GGKGMMN[`aac`s‡ŽŽ}th]M>CKH?7=C=;9BPe{Š‹‡zpfgv‡ŒŠ‰ˆ‰€|tf^_c_VX^cc\TKF8'"""%%(*/-*+00=>CKZdchhcy’”œ•}zk[SJFC?>9:?64;CVk›© ”Š}umsŠœ¡Ÿ˜’pmaTSW[Z[bbdcYQG8*'.+" !(*+.320/17>@FQ]fibY^lx~œ²¸²©¨Ÿ‰yaMITYVMSQLORd~AGC?<;FSbjiidj”™šž •{vi^YMD>;713/0:I_o—¥¢œ–…yux¦­ª¡—‚siYLINZbhrqkig_SH;8;40.(,63684028DLNPbmmmjajigj€­±¦ž„zcPOPPKGKKGJPnGEC<;HV_bdmg[hwŽš›¤œ“‚uy|riXL@7,'&$'7N`l{’œ˜‰|t€–®»´¤„‚udYOKNVanz€|sppgVLOKHE=2,349?>:?AFHHSq}nnxz{tkk{¢¨•‰€qhYRNJDGGH??>GZ_aclmaR[_yŠ‘›š’€w}~ri_N=/%! 2Ofov‰Ž‡†€zŒ¡³¿· ˆ}yk\XVURYbm{„‰…}}saY_\WUN>114;HPKLFEDJ[x…}w„…zzywuˆ˜—•†wmlbPONRPMI;5Fhy;:=GVacelqdWMNPc}”š¡›…†‚vleX@8/+ -Gemn~„‚ƒ‹‡ƒ’¤·¼¯œ‘…~t_W\_Z`l{‡Ž‘Ž†yrkhge_WL?8?N][Vgyƒ†Š…z…ymZL7*" !)4IVfkls‡Ÿµ³ŸžŸ¢¶Ã¶¢£«§œ“–‰‡ƒƒ‰‘››’’…Š’“‰xl[LKRfyŠ’‡…††„ywsivuyxh\WYahoz„…Ž“”œ˜‚geffkgkoa\2-'!#)/9JYddt€ˆ†|ndcikfleVB,$ $')0=CIFET^USNC:31.--.4@JXk{||z{‚‰’•ŽŠ‹“˜‘˜–”™§®°·³©¥ž–˜¡¡¤§¦¨­³­ž˜ ««³µºÆÄ·ªŸ‰{phqkbbuynrƒ‘‘‰‚ttt}†Ž”–™†„}|ƒ~E7$""$,@IIBBD=756:AJNIJFMJG:)**%&/7>E]t€‡„€ƒ~{…‹„|‡ž¦™“š–•¦¬ªª«¦œ•‡‚Œ––™¢§°º»ª›¡«ª©²½À»°ž’vm`aeahs{y~Œ—˜˜‰qnow„ˆšŸ™ŽŒ””‡E4'*(!&6<91.30/*./6=IFC?DJJA,++''+37A]t€›™‘Œ‡‚|vxyƒ—¤§™’Š–¥©§£¥¤—€zˆ—•–¢¦­¿Å² ž¨¨§±¸¹¸¬ž|pdYV`[gr}†‡Ž’•šƒigiou€ƒ‹ž«£ž–œŸ˜‹G=73.)$#'(--&&'&'#(*/0?AA@@FF?2*+&&)08Har“œž—‘ƒvru|Š”œˆŒ“—¥§¢¡ ˜„‚—™¢¬§ª¹À´¦£¥ª¨­³¹¶£š~j\TT[\cn~Š‘•‹‰ydZZ^bp…Ž›­°µµ®¥ž“SOK=1/+#'('$#!")-/:>KXkz††……yu|€ˆ‘’Œ‚”¢š’œ¢Ÿœœ™‹’œ©´¶¨©¶¿À··»¶´¸º¾¸ž”‡ucWSMP\fp†•›ž’‚uldVTWT`vŠ“¥´ÀË»´­¦bZYE3.,*)+'&.0575=CE=?935;CM\bm{€Œƒvmrypmt‰‹„ƒ…†ŸªŸ˜¢¥ ž§© —•›¨²»º°±¹ÂÍÏËÊÃÀÀÇÇįžŽ}nd^ROXesŽ™¡£’}kbZSQTYVj€Œ—§ºÆÅ¿½¸iZZI50,*&&#!(,.*-;ORPUNLFO]gvx‚†•‡ukpqljmwyropx…“¢­¤š¢¬«¯«Ÿ”‘‘™¬·»»¿¾¿ÎØÜÔÈÄÈÄÊÉÍðš‡viddV\ev‰–£ {h_XOPQZ]mzˆ’Ÿ¸ÅÈÄËÅaMMD<3,# #%!!3R___abcmx~†‡‡‰‡–Œxozypgdilc]_i~Š•¤¥›š¤®±¦œ™›˜œ­ºÀÁÉÏÕååäÝÒÊËÆÇÐÐÌÀ®{nii`[Zf–‹n^\QKNW\ju€‰˜¢µÁÇÈÌÈQFA<9/#  .MZVWcl•“•‘‘”–Œ~y{ue[Z]^[[jx¤”¤£¡¡œŸž «¸ÀÇÓÜçñêèäÞÝÒÌÎÓÍû®•sod_SN]nv|unbTMDANZcyƒ™Ÿ§«¹À»·I;2+*#  -,GOLTj€›­§›”‘“–•¢™†‚ˆvhXQRVYiw{‡“‚‰Ÿ£•’™¤³¿ÇÍÖÚâéââåæéÝÒÐÐʺ³¦ŽulibZMEMR^a_bd[OIEN]q€Œˆ” ¤ž–ž±«¤F5.# - !(2AJQ`¢¹É¾±¨ž˜“˜Ÿ©¦ˆ‘‹wdQNMRery|†‰yz–¨Ÿ”Œ’¡³ÁÈÈÎÖÜÚ×ÙäîíàÕÌÍʽ®ž‡qg]VTJ<=HNKMM[_TPLPcs‹•œŸ¢ž–˜žŸ¢>.' "+6>FOXpš·ÈÚÛÏü¬Ÿ ¦®«›¢™Žƒr_TJGR_hnw‚ƒ~z‰Ÿš‹Šˆ¢²¼¾½½ÂÇËÑØáëçÚÍÁ¸´¯¡“}jb[OHE96=?B?=FQOQQVlw‹—¢§¤«¡––—7-"   ,4>LMZl‰¦ÃÔäæÚÏË¿´­©±·³¬¦˜ˆ}viUMHADTejmpxv€’…}„Ž£²·¹º·¶¸¿ÉÔÛÝ×Ç»®Ÿ––eSNMA=?<>657732@KNXan¦±°°³£•“•+% -!19AJQa‚¯ÄÔßàÓÓÐÇÆ¿¹ÃÉĵ ™—„wpaWPJA9AQWQQ\\dqztkvŠ ­µ´¸¸±¯²¸Æ̼µªš–Œ€xviP?><>=@@E:31.+.8CMUbwˆ“¡®³°­±©ž˜›Ÿ&  - ,7@IHUj‚¡¸ÆÉÓÜØÖÕËÊÍÓÜÛÒ»¥Ÿ’yfjcQIG>6>HE@AEFM[b]Zi„£³²°¶²£œ› ­«›–‹ƒ…~wiYH:143AJEBE?761/*1>IW_w‡‘™¦«¨¦¬­¦¥¯±' - - -  (1BQRWg}š·ÊÌÓÜãâà××ÕÜèßÔ¿¦šŒxfh`NE?:8?BA<:417?BKPZxœ²¹»¹±©›“™Ž‡pnuoieSC7,+3>EKLH><;2/++=Q[fuˆ“ž§©¦¤¬ª®²º-   "&/@Wdhl}”¸ÌÐÔÛîïìëèäçãÙÓĬ™qmeXLC:68=><4*$''&1DWo¥¶¼±§£•ŠzrodXVWUXZSH;,,55:LYQCA?520-DZbk…‘§¦ ¤««¯²°³¸6"  -  $*3IWfx{|®ÀÈÒàíïññìëéßÚÖǵ¦–‰{weO?2.2675*$7RlŸ©£”†xk[W]VNH??C@??1)'.38EVSCA93-.3G`rx‘©´º®®¯¯¼½²µ±E2&   $0;GVi}~‡“Ÿ«½ÆÛêòõóñîçáÜ×Í»¥—ŠrbPD7.,**)#+BUez‹”‹†ƒufZIAIK?407=967*!$(-9M^VI;,'$,9Tu‡‘¢§²¼Ëĵ¬ª»¸³»ºT?,$+.2?MQ^vz„’œŸªµÄÚìñôðíéàÛÔÓ̺¢”Œ‡ocVC0),*'!-9Mgv€zjdhaK?<=?6,&+145+ (09N]UH8+%%(6_{¦¯¹ÀÅÎÎƶ­¼½¾¸ÄSE1!"-:?CCGX]esŽ¢³´¸ÁÍáñîïçãåßÔÑ̸¨—ˆ„|q_LC?90+)),*#!%03<;1+++5=Qbz’¤§°¶ÇÊÑÈÁÊÓÏÌÏÙMIA75/*"$)0>SZcbcl}€ƒ…ž©©«´ÂÑâèïêÝŸ¸ÅÈ¿½Áº©—‰|aUE0)+( #$ #030+,24ALG?1('''%"#24/2/+(*=HXh‚™©¡©½ÉÅÊÌÍÎÈÊÊÎËMPK><13+#*)2>Tchinmx‰‹Š‰’¥¨›¦¹ÊØÝßÙѾ©£¨©«©®²§†j`WJ7+**"#*%&3>BGH:+# "" #/44752.19CKbwŠ£«µÀ»ÊÌËÀ¹ÄÉƹV^WKDAE=//2>N`heiokzˆŒ——š¢“‘ž®¿ÔØÐƸ´¥–”š™„h^XOB-"   $#&/69591%#)8>=54;824AXf{—­¼»½½Æ˽²­½¼±¯dpi^PSWG:8@ESdnlmwuvƒ”§¦¢œ›‘–š±ÀÄƹª¥˜ˆ||z{ˆ…yaNORI3%"  -&*0+,)%$139BLJC@67CKTRh‡ªª«³¹Àµ§¥°º²°flom`geRBHMX`jjmou~|‰¡®®œ•˜˜•‘‘™§µ¿Ä¶Ÿ•“‘‰€}|~ƒ„xgTGIJA2)#  - -  $# "!!%(# (2=BDKNH=;=MSWM[w™¢¨£±½¬¨±¶®¦iqyyvxp`[XV[gmkmuz‰…Œ¢®©Ÿ˜›¦¤ £§¨°·»¯––•‡{~‚ˆy^L=::62)    (*1,''5DLHDF?>6ANW^SXks˜˜˜¥·³­²´«žuzyy|yf^Xgkilx„†‘£«ªŸ¡£¯­¯´±±±³³ª™–’“Š‡}…‡†~kU:/10/& - -%0857;=LLFAD@A?LX_c]]i~ˆŒ…“›ž°­±´³¬¢u~wv{|Š}gb_hignq{†Š“¤«¥Ÿ¤¬¸·µ´³«©«©˜¦¨Š•“ƒkR:*+23%  &09>EPOUTL?ABHKVfkgcdnˆ‰‡†™™Ÿ±¯·¼¾º±irgkt{Šzqngs}z‚‡”•—¡§ žœ§´´·³°ª¦¤¤š¡¥²·ª›––œšŒqUE30?OY_ilqz‰”˜•––¦¬«P?:9==;>Ncx‰ž¦¢¦°¯®§ ©®­³¹¿Ä¾Â¿¼°ª§²½¼³´ÃÉÎËĶ£™Ž~whXNE4#   - %)15.-24B?>KLPNJKLOT_ndfsx~zŒ€vz}|ˆ™••QFC@A@@W[UUYk€ £¥Ÿ—’œ˜Œ˜›‘¯´¤¢¤¦¬¢¢°³®«¯½ÕãÛžºµ³¯ž‹„}tdK7-##)2?QYM<,$&% %(""&-99@S]lleedp{tkdgjeegq}Œž˜‰~rnnlrq€†~|r:=>=ETca`lr–– ¨ª ™’…€‚zr‡¢¥–›¡š˜™š˜œ¤²ÎÝØËÉÎÍÇÆ´ž–‘ƒsbM=.),3>BET^VE6(&%!',! #$$&7BR^euxru{ˆ‰ƒzumfky|‰•ž¤“Šviknlhnz{nl37:EP[jrwƒ‚Ž ¢¥¦¨¢šŠ†zgd`Ykƒ‹’š–Žz€„~™¯¿ÈÊÍÓ×Õ×ÙÊ´¦žƒw]E20&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src ;; - esac - - if test -n "$dir_arg"; then - dst=$src - src= - - if test -d "$dst"; then - mkdircmd=: - chmodcmd= - else - mkdircmd=$mkdirprog - fi - else - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dstarg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 - fi - dst=$dst/`basename "$src"` - fi - fi - - # This sed command emulates the dirname command. - dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - - # Make sure that the destination directory exists. - - # Skip lots of stat calls in the usual case. - if test ! -d "$dstdir"; then - defaultIFS=' - ' - IFS="${IFS-$defaultIFS}" - - oIFS=$IFS - # Some sh's can't handle IFS=/ for some reason. - IFS='%' - set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` - IFS=$oIFS - - pathcomp= - - while test $# -ne 0 ; do - pathcomp=$pathcomp$1 - shift - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # mkdir can fail with a `File exist' error in case several - # install-sh are creating the directory concurrently. This - # is OK. - test -d "$pathcomp" || exit - fi - pathcomp=$pathcomp/ - done - fi - - if test -n "$dir_arg"; then - $doit $mkdircmd "$dst" \ - && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } - - else - dstfile=`basename "$dst"` - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 - trap '(exit $?); exit' 1 2 13 15 - - # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dstdir/$dstfile"; then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ - || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ - || { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit - } - else - : - fi - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - } - } - fi || { (exit 1); exit; } -done - -# The final little trick to "correctly" pass the exit status to the exit trap. -{ - (exit 0); exit -} - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/Code/Physics/Bullet Source/jenga.dae b/Code/Physics/Bullet Source/jenga.dae deleted file mode 100644 index 19c85d00..00000000 --- a/Code/Physics/Bullet Source/jenga.dae +++ /dev/null @@ -1,5632 +0,0 @@ - - - - - Illusoft Collada 1.4.0 plugin for Blender - http://colladablender.illusoft.com - Blender v:242 - Illusoft Collada Exporter v:0.2.65 - - - file:///Users/erwin/Desktop/physics_demos-2.42-preview34/jenga_physics_test.blend - - 2006-07-18T10:32:54.891550 - 2006-07-18T10:32:54.891607 - Z_UP - - - - - - - 49.13434 - 0.1 - 100.0 - - - - - - - - - - - - - - - - - - - - - - - 0.0 0.0 0.0 1.0 - - - 0.4 0.4 0.4 1.0 - - - 0.8 0.8 0.8 1.0 - - - 0.5 0.5 0.5 1.0 - - - 12.5 - - - 1.0 1.0 1.0 1.0 - - - 0.8 - - - 1 1 1 1 - - - 0.0 - - - - - - - - - - - 4.628 0.542 0.0 4.461 0.379 0.0 4.461 0.369 0.0 4.539 0.369 0.0 4.539 0.132 0.0 4.54308 0.09343 0.0 4.5553 0.05944 0.0 4.57563 0.03112 0.0 4.60404 0.00956 0.0 4.6405 -0.00418 0.0 4.685 -0.009 0.0 4.70092 -0.00796 0.0 4.719 -0.005 0.0 4.73825 -0.00038 0.0 4.75767 0.00567 0.0 4.77625 0.01288 0.0 4.793 0.021 0.0 4.793 0.104 0.0 4.77524 0.09392 0.0 4.75793 0.08567 0.0 4.741 0.07925 0.0 4.72441 0.07467 0.0 4.70809 0.07192 0.0 4.692 0.071 0.0 4.67823 0.07236 0.0 4.66385 0.07685 0.0 4.65025 0.08513 0.0 4.63882 0.09781 0.0 4.63094 0.11556 0.0 4.628 0.139 0.0 4.628 0.369 0.0 4.77 0.369 0.0 4.77 0.449 0.0 4.628 0.449 0.0 4.134 0.449 0.0 4.134 0.0 0.0 4.223 0.0 0.0 4.223 0.235 0.0 4.22684 0.27196 0.0 4.2377 0.305 0.0 4.25463 0.33288 0.0 4.27663 0.35433 0.0 4.30275 0.36813 0.0 4.332 0.373 0.0 4.34357 0.37155 0.0 4.35685 0.36737 0.0 4.37125 0.36075 0.0 4.38615 0.35196 0.0 4.40094 0.34129 0.0 4.415 0.329 0.0 4.462 0.406 0.0 4.44373 0.422 0.0 4.42582 0.43504 0.0 4.40813 0.44513 0.0 4.39052 0.4523 0.0 4.37286 0.45658 0.0 4.355 0.458 0.0 4.33391 0.45519 0.0 4.31263 0.44652 0.0 4.29113 0.43163 0.0 4.26937 0.41015 0.0 4.24734 0.38173 0.0 4.225 0.346 0.0 4.223 0.346 0.0 4.223 0.449 0.0 4.049 0.08 0.0 4.0392 0.07301 0.0 4.02993 0.06711 0.0 4.02138 0.06238 0.0 4.01374 0.05889 0.0 4.00722 0.05674 0.0 4.002 0.056 0.0 3.99692 0.05652 0.0 3.9927 0.05819 0.0 3.98938 0.06113 0.0 3.98696 0.06548 0.0 3.9855 0.07139 0.0 3.985 0.079 0.0 3.985 0.31 0.0 3.97925 0.35638 0.0 3.96296 0.3937 0.0 3.93763 0.42225 0.0 3.9047 0.4423 0.0 3.86567 0.45412 0.0 3.822 0.458 0.0 3.79082 0.45633 0.0 3.76226 0.4513 0.0 3.73625 0.44288 0.0 3.71274 0.43104 0.0 3.69168 0.41575 0.0 3.673 0.397 0.0 3.673 0.3 0.0 3.69505 0.32319 0.0 3.71804 0.34185 0.0 3.74175 0.35612 0.0 3.76596 0.36615 0.0 3.79045 0.37206 0.0 3.815 0.374 0.0 3.83975 0.37204 0.0 3.86 0.36596 0.0 3.87575 0.3555 0.0 3.887 0.34037 0.0 3.89375 0.3203 0.0 3.896 0.295 0.0 3.896 0.271 0.0 3.817 0.243 0.0 3.78067 0.22963 0.0 3.74533 0.21441 0.0 3.7135 0.19563 0.0 3.68767 0.17159 0.0 3.67033 0.14062 0.0 3.664 0.101 0.0 3.66757 0.07271 0.0 3.67785 0.0467 0.0 3.69425 0.02425 0.0 3.71615 0.00663 0.0 3.74294 -0.00488 0.0 3.774 -0.009 0.0 3.79449 -0.00775 0.0 3.81493 -0.00396 0.0 3.83525 0.00238 0.0 3.85541 0.0113 0.0 3.87534 0.02283 0.0 3.895 0.037 0.0 3.90011 0.02248 0.0 3.90752 0.01085 0.0 3.91738 0.002 0.0 3.92982 -0.00419 0.0 3.94498 -0.00781 0.0 3.963 -0.009 0.0 3.97625 -0.00828 0.0 3.98863 -0.00593 0.0 4.00113 -0.00163 0.0 4.0147 0.00493 0.0 4.03034 0.01403 0.0 4.049 0.026 0.0 3.896 0.091 0.0 3.88383 0.08027 0.0 3.87133 0.07119 0.0 3.8585 0.06387 0.0 3.84533 0.05848 0.0 3.83183 0.05514 0.0 3.818 0.054 0.0 3.80041 0.0561 0.0 3.78496 0.06211 0.0 3.77213 0.07163 0.0 3.76237 0.08422 0.0 3.75617 0.09949 0.0 3.754 0.117 0.0 3.75924 0.14138 0.0 3.77393 0.162 0.0 3.7965 0.17963 0.0 3.82541 0.195 0.0 3.85909 0.20888 0.0 3.896 0.222 0.0 3.472 0.542 0.0 3.305 0.379 0.0 3.305 0.369 0.0 3.383 0.369 0.0 3.383 0.132 0.0 3.38708 0.09343 0.0 3.3993 0.05944 0.0 3.41963 0.03112 0.0 3.44804 0.00956 0.0 3.48451 -0.00418 0.0 3.529 -0.009 0.0 3.54492 -0.00796 0.0 3.563 -0.005 0.0 3.58225 -0.00038 0.0 3.60167 0.00567 0.0 3.62025 0.01288 0.0 3.637 0.021 0.0 3.637 0.104 0.0 3.61924 0.09392 0.0 3.60193 0.08567 0.0 3.585 0.07925 0.0 3.56841 0.07467 0.0 3.55209 0.07192 0.0 3.536 0.071 0.0 3.52223 0.07236 0.0 3.50785 0.07685 0.0 3.49425 0.08513 0.0 3.48282 0.09781 0.0 3.47494 0.11556 0.0 3.472 0.139 0.0 3.472 0.369 0.0 3.614 0.369 0.0 3.614 0.449 0.0 3.472 0.449 0.0 3.244 0.421 0.0 3.22082 0.43242 0.0 3.19822 0.4417 0.0 3.17613 0.44888 0.0 3.15444 0.45396 0.0 3.1331 0.457 0.0 3.112 0.458 0.0 3.06979 0.45424 0.0 3.03363 0.44326 0.0 3.00425 0.4255 0.0 2.98237 0.40141 0.0 2.96871 0.37143 0.0 2.964 0.336 0.0 2.97956 0.28229 0.0 3.01845 0.24 0.0 3.069 0.20588 0.0 3.11956 0.17667 0.0 3.15844 0.14913 0.0 3.174 0.12 0.0 3.17161 0.10525 0.0 3.16489 0.093 0.0 3.1545 0.08325 0.0 3.14111 0.076 0.0 3.12539 0.07125 0.0 3.108 0.069 0.0 3.08864 0.07059 0.0 3.06678 0.07541 0.0 3.04275 0.0835 0.0 3.01689 0.09493 0.0 2.98953 0.10974 0.0 2.961 0.128 0.0 2.961 0.032 0.0 2.98888 0.01855 0.0 3.015 0.00804 0.0 3.04013 0.00025 0.0 3.065 -0.00504 0.0 3.09038 -0.00805 0.0 3.117 -0.009 0.0 3.15748 -0.00471 0.0 3.19315 0.00767 0.0 3.22288 0.02737 0.0 3.24552 0.05367 0.0 3.25994 0.08579 0.0 3.265 0.123 0.0 3.26266 0.1449 0.0 3.25526 0.16522 0.0 3.24225 0.18488 0.0 3.22307 0.20478 0.0 3.19718 0.22585 0.0 3.164 0.249 0.0 3.1285 0.27025 0.0 3.10063 0.28833 0.0 3.07988 0.30375 0.0 3.0657 0.317 0.0 3.05759 0.32858 0.0 3.055 0.339 0.0 3.05687 0.35037 0.0 3.0623 0.3603 0.0 3.071 0.3685 0.0 3.0827 0.3747 0.0 3.09713 0.37863 0.0 3.114 0.38 0.0 3.13162 0.37881 0.0 3.15126 0.37515 0.0 3.17263 0.36887 0.0 3.19541 0.35985 0.0 3.2193 0.34794 0.0 3.244 0.333 0.0 2.879 0.13 0.0 2.85307 0.11419 0.0 2.82719 0.10089 0.0 2.80125 0.09025 0.0 2.77515 0.08244 0.0 2.74877 0.07764 0.0 2.722 0.076 0.0 2.68193 0.07982 0.0 2.64774 0.09122 0.0 2.6195 0.11013 0.0 2.59726 0.13644 0.0 2.58107 0.1701 0.0 2.571 0.211 0.0 2.887 0.211 0.0 2.88082 0.28694 0.0 2.86289 0.34881 0.0 2.83413 0.39675 0.0 2.79544 0.43085 0.0 2.74776 0.45123 0.0 2.692 0.458 0.0 2.63339 0.45056 0.0 2.58244 0.42911 0.0 2.5405 0.395 0.0 2.50889 0.34956 0.0 2.48894 0.29411 0.0 2.482 0.23 0.0 2.48843 0.16924 0.0 2.50741 0.11293 0.0 2.5385 0.064 0.0 2.58126 0.02541 0.0 2.63524 9e-05 0.0 2.7 -0.009 0.0 2.7359 -0.00757 0.0 2.76819 -0.00326 0.0 2.79775 0.004 0.0 2.82548 0.01426 0.0 2.85227 0.02757 0.0 2.879 0.044 0.0 2.573 0.27 0.0 2.58141 0.30288 0.0 2.59459 0.33033 0.0 2.6125 0.35213 0.0 2.63507 0.368 0.0 2.66226 0.37771 0.0 2.694 0.381 0.0 2.72344 0.3775 0.0 2.74856 0.36733 0.0 2.769 0.351 0.0 2.78445 0.329 0.0 2.79456 0.30183 0.0 2.799 0.27 0.0 2.114 0.449 0.0 2.114 0.0 0.0 2.203 0.0 0.0 2.203 0.235 0.0 2.20684 0.27196 0.0 2.2177 0.305 0.0 2.23463 0.33288 0.0 2.25663 0.35433 0.0 2.28275 0.36813 0.0 2.312 0.373 0.0 2.32357 0.37155 0.0 2.33685 0.36737 0.0 2.35125 0.36075 0.0 2.36615 0.35196 0.0 2.38094 0.34129 0.0 2.395 0.329 0.0 2.442 0.406 0.0 2.42373 0.422 0.0 2.40582 0.43504 0.0 2.38813 0.44513 0.0 2.37052 0.4523 0.0 2.35286 0.45658 0.0 2.335 0.458 0.0 2.31391 0.45519 0.0 2.29263 0.44652 0.0 2.27113 0.43163 0.0 2.24937 0.41015 0.0 2.22734 0.38173 0.0 2.205 0.346 0.0 2.203 0.346 0.0 2.203 0.449 0.0 1.488 0.458 0.0 1.42392 0.45 0.0 1.367 0.4273 0.0 1.31925 0.39187 0.0 1.28267 0.3457 0.0 1.25925 0.29075 0.0 1.251 0.229 0.0 1.25897 0.16345 0.0 1.28178 0.10596 0.0 1.31775 0.05825 0.0 1.36522 0.02204 0.0 1.42253 -0.00095 0.0 1.488 -0.009 0.0 1.556 -0.00123 0.0 1.615 0.02115 0.0 1.6635 0.05675 0.0 1.7 0.10419 0.0 1.723 0.16206 0.0 1.731 0.229 0.0 1.72279 0.29214 0.0 1.69933 0.34748 0.0 1.66238 0.39338 0.0 1.61367 0.42819 0.0 1.55496 0.45027 0.0 1.487 0.378 0.0 1.52924 0.37293 0.0 1.56622 0.35844 0.0 1.59688 0.33563 0.0 1.62011 0.30556 0.0 1.63485 0.26932 0.0 1.64 0.228 0.0 1.63519 0.18269 0.0 1.62122 0.14419 0.0 1.59875 0.11313 0.0 1.56844 0.09015 0.0 1.53097 0.07589 0.0 1.487 0.071 0.0 1.4464 0.07611 0.0 1.41119 0.09085 0.0 1.38225 0.11437 0.0 1.36048 0.14581 0.0 1.34677 0.18431 0.0 1.342 0.229 0.0 1.34691 0.2699 0.0 1.36093 0.30585 0.0 1.383 0.33575 0.0 1.41207 0.35848 0.0 1.44709 0.37294 0.0 1.049 0.542 0.0 0.882 0.379 0.0 0.882 0.369 0.0 0.96 0.369 0.0 0.96 0.132 0.0 0.96408 0.09343 0.0 0.9763 0.05944 0.0 0.99663 0.03112 0.0 1.02504 0.00956 0.0 1.0615 -0.00418 0.0 1.106 -0.009 0.0 1.12192 -0.00796 0.0 1.14 -0.005 0.0 1.15925 -0.00038 0.0 1.17867 0.00567 0.0 1.19725 0.01288 0.0 1.214 0.021 0.0 1.214 0.104 0.0 1.19624 0.09392 0.0 1.17893 0.08567 0.0 1.162 0.07925 0.0 1.14541 0.07467 0.0 1.12909 0.07192 0.0 1.113 0.071 0.0 1.09923 0.07236 0.0 1.08485 0.07685 0.0 1.07125 0.08513 0.0 1.05981 0.09781 0.0 1.05194 0.11556 0.0 1.049 0.139 0.0 1.049 0.369 0.0 1.191 0.369 0.0 1.191 0.449 0.0 1.049 0.449 0.0 0.077 0.682 0.0 0.077 0.0 0.0 0.175 0.0 0.0 0.175 0.296 0.0 0.216 0.296 0.0 0.24052 0.29417 0.0 0.26515 0.28667 0.0 0.2915 0.2705 0.0 0.32119 0.24267 0.0 0.35581 0.20017 0.0 0.397 0.14 0.0 0.487 0.0 0.0 0.604 0.0 0.0 0.58281 0.02931 0.0 0.56544 0.05344 0.0 0.55075 0.07425 0.0 0.53756 0.09356 0.0 0.52469 0.11319 0.0 0.511 0.135 0.0 0.48599 0.17567 0.0 0.46226 0.21267 0.0 0.43875 0.246 0.0 0.41441 0.27567 0.0 0.38818 0.30167 0.0 0.359 0.324 0.0 0.39279 0.34095 0.0 0.421 0.36263 0.0 0.44337 0.38875 0.0 0.45967 0.41904 0.0 0.46962 0.45321 0.0 0.473 0.491 0.0 0.46599 0.54612 0.0 0.44559 0.59296 0.0 0.41275 0.63075 0.0 0.36841 0.6587 0.0 0.31351 0.67605 0.0 0.249 0.682 0.0 0.175 0.598 0.0 0.238 0.598 0.0 0.28084 0.59481 0.0 0.31474 0.58552 0.0 0.34025 0.5705 0.0 0.35793 0.55015 0.0 0.36832 0.52485 0.0 0.372 0.495 0.0 0.36971 0.46699 0.0 0.36104 0.44089 0.0 0.34475 0.41813 0.0 0.31963 0.40011 0.0 0.28445 0.38826 0.0 0.238 0.384 0.0 0.175 0.384 0.0 - - - - - - - - - - 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    1 0 0 1 33 2 1 3 33 4 32 5 1 6 32 7 31 8 2 9 1 10 31 11 3 12 2 13 31 14 4 15 3 16 30 17 30 18 3 19 31 20 4 21 30 22 29 23 4 24 29 25 28 26 5 27 4 28 28 29 5 30 28 31 27 32 18 33 17 34 16 35 5 36 27 37 26 38 19 39 18 40 16 41 6 42 5 43 26 44 20 45 19 46 16 47 6 48 26 49 25 50 21 51 20 52 16 53 6 54 25 55 24 56 22 57 21 58 16 59 6 60 24 61 23 62 23 63 22 64 16 65 6 66 23 67 16 68 7 69 6 70 16 71 8 72 7 73 16 74 8 75 16 76 15 77 8 78 15 79 14 80 9 81 8 82 14 83 9 84 14 85 13 86 9 87 13 88 12 89 10 90 9 91 12 92 10 93 12 94 11 95 57 96 56 97 55 98 57 99 55 100 54 101 58 102 57 103 54 104 58 105 54 106 53 107 35 108 34 109 64 110 35 111 64 112 63 113 59 114 58 115 53 116 59 117 53 118 52 119 59 120 52 121 51 122 60 123 59 124 51 125 60 126 51 127 50 128 61 129 60 130 50 131 61 132 50 133 43 134 43 135 50 136 44 137 44 138 50 139 45 140 45 141 50 142 46 143 46 144 50 145 47 146 47 147 50 148 48 149 48 150 50 151 49 152 62 153 61 154 42 155 42 156 61 157 43 158 62 159 42 160 41 161 62 162 41 163 40 164 35 165 63 166 62 167 35 168 62 169 39 170 39 171 62 172 40 173 35 174 39 175 38 176 35 177 38 178 37 179 35 180 37 181 36 182 85 183 84 184 83 185 86 186 85 187 83 188 86 189 83 190 82 191 87 192 86 193 82 194 88 195 87 196 82 197 88 198 82 199 81 200 89 201 88 202 81 203 89 204 81 205 80 206 90 207 89 208 80 209 91 210 90 211 92 212 92 213 90 214 93 215 93 216 90 217 94 218 94 219 90 220 95 221 95 222 90 223 96 224 96 225 90 226 97 227 97 228 90 229 80 230 97 231 80 232 98 233 98 234 80 235 79 236 99 237 98 238 79 239 100 240 99 241 79 242 100 243 79 244 78 245 101 246 100 247 78 248 102 249 101 250 78 251 103 252 102 253 78 254 103 255 78 256 77 257 104 258 103 259 77 260 105 261 104 262 154 263 154 264 104 265 77 266 106 267 105 268 154 269 107 270 106 271 154 272 107 273 154 274 153 275 136 276 154 277 77 278 108 279 107 280 153 281 108 282 153 283 152 284 109 285 108 286 152 287 109 288 152 289 151 290 109 291 151 292 150 293 110 294 109 295 150 296 110 297 150 298 149 299 110 300 149 301 148 302 111 303 110 304 148 305 111 306 148 307 147 308 112 309 111 310 147 311 112 312 147 313 146 314 137 315 136 316 77 317 112 318 146 319 145 320 138 321 137 322 77 323 66 324 65 325 135 326 138 327 77 328 76 329 67 330 66 331 135 332 113 333 112 334 145 335 113 336 145 337 144 338 138 339 76 340 75 341 139 342 138 343 75 344 68 345 67 346 135 347 139 348 75 349 74 350 140 351 139 352 74 353 69 354 68 355 135 356 113 357 144 358 143 359 140 360 74 361 73 362 70 363 69 364 135 365 141 366 140 367 73 368 141 369 73 370 72 371 71 372 70 373 135 374 141 375 72 376 71 377 113 378 143 379 142 380 141 381 71 382 135 383 142 384 141 385 135 386 113 387 142 388 123 389 123 390 142 391 135 392 114 393 113 394 123 395 114 396 123 397 122 398 124 399 123 400 135 401 124 402 135 403 134 404 115 405 114 406 122 407 115 408 122 409 121 410 125 411 124 412 134 413 125 414 134 415 133 416 115 417 121 418 120 419 126 420 125 421 133 422 116 423 115 424 120 425 126 426 133 427 132 428 116 429 120 430 119 431 127 432 126 433 132 434 127 435 132 436 131 437 116 438 119 439 118 440 128 441 127 442 131 443 117 444 116 445 118 446 128 447 131 448 130 449 129 450 128 451 130 452 156 453 155 454 188 455 156 456 188 457 187 458 156 459 187 460 186 461 157 462 156 463 186 464 158 465 157 466 186 467 159 468 158 469 185 470 185 471 158 472 186 473 159 474 185 475 184 476 159 477 184 478 183 479 160 480 159 481 183 482 160 483 183 484 182 485 173 486 172 487 171 488 160 489 182 490 181 491 174 492 173 493 171 494 161 495 160 496 181 497 175 498 174 499 171 500 161 501 181 502 180 503 176 504 175 505 171 506 161 507 180 508 179 509 177 510 176 511 171 512 161 513 179 514 178 515 178 516 177 517 171 518 161 519 178 520 171 521 162 522 161 523 171 524 163 525 162 526 171 527 163 528 171 529 170 530 163 531 170 532 169 533 164 534 163 535 169 536 164 537 169 538 168 539 164 540 168 541 167 542 165 543 164 544 167 545 165 546 167 547 166 548 196 549 195 550 194 551 196 552 194 553 193 554 197 555 196 556 193 557 197 558 193 559 192 560 197 561 192 562 191 563 198 564 197 565 191 566 198 567 191 568 190 569 198 570 190 571 189 572 199 573 198 574 189 575 199 576 189 577 250 578 250 579 189 580 251 581 251 582 189 583 252 584 252 585 189 586 253 587 253 588 189 589 254 590 254 591 189 592 255 593 255 594 189 595 256 596 200 597 199 598 250 599 200 600 250 601 249 602 200 603 249 604 248 605 200 606 248 607 247 608 201 609 200 610 247 611 201 612 247 613 246 614 201 615 246 616 245 617 201 618 245 619 244 620 201 621 244 622 243 623 202 624 201 625 243 626 202 627 243 628 242 629 202 630 242 631 241 632 202 633 241 634 240 635 202 636 240 637 239 638 203 639 202 640 239 641 203 642 239 643 238 644 203 645 238 646 237 647 204 648 203 649 237 650 204 651 237 652 236 653 205 654 204 655 236 656 205 657 236 658 235 659 205 660 235 661 234 662 206 663 205 664 234 665 206 666 234 667 233 668 207 669 206 670 233 671 207 672 233 673 232 674 220 675 219 676 218 677 207 678 232 679 231 680 208 681 207 682 231 683 220 684 218 685 217 686 209 687 208 688 231 689 220 690 217 691 216 692 210 693 209 694 231 695 210 696 231 697 230 698 220 699 216 700 215 701 211 702 210 703 230 704 212 705 211 706 230 707 220 708 215 709 214 710 213 711 212 712 230 713 220 714 214 715 213 716 220 717 213 718 230 719 220 720 230 721 229 722 221 723 220 724 229 725 221 726 229 727 228 728 222 729 221 730 228 731 223 732 222 733 228 734 223 735 228 736 227 737 224 738 223 739 227 740 224 741 227 742 226 743 225 744 224 745 226 746 277 747 276 748 275 749 277 750 275 751 274 752 278 753 277 754 274 755 278 756 274 757 273 758 279 759 278 760 273 761 279 762 273 763 301 764 301 765 273 766 302 767 302 768 273 769 272 770 280 771 279 772 300 773 300 774 279 775 301 776 280 777 300 778 299 779 303 780 302 781 272 782 280 783 299 784 298 785 304 786 303 787 272 788 280 789 298 790 297 791 305 792 304 793 272 794 281 795 280 796 297 797 305 798 272 799 271 800 281 801 297 802 296 803 306 804 305 805 271 806 281 807 296 808 295 809 307 810 306 811 271 812 282 813 281 814 295 815 307 816 271 817 270 818 282 819 295 820 307 821 282 822 307 823 270 824 283 825 282 826 269 827 269 828 282 829 270 830 283 831 269 832 268 833 283 834 268 835 267 836 284 837 283 838 267 839 284 840 267 841 266 842 258 843 257 844 294 845 259 846 258 847 294 848 285 849 284 850 266 851 285 852 266 853 265 854 260 855 259 856 294 857 285 858 265 859 264 860 261 861 260 862 294 863 262 864 261 865 294 866 285 867 264 868 263 869 263 870 262 871 294 872 285 873 263 874 294 875 286 876 285 877 294 878 286 879 294 880 293 881 286 882 293 883 292 884 287 885 286 886 292 887 287 888 292 889 291 890 287 891 291 892 290 893 288 894 287 895 290 896 288 897 290 898 289 899 331 900 330 901 329 902 331 903 329 904 328 905 332 906 331 907 328 908 332 909 328 910 327 911 309 912 308 913 338 914 309 915 338 916 337 917 333 918 332 919 327 920 333 921 327 922 326 923 333 924 326 925 325 926 334 927 333 928 325 929 334 930 325 931 324 932 335 933 334 934 324 935 335 936 324 937 317 938 317 939 324 940 318 941 318 942 324 943 319 944 319 945 324 946 320 947 320 948 324 949 321 950 321 951 324 952 322 953 322 954 324 955 323 956 336 957 335 958 316 959 316 960 335 961 317 962 336 963 316 964 315 965 336 966 315 967 314 968 309 969 337 970 336 971 309 972 336 973 313 974 313 975 336 976 314 977 309 978 313 979 312 980 309 981 312 982 311 983 309 984 311 985 310 986 340 987 339 988 362 989 340 990 362 991 361 992 341 993 340 994 361 995 341 996 361 997 360 998 342 999 341 1000 360 1001 342 1002 360 1003 363 1004 363 1005 360 1006 364 1007 364 1008 360 1009 359 1010 343 1011 342 1012 386 1013 386 1014 342 1015 363 1016 343 1017 386 1018 385 1019 365 1020 364 1021 359 1022 343 1023 385 1024 384 1025 366 1026 365 1027 359 1028 366 1029 359 1030 358 1031 344 1032 343 1033 384 1034 344 1035 384 1036 383 1037 367 1038 366 1039 358 1040 344 1041 383 1042 382 1043 368 1044 367 1045 358 1046 368 1047 358 1048 357 1049 345 1050 344 1051 382 1052 345 1053 382 1054 381 1055 369 1056 368 1057 357 1058 346 1059 345 1060 381 1061 346 1062 381 1063 380 1064 369 1065 357 1066 356 1067 370 1068 369 1069 356 1070 346 1071 380 1072 379 1073 371 1074 370 1075 356 1076 347 1077 346 1078 379 1079 371 1080 356 1081 355 1082 347 1083 379 1084 378 1085 372 1086 371 1087 355 1088 347 1089 378 1090 377 1091 373 1092 372 1093 355 1094 348 1095 347 1096 377 1097 373 1098 355 1099 354 1100 348 1101 377 1102 376 1103 374 1104 373 1105 354 1106 348 1107 376 1108 375 1109 375 1110 374 1111 354 1112 348 1113 375 1114 354 1115 349 1116 348 1117 354 1118 349 1119 354 1120 353 1121 350 1122 349 1123 353 1124 350 1125 353 1126 352 1127 351 1128 350 1129 352 1130 388 1131 387 1132 420 1133 388 1134 420 1135 419 1136 388 1137 419 1138 418 1139 389 1140 388 1141 418 1142 390 1143 389 1144 418 1145 391 1146 390 1147 417 1148 417 1149 390 1150 418 1151 391 1152 417 1153 416 1154 391 1155 416 1156 415 1157 392 1158 391 1159 415 1160 392 1161 415 1162 414 1163 405 1164 404 1165 403 1166 392 1167 414 1168 413 1169 406 1170 405 1171 403 1172 393 1173 392 1174 413 1175 407 1176 406 1177 403 1178 393 1179 413 1180 412 1181 408 1182 407 1183 403 1184 393 1185 412 1186 411 1187 409 1188 408 1189 403 1190 393 1191 411 1192 410 1193 410 1194 409 1195 403 1196 393 1197 410 1198 403 1199 394 1200 393 1201 403 1202 395 1203 394 1204 403 1205 395 1206 403 1207 402 1208 395 1209 402 1210 401 1211 396 1212 395 1213 401 1214 396 1215 401 1216 400 1217 396 1218 400 1219 399 1220 397 1221 396 1222 399 1223 397 1224 399 1225 398 1226 422 1227 421 1228 458 1229 458 1230 421 1231 457 1232 458 1233 457 1234 456 1235 458 1236 456 1237 455 1238 458 1239 455 1240 454 1241 458 1242 454 1243 459 1244 459 1245 454 1246 453 1247 422 1248 458 1249 472 1250 460 1251 459 1252 453 1253 461 1254 460 1255 453 1256 461 1257 453 1258 452 1259 462 1260 461 1261 452 1262 463 1263 462 1264 452 1265 464 1266 463 1267 452 1268 464 1269 452 1270 451 1271 465 1272 464 1273 451 1274 466 1275 465 1276 451 1277 466 1278 451 1279 450 1280 467 1281 466 1282 450 1283 467 1284 450 1285 449 1286 468 1287 467 1288 449 1289 468 1290 449 1291 448 1292 469 1293 468 1294 448 1295 470 1296 469 1297 448 1298 470 1299 448 1300 447 1301 471 1302 470 1303 447 1304 422 1305 472 1306 424 1307 424 1308 472 1309 471 1310 424 1311 471 1312 447 1313 424 1314 447 1315 446 1316 424 1317 446 1318 445 1319 424 1320 445 1321 444 1322 424 1323 444 1324 425 1325 425 1326 444 1327 426 1328 426 1329 444 1330 443 1331 422 1332 424 1333 423 1334 427 1335 426 1336 443 1337 428 1338 427 1339 443 1340 428 1341 443 1342 442 1343 429 1344 428 1345 442 1346 429 1347 442 1348 441 1349 430 1350 429 1351 441 1352 430 1353 441 1354 440 1355 431 1356 430 1357 440 1358 431 1359 440 1360 439 1361 432 1362 431 1363 439 1364 432 1365 439 1366 438 1367 432 1368 438 1369 437 1370 432 1371 437 1372 436 1373 432 1374 436 1375 435 1376 432 1377 435 1378 434 1379 432 1380 434 1381 433 1382

    - - - - - - - 9.646 -1.87 0.0 9.62007 -1.88581 0.0 9.59419 -1.89911 0.0 9.56825 -1.90975 0.0 9.54215 -1.91756 0.0 9.51577 -1.92236 0.0 9.489 -1.924 0.0 9.44893 -1.92018 0.0 9.41474 -1.90878 0.0 9.3865 -1.88988 0.0 9.36426 -1.86356 0.0 9.34807 -1.8299 0.0 9.338 -1.789 0.0 9.654 -1.789 0.0 9.64782 -1.71306 0.0 9.62989 -1.65119 0.0 9.60113 -1.60325 0.0 9.56245 -1.56915 0.0 9.51476 -1.54877 0.0 9.459 -1.542 0.0 9.40039 -1.54944 0.0 9.34945 -1.57089 0.0 9.3075 -1.605 0.0 9.27589 -1.65044 0.0 9.25595 -1.70589 0.0 9.249 -1.77 0.0 9.25543 -1.83076 0.0 9.27441 -1.88707 0.0 9.3055 -1.936 0.0 9.34826 -1.97459 0.0 9.40224 -1.99991 0.0 9.467 -2.009 0.0 9.5029 -2.00757 0.0 9.53519 -2.00326 0.0 9.56475 -1.996 0.0 9.59248 -1.98574 0.0 9.61927 -1.97243 0.0 9.646 -1.956 0.0 9.34 -1.73 0.0 9.34841 -1.69712 0.0 9.36159 -1.66967 0.0 9.3795 -1.64787 0.0 9.40208 -1.632 0.0 9.42926 -1.62229 0.0 9.461 -1.619 0.0 9.49045 -1.6225 0.0 9.51556 -1.63267 0.0 9.536 -1.649 0.0 9.55145 -1.671 0.0 9.56156 -1.69817 0.0 9.566 -1.73 0.0 9.042 -1.458 0.0 8.875 -1.621 0.0 8.875 -1.631 0.0 8.953 -1.631 0.0 8.953 -1.868 0.0 8.95708 -1.90657 0.0 8.9693 -1.94056 0.0 8.98963 -1.96888 0.0 9.01804 -1.99044 0.0 9.05451 -2.00418 0.0 9.099 -2.009 0.0 9.11492 -2.00796 0.0 9.133 -2.005 0.0 9.15225 -2.00038 0.0 9.17167 -1.99433 0.0 9.19025 -1.98713 0.0 9.207 -1.979 0.0 9.207 -1.896 0.0 9.18924 -1.90608 0.0 9.17193 -1.91433 0.0 9.155 -1.92075 0.0 9.13841 -1.92533 0.0 9.12209 -1.92808 0.0 9.106 -1.929 0.0 9.09223 -1.92764 0.0 9.07785 -1.92315 0.0 9.06425 -1.91488 0.0 9.05282 -1.90219 0.0 9.04494 -1.88444 0.0 9.042 -1.861 0.0 9.042 -1.631 0.0 9.184 -1.631 0.0 9.184 -1.551 0.0 9.042 -1.551 0.0 8.859 -1.92 0.0 8.8492 -1.92699 0.0 8.83993 -1.93289 0.0 8.83138 -1.93762 0.0 8.82374 -1.94111 0.0 8.81722 -1.94326 0.0 8.812 -1.944 0.0 8.80692 -1.94348 0.0 8.8027 -1.94181 0.0 8.79938 -1.93887 0.0 8.79696 -1.93452 0.0 8.7955 -1.92861 0.0 8.795 -1.921 0.0 8.795 -1.69 0.0 8.78925 -1.64362 0.0 8.77296 -1.6063 0.0 8.74763 -1.57775 0.0 8.7147 -1.5577 0.0 8.67567 -1.54588 0.0 8.632 -1.542 0.0 8.60083 -1.54367 0.0 8.57226 -1.5487 0.0 8.54625 -1.55712 0.0 8.52274 -1.56896 0.0 8.50168 -1.58425 0.0 8.483 -1.603 0.0 8.483 -1.7 0.0 8.50505 -1.67681 0.0 8.52804 -1.65815 0.0 8.55175 -1.64387 0.0 8.57596 -1.63385 0.0 8.60045 -1.62794 0.0 8.625 -1.626 0.0 8.64975 -1.62796 0.0 8.67 -1.63404 0.0 8.68575 -1.6445 0.0 8.697 -1.65963 0.0 8.70375 -1.6797 0.0 8.706 -1.705 0.0 8.706 -1.729 0.0 8.627 -1.757 0.0 8.59067 -1.77037 0.0 8.55533 -1.78559 0.0 8.5235 -1.80437 0.0 8.49767 -1.82841 0.0 8.48033 -1.85938 0.0 8.474 -1.899 0.0 8.47757 -1.92729 0.0 8.48785 -1.9533 0.0 8.50425 -1.97575 0.0 8.52615 -1.99337 0.0 8.55294 -2.00488 0.0 8.584 -2.009 0.0 8.60449 -2.00775 0.0 8.62493 -2.00396 0.0 8.64525 -1.99762 0.0 8.66541 -1.9887 0.0 8.68534 -1.97717 0.0 8.705 -1.963 0.0 8.71011 -1.97752 0.0 8.71752 -1.98915 0.0 8.72738 -1.998 0.0 8.73982 -2.00419 0.0 8.75498 -2.00781 0.0 8.773 -2.009 0.0 8.78625 -2.00828 0.0 8.79863 -2.00593 0.0 8.81113 -2.00162 0.0 8.8247 -1.99507 0.0 8.84034 -1.98597 0.0 8.859 -1.974 0.0 8.706 -1.909 0.0 8.69383 -1.91973 0.0 8.68133 -1.92881 0.0 8.6685 -1.93612 0.0 8.65533 -1.94152 0.0 8.64183 -1.94486 0.0 8.628 -1.946 0.0 8.61041 -1.9439 0.0 8.59496 -1.93789 0.0 8.58212 -1.92838 0.0 8.57237 -1.91578 0.0 8.56617 -1.90051 0.0 8.564 -1.883 0.0 8.56924 -1.85863 0.0 8.58393 -1.838 0.0 8.6065 -1.82038 0.0 8.63541 -1.805 0.0 8.6691 -1.79113 0.0 8.706 -1.778 0.0 8.442 -1.551 0.0 8.257 -1.551 0.0 8.20047 -1.55581 0.0 8.15241 -1.56985 0.0 8.11363 -1.5925 0.0 8.08493 -1.62315 0.0 8.06712 -1.66119 0.0 8.061 -1.706 0.0 8.06167 -1.72208 0.0 8.06367 -1.73733 0.0 8.067 -1.75175 0.0 8.07167 -1.76533 0.0 8.07767 -1.77808 0.0 8.085 -1.79 0.0 8.09417 -1.80158 0.0 8.10467 -1.81233 0.0 8.1165 -1.82225 0.0 8.12967 -1.83133 0.0 8.14417 -1.83958 0.0 8.16 -1.847 0.0 8.16 -1.849 0.0 8.13981 -1.8552 0.0 8.12248 -1.86359 0.0 8.10837 -1.87388 0.0 8.09785 -1.88574 0.0 8.09127 -1.89888 0.0 8.089 -1.913 0.0 8.09018 -1.92285 0.0 8.09378 -1.93244 0.0 8.09988 -1.94187 0.0 8.10856 -1.95122 0.0 8.1199 -1.96057 0.0 8.134 -1.97 0.0 8.09855 -1.9812 0.0 8.07004 -1.99593 0.0 8.04825 -2.01438 0.0 8.03296 -2.03674 0.0 8.02395 -2.06322 0.0 8.021 -2.094 0.0 8.02793 -2.1315 0.0 8.04778 -2.16437 0.0 8.07913 -2.19163 0.0 8.12056 -2.2123 0.0 8.17065 -2.22541 0.0 8.228 -2.23 0.0 8.28988 -2.22559 0.0 8.34207 -2.2127 0.0 8.38387 -2.19188 0.0 8.41459 -2.16363 0.0 8.43353 -2.1285 0.0 8.44 -2.087 0.0 8.43704 -2.05927 0.0 8.42763 -2.03348 0.0 8.411 -2.01025 0.0 8.38637 -1.99019 0.0 8.35296 -1.9739 0.0 8.31 -1.962 0.0 8.2686 -1.95319 0.0 8.23448 -1.94452 0.0 8.20775 -1.93563 0.0 8.18852 -1.92615 0.0 8.1769 -1.91573 0.0 8.173 -1.904 0.0 8.18232 -1.88375 0.0 8.20685 -1.87263 0.0 8.2415 -1.86563 0.0 8.28115 -1.8577 0.0 8.32069 -1.84384 0.0 8.355 -1.819 0.0 8.3654 -1.8068 0.0 8.37522 -1.7917 0.0 8.38388 -1.7745 0.0 8.39078 -1.75596 0.0 8.39535 -1.73687 0.0 8.397 -1.718 0.0 8.39595 -1.69998 0.0 8.39259 -1.68348 0.0 8.38663 -1.66787 0.0 8.37774 -1.65252 0.0 8.36563 -1.63677 0.0 8.35 -1.62 0.0 8.442 -1.62 0.0 8.317 -1.707 0.0 8.3141 -1.73024 0.0 8.30582 -1.75056 0.0 8.29275 -1.76738 0.0 8.27552 -1.78011 0.0 8.25473 -1.78818 0.0 8.231 -1.791 0.0 8.20558 -1.78833 0.0 8.18367 -1.78063 0.0 8.16575 -1.76838 0.0 8.15234 -1.75204 0.0 8.14392 -1.73209 0.0 8.141 -1.709 0.0 8.14419 -1.68772 0.0 8.15319 -1.66844 0.0 8.16713 -1.652 0.0 8.18515 -1.63922 0.0 8.20639 -1.63094 0.0 8.23 -1.628 0.0 8.25276 -1.63087 0.0 8.27345 -1.63893 0.0 8.29113 -1.65138 0.0 8.30489 -1.66741 0.0 8.31382 -1.68622 0.0 8.354 -2.094 0.0 8.35023 -2.11305 0.0 8.33919 -2.12907 0.0 8.32125 -2.14188 0.0 8.29681 -2.15126 0.0 8.26627 -2.15703 0.0 8.23 -2.159 0.0 8.19262 -2.15701 0.0 8.16159 -2.15111 0.0 8.13713 -2.14138 0.0 8.11941 -2.12789 0.0 8.10863 -2.11074 0.0 8.105 -2.09 0.0 8.10839 -2.07107 0.0 8.11811 -2.05459 0.0 8.1335 -2.041 0.0 8.15389 -2.03074 0.0 8.17861 -2.02426 0.0 8.207 -2.022 0.0 8.23699 -2.02338 0.0 8.26956 -2.028 0.0 8.30113 -2.03663 0.0 8.32811 -2.05 0.0 8.34693 -2.06888 0.0 7.956 -1.551 0.0 7.867 -1.551 0.0 7.867 -2.0 0.0 7.956 -2.0 0.0 7.965 -1.415 0.0 7.96309 -1.401 0.0 7.9577 -1.38837 0.0 7.94938 -1.37762 0.0 7.93863 -1.3693 0.0 7.926 -1.36391 0.0 7.912 -1.362 0.0 7.89801 -1.36391 0.0 7.88537 -1.3693 0.0 7.87463 -1.37762 0.0 7.8663 -1.38837 0.0 7.86091 -1.401 0.0 7.859 -1.415 0.0 7.86091 -1.429 0.0 7.8663 -1.44163 0.0 7.87463 -1.45238 0.0 7.88537 -1.4607 0.0 7.89801 -1.46609 0.0 7.912 -1.468 0.0 7.926 -1.46609 0.0 7.93863 -1.4607 0.0 7.94938 -1.45238 0.0 7.9577 -1.44163 0.0 7.96309 -1.429 0.0 7.57 -2.009 0.0 7.6 -2.009 0.0 7.798 -1.551 0.0 7.703 -1.551 0.0 7.585 -1.827 0.0 7.464 -1.551 0.0 7.367 -1.551 0.0 7.348 -1.92 0.0 7.3382 -1.92699 0.0 7.32893 -1.93289 0.0 7.32038 -1.93762 0.0 7.31274 -1.94111 0.0 7.30622 -1.94326 0.0 7.301 -1.944 0.0 7.29592 -1.94348 0.0 7.2917 -1.94181 0.0 7.28837 -1.93887 0.0 7.28596 -1.93452 0.0 7.2845 -1.92861 0.0 7.284 -1.921 0.0 7.284 -1.69 0.0 7.27825 -1.64362 0.0 7.26196 -1.6063 0.0 7.23663 -1.57775 0.0 7.2037 -1.5577 0.0 7.16467 -1.54588 0.0 7.121 -1.542 0.0 7.08982 -1.54367 0.0 7.06126 -1.5487 0.0 7.03525 -1.55712 0.0 7.01174 -1.56896 0.0 6.99068 -1.58425 0.0 6.972 -1.603 0.0 6.972 -1.7 0.0 6.99405 -1.67681 0.0 7.01704 -1.65815 0.0 7.04075 -1.64387 0.0 7.06496 -1.63385 0.0 7.08945 -1.62794 0.0 7.114 -1.626 0.0 7.13875 -1.62796 0.0 7.159 -1.63404 0.0 7.17475 -1.6445 0.0 7.186 -1.65963 0.0 7.19275 -1.6797 0.0 7.195 -1.705 0.0 7.195 -1.729 0.0 7.116 -1.757 0.0 7.07967 -1.77037 0.0 7.04433 -1.78559 0.0 7.0125 -1.80437 0.0 6.98667 -1.82841 0.0 6.96933 -1.85938 0.0 6.963 -1.899 0.0 6.96657 -1.92729 0.0 6.97685 -1.9533 0.0 6.99325 -1.97575 0.0 7.01515 -1.99337 0.0 7.04194 -2.00488 0.0 7.073 -2.009 0.0 7.09349 -2.00775 0.0 7.11393 -2.00396 0.0 7.13425 -1.99762 0.0 7.15441 -1.9887 0.0 7.17434 -1.97717 0.0 7.194 -1.963 0.0 7.19911 -1.97752 0.0 7.20652 -1.98915 0.0 7.21638 -1.998 0.0 7.22882 -2.00419 0.0 7.24398 -2.00781 0.0 7.262 -2.009 0.0 7.27525 -2.00828 0.0 7.28763 -2.00593 0.0 7.30013 -2.00162 0.0 7.3137 -1.99507 0.0 7.32934 -1.98597 0.0 7.348 -1.974 0.0 7.195 -1.909 0.0 7.18283 -1.91973 0.0 7.17033 -1.92881 0.0 7.1575 -1.93612 0.0 7.14433 -1.94152 0.0 7.13083 -1.94486 0.0 7.117 -1.946 0.0 7.09941 -1.9439 0.0 7.08396 -1.93789 0.0 7.07113 -1.92838 0.0 7.06137 -1.91578 0.0 7.05517 -1.90051 0.0 7.053 -1.883 0.0 7.05824 -1.85863 0.0 7.07293 -1.838 0.0 7.0955 -1.82038 0.0 7.12441 -1.805 0.0 7.15809 -1.79113 0.0 7.195 -1.778 0.0 6.587 -1.551 0.0 6.498 -1.551 0.0 6.498 -2.0 0.0 6.587 -2.0 0.0 6.587 -1.678 0.0 6.60717 -1.65687 0.0 6.62604 -1.64026 0.0 6.64412 -1.62787 0.0 6.66196 -1.61941 0.0 6.68008 -1.61455 0.0 6.699 -1.613 0.0 6.72427 -1.61649 0.0 6.74582 -1.62659 0.0 6.76325 -1.64275 0.0 6.77619 -1.66441 0.0 6.78423 -1.69101 0.0 6.787 -1.722 0.0 6.787 -2.0 0.0 6.876 -2.0 0.0 6.876 -1.723 0.0 6.87057 -1.66688 0.0 6.85522 -1.62141 0.0 6.83138 -1.58637 0.0 6.80044 -1.56159 0.0 6.76385 -1.54687 0.0 6.723 -1.542 0.0 6.69807 -1.54405 0.0 6.67359 -1.55007 0.0 6.65 -1.55987 0.0 6.62774 -1.57326 0.0 6.60726 -1.59003 0.0 6.589 -1.61 0.0 6.587 -1.61 0.0 5.88 -1.542 0.0 5.81592 -1.55 0.0 5.759 -1.5727 0.0 5.71125 -1.60812 0.0 5.67467 -1.6543 0.0 5.65125 -1.70925 0.0 5.643 -1.771 0.0 5.65097 -1.83655 0.0 5.67378 -1.89404 0.0 5.70975 -1.94175 0.0 5.75722 -1.97796 0.0 5.81453 -2.00095 0.0 5.88 -2.009 0.0 5.948 -2.00123 0.0 6.007 -1.97885 0.0 6.0555 -1.94325 0.0 6.092 -1.89581 0.0 6.115 -1.83794 0.0 6.123 -1.771 0.0 6.11479 -1.70786 0.0 6.09133 -1.65252 0.0 6.05438 -1.60662 0.0 6.00567 -1.57181 0.0 5.94696 -1.54973 0.0 5.879 -1.622 0.0 5.92124 -1.62707 0.0 5.95822 -1.64156 0.0 5.98888 -1.66437 0.0 6.01211 -1.69444 0.0 6.02685 -1.73068 0.0 6.032 -1.772 0.0 6.02719 -1.81731 0.0 6.01322 -1.85581 0.0 5.99075 -1.88687 0.0 5.96044 -1.90985 0.0 5.92297 -1.92411 0.0 5.879 -1.929 0.0 5.8384 -1.92389 0.0 5.80319 -1.90915 0.0 5.77425 -1.88563 0.0 5.75248 -1.85419 0.0 5.73877 -1.81569 0.0 5.734 -1.771 0.0 5.73891 -1.7301 0.0 5.75293 -1.69415 0.0 5.775 -1.66425 0.0 5.80407 -1.64152 0.0 5.83909 -1.62706 0.0 5.441 -1.458 0.0 5.274 -1.621 0.0 5.274 -1.631 0.0 5.352 -1.631 0.0 5.352 -1.868 0.0 5.35608 -1.90657 0.0 5.3683 -1.94056 0.0 5.38863 -1.96888 0.0 5.41704 -1.99044 0.0 5.4535 -2.00418 0.0 5.498 -2.009 0.0 5.51392 -2.00796 0.0 5.532 -2.005 0.0 5.55125 -2.00038 0.0 5.57067 -1.99433 0.0 5.58925 -1.98713 0.0 5.606 -1.979 0.0 5.606 -1.896 0.0 5.58824 -1.90608 0.0 5.57093 -1.91433 0.0 5.554 -1.92075 0.0 5.53741 -1.92533 0.0 5.52109 -1.92808 0.0 5.505 -1.929 0.0 5.49123 -1.92764 0.0 5.47685 -1.92315 0.0 5.46325 -1.91488 0.0 5.45182 -1.90219 0.0 5.44394 -1.88444 0.0 5.441 -1.861 0.0 5.441 -1.631 0.0 5.583 -1.631 0.0 5.583 -1.551 0.0 5.441 -1.551 0.0 4.935 -1.579 0.0 4.91182 -1.56758 0.0 4.88922 -1.5583 0.0 4.86713 -1.55112 0.0 4.84544 -1.54604 0.0 4.8241 -1.543 0.0 4.803 -1.542 0.0 4.76079 -1.54576 0.0 4.72463 -1.55674 0.0 4.69525 -1.5745 0.0 4.67337 -1.59859 0.0 4.65971 -1.62857 0.0 4.655 -1.664 0.0 4.67056 -1.71771 0.0 4.70944 -1.76 0.0 4.76 -1.79412 0.0 4.81056 -1.82333 0.0 4.84944 -1.85087 0.0 4.865 -1.88 0.0 4.86261 -1.89475 0.0 4.85589 -1.907 0.0 4.8455 -1.91675 0.0 4.83211 -1.924 0.0 4.81639 -1.92875 0.0 4.799 -1.931 0.0 4.77964 -1.92941 0.0 4.75778 -1.92459 0.0 4.73375 -1.9165 0.0 4.70789 -1.90507 0.0 4.68053 -1.89026 0.0 4.652 -1.872 0.0 4.652 -1.968 0.0 4.67987 -1.98145 0.0 4.706 -1.99196 0.0 4.73112 -1.99975 0.0 4.756 -2.00504 0.0 4.78137 -2.00805 0.0 4.808 -2.009 0.0 4.84848 -2.00471 0.0 4.88415 -1.99233 0.0 4.91388 -1.97262 0.0 4.93652 -1.94633 0.0 4.95094 -1.91421 0.0 4.956 -1.877 0.0 4.95366 -1.8551 0.0 4.94626 -1.83478 0.0 4.93325 -1.81512 0.0 4.91407 -1.79522 0.0 4.88818 -1.77415 0.0 4.855 -1.751 0.0 4.8195 -1.72975 0.0 4.79163 -1.71167 0.0 4.77087 -1.69625 0.0 4.7567 -1.683 0.0 4.74859 -1.67142 0.0 4.746 -1.661 0.0 4.74787 -1.64963 0.0 4.7533 -1.6397 0.0 4.762 -1.6315 0.0 4.7737 -1.6253 0.0 4.78813 -1.62137 0.0 4.805 -1.62 0.0 4.82262 -1.62119 0.0 4.84226 -1.62485 0.0 4.86363 -1.63112 0.0 4.88641 -1.64015 0.0 4.9103 -1.65206 0.0 4.935 -1.667 0.0 4.611 -1.551 0.0 4.511 -1.551 0.0 4.395 -1.804 0.0 4.274 -1.551 0.0 4.173 -1.551 0.0 4.347 -1.904 0.0 4.194 -2.23 0.0 4.293 -2.23 0.0 4.132 -1.87 0.0 4.10606 -1.88581 0.0 4.08018 -1.89911 0.0 4.05425 -1.90975 0.0 4.02815 -1.91756 0.0 4.00177 -1.92236 0.0 3.975 -1.924 0.0 3.93493 -1.92018 0.0 3.90074 -1.90878 0.0 3.8725 -1.88988 0.0 3.85026 -1.86356 0.0 3.83407 -1.8299 0.0 3.824 -1.789 0.0 4.14 -1.789 0.0 4.13382 -1.71306 0.0 4.11589 -1.65119 0.0 4.08712 -1.60325 0.0 4.04844 -1.56915 0.0 4.00076 -1.54877 0.0 3.945 -1.542 0.0 3.88639 -1.54944 0.0 3.83544 -1.57089 0.0 3.7935 -1.605 0.0 3.76189 -1.65044 0.0 3.74194 -1.70589 0.0 3.735 -1.77 0.0 3.74143 -1.83076 0.0 3.76041 -1.88707 0.0 3.7915 -1.936 0.0 3.83426 -1.97459 0.0 3.88824 -1.99991 0.0 3.953 -2.009 0.0 3.9889 -2.00757 0.0 4.02118 -2.00326 0.0 4.05075 -1.996 0.0 4.07848 -1.98574 0.0 4.10527 -1.97243 0.0 4.132 -1.956 0.0 3.826 -1.73 0.0 3.83441 -1.69712 0.0 3.84759 -1.66967 0.0 3.8655 -1.64787 0.0 3.88807 -1.632 0.0 3.91526 -1.62229 0.0 3.947 -1.619 0.0 3.97644 -1.6225 0.0 4.00156 -1.63267 0.0 4.022 -1.649 0.0 4.03744 -1.671 0.0 4.04756 -1.69817 0.0 4.052 -1.73 0.0 3.675 -1.551 0.0 3.569 -1.551 0.0 3.37 -1.771 0.0 3.595 -2.0 0.0 3.715 -2.0 0.0 3.483 -1.771 0.0 3.366 -1.318 0.0 3.277 -1.318 0.0 3.277 -2.0 0.0 3.366 -2.0 0.0 2.61 -1.551 0.0 2.61 -2.0 0.0 2.699 -2.0 0.0 2.699 -1.765 0.0 2.70284 -1.72804 0.0 2.7137 -1.695 0.0 2.73062 -1.66712 0.0 2.75263 -1.64567 0.0 2.77875 -1.63187 0.0 2.808 -1.627 0.0 2.81956 -1.62845 0.0 2.83285 -1.63263 0.0 2.84725 -1.63925 0.0 2.86215 -1.64804 0.0 2.87694 -1.65871 0.0 2.891 -1.671 0.0 2.938 -1.594 0.0 2.91973 -1.578 0.0 2.90181 -1.56496 0.0 2.88412 -1.55487 0.0 2.86652 -1.5477 0.0 2.84886 -1.54342 0.0 2.831 -1.542 0.0 2.80991 -1.54481 0.0 2.78863 -1.55348 0.0 2.76712 -1.56837 0.0 2.74537 -1.58985 0.0 2.72334 -1.61827 0.0 2.701 -1.654 0.0 2.699 -1.654 0.0 2.699 -1.551 0.0 2.262 -1.542 0.0 2.19792 -1.55 0.0 2.141 -1.5727 0.0 2.09325 -1.60812 0.0 2.05667 -1.6543 0.0 2.03325 -1.70925 0.0 2.025 -1.771 0.0 2.03297 -1.83655 0.0 2.05578 -1.89404 0.0 2.09175 -1.94175 0.0 2.13922 -1.97796 0.0 2.19653 -2.00095 0.0 2.262 -2.009 0.0 2.33 -2.00123 0.0 2.389 -1.97885 0.0 2.4375 -1.94325 0.0 2.474 -1.89581 0.0 2.497 -1.83794 0.0 2.505 -1.771 0.0 2.49679 -1.70786 0.0 2.47333 -1.65252 0.0 2.43637 -1.60662 0.0 2.38767 -1.57181 0.0 2.32896 -1.54973 0.0 2.261 -1.622 0.0 2.30324 -1.62707 0.0 2.34022 -1.64156 0.0 2.37087 -1.66437 0.0 2.39411 -1.69444 0.0 2.40885 -1.73068 0.0 2.414 -1.772 0.0 2.40919 -1.81731 0.0 2.39522 -1.85581 0.0 2.37275 -1.88687 0.0 2.34244 -1.90985 0.0 2.30497 -1.92411 0.0 2.261 -1.929 0.0 2.2204 -1.92389 0.0 2.18519 -1.90915 0.0 2.15625 -1.88563 0.0 2.13448 -1.85419 0.0 2.12077 -1.81569 0.0 2.116 -1.771 0.0 2.12091 -1.7301 0.0 2.13493 -1.69415 0.0 2.157 -1.66425 0.0 2.18607 -1.64152 0.0 2.22109 -1.62706 0.0 1.928 -1.579 0.0 1.90482 -1.56758 0.0 1.88222 -1.5583 0.0 1.86013 -1.55112 0.0 1.83844 -1.54604 0.0 1.8171 -1.543 0.0 1.796 -1.542 0.0 1.75379 -1.54576 0.0 1.71763 -1.55674 0.0 1.68825 -1.5745 0.0 1.66637 -1.59859 0.0 1.65271 -1.62857 0.0 1.648 -1.664 0.0 1.66356 -1.71771 0.0 1.70244 -1.76 0.0 1.753 -1.79412 0.0 1.80356 -1.82333 0.0 1.84244 -1.85087 0.0 1.858 -1.88 0.0 1.85561 -1.89475 0.0 1.84889 -1.907 0.0 1.8385 -1.91675 0.0 1.82511 -1.924 0.0 1.80939 -1.92875 0.0 1.792 -1.931 0.0 1.77264 -1.92941 0.0 1.75078 -1.92459 0.0 1.72675 -1.9165 0.0 1.70089 -1.90507 0.0 1.67353 -1.89026 0.0 1.645 -1.872 0.0 1.645 -1.968 0.0 1.67287 -1.98145 0.0 1.699 -1.99196 0.0 1.72412 -1.99975 0.0 1.749 -2.00504 0.0 1.77437 -2.00805 0.0 1.801 -2.009 0.0 1.84148 -2.00471 0.0 1.87715 -1.99233 0.0 1.90687 -1.97262 0.0 1.92952 -1.94633 0.0 1.94394 -1.91421 0.0 1.949 -1.877 0.0 1.94666 -1.8551 0.0 1.93926 -1.83478 0.0 1.92625 -1.81512 0.0 1.90707 -1.79522 0.0 1.88118 -1.77415 0.0 1.848 -1.751 0.0 1.8125 -1.72975 0.0 1.78463 -1.71167 0.0 1.76387 -1.69625 0.0 1.7497 -1.683 0.0 1.74159 -1.67142 0.0 1.739 -1.661 0.0 1.74087 -1.64963 0.0 1.7463 -1.6397 0.0 1.755 -1.6315 0.0 1.7667 -1.6253 0.0 1.78113 -1.62137 0.0 1.798 -1.62 0.0 1.81562 -1.62119 0.0 1.83526 -1.62485 0.0 1.85663 -1.63112 0.0 1.87941 -1.64015 0.0 1.9033 -1.65206 0.0 1.928 -1.667 0.0 1.277 -1.551 0.0 1.277 -2.0 0.0 1.366 -2.0 0.0 1.366 -1.765 0.0 1.36984 -1.72804 0.0 1.3807 -1.695 0.0 1.39762 -1.66712 0.0 1.41963 -1.64567 0.0 1.44575 -1.63187 0.0 1.475 -1.627 0.0 1.48656 -1.62845 0.0 1.49985 -1.63263 0.0 1.51425 -1.63925 0.0 1.52915 -1.64804 0.0 1.54394 -1.65871 0.0 1.558 -1.671 0.0 1.605 -1.594 0.0 1.58673 -1.578 0.0 1.56881 -1.56496 0.0 1.55112 -1.55487 0.0 1.53352 -1.5477 0.0 1.51586 -1.54342 0.0 1.498 -1.542 0.0 1.47691 -1.54481 0.0 1.45563 -1.55348 0.0 1.43412 -1.56837 0.0 1.41237 -1.58985 0.0 1.39034 -1.61827 0.0 1.368 -1.654 0.0 1.366 -1.654 0.0 1.366 -1.551 0.0 1.145 -2.0 0.0 1.145 -1.551 0.0 1.056 -1.551 0.0 1.056 -1.872 0.0 1.04078 -1.8909 0.0 1.02426 -1.90656 0.0 1.00662 -1.91887 0.0 0.98807 -1.92778 0.0 0.9688 -1.93318 0.0 0.949 -1.935 0.0 0.921 -1.93204 0.0 0.89804 -1.92333 0.0 0.88013 -1.90912 0.0 0.8673 -1.88967 0.0 0.85958 -1.86521 0.0 0.857 -1.836 0.0 0.857 -1.551 0.0 0.768 -1.551 0.0 0.768 -1.83 0.0 0.77316 -1.88284 0.0 0.78796 -1.92707 0.0 0.81138 -1.96225 0.0 0.84237 -1.98793 0.0 0.87992 -2.00366 0.0 0.923 -2.009 0.0 0.94556 -2.00689 0.0 0.96881 -2.00078 0.0 0.99212 -1.991 0.0 1.01485 -1.97789 0.0 1.03636 -1.96178 0.0 1.056 -1.943 0.0 1.056 -2.0 0.0 0.656 -1.365 0.0 0.61124 -1.34731 0.0 0.56956 -1.33315 0.0 0.53038 -1.32237 0.0 0.49311 -1.31485 0.0 0.45718 -1.31044 0.0 0.422 -1.309 0.0 0.31895 -1.32122 0.0 0.22859 -1.35611 0.0 0.15363 -1.411 0.0 0.09674 -1.48322 0.0 0.06063 -1.57011 0.0 0.048 -1.669 0.0 0.05748 -1.74384 0.0 0.08652 -1.8207 0.0 0.136 -1.89263 0.0 0.20681 -1.95263 0.0 0.29985 -1.99375 0.0 0.416 -2.009 0.0 0.4668 -2.00699 0.0 0.5127 -2.00122 0.0 0.5545 -1.99212 0.0 0.59296 -1.98011 0.0 0.62887 -1.9656 0.0 0.663 -1.949 0.0 0.663 -1.842 0.0 0.62398 -1.86506 0.0 0.58419 -1.88419 0.0 0.544 -1.89925 0.0 0.50381 -1.91015 0.0 0.46402 -1.91677 0.0 0.425 -1.919 0.0 0.34761 -1.91044 0.0 0.28056 -1.88585 0.0 0.2255 -1.84687 0.0 0.18411 -1.79515 0.0 0.15806 -1.73231 0.0 0.149 -1.66 0.0 0.15831 -1.58858 0.0 0.18485 -1.52567 0.0 0.2265 -1.47325 0.0 0.28115 -1.43333 0.0 0.34669 -1.40792 0.0 0.421 -1.399 0.0 0.46 -1.40086 0.0 0.49837 -1.40652 0.0 0.53663 -1.41612 0.0 0.5753 -1.42981 0.0 0.61491 -1.44773 0.0 0.656 -1.47 0.0 14.542 -0.458 0.0 14.375 -0.621 0.0 14.375 -0.631 0.0 14.453 -0.631 0.0 14.453 -0.868 0.0 14.45708 -0.90657 0.0 14.4693 -0.94056 0.0 14.48962 -0.96887 0.0 14.51804 -0.99044 0.0 14.5545 -1.00418 0.0 14.599 -1.009 0.0 14.61492 -1.00796 0.0 14.633 -1.005 0.0 14.65225 -1.00038 0.0 14.67167 -0.99433 0.0 14.69025 -0.98713 0.0 14.707 -0.979 0.0 14.707 -0.896 0.0 14.68924 -0.90608 0.0 14.67193 -0.91433 0.0 14.655 -0.92075 0.0 14.63841 -0.92533 0.0 14.62209 -0.92808 0.0 14.606 -0.929 0.0 14.59223 -0.92764 0.0 14.57785 -0.92315 0.0 14.56425 -0.91487 0.0 14.55281 -0.90219 0.0 14.54494 -0.88444 0.0 14.542 -0.861 0.0 14.542 -0.631 0.0 14.684 -0.631 0.0 14.684 -0.551 0.0 14.542 -0.551 0.0 14.096 -0.542 0.0 14.03192 -0.55 0.0 13.975 -0.5727 0.0 13.92725 -0.60812 0.0 13.89067 -0.6543 0.0 13.86725 -0.70925 0.0 13.859 -0.771 0.0 13.86697 -0.83655 0.0 13.88978 -0.89404 0.0 13.92575 -0.94175 0.0 13.97322 -0.97796 0.0 14.03053 -1.00095 0.0 14.096 -1.009 0.0 14.164 -1.00123 0.0 14.223 -0.97885 0.0 14.2715 -0.94325 0.0 14.308 -0.89581 0.0 14.331 -0.83794 0.0 14.339 -0.771 0.0 14.33079 -0.70786 0.0 14.30733 -0.65252 0.0 14.27037 -0.60662 0.0 14.22167 -0.57181 0.0 14.16296 -0.54973 0.0 14.095 -0.622 0.0 14.13724 -0.62707 0.0 14.17422 -0.64156 0.0 14.20488 -0.66438 0.0 14.22811 -0.69444 0.0 14.24285 -0.73068 0.0 14.248 -0.772 0.0 14.24319 -0.81731 0.0 14.22922 -0.85581 0.0 14.20675 -0.88688 0.0 14.17644 -0.90985 0.0 14.13897 -0.92411 0.0 14.095 -0.929 0.0 14.0544 -0.92389 0.0 14.01919 -0.90915 0.0 13.99025 -0.88563 0.0 13.96848 -0.85419 0.0 13.95477 -0.81569 0.0 13.95 -0.771 0.0 13.95491 -0.7301 0.0 13.96893 -0.69415 0.0 13.991 -0.66425 0.0 14.02007 -0.64152 0.0 14.05509 -0.62706 0.0 13.473 -0.318 0.0 13.384 -0.318 0.0 13.384 -1.0 0.0 13.473 -1.0 0.0 13.473 -0.678 0.0 13.49317 -0.65687 0.0 13.51204 -0.64026 0.0 13.53012 -0.62788 0.0 13.54796 -0.61941 0.0 13.56608 -0.61455 0.0 13.585 -0.613 0.0 13.61027 -0.61649 0.0 13.63181 -0.62659 0.0 13.64925 -0.64275 0.0 13.66219 -0.66441 0.0 13.67023 -0.69101 0.0 13.673 -0.722 0.0 13.673 -1.0 0.0 13.762 -1.0 0.0 13.762 -0.725 0.0 13.75678 -0.66874 0.0 13.74189 -0.62289 0.0 13.7185 -0.58737 0.0 13.68778 -0.56211 0.0 13.65089 -0.54701 0.0 13.609 -0.542 0.0 13.58407 -0.54405 0.0 13.55959 -0.55007 0.0 13.536 -0.55987 0.0 13.51374 -0.57326 0.0 13.49326 -0.59003 0.0 13.475 -0.61 0.0 13.473 -0.61 0.0 13.262 -0.579 0.0 13.23882 -0.56758 0.0 13.21622 -0.5583 0.0 13.19412 -0.55112 0.0 13.17244 -0.54604 0.0 13.1511 -0.543 0.0 13.13 -0.542 0.0 13.08779 -0.54576 0.0 13.05163 -0.55674 0.0 13.02225 -0.5745 0.0 13.00037 -0.59859 0.0 12.98671 -0.62857 0.0 12.982 -0.664 0.0 12.99755 -0.71771 0.0 13.03644 -0.76 0.0 13.087 -0.79412 0.0 13.13755 -0.82333 0.0 13.17644 -0.85088 0.0 13.192 -0.88 0.0 13.18961 -0.89475 0.0 13.18289 -0.907 0.0 13.1725 -0.91675 0.0 13.15911 -0.924 0.0 13.14339 -0.92875 0.0 13.126 -0.931 0.0 13.10664 -0.92941 0.0 13.08478 -0.92459 0.0 13.06075 -0.9165 0.0 13.03489 -0.90507 0.0 13.00753 -0.89026 0.0 12.979 -0.872 0.0 12.979 -0.968 0.0 13.00688 -0.98145 0.0 13.033 -0.99196 0.0 13.05812 -0.99975 0.0 13.083 -1.00504 0.0 13.10837 -1.00805 0.0 13.135 -1.009 0.0 13.17548 -1.00471 0.0 13.21115 -0.99233 0.0 13.24087 -0.97262 0.0 13.26352 -0.94633 0.0 13.27794 -0.91421 0.0 13.283 -0.877 0.0 13.28066 -0.8551 0.0 13.27326 -0.83478 0.0 13.26025 -0.81512 0.0 13.24107 -0.79522 0.0 13.21518 -0.77415 0.0 13.182 -0.751 0.0 13.1465 -0.72975 0.0 13.11863 -0.71167 0.0 13.09788 -0.69625 0.0 13.0837 -0.683 0.0 13.07559 -0.67142 0.0 13.073 -0.661 0.0 13.07487 -0.64963 0.0 13.0803 -0.6397 0.0 13.089 -0.6315 0.0 13.1007 -0.6253 0.0 13.11513 -0.62137 0.0 13.132 -0.62 0.0 13.14962 -0.62119 0.0 13.16926 -0.62485 0.0 13.19063 -0.63113 0.0 13.21341 -0.64015 0.0 13.2373 -0.65206 0.0 13.262 -0.667 0.0 12.66 -0.551 0.0 12.56 -0.551 0.0 12.444 -0.804 0.0 12.323 -0.551 0.0 12.222 -0.551 0.0 12.396 -0.904 0.0 12.243 -1.23 0.0 12.342 -1.23 0.0 12.157 -0.318 0.0 12.068 -0.318 0.0 12.068 -1.0 0.0 12.157 -1.0 0.0 11.649 -0.989 0.0 11.66546 -0.99534 0.0 11.681 -1.00041 0.0 11.69588 -1.00425 0.0 11.71033 -1.00693 0.0 11.72463 -1.00849 0.0 11.739 -1.009 0.0 11.80207 -1.00134 0.0 11.85722 -0.97937 0.0 11.90287 -0.94462 0.0 11.93744 -0.89863 0.0 11.95935 -0.84291 0.0 11.967 -0.779 0.0 11.95965 -0.71072 0.0 11.93785 -0.65411 0.0 11.902 -0.6095 0.0 11.85248 -0.57722 0.0 11.78969 -0.55761 0.0 11.714 -0.551 0.0 11.56 -0.551 0.0 11.56 -1.23 0.0 11.649 -1.23 0.0 11.649 -0.631 0.0 11.73 -0.631 0.0 11.7745 -0.63543 0.0 11.81096 -0.64844 0.0 11.83938 -0.66962 0.0 11.8597 -0.69856 0.0 11.87192 -0.73482 0.0 11.876 -0.778 0.0 11.87117 -0.81939 0.0 11.85737 -0.85581 0.0 11.83563 -0.88613 0.0 11.80696 -0.90919 0.0 11.77241 -0.92386 0.0 11.733 -0.929 0.0 11.71893 -0.92842 0.0 11.70478 -0.9267 0.0 11.69063 -0.92387 0.0 11.67656 -0.91996 0.0 11.66265 -0.915 0.0 11.649 -0.909 0.0 11.149 -0.989 0.0 11.16546 -0.99534 0.0 11.181 -1.00041 0.0 11.19588 -1.00425 0.0 11.21033 -1.00693 0.0 11.22463 -1.00849 0.0 11.239 -1.009 0.0 11.30207 -1.00134 0.0 11.35722 -0.97937 0.0 11.40287 -0.94462 0.0 11.43744 -0.89863 0.0 11.45935 -0.84291 0.0 11.467 -0.779 0.0 11.45965 -0.71072 0.0 11.43785 -0.65411 0.0 11.402 -0.6095 0.0 11.35248 -0.57722 0.0 11.28969 -0.55761 0.0 11.214 -0.551 0.0 11.06 -0.551 0.0 11.06 -1.23 0.0 11.149 -1.23 0.0 11.149 -0.631 0.0 11.23 -0.631 0.0 11.2745 -0.63543 0.0 11.31096 -0.64844 0.0 11.33938 -0.66962 0.0 11.3597 -0.69856 0.0 11.37192 -0.73482 0.0 11.376 -0.778 0.0 11.37117 -0.81939 0.0 11.35737 -0.85581 0.0 11.33563 -0.88613 0.0 11.30696 -0.90919 0.0 11.27241 -0.92386 0.0 11.233 -0.929 0.0 11.21893 -0.92842 0.0 11.20478 -0.9267 0.0 11.19063 -0.92387 0.0 11.17656 -0.91996 0.0 11.16265 -0.915 0.0 11.149 -0.909 0.0 10.987 -0.92 0.0 10.9772 -0.92699 0.0 10.96793 -0.93289 0.0 10.95938 -0.93762 0.0 10.95174 -0.94111 0.0 10.94522 -0.94326 0.0 10.94 -0.944 0.0 10.93492 -0.94348 0.0 10.9307 -0.94181 0.0 10.92737 -0.93888 0.0 10.92496 -0.93452 0.0 10.9235 -0.92861 0.0 10.923 -0.921 0.0 10.923 -0.69 0.0 10.91725 -0.64362 0.0 10.90096 -0.6063 0.0 10.87563 -0.57775 0.0 10.8427 -0.5577 0.0 10.80367 -0.54588 0.0 10.76 -0.542 0.0 10.72882 -0.54367 0.0 10.70026 -0.5487 0.0 10.67425 -0.55712 0.0 10.65074 -0.56896 0.0 10.62968 -0.58425 0.0 10.611 -0.603 0.0 10.611 -0.7 0.0 10.63305 -0.67681 0.0 10.65604 -0.65815 0.0 10.67975 -0.64387 0.0 10.70396 -0.63385 0.0 10.72845 -0.62794 0.0 10.753 -0.626 0.0 10.77775 -0.62796 0.0 10.798 -0.63404 0.0 10.81375 -0.6445 0.0 10.825 -0.65963 0.0 10.83175 -0.6797 0.0 10.834 -0.705 0.0 10.834 -0.729 0.0 10.755 -0.757 0.0 10.71867 -0.77037 0.0 10.68333 -0.78559 0.0 10.6515 -0.80437 0.0 10.62567 -0.82841 0.0 10.60833 -0.85938 0.0 10.602 -0.899 0.0 10.60557 -0.92729 0.0 10.61585 -0.9533 0.0 10.63225 -0.97575 0.0 10.65415 -0.99337 0.0 10.68094 -1.00488 0.0 10.712 -1.009 0.0 10.73249 -1.00775 0.0 10.75293 -1.00396 0.0 10.77325 -0.99762 0.0 10.79341 -0.9887 0.0 10.81334 -0.97717 0.0 10.833 -0.963 0.0 10.83811 -0.97752 0.0 10.84552 -0.98915 0.0 10.85538 -0.998 0.0 10.86782 -1.00419 0.0 10.88298 -1.00781 0.0 10.901 -1.009 0.0 10.91425 -1.00828 0.0 10.92663 -1.00593 0.0 10.93913 -1.00162 0.0 10.9527 -0.99507 0.0 10.96834 -0.98597 0.0 10.987 -0.974 0.0 10.834 -0.909 0.0 10.82183 -0.91973 0.0 10.80933 -0.92881 0.0 10.7965 -0.93613 0.0 10.78333 -0.94152 0.0 10.76983 -0.94486 0.0 10.756 -0.946 0.0 10.73841 -0.9439 0.0 10.72296 -0.93789 0.0 10.71012 -0.92838 0.0 10.70037 -0.91578 0.0 10.69417 -0.90051 0.0 10.692 -0.883 0.0 10.69724 -0.85862 0.0 10.71193 -0.838 0.0 10.7345 -0.82038 0.0 10.76341 -0.805 0.0 10.79709 -0.79112 0.0 10.834 -0.778 0.0 10.019 -0.542 0.0 9.95492 -0.55 0.0 9.898 -0.5727 0.0 9.85025 -0.60812 0.0 9.81367 -0.6543 0.0 9.79025 -0.70925 0.0 9.782 -0.771 0.0 9.78997 -0.83655 0.0 9.81278 -0.89404 0.0 9.84875 -0.94175 0.0 9.89622 -0.97796 0.0 9.95353 -1.00095 0.0 10.019 -1.009 0.0 10.087 -1.00123 0.0 10.146 -0.97885 0.0 10.1945 -0.94325 0.0 10.231 -0.89581 0.0 10.254 -0.83794 0.0 10.262 -0.771 0.0 10.25379 -0.70786 0.0 10.23033 -0.65252 0.0 10.19337 -0.60662 0.0 10.14467 -0.57181 0.0 10.08596 -0.54973 0.0 10.018 -0.622 0.0 10.06024 -0.62707 0.0 10.09722 -0.64156 0.0 10.12788 -0.66438 0.0 10.15111 -0.69444 0.0 10.16585 -0.73068 0.0 10.171 -0.772 0.0 10.16619 -0.81731 0.0 10.15222 -0.85581 0.0 10.12975 -0.88688 0.0 10.09944 -0.90985 0.0 10.06197 -0.92411 0.0 10.018 -0.929 0.0 9.9774 -0.92389 0.0 9.94219 -0.90915 0.0 9.91325 -0.88563 0.0 9.89148 -0.85419 0.0 9.87777 -0.81569 0.0 9.873 -0.771 0.0 9.87791 -0.7301 0.0 9.89193 -0.69415 0.0 9.914 -0.66425 0.0 9.94307 -0.64152 0.0 9.97809 -0.62706 0.0 9.58 -0.458 0.0 9.413 -0.621 0.0 9.413 -0.631 0.0 9.491 -0.631 0.0 9.491 -0.868 0.0 9.49508 -0.90657 0.0 9.5073 -0.94056 0.0 9.52763 -0.96887 0.0 9.55604 -0.99044 0.0 9.5925 -1.00418 0.0 9.637 -1.009 0.0 9.65292 -1.00796 0.0 9.671 -1.005 0.0 9.69025 -1.00038 0.0 9.70967 -0.99433 0.0 9.72825 -0.98713 0.0 9.745 -0.979 0.0 9.745 -0.896 0.0 9.72724 -0.90608 0.0 9.70993 -0.91433 0.0 9.693 -0.92075 0.0 9.67641 -0.92533 0.0 9.66009 -0.92808 0.0 9.644 -0.929 0.0 9.63023 -0.92764 0.0 9.61585 -0.92315 0.0 9.60225 -0.91487 0.0 9.59081 -0.90219 0.0 9.58294 -0.88444 0.0 9.58 -0.861 0.0 9.58 -0.631 0.0 9.722 -0.631 0.0 9.722 -0.551 0.0 9.58 -0.551 0.0 9.094 -0.87 0.0 9.06806 -0.88581 0.0 9.04218 -0.89911 0.0 9.01625 -0.90975 0.0 8.99015 -0.91756 0.0 8.96377 -0.92236 0.0 8.937 -0.924 0.0 8.89693 -0.92018 0.0 8.86274 -0.90878 0.0 8.8345 -0.88987 0.0 8.81226 -0.86356 0.0 8.79607 -0.8299 0.0 8.786 -0.789 0.0 9.102 -0.789 0.0 9.09582 -0.71306 0.0 9.07789 -0.65119 0.0 9.04912 -0.60325 0.0 9.01044 -0.56915 0.0 8.96276 -0.54877 0.0 8.907 -0.542 0.0 8.84839 -0.54944 0.0 8.79745 -0.57089 0.0 8.7555 -0.605 0.0 8.72389 -0.65044 0.0 8.70395 -0.70589 0.0 8.697 -0.77 0.0 8.70343 -0.83076 0.0 8.72241 -0.88707 0.0 8.7535 -0.936 0.0 8.79626 -0.97459 0.0 8.85024 -0.99991 0.0 8.915 -1.009 0.0 8.9509 -1.00757 0.0 8.98318 -1.00326 0.0 9.01275 -0.996 0.0 9.04048 -0.98574 0.0 9.06727 -0.97243 0.0 9.094 -0.956 0.0 8.788 -0.73 0.0 8.79641 -0.69713 0.0 8.80959 -0.66967 0.0 8.8275 -0.64787 0.0 8.85007 -0.632 0.0 8.87726 -0.62229 0.0 8.909 -0.619 0.0 8.93845 -0.6225 0.0 8.96356 -0.63267 0.0 8.984 -0.649 0.0 8.99944 -0.671 0.0 9.00956 -0.69817 0.0 9.014 -0.73 0.0 8.595 -0.579 0.0 8.57182 -0.56758 0.0 8.54922 -0.5583 0.0 8.52712 -0.55112 0.0 8.50544 -0.54604 0.0 8.4841 -0.543 0.0 8.463 -0.542 0.0 8.42079 -0.54576 0.0 8.38463 -0.55674 0.0 8.35525 -0.5745 0.0 8.33337 -0.59859 0.0 8.31971 -0.62857 0.0 8.315 -0.664 0.0 8.33055 -0.71771 0.0 8.36944 -0.76 0.0 8.42 -0.79412 0.0 8.47055 -0.82333 0.0 8.50944 -0.85088 0.0 8.525 -0.88 0.0 8.52261 -0.89475 0.0 8.51589 -0.907 0.0 8.5055 -0.91675 0.0 8.49211 -0.924 0.0 8.47639 -0.92875 0.0 8.459 -0.931 0.0 8.43964 -0.92941 0.0 8.41778 -0.92459 0.0 8.39375 -0.9165 0.0 8.36789 -0.90507 0.0 8.34053 -0.89026 0.0 8.312 -0.872 0.0 8.312 -0.968 0.0 8.33988 -0.98145 0.0 8.366 -0.99196 0.0 8.39112 -0.99975 0.0 8.416 -1.00504 0.0 8.44137 -1.00805 0.0 8.468 -1.009 0.0 8.50848 -1.00471 0.0 8.54415 -0.99233 0.0 8.57387 -0.97262 0.0 8.59652 -0.94633 0.0 8.61094 -0.91421 0.0 8.616 -0.877 0.0 8.61366 -0.8551 0.0 8.60626 -0.83478 0.0 8.59325 -0.81512 0.0 8.57407 -0.79522 0.0 8.54818 -0.77415 0.0 8.515 -0.751 0.0 8.4795 -0.72975 0.0 8.45163 -0.71167 0.0 8.43088 -0.69625 0.0 8.4167 -0.683 0.0 8.40859 -0.67142 0.0 8.406 -0.661 0.0 8.40787 -0.64963 0.0 8.4133 -0.6397 0.0 8.422 -0.6315 0.0 8.4337 -0.6253 0.0 8.44813 -0.62137 0.0 8.465 -0.62 0.0 8.48262 -0.62119 0.0 8.50226 -0.62485 0.0 8.52363 -0.63113 0.0 8.54641 -0.64015 0.0 8.5703 -0.65206 0.0 8.595 -0.667 0.0 8.208 -1.0 0.0 8.208 -0.551 0.0 8.119 -0.551 0.0 8.119 -0.872 0.0 8.10378 -0.8909 0.0 8.08726 -0.90656 0.0 8.06962 -0.91887 0.0 8.05107 -0.92778 0.0 8.0318 -0.93318 0.0 8.012 -0.935 0.0 7.984 -0.93204 0.0 7.96104 -0.92333 0.0 7.94313 -0.90912 0.0 7.9303 -0.88967 0.0 7.92258 -0.86521 0.0 7.92 -0.836 0.0 7.92 -0.551 0.0 7.831 -0.551 0.0 7.831 -0.83 0.0 7.83616 -0.88284 0.0 7.85096 -0.92707 0.0 7.87438 -0.96225 0.0 7.90537 -0.98793 0.0 7.94292 -1.00366 0.0 7.986 -1.009 0.0 8.00856 -1.00689 0.0 8.03182 -1.00078 0.0 8.05513 -0.991 0.0 8.07785 -0.97789 0.0 8.09936 -0.96178 0.0 8.119 -0.943 0.0 8.119 -1.0 0.0 7.492 -0.542 0.0 7.42792 -0.55 0.0 7.371 -0.5727 0.0 7.32325 -0.60812 0.0 7.28667 -0.6543 0.0 7.26325 -0.70925 0.0 7.255 -0.771 0.0 7.26297 -0.83655 0.0 7.28578 -0.89404 0.0 7.32175 -0.94175 0.0 7.36922 -0.97796 0.0 7.42653 -1.00095 0.0 7.492 -1.009 0.0 7.56 -1.00123 0.0 7.619 -0.97885 0.0 7.6675 -0.94325 0.0 7.704 -0.89581 0.0 7.727 -0.83794 0.0 7.735 -0.771 0.0 7.72679 -0.70786 0.0 7.70333 -0.65252 0.0 7.66638 -0.60662 0.0 7.61767 -0.57181 0.0 7.55896 -0.54973 0.0 7.491 -0.622 0.0 7.53324 -0.62707 0.0 7.57022 -0.64156 0.0 7.60088 -0.66438 0.0 7.62411 -0.69444 0.0 7.63885 -0.73068 0.0 7.644 -0.772 0.0 7.63919 -0.81731 0.0 7.62522 -0.85581 0.0 7.60275 -0.88688 0.0 7.57244 -0.90985 0.0 7.53497 -0.92411 0.0 7.491 -0.929 0.0 7.4504 -0.92389 0.0 7.41519 -0.90915 0.0 7.38625 -0.88563 0.0 7.36448 -0.85419 0.0 7.35077 -0.81569 0.0 7.346 -0.771 0.0 7.35091 -0.7301 0.0 7.36493 -0.69415 0.0 7.387 -0.66425 0.0 7.41607 -0.64152 0.0 7.45109 -0.62706 0.0 6.507 -0.551 0.0 6.507 -1.0 0.0 6.596 -1.0 0.0 6.596 -0.674 0.0 6.61402 -0.65485 0.0 6.63148 -0.64011 0.0 6.649 -0.62937 0.0 6.66719 -0.62222 0.0 6.68665 -0.61824 0.0 6.708 -0.617 0.0 6.72928 -0.61963 0.0 6.74856 -0.62774 0.0 6.765 -0.64162 0.0 6.77778 -0.66159 0.0 6.78606 -0.68795 0.0 6.789 -0.721 0.0 6.789 -1.0 0.0 6.878 -1.0 0.0 6.878 -0.674 0.0 6.89451 -0.65825 0.0 6.9117 -0.64433 0.0 6.92913 -0.63275 0.0 6.9463 -0.624 0.0 6.96275 -0.61858 0.0 6.978 -0.617 0.0 7.0026 -0.62006 0.0 7.02478 -0.62911 0.0 7.04363 -0.644 0.0 7.05822 -0.66456 0.0 7.06765 -0.69061 0.0 7.071 -0.722 0.0 7.071 -1.0 0.0 7.16 -1.0 0.0 7.16 -0.718 0.0 7.15528 -0.66816 0.0 7.14159 -0.62526 0.0 7.11963 -0.59025 0.0 7.09007 -0.56407 0.0 7.05363 -0.54768 0.0 7.011 -0.542 0.0 6.98038 -0.54494 0.0 6.95233 -0.55322 0.0 6.92663 -0.566 0.0 6.903 -0.58244 0.0 6.88121 -0.60172 0.0 6.861 -0.623 0.0 6.84462 -0.5986 0.0 6.82559 -0.57844 0.0 6.80413 -0.56262 0.0 6.78041 -0.55122 0.0 6.75463 -0.54432 0.0 6.727 -0.542 0.0 6.70591 -0.54384 0.0 6.68459 -0.54941 0.0 6.663 -0.55875 0.0 6.64107 -0.57193 0.0 6.61876 -0.58899 0.0 6.596 -0.61 0.0 6.596 -0.551 0.0 6.004 -0.458 0.0 5.837 -0.621 0.0 5.837 -0.631 0.0 5.915 -0.631 0.0 5.915 -0.868 0.0 5.91908 -0.90657 0.0 5.9313 -0.94056 0.0 5.95163 -0.96887 0.0 5.98004 -0.99044 0.0 6.0165 -1.00418 0.0 6.061 -1.009 0.0 6.07692 -1.00796 0.0 6.095 -1.005 0.0 6.11425 -1.00038 0.0 6.13367 -0.99433 0.0 6.15225 -0.98713 0.0 6.169 -0.979 0.0 6.169 -0.896 0.0 6.15124 -0.90608 0.0 6.13393 -0.91433 0.0 6.117 -0.92075 0.0 6.10041 -0.92533 0.0 6.08409 -0.92808 0.0 6.068 -0.929 0.0 6.05423 -0.92764 0.0 6.03985 -0.92315 0.0 6.02625 -0.91487 0.0 6.01482 -0.90219 0.0 6.00694 -0.88444 0.0 6.004 -0.861 0.0 6.004 -0.631 0.0 6.146 -0.631 0.0 6.146 -0.551 0.0 6.004 -0.551 0.0 5.883 -0.318 0.0 5.84619 -0.31024 0.0 5.81348 -0.30859 0.0 5.7845 -0.3125 0.0 5.75885 -0.32141 0.0 5.73615 -0.33476 0.0 5.716 -0.352 0.0 5.69928 -0.37069 0.0 5.68522 -0.39148 0.0 5.674 -0.4155 0.0 5.66578 -0.44385 0.0 5.66072 -0.47765 0.0 5.659 -0.518 0.0 5.659 -0.551 0.0 5.596 -0.551 0.0 5.596 -0.631 0.0 5.659 -0.631 0.0 5.659 -1.0 0.0 5.748 -1.0 0.0 5.748 -0.631 0.0 5.829 -0.631 0.0 5.829 -0.551 0.0 5.748 -0.551 0.0 5.748 -0.508 0.0 5.75004 -0.47582 0.0 5.75663 -0.44856 0.0 5.7685 -0.42662 0.0 5.78637 -0.41044 0.0 5.81096 -0.40043 0.0 5.843 -0.397 0.0 5.85048 -0.39718 0.0 5.85715 -0.39774 0.0 5.86338 -0.39875 0.0 5.86952 -0.40026 0.0 5.87594 -0.40232 0.0 5.883 -0.405 0.0 5.546 -0.87 0.0 5.52007 -0.88581 0.0 5.49419 -0.89911 0.0 5.46825 -0.90975 0.0 5.44215 -0.91756 0.0 5.41577 -0.92236 0.0 5.389 -0.924 0.0 5.34893 -0.92018 0.0 5.31474 -0.90878 0.0 5.2865 -0.88987 0.0 5.26426 -0.86356 0.0 5.24807 -0.8299 0.0 5.238 -0.789 0.0 5.554 -0.789 0.0 5.54782 -0.71306 0.0 5.52989 -0.65119 0.0 5.50113 -0.60325 0.0 5.46244 -0.56915 0.0 5.41476 -0.54877 0.0 5.359 -0.542 0.0 5.30039 -0.54944 0.0 5.24944 -0.57089 0.0 5.2075 -0.605 0.0 5.17589 -0.65044 0.0 5.15594 -0.70589 0.0 5.149 -0.77 0.0 5.15543 -0.83076 0.0 5.17441 -0.88707 0.0 5.2055 -0.936 0.0 5.24826 -0.97459 0.0 5.30224 -0.99991 0.0 5.367 -1.009 0.0 5.4029 -1.00757 0.0 5.43519 -1.00326 0.0 5.46475 -0.996 0.0 5.49248 -0.98574 0.0 5.51927 -0.97243 0.0 5.546 -0.956 0.0 5.24 -0.73 0.0 5.24841 -0.69713 0.0 5.26159 -0.66967 0.0 5.2795 -0.64787 0.0 5.30207 -0.632 0.0 5.32926 -0.62229 0.0 5.361 -0.619 0.0 5.39044 -0.6225 0.0 5.41556 -0.63267 0.0 5.436 -0.649 0.0 5.45144 -0.671 0.0 5.46156 -0.69817 0.0 5.466 -0.73 0.0 5.043 -0.318 0.0 4.954 -0.318 0.0 4.954 -1.0 0.0 5.043 -1.0 0.0 4.451 -1.118 0.0 4.4871 -1.10365 0.0 4.51645 -1.08356 0.0 4.53913 -1.05913 0.0 4.55522 -1.03178 0.0 4.56482 -1.00293 0.0 4.568 -0.974 0.0 4.56573 -0.94633 0.0 4.55915 -0.92263 0.0 4.54863 -0.90338 0.0 4.53452 -0.88904 0.0 4.51719 -0.88009 0.0 4.497 -0.877 0.0 4.48082 -0.87893 0.0 4.46659 -0.88444 0.0 4.45475 -0.89312 0.0 4.44574 -0.90456 0.0 4.44001 -0.91832 0.0 4.438 -0.934 0.0 4.43962 -0.94954 0.0 4.44426 -0.96296 0.0 4.45163 -0.974 0.0 4.46141 -0.98237 0.0 4.4733 -0.9878 0.0 4.487 -0.99 0.0 4.48975 -1.00905 0.0 4.489 -1.02937 0.0 4.48475 -1.04975 0.0 4.477 -1.06896 0.0 4.46575 -1.08579 0.0 4.451 -1.099 0.0 3.68 -0.551 0.0 3.68 -1.0 0.0 3.769 -1.0 0.0 3.769 -0.674 0.0 3.78702 -0.65485 0.0 3.80448 -0.64011 0.0 3.822 -0.62937 0.0 3.84019 -0.62222 0.0 3.85965 -0.61824 0.0 3.881 -0.617 0.0 3.90228 -0.61963 0.0 3.92156 -0.62774 0.0 3.938 -0.64162 0.0 3.95078 -0.66159 0.0 3.95906 -0.68795 0.0 3.962 -0.721 0.0 3.962 -1.0 0.0 4.051 -1.0 0.0 4.051 -0.674 0.0 4.06751 -0.65825 0.0 4.0847 -0.64433 0.0 4.10213 -0.63275 0.0 4.1193 -0.624 0.0 4.13575 -0.61858 0.0 4.151 -0.617 0.0 4.1756 -0.62006 0.0 4.19778 -0.62911 0.0 4.21663 -0.644 0.0 4.23122 -0.66456 0.0 4.24065 -0.69061 0.0 4.244 -0.722 0.0 4.244 -1.0 0.0 4.333 -1.0 0.0 4.333 -0.718 0.0 4.32828 -0.66816 0.0 4.31459 -0.62526 0.0 4.29263 -0.59025 0.0 4.26307 -0.56407 0.0 4.22663 -0.54768 0.0 4.184 -0.542 0.0 4.15338 -0.54494 0.0 4.12533 -0.55322 0.0 4.09963 -0.566 0.0 4.076 -0.58244 0.0 4.05421 -0.60172 0.0 4.034 -0.623 0.0 4.01762 -0.5986 0.0 3.99859 -0.57844 0.0 3.97713 -0.56262 0.0 3.95341 -0.55122 0.0 3.92763 -0.54432 0.0 3.9 -0.542 0.0 3.87891 -0.54384 0.0 3.85759 -0.54941 0.0 3.836 -0.55875 0.0 3.81407 -0.57193 0.0 3.79176 -0.58899 0.0 3.769 -0.61 0.0 3.769 -0.551 0.0 3.556 -0.551 0.0 3.467 -0.551 0.0 3.467 -1.0 0.0 3.556 -1.0 0.0 3.565 -0.415 0.0 3.56309 -0.401 0.0 3.5577 -0.38837 0.0 3.54938 -0.37762 0.0 3.53863 -0.3693 0.0 3.526 -0.36391 0.0 3.512 -0.362 0.0 3.498 -0.36391 0.0 3.48537 -0.3693 0.0 3.47463 -0.37762 0.0 3.4663 -0.38837 0.0 3.46091 -0.401 0.0 3.459 -0.415 0.0 3.46091 -0.429 0.0 3.4663 -0.44163 0.0 3.47463 -0.45237 0.0 3.48537 -0.4607 0.0 3.498 -0.46609 0.0 3.512 -0.468 0.0 3.526 -0.46609 0.0 3.53863 -0.4607 0.0 3.54938 -0.45237 0.0 3.5577 -0.44163 0.0 3.56309 -0.429 0.0 3.386 -0.92 0.0 3.3762 -0.92699 0.0 3.36693 -0.93289 0.0 3.35838 -0.93762 0.0 3.35074 -0.94111 0.0 3.34422 -0.94326 0.0 3.339 -0.944 0.0 3.33392 -0.94348 0.0 3.3297 -0.94181 0.0 3.32638 -0.93888 0.0 3.32396 -0.93452 0.0 3.3225 -0.92861 0.0 3.322 -0.921 0.0 3.322 -0.69 0.0 3.31625 -0.64362 0.0 3.29996 -0.6063 0.0 3.27463 -0.57775 0.0 3.2417 -0.5577 0.0 3.20267 -0.54588 0.0 3.159 -0.542 0.0 3.12782 -0.54367 0.0 3.09926 -0.5487 0.0 3.07325 -0.55712 0.0 3.04974 -0.56896 0.0 3.02868 -0.58425 0.0 3.01 -0.603 0.0 3.01 -0.7 0.0 3.03205 -0.67681 0.0 3.05504 -0.65815 0.0 3.07875 -0.64387 0.0 3.10296 -0.63385 0.0 3.12745 -0.62794 0.0 3.152 -0.626 0.0 3.17675 -0.62796 0.0 3.197 -0.63404 0.0 3.21275 -0.6445 0.0 3.224 -0.65963 0.0 3.23075 -0.6797 0.0 3.233 -0.705 0.0 3.233 -0.729 0.0 3.154 -0.757 0.0 3.11767 -0.77037 0.0 3.08233 -0.78559 0.0 3.0505 -0.80437 0.0 3.02467 -0.82841 0.0 3.00733 -0.85938 0.0 3.001 -0.899 0.0 3.00457 -0.92729 0.0 3.01485 -0.9533 0.0 3.03125 -0.97575 0.0 3.05315 -0.99337 0.0 3.07994 -1.00488 0.0 3.111 -1.009 0.0 3.13149 -1.00775 0.0 3.15193 -1.00396 0.0 3.17225 -0.99762 0.0 3.19241 -0.9887 0.0 3.21234 -0.97717 0.0 3.232 -0.963 0.0 3.23711 -0.97752 0.0 3.24452 -0.98915 0.0 3.25438 -0.998 0.0 3.26681 -1.00419 0.0 3.28198 -1.00781 0.0 3.3 -1.009 0.0 3.31325 -1.00828 0.0 3.32563 -1.00593 0.0 3.33813 -1.00162 0.0 3.3517 -0.99507 0.0 3.36734 -0.98597 0.0 3.386 -0.974 0.0 3.233 -0.909 0.0 3.22083 -0.91973 0.0 3.20833 -0.92881 0.0 3.1955 -0.93613 0.0 3.18233 -0.94152 0.0 3.16883 -0.94486 0.0 3.155 -0.946 0.0 3.13741 -0.9439 0.0 3.12196 -0.93789 0.0 3.10913 -0.92838 0.0 3.09937 -0.91578 0.0 3.09317 -0.90051 0.0 3.091 -0.883 0.0 3.09624 -0.85862 0.0 3.11093 -0.838 0.0 3.1335 -0.82038 0.0 3.16241 -0.805 0.0 3.19609 -0.79112 0.0 3.233 -0.778 0.0 2.656 -0.87 0.0 2.63006 -0.88581 0.0 2.60419 -0.89911 0.0 2.57825 -0.90975 0.0 2.55215 -0.91756 0.0 2.52577 -0.92236 0.0 2.499 -0.924 0.0 2.45893 -0.92018 0.0 2.42474 -0.90878 0.0 2.3965 -0.88987 0.0 2.37426 -0.86356 0.0 2.35807 -0.8299 0.0 2.348 -0.789 0.0 2.664 -0.789 0.0 2.65782 -0.71306 0.0 2.63989 -0.65119 0.0 2.61113 -0.60325 0.0 2.57244 -0.56915 0.0 2.52476 -0.54877 0.0 2.469 -0.542 0.0 2.41039 -0.54944 0.0 2.35944 -0.57089 0.0 2.3175 -0.605 0.0 2.28589 -0.65044 0.0 2.26594 -0.70589 0.0 2.259 -0.77 0.0 2.26543 -0.83076 0.0 2.28441 -0.88707 0.0 2.3155 -0.936 0.0 2.35826 -0.97459 0.0 2.41224 -0.99991 0.0 2.477 -1.009 0.0 2.5129 -1.00757 0.0 2.54519 -1.00326 0.0 2.57475 -0.996 0.0 2.60248 -0.98574 0.0 2.62927 -0.97243 0.0 2.656 -0.956 0.0 2.35 -0.73 0.0 2.35841 -0.69713 0.0 2.37159 -0.66967 0.0 2.3895 -0.64787 0.0 2.41207 -0.632 0.0 2.43926 -0.62229 0.0 2.471 -0.619 0.0 2.50044 -0.6225 0.0 2.52556 -0.63267 0.0 2.546 -0.649 0.0 2.56144 -0.671 0.0 2.57156 -0.69817 0.0 2.576 -0.73 0.0 2.157 -0.579 0.0 2.13382 -0.56758 0.0 2.11122 -0.5583 0.0 2.08913 -0.55112 0.0 2.06744 -0.54604 0.0 2.0461 -0.543 0.0 2.025 -0.542 0.0 1.98279 -0.54576 0.0 1.94663 -0.55674 0.0 1.91725 -0.5745 0.0 1.89537 -0.59859 0.0 1.88171 -0.62857 0.0 1.877 -0.664 0.0 1.89256 -0.71771 0.0 1.93144 -0.76 0.0 1.982 -0.79412 0.0 2.03256 -0.82333 0.0 2.07144 -0.85088 0.0 2.087 -0.88 0.0 2.08461 -0.89475 0.0 2.07789 -0.907 0.0 2.0675 -0.91675 0.0 2.05411 -0.924 0.0 2.03839 -0.92875 0.0 2.021 -0.931 0.0 2.00164 -0.92941 0.0 1.97978 -0.92459 0.0 1.95575 -0.9165 0.0 1.92989 -0.90507 0.0 1.90253 -0.89026 0.0 1.874 -0.872 0.0 1.874 -0.968 0.0 1.90188 -0.98145 0.0 1.928 -0.99196 0.0 1.95313 -0.99975 0.0 1.978 -1.00504 0.0 2.00337 -1.00805 0.0 2.03 -1.009 0.0 2.07048 -1.00471 0.0 2.10615 -0.99233 0.0 2.13587 -0.97262 0.0 2.15852 -0.94633 0.0 2.17294 -0.91421 0.0 2.178 -0.877 0.0 2.17566 -0.8551 0.0 2.16826 -0.83478 0.0 2.15525 -0.81512 0.0 2.13607 -0.79522 0.0 2.11018 -0.77415 0.0 2.077 -0.751 0.0 2.0415 -0.72975 0.0 2.01363 -0.71167 0.0 1.99288 -0.69625 0.0 1.9787 -0.683 0.0 1.97059 -0.67142 0.0 1.968 -0.661 0.0 1.96987 -0.64963 0.0 1.9753 -0.6397 0.0 1.984 -0.6315 0.0 1.9957 -0.6253 0.0 2.01013 -0.62137 0.0 2.027 -0.62 0.0 2.04462 -0.62119 0.0 2.06426 -0.62485 0.0 2.08562 -0.63113 0.0 2.10841 -0.64015 0.0 2.1323 -0.65206 0.0 2.157 -0.667 0.0 1.77 -1.0 0.0 1.77 -0.551 0.0 1.681 -0.551 0.0 1.681 -0.872 0.0 1.66578 -0.8909 0.0 1.64926 -0.90656 0.0 1.63163 -0.91887 0.0 1.61307 -0.92778 0.0 1.5938 -0.93318 0.0 1.574 -0.935 0.0 1.546 -0.93204 0.0 1.52304 -0.92333 0.0 1.50513 -0.90912 0.0 1.4923 -0.88967 0.0 1.48458 -0.86521 0.0 1.482 -0.836 0.0 1.482 -0.551 0.0 1.393 -0.551 0.0 1.393 -0.83 0.0 1.39816 -0.88284 0.0 1.41296 -0.92707 0.0 1.43638 -0.96225 0.0 1.46737 -0.98793 0.0 1.50492 -1.00366 0.0 1.548 -1.009 0.0 1.57056 -1.00689 0.0 1.59381 -1.00078 0.0 1.61713 -0.991 0.0 1.63985 -0.97789 0.0 1.66136 -0.96178 0.0 1.681 -0.943 0.0 1.681 -1.0 0.0 1.054 -0.542 0.0 0.98992 -0.55 0.0 0.933 -0.5727 0.0 0.88525 -0.60812 0.0 0.84867 -0.6543 0.0 0.82525 -0.70925 0.0 0.817 -0.771 0.0 0.82497 -0.83655 0.0 0.84778 -0.89404 0.0 0.88375 -0.94175 0.0 0.93122 -0.97796 0.0 0.98853 -1.00095 0.0 1.054 -1.009 0.0 1.122 -1.00123 0.0 1.181 -0.97885 0.0 1.2295 -0.94325 0.0 1.266 -0.89581 0.0 1.289 -0.83794 0.0 1.297 -0.771 0.0 1.28879 -0.70786 0.0 1.26533 -0.65252 0.0 1.22838 -0.60662 0.0 1.17967 -0.57181 0.0 1.12096 -0.54973 0.0 1.053 -0.622 0.0 1.09524 -0.62707 0.0 1.13222 -0.64156 0.0 1.16288 -0.66438 0.0 1.18611 -0.69444 0.0 1.20085 -0.73068 0.0 1.206 -0.772 0.0 1.20119 -0.81731 0.0 1.18722 -0.85581 0.0 1.16475 -0.88688 0.0 1.13444 -0.90985 0.0 1.09697 -0.92411 0.0 1.053 -0.929 0.0 1.0124 -0.92389 0.0 0.97719 -0.90915 0.0 0.94825 -0.88563 0.0 0.92648 -0.85419 0.0 0.91277 -0.81569 0.0 0.908 -0.771 0.0 0.91291 -0.7301 0.0 0.92693 -0.69415 0.0 0.949 -0.66425 0.0 0.97807 -0.64152 0.0 1.01309 -0.62706 0.0 0.709 -0.318 0.0 0.618 -0.318 0.0 0.391 -0.598 0.0 0.165 -0.318 0.0 0.073 -0.318 0.0 0.073 -1.0 0.0 0.171 -1.0 0.0 0.171 -0.469 0.0 0.173 -0.469 0.0 0.383 -0.733 0.0 0.399 -0.733 0.0 0.609 -0.469 0.0 0.611 -0.469 0.0 0.611 -1.0 0.0 0.709 -1.0 0.0 7.379 0.542 0.0 7.212 0.379 0.0 7.212 0.369 0.0 7.29 0.369 0.0 7.29 0.132 0.0 7.29408 0.09343 0.0 7.3063 0.05944 0.0 7.32663 0.03112 0.0 7.35504 0.00956 0.0 7.39151 -0.00418 0.0 7.436 -0.009 0.0 7.45192 -0.00796 0.0 7.47 -0.005 0.0 7.48925 -0.00038 0.0 7.50867 0.00567 0.0 7.52725 0.01288 0.0 7.544 0.021 0.0 7.544 0.104 0.0 7.52624 0.09392 0.0 7.50893 0.08567 0.0 7.492 0.07925 0.0 7.47541 0.07467 0.0 7.45909 0.07192 0.0 7.443 0.071 0.0 7.42923 0.07236 0.0 7.41485 0.07685 0.0 7.40125 0.08513 0.0 7.38982 0.09781 0.0 7.38194 0.11556 0.0 7.379 0.139 0.0 7.379 0.369 0.0 7.521 0.369 0.0 7.521 0.449 0.0 7.379 0.449 0.0 7.151 0.421 0.0 7.12782 0.43242 0.0 7.10522 0.4417 0.0 7.08313 0.44888 0.0 7.06145 0.45396 0.0 7.0401 0.457 0.0 7.019 0.458 0.0 6.97679 0.45424 0.0 6.94063 0.44326 0.0 6.91125 0.4255 0.0 6.88937 0.40141 0.0 6.87571 0.37143 0.0 6.871 0.336 0.0 6.88656 0.28229 0.0 6.92545 0.24 0.0 6.976 0.20588 0.0 7.02656 0.17667 0.0 7.06545 0.14913 0.0 7.081 0.12 0.0 7.07861 0.10525 0.0 7.07189 0.093 0.0 7.0615 0.08325 0.0 7.04811 0.076 0.0 7.03239 0.07125 0.0 7.015 0.069 0.0 6.99564 0.07059 0.0 6.97378 0.07541 0.0 6.94975 0.0835 0.0 6.92389 0.09493 0.0 6.89653 0.10974 0.0 6.868 0.128 0.0 6.868 0.032 0.0 6.89588 0.01855 0.0 6.922 0.00804 0.0 6.94713 0.00025 0.0 6.972 -0.00504 0.0 6.99738 -0.00805 0.0 7.024 -0.009 0.0 7.06448 -0.00471 0.0 7.10015 0.00767 0.0 7.12988 0.02737 0.0 7.15252 0.05367 0.0 7.16694 0.08579 0.0 7.172 0.123 0.0 7.16966 0.1449 0.0 7.16226 0.16522 0.0 7.14925 0.18488 0.0 7.13007 0.20478 0.0 7.10418 0.22585 0.0 7.071 0.249 0.0 7.0355 0.27025 0.0 7.00763 0.28833 0.0 6.98688 0.30375 0.0 6.9727 0.317 0.0 6.96459 0.32858 0.0 6.962 0.339 0.0 6.96387 0.35037 0.0 6.9693 0.3603 0.0 6.978 0.3685 0.0 6.9897 0.3747 0.0 7.00413 0.37863 0.0 7.021 0.38 0.0 7.03862 0.37881 0.0 7.05826 0.37515 0.0 7.07963 0.36887 0.0 7.10241 0.35985 0.0 7.1263 0.34794 0.0 7.151 0.333 0.0 6.786 0.13 0.0 6.76007 0.11419 0.0 6.73419 0.10089 0.0 6.70825 0.09025 0.0 6.68215 0.08244 0.0 6.65577 0.07764 0.0 6.629 0.076 0.0 6.58893 0.07982 0.0 6.55474 0.09122 0.0 6.5265 0.11013 0.0 6.50426 0.13644 0.0 6.48807 0.1701 0.0 6.478 0.211 0.0 6.794 0.211 0.0 6.78782 0.28694 0.0 6.76989 0.34881 0.0 6.74113 0.39675 0.0 6.70245 0.43085 0.0 6.65476 0.45123 0.0 6.599 0.458 0.0 6.54039 0.45056 0.0 6.48945 0.42911 0.0 6.4475 0.395 0.0 6.41589 0.34956 0.0 6.39595 0.29411 0.0 6.389 0.23 0.0 6.39543 0.16924 0.0 6.41441 0.11293 0.0 6.4455 0.064 0.0 6.48826 0.02541 0.0 6.54224 9e-05 0.0 6.607 -0.009 0.0 6.6429 -0.00757 0.0 6.67519 -0.00326 0.0 6.70475 0.004 0.0 6.73248 0.01426 0.0 6.75927 0.02757 0.0 6.786 0.044 0.0 6.48 0.27 0.0 6.48841 0.30288 0.0 6.50159 0.33033 0.0 6.5195 0.35213 0.0 6.54207 0.368 0.0 6.56926 0.37771 0.0 6.601 0.381 0.0 6.63045 0.3775 0.0 6.65556 0.36733 0.0 6.676 0.351 0.0 6.69144 0.329 0.0 6.70156 0.30183 0.0 6.706 0.27 0.0 6.331 0.682 0.0 5.761 0.682 0.0 5.761 0.594 0.0 5.997 0.594 0.0 5.997 0.0 0.0 6.095 0.0 0.0 6.095 0.594 0.0 6.331 0.594 0.0 5.405 0.421 0.0 5.38182 0.43242 0.0 5.35922 0.4417 0.0 5.33713 0.44888 0.0 5.31544 0.45396 0.0 5.2941 0.457 0.0 5.273 0.458 0.0 5.23079 0.45424 0.0 5.19463 0.44326 0.0 5.16525 0.4255 0.0 5.14337 0.40141 0.0 5.12971 0.37143 0.0 5.125 0.336 0.0 5.14056 0.28229 0.0 5.17944 0.24 0.0 5.23 0.20588 0.0 5.28056 0.17667 0.0 5.31945 0.14913 0.0 5.335 0.12 0.0 5.33261 0.10525 0.0 5.32589 0.093 0.0 5.3155 0.08325 0.0 5.30211 0.076 0.0 5.28639 0.07125 0.0 5.269 0.069 0.0 5.24964 0.07059 0.0 5.22778 0.07541 0.0 5.20375 0.0835 0.0 5.17789 0.09493 0.0 5.15053 0.10974 0.0 5.122 0.128 0.0 5.122 0.032 0.0 5.14988 0.01855 0.0 5.176 0.00804 0.0 5.20113 0.00025 0.0 5.226 -0.00504 0.0 5.25138 -0.00805 0.0 5.278 -0.009 0.0 5.31848 -0.00471 0.0 5.35415 0.00767 0.0 5.38388 0.02737 0.0 5.40652 0.05367 0.0 5.42094 0.08579 0.0 5.426 0.123 0.0 5.42366 0.1449 0.0 5.41626 0.16522 0.0 5.40325 0.18488 0.0 5.38407 0.20478 0.0 5.35818 0.22585 0.0 5.325 0.249 0.0 5.2895 0.27025 0.0 5.26163 0.28833 0.0 5.24088 0.30375 0.0 5.2267 0.317 0.0 5.21859 0.32858 0.0 5.216 0.339 0.0 5.21787 0.35037 0.0 5.2233 0.3603 0.0 5.232 0.3685 0.0 5.2437 0.3747 0.0 5.25813 0.37863 0.0 5.275 0.38 0.0 5.29262 0.37881 0.0 5.31226 0.37515 0.0 5.33363 0.36887 0.0 5.35641 0.35985 0.0 5.3803 0.34794 0.0 5.405 0.333 0.0 5.036 0.427 0.0 5.01505 0.43589 0.0 4.99474 0.44348 0.0 4.97437 0.44963 0.0 4.95326 0.45419 0.0 4.9307 0.45702 0.0 4.906 0.458 0.0 4.84233 0.45035 0.0 4.788 0.42815 0.0 4.744 0.3925 0.0 4.71133 0.34452 0.0 4.691 0.28531 0.0 4.684 0.216 0.0 4.69158 0.1535 0.0 4.71333 0.099 0.0 4.74775 0.054 0.0 4.79333 0.02 0.0 4.84858 -0.0015 0.0 4.912 -0.009 0.0 4.93616 -0.00805 0.0 4.96096 -0.00537 0.0 4.98537 -0.00125 0.0 5.00837 0.00404 0.0 5.02892 0.01021 0.0 5.046 0.017 0.0 5.046 0.105 0.0 5.0242 0.09583 0.0 5.00359 0.08833 0.0 4.98387 0.0825 0.0 4.96474 0.07833 0.0 4.94588 0.07583 0.0 4.927 0.075 0.0 4.8838 0.07958 0.0 4.8467 0.09296 0.0 4.8165 0.11463 0.0 4.79396 0.14404 0.0 4.77987 0.18067 0.0 4.775 0.224 0.0 4.77952 0.26686 0.0 4.79252 0.30385 0.0 4.81313 0.33413 0.0 4.84048 0.35681 0.0 4.87373 0.37106 0.0 4.912 0.376 0.0 4.93119 0.3751 0.0 4.95015 0.37215 0.0 4.9695 0.36675 0.0 4.98985 0.35852 0.0 5.01182 0.34706 0.0 5.036 0.332 0.0 4.578 0.449 0.0 4.489 0.449 0.0 4.489 0.0 0.0 4.578 0.0 0.0 4.587 0.585 0.0 4.58509 0.599 0.0 4.5797 0.61163 0.0 4.57137 0.62238 0.0 4.56063 0.6307 0.0 4.548 0.63609 0.0 4.534 0.638 0.0 4.52 0.63609 0.0 4.50737 0.6307 0.0 4.49662 0.62238 0.0 4.4883 0.61163 0.0 4.48291 0.599 0.0 4.481 0.585 0.0 4.48291 0.571 0.0 4.4883 0.55837 0.0 4.49663 0.54763 0.0 4.50737 0.5393 0.0 4.52001 0.53391 0.0 4.534 0.532 0.0 4.548 0.53391 0.0 4.56063 0.5393 0.0 4.57138 0.54763 0.0 4.5797 0.55837 0.0 4.58509 0.571 0.0 4.363 0.421 0.0 4.33982 0.43242 0.0 4.31722 0.4417 0.0 4.29513 0.44888 0.0 4.27344 0.45396 0.0 4.2521 0.457 0.0 4.231 0.458 0.0 4.18879 0.45424 0.0 4.15263 0.44326 0.0 4.12325 0.4255 0.0 4.10137 0.40141 0.0 4.08771 0.37143 0.0 4.083 0.336 0.0 4.09856 0.28229 0.0 4.13744 0.24 0.0 4.188 0.20588 0.0 4.23856 0.17667 0.0 4.27744 0.14913 0.0 4.293 0.12 0.0 4.29061 0.10525 0.0 4.28389 0.093 0.0 4.2735 0.08325 0.0 4.26011 0.076 0.0 4.24439 0.07125 0.0 4.227 0.069 0.0 4.20764 0.07059 0.0 4.18578 0.07541 0.0 4.16175 0.0835 0.0 4.13589 0.09493 0.0 4.10853 0.10974 0.0 4.08 0.128 0.0 4.08 0.032 0.0 4.10787 0.01855 0.0 4.134 0.00804 0.0 4.15912 0.00025 0.0 4.184 -0.00504 0.0 4.20937 -0.00805 0.0 4.236 -0.009 0.0 4.27648 -0.00471 0.0 4.31215 0.00767 0.0 4.34188 0.02737 0.0 4.36452 0.05367 0.0 4.37894 0.08579 0.0 4.384 0.123 0.0 4.38166 0.1449 0.0 4.37426 0.16522 0.0 4.36125 0.18488 0.0 4.34207 0.20478 0.0 4.31618 0.22585 0.0 4.283 0.249 0.0 4.2475 0.27025 0.0 4.21963 0.28833 0.0 4.19887 0.30375 0.0 4.1847 0.317 0.0 4.17659 0.32858 0.0 4.174 0.339 0.0 4.17587 0.35037 0.0 4.1813 0.3603 0.0 4.19 0.3685 0.0 4.2017 0.3747 0.0 4.21613 0.37863 0.0 4.233 0.38 0.0 4.25062 0.37881 0.0 4.27026 0.37515 0.0 4.29163 0.36887 0.0 4.31441 0.35985 0.0 4.3383 0.34794 0.0 4.363 0.333 0.0 4.039 0.449 0.0 3.939 0.449 0.0 3.823 0.196 0.0 3.702 0.449 0.0 3.601 0.449 0.0 3.775 0.096 0.0 3.622 -0.23 0.0 3.721 -0.23 0.0 3.251 0.682 0.0 3.162 0.682 0.0 3.162 0.0 0.0 3.251 0.0 0.0 3.251 0.322 0.0 3.27117 0.34313 0.0 3.29004 0.35974 0.0 3.30813 0.37213 0.0 3.32596 0.38059 0.0 3.34408 0.38545 0.0 3.363 0.387 0.0 3.38827 0.38351 0.0 3.40982 0.37341 0.0 3.42725 0.35725 0.0 3.44019 0.33559 0.0 3.44823 0.30899 0.0 3.451 0.278 0.0 3.451 0.0 0.0 3.54 0.0 0.0 3.54 0.275 0.0 3.53478 0.33126 0.0 3.51989 0.37711 0.0 3.4965 0.41263 0.0 3.46578 0.43789 0.0 3.42889 0.45299 0.0 3.387 0.458 0.0 3.36207 0.45595 0.0 3.33759 0.44993 0.0 3.314 0.44013 0.0 3.29174 0.42674 0.0 3.27126 0.40997 0.0 3.253 0.39 0.0 3.251 0.39 0.0 2.661 0.682 0.0 2.661 0.0 0.0 2.759 0.0 0.0 2.759 0.295 0.0 2.861 0.295 0.0 2.9329 0.30172 0.0 2.99085 0.32074 0.0 3.03525 0.35038 0.0 3.06648 0.38893 0.0 3.08493 0.4347 0.0 3.091 0.486 0.0 3.08527 0.53802 0.0 3.06785 0.58481 0.0 3.03838 0.6245 0.0 2.99648 0.65519 0.0 2.94181 0.67498 0.0 2.874 0.682 0.0 2.759 0.594 0.0 2.874 0.594 0.0 2.9135 0.58977 0.0 2.94363 0.57815 0.0 2.96538 0.56075 0.0 2.9797 0.53919 0.0 2.98759 0.51506 0.0 2.99 0.49 0.0 2.98618 0.45846 0.0 2.97511 0.43204 0.0 2.95737 0.411 0.0 2.93356 0.39563 0.0 2.90424 0.3862 0.0 2.87 0.383 0.0 2.759 0.383 0.0 2.147 0.542 0.0 1.98 0.379 0.0 1.98 0.369 0.0 2.058 0.369 0.0 2.058 0.132 0.0 2.06208 0.09343 0.0 2.0743 0.05944 0.0 2.09462 0.03112 0.0 2.12304 0.00956 0.0 2.1595 -0.00418 0.0 2.204 -0.009 0.0 2.21992 -0.00796 0.0 2.238 -0.005 0.0 2.25725 -0.00038 0.0 2.27667 0.00567 0.0 2.29525 0.01288 0.0 2.312 0.021 0.0 2.312 0.104 0.0 2.29424 0.09392 0.0 2.27693 0.08567 0.0 2.26 0.07925 0.0 2.24341 0.07467 0.0 2.22709 0.07192 0.0 2.211 0.071 0.0 2.19723 0.07236 0.0 2.18285 0.07685 0.0 2.16925 0.08513 0.0 2.15781 0.09781 0.0 2.14994 0.11556 0.0 2.147 0.139 0.0 2.147 0.369 0.0 2.289 0.369 0.0 2.289 0.449 0.0 2.147 0.449 0.0 1.939 0.13 0.0 1.91306 0.11419 0.0 1.88719 0.10089 0.0 1.86125 0.09025 0.0 1.83515 0.08244 0.0 1.80877 0.07764 0.0 1.782 0.076 0.0 1.74193 0.07982 0.0 1.70774 0.09122 0.0 1.6795 0.11013 0.0 1.65726 0.13644 0.0 1.64107 0.1701 0.0 1.631 0.211 0.0 1.947 0.211 0.0 1.94082 0.28694 0.0 1.92289 0.34881 0.0 1.89412 0.39675 0.0 1.85544 0.43085 0.0 1.80776 0.45123 0.0 1.752 0.458 0.0 1.69339 0.45056 0.0 1.64244 0.42911 0.0 1.6005 0.395 0.0 1.56889 0.34956 0.0 1.54894 0.29411 0.0 1.542 0.23 0.0 1.54843 0.16924 0.0 1.56741 0.11293 0.0 1.5985 0.064 0.0 1.64126 0.02541 0.0 1.69524 9e-05 0.0 1.76 -0.009 0.0 1.7959 -0.00757 0.0 1.82819 -0.00326 0.0 1.85775 0.004 0.0 1.88548 0.01426 0.0 1.91227 0.02757 0.0 1.939 0.044 0.0 1.633 0.27 0.0 1.64141 0.30288 0.0 1.65459 0.33033 0.0 1.6725 0.35213 0.0 1.69507 0.368 0.0 1.72226 0.37771 0.0 1.754 0.381 0.0 1.78344 0.3775 0.0 1.80856 0.36733 0.0 1.829 0.351 0.0 1.84444 0.329 0.0 1.85456 0.30183 0.0 1.859 0.27 0.0 1.436 0.682 0.0 1.347 0.682 0.0 1.347 0.0 0.0 1.436 0.0 0.0 1.217 0.682 0.0 1.128 0.682 0.0 1.128 0.0 0.0 1.217 0.0 0.0 1.0 0.0 0.0 1.0 0.449 0.0 0.911 0.449 0.0 0.911 0.128 0.0 0.89578 0.1091 0.0 0.87926 0.09344 0.0 0.86163 0.08113 0.0 0.84307 0.07222 0.0 0.8238 0.06682 0.0 0.804 0.065 0.0 0.776 0.06796 0.0 0.75304 0.07667 0.0 0.73513 0.09088 0.0 0.7223 0.11033 0.0 0.71458 0.13479 0.0 0.712 0.164 0.0 0.712 0.449 0.0 0.623 0.449 0.0 0.623 0.17 0.0 0.62816 0.11716 0.0 0.64296 0.07293 0.0 0.66638 0.03775 0.0 0.69737 0.01207 0.0 0.73492 -0.00366 0.0 0.778 -0.009 0.0 0.80056 -0.00689 0.0 0.82381 -0.00078 0.0 0.84712 0.009 0.0 0.86985 0.02211 0.0 0.89136 0.03822 0.0 0.911 0.057 0.0 0.911 0.0 0.0 0.075 0.0 0.0 0.309 0.0 0.0 0.38571 0.00765 0.0 0.44567 0.02852 0.0 0.49013 0.0595 0.0 0.52033 0.09748 0.0 0.53754 0.13935 0.0 0.543 0.182 0.0 0.53794 0.22581 0.0 0.52315 0.26481 0.0 0.49925 0.29838 0.0 0.46685 0.32585 0.0 0.42656 0.34661 0.0 0.379 0.36 0.0 0.379 0.362 0.0 0.41136 0.37795 0.0 0.43752 0.39696 0.0 0.45763 0.41925 0.0 0.47181 0.44504 0.0 0.48023 0.47455 0.0 0.483 0.508 0.0 0.47765 0.55075 0.0 0.46122 0.59133 0.0 0.43313 0.62725 0.0 0.39278 0.656 0.0 0.3396 0.67508 0.0 0.273 0.682 0.0 0.075 0.682 0.0 0.173 0.594 0.0 0.263 0.594 0.0 0.30306 0.5905 0.0 0.33385 0.5807 0.0 0.35625 0.56563 0.0 0.37115 0.5463 0.0 0.37944 0.52375 0.0 0.382 0.499 0.0 0.37807 0.46558 0.0 0.36622 0.4383 0.0 0.34638 0.41713 0.0 0.31844 0.40204 0.0 0.28235 0.393 0.0 0.238 0.39 0.0 0.173 0.39 0.0 0.173 0.302 0.0 0.291 0.302 0.0 0.33795 0.29845 0.0 0.37593 0.2883 0.0 0.40513 0.27225 0.0 0.42574 0.25104 0.0 0.43797 0.22538 0.0 0.442 0.196 0.0 0.43917 0.17029 0.0 0.4297 0.14533 0.0 0.41212 0.12288 0.0 0.38496 0.10467 0.0 0.34675 0.09246 0.0 0.296 0.088 0.0 0.173 0.088 0.0 - - - - - - - - - - 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 0.0 0.0 -1.0 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    20 0 19 1 18 2 20 3 18 4 17 5 21 6 20 7 17 8 21 9 17 10 16 11 22 12 21 13 16 14 22 15 16 16 44 17 44 18 16 19 45 20 45 21 16 22 15 23 23 24 22 25 43 26 43 27 22 28 44 29 23 30 43 31 42 32 46 33 45 34 15 35 23 36 42 37 41 38 47 39 46 40 15 41 23 42 41 43 40 44 48 45 47 46 15 47 24 48 23 49 40 50 48 51 15 52 14 53 24 54 40 55 39 56 49 57 48 58 14 59 24 60 39 61 38 62 50 63 49 64 14 65 25 66 24 67 38 68 50 69 14 70 13 71 25 72 38 73 50 74 25 75 50 76 13 77 26 78 25 79 12 80 12 81 25 82 13 83 26 84 12 85 11 86 26 87 11 88 10 89 27 90 26 91 10 92 27 93 10 94 9 95 1 96 0 97 37 98 2 99 1 100 37 101 28 102 27 103 9 104 28 105 9 106 8 107 3 108 2 109 37 110 28 111 8 112 7 113 4 114 3 115 37 116 5 117 4 118 37 119 28 120 7 121 6 122 6 123 5 124 37 125 28 126 6 127 37 128 29 129 28 130 37 131 29 132 37 133 36 134 29 135 36 136 35 137 30 138 29 139 35 140 30 141 35 142 34 143 30 144 34 145 33 146 31 147 30 148 33 149 31 150 33 151 32 152 52 153 51 154 84 155 52 156 84 157 83 158 52 159 83 160 82 161 53 162 52 163 82 164 54 165 53 166 82 167 55 168 54 169 81 170 81 171 54 172 82 173 55 174 81 175 80 176 55 177 80 178 79 179 56 180 55 181 79 182 56 183 79 184 78 185 69 186 68 187 67 188 56 189 78 190 77 191 70 192 69 193 67 194 57 195 56 196 77 197 71 198 70 199 67 200 57 201 77 202 76 203 72 204 71 205 67 206 57 207 76 208 75 209 73 210 72 211 67 212 57 213 75 214 74 215 74 216 73 217 67 218 57 219 74 220 67 221 58 222 57 223 67 224 59 225 58 226 67 227 59 228 67 229 66 230 59 231 66 232 65 233 60 234 59 235 65 236 60 237 65 238 64 239 60 240 64 241 63 242 61 243 60 244 63 245 61 246 63 247 62 248 105 249 104 250 103 251 106 252 105 253 103 254 106 255 103 256 102 257 107 258 106 259 102 260 108 261 107 262 102 263 108 264 102 265 101 266 109 267 108 268 101 269 109 270 101 271 100 272 110 273 109 274 100 275 111 276 110 277 112 278 112 279 110 280 113 281 113 282 110 283 114 284 114 285 110 286 115 287 115 288 110 289 116 290 116 291 110 292 117 293 117 294 110 295 100 296 117 297 100 298 118 299 118 300 100 301 99 302 119 303 118 304 99 305 120 306 119 307 99 308 120 309 99 310 98 311 121 312 120 313 98 314 122 315 121 316 98 317 123 318 122 319 98 320 123 321 98 322 97 323 124 324 123 325 97 326 125 327 124 328 174 329 174 330 124 331 97 332 126 333 125 334 174 335 127 336 126 337 174 338 127 339 174 340 173 341 156 342 174 343 97 344 128 345 127 346 173 347 128 348 173 349 172 350 129 351 128 352 172 353 129 354 172 355 171 356 129 357 171 358 170 359 130 360 129 361 170 362 130 363 170 364 169 365 130 366 169 367 168 368 131 369 130 370 168 371 131 372 168 373 167 374 132 375 131 376 167 377 132 378 167 379 166 380 157 381 156 382 97 383 132 384 166 385 165 386 158 387 157 388 97 389 86 390 85 391 155 392 158 393 97 394 96 395 87 396 86 397 155 398 133 399 132 400 165 401 133 402 165 403 164 404 158 405 96 406 95 407 159 408 158 409 95 410 88 411 87 412 155 413 159 414 95 415 94 416 160 417 159 418 94 419 89 420 88 421 155 422 133 423 164 424 163 425 160 426 94 427 93 428 90 429 89 430 155 431 161 432 160 433 93 434 161 435 93 436 92 437 91 438 90 439 155 440 161 441 92 442 91 443 133 444 163 445 162 446 161 447 91 448 155 449 162 450 161 451 155 452 133 453 162 454 143 455 143 456 162 457 155 458 134 459 133 460 143 461 134 462 143 463 142 464 144 465 143 466 155 467 144 468 155 469 154 470 135 471 134 472 142 473 135 474 142 475 141 476 145 477 144 478 154 479 145 480 154 481 153 482 135 483 141 484 140 485 146 486 145 487 153 488 136 489 135 490 140 491 146 492 153 493 152 494 136 495 140 496 139 497 147 498 146 499 152 500 147 501 152 502 151 503 136 504 139 505 138 506 148 507 147 508 151 509 137 510 136 511 138 512 148 513 151 514 150 515 149 516 148 517 150 518 177 519 176 520 175 521 177 522 175 523 256 524 178 525 177 526 256 527 179 528 178 529 256 530 180 531 179 532 255 533 255 534 179 535 256 536 180 537 255 538 275 539 275 540 255 541 254 542 181 543 180 544 274 545 274 546 180 547 275 548 276 549 275 550 254 551 277 552 276 553 254 554 181 555 274 556 273 557 277 558 254 559 253 560 278 561 277 562 253 563 181 564 273 565 272 566 279 567 278 568 253 569 181 570 272 571 271 572 279 573 253 574 252 575 182 576 181 577 271 578 280 579 279 580 252 581 280 582 252 583 251 584 182 585 271 586 270 587 280 588 251 589 250 590 257 591 280 592 250 593 182 594 270 595 269 596 257 597 250 598 249 599 183 600 182 601 269 602 258 603 257 604 249 605 183 606 269 607 268 608 258 609 249 610 248 611 184 612 183 613 268 614 259 615 258 616 248 617 184 618 268 619 267 620 259 621 248 622 247 623 185 624 184 625 267 626 260 627 259 628 247 629 186 630 185 631 267 632 186 633 267 634 266 635 260 636 247 637 246 638 187 639 186 640 266 641 261 642 260 643 246 644 187 645 266 646 265 647 261 648 246 649 245 650 188 651 187 652 265 653 262 654 261 655 245 656 188 657 265 658 264 659 263 660 262 661 245 662 188 663 264 664 263 665 189 666 188 667 263 668 189 669 263 670 245 671 189 672 245 673 244 674 190 675 189 676 244 677 190 678 244 679 243 680 191 681 190 682 243 683 191 684 243 685 242 686 192 687 191 688 242 689 193 690 192 691 242 692 194 693 193 694 242 695 194 696 242 697 241 698 195 699 194 700 241 701 196 702 195 703 241 704 197 705 196 706 241 707 197 708 241 709 240 710 198 711 197 712 240 713 198 714 240 715 239 716 198 717 239 718 238 719 199 720 198 721 238 722 199 723 238 724 237 725 200 726 199 727 237 728 201 729 200 730 237 731 201 732 237 733 236 734 202 735 201 736 236 737 202 738 236 739 235 740 203 741 202 742 235 743 203 744 235 745 234 746 204 747 203 748 234 749 204 750 234 751 233 752 205 753 204 754 233 755 205 756 233 757 232 758 206 759 205 760 232 761 206 762 232 763 231 764 207 765 206 766 231 767 207 768 231 769 230 770 208 771 207 772 230 773 208 774 230 775 229 776 209 777 208 778 229 779 209 780 229 781 228 782 210 783 209 784 228 785 210 786 228 787 299 788 299 789 228 790 300 791 300 792 228 793 227 794 211 795 210 796 298 797 298 798 210 799 299 800 301 801 300 802 227 803 211 804 298 805 297 806 302 807 301 808 227 809 211 810 297 811 296 812 302 813 227 814 226 815 303 816 302 817 226 818 212 819 211 820 296 821 212 822 296 823 295 824 304 825 303 826 226 827 212 828 295 829 294 830 304 831 226 832 225 833 213 834 212 835 294 836 281 837 304 838 225 839 213 840 294 841 293 842 281 843 225 844 224 845 213 846 293 847 292 848 214 849 213 850 292 851 282 852 281 853 224 854 214 855 292 856 291 857 283 858 282 859 224 860 214 861 291 862 290 863 283 864 224 865 223 866 284 867 283 868 223 869 215 870 214 871 290 872 215 873 290 874 289 875 285 876 284 877 223 878 215 879 289 880 288 881 286 882 285 883 223 884 215 885 288 886 287 887 287 888 286 889 223 890 215 891 287 892 223 893 215 894 223 895 222 896 216 897 215 898 222 899 217 900 216 901 222 902 217 903 222 904 221 905 218 906 217 907 221 908 218 909 221 910 220 911 219 912 218 913 220 914 316 915 315 916 314 917 317 918 316 919 314 920 317 921 314 922 313 923 318 924 317 925 313 926 318 927 313 928 312 929 319 930 318 931 312 932 319 933 312 934 311 935 320 936 319 937 311 938 320 939 311 940 310 941 321 942 320 943 310 944 321 945 310 946 309 947 322 948 321 949 309 950 322 951 309 952 332 953 323 954 322 955 332 956 323 957 332 958 331 959 324 960 323 961 331 962 324 963 331 964 330 965 325 966 324 967 330 968 325 969 330 970 329 971 326 972 325 973 329 974 326 975 329 976 328 977 327 978 326 979 328 980 307 981 306 982 305 983 307 984 305 985 308 986 333 987 339 988 338 989 333 990 338 991 337 992 337 993 336 994 335 995 337 996 335 997 334 998 333 999 337 1000 334 1001 360 1002 359 1003 358 1004 361 1005 360 1006 358 1007 361 1008 358 1009 357 1010 362 1011 361 1012 357 1013 363 1014 362 1015 357 1016 363 1017 357 1018 356 1019 364 1020 363 1021 356 1022 364 1023 356 1024 355 1025 365 1026 364 1027 355 1028 366 1029 365 1030 367 1031 367 1032 365 1033 368 1034 368 1035 365 1036 369 1037 369 1038 365 1039 370 1040 370 1041 365 1042 371 1043 371 1044 365 1045 372 1046 372 1047 365 1048 355 1049 372 1050 355 1051 373 1052 373 1053 355 1054 354 1055 374 1056 373 1057 354 1058 375 1059 374 1060 354 1061 375 1062 354 1063 353 1064 376 1065 375 1066 353 1067 377 1068 376 1069 353 1070 378 1071 377 1072 353 1073 378 1074 353 1075 352 1076 379 1077 378 1078 352 1079 380 1080 379 1081 429 1082 429 1083 379 1084 352 1085 381 1086 380 1087 429 1088 382 1089 381 1090 429 1091 382 1092 429 1093 428 1094 411 1095 429 1096 352 1097 383 1098 382 1099 428 1100 383 1101 428 1102 427 1103 384 1104 383 1105 427 1106 384 1107 427 1108 426 1109 384 1110 426 1111 425 1112 385 1113 384 1114 425 1115 385 1116 425 1117 424 1118 385 1119 424 1120 423 1121 386 1122 385 1123 423 1124 386 1125 423 1126 422 1127 387 1128 386 1129 422 1130 387 1131 422 1132 421 1133 412 1134 411 1135 352 1136 387 1137 421 1138 420 1139 413 1140 412 1141 352 1142 341 1143 340 1144 410 1145 413 1146 352 1147 351 1148 342 1149 341 1150 410 1151 388 1152 387 1153 420 1154 388 1155 420 1156 419 1157 413 1158 351 1159 350 1160 414 1161 413 1162 350 1163 343 1164 342 1165 410 1166 414 1167 350 1168 349 1169 415 1170 414 1171 349 1172 344 1173 343 1174 410 1175 388 1176 419 1177 418 1178 415 1179 349 1180 348 1181 345 1182 344 1183 410 1184 416 1185 415 1186 348 1187 416 1188 348 1189 347 1190 346 1191 345 1192 410 1193 416 1194 347 1195 346 1196 388 1197 418 1198 417 1199 416 1200 346 1201 410 1202 417 1203 416 1204 410 1205 388 1206 417 1207 398 1208 398 1209 417 1210 410 1211 389 1212 388 1213 398 1214 389 1215 398 1216 397 1217 399 1218 398 1219 410 1220 399 1221 410 1222 409 1223 390 1224 389 1225 397 1226 390 1227 397 1228 396 1229 400 1230 399 1231 409 1232 400 1233 409 1234 408 1235 390 1236 396 1237 395 1238 401 1239 400 1240 408 1241 391 1242 390 1243 395 1244 401 1245 408 1246 407 1247 391 1248 395 1249 394 1250 402 1251 401 1252 407 1253 402 1254 407 1255 406 1256 391 1257 394 1258 393 1259 403 1260 402 1261 406 1262 392 1263 391 1264 393 1265 403 1266 406 1267 405 1268 404 1269 403 1270 405 1271 456 1272 455 1273 454 1274 457 1275 456 1276 454 1277 457 1278 454 1279 453 1280 458 1281 457 1282 453 1283 432 1284 431 1285 430 1286 432 1287 430 1288 462 1289 459 1290 458 1291 453 1292 459 1293 453 1294 452 1295 460 1296 459 1297 452 1298 460 1299 452 1300 451 1301 461 1302 460 1303 440 1304 440 1305 460 1306 451 1307 432 1308 462 1309 461 1310 432 1311 461 1312 434 1313 434 1314 461 1315 435 1316 435 1317 461 1318 436 1319 436 1320 461 1321 437 1322 437 1323 461 1324 438 1325 438 1326 461 1327 439 1328 439 1329 461 1330 440 1331 441 1332 440 1333 451 1334 442 1335 441 1336 451 1337 442 1338 451 1339 450 1340 443 1341 442 1342 450 1343 444 1344 443 1345 450 1346 445 1347 444 1348 450 1349 445 1350 450 1351 449 1352 432 1353 434 1354 433 1355 446 1356 445 1357 449 1358 447 1359 446 1360 449 1361 447 1362 449 1363 448 1364 464 1365 463 1366 486 1367 464 1368 486 1369 485 1370 465 1371 464 1372 485 1373 465 1374 485 1375 484 1376 466 1377 465 1378 484 1379 466 1380 484 1381 487 1382 487 1383 484 1384 488 1385 488 1386 484 1387 483 1388 467 1389 466 1390 510 1391 510 1392 466 1393 487 1394 467 1395 510 1396 509 1397 489 1398 488 1399 483 1400 467 1401 509 1402 508 1403 490 1404 489 1405 483 1406 490 1407 483 1408 482 1409 468 1410 467 1411 508 1412 468 1413 508 1414 507 1415 491 1416 490 1417 482 1418 468 1419 507 1420 506 1421 492 1422 491 1423 482 1424 492 1425 482 1426 481 1427 469 1428 468 1429 506 1430 469 1431 506 1432 505 1433 493 1434 492 1435 481 1436 470 1437 469 1438 505 1439 470 1440 505 1441 504 1442 493 1443 481 1444 480 1445 494 1446 493 1447 480 1448 470 1449 504 1450 503 1451 495 1452 494 1453 480 1454 471 1455 470 1456 503 1457 495 1458 480 1459 479 1460 471 1461 503 1462 502 1463 496 1464 495 1465 479 1466 471 1467 502 1468 501 1469 497 1470 496 1471 479 1472 472 1473 471 1474 501 1475 497 1476 479 1477 478 1478 472 1479 501 1480 500 1481 498 1482 497 1483 478 1484 472 1485 500 1486 499 1487 499 1488 498 1489 478 1490 472 1491 499 1492 478 1493 473 1494 472 1495 478 1496 473 1497 478 1498 477 1499 474 1500 473 1501 477 1502 474 1503 477 1504 476 1505 475 1506 474 1507 476 1508 512 1509 511 1510 544 1511 512 1512 544 1513 543 1514 512 1515 543 1516 542 1517 513 1518 512 1519 542 1520 514 1521 513 1522 542 1523 515 1524 514 1525 541 1526 541 1527 514 1528 542 1529 515 1530 541 1531 540 1532 515 1533 540 1534 539 1535 516 1536 515 1537 539 1538 516 1539 539 1540 538 1541 529 1542 528 1543 527 1544 516 1545 538 1546 537 1547 530 1548 529 1549 527 1550 517 1551 516 1552 537 1553 531 1554 530 1555 527 1556 517 1557 537 1558 536 1559 532 1560 531 1561 527 1562 517 1563 536 1564 535 1565 533 1566 532 1567 527 1568 517 1569 535 1570 534 1571 534 1572 533 1573 527 1574 517 1575 534 1576 527 1577 518 1578 517 1579 527 1580 519 1581 518 1582 527 1583 519 1584 527 1585 526 1586 519 1587 526 1588 525 1589 520 1590 519 1591 525 1592 520 1593 525 1594 524 1595 520 1596 524 1597 523 1598 521 1599 520 1600 523 1601 521 1602 523 1603 522 1604 552 1605 551 1606 550 1607 552 1608 550 1609 549 1610 553 1611 552 1612 549 1613 553 1614 549 1615 548 1616 553 1617 548 1618 547 1619 554 1620 553 1621 547 1622 554 1623 547 1624 546 1625 554 1626 546 1627 545 1628 555 1629 554 1630 545 1631 555 1632 545 1633 606 1634 606 1635 545 1636 607 1637 607 1638 545 1639 608 1640 608 1641 545 1642 609 1643 609 1644 545 1645 610 1646 610 1647 545 1648 611 1649 611 1650 545 1651 612 1652 556 1653 555 1654 606 1655 556 1656 606 1657 605 1658 556 1659 605 1660 604 1661 556 1662 604 1663 603 1664 557 1665 556 1666 603 1667 557 1668 603 1669 602 1670 557 1671 602 1672 601 1673 557 1674 601 1675 600 1676 557 1677 600 1678 599 1679 558 1680 557 1681 599 1682 558 1683 599 1684 598 1685 558 1686 598 1687 597 1688 558 1689 597 1690 596 1691 558 1692 596 1693 595 1694 559 1695 558 1696 595 1697 559 1698 595 1699 594 1700 559 1701 594 1702 593 1703 560 1704 559 1705 593 1706 560 1707 593 1708 592 1709 561 1710 560 1711 592 1712 561 1713 592 1714 591 1715 561 1716 591 1717 590 1718 562 1719 561 1720 590 1721 562 1722 590 1723 589 1724 563 1725 562 1726 589 1727 563 1728 589 1729 588 1730 576 1731 575 1732 574 1733 563 1734 588 1735 587 1736 564 1737 563 1738 587 1739 576 1740 574 1741 573 1742 565 1743 564 1744 587 1745 576 1746 573 1747 572 1748 566 1749 565 1750 587 1751 566 1752 587 1753 586 1754 576 1755 572 1756 571 1757 567 1758 566 1759 586 1760 568 1761 567 1762 586 1763 576 1764 571 1765 570 1766 569 1767 568 1768 586 1769 576 1770 570 1771 569 1772 576 1773 569 1774 586 1775 576 1776 586 1777 585 1778 577 1779 576 1780 585 1781 577 1782 585 1783 584 1784 578 1785 577 1786 584 1787 579 1788 578 1789 584 1790 579 1791 584 1792 583 1793 580 1794 579 1795 583 1796 580 1797 583 1798 582 1799 581 1800 580 1801 582 1802 618 1803 617 1804 616 1805 618 1806 616 1807 615 1808 615 1809 614 1810 613 1811 615 1812 613 1813 620 1814 618 1815 615 1816 620 1817 619 1818 618 1819 620 1820 641 1821 640 1822 639 1823 641 1824 639 1825 638 1826 642 1827 641 1828 638 1829 642 1830 638 1831 637 1832 643 1833 642 1834 637 1835 643 1836 637 1837 665 1838 665 1839 637 1840 666 1841 666 1842 637 1843 636 1844 644 1845 643 1846 664 1847 664 1848 643 1849 665 1850 644 1851 664 1852 663 1853 667 1854 666 1855 636 1856 644 1857 663 1858 662 1859 668 1860 667 1861 636 1862 644 1863 662 1864 661 1865 669 1866 668 1867 636 1868 645 1869 644 1870 661 1871 669 1872 636 1873 635 1874 645 1875 661 1876 660 1877 670 1878 669 1879 635 1880 645 1881 660 1882 659 1883 671 1884 670 1885 635 1886 646 1887 645 1888 659 1889 671 1890 635 1891 634 1892 646 1893 659 1894 671 1895 646 1896 671 1897 634 1898 647 1899 646 1900 633 1901 633 1902 646 1903 634 1904 647 1905 633 1906 632 1907 647 1908 632 1909 631 1910 648 1911 647 1912 631 1913 648 1914 631 1915 630 1916 622 1917 621 1918 658 1919 623 1920 622 1921 658 1922 649 1923 648 1924 630 1925 649 1926 630 1927 629 1928 624 1929 623 1930 658 1931 649 1932 629 1933 628 1934 625 1935 624 1936 658 1937 626 1938 625 1939 658 1940 649 1941 628 1942 627 1943 627 1944 626 1945 658 1946 649 1947 627 1948 658 1949 650 1950 649 1951 658 1952 650 1953 658 1954 657 1955 650 1956 657 1957 656 1958 651 1959 650 1960 656 1961 651 1962 656 1963 655 1964 651 1965 655 1966 654 1967 652 1968 651 1969 654 1970 652 1971 654 1972 653 1973 680 1974 679 1975 678 1976 680 1977 678 1978 681 1979 674 1980 673 1981 672 1982 674 1983 672 1984 677 1985 675 1986 674 1987 677 1988 675 1989 677 1990 676 1991 705 1992 704 1993 703 1994 705 1995 703 1996 702 1997 706 1998 705 1999 702 2000 706 2001 702 2002 701 2003 683 2004 682 2005 712 2006 683 2007 712 2008 711 2009 707 2010 706 2011 701 2012 707 2013 701 2014 700 2015 707 2016 700 2017 699 2018 708 2019 707 2020 699 2021 708 2022 699 2023 698 2024 709 2025 708 2026 698 2027 709 2028 698 2029 691 2030 691 2031 698 2032 692 2033 692 2034 698 2035 693 2036 693 2037 698 2038 694 2039 694 2040 698 2041 695 2042 695 2043 698 2044 696 2045 696 2046 698 2047 697 2048 710 2049 709 2050 690 2051 690 2052 709 2053 691 2054 710 2055 690 2056 689 2057 710 2058 689 2059 688 2060 683 2061 711 2062 710 2063 683 2064 710 2065 687 2066 687 2067 710 2068 688 2069 683 2070 687 2071 686 2072 683 2073 686 2074 685 2075 683 2076 685 2077 684 2078 714 2079 713 2080 736 2081 714 2082 736 2083 735 2084 715 2085 714 2086 735 2087 715 2088 735 2089 734 2090 716 2091 715 2092 734 2093 716 2094 734 2095 737 2096 737 2097 734 2098 738 2099 738 2100 734 2101 733 2102 717 2103 716 2104 760 2105 760 2106 716 2107 737 2108 717 2109 760 2110 759 2111 739 2112 738 2113 733 2114 717 2115 759 2116 758 2117 740 2118 739 2119 733 2120 740 2121 733 2122 732 2123 718 2124 717 2125 758 2126 718 2127 758 2128 757 2129 741 2130 740 2131 732 2132 718 2133 757 2134 756 2135 742 2136 741 2137 732 2138 742 2139 732 2140 731 2141 719 2142 718 2143 756 2144 719 2145 756 2146 755 2147 743 2148 742 2149 731 2150 720 2151 719 2152 755 2153 720 2154 755 2155 754 2156 743 2157 731 2158 730 2159 744 2160 743 2161 730 2162 720 2163 754 2164 753 2165 745 2166 744 2167 730 2168 721 2169 720 2170 753 2171 745 2172 730 2173 729 2174 721 2175 753 2176 752 2177 746 2178 745 2179 729 2180 721 2181 752 2182 751 2183 747 2184 746 2185 729 2186 722 2187 721 2188 751 2189 747 2190 729 2191 728 2192 722 2193 751 2194 750 2195 748 2196 747 2197 728 2198 722 2199 750 2200 749 2201 749 2202 748 2203 728 2204 722 2205 749 2206 728 2207 723 2208 722 2209 728 2210 723 2211 728 2212 727 2213 724 2214 723 2215 727 2216 724 2217 727 2218 726 2219 725 2220 724 2221 726 2222 768 2223 767 2224 766 2225 768 2226 766 2227 765 2228 769 2229 768 2230 765 2231 769 2232 765 2233 764 2234 769 2235 764 2236 763 2237 770 2238 769 2239 763 2240 770 2241 763 2242 762 2243 770 2244 762 2245 761 2246 771 2247 770 2248 761 2249 771 2250 761 2251 822 2252 822 2253 761 2254 823 2255 823 2256 761 2257 824 2258 824 2259 761 2260 825 2261 825 2262 761 2263 826 2264 826 2265 761 2266 827 2267 827 2268 761 2269 828 2270 772 2271 771 2272 822 2273 772 2274 822 2275 821 2276 772 2277 821 2278 820 2279 772 2280 820 2281 819 2282 773 2283 772 2284 819 2285 773 2286 819 2287 818 2288 773 2289 818 2290 817 2291 773 2292 817 2293 816 2294 773 2295 816 2296 815 2297 774 2298 773 2299 815 2300 774 2301 815 2302 814 2303 774 2304 814 2305 813 2306 774 2307 813 2308 812 2309 774 2310 812 2311 811 2312 775 2313 774 2314 811 2315 775 2316 811 2317 810 2318 775 2319 810 2320 809 2321 776 2322 775 2323 809 2324 776 2325 809 2326 808 2327 777 2328 776 2329 808 2330 777 2331 808 2332 807 2333 777 2334 807 2335 806 2336 778 2337 777 2338 806 2339 778 2340 806 2341 805 2342 779 2343 778 2344 805 2345 779 2346 805 2347 804 2348 792 2349 791 2350 790 2351 779 2352 804 2353 803 2354 780 2355 779 2356 803 2357 792 2358 790 2359 789 2360 781 2361 780 2362 803 2363 792 2364 789 2365 788 2366 782 2367 781 2368 803 2369 782 2370 803 2371 802 2372 792 2373 788 2374 787 2375 783 2376 782 2377 802 2378 784 2379 783 2380 802 2381 792 2382 787 2383 786 2384 785 2385 784 2386 802 2387 792 2388 786 2389 785 2390 792 2391 785 2392 802 2393 792 2394 802 2395 801 2396 793 2397 792 2398 801 2399 793 2400 801 2401 800 2402 794 2403 793 2404 800 2405 795 2406 794 2407 800 2408 795 2409 800 2410 799 2411 796 2412 795 2413 799 2414 796 2415 799 2416 798 2417 797 2418 796 2419 798 2420 852 2421 851 2422 850 2423 852 2424 850 2425 849 2426 853 2427 852 2428 849 2429 853 2430 849 2431 848 2432 830 2433 829 2434 859 2435 830 2436 859 2437 858 2438 854 2439 853 2440 848 2441 854 2442 848 2443 847 2444 854 2445 847 2446 846 2447 855 2448 854 2449 846 2450 855 2451 846 2452 845 2453 856 2454 855 2455 845 2456 856 2457 845 2458 838 2459 838 2460 845 2461 839 2462 839 2463 845 2464 840 2465 840 2466 845 2467 841 2468 841 2469 845 2470 842 2471 842 2472 845 2473 843 2474 843 2475 845 2476 844 2477 857 2478 856 2479 837 2480 837 2481 856 2482 838 2483 857 2484 837 2485 836 2486 857 2487 836 2488 835 2489 830 2490 858 2491 857 2492 830 2493 857 2494 834 2495 834 2496 857 2497 835 2498 830 2499 834 2500 833 2501 830 2502 833 2503 832 2504 830 2505 832 2506 831 2507 878 2508 877 2509 876 2510 878 2511 876 2512 875 2513 863 2514 862 2515 861 2516 863 2517 861 2518 860 2519 879 2520 878 2521 875 2522 879 2523 875 2524 874 2525 879 2526 874 2527 873 2528 864 2529 863 2530 860 2531 880 2532 879 2533 873 2534 880 2535 873 2536 872 2537 865 2538 864 2539 860 2540 866 2541 865 2542 890 2543 890 2544 865 2545 860 2546 880 2547 872 2548 871 2549 867 2550 866 2551 890 2552 880 2553 871 2554 870 2555 881 2556 880 2557 870 2558 868 2559 867 2560 890 2561 881 2562 870 2563 869 2564 869 2565 868 2566 890 2567 881 2568 869 2569 890 2570 881 2571 890 2572 889 2573 891 2574 890 2575 860 2576 881 2577 889 2578 888 2579 882 2580 881 2581 888 2582 882 2583 888 2584 887 2585 883 2586 882 2587 887 2588 883 2589 887 2590 886 2591 883 2592 886 2593 885 2594 884 2595 883 2596 885 2597 899 2598 898 2599 897 2600 899 2601 897 2602 896 2603 899 2604 896 2605 895 2606 900 2607 899 2608 895 2609 900 2610 895 2611 894 2612 900 2613 894 2614 893 2615 900 2616 893 2617 892 2618 901 2619 900 2620 892 2621 901 2622 892 2623 935 2624 935 2625 892 2626 936 2627 936 2628 892 2629 937 2630 937 2631 892 2632 938 2633 938 2634 892 2635 939 2636 939 2637 892 2638 940 2639 940 2640 892 2641 941 2642 901 2643 935 2644 934 2645 901 2646 934 2647 933 2648 902 2649 901 2650 933 2651 902 2652 933 2653 932 2654 902 2655 932 2656 931 2657 903 2658 902 2659 931 2660 903 2661 931 2662 930 2663 904 2664 903 2665 930 2666 904 2667 930 2668 929 2669 904 2670 929 2671 928 2672 905 2673 904 2674 928 2675 905 2676 928 2677 927 2678 906 2679 905 2680 927 2681 906 2682 927 2683 926 2684 907 2685 906 2686 926 2687 918 2688 917 2689 916 2690 907 2691 926 2692 925 2693 919 2694 918 2695 916 2696 920 2697 919 2698 916 2699 907 2700 925 2701 924 2702 908 2703 907 2704 924 2705 921 2706 920 2707 916 2708 922 2709 921 2710 916 2711 908 2712 924 2713 923 2714 923 2715 922 2716 916 2717 908 2718 923 2719 916 2720 908 2721 916 2722 915 2723 909 2724 908 2725 915 2726 909 2727 915 2728 914 2729 909 2730 914 2731 913 2732 909 2733 913 2734 912 2735 910 2736 909 2737 912 2738 910 2739 912 2740 911 2741 943 2742 942 2743 975 2744 943 2745 975 2746 974 2747 943 2748 974 2749 973 2750 944 2751 943 2752 973 2753 945 2754 944 2755 973 2756 946 2757 945 2758 972 2759 972 2760 945 2761 973 2762 946 2763 972 2764 971 2765 946 2766 971 2767 970 2768 947 2769 946 2770 970 2771 947 2772 970 2773 969 2774 960 2775 959 2776 958 2777 947 2778 969 2779 968 2780 961 2781 960 2782 958 2783 948 2784 947 2785 968 2786 962 2787 961 2788 958 2789 948 2790 968 2791 967 2792 963 2793 962 2794 958 2795 948 2796 967 2797 966 2798 964 2799 963 2800 958 2801 948 2802 966 2803 965 2804 965 2805 964 2806 958 2807 948 2808 965 2809 958 2810 949 2811 948 2812 958 2813 950 2814 949 2815 958 2816 950 2817 958 2818 957 2819 950 2820 957 2821 956 2822 951 2823 950 2824 956 2825 951 2826 956 2827 955 2828 951 2829 955 2830 954 2831 952 2832 951 2833 954 2834 952 2835 954 2836 953 2837 977 2838 976 2839 999 2840 977 2841 999 2842 998 2843 978 2844 977 2845 998 2846 978 2847 998 2848 997 2849 979 2850 978 2851 997 2852 979 2853 997 2854 1000 2855 1000 2856 997 2857 1001 2858 1001 2859 997 2860 996 2861 980 2862 979 2863 1023 2864 1023 2865 979 2866 1000 2867 980 2868 1023 2869 1022 2870 1002 2871 1001 2872 996 2873 980 2874 1022 2875 1021 2876 1003 2877 1002 2878 996 2879 1003 2880 996 2881 995 2882 981 2883 980 2884 1021 2885 981 2886 1021 2887 1020 2888 1004 2889 1003 2890 995 2891 981 2892 1020 2893 1019 2894 1005 2895 1004 2896 995 2897 1005 2898 995 2899 994 2900 982 2901 981 2902 1019 2903 982 2904 1019 2905 1018 2906 1006 2907 1005 2908 994 2909 983 2910 982 2911 1018 2912 983 2913 1018 2914 1017 2915 1006 2916 994 2917 993 2918 1007 2919 1006 2920 993 2921 983 2922 1017 2923 1016 2924 1008 2925 1007 2926 993 2927 984 2928 983 2929 1016 2930 1008 2931 993 2932 992 2933 984 2934 1016 2935 1015 2936 1009 2937 1008 2938 992 2939 984 2940 1015 2941 1014 2942 1010 2943 1009 2944 992 2945 985 2946 984 2947 1014 2948 1010 2949 992 2950 991 2951 985 2952 1014 2953 1013 2954 1011 2955 1010 2956 991 2957 985 2958 1013 2959 1012 2960 1012 2961 1011 2962 991 2963 985 2964 1012 2965 991 2966 986 2967 985 2968 991 2969 986 2970 991 2971 990 2972 987 2973 986 2974 990 2975 987 2976 990 2977 989 2978 988 2979 987 2980 989 2981 1026 2982 1025 2983 1024 2984 1026 2985 1024 2986 1056 2987 1050 2988 1049 2989 1048 2990 1051 2991 1050 2992 1048 2993 1051 2994 1048 2995 1047 2996 1052 2997 1051 2998 1047 2999 1053 3000 1052 3001 1047 3002 1053 3003 1047 3004 1046 3005 1054 3006 1053 3007 1046 3008 1054 3009 1046 3010 1045 3011 1055 3012 1054 3013 1034 3014 1034 3015 1054 3016 1045 3017 1026 3018 1056 3019 1055 3020 1026 3021 1055 3022 1028 3023 1028 3024 1055 3025 1029 3026 1029 3027 1055 3028 1030 3029 1030 3030 1055 3031 1031 3032 1031 3033 1055 3034 1032 3035 1032 3036 1055 3037 1033 3038 1033 3039 1055 3040 1034 3041 1035 3042 1034 3043 1045 3044 1036 3045 1035 3046 1045 3047 1036 3048 1045 3049 1044 3050 1037 3051 1036 3052 1044 3053 1038 3054 1037 3055 1044 3056 1039 3057 1038 3058 1044 3059 1039 3060 1044 3061 1043 3062 1026 3063 1028 3064 1027 3065 1040 3066 1039 3067 1043 3068 1041 3069 1040 3070 1043 3071 1041 3072 1043 3073 1042 3074 1064 3075 1063 3076 1062 3077 1064 3078 1062 3079 1061 3080 1065 3081 1064 3082 1061 3083 1065 3084 1061 3085 1060 3086 1065 3087 1060 3088 1059 3089 1066 3090 1065 3091 1059 3092 1066 3093 1059 3094 1058 3095 1066 3096 1058 3097 1057 3098 1067 3099 1066 3100 1057 3101 1067 3102 1057 3103 1118 3104 1118 3105 1057 3106 1119 3107 1119 3108 1057 3109 1120 3110 1120 3111 1057 3112 1121 3113 1121 3114 1057 3115 1122 3116 1122 3117 1057 3118 1123 3119 1123 3120 1057 3121 1124 3122 1068 3123 1067 3124 1118 3125 1068 3126 1118 3127 1117 3128 1068 3129 1117 3130 1116 3131 1068 3132 1116 3133 1115 3134 1069 3135 1068 3136 1115 3137 1069 3138 1115 3139 1114 3140 1069 3141 1114 3142 1113 3143 1069 3144 1113 3145 1112 3146 1069 3147 1112 3148 1111 3149 1070 3150 1069 3151 1111 3152 1070 3153 1111 3154 1110 3155 1070 3156 1110 3157 1109 3158 1070 3159 1109 3160 1108 3161 1070 3162 1108 3163 1107 3164 1071 3165 1070 3166 1107 3167 1071 3168 1107 3169 1106 3170 1071 3171 1106 3172 1105 3173 1072 3174 1071 3175 1105 3176 1072 3177 1105 3178 1104 3179 1073 3180 1072 3181 1104 3182 1073 3183 1104 3184 1103 3185 1073 3186 1103 3187 1102 3188 1074 3189 1073 3190 1102 3191 1074 3192 1102 3193 1101 3194 1075 3195 1074 3196 1101 3197 1075 3198 1101 3199 1100 3200 1088 3201 1087 3202 1086 3203 1075 3204 1100 3205 1099 3206 1076 3207 1075 3208 1099 3209 1088 3210 1086 3211 1085 3212 1077 3213 1076 3214 1099 3215 1088 3216 1085 3217 1084 3218 1078 3219 1077 3220 1099 3221 1078 3222 1099 3223 1098 3224 1088 3225 1084 3226 1083 3227 1079 3228 1078 3229 1098 3230 1080 3231 1079 3232 1098 3233 1088 3234 1083 3235 1082 3236 1081 3237 1080 3238 1098 3239 1088 3240 1082 3241 1081 3242 1088 3243 1081 3244 1098 3245 1088 3246 1098 3247 1097 3248 1089 3249 1088 3250 1097 3251 1089 3252 1097 3253 1096 3254 1090 3255 1089 3256 1096 3257 1091 3258 1090 3259 1096 3260 1091 3261 1096 3262 1095 3263 1092 3264 1091 3265 1095 3266 1092 3267 1095 3268 1094 3269 1093 3270 1092 3271 1094 3272 1130 3273 1129 3274 1128 3275 1130 3276 1128 3277 1127 3278 1127 3279 1126 3280 1125 3281 1127 3282 1125 3283 1132 3284 1130 3285 1127 3286 1132 3287 1131 3288 1130 3289 1132 3290 1135 3291 1134 3292 1133 3293 1135 3294 1133 3295 1136 3296 1157 3297 1156 3298 1159 3299 1159 3300 1156 3301 1155 3302 1159 3303 1155 3304 1154 3305 1159 3306 1154 3307 1153 3308 1159 3309 1153 3310 1152 3311 1159 3312 1152 3313 1160 3314 1160 3315 1152 3316 1161 3317 1161 3318 1152 3319 1151 3320 1157 3321 1159 3322 1178 3323 1162 3324 1161 3325 1151 3326 1163 3327 1162 3328 1151 3329 1163 3330 1151 3331 1150 3332 1164 3333 1163 3334 1150 3335 1165 3336 1164 3337 1150 3338 1165 3339 1150 3340 1149 3341 1166 3342 1165 3343 1149 3344 1167 3345 1166 3346 1149 3347 1167 3348 1149 3349 1148 3350 1168 3351 1167 3352 1148 3353 1168 3354 1148 3355 1147 3356 1169 3357 1168 3358 1147 3359 1170 3360 1169 3361 1147 3362 1170 3363 1147 3364 1146 3365 1157 3366 1178 3367 1177 3368 1171 3369 1170 3370 1146 3371 1157 3372 1177 3373 1137 3374 1137 3375 1177 3376 1176 3377 1137 3378 1176 3379 1175 3380 1172 3381 1171 3382 1146 3383 1137 3384 1175 3385 1174 3386 1137 3387 1174 3388 1173 3389 1137 3390 1173 3391 1172 3392 1137 3393 1172 3394 1146 3395 1137 3396 1146 3397 1145 3398 1137 3399 1145 3400 1144 3401 1157 3402 1137 3403 1158 3404 1138 3405 1137 3406 1144 3407 1139 3408 1138 3409 1144 3410 1140 3411 1139 3412 1144 3413 1140 3414 1144 3415 1143 3416 1141 3417 1140 3418 1143 3419 1142 3420 1141 3421 1143 3422 1199 3423 1198 3424 1201 3425 1201 3426 1198 3427 1197 3428 1201 3429 1197 3430 1196 3431 1201 3432 1196 3433 1195 3434 1201 3435 1195 3436 1194 3437 1201 3438 1194 3439 1202 3440 1202 3441 1194 3442 1203 3443 1203 3444 1194 3445 1193 3446 1199 3447 1201 3448 1220 3449 1204 3450 1203 3451 1193 3452 1205 3453 1204 3454 1193 3455 1205 3456 1193 3457 1192 3458 1206 3459 1205 3460 1192 3461 1207 3462 1206 3463 1192 3464 1207 3465 1192 3466 1191 3467 1208 3468 1207 3469 1191 3470 1209 3471 1208 3472 1191 3473 1209 3474 1191 3475 1190 3476 1210 3477 1209 3478 1190 3479 1210 3480 1190 3481 1189 3482 1211 3483 1210 3484 1189 3485 1212 3486 1211 3487 1189 3488 1212 3489 1189 3490 1188 3491 1199 3492 1220 3493 1219 3494 1213 3495 1212 3496 1188 3497 1199 3498 1219 3499 1179 3500 1179 3501 1219 3502 1218 3503 1179 3504 1218 3505 1217 3506 1214 3507 1213 3508 1188 3509 1179 3510 1217 3511 1216 3512 1179 3513 1216 3514 1215 3515 1179 3516 1215 3517 1214 3518 1179 3519 1214 3520 1188 3521 1179 3522 1188 3523 1187 3524 1179 3525 1187 3526 1186 3527 1199 3528 1179 3529 1200 3530 1180 3531 1179 3532 1186 3533 1181 3534 1180 3535 1186 3536 1182 3537 1181 3538 1186 3539 1182 3540 1186 3541 1185 3542 1183 3543 1182 3544 1185 3545 1184 3546 1183 3547 1185 3548 1241 3549 1240 3550 1239 3551 1242 3552 1241 3553 1239 3554 1242 3555 1239 3556 1238 3557 1243 3558 1242 3559 1238 3560 1244 3561 1243 3562 1238 3563 1244 3564 1238 3565 1237 3566 1245 3567 1244 3568 1237 3569 1245 3570 1237 3571 1236 3572 1246 3573 1245 3574 1236 3575 1247 3576 1246 3577 1248 3578 1248 3579 1246 3580 1249 3581 1249 3582 1246 3583 1250 3584 1250 3585 1246 3586 1251 3587 1251 3588 1246 3589 1252 3590 1252 3591 1246 3592 1253 3593 1253 3594 1246 3595 1236 3596 1253 3597 1236 3598 1254 3599 1254 3600 1236 3601 1235 3602 1255 3603 1254 3604 1235 3605 1256 3606 1255 3607 1235 3608 1256 3609 1235 3610 1234 3611 1257 3612 1256 3613 1234 3614 1258 3615 1257 3616 1234 3617 1259 3618 1258 3619 1234 3620 1259 3621 1234 3622 1233 3623 1260 3624 1259 3625 1233 3626 1261 3627 1260 3628 1310 3629 1310 3630 1260 3631 1233 3632 1262 3633 1261 3634 1310 3635 1263 3636 1262 3637 1310 3638 1263 3639 1310 3640 1309 3641 1292 3642 1310 3643 1233 3644 1264 3645 1263 3646 1309 3647 1264 3648 1309 3649 1308 3650 1265 3651 1264 3652 1308 3653 1265 3654 1308 3655 1307 3656 1265 3657 1307 3658 1306 3659 1266 3660 1265 3661 1306 3662 1266 3663 1306 3664 1305 3665 1266 3666 1305 3667 1304 3668 1267 3669 1266 3670 1304 3671 1267 3672 1304 3673 1303 3674 1268 3675 1267 3676 1303 3677 1268 3678 1303 3679 1302 3680 1293 3681 1292 3682 1233 3683 1268 3684 1302 3685 1301 3686 1294 3687 1293 3688 1233 3689 1222 3690 1221 3691 1291 3692 1294 3693 1233 3694 1232 3695 1223 3696 1222 3697 1291 3698 1269 3699 1268 3700 1301 3701 1269 3702 1301 3703 1300 3704 1294 3705 1232 3706 1231 3707 1295 3708 1294 3709 1231 3710 1224 3711 1223 3712 1291 3713 1295 3714 1231 3715 1230 3716 1296 3717 1295 3718 1230 3719 1225 3720 1224 3721 1291 3722 1269 3723 1300 3724 1299 3725 1296 3726 1230 3727 1229 3728 1226 3729 1225 3730 1291 3731 1297 3732 1296 3733 1229 3734 1297 3735 1229 3736 1228 3737 1227 3738 1226 3739 1291 3740 1297 3741 1228 3742 1227 3743 1269 3744 1299 3745 1298 3746 1297 3747 1227 3748 1291 3749 1298 3750 1297 3751 1291 3752 1269 3753 1298 3754 1279 3755 1279 3756 1298 3757 1291 3758 1270 3759 1269 3760 1279 3761 1270 3762 1279 3763 1278 3764 1280 3765 1279 3766 1291 3767 1280 3768 1291 3769 1290 3770 1271 3771 1270 3772 1278 3773 1271 3774 1278 3775 1277 3776 1281 3777 1280 3778 1290 3779 1281 3780 1290 3781 1289 3782 1271 3783 1277 3784 1276 3785 1282 3786 1281 3787 1289 3788 1272 3789 1271 3790 1276 3791 1282 3792 1289 3793 1288 3794 1272 3795 1276 3796 1275 3797 1283 3798 1282 3799 1288 3800 1283 3801 1288 3802 1287 3803 1272 3804 1275 3805 1274 3806 1284 3807 1283 3808 1287 3809 1273 3810 1272 3811 1274 3812 1284 3813 1287 3814 1286 3815 1285 3816 1284 3817 1286 3818 1312 3819 1311 3820 1334 3821 1312 3822 1334 3823 1333 3824 1313 3825 1312 3826 1333 3827 1313 3828 1333 3829 1332 3830 1314 3831 1313 3832 1332 3833 1314 3834 1332 3835 1335 3836 1335 3837 1332 3838 1336 3839 1336 3840 1332 3841 1331 3842 1315 3843 1314 3844 1358 3845 1358 3846 1314 3847 1335 3848 1315 3849 1358 3850 1357 3851 1337 3852 1336 3853 1331 3854 1315 3855 1357 3856 1356 3857 1338 3858 1337 3859 1331 3860 1338 3861 1331 3862 1330 3863 1316 3864 1315 3865 1356 3866 1316 3867 1356 3868 1355 3869 1339 3870 1338 3871 1330 3872 1316 3873 1355 3874 1354 3875 1340 3876 1339 3877 1330 3878 1340 3879 1330 3880 1329 3881 1317 3882 1316 3883 1354 3884 1317 3885 1354 3886 1353 3887 1341 3888 1340 3889 1329 3890 1318 3891 1317 3892 1353 3893 1318 3894 1353 3895 1352 3896 1341 3897 1329 3898 1328 3899 1342 3900 1341 3901 1328 3902 1318 3903 1352 3904 1351 3905 1343 3906 1342 3907 1328 3908 1319 3909 1318 3910 1351 3911 1343 3912 1328 3913 1327 3914 1319 3915 1351 3916 1350 3917 1344 3918 1343 3919 1327 3920 1319 3921 1350 3922 1349 3923 1345 3924 1344 3925 1327 3926 1320 3927 1319 3928 1349 3929 1345 3930 1327 3931 1326 3932 1320 3933 1349 3934 1348 3935 1346 3936 1345 3937 1326 3938 1320 3939 1348 3940 1347 3941 1347 3942 1346 3943 1326 3944 1320 3945 1347 3946 1326 3947 1321 3948 1320 3949 1326 3950 1321 3951 1326 3952 1325 3953 1322 3954 1321 3955 1325 3956 1322 3957 1325 3958 1324 3959 1323 3960 1322 3961 1324 3962 1360 3963 1359 3964 1392 3965 1360 3966 1392 3967 1391 3968 1360 3969 1391 3970 1390 3971 1361 3972 1360 3973 1390 3974 1362 3975 1361 3976 1390 3977 1363 3978 1362 3979 1389 3980 1389 3981 1362 3982 1390 3983 1363 3984 1389 3985 1388 3986 1363 3987 1388 3988 1387 3989 1364 3990 1363 3991 1387 3992 1364 3993 1387 3994 1386 3995 1377 3996 1376 3997 1375 3998 1364 3999 1386 4000 1385 4001 1378 4002 1377 4003 1375 4004 1365 4005 1364 4006 1385 4007 1379 4008 1378 4009 1375 4010 1365 4011 1385 4012 1384 4013 1380 4014 1379 4015 1375 4016 1365 4017 1384 4018 1383 4019 1381 4020 1380 4021 1375 4022 1365 4023 1383 4024 1382 4025 1382 4026 1381 4027 1375 4028 1365 4029 1382 4030 1375 4031 1366 4032 1365 4033 1375 4034 1367 4035 1366 4036 1375 4037 1367 4038 1375 4039 1374 4040 1367 4041 1374 4042 1373 4043 1368 4044 1367 4045 1373 4046 1368 4047 1373 4048 1372 4049 1368 4050 1372 4051 1371 4052 1369 4053 1368 4054 1371 4055 1369 4056 1371 4057 1370 4058 1413 4059 1412 4060 1411 4061 1413 4062 1411 4063 1410 4064 1414 4065 1413 4066 1410 4067 1414 4068 1410 4069 1409 4070 1415 4071 1414 4072 1409 4073 1415 4074 1409 4075 1437 4076 1437 4077 1409 4078 1438 4079 1438 4080 1409 4081 1408 4082 1416 4083 1415 4084 1436 4085 1436 4086 1415 4087 1437 4088 1416 4089 1436 4090 1435 4091 1439 4092 1438 4093 1408 4094 1416 4095 1435 4096 1434 4097 1440 4098 1439 4099 1408 4100 1416 4101 1434 4102 1433 4103 1441 4104 1440 4105 1408 4106 1417 4107 1416 4108 1433 4109 1441 4110 1408 4111 1407 4112 1417 4113 1433 4114 1432 4115 1442 4116 1441 4117 1407 4118 1417 4119 1432 4120 1431 4121 1443 4122 1442 4123 1407 4124 1418 4125 1417 4126 1431 4127 1443 4128 1407 4129 1406 4130 1418 4131 1431 4132 1443 4133 1418 4134 1443 4135 1406 4136 1419 4137 1418 4138 1405 4139 1405 4140 1418 4141 1406 4142 1419 4143 1405 4144 1404 4145 1419 4146 1404 4147 1403 4148 1420 4149 1419 4150 1403 4151 1420 4152 1403 4153 1402 4154 1394 4155 1393 4156 1430 4157 1395 4158 1394 4159 1430 4160 1421 4161 1420 4162 1402 4163 1421 4164 1402 4165 1401 4166 1396 4167 1395 4168 1430 4169 1421 4170 1401 4171 1400 4172 1397 4173 1396 4174 1430 4175 1398 4176 1397 4177 1430 4178 1421 4179 1400 4180 1399 4181 1399 4182 1398 4183 1430 4184 1421 4185 1399 4186 1430 4187 1422 4188 1421 4189 1430 4190 1422 4191 1430 4192 1429 4193 1422 4194 1429 4195 1428 4196 1423 4197 1422 4198 1428 4199 1423 4200 1428 4201 1427 4202 1423 4203 1427 4204 1426 4205 1424 4206 1423 4207 1426 4208 1424 4209 1426 4210 1425 4211 1451 4212 1450 4213 1449 4214 1451 4215 1449 4216 1448 4217 1452 4218 1451 4219 1448 4220 1452 4221 1448 4222 1447 4223 1452 4224 1447 4225 1446 4226 1453 4227 1452 4228 1446 4229 1453 4230 1446 4231 1445 4232 1453 4233 1445 4234 1444 4235 1454 4236 1453 4237 1444 4238 1454 4239 1444 4240 1505 4241 1505 4242 1444 4243 1506 4244 1506 4245 1444 4246 1507 4247 1507 4248 1444 4249 1508 4250 1508 4251 1444 4252 1509 4253 1509 4254 1444 4255 1510 4256 1510 4257 1444 4258 1511 4259 1455 4260 1454 4261 1505 4262 1455 4263 1505 4264 1504 4265 1455 4266 1504 4267 1503 4268 1455 4269 1503 4270 1502 4271 1456 4272 1455 4273 1502 4274 1456 4275 1502 4276 1501 4277 1456 4278 1501 4279 1500 4280 1456 4281 1500 4282 1499 4283 1456 4284 1499 4285 1498 4286 1457 4287 1456 4288 1498 4289 1457 4290 1498 4291 1497 4292 1457 4293 1497 4294 1496 4295 1457 4296 1496 4297 1495 4298 1457 4299 1495 4300 1494 4301 1458 4302 1457 4303 1494 4304 1458 4305 1494 4306 1493 4307 1458 4308 1493 4309 1492 4310 1459 4311 1458 4312 1492 4313 1459 4314 1492 4315 1491 4316 1460 4317 1459 4318 1491 4319 1460 4320 1491 4321 1490 4322 1460 4323 1490 4324 1489 4325 1461 4326 1460 4327 1489 4328 1461 4329 1489 4330 1488 4331 1462 4332 1461 4333 1488 4334 1462 4335 1488 4336 1487 4337 1475 4338 1474 4339 1473 4340 1462 4341 1487 4342 1486 4343 1463 4344 1462 4345 1486 4346 1475 4347 1473 4348 1472 4349 1464 4350 1463 4351 1486 4352 1475 4353 1472 4354 1471 4355 1465 4356 1464 4357 1486 4358 1465 4359 1486 4360 1485 4361 1475 4362 1471 4363 1470 4364 1466 4365 1465 4366 1485 4367 1467 4368 1466 4369 1485 4370 1475 4371 1470 4372 1469 4373 1468 4374 1467 4375 1485 4376 1475 4377 1469 4378 1468 4379 1475 4380 1468 4381 1485 4382 1475 4383 1485 4384 1484 4385 1476 4386 1475 4387 1484 4388 1476 4389 1484 4390 1483 4391 1477 4392 1476 4393 1483 4394 1478 4395 1477 4396 1483 4397 1478 4398 1483 4399 1482 4400 1479 4401 1478 4402 1482 4403 1479 4404 1482 4405 1481 4406 1480 4407 1479 4408 1481 4409 1530 4410 1529 4411 1528 4412 1530 4413 1528 4414 1527 4415 1515 4416 1514 4417 1513 4418 1515 4419 1513 4420 1512 4421 1531 4422 1530 4423 1527 4424 1531 4425 1527 4426 1526 4427 1531 4428 1526 4429 1525 4430 1516 4431 1515 4432 1512 4433 1532 4434 1531 4435 1525 4436 1532 4437 1525 4438 1524 4439 1517 4440 1516 4441 1512 4442 1518 4443 1517 4444 1542 4445 1542 4446 1517 4447 1512 4448 1532 4449 1524 4450 1523 4451 1519 4452 1518 4453 1542 4454 1532 4455 1523 4456 1522 4457 1533 4458 1532 4459 1522 4460 1520 4461 1519 4462 1542 4463 1533 4464 1522 4465 1521 4466 1521 4467 1520 4468 1542 4469 1533 4470 1521 4471 1542 4472 1533 4473 1542 4474 1541 4475 1543 4476 1542 4477 1512 4478 1533 4479 1541 4480 1540 4481 1534 4482 1533 4483 1540 4484 1534 4485 1540 4486 1539 4487 1535 4488 1534 4489 1539 4490 1535 4491 1539 4492 1538 4493 1535 4494 1538 4495 1537 4496 1536 4497 1535 4498 1537 4499 1545 4500 1544 4501 1567 4502 1545 4503 1567 4504 1566 4505 1546 4506 1545 4507 1566 4508 1546 4509 1566 4510 1565 4511 1547 4512 1546 4513 1565 4514 1547 4515 1565 4516 1568 4517 1568 4518 1565 4519 1569 4520 1569 4521 1565 4522 1564 4523 1548 4524 1547 4525 1591 4526 1591 4527 1547 4528 1568 4529 1548 4530 1591 4531 1590 4532 1570 4533 1569 4534 1564 4535 1548 4536 1590 4537 1589 4538 1571 4539 1570 4540 1564 4541 1571 4542 1564 4543 1563 4544 1549 4545 1548 4546 1589 4547 1549 4548 1589 4549 1588 4550 1572 4551 1571 4552 1563 4553 1549 4554 1588 4555 1587 4556 1573 4557 1572 4558 1563 4559 1573 4560 1563 4561 1562 4562 1550 4563 1549 4564 1587 4565 1550 4566 1587 4567 1586 4568 1574 4569 1573 4570 1562 4571 1551 4572 1550 4573 1586 4574 1551 4575 1586 4576 1585 4577 1574 4578 1562 4579 1561 4580 1575 4581 1574 4582 1561 4583 1551 4584 1585 4585 1584 4586 1576 4587 1575 4588 1561 4589 1552 4590 1551 4591 1584 4592 1576 4593 1561 4594 1560 4595 1552 4596 1584 4597 1583 4598 1577 4599 1576 4600 1560 4601 1552 4602 1583 4603 1582 4604 1578 4605 1577 4606 1560 4607 1553 4608 1552 4609 1582 4610 1578 4611 1560 4612 1559 4613 1553 4614 1582 4615 1581 4616 1579 4617 1578 4618 1559 4619 1553 4620 1581 4621 1580 4622 1580 4623 1579 4624 1559 4625 1553 4626 1580 4627 1559 4628 1554 4629 1553 4630 1559 4631 1554 4632 1559 4633 1558 4634 1555 4635 1554 4636 1558 4637 1555 4638 1558 4639 1557 4640 1556 4641 1555 4642 1557 4643 1644 4644 1643 4645 1642 4646 1632 4647 1631 4648 1630 4649 1645 4650 1644 4651 1642 4652 1645 4653 1642 4654 1641 4655 1633 4656 1632 4657 1630 4658 1633 4659 1630 4660 1629 4661 1646 4662 1645 4663 1641 4664 1593 4665 1592 4666 1650 4667 1593 4668 1650 4669 1649 4670 1646 4671 1641 4672 1640 4673 1634 4674 1633 4675 1629 4676 1647 4677 1646 4678 1640 4679 1647 4680 1640 4681 1639 4682 1634 4683 1629 4684 1628 4685 1635 4686 1634 4687 1628 4688 1648 4689 1647 4690 1639 4691 1648 4692 1639 4693 1638 4694 1636 4695 1635 4696 1628 4697 1649 4698 1648 4699 1638 4700 1636 4701 1628 4702 1627 4703 1649 4704 1638 4705 1637 4706 1637 4707 1636 4708 1616 4709 1616 4710 1636 4711 1627 4712 1593 4713 1649 4714 1595 4715 1595 4716 1649 4717 1596 4718 1596 4719 1649 4720 1597 4721 1597 4722 1649 4723 1598 4724 1598 4725 1649 4726 1599 4727 1599 4728 1649 4729 1600 4730 1600 4731 1649 4732 1601 4733 1601 4734 1649 4735 1637 4736 1602 4737 1601 4738 1637 4739 1637 4740 1616 4741 1615 4742 1617 4743 1616 4744 1627 4745 1637 4746 1615 4747 1614 4748 1603 4749 1602 4750 1637 4751 1618 4752 1617 4753 1627 4754 1603 4755 1637 4756 1614 4757 1603 4758 1614 4759 1613 4760 1618 4761 1627 4762 1626 4763 1604 4764 1603 4765 1613 4766 1619 4767 1618 4768 1626 4769 1604 4770 1613 4771 1612 4772 1605 4773 1604 4774 1612 4775 1620 4776 1619 4777 1626 4778 1605 4779 1612 4780 1611 4781 1605 4782 1611 4783 1610 4784 1606 4785 1605 4786 1610 4787 1621 4788 1620 4789 1626 4790 1621 4791 1626 4792 1625 4793 1593 4794 1595 4795 1594 4796 1606 4797 1610 4798 1609 4799 1607 4800 1606 4801 1609 4802 1622 4803 1621 4804 1625 4805 1622 4806 1625 4807 1624 4808 1608 4809 1607 4810 1609 4811 1623 4812 1622 4813 1624 4814 1652 4815 1651 4816 1684 4817 1652 4818 1684 4819 1683 4820 1652 4821 1683 4822 1682 4823 1653 4824 1652 4825 1682 4826 1654 4827 1653 4828 1682 4829 1655 4830 1654 4831 1681 4832 1681 4833 1654 4834 1682 4835 1655 4836 1681 4837 1680 4838 1655 4839 1680 4840 1679 4841 1656 4842 1655 4843 1679 4844 1656 4845 1679 4846 1678 4847 1669 4848 1668 4849 1667 4850 1656 4851 1678 4852 1677 4853 1670 4854 1669 4855 1667 4856 1657 4857 1656 4858 1677 4859 1671 4860 1670 4861 1667 4862 1657 4863 1677 4864 1676 4865 1672 4866 1671 4867 1667 4868 1657 4869 1676 4870 1675 4871 1673 4872 1672 4873 1667 4874 1657 4875 1675 4876 1674 4877 1674 4878 1673 4879 1667 4880 1657 4881 1674 4882 1667 4883 1658 4884 1657 4885 1667 4886 1659 4887 1658 4888 1667 4889 1659 4890 1667 4891 1666 4892 1659 4893 1666 4894 1665 4895 1660 4896 1659 4897 1665 4898 1660 4899 1665 4900 1664 4901 1660 4902 1664 4903 1663 4904 1661 4905 1660 4906 1663 4907 1661 4908 1663 4909 1662 4910 1688 4911 1687 4912 1686 4913 1688 4914 1686 4915 1685 4916 1689 4917 1688 4918 1685 4919 1689 4920 1685 4921 1720 4922 1690 4923 1689 4924 1720 4925 1691 4926 1690 4927 1717 4928 1717 4929 1690 4930 1718 4931 1718 4932 1690 4933 1719 4934 1719 4935 1690 4936 1720 4937 1692 4938 1691 4939 1717 4940 1693 4941 1692 4942 1714 4943 1714 4944 1692 4945 1715 4946 1715 4947 1692 4948 1716 4949 1716 4950 1692 4951 1717 4952 1694 4953 1693 4954 1713 4955 1713 4956 1693 4957 1714 4958 1694 4959 1713 4960 1712 4961 1694 4962 1712 4963 1711 4964 1695 4965 1694 4966 1711 4967 1695 4968 1711 4969 1710 4970 1696 4971 1695 4972 1710 4973 1696 4974 1710 4975 1709 4976 1696 4977 1709 4978 1708 4979 1697 4980 1696 4981 1708 4982 1697 4983 1708 4984 1707 4985 1698 4986 1697 4987 1707 4988 1700 4989 1699 4990 1698 4991 1700 4992 1698 4993 1707 4994 1700 4995 1707 4996 1706 4997 1700 4998 1706 4999 1705 5000 1701 5001 1700 5002 1705 5003 1702 5004 1701 5005 1704 5006 1704 5007 1701 5008 1705 5009 1702 5010 1704 5011 1703 5012 1741 5013 1740 5014 1739 5015 1741 5016 1739 5017 1738 5018 1742 5019 1741 5020 1738 5021 1742 5022 1738 5023 1737 5024 1743 5025 1742 5026 1737 5027 1743 5028 1737 5029 1765 5030 1765 5031 1737 5032 1766 5033 1766 5034 1737 5035 1736 5036 1744 5037 1743 5038 1764 5039 1764 5040 1743 5041 1765 5042 1744 5043 1764 5044 1763 5045 1767 5046 1766 5047 1736 5048 1744 5049 1763 5050 1762 5051 1768 5052 1767 5053 1736 5054 1744 5055 1762 5056 1761 5057 1769 5058 1768 5059 1736 5060 1745 5061 1744 5062 1761 5063 1769 5064 1736 5065 1735 5066 1745 5067 1761 5068 1760 5069 1770 5070 1769 5071 1735 5072 1745 5073 1760 5074 1759 5075 1771 5076 1770 5077 1735 5078 1746 5079 1745 5080 1759 5081 1771 5082 1735 5083 1734 5084 1746 5085 1759 5086 1771 5087 1746 5088 1771 5089 1734 5090 1747 5091 1746 5092 1733 5093 1733 5094 1746 5095 1734 5096 1747 5097 1733 5098 1732 5099 1747 5100 1732 5101 1731 5102 1748 5103 1747 5104 1731 5105 1748 5106 1731 5107 1730 5108 1722 5109 1721 5110 1758 5111 1723 5112 1722 5113 1758 5114 1749 5115 1748 5116 1730 5117 1749 5118 1730 5119 1729 5120 1724 5121 1723 5122 1758 5123 1749 5124 1729 5125 1728 5126 1725 5127 1724 5128 1758 5129 1726 5130 1725 5131 1758 5132 1749 5133 1728 5134 1727 5135 1727 5136 1726 5137 1758 5138 1749 5139 1727 5140 1758 5141 1750 5142 1749 5143 1758 5144 1750 5145 1758 5146 1757 5147 1750 5148 1757 5149 1756 5150 1751 5151 1750 5152 1756 5153 1751 5154 1756 5155 1755 5156 1751 5157 1755 5158 1754 5159 1752 5160 1751 5161 1754 5162 1752 5163 1754 5164 1753 5165 1774 5166 1773 5167 1772 5168 1774 5169 1772 5170 1775 5171 1789 5172 1788 5173 1787 5174 1790 5175 1789 5176 1787 5177 1790 5178 1787 5179 1786 5180 1791 5181 1790 5182 1786 5183 1791 5184 1786 5185 1785 5186 1792 5187 1791 5188 1785 5189 1792 5190 1785 5191 1784 5192 1793 5193 1792 5194 1784 5195 1794 5196 1793 5197 1784 5198 1794 5199 1784 5200 1783 5201 1795 5202 1794 5203 1783 5204 1795 5205 1783 5206 1782 5207 1796 5208 1795 5209 1782 5210 1797 5211 1796 5212 1782 5213 1797 5214 1782 5215 1781 5216 1798 5217 1797 5218 1781 5219 1799 5220 1798 5221 1800 5222 1800 5223 1798 5224 1781 5225 1801 5226 1800 5227 1781 5228 1801 5229 1781 5230 1780 5231 1802 5232 1801 5233 1780 5234 1803 5235 1802 5236 1780 5237 1803 5238 1780 5239 1779 5240 1804 5241 1803 5242 1779 5243 1804 5244 1779 5245 1778 5246 1805 5247 1804 5248 1778 5249 1805 5250 1778 5251 1777 5252 1806 5253 1805 5254 1777 5255 1776 5256 1806 5257 1777 5258 1859 5259 1858 5260 1857 5261 1847 5262 1846 5263 1845 5264 1860 5265 1859 5266 1857 5267 1860 5268 1857 5269 1856 5270 1848 5271 1847 5272 1845 5273 1848 5274 1845 5275 1844 5276 1861 5277 1860 5278 1856 5279 1808 5280 1807 5281 1865 5282 1808 5283 1865 5284 1864 5285 1861 5286 1856 5287 1855 5288 1849 5289 1848 5290 1844 5291 1862 5292 1861 5293 1855 5294 1862 5295 1855 5296 1854 5297 1849 5298 1844 5299 1843 5300 1850 5301 1849 5302 1843 5303 1863 5304 1862 5305 1854 5306 1863 5307 1854 5308 1853 5309 1851 5310 1850 5311 1843 5312 1864 5313 1863 5314 1853 5315 1851 5316 1843 5317 1842 5318 1864 5319 1853 5320 1852 5321 1852 5322 1851 5323 1831 5324 1831 5325 1851 5326 1842 5327 1808 5328 1864 5329 1810 5330 1810 5331 1864 5332 1811 5333 1811 5334 1864 5335 1812 5336 1812 5337 1864 5338 1813 5339 1813 5340 1864 5341 1814 5342 1814 5343 1864 5344 1815 5345 1815 5346 1864 5347 1816 5348 1816 5349 1864 5350 1852 5351 1817 5352 1816 5353 1852 5354 1852 5355 1831 5356 1830 5357 1832 5358 1831 5359 1842 5360 1852 5361 1830 5362 1829 5363 1818 5364 1817 5365 1852 5366 1833 5367 1832 5368 1842 5369 1818 5370 1852 5371 1829 5372 1818 5373 1829 5374 1828 5375 1833 5376 1842 5377 1841 5378 1819 5379 1818 5380 1828 5381 1834 5382 1833 5383 1841 5384 1819 5385 1828 5386 1827 5387 1820 5388 1819 5389 1827 5390 1835 5391 1834 5392 1841 5393 1820 5394 1827 5395 1826 5396 1820 5397 1826 5398 1825 5399 1821 5400 1820 5401 1825 5402 1836 5403 1835 5404 1841 5405 1836 5406 1841 5407 1840 5408 1808 5409 1810 5410 1809 5411 1821 5412 1825 5413 1824 5414 1822 5415 1821 5416 1824 5417 1837 5418 1836 5419 1840 5420 1837 5421 1840 5422 1839 5423 1823 5424 1822 5425 1824 5426 1838 5427 1837 5428 1839 5429 1877 5430 1876 5431 1875 5432 1878 5433 1877 5434 1875 5435 1878 5436 1875 5437 1874 5438 1879 5439 1878 5440 1874 5441 1879 5442 1874 5443 1873 5444 1880 5445 1879 5446 1873 5447 1880 5448 1873 5449 1872 5450 1881 5451 1880 5452 1872 5453 1881 5454 1872 5455 1871 5456 1882 5457 1881 5458 1871 5459 1882 5460 1871 5461 1870 5462 1883 5463 1882 5464 1870 5465 1883 5466 1870 5467 1893 5468 1884 5469 1883 5470 1893 5471 1884 5472 1893 5473 1892 5474 1885 5475 1884 5476 1892 5477 1885 5478 1892 5479 1891 5480 1886 5481 1885 5482 1891 5483 1886 5484 1891 5485 1890 5486 1887 5487 1886 5488 1890 5489 1887 5490 1890 5491 1889 5492 1888 5493 1887 5494 1889 5495 1868 5496 1867 5497 1866 5498 1868 5499 1866 5500 1869 5501 1914 5502 1913 5503 1912 5504 1915 5505 1914 5506 1912 5507 1915 5508 1912 5509 1911 5510 1916 5511 1915 5512 1911 5513 1917 5514 1916 5515 1911 5516 1917 5517 1911 5518 1910 5519 1918 5520 1917 5521 1910 5522 1918 5523 1910 5524 1909 5525 1919 5526 1918 5527 1909 5528 1920 5529 1919 5530 1921 5531 1921 5532 1919 5533 1922 5534 1922 5535 1919 5536 1923 5537 1923 5538 1919 5539 1924 5540 1924 5541 1919 5542 1925 5543 1925 5544 1919 5545 1926 5546 1926 5547 1919 5548 1909 5549 1926 5550 1909 5551 1927 5552 1927 5553 1909 5554 1908 5555 1928 5556 1927 5557 1908 5558 1929 5559 1928 5560 1908 5561 1929 5562 1908 5563 1907 5564 1930 5565 1929 5566 1907 5567 1931 5568 1930 5569 1907 5570 1932 5571 1931 5572 1907 5573 1932 5574 1907 5575 1906 5576 1933 5577 1932 5578 1906 5579 1934 5580 1933 5581 1983 5582 1983 5583 1933 5584 1906 5585 1935 5586 1934 5587 1983 5588 1936 5589 1935 5590 1983 5591 1936 5592 1983 5593 1982 5594 1965 5595 1983 5596 1906 5597 1937 5598 1936 5599 1982 5600 1937 5601 1982 5602 1981 5603 1938 5604 1937 5605 1981 5606 1938 5607 1981 5608 1980 5609 1938 5610 1980 5611 1979 5612 1939 5613 1938 5614 1979 5615 1939 5616 1979 5617 1978 5618 1939 5619 1978 5620 1977 5621 1940 5622 1939 5623 1977 5624 1940 5625 1977 5626 1976 5627 1941 5628 1940 5629 1976 5630 1941 5631 1976 5632 1975 5633 1966 5634 1965 5635 1906 5636 1941 5637 1975 5638 1974 5639 1967 5640 1966 5641 1906 5642 1895 5643 1894 5644 1964 5645 1967 5646 1906 5647 1905 5648 1896 5649 1895 5650 1964 5651 1942 5652 1941 5653 1974 5654 1942 5655 1974 5656 1973 5657 1967 5658 1905 5659 1904 5660 1968 5661 1967 5662 1904 5663 1897 5664 1896 5665 1964 5666 1968 5667 1904 5668 1903 5669 1969 5670 1968 5671 1903 5672 1898 5673 1897 5674 1964 5675 1942 5676 1973 5677 1972 5678 1969 5679 1903 5680 1902 5681 1899 5682 1898 5683 1964 5684 1970 5685 1969 5686 1902 5687 1970 5688 1902 5689 1901 5690 1900 5691 1899 5692 1964 5693 1970 5694 1901 5695 1900 5696 1942 5697 1972 5698 1971 5699 1970 5700 1900 5701 1964 5702 1971 5703 1970 5704 1964 5705 1942 5706 1971 5707 1952 5708 1952 5709 1971 5710 1964 5711 1943 5712 1942 5713 1952 5714 1943 5715 1952 5716 1951 5717 1953 5718 1952 5719 1964 5720 1953 5721 1964 5722 1963 5723 1944 5724 1943 5725 1951 5726 1944 5727 1951 5728 1950 5729 1954 5730 1953 5731 1963 5732 1954 5733 1963 5734 1962 5735 1944 5736 1950 5737 1949 5738 1955 5739 1954 5740 1962 5741 1945 5742 1944 5743 1949 5744 1955 5745 1962 5746 1961 5747 1945 5748 1949 5749 1948 5750 1956 5751 1955 5752 1961 5753 1956 5754 1961 5755 1960 5756 1945 5757 1948 5758 1947 5759 1957 5760 1956 5761 1960 5762 1946 5763 1945 5764 1947 5765 1957 5766 1960 5767 1959 5768 1958 5769 1957 5770 1959 5771 2004 5772 2003 5773 2002 5774 2004 5775 2002 5776 2001 5777 2005 5778 2004 5779 2001 5780 2005 5781 2001 5782 2000 5783 2006 5784 2005 5785 2000 5786 2006 5787 2000 5788 2028 5789 2028 5790 2000 5791 2029 5792 2029 5793 2000 5794 1999 5795 2007 5796 2006 5797 2027 5798 2027 5799 2006 5800 2028 5801 2007 5802 2027 5803 2026 5804 2030 5805 2029 5806 1999 5807 2007 5808 2026 5809 2025 5810 2031 5811 2030 5812 1999 5813 2007 5814 2025 5815 2024 5816 2032 5817 2031 5818 1999 5819 2008 5820 2007 5821 2024 5822 2032 5823 1999 5824 1998 5825 2008 5826 2024 5827 2023 5828 2033 5829 2032 5830 1998 5831 2008 5832 2023 5833 2022 5834 2034 5835 2033 5836 1998 5837 2009 5838 2008 5839 2022 5840 2034 5841 1998 5842 1997 5843 2009 5844 2022 5845 2034 5846 2009 5847 2034 5848 1997 5849 2010 5850 2009 5851 1996 5852 1996 5853 2009 5854 1997 5855 2010 5856 1996 5857 1995 5858 2010 5859 1995 5860 1994 5861 2011 5862 2010 5863 1994 5864 2011 5865 1994 5866 1993 5867 1985 5868 1984 5869 2021 5870 1986 5871 1985 5872 2021 5873 2012 5874 2011 5875 1993 5876 2012 5877 1993 5878 1992 5879 1987 5880 1986 5881 2021 5882 2012 5883 1992 5884 1991 5885 1988 5886 1987 5887 2021 5888 1989 5889 1988 5890 2021 5891 2012 5892 1991 5893 1990 5894 1990 5895 1989 5896 2021 5897 2012 5898 1990 5899 2021 5900 2013 5901 2012 5902 2021 5903 2013 5904 2021 5905 2020 5906 2013 5907 2020 5908 2019 5909 2014 5910 2013 5911 2019 5912 2014 5913 2019 5914 2018 5915 2014 5916 2018 5917 2017 5918 2015 5919 2014 5920 2017 5921 2015 5922 2017 5923 2016 5924 2042 5925 2041 5926 2040 5927 2042 5928 2040 5929 2039 5930 2043 5931 2042 5932 2039 5933 2043 5934 2039 5935 2038 5936 2043 5937 2038 5938 2037 5939 2044 5940 2043 5941 2037 5942 2044 5943 2037 5944 2036 5945 2044 5946 2036 5947 2035 5948 2045 5949 2044 5950 2035 5951 2045 5952 2035 5953 2096 5954 2096 5955 2035 5956 2097 5957 2097 5958 2035 5959 2098 5960 2098 5961 2035 5962 2099 5963 2099 5964 2035 5965 2100 5966 2100 5967 2035 5968 2101 5969 2101 5970 2035 5971 2102 5972 2046 5973 2045 5974 2096 5975 2046 5976 2096 5977 2095 5978 2046 5979 2095 5980 2094 5981 2046 5982 2094 5983 2093 5984 2047 5985 2046 5986 2093 5987 2047 5988 2093 5989 2092 5990 2047 5991 2092 5992 2091 5993 2047 5994 2091 5995 2090 5996 2047 5997 2090 5998 2089 5999 2048 6000 2047 6001 2089 6002 2048 6003 2089 6004 2088 6005 2048 6006 2088 6007 2087 6008 2048 6009 2087 6010 2086 6011 2048 6012 2086 6013 2085 6014 2049 6015 2048 6016 2085 6017 2049 6018 2085 6019 2084 6020 2049 6021 2084 6022 2083 6023 2050 6024 2049 6025 2083 6026 2050 6027 2083 6028 2082 6029 2051 6030 2050 6031 2082 6032 2051 6033 2082 6034 2081 6035 2051 6036 2081 6037 2080 6038 2052 6039 2051 6040 2080 6041 2052 6042 2080 6043 2079 6044 2053 6045 2052 6046 2079 6047 2053 6048 2079 6049 2078 6050 2066 6051 2065 6052 2064 6053 2053 6054 2078 6055 2077 6056 2054 6057 2053 6058 2077 6059 2066 6060 2064 6061 2063 6062 2055 6063 2054 6064 2077 6065 2066 6066 2063 6067 2062 6068 2056 6069 2055 6070 2077 6071 2056 6072 2077 6073 2076 6074 2066 6075 2062 6076 2061 6077 2057 6078 2056 6079 2076 6080 2058 6081 2057 6082 2076 6083 2066 6084 2061 6085 2060 6086 2059 6087 2058 6088 2076 6089 2066 6090 2060 6091 2059 6092 2066 6093 2059 6094 2076 6095 2066 6096 2076 6097 2075 6098 2067 6099 2066 6100 2075 6101 2067 6102 2075 6103 2074 6104 2068 6105 2067 6106 2074 6107 2069 6108 2068 6109 2074 6110 2069 6111 2074 6112 2073 6113 2070 6114 2069 6115 2073 6116 2070 6117 2073 6118 2072 6119 2071 6120 2070 6121 2072 6122 2121 6123 2120 6124 2119 6125 2121 6126 2119 6127 2118 6128 2106 6129 2105 6130 2104 6131 2106 6132 2104 6133 2103 6134 2122 6135 2121 6136 2118 6137 2122 6138 2118 6139 2117 6140 2122 6141 2117 6142 2116 6143 2107 6144 2106 6145 2103 6146 2123 6147 2122 6148 2116 6149 2123 6150 2116 6151 2115 6152 2108 6153 2107 6154 2103 6155 2109 6156 2108 6157 2133 6158 2133 6159 2108 6160 2103 6161 2123 6162 2115 6163 2114 6164 2110 6165 2109 6166 2133 6167 2123 6168 2114 6169 2113 6170 2124 6171 2123 6172 2113 6173 2111 6174 2110 6175 2133 6176 2124 6177 2113 6178 2112 6179 2112 6180 2111 6181 2133 6182 2124 6183 2112 6184 2133 6185 2124 6186 2133 6187 2132 6188 2134 6189 2133 6190 2103 6191 2124 6192 2132 6193 2131 6194 2125 6195 2124 6196 2131 6197 2125 6198 2131 6199 2130 6200 2126 6201 2125 6202 2130 6203 2126 6204 2130 6205 2129 6206 2126 6207 2129 6208 2128 6209 2127 6210 2126 6211 2128 6212 2136 6213 2135 6214 2158 6215 2136 6216 2158 6217 2157 6218 2137 6219 2136 6220 2157 6221 2137 6222 2157 6223 2156 6224 2138 6225 2137 6226 2156 6227 2138 6228 2156 6229 2159 6230 2159 6231 2156 6232 2160 6233 2160 6234 2156 6235 2155 6236 2139 6237 2138 6238 2182 6239 2182 6240 2138 6241 2159 6242 2139 6243 2182 6244 2181 6245 2161 6246 2160 6247 2155 6248 2139 6249 2181 6250 2180 6251 2162 6252 2161 6253 2155 6254 2162 6255 2155 6256 2154 6257 2140 6258 2139 6259 2180 6260 2140 6261 2180 6262 2179 6263 2163 6264 2162 6265 2154 6266 2140 6267 2179 6268 2178 6269 2164 6270 2163 6271 2154 6272 2164 6273 2154 6274 2153 6275 2141 6276 2140 6277 2178 6278 2141 6279 2178 6280 2177 6281 2165 6282 2164 6283 2153 6284 2142 6285 2141 6286 2177 6287 2142 6288 2177 6289 2176 6290 2165 6291 2153 6292 2152 6293 2166 6294 2165 6295 2152 6296 2142 6297 2176 6298 2175 6299 2167 6300 2166 6301 2152 6302 2143 6303 2142 6304 2175 6305 2167 6306 2152 6307 2151 6308 2143 6309 2175 6310 2174 6311 2168 6312 2167 6313 2151 6314 2143 6315 2174 6316 2173 6317 2169 6318 2168 6319 2151 6320 2144 6321 2143 6322 2173 6323 2169 6324 2151 6325 2150 6326 2144 6327 2173 6328 2172 6329 2170 6330 2169 6331 2150 6332 2144 6333 2172 6334 2171 6335 2171 6336 2170 6337 2150 6338 2144 6339 2171 6340 2150 6341 2145 6342 2144 6343 2150 6344 2145 6345 2150 6346 2149 6347 2146 6348 2145 6349 2149 6350 2146 6351 2149 6352 2148 6353 2147 6354 2146 6355 2148 6356 2188 6357 2187 6358 2186 6359 2188 6360 2186 6361 2190 6362 2190 6363 2186 6364 2191 6365 2191 6366 2186 6367 2185 6368 2185 6369 2184 6370 2183 6371 2185 6372 2183 6373 2194 6374 2194 6375 2183 6376 2195 6377 2195 6378 2183 6379 2197 6380 2188 6381 2190 6382 2189 6383 2192 6384 2191 6385 2185 6386 2185 6387 2194 6388 2193 6389 2196 6390 2195 6391 2197 6392 2192 6393 2185 6394 2193 6395 2199 6396 2198 6397 2231 6398 2199 6399 2231 6400 2230 6401 2199 6402 2230 6403 2229 6404 2200 6405 2199 6406 2229 6407 2201 6408 2200 6409 2229 6410 2202 6411 2201 6412 2228 6413 2228 6414 2201 6415 2229 6416 2202 6417 2228 6418 2227 6419 2202 6420 2227 6421 2226 6422 2203 6423 2202 6424 2226 6425 2203 6426 2226 6427 2225 6428 2216 6429 2215 6430 2214 6431 2203 6432 2225 6433 2224 6434 2217 6435 2216 6436 2214 6437 2204 6438 2203 6439 2224 6440 2218 6441 2217 6442 2214 6443 2204 6444 2224 6445 2223 6446 2219 6447 2218 6448 2214 6449 2204 6450 2223 6451 2222 6452 2220 6453 2219 6454 2214 6455 2204 6456 2222 6457 2221 6458 2221 6459 2220 6460 2214 6461 2204 6462 2221 6463 2214 6464 2205 6465 2204 6466 2214 6467 2206 6468 2205 6469 2214 6470 2206 6471 2214 6472 2213 6473 2206 6474 2213 6475 2212 6476 2207 6477 2206 6478 2212 6479 2207 6480 2212 6481 2211 6482 2207 6483 2211 6484 2210 6485 2208 6486 2207 6487 2210 6488 2208 6489 2210 6490 2209 6491 2239 6492 2238 6493 2237 6494 2239 6495 2237 6496 2236 6497 2240 6498 2239 6499 2236 6500 2240 6501 2236 6502 2235 6503 2240 6504 2235 6505 2234 6506 2241 6507 2240 6508 2234 6509 2241 6510 2234 6511 2233 6512 2241 6513 2233 6514 2232 6515 2242 6516 2241 6517 2232 6518 2242 6519 2232 6520 2293 6521 2293 6522 2232 6523 2294 6524 2294 6525 2232 6526 2295 6527 2295 6528 2232 6529 2296 6530 2296 6531 2232 6532 2297 6533 2297 6534 2232 6535 2298 6536 2298 6537 2232 6538 2299 6539 2243 6540 2242 6541 2293 6542 2243 6543 2293 6544 2292 6545 2243 6546 2292 6547 2291 6548 2243 6549 2291 6550 2290 6551 2244 6552 2243 6553 2290 6554 2244 6555 2290 6556 2289 6557 2244 6558 2289 6559 2288 6560 2244 6561 2288 6562 2287 6563 2244 6564 2287 6565 2286 6566 2245 6567 2244 6568 2286 6569 2245 6570 2286 6571 2285 6572 2245 6573 2285 6574 2284 6575 2245 6576 2284 6577 2283 6578 2245 6579 2283 6580 2282 6581 2246 6582 2245 6583 2282 6584 2246 6585 2282 6586 2281 6587 2246 6588 2281 6589 2280 6590 2247 6591 2246 6592 2280 6593 2247 6594 2280 6595 2279 6596 2248 6597 2247 6598 2279 6599 2248 6600 2279 6601 2278 6602 2248 6603 2278 6604 2277 6605 2249 6606 2248 6607 2277 6608 2249 6609 2277 6610 2276 6611 2250 6612 2249 6613 2276 6614 2250 6615 2276 6616 2275 6617 2263 6618 2262 6619 2261 6620 2250 6621 2275 6622 2274 6623 2251 6624 2250 6625 2274 6626 2263 6627 2261 6628 2260 6629 2252 6630 2251 6631 2274 6632 2263 6633 2260 6634 2259 6635 2253 6636 2252 6637 2274 6638 2253 6639 2274 6640 2273 6641 2263 6642 2259 6643 2258 6644 2254 6645 2253 6646 2273 6647 2255 6648 2254 6649 2273 6650 2263 6651 2258 6652 2257 6653 2256 6654 2255 6655 2273 6656 2263 6657 2257 6658 2256 6659 2263 6660 2256 6661 2273 6662 2263 6663 2273 6664 2272 6665 2264 6666 2263 6667 2272 6668 2264 6669 2272 6670 2271 6671 2265 6672 2264 6673 2271 6674 2266 6675 2265 6676 2271 6677 2266 6678 2271 6679 2270 6680 2267 6681 2266 6682 2270 6683 2267 6684 2270 6685 2269 6686 2268 6687 2267 6688 2269 6689 2320 6690 2319 6691 2318 6692 2320 6693 2318 6694 2317 6695 2321 6696 2320 6697 2317 6698 2321 6699 2317 6700 2316 6701 2322 6702 2321 6703 2316 6704 2322 6705 2316 6706 2344 6707 2344 6708 2316 6709 2345 6710 2345 6711 2316 6712 2315 6713 2323 6714 2322 6715 2343 6716 2343 6717 2322 6718 2344 6719 2323 6720 2343 6721 2342 6722 2346 6723 2345 6724 2315 6725 2323 6726 2342 6727 2341 6728 2347 6729 2346 6730 2315 6731 2323 6732 2341 6733 2340 6734 2348 6735 2347 6736 2315 6737 2324 6738 2323 6739 2340 6740 2348 6741 2315 6742 2314 6743 2324 6744 2340 6745 2339 6746 2349 6747 2348 6748 2314 6749 2324 6750 2339 6751 2338 6752 2350 6753 2349 6754 2314 6755 2325 6756 2324 6757 2338 6758 2350 6759 2314 6760 2313 6761 2325 6762 2338 6763 2350 6764 2325 6765 2350 6766 2313 6767 2326 6768 2325 6769 2312 6770 2312 6771 2325 6772 2313 6773 2326 6774 2312 6775 2311 6776 2326 6777 2311 6778 2310 6779 2327 6780 2326 6781 2310 6782 2327 6783 2310 6784 2309 6785 2301 6786 2300 6787 2337 6788 2302 6789 2301 6790 2337 6791 2328 6792 2327 6793 2309 6794 2328 6795 2309 6796 2308 6797 2303 6798 2302 6799 2337 6800 2328 6801 2308 6802 2307 6803 2304 6804 2303 6805 2337 6806 2305 6807 2304 6808 2337 6809 2328 6810 2307 6811 2306 6812 2306 6813 2305 6814 2337 6815 2328 6816 2306 6817 2337 6818 2329 6819 2328 6820 2337 6821 2329 6822 2337 6823 2336 6824 2329 6825 2336 6826 2335 6827 2330 6828 2329 6829 2335 6830 2330 6831 2335 6832 2334 6833 2330 6834 2334 6835 2333 6836 2331 6837 2330 6838 2333 6839 2331 6840 2333 6841 2332 6842 2353 6843 2352 6844 2351 6845 2353 6846 2351 6847 2358 6848 2354 6849 2353 6850 2358 6851 2355 6852 2354 6853 2357 6854 2357 6855 2354 6856 2358 6857 2355 6858 2357 6859 2356 6860 2366 6861 2365 6862 2364 6863 2366 6864 2364 6865 2363 6866 2367 6867 2366 6868 2363 6869 2367 6870 2363 6871 2362 6872 2367 6873 2362 6874 2361 6875 2368 6876 2367 6877 2361 6878 2368 6879 2361 6880 2360 6881 2368 6882 2360 6883 2359 6884 2369 6885 2368 6886 2359 6887 2369 6888 2359 6889 2420 6890 2420 6891 2359 6892 2421 6893 2421 6894 2359 6895 2422 6896 2422 6897 2359 6898 2423 6899 2423 6900 2359 6901 2424 6902 2424 6903 2359 6904 2425 6905 2425 6906 2359 6907 2426 6908 2370 6909 2369 6910 2420 6911 2370 6912 2420 6913 2419 6914 2370 6915 2419 6916 2418 6917 2370 6918 2418 6919 2417 6920 2371 6921 2370 6922 2417 6923 2371 6924 2417 6925 2416 6926 2371 6927 2416 6928 2415 6929 2371 6930 2415 6931 2414 6932 2371 6933 2414 6934 2413 6935 2372 6936 2371 6937 2413 6938 2372 6939 2413 6940 2412 6941 2372 6942 2412 6943 2411 6944 2372 6945 2411 6946 2410 6947 2372 6948 2410 6949 2409 6950 2373 6951 2372 6952 2409 6953 2373 6954 2409 6955 2408 6956 2373 6957 2408 6958 2407 6959 2374 6960 2373 6961 2407 6962 2374 6963 2407 6964 2406 6965 2375 6966 2374 6967 2406 6968 2375 6969 2406 6970 2405 6971 2375 6972 2405 6973 2404 6974 2376 6975 2375 6976 2404 6977 2376 6978 2404 6979 2403 6980 2377 6981 2376 6982 2403 6983 2377 6984 2403 6985 2402 6986 2390 6987 2389 6988 2388 6989 2377 6990 2402 6991 2401 6992 2378 6993 2377 6994 2401 6995 2390 6996 2388 6997 2387 6998 2379 6999 2378 7000 2401 7001 2390 7002 2387 7003 2386 7004 2380 7005 2379 7006 2401 7007 2380 7008 2401 7009 2400 7010 2390 7011 2386 7012 2385 7013 2381 7014 2380 7015 2400 7016 2382 7017 2381 7018 2400 7019 2390 7020 2385 7021 2384 7022 2383 7023 2382 7024 2400 7025 2390 7026 2384 7027 2383 7028 2390 7029 2383 7030 2400 7031 2390 7032 2400 7033 2399 7034 2391 7035 2390 7036 2399 7037 2391 7038 2399 7039 2398 7040 2392 7041 2391 7042 2398 7043 2393 7044 2392 7045 2398 7046 2393 7047 2398 7048 2397 7049 2394 7050 2393 7051 2397 7052 2394 7053 2397 7054 2396 7055 2395 7056 2394 7057 2396 7058 2434 7059 2433 7060 2432 7061 2434 7062 2432 7063 2431 7064 2434 7065 2431 7066 2430 7067 2435 7068 2434 7069 2430 7070 2435 7071 2430 7072 2429 7073 2435 7074 2429 7075 2428 7076 2435 7077 2428 7078 2427 7079 2436 7080 2435 7081 2427 7082 2436 7083 2427 7084 2470 7085 2470 7086 2427 7087 2471 7088 2471 7089 2427 7090 2472 7091 2472 7092 2427 7093 2473 7094 2473 7095 2427 7096 2474 7097 2474 7098 2427 7099 2475 7100 2475 7101 2427 7102 2476 7103 2437 7104 2436 7105 2469 7106 2469 7107 2436 7108 2470 7109 2437 7110 2469 7111 2468 7112 2437 7113 2468 7114 2467 7115 2438 7116 2437 7117 2467 7118 2438 7119 2467 7120 2466 7121 2438 7122 2466 7123 2465 7124 2439 7125 2438 7126 2465 7127 2439 7128 2465 7129 2464 7130 2439 7131 2464 7132 2463 7133 2440 7134 2439 7135 2463 7136 2440 7137 2463 7138 2462 7139 2441 7140 2440 7141 2462 7142 2441 7143 2462 7144 2461 7145 2441 7146 2461 7147 2460 7148 2453 7149 2452 7150 2451 7151 2442 7152 2441 7153 2460 7154 2454 7155 2453 7156 2451 7157 2442 7158 2460 7159 2459 7160 2455 7161 2454 7162 2451 7163 2456 7164 2455 7165 2451 7166 2442 7167 2459 7168 2458 7169 2457 7170 2456 7171 2451 7172 2458 7173 2457 7174 2451 7175 2442 7176 2458 7177 2451 7178 2443 7179 2442 7180 2451 7181 2444 7182 2443 7183 2451 7184 2444 7185 2451 7186 2450 7187 2444 7188 2450 7189 2449 7190 2444 7191 2449 7192 2448 7193 2444 7194 2448 7195 2447 7196 2445 7197 2444 7198 2447 7199 2445 7200 2447 7201 2446 7202 2488 7203 2487 7204 2486 7205 2489 7206 2488 7207 2486 7208 2489 7209 2486 7210 2485 7211 2490 7212 2489 7213 2485 7214 2490 7215 2485 7216 2484 7217 2491 7218 2490 7219 2484 7220 2491 7221 2484 7222 2483 7223 2492 7224 2491 7225 2483 7226 2492 7227 2483 7228 2482 7229 2493 7230 2492 7231 2482 7232 2493 7233 2482 7234 2481 7235 2494 7236 2493 7237 2481 7238 2494 7239 2481 7240 2504 7241 2494 7242 2504 7243 2503 7244 2495 7245 2494 7246 2503 7247 2495 7248 2503 7249 2502 7250 2496 7251 2495 7252 2502 7253 2496 7254 2502 7255 2501 7256 2497 7257 2496 7258 2501 7259 2497 7260 2501 7261 2500 7262 2498 7263 2497 7264 2500 7265 2498 7266 2500 7267 2499 7268 2479 7269 2478 7270 2477 7271 2479 7272 2477 7273 2480 7274 2512 7275 2511 7276 2510 7277 2512 7278 2510 7279 2509 7280 2513 7281 2512 7282 2509 7283 2513 7284 2509 7285 2508 7286 2513 7287 2508 7288 2507 7289 2514 7290 2513 7291 2507 7292 2514 7293 2507 7294 2506 7295 2514 7296 2506 7297 2505 7298 2515 7299 2514 7300 2505 7301 2515 7302 2505 7303 2566 7304 2566 7305 2505 7306 2567 7307 2567 7308 2505 7309 2568 7310 2568 7311 2505 7312 2569 7313 2569 7314 2505 7315 2570 7316 2570 7317 2505 7318 2571 7319 2571 7320 2505 7321 2572 7322 2516 7323 2515 7324 2566 7325 2516 7326 2566 7327 2565 7328 2516 7329 2565 7330 2564 7331 2516 7332 2564 7333 2563 7334 2517 7335 2516 7336 2563 7337 2517 7338 2563 7339 2562 7340 2517 7341 2562 7342 2561 7343 2517 7344 2561 7345 2560 7346 2517 7347 2560 7348 2559 7349 2518 7350 2517 7351 2559 7352 2518 7353 2559 7354 2558 7355 2518 7356 2558 7357 2557 7358 2518 7359 2557 7360 2556 7361 2518 7362 2556 7363 2555 7364 2519 7365 2518 7366 2555 7367 2519 7368 2555 7369 2554 7370 2519 7371 2554 7372 2553 7373 2520 7374 2519 7375 2553 7376 2520 7377 2553 7378 2552 7379 2521 7380 2520 7381 2552 7382 2521 7383 2552 7384 2551 7385 2521 7386 2551 7387 2550 7388 2522 7389 2521 7390 2550 7391 2522 7392 2550 7393 2549 7394 2523 7395 2522 7396 2549 7397 2523 7398 2549 7399 2548 7400 2536 7401 2535 7402 2534 7403 2523 7404 2548 7405 2547 7406 2524 7407 2523 7408 2547 7409 2536 7410 2534 7411 2533 7412 2525 7413 2524 7414 2547 7415 2536 7416 2533 7417 2532 7418 2526 7419 2525 7420 2547 7421 2526 7422 2547 7423 2546 7424 2536 7425 2532 7426 2531 7427 2527 7428 2526 7429 2546 7430 2528 7431 2527 7432 2546 7433 2536 7434 2531 7435 2530 7436 2529 7437 2528 7438 2546 7439 2536 7440 2530 7441 2529 7442 2536 7443 2529 7444 2546 7445 2536 7446 2546 7447 2545 7448 2537 7449 2536 7450 2545 7451 2537 7452 2545 7453 2544 7454 2538 7455 2537 7456 2544 7457 2539 7458 2538 7459 2544 7460 2539 7461 2544 7462 2543 7463 2540 7464 2539 7465 2543 7466 2540 7467 2543 7468 2542 7469 2541 7470 2540 7471 2542 7472 2578 7473 2577 7474 2576 7475 2578 7476 2576 7477 2575 7478 2575 7479 2574 7480 2573 7481 2575 7482 2573 7483 2580 7484 2578 7485 2575 7486 2580 7487 2579 7488 2578 7489 2580 7490 2583 7491 2582 7492 2581 7493 2583 7494 2581 7495 2613 7496 2607 7497 2606 7498 2605 7499 2608 7500 2607 7501 2605 7502 2608 7503 2605 7504 2604 7505 2609 7506 2608 7507 2604 7508 2610 7509 2609 7510 2604 7511 2610 7512 2604 7513 2603 7514 2611 7515 2610 7516 2603 7517 2611 7518 2603 7519 2602 7520 2612 7521 2611 7522 2591 7523 2591 7524 2611 7525 2602 7526 2583 7527 2613 7528 2612 7529 2583 7530 2612 7531 2585 7532 2585 7533 2612 7534 2586 7535 2586 7536 2612 7537 2587 7538 2587 7539 2612 7540 2588 7541 2588 7542 2612 7543 2589 7544 2589 7545 2612 7546 2590 7547 2590 7548 2612 7549 2591 7550 2592 7551 2591 7552 2602 7553 2593 7554 2592 7555 2602 7556 2593 7557 2602 7558 2601 7559 2594 7560 2593 7561 2601 7562 2595 7563 2594 7564 2601 7565 2596 7566 2595 7567 2601 7568 2596 7569 2601 7570 2600 7571 2583 7572 2585 7573 2584 7574 2597 7575 2596 7576 2600 7577 2598 7578 2597 7579 2600 7580 2598 7581 2600 7582 2599 7583 2615 7584 2614 7585 2631 7586 2631 7587 2614 7588 2630 7589 2631 7590 2630 7591 2629 7592 2631 7593 2629 7594 2628 7595 2631 7596 2628 7597 2627 7598 2631 7599 2627 7600 2632 7601 2632 7602 2627 7603 2626 7604 2615 7605 2631 7606 2645 7607 2633 7608 2632 7609 2626 7610 2634 7611 2633 7612 2626 7613 2634 7614 2626 7615 2625 7616 2635 7617 2634 7618 2625 7619 2636 7620 2635 7621 2625 7622 2637 7623 2636 7624 2625 7625 2637 7626 2625 7627 2624 7628 2638 7629 2637 7630 2624 7631 2639 7632 2638 7633 2624 7634 2639 7635 2624 7636 2623 7637 2640 7638 2639 7639 2623 7640 2640 7641 2623 7642 2622 7643 2641 7644 2640 7645 2622 7646 2642 7647 2641 7648 2622 7649 2643 7650 2642 7651 2622 7652 2643 7653 2622 7654 2621 7655 2644 7656 2643 7657 2621 7658 2615 7659 2645 7660 2617 7661 2617 7662 2645 7663 2644 7664 2617 7665 2644 7666 2621 7667 2617 7668 2621 7669 2620 7670 2617 7671 2620 7672 2619 7673 2617 7674 2619 7675 2618 7676 2615 7677 2617 7678 2616 7679 2647 7680 2646 7681 2679 7682 2647 7683 2679 7684 2678 7685 2647 7686 2678 7687 2677 7688 2648 7689 2647 7690 2677 7691 2649 7692 2648 7693 2677 7694 2650 7695 2649 7696 2676 7697 2676 7698 2649 7699 2677 7700 2650 7701 2676 7702 2675 7703 2650 7704 2675 7705 2674 7706 2651 7707 2650 7708 2674 7709 2651 7710 2674 7711 2673 7712 2664 7713 2663 7714 2662 7715 2651 7716 2673 7717 2672 7718 2665 7719 2664 7720 2662 7721 2652 7722 2651 7723 2672 7724 2666 7725 2665 7726 2662 7727 2652 7728 2672 7729 2671 7730 2667 7731 2666 7732 2662 7733 2652 7734 2671 7735 2670 7736 2668 7737 2667 7738 2662 7739 2652 7740 2670 7741 2669 7742 2669 7743 2668 7744 2662 7745 2652 7746 2669 7747 2662 7748 2653 7749 2652 7750 2662 7751 2654 7752 2653 7753 2662 7754 2654 7755 2662 7756 2661 7757 2654 7758 2661 7759 2660 7760 2655 7761 2654 7762 2660 7763 2655 7764 2660 7765 2659 7766 2655 7767 2659 7768 2658 7769 2656 7770 2655 7771 2658 7772 2656 7773 2658 7774 2657 7775 2700 7776 2699 7777 2698 7778 2700 7779 2698 7780 2697 7781 2701 7782 2700 7783 2697 7784 2701 7785 2697 7786 2696 7787 2702 7788 2701 7789 2696 7790 2702 7791 2696 7792 2724 7793 2724 7794 2696 7795 2725 7796 2725 7797 2696 7798 2695 7799 2703 7800 2702 7801 2723 7802 2723 7803 2702 7804 2724 7805 2703 7806 2723 7807 2722 7808 2726 7809 2725 7810 2695 7811 2703 7812 2722 7813 2721 7814 2727 7815 2726 7816 2695 7817 2703 7818 2721 7819 2720 7820 2728 7821 2727 7822 2695 7823 2704 7824 2703 7825 2720 7826 2728 7827 2695 7828 2694 7829 2704 7830 2720 7831 2719 7832 2729 7833 2728 7834 2694 7835 2704 7836 2719 7837 2718 7838 2730 7839 2729 7840 2694 7841 2705 7842 2704 7843 2718 7844 2730 7845 2694 7846 2693 7847 2705 7848 2718 7849 2730 7850 2705 7851 2730 7852 2693 7853 2706 7854 2705 7855 2692 7856 2692 7857 2705 7858 2693 7859 2706 7860 2692 7861 2691 7862 2706 7863 2691 7864 2690 7865 2707 7866 2706 7867 2690 7868 2707 7869 2690 7870 2689 7871 2681 7872 2680 7873 2717 7874 2682 7875 2681 7876 2717 7877 2708 7878 2707 7879 2689 7880 2708 7881 2689 7882 2688 7883 2683 7884 2682 7885 2717 7886 2708 7887 2688 7888 2687 7889 2684 7890 2683 7891 2717 7892 2685 7893 2684 7894 2717 7895 2708 7896 2687 7897 2686 7898 2686 7899 2685 7900 2717 7901 2708 7902 2686 7903 2717 7904 2709 7905 2708 7906 2717 7907 2709 7908 2717 7909 2716 7910 2709 7911 2716 7912 2715 7913 2710 7914 2709 7915 2715 7916 2710 7917 2715 7918 2714 7919 2710 7920 2714 7921 2713 7922 2711 7923 2710 7924 2713 7925 2711 7926 2713 7927 2712 7928 2733 7929 2732 7930 2731 7931 2733 7932 2731 7933 2734 7934 2737 7935 2736 7936 2735 7937 2737 7938 2735 7939 2738 7940 2757 7941 2756 7942 2755 7943 2757 7944 2755 7945 2754 7946 2742 7947 2741 7948 2740 7949 2742 7950 2740 7951 2739 7952 2758 7953 2757 7954 2754 7955 2758 7956 2754 7957 2753 7958 2758 7959 2753 7960 2752 7961 2743 7962 2742 7963 2739 7964 2759 7965 2758 7966 2752 7967 2759 7968 2752 7969 2751 7970 2744 7971 2743 7972 2739 7973 2745 7974 2744 7975 2769 7976 2769 7977 2744 7978 2739 7979 2759 7980 2751 7981 2750 7982 2746 7983 2745 7984 2769 7985 2759 7986 2750 7987 2749 7988 2760 7989 2759 7990 2749 7991 2747 7992 2746 7993 2769 7994 2760 7995 2749 7996 2748 7997 2748 7998 2747 7999 2769 8000 2760 8001 2748 8002 2769 8003 2760 8004 2769 8005 2768 8006 2770 8007 2769 8008 2739 8009 2760 8010 2768 8011 2767 8012 2761 8013 2760 8014 2767 8015 2761 8016 2767 8017 2766 8018 2762 8019 2761 8020 2766 8021 2762 8022 2766 8023 2765 8024 2762 8025 2765 8026 2764 8027 2763 8028 2762 8029 2764 8030 2771 8031 2798 8032 2799 8033 2799 8034 2798 8035 2797 8036 2799 8037 2797 8038 2796 8039 2799 8040 2796 8041 2795 8042 2799 8043 2795 8044 2794 8045 2799 8046 2794 8047 2800 8048 2800 8049 2794 8050 2793 8051 2771 8052 2799 8053 2813 8054 2801 8055 2800 8056 2793 8057 2801 8058 2793 8059 2792 8060 2802 8061 2801 8062 2792 8063 2803 8064 2802 8065 2792 8066 2804 8067 2803 8068 2792 8069 2804 8070 2792 8071 2791 8072 2805 8073 2804 8074 2791 8075 2806 8076 2805 8077 2791 8078 2806 8079 2791 8080 2790 8081 2807 8082 2806 8083 2790 8084 2807 8085 2790 8086 2789 8087 2808 8088 2807 8089 2789 8090 2808 8091 2789 8092 2788 8093 2809 8094 2808 8095 2788 8096 2809 8097 2788 8098 2787 8099 2810 8100 2809 8101 2787 8102 2811 8103 2810 8104 2787 8105 2811 8106 2787 8107 2786 8108 2812 8109 2811 8110 2786 8111 2771 8112 2813 8113 2814 8114 2814 8115 2813 8116 2812 8117 2814 8118 2812 8119 2786 8120 2814 8121 2786 8122 2785 8123 2814 8124 2785 8125 2784 8126 2814 8127 2784 8128 2783 8129 2814 8130 2783 8131 2782 8132 2814 8133 2782 8134 2815 8135 2815 8136 2782 8137 2781 8138 2771 8139 2814 8140 2828 8141 2816 8142 2815 8143 2781 8144 2817 8145 2816 8146 2781 8147 2817 8148 2781 8149 2780 8150 2818 8151 2817 8152 2780 8153 2819 8154 2818 8155 2780 8156 2819 8157 2780 8158 2779 8159 2820 8160 2819 8161 2779 8162 2820 8163 2779 8164 2778 8165 2821 8166 2820 8167 2778 8168 2822 8169 2821 8170 2778 8171 2822 8172 2778 8173 2777 8174 2823 8175 2822 8176 2777 8177 2824 8178 2823 8179 2777 8180 2824 8181 2777 8182 2776 8183 2825 8184 2824 8185 2776 8186 2826 8187 2825 8188 2776 8189 2826 8190 2776 8191 2775 8192 2827 8193 2826 8194 2775 8195 2771 8196 2828 8197 2827 8198 2771 8199 2827 8200 2775 8201 2771 8202 2775 8203 2774 8204 2771 8205 2774 8206 2773 8207 2771 8208 2773 8209 2772 8210

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 0.0 -0.0 1.0 -0.0 0.0 -1.0 - - - - - - - - - - 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 - - - - - - - - - - 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 - - - - - - - - - - - - - - -

    1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

    -
    -
    -
    - - - - 1.19619 0.58226 -1.0 0.41454 -0.7869 -1.0 -1.39461 0.06574 -1.0 -0.80381 0.58226 -1.0 1.19619 0.58226 1.0 0.41454 -0.7869 1.0 -1.39461 0.06574 1.0 -0.80381 0.58226 1.0 - - - - - - - - - - 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 - - - - - - - - - - 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - - - - 1.12341 0.59904 -1.0 0.34176 -0.77012 -1.0 -1.46739 0.08252 -1.0 -0.87659 0.59904 -1.0 1.12341 0.59904 1.0 0.34176 -0.77012 1.0 -1.46739 0.08252 1.0 -0.87659 0.59904 1.0 - - - - - - - - - - 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 - - - - - - - - - - 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - - - - 1.35033 0.45305 -1.0 0.56868 -0.9161 -1.0 -1.24047 -0.06347 -1.0 -0.64967 0.45305 -1.0 1.35033 0.45305 1.0 0.56868 -0.9161 1.0 -1.24047 -0.06347 1.0 -0.64967 0.45305 1.0 - - - - - - - - - - 0.61278 0.35575 -0.70562 0.24885 -0.7882 -0.56285 -0.73128 -0.1023 -0.67431 -0.31007 0.82577 -0.47108 0.61278 0.35575 0.70562 0.24885 -0.7882 0.56285 -0.73128 -0.1023 0.67431 -0.31007 0.82577 0.47108 - - - - - - - - - - 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 0.72873 0.47178 0.60186 0.37916 0.37041 0.15993 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 1.02857 0.44771 0.453 0.33992 -0.02857 0.44771 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.72873 0.47178 1.02857 0.44771 0.60116 0.61947 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.60186 0.37916 0.60116 0.61947 -0.02857 0.44771 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 0.37041 0.15993 -0.02857 0.44771 0.453 0.33992 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 1.02857 0.44771 0.72873 0.47178 0.50417 0.38059 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - - - - 0.0 -0.0 -1.41421 1.02332 -0.74348 -0.63246 -0.39087 -1.20299 -0.63246 -1.26491 -0.0 -0.63246 -0.39087 1.20299 -0.63246 1.02332 0.74348 -0.63246 0.39087 -1.20299 0.63246 -1.02332 -0.74348 0.63246 -1.02332 0.74348 0.63246 0.39087 1.20299 0.63246 1.26491 0.0 0.63246 -0.0 0.0 1.41421 0.6015 -0.43701 -1.20301 -0.22975 -0.7071 -1.20301 0.37175 -1.14412 -0.74351 0.6015 0.43701 -1.20301 1.203 -0.0 -0.7435 -0.74349 -0.0 -1.203 -0.97325 -0.7071 -0.7435 -0.22975 0.7071 -1.20301 -0.97325 0.7071 -0.7435 0.37175 1.14412 -0.74351 1.345 0.43701 -0.0 1.345 -0.43701 0.0 0.83125 -1.14412 0.0 -0.0 -1.41421 0.0 -0.83125 -1.14412 0.0 -1.345 -0.43701 0.0 -1.345 0.43701 -0.0 -0.83125 1.14412 -0.0 0.0 1.41421 -0.0 0.83125 1.14412 -0.0 0.97325 -0.7071 0.7435 -0.37175 -1.14412 0.74351 -1.203 0.0 0.7435 -0.37175 1.14412 0.74351 0.97325 0.7071 0.7435 0.74349 0.0 1.203 0.22975 -0.7071 1.20301 -0.6015 -0.43701 1.20301 -0.6015 0.43701 1.20301 0.22975 0.7071 1.20301 - - - - - - - - - - 0.0 0.0 -1.0 0.72359 -0.52571 -0.44719 -0.27638 -0.85064 -0.44719 -0.89441 0.0 -0.44719 -0.27638 0.85064 -0.44719 0.72359 0.52571 -0.44719 0.27638 -0.85064 0.44722 -0.72359 -0.52571 0.44719 -0.72359 0.52571 0.44719 0.27638 0.85064 0.44719 0.89441 0.0 0.44719 0.0 0.0 1.0 0.42531 -0.309 -0.85064 -0.16245 -0.49998 -0.85064 0.26286 -0.80898 -0.52571 0.42531 0.309 -0.85064 0.85064 0.0 -0.52571 -0.52571 0.0 -0.85064 -0.68816 -0.49998 -0.52571 -0.16245 0.49998 -0.85064 -0.68816 0.49998 -0.52571 0.26286 0.80898 -0.52571 0.95105 0.309 0.0 0.95105 -0.309 0.0 0.58776 -0.80902 0.0 0.0 -1.0 0.0 -0.58776 -0.80902 0.0 -0.95105 -0.309 0.0 -0.95105 0.309 0.0 -0.58776 0.80902 0.0 0.0 1.0 0.0 0.58776 0.80902 0.0 0.68816 -0.49998 0.52571 -0.26286 -0.80898 0.52571 -0.85064 0.0 0.52571 -0.26286 0.80898 0.52571 0.68816 0.49998 0.52571 0.52571 0.0 0.85064 0.16245 -0.49998 0.85064 -0.42531 -0.309 0.85064 -0.42531 0.309 0.85064 0.16245 0.49998 0.85064 - - - - - - - - - - 0.75311 0.11158 0.95018 0.21117 0.82689 0.27054 0.95018 0.21117 0.75311 0.11158 1.14943 0.09989 0.46246 0.11286 1.14943 0.09989 0.75311 0.11158 1.14943 0.09989 1.07744 0.2618 0.95018 0.21117 0.90005 0.39508 0.82689 0.27054 0.95018 0.21117 0.95018 0.21117 1.00617 0.39104 0.90005 0.39508 0.95447 0.53487 0.90005 0.39508 1.00617 0.39104 0.95018 0.21117 1.07744 0.2618 1.00617 0.39104 0.32261 0.22952 0.14943 0.09989 0.46246 0.11286 0.14943 0.09989 0.32261 0.22952 0.19133 0.29524 0.27674 0.38955 0.19133 0.29524 0.32261 0.22952 0.19133 0.29524 0.07744 0.2618 0.14943 0.09989 0.20413 0.49383 0.19133 0.29524 0.27674 0.38955 0.19133 0.29524 0.20413 0.49383 0.10855 0.42958 0.13244 0.59936 0.10855 0.42958 0.20413 0.49383 0.10855 0.42958 0.07744 0.2618 0.19133 0.29524 0.04129 0.57872 0.10855 0.42958 0.13244 0.59936 0.10855 0.42958 0.04129 0.57872 0.00617 0.39104 0.95447 0.53487 1.00617 0.39104 1.04129 0.57872 0.00617 0.39104 0.07744 0.2618 0.10855 0.42958 0.79899 0.43978 0.82689 0.27054 0.90005 0.39508 0.90005 0.39508 0.86836 0.58509 0.79899 0.43978 0.77674 0.61045 0.79899 0.43978 0.86836 0.58509 0.86836 0.58509 0.90005 0.39508 0.95447 0.53487 0.59019 0.23871 0.46246 0.11286 0.75311 0.11158 0.75311 0.11158 0.71658 0.30753 0.59019 0.23871 0.63244 0.40064 0.59019 0.23871 0.71658 0.30753 0.71658 0.30753 0.75311 0.11158 0.82689 0.27054 0.36836 0.41491 0.27674 0.38955 0.32261 0.22952 0.32261 0.22952 0.45654 0.28896 0.36836 0.41491 0.45447 0.46513 0.36836 0.41491 0.45654 0.28896 0.45654 0.28896 0.32261 0.22952 0.46246 0.11286 0.21658 0.69247 0.13244 0.59936 0.20413 0.49383 0.20413 0.49383 0.29899 0.56022 0.21658 0.69247 0.32689 0.72946 0.21658 0.69247 0.29899 0.56022 0.29899 0.56022 0.20413 0.49383 0.27674 0.38955 0.95654 0.71104 0.95447 0.53487 1.04129 0.57872 1.04129 0.57872 1.09019 0.76129 0.95654 0.71104 0.96246 0.88714 0.95654 0.71104 1.09019 0.76129 0.09019 0.76129 0.04129 0.57872 0.13244 0.59936 0.70413 0.50617 0.79899 0.43978 0.77674 0.61045 0.79899 0.43978 0.70413 0.50617 0.71658 0.30753 0.63244 0.40064 0.71658 0.30753 0.70413 0.50617 0.71658 0.30753 0.82689 0.27054 0.79899 0.43978 0.54129 0.42128 0.59019 0.23871 0.63244 0.40064 0.59019 0.23871 0.54129 0.42128 0.45654 0.28896 0.45447 0.46513 0.45654 0.28896 0.54129 0.42128 0.45654 0.28896 0.46246 0.11286 0.59019 0.23871 0.40005 0.60492 0.36836 0.41491 0.45447 0.46513 0.36836 0.41491 0.40005 0.60492 0.29899 0.56022 0.32689 0.72946 0.29899 0.56022 0.40005 0.60492 0.29899 0.56022 0.27674 0.38955 0.36836 0.41491 0.25311 0.88842 0.21658 0.69247 0.32689 0.72946 0.21658 0.69247 0.25311 0.88842 0.09019 0.76129 0.96246 0.88714 1.09019 0.76129 1.25311 0.88842 0.09019 0.76129 0.13244 0.59936 0.21658 0.69247 0.82261 0.77048 0.95654 0.71104 0.96246 0.88714 0.95654 0.71104 0.82261 0.77048 0.86836 0.58509 0.77674 0.61045 0.86836 0.58509 0.82261 0.77048 0.86836 0.58509 0.95447 0.53487 0.95654 0.71104 0.60855 0.57042 0.63244 0.40064 0.70413 0.50617 0.70413 0.50617 0.69133 0.70476 0.60855 0.57042 0.57744 0.7382 0.60855 0.57042 0.69133 0.70476 0.69133 0.70476 0.70413 0.50617 0.77674 0.61045 0.50617 0.60896 0.45447 0.46513 0.54129 0.42128 0.54129 0.42128 0.60855 0.57042 0.50617 0.60896 0.57744 0.7382 0.50617 0.60896 0.60855 0.57042 0.60855 0.57042 0.54129 0.42128 0.63244 0.40064 0.45018 0.78883 0.32689 0.72946 0.40005 0.60492 0.40005 0.60492 0.50617 0.60896 0.45018 0.78883 0.57744 0.7382 0.45018 0.78883 0.50617 0.60896 0.50617 0.60896 0.40005 0.60492 0.45447 0.46513 0.64943 0.90011 0.96246 0.88714 1.25311 0.88842 0.25311 0.88842 0.45018 0.78883 0.64943 0.90011 0.57744 0.7382 0.64943 0.90011 0.45018 0.78883 0.45018 0.78883 0.25311 0.88842 0.32689 0.72946 0.69133 0.70476 0.77674 0.61045 0.82261 0.77048 0.82261 0.77048 0.64943 0.90011 0.69133 0.70476 0.57744 0.7382 0.69133 0.70476 0.64943 0.90011 0.64943 0.90011 0.82261 0.77048 0.96246 0.88714 - - - - - - - - - - - - - - -

    14 0 12 1 1 2 12 3 14 4 13 5 2 6 13 7 14 8 13 9 0 10 12 11 16 12 1 13 12 14 12 15 15 16 16 17 5 18 16 19 15 20 12 21 0 22 15 23 18 24 13 25 2 26 13 27 18 28 17 29 3 30 17 31 18 32 17 33 0 34 13 35 20 36 17 37 3 38 17 39 20 40 19 41 4 42 19 43 20 44 19 45 0 46 17 47 21 48 19 49 4 50 19 51 21 52 15 53 5 54 15 55 21 56 15 57 0 58 19 59 23 60 1 61 16 62 16 63 22 64 23 65 10 66 23 67 22 68 22 69 16 70 5 71 25 72 2 73 14 74 14 75 24 76 25 77 6 78 25 79 24 80 24 81 14 82 1 83 27 84 3 85 18 86 18 87 26 88 27 89 7 90 27 91 26 92 26 93 18 94 2 95 29 96 4 97 20 98 20 99 28 100 29 101 8 102 29 103 28 104 28 105 20 106 3 107 31 108 5 109 21 110 21 111 30 112 31 113 9 114 31 115 30 116 30 117 21 118 4 119 32 120 23 121 10 122 23 123 32 124 24 125 6 126 24 127 32 128 24 129 1 130 23 131 33 132 25 133 6 134 25 135 33 136 26 137 7 138 26 139 33 140 26 141 2 142 25 143 34 144 27 145 7 146 27 147 34 148 28 149 8 150 28 151 34 152 28 153 3 154 27 155 35 156 29 157 8 158 29 159 35 160 30 161 9 162 30 163 35 164 30 165 4 166 29 167 36 168 31 169 9 170 31 171 36 172 22 173 10 174 22 175 36 176 22 177 5 178 31 179 38 180 6 181 32 182 32 183 37 184 38 185 11 186 38 187 37 188 37 189 32 190 10 191 39 192 7 193 33 194 33 195 38 196 39 197 11 198 39 199 38 200 38 201 33 202 6 203 40 204 8 205 34 206 34 207 39 208 40 209 11 210 40 211 39 212 39 213 34 214 7 215 41 216 9 217 35 218 35 219 40 220 41 221 11 222 41 223 40 224 40 225 35 226 8 227 37 228 10 229 36 230 36 231 41 232 37 233 11 234 37 235 41 236 41 237 36 238 9 239

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 - - - - - - - - - - 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.42013 0.42013 -0.42013 0.49402 0.33009 -0.42013 0.54892 0.22737 -0.42013 0.58273 0.11591 -0.42013 0.59415 0.0 -0.42013 0.58273 -0.11591 -0.42013 0.54892 -0.22737 -0.42013 0.49402 -0.33009 -0.42013 0.42013 -0.42013 -0.42013 0.33009 -0.49402 -0.42013 0.22737 -0.54892 -0.42013 0.11591 -0.58273 -0.42013 -0.0 -0.59415 -0.42013 -0.11591 -0.58273 -0.42013 -0.22737 -0.54892 -0.42013 -0.33009 -0.49402 -0.42013 -0.42013 -0.42013 -0.42013 -0.49402 -0.33009 -0.42013 -0.54892 -0.22737 -0.42013 -0.58273 -0.11591 -0.42013 -0.59415 0.0 -0.42013 -0.58273 0.11591 -0.42013 -0.54892 0.22737 -0.42013 -0.49402 0.33009 -0.42013 -0.42013 0.42013 -0.42013 -0.33009 0.49402 -0.42013 -0.22737 0.54892 -0.42013 -0.11591 0.58273 -0.42013 0.0 0.59415 -0.42013 0.11591 0.58273 -0.42013 0.22737 0.54892 -0.42013 0.33009 0.49402 -0.42013 -0.0 0.0 0.42013 -0.0 0.0 -0.42013 - - - - - - - - - - 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 - - - - - - - - - - 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 - - - - - - - - - - - - - - -

    1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 0.0 -0.0 1.0 -0.0 0.0 -1.0 - - - - - - - - - - 0.62694 0.62694 -0.46245 0.73721 0.49257 -0.46245 0.81912 0.33927 -0.46245 0.86959 0.17295 -0.46245 0.88662 0.0 -0.46245 0.86959 -0.17295 -0.46245 0.81912 -0.33927 -0.46245 0.73721 -0.49257 -0.46245 0.62694 -0.62694 -0.46245 0.49257 -0.73721 -0.46245 0.33927 -0.81912 -0.46245 0.17295 -0.86959 -0.46245 0.0 -0.88662 -0.46245 -0.17295 -0.86959 -0.46245 -0.33927 -0.81912 -0.46245 -0.49257 -0.73721 -0.46245 -0.62694 -0.62694 -0.46245 -0.73721 -0.49257 -0.46245 -0.81912 -0.33927 -0.46245 -0.86959 -0.17295 -0.46245 -0.88662 0.0 -0.46245 -0.86959 0.17295 -0.46245 -0.81912 0.33927 -0.46245 -0.73721 0.49257 -0.46245 -0.62694 0.62694 -0.46245 -0.49257 0.73721 -0.46245 -0.33927 0.81915 -0.46245 -0.17295 0.86959 -0.46245 0.0 0.88662 -0.46245 0.17295 0.86959 -0.46245 0.33927 0.81912 -0.46245 0.49257 0.73721 -0.46245 0.0 0.0 1.0 0.0 0.0 -1.0 - - - - - - - - - - 0.89466 0.14214 1.02385 0.18062 0.53437 0.50208 0.53437 0.50208 0.77134 0.1159 0.89466 0.14214 0.53437 0.50208 0.65189 0.10064 0.77134 0.1159 0.53437 0.50208 0.53438 0.09564 0.65189 0.10064 0.53437 0.50208 0.41686 0.10064 0.53438 0.09564 0.53437 0.50208 0.29742 0.1159 0.41686 0.10064 0.53437 0.50208 0.17409 0.14214 0.29742 0.1159 0.53437 0.50208 0.0449 0.18062 0.17409 0.14214 0.53437 0.50208 -0.09221 0.23313 0.0449 0.18062 0.53437 0.50208 -0.23937 0.30206 -0.09221 0.23313 0.53437 0.50208 -0.39881 0.39046 -0.23937 0.30206 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.6137 -0.57289 0.50208 0.53437 0.50208 -0.23937 0.70209 -0.39881 0.6137 0.53437 0.50208 -0.09221 0.77103 -0.23937 0.70209 0.53437 0.50208 0.0449 0.82354 -0.09221 0.77103 0.53437 0.50208 0.17409 0.86202 0.0449 0.82354 0.53437 0.50208 0.29741 0.88826 0.17409 0.86202 0.53437 0.50208 0.41686 0.90351 0.29741 0.88826 0.53437 0.50208 0.53437 0.90852 0.41686 0.90351 0.53437 0.50208 0.65189 0.90351 0.53437 0.90852 0.53437 0.50208 0.77133 0.88826 0.65189 0.90351 0.53437 0.50208 0.89466 0.86202 0.77133 0.88826 0.53437 0.50208 1.02385 0.82354 0.89466 0.86202 0.53437 0.50208 1.16096 0.77103 1.02385 0.82354 0.53437 0.50208 1.30812 0.70209 1.16096 0.77103 0.53437 0.50208 1.46756 0.6137 1.30812 0.70209 0.53437 0.50208 1.64164 0.50208 1.46756 0.6137 0.53437 0.50208 1.46756 0.39046 1.64164 0.50208 0.53437 0.50208 1.30812 0.30207 1.46756 0.39046 0.53437 0.50208 1.16096 0.23313 1.30812 0.30207 0.53437 0.50208 1.02385 0.18062 1.16096 0.23313 0.53437 0.50208 1.02385 0.18062 0.89466 0.14214 0.53437 0.50208 0.89466 0.14214 0.77134 0.1159 0.53437 0.50208 0.77134 0.1159 0.65189 0.10064 0.53437 0.50208 0.65189 0.10064 0.53438 0.09564 0.53437 0.50208 0.53438 0.09564 0.41686 0.10064 0.53437 0.50208 0.41686 0.10064 0.29742 0.1159 0.53437 0.50208 0.29742 0.1159 0.17409 0.14214 0.53437 0.50208 0.17409 0.14214 0.0449 0.18062 0.53437 0.50208 0.0449 0.18062 -0.09221 0.23313 0.53437 0.50208 -0.09221 0.23313 -0.23937 0.30206 0.53437 0.50208 -0.23937 0.30206 -0.39881 0.39046 0.53437 0.50208 -0.39881 0.39046 -0.57289 0.50208 0.53437 0.50208 -0.57289 0.50208 -0.39881 0.6137 0.53437 0.50208 -0.39881 0.6137 -0.23937 0.70209 0.53437 0.50208 -0.23937 0.70209 -0.09221 0.77103 0.53437 0.50208 -0.09221 0.77103 0.0449 0.82354 0.53437 0.50208 0.0449 0.82354 0.17409 0.86202 0.53437 0.50208 0.17409 0.86202 0.29741 0.88826 0.53437 0.50208 0.29741 0.88826 0.41686 0.90351 0.53437 0.50208 0.41686 0.90351 0.53437 0.90852 0.53437 0.50208 0.53437 0.90852 0.65189 0.90351 0.53437 0.50208 0.65189 0.90351 0.77133 0.88826 0.53437 0.50208 0.77133 0.88826 0.89466 0.86202 0.53437 0.50208 0.89466 0.86202 1.02385 0.82354 0.53437 0.50208 1.02385 0.82354 1.16096 0.77103 0.53437 0.50208 1.16096 0.77103 1.30812 0.70209 0.53437 0.50208 1.30812 0.70209 1.46756 0.6137 0.53437 0.50208 1.46756 0.6137 1.64164 0.50208 0.53437 0.50208 1.64164 0.50208 1.46756 0.39046 0.53437 0.50208 1.46756 0.39046 1.30812 0.30207 0.53437 0.50208 1.30812 0.30207 1.16096 0.23313 1.16096 0.23313 1.02385 0.18062 0.53437 0.50208 - - - - - - - - - - - - - - -

    1 0 0 1 32 2 32 3 2 4 1 5 32 6 3 7 2 8 32 9 4 10 3 11 32 12 5 13 4 14 32 15 6 16 5 17 32 18 7 19 6 20 32 21 8 22 7 23 32 24 9 25 8 26 32 27 10 28 9 29 32 30 11 31 10 32 32 33 12 34 11 35 32 36 13 37 12 38 32 39 14 40 13 41 32 42 15 43 14 44 32 45 16 46 15 47 32 48 17 49 16 50 32 51 18 52 17 53 32 54 19 55 18 56 32 57 20 58 19 59 32 60 21 61 20 62 32 63 22 64 21 65 32 66 23 67 22 68 32 69 24 70 23 71 32 72 25 73 24 74 32 75 26 76 25 77 32 78 27 79 26 80 32 81 28 82 27 83 32 84 29 85 28 86 32 87 30 88 29 89 32 90 31 91 30 92 32 93 0 94 31 95 33 96 0 97 1 98 33 99 1 100 2 101 33 102 2 103 3 104 33 105 3 106 4 107 33 108 4 109 5 110 33 111 5 112 6 113 33 114 6 115 7 116 33 117 7 118 8 119 33 120 8 121 9 122 33 123 9 124 10 125 33 126 10 127 11 128 33 129 11 130 12 131 33 132 12 133 13 134 33 135 13 136 14 137 33 138 14 139 15 140 33 141 15 142 16 143 33 144 16 145 17 146 33 147 17 148 18 149 33 150 18 151 19 152 33 153 19 154 20 155 33 156 20 157 21 158 33 159 21 160 22 161 33 162 22 163 23 164 33 165 23 166 24 167 33 168 24 169 25 170 33 171 25 172 26 173 33 174 26 175 27 176 33 177 27 178 28 179 33 180 28 181 29 182 33 183 29 184 30 185 33 186 30 187 31 188 31 189 0 190 33 191

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 - - - - - - - - - - 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 - - - - - - - - - - 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 - - - - - - - - - - - - - - -

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 - - - - - - - - - - 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 - - - - - - - - - - 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 - - - - - - - - - - - - - - -

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 - - - - - - - - - - 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 - - - - - - - - - - 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 - - - - - - - - - - - - - - -

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 - - - - - - - - - - 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 - - - - - - - - - - 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 - - - - - - - - - - - - - - -

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.17588 0.7857 -1.0 1.30656 0.5412 -1.0 1.38704 0.2759 -1.0 1.41421 0.0 -1.0 1.38704 -0.2759 -1.0 1.30656 -0.5412 -1.0 1.17588 -0.78569 -1.0 1.0 -1.0 -1.0 0.78569 -1.17588 -1.0 0.5412 -1.30656 -1.0 0.2759 -1.38704 -1.0 -0.0 -1.41421 -1.0 -0.2759 -1.38704 -1.0 -0.5412 -1.30656 -1.0 -0.7857 -1.17588 -1.0 -1.0 -1.0 -1.0 -1.17588 -0.78569 -1.0 -1.30656 -0.5412 -1.0 -1.38704 -0.2759 -1.0 -1.41421 0.0 -1.0 -1.38704 0.2759 -1.0 -1.30656 0.5412 -1.0 -1.17587 0.7857 -1.0 -1.0 1.0 -1.0 -0.78569 1.17588 -1.0 -0.54119 1.30656 -1.0 -0.2759 1.38704 -1.0 0.0 1.41421 -1.0 0.2759 1.38704 -1.0 0.5412 1.30656 -1.0 0.7857 1.17587 -1.0 1.0 1.0 1.0 1.17588 0.78569 1.0 1.30656 0.54119 1.0 1.38704 0.2759 1.0 1.41421 -0.0 1.0 1.38704 -0.2759 1.0 1.30656 -0.5412 1.0 1.17587 -0.7857 1.0 1.0 -1.0 1.0 0.78569 -1.17588 1.0 0.5412 -1.30656 1.0 0.2759 -1.38704 1.0 0.0 -1.41421 1.0 -0.2759 -1.38704 1.0 -0.54119 -1.30656 1.0 -0.78569 -1.17588 1.0 -1.0 -1.0 1.0 -1.17587 -0.7857 1.0 -1.30656 -0.5412 1.0 -1.38704 -0.2759 1.0 -1.41421 -1e-05 1.0 -1.38704 0.27589 1.0 -1.30657 0.54119 1.0 -1.17588 0.78569 1.0 -1.00001 0.99999 1.0 -0.7857 1.17587 1.0 -0.5412 1.30656 1.0 -0.27591 1.38704 1.0 -1e-05 1.41421 1.0 0.27589 1.38704 1.0 0.54119 1.30657 1.0 0.78569 1.17588 1.0 -0.0 0.0 -1.0 0.0 -0.0 1.0 - - - - - - - - - - 0.49876 0.49876 -0.70879 0.5865 0.39189 -0.70879 0.65169 0.26994 -0.70879 0.69182 0.13761 -0.70879 0.70537 0.0 -0.70879 0.69182 -0.13761 -0.70879 0.65169 -0.26994 -0.70879 0.5865 -0.39189 -0.70879 0.49876 -0.49876 -0.70879 0.39189 -0.5865 -0.70879 0.26994 -0.65169 -0.70879 0.13761 -0.69182 -0.70879 0.0 -0.70537 -0.70879 -0.13761 -0.69182 -0.70879 -0.26994 -0.65169 -0.70879 -0.39189 -0.5865 -0.70879 -0.49876 -0.49876 -0.70879 -0.5865 -0.39189 -0.70879 -0.65169 -0.26994 -0.70879 -0.69182 -0.13761 -0.70879 -0.70537 0.0 -0.70879 -0.69182 0.13761 -0.70879 -0.65169 0.26994 -0.70879 -0.5865 0.39189 -0.70879 -0.49876 0.49876 -0.70879 -0.39189 0.5865 -0.70879 -0.26994 0.65169 -0.70879 -0.13761 0.69182 -0.70879 0.0 0.70537 -0.70879 0.13761 0.69182 -0.70879 0.26994 0.65169 -0.70879 0.39189 0.5865 -0.70879 0.49876 0.49876 0.70879 0.5865 0.39189 0.70879 0.65169 0.26994 0.70879 0.69182 0.13761 0.70879 0.70537 0.0 0.70879 0.69182 -0.13761 0.70879 0.65169 -0.26994 0.70879 0.5865 -0.39189 0.70879 0.49876 -0.49876 0.70879 0.39189 -0.5865 0.70879 0.26994 -0.65169 0.70879 0.13761 -0.69182 0.70879 0.0 -0.70537 0.70879 -0.13761 -0.69182 0.70879 -0.26994 -0.65169 0.70879 -0.39189 -0.5865 0.70879 -0.49876 -0.49876 0.70879 -0.5865 -0.39189 0.70879 -0.65169 -0.26994 0.70879 -0.69182 -0.13761 0.70879 -0.70537 0.0 0.70879 -0.69182 0.13761 0.70879 -0.65169 0.26994 0.70879 -0.5865 0.39189 0.70879 -0.49876 0.49876 0.70879 -0.39189 0.5865 0.70879 -0.26994 0.65169 0.70879 -0.13761 0.69182 0.70879 0.0 0.70537 0.70879 0.13761 0.69182 0.70879 0.26994 0.65169 0.70879 0.39189 0.5865 0.70879 0.0 0.0 -1.0 0.0 0.0 1.0 - - - - - - - - - - 1.10675 0.0 0.625 0.0 0.59375 0.0 0.60675 1.0 0.59375 1.0 0.625 1.0 0.10675 0.0 0.59375 0.0 0.5625 0.0 0.60675 1.0 0.5625 1.0 0.59375 1.0 0.10675 0.0 0.5625 0.0 0.53125 0.0 0.60675 1.0 0.53125 1.0 0.5625 1.0 0.10675 0.0 0.53125 0.0 0.5 0.0 0.60675 1.0 0.5 1.0 0.53125 1.0 0.10675 0.0 0.5 0.0 0.46875 0.0 0.60675 1.0 0.46875 1.0 0.5 1.0 0.10675 0.0 0.46875 0.0 0.4375 0.0 0.60675 1.0 0.4375 1.0 0.46875 1.0 0.10675 0.0 0.4375 0.0 0.40625 0.0 0.60675 1.0 0.40625 1.0 0.4375 1.0 0.10675 0.0 0.40625 0.0 0.375 0.0 0.60675 1.0 0.375 1.0 0.40625 1.0 0.10675 0.0 0.375 0.0 0.34375 0.0 0.60675 1.0 0.34375 1.0 0.375 1.0 0.10675 0.0 0.34375 0.0 0.3125 0.0 0.60675 1.0 0.3125 1.0 0.34375 1.0 0.10675 0.0 0.3125 0.0 0.28125 0.0 0.60675 1.0 0.28125 1.0 0.3125 1.0 0.10675 0.0 0.28125 0.0 0.25 0.0 0.60675 1.0 0.25 1.0 0.28125 1.0 0.10675 0.0 0.25 0.0 0.21875 0.0 0.60675 1.0 0.21875 1.0 0.25 1.0 0.10675 0.0 0.21875 0.0 0.1875 0.0 0.60675 1.0 0.1875 1.0 0.21875 1.0 0.10675 0.0 0.1875 0.0 0.15625 0.0 0.60675 1.0 0.15625 1.0 0.1875 1.0 0.10675 0.0 0.15625 0.0 0.125 0.0 0.60675 1.0 0.125 1.0 0.15625 1.0 0.10675 0.0 0.125 0.0 0.09375 0.0 0.60675 1.0 1.09375 1.0 0.125 1.0 0.10675 0.0 0.09375 0.0 0.0625 0.0 0.60675 1.0 1.0625 1.0 1.09375 1.0 0.10675 0.0 0.0625 0.0 0.03125 0.0 0.60675 1.0 1.03125 1.0 1.0625 1.0 1.10675 0.0 1.03125 0.0 1.0 0.0 0.60675 1.0 1.0 1.0 1.03125 1.0 1.10675 0.0 1.0 0.0 0.96875 -0.0 0.60675 1.0 0.96875 1.0 1.0 1.0 1.10675 0.0 0.96875 -0.0 0.9375 -0.0 0.60675 1.0 0.9375 1.0 0.96875 1.0 1.10675 0.0 0.9375 -0.0 0.90625 0.0 0.60675 1.0 0.90625 1.0 0.9375 1.0 1.10675 0.0 0.90625 0.0 0.875 0.0 0.60675 1.0 0.875 1.0 0.90625 1.0 1.10675 0.0 0.875 0.0 0.84375 -0.0 0.60675 1.0 0.84375 1.0 0.875 1.0 1.10675 0.0 0.84375 -0.0 0.8125 -0.0 0.60675 1.0 0.8125 1.0 0.84375 1.0 1.10675 0.0 0.8125 -0.0 0.78125 -0.0 0.60675 1.0 0.78125 1.0 0.8125 1.0 1.10675 0.0 0.78125 -0.0 0.75 -0.0 0.60675 1.0 0.75 1.0 0.78125 1.0 1.10675 0.0 0.75 -0.0 0.71875 -0.0 0.60675 1.0 0.71875 1.0 0.75 1.0 1.10675 0.0 0.71875 -0.0 0.6875 -0.0 0.60675 1.0 0.6875 1.0 0.71875 1.0 1.10675 0.0 0.6875 -0.0 0.65625 -0.0 0.60675 1.0 0.65625 1.0 0.6875 1.0 0.65625 -0.0 0.625 0.0 1.10675 0.0 0.60675 1.0 0.625 1.0 0.65625 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.625 0.0 0.625 1.0 0.59375 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.59375 0.0 0.59375 1.0 0.5625 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.5625 0.0 0.5625 1.0 0.53125 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.53125 0.0 0.53125 1.0 0.5 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.5 0.0 0.5 1.0 0.46875 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.46875 0.0 0.46875 1.0 0.4375 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.4375 0.0 0.4375 1.0 0.40625 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.40625 0.0 0.40625 1.0 0.375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.375 0.0 0.375 1.0 0.34375 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.34375 0.0 0.34375 1.0 0.3125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.3125 0.0 0.3125 1.0 0.28125 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.28125 0.0 0.28125 1.0 0.25 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.25 0.0 0.25 1.0 0.21875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.21875 0.0 0.21875 1.0 0.1875 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.1875 0.0 0.1875 1.0 0.15625 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.15625 0.0 0.15625 1.0 0.125 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.125 0.0 0.125 1.0 0.09375 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.09375 0.0 0.09375 1.0 0.0625 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 0.0625 0.0 0.0625 1.0 0.03125 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.03125 0.0 1.03125 1.0 1.0 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 1.0 0.0 1.0 1.0 0.96875 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.96875 -0.0 0.96875 1.0 0.9375 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.9375 -0.0 0.9375 1.0 0.90625 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.90625 0.0 0.90625 1.0 0.875 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.875 0.0 0.875 1.0 0.84375 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.84375 -0.0 0.84375 1.0 0.8125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.8125 -0.0 0.8125 1.0 0.78125 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.78125 -0.0 0.78125 1.0 0.75 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.75 -0.0 0.75 1.0 0.71875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.71875 -0.0 0.71875 1.0 0.6875 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.6875 -0.0 0.6875 1.0 0.65625 1.0 0.625 1.0 0.625 0.0 0.65625 -0.0 0.625 1.0 0.625 0.0 0.65625 -0.0 - - - - - - - - - - - - - - -

    64 0 0 1 1 2 65 3 33 4 32 5 64 6 1 7 2 8 65 9 34 10 33 11 64 12 2 13 3 14 65 15 35 16 34 17 64 18 3 19 4 20 65 21 36 22 35 23 64 24 4 25 5 26 65 27 37 28 36 29 64 30 5 31 6 32 65 33 38 34 37 35 64 36 6 37 7 38 65 39 39 40 38 41 64 42 7 43 8 44 65 45 40 46 39 47 64 48 8 49 9 50 65 51 41 52 40 53 64 54 9 55 10 56 65 57 42 58 41 59 64 60 10 61 11 62 65 63 43 64 42 65 64 66 11 67 12 68 65 69 44 70 43 71 64 72 12 73 13 74 65 75 45 76 44 77 64 78 13 79 14 80 65 81 46 82 45 83 64 84 14 85 15 86 65 87 47 88 46 89 64 90 15 91 16 92 65 93 48 94 47 95 64 96 16 97 17 98 65 99 49 100 48 101 64 102 17 103 18 104 65 105 50 106 49 107 64 108 18 109 19 110 65 111 51 112 50 113 64 114 19 115 20 116 65 117 52 118 51 119 64 120 20 121 21 122 65 123 53 124 52 125 64 126 21 127 22 128 65 129 54 130 53 131 64 132 22 133 23 134 65 135 55 136 54 137 64 138 23 139 24 140 65 141 56 142 55 143 64 144 24 145 25 146 65 147 57 148 56 149 64 150 25 151 26 152 65 153 58 154 57 155 64 156 26 157 27 158 65 159 59 160 58 161 64 162 27 163 28 164 65 165 60 166 59 167 64 168 28 169 29 170 65 171 61 172 60 173 64 174 29 175 30 176 65 177 62 178 61 179 64 180 30 181 31 182 65 183 63 184 62 185 31 186 0 187 64 188 65 189 32 190 63 191 0 192 32 193 33 194 33 195 1 196 0 197 1 198 33 199 34 200 34 201 2 202 1 203 2 204 34 205 35 206 35 207 3 208 2 209 3 210 35 211 36 212 36 213 4 214 3 215 4 216 36 217 37 218 37 219 5 220 4 221 5 222 37 223 38 224 38 225 6 226 5 227 6 228 38 229 39 230 39 231 7 232 6 233 7 234 39 235 40 236 40 237 8 238 7 239 8 240 40 241 41 242 41 243 9 244 8 245 9 246 41 247 42 248 42 249 10 250 9 251 10 252 42 253 43 254 43 255 11 256 10 257 11 258 43 259 44 260 44 261 12 262 11 263 12 264 44 265 45 266 45 267 13 268 12 269 13 270 45 271 46 272 46 273 14 274 13 275 14 276 46 277 47 278 47 279 15 280 14 281 15 282 47 283 48 284 48 285 16 286 15 287 16 288 48 289 49 290 49 291 17 292 16 293 17 294 49 295 50 296 50 297 18 298 17 299 18 300 50 301 51 302 51 303 19 304 18 305 19 306 51 307 52 308 52 309 20 310 19 311 20 312 52 313 53 314 53 315 21 316 20 317 21 318 53 319 54 320 54 321 22 322 21 323 22 324 54 325 55 326 55 327 23 328 22 329 23 330 55 331 56 332 56 333 24 334 23 335 24 336 56 337 57 338 57 339 25 340 24 341 25 342 57 343 58 344 58 345 26 346 25 347 26 348 58 349 59 350 59 351 27 352 26 353 27 354 59 355 60 356 60 357 28 358 27 359 28 360 60 361 61 362 61 363 29 364 28 365 29 366 61 367 62 368 62 369 30 370 29 371 30 372 62 373 63 374 63 375 31 376 30 377 32 378 0 379 31 380 31 381 63 382 32 383

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.5076 0.17099 0.5076 0.02724 0.81102 0.02724 0.5076 0.17099 0.5076 0.02724 0.81102 0.02724 0.5076 0.17099 0.81102 0.17099 0.81102 0.02724 0.5076 0.17099 0.81102 0.17099 0.81102 0.02724 0.2494 0.17099 0.10396 0.17099 0.10396 0.02724 0.2494 0.17099 0.10396 0.17099 0.10396 0.02724 0.2494 0.48019 0.10396 0.48019 0.10396 0.78361 0.2494 0.48019 0.10396 0.48019 0.10396 0.78361 0.2494 0.67389 0.10396 0.67389 0.10396 0.81764 0.2494 0.67389 0.10396 0.67389 0.10396 0.81764 0.7506 0.48019 0.89604 0.48019 0.89604 0.78361 0.7506 0.48019 0.89604 0.48019 0.89604 0.78361 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.22491 -0.46923 0.2223 0.22491 -0.46923 -0.2223 0.22491 0.46923 -0.2223 0.22491 0.46923 0.2223 -0.22491 -0.46923 0.2223 -0.22491 -0.46923 -0.2223 -0.22491 0.46923 -0.2223 -0.22491 0.46923 0.2223 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 1.0 -1.0 1.0 1.0 - - - - - - - - - - 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 1.0 3.0 0.5 1.0 3.0 -0.5 -1.0 3.0 -0.5 -1.0 3.0 0.5 1.0 -3.0 0.5 1.0 -3.0 -0.5 -1.0 -3.0 -0.5 -1.0 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 0.5 -0.49 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 0.5 0.01 -0.5 0.01 -0.5 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.5 0.0 0.5 -3.0 -0.5 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.5 0.0 0.5 3.0 -0.5 3.0 0.5 0.0 0.5 3.0 -0.5 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.97962 3.0 0.5 0.97962 3.0 -0.5 -0.97962 3.0 -0.5 -0.97962 3.0 0.5 0.97962 -3.0 0.5 0.97962 -3.0 -0.5 -0.97962 -3.0 -0.5 -0.97962 -3.0 0.5 - - - - - - - - - - 0.57735 0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 - - - - - - - - - - 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 0.48981 -0.49 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 0.48981 0.01 -0.48981 0.01 -0.48981 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 1.0 0.01 -2.0 0.01 -2.0 -0.49 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.48981 0.0 0.48981 -3.0 -0.48981 -3.0 0.0 0.51 -3.0 0.51 -3.0 1.01 0.0 0.51 -3.0 0.51 -3.0 1.01 0.48981 0.0 0.48981 3.0 -0.48981 3.0 0.48981 0.0 0.48981 3.0 -0.48981 3.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 0.47933 -1.0 0.47376 0.47933 -1.0 -0.47376 0.47933 1.0 -0.47376 0.47933 1.0 0.47376 -0.47933 -1.0 0.47376 -0.47933 -1.0 -0.47376 -0.47933 1.0 -0.47376 -0.47933 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - - - - - -

    0 1 2 2 3 0 4 7 6 6 5 4 0 4 5 5 1 0 1 5 6 6 2 1 2 6 7 7 3 2 4 0 3 3 7 4

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -1.0 0.47376 3.0 -1.0 -0.47376 3.0 1.0 -0.47376 3.0 1.0 0.47376 -3.0 -1.0 0.47376 -3.0 -1.0 -0.47376 -3.0 1.0 -0.47376 -3.0 1.0 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 0.49688 0.0 0.02312 1.0 0.02312 0.0 0.49688 0.0 0.02312 1.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 1.0 0.49688 2.0 0.49688 2.0 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.49688 -2.5 0.49688 -2.5 0.02312 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.0 -2.5 0.0 -2.5 1.0 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 0.02312 -2.5 0.02312 -2.5 0.49688 0.5 1.0 3.5 1.0 3.5 2.0 0.5 1.0 3.5 1.0 3.5 2.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 3.0 -0.98953 0.47376 3.0 -0.98953 -0.47376 3.0 0.98953 -0.47376 3.0 0.98953 0.47376 -3.0 -0.98954 0.47376 -3.0 -0.98953 -0.47376 -3.0 0.98953 -0.47376 -3.0 0.98953 0.47376 - - - - - - - - - - 0.57735 -0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 -0.57735 0.57735 0.57735 0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 -0.57735 -0.57735 0.57735 -0.57735 -0.57735 0.57735 0.57735 - - - - - - - - - - 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 - - - - - - - - - - - - - - -

    0 0 1 1 2 2 2 3 3 4 0 5 4 6 7 7 6 8 6 9 5 10 4 11 0 12 4 13 5 14 5 15 1 16 0 17 1 18 5 19 6 20 6 21 2 22 1 23 2 24 6 25 7 26 7 27 3 28 2 29 4 30 0 31 3 32 3 33 7 34 4 35

    -
    -
    -
    - - - - 15.68421 15.68421 0.0 15.68421 -15.68421 0.0 -15.68421 -15.68421 0.0 -15.6842 15.68421 0.0 0.0 15.68421 0.0 -15.68421 0.0 0.0 0.0 -15.68421 0.0 15.68421 -0.0 0.0 0.0 -0.0 0.0 7.84211 15.68421 0.0 -7.8421 15.68421 0.0 -15.68421 -7.8421 0.0 -15.68421 7.84211 0.0 7.84211 -15.68421 0.0 -7.84211 -15.68421 0.0 15.68421 7.8421 0.0 15.68421 -7.84211 0.0 -7.8421 0.0 0.0 0.0 7.8421 0.0 7.84211 -0.0 0.0 0.0 -7.84211 0.0 -7.8421 7.84211 0.0 7.84211 7.8421 0.0 -7.8421 -7.84211 0.0 7.84211 -7.84211 0.0 - - - - - - - - - - 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 - - - - - - - - - - - - - - -

    10 3 12 12 21 10 4 10 21 21 18 4 21 12 5 5 17 21 18 21 17 17 8 18 9 4 18 18 22 9 0 9 22 22 15 0 22 18 8 8 19 22 15 22 19 19 7 15 17 5 11 11 23 17 8 17 23 23 20 8 23 11 2 2 14 23 20 23 14 14 6 20 19 8 20 20 24 19 7 19 24 24 16 7 24 20 6 6 13 24 16 24 13 13 1 16

    -
    -
    -
    - - - - d:/bullet_logo.JPG - - - - - - - 1.0 1.0 0.71397 - 0.0 - 0.0 - 0.0 - - - - - - - - - - - - - - - - - - - - - - -14.55524 -12.21748 -0.85392 - 0.0 0.0 1.0 -0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 90.0 - - - - - - - - -14.51144 -12.21746 1.49207 - 0.0 0.0 1.0 -0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 90.0 - 0.59992 0.59992 0.59992 - - - - - - - - -10.54595 9.00056 -7.95634 - 0.0 0.0 1.0 161.23931 - 0.0 1.0 0.0 7.87085 - 1.0 0.0 0.0 -1.43785 - - - - - - - - - - -11.51412 -12.21752 -6.47685 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -40.16574 - 1.0 0.0 0.0 89.99999 - - - - - - - - - - -10.80608 -12.21753 -8.20963 - 0.0 0.0 1.0 179.99999 - 0.0 1.0 0.0 -68.68968 - 1.0 0.0 0.0 -90.0 - - - - - - - - - - -12.13872 -12.21753 -8.73677 - 0.0 0.0 1.0 -0.0 - 0.0 1.0 0.0 61.88929 - 1.0 0.0 0.0 89.99999 - - - - - - - - - - -11.09567 -3.46707 -5.6227 - 0.0 0.0 1.0 13.53526 - 0.0 1.0 0.0 -3.36769 - 1.0 0.0 0.0 31.10502 - - - - - - - - - - -5.6758 9.44806 -7.98855 - 0.0 0.0 1.0 90.0 - 0.0 1.0 0.0 -30.45178 - 1.0 0.0 0.0 90.0 - - - - 5.76483 -5.12569 1.3994 - 0.0 0.0 1.0 -5.78135 - 0.0 1.0 0.0 8.39643 - 1.0 0.0 0.0 -226.35694 - - - - - - - - - - -4.6651 -3.31256 -8.47664 - 0.0 0.0 1.0 165.33786 - 0.0 1.0 0.0 -9.4701 - 1.0 0.0 0.0 164.1133 - - - - - - - - - - 12.0373 6.52345 -7.84086 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 -36.81686 - - - - - - - - - - 10.69918 0.32979 -8.69131 - 0.0 0.0 1.0 -38.06934 - 0.0 1.0 0.0 0.0 - 1.0 0.0 0.0 0.0 - - - - - - - - - - 10.6716 0.3339 -6.5472 - 0.0 0.0 1.0 -38.06934 - 0.0 1.0 0.0 0.0 - 1.0 0.0 0.0 0.0 - - - - - - - - - - 10.64675 0.37131 -4.4428 - 0.0 0.0 1.0 -38.06934 - 0.0 1.0 0.0 0.0 - 1.0 0.0 0.0 0.0 - - - - - - - - - - 13.39988 -6.62079 -7.48373 - 0.0 0.0 1.0 -23.42368 - 0.0 1.0 0.0 -47.70962 - 1.0 0.0 0.0 14.68375 - - - - - - - - - - 1.07068 1.0946 -9.17122 - - - - - - - - - - 3.07068 1.0946 -9.17122 - - - - - - - - - - -0.92932 1.0946 -9.17122 - - - - - - - - - - -0.92932 1.0946 -7.17122 - - - - - - - - - - 3.07068 1.0946 -7.17122 - - - - - - - - - - 1.07068 1.0946 -7.17122 - - - - - - - - - - 1.07068 3.0946 -8.17122 - - - - - - - - - - 1.07068 -0.9054 -8.17122 - - - - - - - - - - 1.07068 1.0946 -8.17122 - - - - - - - - - - 1.07068 1.0946 -6.17122 - - - - - - - - - - 1.07068 -0.9054 -6.17122 - - - - - - - - - - 1.07068 3.0946 -6.17122 - - - - - - - - - - 1.07068 1.0946 -5.17122 - - - - - - - - - - 3.07068 1.0946 -5.17122 - - - - - - - - - - -0.92932 1.0946 -5.17122 - - - - - - - - - - -0.92932 1.0946 -3.17122 - - - - - - - - - - 3.07068 1.0946 -3.17122 - - - - - - - - - - 1.07068 1.0946 -3.17122 - - - - - - - - - - 1.07068 3.0946 -4.17122 - - - - - - - - - - 1.07068 -0.9054 -4.17122 - - - - - - - - - - 1.07068 1.0946 -4.17122 - - - - - - - - - - 1.07068 1.0946 -2.17122 - - - - - - - - - - 1.07068 -0.9054 -2.17122 - - - - - - - - - - 1.07068 3.0946 -2.17122 - - - - - - - - - - 1.07068 1.0946 -1.17122 - - - - - - - - - - 3.07068 1.0946 -1.17122 - - - - - - - - - - -0.92932 1.0946 -1.17122 - - - - - - - - - - -0.92932 1.0946 0.82878 - - - - - - - - - - 3.07068 1.0946 0.82878 - - - - - - - - - - 1.07068 1.0946 0.82878 - - - - - - - - - - 1.07068 3.0946 -0.17122 - - - - - - - - - - 1.07068 -0.9054 -0.17122 - - - - - - - - - - 1.07068 1.0946 -0.17122 - - - - - - - - - - 1.07068 1.0946 1.82878 - - - - - - - - - - 1.07068 -0.9054 1.82878 - - - - - - - - - - 1.07068 3.0946 1.82878 - - - - - - - - - - 1.07068 1.0946 2.82878 - - - - - - - - - - 3.07068 1.0946 2.82878 - - - - - - - - - - -0.92932 1.0946 2.82878 - - - - - - - - - - 1.07068 -12.41267 -2.84635 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 -146.99812 - - - - - - - - - - 1.07068 -12.65713 -3.97696 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 -146.99812 - - - - - - - - - - 1.07068 -12.93214 -4.92423 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 -146.99812 - - - - - - - - - - 1.07068 -15.19337 -5.0159 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 -146.99812 - - - - - - - - - - 1.07068 -13.57384 -7.5827 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 -0.0 - 1.0 0.0 0.0 -146.99812 - - - - - - - - - - 0.62583 12.00328 -8.00472 - 0.0 0.0 1.0 3.21265 - 0.0 1.0 0.0 -12.03335 - 1.0 0.0 0.0 66.50218 - - - - - - - - - - 1.28844 9.15244 -3.68906 - - - - 1.07068 -7.9054 -7.17122 - - - - - - - - - - 1.07068 -8.9054 -8.17122 - - - - - - - - - - 1.07068 -6.9054 -8.17122 - - - - - - - - - - 1.07068 -7.9054 -9.17122 - - - - - - - - - - -6.69969 -10.22419 -7.75589 - 0.0 0.0 1.0 -0.18482 - 0.0 1.0 0.0 -14.9718 - 1.0 0.0 0.0 -1.78118 - - - - - - - - - - 3.07068 1.0946 4.82878 - - - - - - - - - - 1.07068 1.0946 4.82878 - - - - - - - - - - 1.07068 -5.9054 -9.17122 - - - - - - - - - - 1.07068 3.0946 3.82878 - - - - - - - - - - 1.07068 -0.9054 3.82878 - - - - - - - - - - 1.07068 1.0946 3.82878 - - - - - - - - - - 0.31712 0.02145 -9.78565 - - - - - - - - - - 9.62214 -5.88949 -0.13709 - 0.0 0.0 1.0 106.93632 - 0.0 1.0 0.0 3.16371 - 1.0 0.0 0.0 37.26105 - - - - -7.40201 -33.19793 -3.19828 - 0.0 0.0 1.0 0.0 - 0.0 1.0 0.0 0.0 - 1.0 0.0 0.0 90.0 - - - - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - - - - - - - - 2.358 0.3455 0.0 - - - false - 1.0 - - - - - - - - - - 7.3295 1.456 0.0 - - - false - 1.0 - - - - - - - - - - 1.0 - 1.0 - 0 0 - 1.0 - - - true - 1.0 - - - - - - - - - - - true - 1.0 - - - - - - - - - - - true - 1.0 - - - - - - - - - - - true - 1.0 - - - - - - - - - - 1.4 - - - true - 1.0 - - - - - - - - - - 1.0 1.0 1.0 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 0 0 - 0.42013 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 0 0 - 1.0 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 1.0 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 1.0 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 1.0 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 1.0 - - - true - 1.0 - - - - - - - - - - 1.0 - 1.0 - 1.0 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 0.22491 0.46923 0.2223 - - - true - 1.0 - - - - - - - - - - 0.22491 0.46923 0.2223 - - - true - 1.0 - - - - - - - - - - 0.22491 0.46923 0.2223 - - - true - 1.0 - - - - - - - - - - 0.22491 0.46923 0.2223 - - - true - 1.0 - - - - - - - - - - 0.22491 0.46923 0.2223 - - - true - 1.0 - - - - - - - - - - 0.47933 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 1.0 1.0 1.0 - - - false - 1.0 - - - - - - - - - - 0.47933 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 0.47933 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 0.47933 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 0.47933 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 1.0 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 0.97962 3.0 0.5 - - - true - 1.0 - - - - - - - - - - 0.47933 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 1.0 0.47376 - - - true - 1.0 - - - - - - - - - - 3.0 0.98954 0.47376 - - - true - 1.0 - - - - - - - - - - - false - 1.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 -9.810000 - 0.0166666 - - - - - - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt deleted file mode 100644 index dcc54277..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt +++ /dev/null @@ -1,126 +0,0 @@ -INCLUDE_DIRECTORIES( - ${BULLET_PHYSICS_SOURCE_DIR}/src - ${VECTOR_MATH_INCLUDE} -) - -SET(BulletMultiThreaded_SRCS - SpuFakeDma.cpp - SpuLibspe2Support.cpp - btThreadSupportInterface.cpp - Win32ThreadSupport.cpp - PosixThreadSupport.cpp - SequentialThreadSupport.cpp - SpuSampleTaskProcess.cpp - SpuCollisionObjectWrapper.cpp - SpuCollisionTaskProcess.cpp - SpuGatheringCollisionDispatcher.cpp - SpuContactManifoldCollisionAlgorithm.cpp - btParallelConstraintSolver.cpp - - #SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.cpp - #SpuPEGatherScatterTaskProcess.cpp - - SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp - SpuNarrowPhaseCollisionTask/SpuContactResult.cpp - SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp - SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp - SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp - - #Some GPU related stuff, mainly CUDA and perhaps OpenCL - btGpu3DGridBroadphase.cpp -) - -SET(Root_HDRS - PlatformDefinitions.h - PpuAddressSpace.h - SpuFakeDma.h - SpuDoubleBuffer.h - SpuLibspe2Support.h - btThreadSupportInterface.h - Win32ThreadSupport.h - PosixThreadSupport.h - SequentialThreadSupport.h - SpuSampleTaskProcess.h - SpuCollisionObjectWrapper.cpp - SpuCollisionObjectWrapper.h - SpuCollisionTaskProcess.h - SpuGatheringCollisionDispatcher.h - SpuContactManifoldCollisionAlgorithm.h - btParallelConstraintSolver.h - - #SPURS_PEGatherScatterTask/SpuPEGatherScatterTask.h - #SpuPEGatherScatterTaskProcess.h - - #Some GPU related stuff, mainly CUDA and perhaps OpenCL - btGpu3DGridBroadphase.h - btGpu3DGridBroadphaseSharedCode.h - btGpu3DGridBroadphaseSharedDefs.h - btGpu3DGridBroadphaseSharedTypes.h - btGpuDefines.h - btGpuUtilsSharedCode.h - btGpuUtilsSharedDefs.h -) - -SET(SpuNarrowPhaseCollisionTask_HDRS - SpuNarrowPhaseCollisionTask/Box.h - SpuNarrowPhaseCollisionTask/boxBoxDistance.h - SpuNarrowPhaseCollisionTask/SpuContactResult.h - SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h - SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h - SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h - SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h - SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h -) - -SET(BulletMultiThreaded_HDRS - ${Root_HDRS} - ${SpuNarrowPhaseCollisionTask_HDRS} -) - -ADD_LIBRARY(BulletMultiThreaded ${BulletMultiThreaded_SRCS} ${BulletMultiThreaded_HDRS}) -SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES SOVERSION ${BULLET_VERSION}) - - -SUBDIRS(GpuSoftBodySolvers) - - -IF (BUILD_SHARED_LIBS) - IF (UNIX) - TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision pthread) - ELSE() - TARGET_LINK_LIBRARIES(BulletMultiThreaded BulletDynamics BulletCollision) - ENDIF() -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - #INSTALL of other files requires CMake 2.6 - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) -# IF(INSTALL_EXTRA_LIBS) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletMultiThreaded DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletMultiThreaded - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) - INSTALL(DIRECTORY -${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING -PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) -# ENDIF (INSTALL_EXTRA_LIBS) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES FRAMEWORK true) - - SET_TARGET_PROPERTIES(BulletMultiThreaded PROPERTIES PUBLIC_HEADER "${Root_HDRS}") - # Have to list out sub-directories manually: - SET_PROPERTY(SOURCE ${SpuNarrowPhaseCollisionTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/SpuNarrowPhaseCollisionTask) - - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt deleted file mode 100644 index 224a3e0a..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src -) - - -SUBDIRS ( - OpenCL -) - -IF( USE_DX11 ) - SUBDIRS( DX11 ) -ENDIF( USE_DX11 ) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt deleted file mode 100644 index 52f335d2..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt +++ /dev/null @@ -1,86 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src -) - -SET(DXSDK_DIR $ENV{DXSDK_DIR}) -SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Microsoft directX SDK include path") - - -INCLUDE_DIRECTORIES( -${DX11_INCLUDE_PATH} "../Shared/" -${VECTOR_MATH_INCLUDE} -) - -SET(BulletSoftBodyDX11Solvers_SRCS - btSoftBodySolver_DX11.cpp - btSoftBodySolver_DX11SIMDAware.cpp -) - -SET(BulletSoftBodyDX11Solvers_HDRS - btSoftBodySolver_DX11.h - btSoftBodySolver_DX11SIMDAware.h - ../Shared/btSoftBodySolverData.h - btSoftBodySolverVertexData_DX11.h - btSoftBodySolverTriangleData_DX11.h - btSoftBodySolverLinkData_DX11.h - btSoftBodySolverLinkData_DX11SIMDAware.h - btSoftBodySolverBuffer_DX11.h - btSoftBodySolverVertexBuffer_DX11.h - -) - -# OpenCL and HLSL Shaders. -# Build rules generated to stringify these into headers -# which are needed by some of the sources -SET(BulletSoftBodyDX11Solvers_Shaders - OutputToVertexArray - UpdateNormals - Integrate - UpdatePositions - UpdateNodes - ComputeBounds - SolvePositions - SolvePositionsSIMDBatched - SolveCollisionsAndUpdateVelocities - SolveCollisionsAndUpdateVelocitiesSIMDBatched - UpdatePositionsFromVelocities - ApplyForces - PrepareLinks - VSolveLinks -) - -foreach(f ${BulletSoftBodyDX11Solvers_Shaders}) - LIST(APPEND BulletSoftBodyDX11Solvers_HLSL "HLSL/${f}.hlsl") -endforeach(f) - - - -ADD_LIBRARY(BulletSoftBodySolvers_DX11 ${BulletSoftBodyDX11Solvers_SRCS} ${BulletSoftBodyDX11Solvers_HDRS} ${BulletSoftBodyDX11Solvers_HLSL}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_DX11 BulletSoftBody BulletDynamics) -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_DX11 - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -#headers are already installed by BulletMultiThreaded library - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES PUBLIC_HEADER "${BulletSoftBodyDX11Solvers_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl deleted file mode 100644 index 37e22695..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ApplyForces.hlsl +++ /dev/null @@ -1,95 +0,0 @@ -MSTRINGIFY( - -cbuffer ApplyForcesCB : register( b0 ) -{ - unsigned int numNodes; - float solverdt; - float epsilon; - int padding3; -}; - - -StructuredBuffer g_vertexClothIdentifier : register( t0 ); -StructuredBuffer g_vertexNormal : register( t1 ); -StructuredBuffer g_vertexArea : register( t2 ); -StructuredBuffer g_vertexInverseMass : register( t3 ); -// TODO: These could be combined into a lift/drag factor array along with medium density -StructuredBuffer g_clothLiftFactor : register( t4 ); -StructuredBuffer g_clothDragFactor : register( t5 ); -StructuredBuffer g_clothWindVelocity : register( t6 ); -StructuredBuffer g_clothAcceleration : register( t7 ); -StructuredBuffer g_clothMediumDensity : register( t8 ); - -RWStructuredBuffer g_vertexForceAccumulator : register( u0 ); -RWStructuredBuffer g_vertexVelocity : register( u1 ); - -float3 projectOnAxis( float3 v, float3 a ) -{ - return (a*dot(v, a)); -} - -[numthreads(128, 1, 1)] -void -ApplyForcesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - unsigned int nodeID = DTid.x; - if( nodeID < numNodes ) - { - int clothId = g_vertexClothIdentifier[nodeID]; - float nodeIM = g_vertexInverseMass[nodeID]; - - if( nodeIM > 0.0f ) - { - float3 nodeV = g_vertexVelocity[nodeID].xyz; - float3 normal = g_vertexNormal[nodeID].xyz; - float area = g_vertexArea[nodeID]; - float3 nodeF = g_vertexForceAccumulator[nodeID].xyz; - - // Read per-cloth values - float3 clothAcceleration = g_clothAcceleration[clothId].xyz; - float3 clothWindVelocity = g_clothWindVelocity[clothId].xyz; - float liftFactor = g_clothLiftFactor[clothId]; - float dragFactor = g_clothDragFactor[clothId]; - float mediumDensity = g_clothMediumDensity[clothId]; - - // Apply the acceleration to the cloth rather than do this via a force - nodeV += (clothAcceleration*solverdt); - - g_vertexVelocity[nodeID] = float4(nodeV, 0.f); - - float3 relativeWindVelocity = nodeV - clothWindVelocity; - float relativeSpeedSquared = dot(relativeWindVelocity, relativeWindVelocity); - - if( relativeSpeedSquared > epsilon ) - { - // Correct direction of normal relative to wind direction and get dot product - normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : 1.f); - float dvNormal = dot(normal, relativeWindVelocity); - if( dvNormal > 0 ) - { - float3 force = float3(0.f, 0.f, 0.f); - float c0 = area * dvNormal * relativeSpeedSquared / 2.f; - float c1 = c0 * mediumDensity; - force += normal * (-c1 * liftFactor); - force += normalize(relativeWindVelocity)*(-c1 * dragFactor); - - float dtim = solverdt * nodeIM; - float3 forceDTIM = force * dtim; - - float3 nodeFPlusForce = nodeF + force; - - // m_nodesf[i] -= ProjectOnAxis(m_nodesv[i], force.normalized())/dtim; - float3 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim); - - nodeF = nodeFPlusForce; - if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) ) - nodeF = nodeFMinus; - - g_vertexForceAccumulator[nodeID] = float4(nodeF, 0.0f); - } - } - } - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl deleted file mode 100644 index 65ae515c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/ComputeBounds.hlsl +++ /dev/null @@ -1,83 +0,0 @@ -MSTRINGIFY( - -cbuffer ComputeBoundsCB : register( b0 ) -{ - int numNodes; - int numSoftBodies; - int padding1; - int padding2; -}; - -// Node indices for each link -StructuredBuffer g_vertexClothIdentifier : register( t0 ); -StructuredBuffer g_vertexPositions : register( t1 ); - -RWStructuredBuffer g_clothMinBounds : register( u0 ); -RWStructuredBuffer g_clothMaxBounds : register( u1 ); - -groupshared uint4 clothMinBounds[256]; -groupshared uint4 clothMaxBounds[256]; - -[numthreads(128, 1, 1)] -void -ComputeBoundsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - const unsigned int UINT_MAX = 0xffffffff; - - // Init min and max bounds arrays - if( GTid.x < numSoftBodies ) - { - clothMinBounds[GTid.x] = uint4(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX); - clothMaxBounds[GTid.x] = uint4(0,0,0,0); - } - - AllMemoryBarrierWithGroupSync(); - - int nodeID = DTid.x; - if( nodeID < numNodes ) - { - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - if( clothIdentifier >= 0 ) - { - float3 position = g_vertexPositions[nodeID].xyz; - - // Reinterpret position as uint - uint3 positionUInt = uint3(asuint(position.x), asuint(position.y), asuint(position.z)); - - // Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints - //positionUInt.x ^= uint((-int(positionUInt.x >> 31) | 0x80000000)); - //positionUInt.y ^= uint((-int(positionUInt.y >> 31) | 0x80000000)); - //positionUInt.z ^= uint((-int(positionUInt.z >> 31) | 0x80000000)); - positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000); - positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000); - positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000); - - // Min/max with the LDS values - InterlockedMin(clothMinBounds[clothIdentifier].x, positionUInt.x); - InterlockedMin(clothMinBounds[clothIdentifier].y, positionUInt.y); - InterlockedMin(clothMinBounds[clothIdentifier].z, positionUInt.z); - - InterlockedMax(clothMaxBounds[clothIdentifier].x, positionUInt.x); - InterlockedMax(clothMaxBounds[clothIdentifier].y, positionUInt.y); - InterlockedMax(clothMaxBounds[clothIdentifier].z, positionUInt.z); - } - } - - AllMemoryBarrierWithGroupSync(); - - - // Use global atomics to update the global versions of the data - if( GTid.x < numSoftBodies ) - { - InterlockedMin(g_clothMinBounds[GTid.x].x, clothMinBounds[GTid.x].x); - InterlockedMin(g_clothMinBounds[GTid.x].y, clothMinBounds[GTid.x].y); - InterlockedMin(g_clothMinBounds[GTid.x].z, clothMinBounds[GTid.x].z); - - InterlockedMax(g_clothMaxBounds[GTid.x].x, clothMaxBounds[GTid.x].x); - InterlockedMax(g_clothMaxBounds[GTid.x].y, clothMaxBounds[GTid.x].y); - InterlockedMax(g_clothMaxBounds[GTid.x].z, clothMaxBounds[GTid.x].z); - } -} - - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl deleted file mode 100644 index f85fd115..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/Integrate.hlsl +++ /dev/null @@ -1,41 +0,0 @@ -MSTRINGIFY( - -cbuffer IntegrateCB : register( b0 ) -{ - int numNodes; - float solverdt; - int padding1; - int padding2; -}; - -// Node indices for each link -StructuredBuffer g_vertexInverseMasses : register( t0 ); - -RWStructuredBuffer g_vertexPositions : register( u0 ); -RWStructuredBuffer g_vertexVelocity : register( u1 ); -RWStructuredBuffer g_vertexPreviousPositions : register( u2 ); -RWStructuredBuffer g_vertexForceAccumulator : register( u3 ); - -[numthreads(128, 1, 1)] -void -IntegrateKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - if( nodeID < numNodes ) - { - float3 position = g_vertexPositions[nodeID].xyz; - float3 velocity = g_vertexVelocity[nodeID].xyz; - float3 force = g_vertexForceAccumulator[nodeID].xyz; - float inverseMass = g_vertexInverseMasses[nodeID]; - - g_vertexPreviousPositions[nodeID] = float4(position, 0.f); - velocity += force * inverseMass * solverdt; - position += velocity * solverdt; - - g_vertexForceAccumulator[nodeID] = float4(0.f, 0.f, 0.f, 0.0f); - g_vertexPositions[nodeID] = float4(position, 0.f); - g_vertexVelocity[nodeID] = float4(velocity, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl deleted file mode 100644 index a6fa7b95..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/OutputToVertexArray.hlsl +++ /dev/null @@ -1,63 +0,0 @@ -MSTRINGIFY( - -cbuffer OutputToVertexArrayCB : register( b0 ) -{ - int startNode; - int numNodes; - int positionOffset; - int positionStride; - - int normalOffset; - int normalStride; - int padding1; - int padding2; -}; - - -StructuredBuffer g_vertexPositions : register( t0 ); -StructuredBuffer g_vertexNormals : register( t1 ); - -RWBuffer g_vertexBuffer : register( u0 ); - - -[numthreads(128, 1, 1)] -void -OutputToVertexArrayWithNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID + startNode]; - float4 normal = g_vertexNormals[nodeID + startNode]; - - // Stride should account for the float->float4 conversion - int positionDestination = nodeID * positionStride + positionOffset; - g_vertexBuffer[positionDestination] = position.x; - g_vertexBuffer[positionDestination+1] = position.y; - g_vertexBuffer[positionDestination+2] = position.z; - - int normalDestination = nodeID * normalStride + normalOffset; - g_vertexBuffer[normalDestination] = normal.x; - g_vertexBuffer[normalDestination+1] = normal.y; - g_vertexBuffer[normalDestination+2] = normal.z; - } -} - -[numthreads(128, 1, 1)] -void -OutputToVertexArrayWithoutNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID + startNode]; - float4 normal = g_vertexNormals[nodeID + startNode]; - - // Stride should account for the float->float4 conversion - int positionDestination = nodeID * positionStride + positionOffset; - g_vertexBuffer[positionDestination] = position.x; - g_vertexBuffer[positionDestination+1] = position.y; - g_vertexBuffer[positionDestination+2] = position.z; - } -} -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl deleted file mode 100644 index 75db8d14..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/PrepareLinks.hlsl +++ /dev/null @@ -1,44 +0,0 @@ -MSTRINGIFY( - -cbuffer PrepareLinksCB : register( b0 ) -{ - int numLinks; - int padding0; - int padding1; - int padding2; -}; - -// Node indices for each link -StructuredBuffer g_linksVertexIndices : register( t0 ); -StructuredBuffer g_linksMassLSC : register( t1 ); -StructuredBuffer g_nodesPreviousPosition : register( t2 ); - -RWStructuredBuffer g_linksLengthRatio : register( u0 ); -RWStructuredBuffer g_linksCurrentLength : register( u1 ); - -[numthreads(128, 1, 1)] -void -PrepareLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int linkID = DTid.x; - if( linkID < numLinks ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - - float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0]; - float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1]; - - float massLSC = g_linksMassLSC[linkID]; - - float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0; - - float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC; - linkLengthRatio = 1./linkLengthRatio; - - g_linksCurrentLength[linkID] = linkCurrentLength; - g_linksLengthRatio[linkID] = linkLengthRatio; - } -} -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl deleted file mode 100644 index de979d7f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositions.hlsl +++ /dev/null @@ -1,55 +0,0 @@ -MSTRINGIFY( - -cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) -{ - int startLink; - int numLinks; - float kst; - float ti; -}; - -// Node indices for each link -StructuredBuffer g_linksVertexIndices : register( t0 ); - -StructuredBuffer g_linksMassLSC : register( t1 ); -StructuredBuffer g_linksRestLengthSquared : register( t2 ); -StructuredBuffer g_verticesInverseMass : register( t3 ); - -RWStructuredBuffer g_vertexPositions : register( u0 ); - -[numthreads(128, 1, 1)] -void -SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int linkID = DTid.x + startLink; - if( DTid.x < numLinks ) - { - float massLSC = g_linksMassLSC[linkID]; - float restLengthSquared = g_linksRestLengthSquared[linkID]; - - if( massLSC > 0.0f ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - - float3 position0 = g_vertexPositions[node0].xyz; - float3 position1 = g_vertexPositions[node1].xyz; - - float inverseMass0 = g_verticesInverseMass[node0]; - float inverseMass1 = g_verticesInverseMass[node1]; - - float3 del = position1 - position0; - float len = dot(del, del); - float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; - position0 = position0 - del*(k*inverseMass0); - position1 = position1 + del*(k*inverseMass1); - - g_vertexPositions[node0] = float4(position0, 0.f); - g_vertexPositions[node1] = float4(position1, 0.f); - - } - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl deleted file mode 100644 index 3cbb352e..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/SolvePositionsSIMDBatched.hlsl +++ /dev/null @@ -1,147 +0,0 @@ -MSTRINGIFY( - - - -cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) -{ - int startWaveInBatch; - int numWaves; - float kst; - float ti; -}; - - -// Number of batches per wavefront stored one element per logical wavefront -StructuredBuffer g_wavefrontBatchCountsVertexCounts : register( t0 ); -// Set of up to maxNumVertices vertex addresses per wavefront -StructuredBuffer g_vertexAddressesPerWavefront : register( t1 ); - -StructuredBuffer g_verticesInverseMass : register( t2 ); - -// Per-link data layed out structured in terms of sub batches within wavefronts -StructuredBuffer g_linksVertexIndices : register( t3 ); -StructuredBuffer g_linksMassLSC : register( t4 ); -StructuredBuffer g_linksRestLengthSquared : register( t5 ); - -RWStructuredBuffer g_vertexPositions : register( u0 ); - -// Data loaded on a per-wave basis -groupshared int2 wavefrontBatchCountsVertexCounts[WAVEFRONT_BLOCK_MULTIPLIER]; -groupshared float4 vertexPositionSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; -groupshared float vertexInverseMassSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; - -// Storing the vertex addresses actually slowed things down a little -//groupshared int vertexAddressSharedData[MAX_NUM_VERTICES_PER_WAVE*WAVEFRONT_BLOCK_MULTIPLIER]; - - -[numthreads(BLOCK_SIZE, 1, 1)] -void -SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - const int laneInWavefront = (DTid.x & (WAVEFRONT_SIZE-1)); - const int wavefront = startWaveInBatch + (DTid.x / WAVEFRONT_SIZE); - const int firstWavefrontInBlock = startWaveInBatch + Gid.x * WAVEFRONT_BLOCK_MULTIPLIER; - const int localWavefront = wavefront - firstWavefrontInBlock; - - int batchesWithinWavefront = 0; - int verticesUsedByWave = 0; - int cond = wavefront < (startWaveInBatch + numWaves); - - // Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier - if( cond) - { - - // Load the batch counts for the wavefronts - - int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront]; - - batchesWithinWavefront = batchesAndVerticesWithinWavefront.x; - verticesUsedByWave = batchesAndVerticesWithinWavefront.y; - - // Load the vertices for the wavefronts - for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) - { - int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; - - //vertexAddressSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = vertexAddress; - vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress]; - vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress]; - } - - } - // Ensure compiler does not re-order memory operations - //AllMemoryBarrier(); - AllMemoryBarrierWithGroupSync (); - - if( cond) - { - // Loop through the batches performing the solve on each in LDS - int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE; - - //for( int batch = 0; batch < batchesWithinWavefront; ++batch ) - - int batch = 0; - do - { - int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch; - int locationOfValue = baseDataLocation + laneInWavefront; - - - // These loads should all be perfectly linear across the WF - int2 localVertexIndices = g_linksVertexIndices[locationOfValue]; - float massLSC = g_linksMassLSC[locationOfValue]; - float restLengthSquared = g_linksRestLengthSquared[locationOfValue]; - - - // LDS vertex addresses based on logical wavefront number in block and loaded index - int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x; - int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y; - - float3 position0 = vertexPositionSharedData[vertexAddress0].xyz; - float3 position1 = vertexPositionSharedData[vertexAddress1].xyz; - - float inverseMass0 = vertexInverseMassSharedData[vertexAddress0]; - float inverseMass1 = vertexInverseMassSharedData[vertexAddress1]; - - float3 del = position1 - position0; - float len = dot(del, del); - - float k = 0; - if( massLSC > 0.0f ) - { - k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; - } - - position0 = position0 - del*(k*inverseMass0); - position1 = position1 + del*(k*inverseMass1); - - // Ensure compiler does not re-order memory operations - AllMemoryBarrier(); - - vertexPositionSharedData[vertexAddress0] = float4(position0, 0.f); - vertexPositionSharedData[vertexAddress1] = float4(position1, 0.f); - - // Ensure compiler does not re-order memory operations - AllMemoryBarrier(); - - - ++batch; - } while( batch < batchesWithinWavefront ); - - // Update the global memory vertices for the wavefronts - for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) - { - int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; - - g_vertexPositions[vertexAddress] = vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; - } - } - - -} - - - - -); - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl deleted file mode 100644 index fafd236f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateConstants.hlsl +++ /dev/null @@ -1,48 +0,0 @@ -MSTRINGIFY( - -cbuffer UpdateConstantsCB : register( b0 ) -{ - int numLinks; - int padding0; - int padding1; - int padding2; -}; - -// Node indices for each link -StructuredBuffer g_linksVertexIndices : register( t0 ); -StructuredBuffer g_vertexPositions : register( t1 ); -StructuredBuffer g_vertexInverseMasses : register( t2 ); -StructuredBuffer g_linksMaterialLSC : register( t3 ); - -RWStructuredBuffer g_linksMassLSC : register( u0 ); -RWStructuredBuffer g_linksRestLengthSquared : register( u1 ); -RWStructuredBuffer g_linksRestLengths : register( u2 ); - -[numthreads(128, 1, 1)] -void -UpdateConstantsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int linkID = DTid.x; - if( linkID < numLinks ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ]; - - float3 position0 = g_vertexPositions[node0].xyz; - float3 position1 = g_vertexPositions[node1].xyz; - float inverseMass0 = g_vertexInverseMasses[node0]; - float inverseMass1 = g_vertexInverseMasses[node1]; - - float3 difference = position0 - position1; - float length2 = dot(difference, difference); - float length = sqrt(length2); - - g_linksRestLengths[linkID] = length; - g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient; - g_linksRestLengthSquared[linkID] = length*length; - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl deleted file mode 100644 index a16d8943..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNodes.hlsl +++ /dev/null @@ -1,49 +0,0 @@ -MSTRINGIFY( - -cbuffer UpdateVelocitiesFromPositionsWithVelocitiesCB : register( b0 ) -{ - int numNodes; - float isolverdt; - int padding1; - int padding2; -}; - - -StructuredBuffer g_vertexPositions : register( t0 ); -StructuredBuffer g_vertexPreviousPositions : register( t1 ); -StructuredBuffer g_vertexClothIndices : register( t2 ); -StructuredBuffer g_clothVelocityCorrectionCoefficients : register( t3 ); -StructuredBuffer g_clothDampingFactor : register( t4 ); - -RWStructuredBuffer g_vertexVelocities : register( u0 ); -RWStructuredBuffer g_vertexForces : register( u1 ); - - -[numthreads(128, 1, 1)] -void -updateVelocitiesFromPositionsWithVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - if( nodeID < numNodes ) - { - float3 position = g_vertexPositions[nodeID].xyz; - float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz; - float3 velocity = g_vertexVelocities[nodeID].xyz; - int clothIndex = g_vertexClothIndices[nodeID]; - float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex]; - float dampingFactor = g_clothDampingFactor[clothIndex]; - float velocityCoefficient = (1.f - dampingFactor); - - float3 difference = position - previousPosition; - - velocity += difference*velocityCorrectionCoefficient*isolverdt; - - // Damp the velocity - velocity *= velocityCoefficient; - - g_vertexVelocities[nodeID] = float4(velocity, 0.f); - g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl deleted file mode 100644 index 54ab3ed2..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdateNormals.hlsl +++ /dev/null @@ -1,98 +0,0 @@ -MSTRINGIFY( - -cbuffer UpdateSoftBodiesCB : register( b0 ) -{ - unsigned int numNodes; - unsigned int startFace; - unsigned int numFaces; - float epsilon; -}; - - -// Node indices for each link -StructuredBuffer g_triangleVertexIndexSet : register( t0 ); -StructuredBuffer g_vertexPositions : register( t1 ); -StructuredBuffer g_vertexTriangleCount : register( t2 ); - -RWStructuredBuffer g_vertexNormals : register( u0 ); -RWStructuredBuffer g_vertexArea : register( u1 ); -RWStructuredBuffer g_triangleNormals : register( u2 ); -RWStructuredBuffer g_triangleArea : register( u3 ); - - -[numthreads(128, 1, 1)] -void -ResetNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - if( DTid.x < numNodes ) - { - g_vertexNormals[DTid.x] = float4(0.0f, 0.0f, 0.0f, 0.0f); - g_vertexArea[DTid.x] = 0.0f; - } -} - - -[numthreads(128, 1, 1)] -void -UpdateSoftBodiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int faceID = DTid.x + startFace; - if( DTid.x < numFaces ) - { - int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ]; - int nodeIndex0 = triangleIndexSet.x; - int nodeIndex1 = triangleIndexSet.y; - int nodeIndex2 = triangleIndexSet.z; - - float3 node0 = g_vertexPositions[nodeIndex0].xyz; - float3 node1 = g_vertexPositions[nodeIndex1].xyz; - float3 node2 = g_vertexPositions[nodeIndex2].xyz; - float3 nodeNormal0 = g_vertexNormals[nodeIndex0].xyz; - float3 nodeNormal1 = g_vertexNormals[nodeIndex1].xyz; - float3 nodeNormal2 = g_vertexNormals[nodeIndex2].xyz; - float vertexArea0 = g_vertexArea[nodeIndex0]; - float vertexArea1 = g_vertexArea[nodeIndex1]; - float vertexArea2 = g_vertexArea[nodeIndex2]; - - float3 vector0 = node1 - node0; - float3 vector1 = node2 - node0; - - float3 faceNormal = cross(vector0.xyz, vector1.xyz); - float triangleArea = length(faceNormal); - - nodeNormal0 = nodeNormal0 + faceNormal; - nodeNormal1 = nodeNormal1 + faceNormal; - nodeNormal2 = nodeNormal2 + faceNormal; - vertexArea0 = vertexArea0 + triangleArea; - vertexArea1 = vertexArea1 + triangleArea; - vertexArea2 = vertexArea2 + triangleArea; - - g_triangleNormals[faceID] = float4(normalize(faceNormal), 0.f); - g_vertexNormals[nodeIndex0] = float4(nodeNormal0, 0.f); - g_vertexNormals[nodeIndex1] = float4(nodeNormal1, 0.f); - g_vertexNormals[nodeIndex2] = float4(nodeNormal2, 0.f); - g_triangleArea[faceID] = triangleArea; - g_vertexArea[nodeIndex0] = vertexArea0; - g_vertexArea[nodeIndex1] = vertexArea1; - g_vertexArea[nodeIndex2] = vertexArea2; - } -} - -[numthreads(128, 1, 1)] -void -NormalizeNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - if( DTid.x < numNodes ) - { - float4 normal = g_vertexNormals[DTid.x]; - float area = g_vertexArea[DTid.x]; - int numTriangles = g_vertexTriangleCount[DTid.x]; - - float vectorLength = length(normal); - - g_vertexNormals[DTid.x] = normalize(normal); - g_vertexArea[DTid.x] = area/float(numTriangles); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl deleted file mode 100644 index 9685fa8f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositions.hlsl +++ /dev/null @@ -1,44 +0,0 @@ -MSTRINGIFY( - -cbuffer UpdateVelocitiesFromPositionsWithoutVelocitiesCB : register( b0 ) -{ - int numNodes; - float isolverdt; - int padding1; - int padding2; -}; - - -StructuredBuffer g_vertexPositions : register( t0 ); -StructuredBuffer g_vertexPreviousPositions : register( t1 ); -StructuredBuffer g_vertexClothIndices : register( t2 ); -StructuredBuffer g_clothDampingFactor : register( t3 ); - -RWStructuredBuffer g_vertexVelocities : register( u0 ); -RWStructuredBuffer g_vertexForces : register( u1 ); - - -[numthreads(128, 1, 1)] -void -updateVelocitiesFromPositionsWithoutVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - if( nodeID < numNodes ) - { - float3 position = g_vertexPositions[nodeID].xyz; - float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz; - float3 velocity = g_vertexVelocities[nodeID].xyz; - int clothIndex = g_vertexClothIndices[nodeID]; - float dampingFactor = g_clothDampingFactor[clothIndex]; - float velocityCoefficient = (1.f - dampingFactor); - - float3 difference = position - previousPosition; - - velocity = difference*velocityCoefficient*isolverdt; - - g_vertexVelocities[nodeID] = float4(velocity, 0.f); - g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl deleted file mode 100644 index e816b1e1..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/UpdatePositionsFromVelocities.hlsl +++ /dev/null @@ -1,35 +0,0 @@ -MSTRINGIFY( - -cbuffer UpdatePositionsFromVelocitiesCB : register( b0 ) -{ - int numNodes; - float solverSDT; - int padding1; - int padding2; -}; - - -StructuredBuffer g_vertexVelocities : register( t0 ); - -RWStructuredBuffer g_vertexPreviousPositions : register( u0 ); -RWStructuredBuffer g_vertexCurrentPosition : register( u1 ); - - -[numthreads(128, 1, 1)] -void -UpdatePositionsFromVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int vertexID = DTid.x; - if( vertexID < numNodes ) - { - float3 previousPosition = g_vertexPreviousPositions[vertexID].xyz; - float3 velocity = g_vertexVelocities[vertexID].xyz; - - float3 newPosition = previousPosition + velocity*solverSDT; - - g_vertexCurrentPosition[vertexID] = float4(newPosition, 0.f); - g_vertexPreviousPositions[vertexID] = float4(newPosition, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl deleted file mode 100644 index 14afca67..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/VSolveLinks.hlsl +++ /dev/null @@ -1,55 +0,0 @@ -MSTRINGIFY( - -cbuffer VSolveLinksCB : register( b0 ) -{ - int startLink; - int numLinks; - float kst; - int padding; -}; - -// Node indices for each link -StructuredBuffer g_linksVertexIndices : register( t0 ); - -StructuredBuffer g_linksLengthRatio : register( t1 ); -StructuredBuffer g_linksCurrentLength : register( t2 ); -StructuredBuffer g_vertexInverseMass : register( t3 ); - -RWStructuredBuffer g_vertexVelocity : register( u0 ); - -[numthreads(128, 1, 1)] -void -VSolveLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int linkID = DTid.x + startLink; - if( DTid.x < numLinks ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - - float linkLengthRatio = g_linksLengthRatio[linkID]; - float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz; - - float3 vertexVelocity0 = g_vertexVelocity[node0].xyz; - float3 vertexVelocity1 = g_vertexVelocity[node1].xyz; - - float vertexInverseMass0 = g_vertexInverseMass[node0]; - float vertexInverseMass1 = g_vertexInverseMass[node1]; - - float3 nodeDifference = vertexVelocity0 - vertexVelocity1; - float dotResult = dot(linkCurrentLength, nodeDifference); - float j = -dotResult*linkLengthRatio*kst; - - float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0); - float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1); - - vertexVelocity0 += velocityChange0; - vertexVelocity1 -= velocityChange1; - - g_vertexVelocity[node0] = float4(vertexVelocity0, 0.f); - g_vertexVelocity[node1] = float4(vertexVelocity1, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl deleted file mode 100644 index 9d46a596..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocities.hlsl +++ /dev/null @@ -1,170 +0,0 @@ -MSTRINGIFY( - -cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) -{ - unsigned int numNodes; - float isolverdt; - int padding0; - int padding1; -}; - -struct CollisionObjectIndices -{ - int firstObject; - int endObject; -}; - -struct CollisionShapeDescription -{ - float4x4 shapeTransform; - float4 linearVelocity; - float4 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - - // Shape information - // Compressed from the union - float radius; - float halfHeight; - - float margin; - float friction; - - int padding0; - int padding1; - -}; - -// From btBroadphaseProxy.h -static const int CAPSULE_SHAPE_PROXYTYPE = 10; - -// Node indices for each link -StructuredBuffer g_vertexClothIdentifier : register( t0 ); -StructuredBuffer g_vertexPreviousPositions : register( t1 ); -StructuredBuffer g_perClothFriction : register( t2 ); -StructuredBuffer g_clothDampingFactor : register( t3 ); -StructuredBuffer g_perClothCollisionObjectIndices : register( t4 ); -StructuredBuffer g_collisionObjectDetails : register( t5 ); - -RWStructuredBuffer g_vertexForces : register( u0 ); -RWStructuredBuffer g_vertexVelocities : register( u1 ); -RWStructuredBuffer g_vertexPositions : register( u2 ); - -[numthreads(128, 1, 1)] -void -SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - float3 forceOnVertex = float3(0.f, 0.f, 0.f); - if( DTid.x < numNodes ) - { - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f); - float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f); - float3 velocity; - float clothFriction = g_perClothFriction[clothIdentifier]; - float dampingFactor = g_clothDampingFactor[clothIdentifier]; - float velocityCoefficient = (1.f - dampingFactor); - CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; - - if( collisionObjectIndices.firstObject != collisionObjectIndices.endObject ) - { - velocity = float3(15, 0, 0); - - // We have some possible collisions to deal with - for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) - { - CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; - float colliderFriction = shapeDescription.friction; - - if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Colliding with a capsule - - float capsuleHalfHeight = shapeDescription.halfHeight; - float capsuleRadius = shapeDescription.radius; - float capsuleMargin = shapeDescription.margin; - float4x4 worldTransform = shapeDescription.shapeTransform; - - float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f); - float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f); - float4 worldC1 = mul(worldTransform, c1); - float4 worldC2 = mul(worldTransform, c2); - float3 segment = (worldC2 - worldC1).xyz; - - // compute distance of tangent to vertex along line segment in capsule - float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) ); - - float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f)); - float distanceFromLine = length(position - closestPoint); - float distanceFromC1 = length(worldC1 - position); - float distanceFromC2 = length(worldC2 - position); - - // Final distance from collision, point to push from, direction to push in - // for impulse force - float dist; - float3 normalVector; - if( distanceAlongSegment < 0 ) - { - dist = distanceFromC1; - normalVector = normalize(position - worldC1).xyz; - } else if( distanceAlongSegment > 1.f ) { - dist = distanceFromC2; - normalVector = normalize(position - worldC2).xyz; - } else { - dist = distanceFromLine; - normalVector = normalize(position - closestPoint).xyz; - } - - float3 colliderLinearVelocity = shapeDescription.linearVelocity.xyz; - float3 colliderAngularVelocity = shapeDescription.angularVelocity.xyz; - float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23); - - float minDistance = capsuleRadius + capsuleMargin; - - // In case of no collision, this is the value of velocity - velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; - - - // Check for a collision - if( dist < minDistance ) - { - // Project back to surface along normal - position = position + float4((minDistance - dist)*normalVector*0.9, 0.f); - velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; - float3 relativeVelocity = velocity - velocityOfSurfacePoint; - - float3 p1 = normalize(cross(normalVector, segment)); - float3 p2 = normalize(cross(p1, normalVector)); - // Full friction is sum of velocities in each direction of plane - float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2); - - // Real friction is peak friction corrected by friction coefficients - frictionVector = frictionVector * (colliderFriction*clothFriction); - - float approachSpeed = dot(relativeVelocity, normalVector); - - if( approachSpeed <= 0.0 ) - forceOnVertex -= frictionVector; - } - - } - } - } else { - // Update velocity - float3 difference = position.xyz - previousPosition.xyz; - velocity = difference*velocityCoefficient*isolverdt; - } - - g_vertexVelocities[nodeID] = float4(velocity, 0.f); - - // Update external force - g_vertexForces[nodeID] = float4(forceOnVertex, 0.f); - - g_vertexPositions[nodeID] = float4(position.xyz, 0.f); - } -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl deleted file mode 100644 index 0b2a0271..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl +++ /dev/null @@ -1,191 +0,0 @@ -MSTRINGIFY( - -cbuffer SolvePositionsFromLinksKernelCB : register( b0 ) -{ - unsigned int numNodes; - float isolverdt; - int padding0; - int padding1; -}; - -struct CollisionObjectIndices -{ - int firstObject; - int endObject; -}; - -struct CollisionShapeDescription -{ - float4x4 shapeTransform; - float4 linearVelocity; - float4 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - - // Shape information - // Compressed from the union - float radius; - float halfHeight; - - float margin; - float friction; - - int padding0; - int padding1; - -}; - -// From btBroadphaseProxy.h -static const int CAPSULE_SHAPE_PROXYTYPE = 10; - -// Node indices for each link -StructuredBuffer g_vertexClothIdentifier : register( t0 ); -StructuredBuffer g_vertexPreviousPositions : register( t1 ); -StructuredBuffer g_perClothFriction : register( t2 ); -StructuredBuffer g_clothDampingFactor : register( t3 ); -StructuredBuffer g_perClothCollisionObjectIndices : register( t4 ); -StructuredBuffer g_collisionObjectDetails : register( t5 ); - -RWStructuredBuffer g_vertexForces : register( u0 ); -RWStructuredBuffer g_vertexVelocities : register( u1 ); -RWStructuredBuffer g_vertexPositions : register( u2 ); - -// A buffer of local collision shapes -// TODO: Iterate to support more than 16 -groupshared CollisionShapeDescription localCollisionShapes[16]; - -[numthreads(128, 1, 1)] -void -SolveCollisionsAndUpdateVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex ) -{ - int nodeID = DTid.x; - float3 forceOnVertex = float3(0.f, 0.f, 0.f); - - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - float4 position = float4(g_vertexPositions[nodeID].xyz, 1.f); - float4 previousPosition = float4(g_vertexPreviousPositions[nodeID].xyz, 1.f); - float3 velocity; - float clothFriction = g_perClothFriction[clothIdentifier]; - float dampingFactor = g_clothDampingFactor[clothIdentifier]; - float velocityCoefficient = (1.f - dampingFactor); - CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; - - int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; - if( numObjects > 0 ) - { - // We have some possible collisions to deal with - - // First load all of the collision objects into LDS - int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; - if( GTid.x < numObjects ) - { - localCollisionShapes[GTid.x] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + GTid.x ]; - } - } - - // Safe as the vertices are padded so that not more than one soft body is in a group - AllMemoryBarrierWithGroupSync(); - - // Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this - if( numObjects > 0 ) - { - velocity = float3(0, 0, 0); - - - // We have some possible collisions to deal with - for( int collision = 0; collision < numObjects; ++collision ) - { - CollisionShapeDescription shapeDescription = localCollisionShapes[collision]; - float colliderFriction = shapeDescription.friction; - - if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Colliding with a capsule - - float capsuleHalfHeight = localCollisionShapes[collision].halfHeight; - float capsuleRadius = localCollisionShapes[collision].radius; - float capsuleMargin = localCollisionShapes[collision].margin; - - float4x4 worldTransform = localCollisionShapes[collision].shapeTransform; - - float4 c1 = float4(0.f, -capsuleHalfHeight, 0.f, 1.f); - float4 c2 = float4(0.f, +capsuleHalfHeight, 0.f, 1.f); - float4 worldC1 = mul(worldTransform, c1); - float4 worldC2 = mul(worldTransform, c2); - float3 segment = (worldC2 - worldC1).xyz; - - // compute distance of tangent to vertex along line segment in capsule - float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) ); - - float4 closestPoint = (worldC1 + float4(segment * distanceAlongSegment, 0.f)); - float distanceFromLine = length(position - closestPoint); - float distanceFromC1 = length(worldC1 - position); - float distanceFromC2 = length(worldC2 - position); - - // Final distance from collision, point to push from, direction to push in - // for impulse force - float dist; - float3 normalVector; - if( distanceAlongSegment < 0 ) - { - dist = distanceFromC1; - normalVector = normalize(position - worldC1).xyz; - } else if( distanceAlongSegment > 1.f ) { - dist = distanceFromC2; - normalVector = normalize(position - worldC2).xyz; - } else { - dist = distanceFromLine; - normalVector = normalize(position - closestPoint).xyz; - } - - float3 colliderLinearVelocity = localCollisionShapes[collision].linearVelocity.xyz; - float3 colliderAngularVelocity = localCollisionShapes[collision].angularVelocity.xyz; - float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - worldTransform._m03_m13_m23); - - float minDistance = capsuleRadius + capsuleMargin; - - // In case of no collision, this is the value of velocity - velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; - - - // Check for a collision - if( dist < minDistance ) - { - // Project back to surface along normal - position = position + float4((minDistance - dist)*normalVector*0.9, 0.f); - velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt; - float3 relativeVelocity = velocity - velocityOfSurfacePoint; - - float3 p1 = normalize(cross(normalVector, segment)); - float3 p2 = normalize(cross(p1, normalVector)); - // Full friction is sum of velocities in each direction of plane - float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2); - - // Real friction is peak friction corrected by friction coefficients - frictionVector = frictionVector * (colliderFriction*clothFriction); - - float approachSpeed = dot(relativeVelocity, normalVector); - - if( approachSpeed <= 0.0 ) - forceOnVertex -= frictionVector; - } - - } - } - } else { - // Update velocity - float3 difference = position.xyz - previousPosition.xyz; - velocity = difference*velocityCoefficient*isolverdt; - } - - g_vertexVelocities[nodeID] = float4(velocity, 0.f); - - // Update external force - g_vertexForces[nodeID] = float4(forceOnVertex, 0.f); - - g_vertexPositions[nodeID] = float4(position.xyz, 0.f); -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h deleted file mode 100644 index b6a99cc1..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverBuffer_DX11.h +++ /dev/null @@ -1,323 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -#ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H -#define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H - -// DX11 support -#include -#include -#include -#include -#include - -#ifndef SAFE_RELEASE -#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } -#endif - -/** - * DX11 Buffer that tracks a host buffer on use to ensure size-correctness. - */ -template class btDX11Buffer -{ -protected: - ID3D11Device* m_d3dDevice; - ID3D11DeviceContext* m_d3dDeviceContext; - - ID3D11Buffer* m_Buffer; - ID3D11ShaderResourceView* m_SRV; - ID3D11UnorderedAccessView* m_UAV; - btAlignedObjectArray< ElementType >* m_CPUBuffer; - - // TODO: Separate this from the main class - // as read back buffers can be shared between buffers - ID3D11Buffer* m_readBackBuffer; - - int m_gpuSize; - bool m_onGPU; - - bool m_readOnlyOnGPU; - - bool createBuffer( ID3D11Buffer *preexistingBuffer = 0) - { - HRESULT hr = S_OK; - - // Create all CS buffers - if( preexistingBuffer ) - { - m_Buffer = preexistingBuffer; - } else { - D3D11_BUFFER_DESC buffer_desc; - ZeroMemory(&buffer_desc, sizeof(buffer_desc)); - buffer_desc.Usage = D3D11_USAGE_DEFAULT; - if( m_readOnlyOnGPU ) - buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - else - buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; - buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; - - buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType); - // At a minimum the buffer must exist - if( buffer_desc.ByteWidth == 0 ) - buffer_desc.ByteWidth = sizeof(ElementType); - buffer_desc.StructureByteStride = sizeof(ElementType); - hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer); - if( FAILED( hr ) ) - return (hr==S_OK); - } - - if( m_readOnlyOnGPU ) - { - D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; - ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); - srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; - srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - - srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size(); - if( srvbuffer_desc.Buffer.ElementWidth == 0 ) - srvbuffer_desc.Buffer.ElementWidth = 1; - hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV); - if( FAILED( hr ) ) - return (hr==S_OK); - } else { - // Create SRV - D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc; - ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc)); - srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; - srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - - srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size(); - if( srvbuffer_desc.Buffer.ElementWidth == 0 ) - srvbuffer_desc.Buffer.ElementWidth = 1; - hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV); - if( FAILED( hr ) ) - return (hr==S_OK); - - // Create UAV - D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc; - ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc)); - uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN; - uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - - uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size(); - if( uavbuffer_desc.Buffer.NumElements == 0 ) - uavbuffer_desc.Buffer.NumElements = 1; - hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV); - if( FAILED( hr ) ) - return (hr==S_OK); - - // Create read back buffer - D3D11_BUFFER_DESC readback_buffer_desc; - ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc)); - - readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType); - readback_buffer_desc.Usage = D3D11_USAGE_STAGING; - readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - readback_buffer_desc.StructureByteStride = sizeof(ElementType); - hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer); - if( FAILED( hr ) ) - return (hr==S_OK); - } - - m_gpuSize = m_CPUBuffer->size(); - return true; - } - - - -public: - btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly ) - { - m_d3dDevice = d3dDevice; - m_d3dDeviceContext = d3dDeviceContext; - m_Buffer = 0; - m_SRV = 0; - m_UAV = 0; - m_readBackBuffer = 0; - - m_CPUBuffer = CPUBuffer; - - m_gpuSize = 0; - m_onGPU = false; - - m_readOnlyOnGPU = readOnly; - } - - virtual ~btDX11Buffer() - { - SAFE_RELEASE(m_Buffer); - SAFE_RELEASE(m_SRV); - SAFE_RELEASE(m_UAV); - SAFE_RELEASE(m_readBackBuffer); - } - - ID3D11ShaderResourceView* &getSRV() - { - return m_SRV; - } - - ID3D11UnorderedAccessView* &getUAV() - { - return m_UAV; - } - - ID3D11Buffer* &getBuffer() - { - return m_Buffer; - } - - /** - * Move the data to the GPU if it is not there already. - */ - bool moveToGPU() - { - // Reallocate if GPU size is too small - if( (m_CPUBuffer->size() > m_gpuSize ) ) - m_onGPU = false; - if( !m_onGPU && m_CPUBuffer->size() > 0 ) - { - // If the buffer doesn't exist or the CPU-side buffer has changed size, create - // We should really delete the old one, too, but let's leave that for later - if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) ) - { - SAFE_RELEASE(m_Buffer); - SAFE_RELEASE(m_SRV); - SAFE_RELEASE(m_UAV); - SAFE_RELEASE(m_readBackBuffer); - if( !createBuffer() ) - { - btAssert("Buffer creation failed."); - return false; - } - } - - if( m_gpuSize > 0 ) - { - D3D11_BOX destRegion; - destRegion.left = 0; - destRegion.front = 0; - destRegion.top = 0; - destRegion.bottom = 1; - destRegion.back = 1; - destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); - m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0); - - m_onGPU = true; - } - - } - - return true; - } - - /** - * Move the data back from the GPU if it is on there and isn't read only. - */ - bool moveFromGPU() - { - if( m_CPUBuffer->size() > 0 ) - { - if( m_onGPU && !m_readOnlyOnGPU ) - { - // Copy back - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - //m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel); - - D3D11_BOX destRegion; - destRegion.left = 0; - destRegion.front = 0; - destRegion.top = 0; - destRegion.bottom = 1; - destRegion.back = 1; - - destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); - m_d3dDeviceContext->CopySubresourceRegion( - m_readBackBuffer, - 0, - 0, - 0, - 0 , - m_Buffer, - 0, - &destRegion - ); - - m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource); - //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) )); - memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) )); - m_d3dDeviceContext->Unmap(m_readBackBuffer, 0); - - m_onGPU = false; - } - } - - return true; - } - - - /** - * Copy the data back from the GPU without changing its state to be CPU-side. - * Useful if we just want to view it on the host for visualization. - */ - bool copyFromGPU() - { - if( m_CPUBuffer->size() > 0 ) - { - if( m_onGPU && !m_readOnlyOnGPU ) - { - // Copy back - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - - D3D11_BOX destRegion; - destRegion.left = 0; - destRegion.front = 0; - destRegion.top = 0; - destRegion.bottom = 1; - destRegion.back = 1; - - destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType); - m_d3dDeviceContext->CopySubresourceRegion( - m_readBackBuffer, - 0, - 0, - 0, - 0 , - m_Buffer, - 0, - &destRegion - ); - - m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource); - //memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) )); - memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) )); - m_d3dDeviceContext->Unmap(m_readBackBuffer, 0); - } - } - - return true; - } - - /** - * Call if data has changed on the CPU. - * Can then trigger a move to the GPU as necessary. - */ - virtual void changedOnCPU() - { - m_onGPU = false; - } -}; // class btDX11Buffer - - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h deleted file mode 100644 index 454c3c8c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_DX11.h" - - -#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H -#define BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H - -struct ID3D11Device; -struct ID3D11DeviceContext; - - -class btSoftBodyLinkDataDX11 : public btSoftBodyLinkData -{ -public: - bool m_onGPU; - ID3D11Device *m_d3dDevice; - ID3D11DeviceContext *m_d3dDeviceContext; - - - btDX11Buffer m_dx11Links; - btDX11Buffer m_dx11LinkStrength; - btDX11Buffer m_dx11LinksMassLSC; - btDX11Buffer m_dx11LinksRestLengthSquared; - btDX11Buffer m_dx11LinksCLength; - btDX11Buffer m_dx11LinksLengthRatio; - btDX11Buffer m_dx11LinksRestLength; - btDX11Buffer m_dx11LinksMaterialLinearStiffnessCoefficient; - - struct BatchPair - { - int start; - int length; - - BatchPair() : - start(0), - length(0) - { - } - - BatchPair( int s, int l ) : - start( s ), - length( l ) - { - } - }; - - /** - * Link addressing information for each cloth. - * Allows link locations to be computed independently of data batching. - */ - btAlignedObjectArray< int > m_linkAddresses; - - /** - * Start and length values for computation batches over link data. - */ - btAlignedObjectArray< BatchPair > m_batchStartLengths; - - - //ID3D11Buffer* readBackBuffer; - - btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); - - virtual ~btSoftBodyLinkDataDX11(); - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createLinks( int numLinks ); - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setLinkAt( const LinkDescription &link, int linkIndex ); - - virtual bool onAccelerator(); - - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(); - - /** - * Generate (and later update) the batching for the entire link set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ - void generateBatches(); -}; - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h deleted file mode 100644 index 6eb26c68..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverLinkData_DX11SIMDAware.h +++ /dev/null @@ -1,173 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_DX11.h" - -#ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H -#define BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H - -struct ID3D11Device; -struct ID3D11DeviceContext; - - -class btSoftBodyLinkDataDX11SIMDAware : public btSoftBodyLinkData -{ -public: - bool m_onGPU; - ID3D11Device *m_d3dDevice; - ID3D11DeviceContext *m_d3dDeviceContext; - - const int m_wavefrontSize; - const int m_linksPerWorkItem; - const int m_maxLinksPerWavefront; - int m_maxBatchesWithinWave; - int m_maxVerticesWithinWave; - int m_numWavefronts; - - int m_maxVertex; - - struct NumBatchesVerticesPair - { - int numBatches; - int numVertices; - }; - - // Array storing number of links in each wavefront - btAlignedObjectArray m_linksPerWavefront; - btAlignedObjectArray m_numBatchesAndVerticesWithinWaves; - btDX11Buffer< NumBatchesVerticesPair > m_dx11NumBatchesAndVerticesWithinWaves; - - // All arrays here will contain batches of m_maxLinksPerWavefront links - // ordered by wavefront. - // with either global vertex pairs or local vertex pairs - btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront - btDX11Buffer m_dx11WavefrontVerticesGlobalAddresses; - btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link - btDX11Buffer m_dx11LinkVerticesLocalAddresses; - btDX11Buffer m_dx11LinkStrength; - btDX11Buffer m_dx11LinksMassLSC; - btDX11Buffer m_dx11LinksRestLengthSquared; - btDX11Buffer m_dx11LinksRestLength; - btDX11Buffer m_dx11LinksMaterialLinearStiffnessCoefficient; - - struct BatchPair - { - int start; - int length; - - BatchPair() : - start(0), - length(0) - { - } - - BatchPair( int s, int l ) : - start( s ), - length( l ) - { - } - }; - - /** - * Link addressing information for each cloth. - * Allows link locations to be computed independently of data batching. - */ - btAlignedObjectArray< int > m_linkAddresses; - - /** - * Start and length values for computation batches over link data. - */ - btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths; - - - //ID3D11Buffer* readBackBuffer; - - btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); - - virtual ~btSoftBodyLinkDataDX11SIMDAware(); - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createLinks( int numLinks ); - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setLinkAt( const LinkDescription &link, int linkIndex ); - - virtual bool onAccelerator(); - - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(); - - /** - * Generate (and later update) the batching for the entire link set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ - void generateBatches(); - - int getMaxVerticesPerWavefront() - { - return m_maxVerticesWithinWave; - } - - int getWavefrontSize() - { - return m_wavefrontSize; - } - - int getLinksPerWorkItem() - { - return m_linksPerWorkItem; - } - - int getMaxLinksPerWavefront() - { - return m_maxLinksPerWavefront; - } - - int getMaxBatchesPerWavefront() - { - return m_maxBatchesWithinWave; - } - - int getNumWavefronts() - { - return m_numWavefronts; - } - - NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront ) - { - return m_numBatchesAndVerticesWithinWaves[wavefront]; - } - - int getVertexGlobalAddresses( int vertexIndex ) - { - return m_wavefrontVerticesGlobalAddresses[vertexIndex]; - } - - /** - * Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally. - */ - LinkNodePair getVertexPairLocalAddresses( int linkIndex ) - { - return m_linkVerticesLocalAddresses[linkIndex]; - } - -}; - - -#endif // #ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h deleted file mode 100644 index 7012fabd..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverTriangleData_DX11.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_DX11.h" - - -#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H -#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H - -struct ID3D11Device; -struct ID3D11DeviceContext; - -class btSoftBodyTriangleDataDX11 : public btSoftBodyTriangleData -{ -public: - bool m_onGPU; - ID3D11Device *m_d3dDevice; - ID3D11DeviceContext *m_d3dDeviceContext; - - btDX11Buffer m_dx11VertexIndices; - btDX11Buffer m_dx11Area; - btDX11Buffer m_dx11Normal; - - struct BatchPair - { - int start; - int length; - - BatchPair() : - start(0), - length(0) - { - } - - BatchPair( int s, int l ) : - start( s ), - length( l ) - { - } - }; - - - /** - * Link addressing information for each cloth. - * Allows link locations to be computed independently of data batching. - */ - btAlignedObjectArray< int > m_triangleAddresses; - - /** - * Start and length values for computation batches over link data. - */ - btAlignedObjectArray< BatchPair > m_batchStartLengths; - - //ID3D11Buffer* readBackBuffer; - -public: - btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); - - virtual ~btSoftBodyTriangleDataDX11(); - - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createTriangles( int numTriangles ); - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ); - - virtual bool onAccelerator(); - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(); - /** - * Generate (and later update) the batching for the entire triangle set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ - void generateBatches(); -}; - - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h deleted file mode 100644 index 66bd90fa..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexBuffer_DX11.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H -#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H - - -#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" - -#include -#include -#include -#include -#include - -class btDX11VertexBufferDescriptor : public btVertexBufferDescriptor -{ -protected: - /** Context of the DX11 device on which the vertex buffer is stored. */ - ID3D11DeviceContext* m_context; - /** DX11 vertex buffer */ - ID3D11Buffer* m_vertexBuffer; - /** UAV for DX11 buffer */ - ID3D11UnorderedAccessView* m_vertexBufferUAV; - - -public: - /** - * buffer is a pointer to the DX11 buffer to place the vertex data in. - * UAV is a pointer to the UAV representation of the buffer laid out in floats. - * vertexOffset is the offset in floats to the first vertex. - * vertexStride is the stride in floats between vertices. - */ - btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride ) - { - m_context = context; - m_vertexBuffer = buffer; - m_vertexBufferUAV = UAV; - m_vertexOffset = vertexOffset; - m_vertexStride = vertexStride; - m_hasVertexPositions = true; - } - - /** - * buffer is a pointer to the DX11 buffer to place the vertex data in. - * UAV is a pointer to the UAV representation of the buffer laid out in floats. - * vertexOffset is the offset in floats to the first vertex. - * vertexStride is the stride in floats between vertices. - * normalOffset is the offset in floats to the first normal. - * normalStride is the stride in floats between normals. - */ - btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) - { - m_context = context; - m_vertexBuffer = buffer; - m_vertexBufferUAV = UAV; - m_vertexOffset = vertexOffset; - m_vertexStride = vertexStride; - m_hasVertexPositions = true; - - m_normalOffset = normalOffset; - m_normalStride = normalStride; - m_hasNormals = true; - } - - virtual ~btDX11VertexBufferDescriptor() - { - - } - - /** - * Return the type of the vertex buffer descriptor. - */ - virtual BufferTypes getBufferType() const - { - return DX11_BUFFER; - } - - virtual ID3D11DeviceContext* getContext() const - { - return m_context; - } - - virtual ID3D11Buffer* getbtDX11Buffer() const - { - return m_vertexBuffer; - } - - virtual ID3D11UnorderedAccessView* getDX11UAV() const - { - return m_vertexBufferUAV; - } -}; - -#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h deleted file mode 100644 index dd7cc84c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolverVertexData_DX11.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_DX11.h" - - -#ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H -#define BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H - -class btSoftBodyLinkData; -class btSoftBodyLinkData::LinkDescription; - -struct ID3D11Device; -struct ID3D11DeviceContext; - -class btSoftBodyVertexDataDX11 : public btSoftBodyVertexData -{ -protected: - bool m_onGPU; - ID3D11Device *m_d3dDevice; - ID3D11DeviceContext *m_d3dDeviceContext; - -public: - btDX11Buffer m_dx11ClothIdentifier; - btDX11Buffer m_dx11VertexPosition; - btDX11Buffer m_dx11VertexPreviousPosition; - btDX11Buffer m_dx11VertexVelocity; - btDX11Buffer m_dx11VertexForceAccumulator; - btDX11Buffer m_dx11VertexNormal; - btDX11Buffer m_dx11VertexInverseMass; - btDX11Buffer m_dx11VertexArea; - btDX11Buffer m_dx11VertexTriangleCount; - - - //ID3D11Buffer* readBackBuffer; - -public: - btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ); - virtual ~btSoftBodyVertexDataDX11(); - - virtual bool onAccelerator(); - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true); -}; - - -#endif // #ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp deleted file mode 100644 index 357c4089..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.cpp +++ /dev/null @@ -1,2236 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "vectormath/vmInclude.h" - -#include "btSoftBodySolver_DX11.h" -#include "btSoftBodySolverVertexBuffer_DX11.h" -#include "BulletSoftBody/btSoftBody.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" -#include //printf -#define MSTRINGIFY(A) #A -static char* PrepareLinksHLSLString = -#include "HLSL/PrepareLinks.hlsl" -static char* UpdatePositionsFromVelocitiesHLSLString = -#include "HLSL/UpdatePositionsFromVelocities.hlsl" -static char* SolvePositionsHLSLString = -#include "HLSL/SolvePositions.hlsl" -static char* UpdateNodesHLSLString = -#include "HLSL/UpdateNodes.hlsl" -static char* UpdatePositionsHLSLString = -#include "HLSL/UpdatePositions.hlsl" -static char* UpdateConstantsHLSLString = -#include "HLSL/UpdateConstants.hlsl" -static char* IntegrateHLSLString = -#include "HLSL/Integrate.hlsl" -static char* ApplyForcesHLSLString = -#include "HLSL/ApplyForces.hlsl" -static char* UpdateNormalsHLSLString = -#include "HLSL/UpdateNormals.hlsl" -static char* OutputToVertexArrayHLSLString = -#include "HLSL/OutputToVertexArray.hlsl" -static char* VSolveLinksHLSLString = -#include "HLSL/VSolveLinks.hlsl" -static char* ComputeBoundsHLSLString = -#include "HLSL/ComputeBounds.hlsl" -static char* SolveCollisionsAndUpdateVelocitiesHLSLString = -#include "HLSL/SolveCollisionsAndUpdateVelocities.hlsl" -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - -btSoftBodyLinkDataDX11::btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : - m_dx11Links( d3dDevice, d3dDeviceContext, &m_links, false ), - m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, false ), - m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, false ), - m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, false ), - m_dx11LinksCLength( d3dDevice, d3dDeviceContext, &m_linksCLength, false ), - m_dx11LinksLengthRatio( d3dDevice, d3dDeviceContext, &m_linksLengthRatio, false ), - m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, false ), - m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, false ) -{ - m_d3dDevice = d3dDevice; - m_d3dDeviceContext = d3dDeviceContext; -} - -btSoftBodyLinkDataDX11::~btSoftBodyLinkDataDX11() -{ -} - -static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) -{ - Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); - return outVec; -} - -void btSoftBodyLinkDataDX11::createLinks( int numLinks ) -{ - int previousSize = m_links.size(); - int newSize = previousSize + numLinks; - - btSoftBodyLinkData::createLinks( numLinks ); - - // Resize the link addresses array as well - m_linkAddresses.resize( newSize ); -} - -void btSoftBodyLinkDataDX11::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex ) -{ - btSoftBodyLinkData::setLinkAt( link, linkIndex ); - - // Set the link index correctly for initialisation - m_linkAddresses[linkIndex] = linkIndex; -} - -bool btSoftBodyLinkDataDX11::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyLinkDataDX11::moveToAccelerator() -{ - bool success = true; - success = success && m_dx11Links.moveToGPU(); - success = success && m_dx11LinkStrength.moveToGPU(); - success = success && m_dx11LinksMassLSC.moveToGPU(); - success = success && m_dx11LinksRestLengthSquared.moveToGPU(); - success = success && m_dx11LinksCLength.moveToGPU(); - success = success && m_dx11LinksLengthRatio.moveToGPU(); - success = success && m_dx11LinksRestLength.moveToGPU(); - success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -bool btSoftBodyLinkDataDX11::moveFromAccelerator() -{ - bool success = true; - success = success && m_dx11Links.moveFromGPU(); - success = success && m_dx11LinkStrength.moveFromGPU(); - success = success && m_dx11LinksMassLSC.moveFromGPU(); - success = success && m_dx11LinksRestLengthSquared.moveFromGPU(); - success = success && m_dx11LinksCLength.moveFromGPU(); - success = success && m_dx11LinksLengthRatio.moveFromGPU(); - success = success && m_dx11LinksRestLength.moveFromGPU(); - success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU(); - - if( success ) - m_onGPU = false; - - return success; -} - -void btSoftBodyLinkDataDX11::generateBatches() -{ - int numLinks = getNumLinks(); - - // Do the graph colouring here temporarily - btAlignedObjectArray< int > batchValues; - batchValues.resize( numLinks, 0 ); - - // Find the maximum vertex value internally for now - int maxVertex = 0; - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - int vertex0 = getVertexPair(linkIndex).vertex0; - int vertex1 = getVertexPair(linkIndex).vertex1; - if( vertex0 > maxVertex ) - maxVertex = vertex0; - if( vertex1 > maxVertex ) - maxVertex = vertex1; - } - int numVertices = maxVertex + 1; - - // Set of lists, one for each node, specifying which colours are connected - // to that node. - // No two edges into a node can share a colour. - btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; - vertexConnectedColourLists.resize(numVertices); - - - - // Simple algorithm that chooses the lowest batch number - // that none of the links attached to either of the connected - // nodes is in - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - int linkLocation = m_linkAddresses[linkIndex]; - - int vertex0 = getVertexPair(linkLocation).vertex0; - int vertex1 = getVertexPair(linkLocation).vertex1; - - // Get the two node colour lists - btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); - btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); - - // Choose the minimum colour that is in neither list - int colour = 0; - while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ) - ++colour; - // i should now be the minimum colour in neither list - // Add to the two lists so that future edges don't share - // And store the colour against this edge - - colourListVertex0.push_back(colour); - colourListVertex1.push_back(colour); - batchValues[linkIndex] = colour; - } - - // Check the colour counts - btAlignedObjectArray< int > batchCounts; - for( int i = 0; i < numLinks; ++i ) - { - int batch = batchValues[i]; - if( batch >= batchCounts.size() ) - batchCounts.push_back(1); - else - ++(batchCounts[batch]); - } - - m_batchStartLengths.resize(batchCounts.size()); - if( m_batchStartLengths.size() > 0 ) - { - m_batchStartLengths[0] = BatchPair( 0, 0 ); - - int sum = 0; - for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) - { - m_batchStartLengths[batchIndex].start = sum; - m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; - sum += batchCounts[batchIndex]; - } - } - - ///////////////////////////// - // Sort data based on batches - - // Create source arrays by copying originals - btAlignedObjectArray m_links_Backup(m_links); - btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); - btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); - btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); - btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); - btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); - btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); - btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); - - - for( int batch = 0; batch < batchCounts.size(); ++batch ) - batchCounts[batch] = 0; - - // Do sort as single pass into destination arrays - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - // To maintain locations run off the original link locations rather than the current position. - // It's not cache efficient, but as we run this rarely that should not matter. - // It's faster than searching the link location array for the current location and then updating it. - // The other alternative would be to unsort before resorting, but this is equivalent to doing that. - int linkLocation = m_linkAddresses[linkIndex]; - - // Obtain batch and calculate target location for the - // next element in that batch, incrementing the batch counter - // afterwards - int batch = batchValues[linkIndex]; - int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; - - batchCounts[batch] = batchCounts[batch] + 1; - m_links[newLocation] = m_links_Backup[linkLocation]; -#if 1 - m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation]; - m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation]; - m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation]; - m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation]; - m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation]; - m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation]; -#endif - // Update the locations array to account for the moved entry - m_linkAddresses[linkIndex] = newLocation; - } -} // void btSoftBodyLinkDataDX11::generateBatches() - - - -btSoftBodyVertexDataDX11::btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : - m_dx11ClothIdentifier( d3dDevice, d3dDeviceContext, &m_clothIdentifier, false ), - m_dx11VertexPosition( d3dDevice, d3dDeviceContext, &m_vertexPosition, false ), - m_dx11VertexPreviousPosition( d3dDevice, d3dDeviceContext, &m_vertexPreviousPosition, false ), - m_dx11VertexVelocity( d3dDevice, d3dDeviceContext, &m_vertexVelocity, false ), - m_dx11VertexForceAccumulator( d3dDevice, d3dDeviceContext, &m_vertexForceAccumulator, false ), - m_dx11VertexNormal( d3dDevice, d3dDeviceContext, &m_vertexNormal, false ), - m_dx11VertexInverseMass( d3dDevice, d3dDeviceContext, &m_vertexInverseMass, false ), - m_dx11VertexArea( d3dDevice, d3dDeviceContext, &m_vertexArea, false ), - m_dx11VertexTriangleCount( d3dDevice, d3dDeviceContext, &m_vertexTriangleCount, false ) -{ - m_d3dDevice = d3dDevice; - m_d3dDeviceContext = d3dDeviceContext; -} - -btSoftBodyVertexDataDX11::~btSoftBodyVertexDataDX11() -{ - -} - -bool btSoftBodyVertexDataDX11::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyVertexDataDX11::moveToAccelerator() -{ - bool success = true; - success = success && m_dx11ClothIdentifier.moveToGPU(); - success = success && m_dx11VertexPosition.moveToGPU(); - success = success && m_dx11VertexPreviousPosition.moveToGPU(); - success = success && m_dx11VertexVelocity.moveToGPU(); - success = success && m_dx11VertexForceAccumulator.moveToGPU(); - success = success && m_dx11VertexNormal.moveToGPU(); - success = success && m_dx11VertexInverseMass.moveToGPU(); - success = success && m_dx11VertexArea.moveToGPU(); - success = success && m_dx11VertexTriangleCount.moveToGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -bool btSoftBodyVertexDataDX11::moveFromAccelerator(bool bCopy, bool bCopyMinimum) -{ - bool success = true; - - if (!bCopy) - { - success = success && m_dx11ClothIdentifier.moveFromGPU(); - success = success && m_dx11VertexPosition.moveFromGPU(); - success = success && m_dx11VertexPreviousPosition.moveFromGPU(); - success = success && m_dx11VertexVelocity.moveFromGPU(); - success = success && m_dx11VertexForceAccumulator.moveFromGPU(); - success = success && m_dx11VertexNormal.moveFromGPU(); - success = success && m_dx11VertexInverseMass.moveFromGPU(); - success = success && m_dx11VertexArea.moveFromGPU(); - success = success && m_dx11VertexTriangleCount.moveFromGPU(); - } - else - { - if (bCopyMinimum) - { - success = success && m_dx11VertexPosition.copyFromGPU(); - success = success && m_dx11VertexNormal.copyFromGPU(); - } - else - { - success = success && m_dx11ClothIdentifier.copyFromGPU(); - success = success && m_dx11VertexPosition.copyFromGPU(); - success = success && m_dx11VertexPreviousPosition.copyFromGPU(); - success = success && m_dx11VertexVelocity.copyFromGPU(); - success = success && m_dx11VertexForceAccumulator.copyFromGPU(); - success = success && m_dx11VertexNormal.copyFromGPU(); - success = success && m_dx11VertexInverseMass.copyFromGPU(); - success = success && m_dx11VertexArea.copyFromGPU(); - success = success && m_dx11VertexTriangleCount.copyFromGPU(); - } - } - - if( success ) - m_onGPU = true; - - return success; -} - - -btSoftBodyTriangleDataDX11::btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : - m_dx11VertexIndices( d3dDevice, d3dDeviceContext, &m_vertexIndices, false ), - m_dx11Area( d3dDevice, d3dDeviceContext, &m_area, false ), - m_dx11Normal( d3dDevice, d3dDeviceContext, &m_normal, false ) -{ - m_d3dDevice = d3dDevice; - m_d3dDeviceContext = d3dDeviceContext; -} - -btSoftBodyTriangleDataDX11::~btSoftBodyTriangleDataDX11() -{ - -} - - -/** Allocate enough space in all link-related arrays to fit numLinks links */ -void btSoftBodyTriangleDataDX11::createTriangles( int numTriangles ) -{ - int previousSize = getNumTriangles(); - int newSize = previousSize + numTriangles; - - btSoftBodyTriangleData::createTriangles( numTriangles ); - - // Resize the link addresses array as well - m_triangleAddresses.resize( newSize ); -} - -/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ -void btSoftBodyTriangleDataDX11::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ) -{ - btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex ); - - m_triangleAddresses[triangleIndex] = triangleIndex; -} - -bool btSoftBodyTriangleDataDX11::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyTriangleDataDX11::moveToAccelerator() -{ - bool success = true; - success = success && m_dx11VertexIndices.moveToGPU(); - success = success && m_dx11Area.moveToGPU(); - success = success && m_dx11Normal.moveToGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -bool btSoftBodyTriangleDataDX11::moveFromAccelerator() -{ - bool success = true; - success = success && m_dx11VertexIndices.moveFromGPU(); - success = success && m_dx11Area.moveFromGPU(); - success = success && m_dx11Normal.moveFromGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -/** - * Generate (and later update) the batching for the entire triangle set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ -void btSoftBodyTriangleDataDX11::generateBatches() -{ - int numTriangles = getNumTriangles(); - if( numTriangles == 0 ) - return; - - // Do the graph colouring here temporarily - btAlignedObjectArray< int > batchValues; - batchValues.resize( numTriangles ); - - // Find the maximum vertex value internally for now - int maxVertex = 0; - for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) - { - int vertex0 = getVertexSet(triangleIndex).vertex0; - int vertex1 = getVertexSet(triangleIndex).vertex1; - int vertex2 = getVertexSet(triangleIndex).vertex2; - - if( vertex0 > maxVertex ) - maxVertex = vertex0; - if( vertex1 > maxVertex ) - maxVertex = vertex1; - if( vertex2 > maxVertex ) - maxVertex = vertex2; - } - int numVertices = maxVertex + 1; - - // Set of lists, one for each node, specifying which colours are connected - // to that node. - // No two edges into a node can share a colour. - btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; - vertexConnectedColourLists.resize(numVertices); - - - //std::cout << "\n"; - // Simple algorithm that chooses the lowest batch number - // that none of the faces attached to either of the connected - // nodes is in - for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) - { - // To maintain locations run off the original link locations rather than the current position. - // It's not cache efficient, but as we run this rarely that should not matter. - // It's faster than searching the link location array for the current location and then updating it. - // The other alternative would be to unsort before resorting, but this is equivalent to doing that. - int triangleLocation = m_triangleAddresses[triangleIndex]; - - int vertex0 = getVertexSet(triangleLocation).vertex0; - int vertex1 = getVertexSet(triangleLocation).vertex1; - int vertex2 = getVertexSet(triangleLocation).vertex2; - - // Get the three node colour lists - btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); - btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); - btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] ); - - // Choose the minimum colour that is in none of the lists - int colour = 0; - while( - colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || - colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() || - colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() ) - { - ++colour; - } - // i should now be the minimum colour in neither list - // Add to the three lists so that future edges don't share - // And store the colour against this face - colourListVertex0.push_back(colour); - colourListVertex1.push_back(colour); - colourListVertex2.push_back(colour); - - batchValues[triangleIndex] = colour; - } - - - // Check the colour counts - btAlignedObjectArray< int > batchCounts; - for( int i = 0; i < numTriangles; ++i ) - { - int batch = batchValues[i]; - if( batch >= batchCounts.size() ) - batchCounts.push_back(1); - else - ++(batchCounts[batch]); - } - - - m_batchStartLengths.resize(batchCounts.size()); - m_batchStartLengths[0] = BatchPair( 0, 0 ); - - - int sum = 0; - for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) - { - m_batchStartLengths[batchIndex].start = sum; - m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; - sum += batchCounts[batchIndex]; - } - - ///////////////////////////// - // Sort data based on batches - - // Create source arrays by copying originals - btAlignedObjectArray m_vertexIndices_Backup(m_vertexIndices); - btAlignedObjectArray m_area_Backup(m_area); - btAlignedObjectArray m_normal_Backup(m_normal); - - - for( int batch = 0; batch < batchCounts.size(); ++batch ) - batchCounts[batch] = 0; - - // Do sort as single pass into destination arrays - for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) - { - // To maintain locations run off the original link locations rather than the current position. - // It's not cache efficient, but as we run this rarely that should not matter. - // It's faster than searching the link location array for the current location and then updating it. - // The other alternative would be to unsort before resorting, but this is equivalent to doing that. - int triangleLocation = m_triangleAddresses[triangleIndex]; - - // Obtain batch and calculate target location for the - // next element in that batch, incrementing the batch counter - // afterwards - int batch = batchValues[triangleIndex]; - int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; - - batchCounts[batch] = batchCounts[batch] + 1; - m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation]; - m_area[newLocation] = m_area_Backup[triangleLocation]; - m_normal[newLocation] = m_normal_Backup[triangleLocation]; - - // Update the locations array to account for the moved entry - m_triangleAddresses[triangleIndex] = newLocation; - } -} // btSoftBodyTriangleDataDX11::generateBatches - - - - - - - - - - - - -btDX11SoftBodySolver::btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) : - m_dx11Device( dx11Device ), - m_dx11Context( dx11Context ), - dxFunctions( m_dx11Device, m_dx11Context, dx11CompileFromMemory ), - m_linkData(m_dx11Device, m_dx11Context), - m_vertexData(m_dx11Device, m_dx11Context), - m_triangleData(m_dx11Device, m_dx11Context), - m_dx11PerClothAcceleration( m_dx11Device, m_dx11Context, &m_perClothAcceleration, true ), - m_dx11PerClothWindVelocity( m_dx11Device, m_dx11Context, &m_perClothWindVelocity, true ), - m_dx11PerClothDampingFactor( m_dx11Device, m_dx11Context, &m_perClothDampingFactor, true ), - m_dx11PerClothVelocityCorrectionCoefficient( m_dx11Device, m_dx11Context, &m_perClothVelocityCorrectionCoefficient, true ), - m_dx11PerClothLiftFactor( m_dx11Device, m_dx11Context, &m_perClothLiftFactor, true ), - m_dx11PerClothDragFactor( m_dx11Device, m_dx11Context, &m_perClothDragFactor, true ), - m_dx11PerClothMediumDensity( m_dx11Device, m_dx11Context, &m_perClothMediumDensity, true ), - m_dx11PerClothCollisionObjects( m_dx11Device, m_dx11Context, &m_perClothCollisionObjects, true ), - m_dx11CollisionObjectDetails( m_dx11Device, m_dx11Context, &m_collisionObjectDetails, true ), - m_dx11PerClothMinBounds( m_dx11Device, m_dx11Context, &m_perClothMinBounds, false ), - m_dx11PerClothMaxBounds( m_dx11Device, m_dx11Context, &m_perClothMaxBounds, false ), - m_dx11PerClothFriction( m_dx11Device, m_dx11Context, &m_perClothFriction, false ), - m_enableUpdateBounds(false) -{ - // Initial we will clearly need to update solver constants - // For now this is global for the cloths linked with this solver - we should probably make this body specific - // for performance in future once we understand more clearly when constants need to be updated - m_updateSolverConstants = true; - - m_shadersInitialized = false; -} - -btDX11SoftBodySolver::~btDX11SoftBodySolver() -{ - releaseKernels(); -} - -void btDX11SoftBodySolver::releaseKernels() -{ - - SAFE_RELEASE( prepareLinksKernel.kernel ); - SAFE_RELEASE( prepareLinksKernel.constBuffer ); - SAFE_RELEASE( integrateKernel.kernel ); - SAFE_RELEASE( integrateKernel.constBuffer ); - SAFE_RELEASE( integrateKernel.kernel ); - SAFE_RELEASE( solvePositionsFromLinksKernel.constBuffer ); - SAFE_RELEASE( solvePositionsFromLinksKernel.kernel ); - SAFE_RELEASE( updatePositionsFromVelocitiesKernel.constBuffer ); - SAFE_RELEASE( updatePositionsFromVelocitiesKernel.kernel ); - SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ); - SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel ); - SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ); - SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel ); - SAFE_RELEASE( resetNormalsAndAreasKernel.constBuffer ); - SAFE_RELEASE( resetNormalsAndAreasKernel.kernel ); - SAFE_RELEASE( normalizeNormalsAndAreasKernel.constBuffer ); - SAFE_RELEASE( normalizeNormalsAndAreasKernel.kernel ); - SAFE_RELEASE( updateSoftBodiesKernel.constBuffer ); - SAFE_RELEASE( updateSoftBodiesKernel.kernel ); - SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.kernel ); - SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.constBuffer ); - SAFE_RELEASE( computeBoundsKernel.kernel ); - SAFE_RELEASE( computeBoundsKernel.constBuffer ); - SAFE_RELEASE( vSolveLinksKernel.kernel ); - SAFE_RELEASE( vSolveLinksKernel.constBuffer ); - - SAFE_RELEASE( addVelocityKernel.constBuffer ); - SAFE_RELEASE( addVelocityKernel.kernel ); - SAFE_RELEASE( applyForcesKernel.constBuffer ); - SAFE_RELEASE( applyForcesKernel.kernel ); - - m_shadersInitialized = false; -} - - -void btDX11SoftBodySolver::copyBackToSoftBodies(bool bMove) -{ - // Move the vertex data back to the host first - m_vertexData.moveFromAccelerator(!bMove); - - // Loop over soft bodies, copying all the vertex positions back for each body in turn - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ]; - btSoftBody *softBody = softBodyInterface->getSoftBody(); - - int firstVertex = softBodyInterface->getFirstVertex(); - int numVertices = softBodyInterface->getNumVertices(); - - // Copy vertices from solver back into the softbody - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - using Vectormath::Aos::Point3; - Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] ); - - softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() ); - softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() ); - softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() ); - - softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() ); - softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() ); - softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() ); - } - } -} // btDX11SoftBodySolver::copyBackToSoftBodies - - -void btDX11SoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate ) -{ - if( forceUpdate || m_softBodySet.size() != softBodies.size() ) - { - // Have a change in the soft body set so update, reloading all the data - getVertexData().clear(); - getTriangleData().clear(); - getLinkData().clear(); - m_softBodySet.resize(0); - - - for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) - { - btSoftBody *softBody = softBodies[ softBodyIndex ]; - using Vectormath::Aos::Matrix3; - using Vectormath::Aos::Point3; - - // Create SoftBody that will store the information within the solver - btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody ); - m_softBodySet.push_back( newSoftBody ); - - m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); - m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); - m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); - m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); - m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); - m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); - // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time - m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) ); - m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) ); - m_perClothFriction.push_back( softBody->getFriction() ); - m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); - - // Add space for new vertices and triangles in the default solver for now - // TODO: Include space here for tearing too later - int firstVertex = getVertexData().getNumVertices(); - int numVertices = softBody->m_nodes.size(); - int maxVertices = numVertices; - // Allocate space for new vertices in all the vertex arrays - getVertexData().createVertices( maxVertices, softBodyIndex ); - - int firstTriangle = getTriangleData().getNumTriangles(); - int numTriangles = softBody->m_faces.size(); - int maxTriangles = numTriangles; - getTriangleData().createTriangles( maxTriangles ); - - // Copy vertices from softbody into the solver - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); - btSoftBodyVertexData::VertexDescription desc; - - // TODO: Position in the softbody might be pre-transformed - // or we may need to adapt for the pose. - //desc.setPosition( cloth.getMeshTransform()*multPoint ); - desc.setPosition( multPoint ); - - float vertexInverseMass = softBody->m_nodes[vertex].m_im; - desc.setInverseMass(vertexInverseMass); - getVertexData().setVertexAt( desc, firstVertex + vertex ); - } - - // Copy triangles similarly - // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene - for( int triangle = 0; triangle < numTriangles; ++triangle ) - { - // Note that large array storage is relative to the array not to the cloth - // So we need to add firstVertex to each value - int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); - int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); - int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); - btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); - getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); - - // Increase vertex triangle counts for this triangle - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; - } - - int firstLink = getLinkData().getNumLinks(); - int numLinks = softBody->m_links.size(); - int maxLinks = numLinks; - - // Allocate space for the links - getLinkData().createLinks( numLinks ); - - // Add the links - for( int link = 0; link < numLinks; ++link ) - { - int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); - int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); - - btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); - newLink.setLinkStrength(1.f); - getLinkData().setLinkAt(newLink, firstLink + link); - } - - newSoftBody->setFirstVertex( firstVertex ); - newSoftBody->setFirstTriangle( firstTriangle ); - newSoftBody->setNumVertices( numVertices ); - newSoftBody->setMaxVertices( maxVertices ); - newSoftBody->setNumTriangles( numTriangles ); - newSoftBody->setMaxTriangles( maxTriangles ); - newSoftBody->setFirstLink( firstLink ); - newSoftBody->setNumLinks( numLinks ); - } - - - - updateConstants(0.f); - - - m_linkData.generateBatches(); - m_triangleData.generateBatches(); - } -} - - -btSoftBodyLinkData &btDX11SoftBodySolver::getLinkData() -{ - // TODO: Consider setting link data to "changed" here - return m_linkData; -} - -btSoftBodyVertexData &btDX11SoftBodySolver::getVertexData() -{ - // TODO: Consider setting vertex data to "changed" here - return m_vertexData; -} - -btSoftBodyTriangleData &btDX11SoftBodySolver::getTriangleData() -{ - // TODO: Consider setting triangle data to "changed" here - return m_triangleData; -} - -bool btDX11SoftBodySolver::checkInitialized() -{ - if( !m_shadersInitialized ) - if( buildShaders() ) - m_shadersInitialized = true; - - return m_shadersInitialized; -} - -void btDX11SoftBodySolver::resetNormalsAndAreas( int numVertices ) -{ - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - UpdateSoftBodiesCB constBuffer; - - constBuffer.numNodes = numVertices; - constBuffer.epsilon = FLT_EPSILON; - - // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); - m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( resetNormalsAndAreasKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::resetNormalsAndAreas - -void btDX11SoftBodySolver::normalizeNormalsAndAreas( int numVertices ) -{ - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - UpdateSoftBodiesCB constBuffer; - - constBuffer.numNodes = numVertices; - constBuffer.epsilon = FLT_EPSILON; - - // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); - m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexTriangleCount.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( normalizeNormalsAndAreasKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::normalizeNormalsAndAreas - -void btDX11SoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles ) -{ - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - UpdateSoftBodiesCB constBuffer; - - constBuffer.startFace = firstTriangle; - constBuffer.numFaces = numTriangles; - - // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( updateSoftBodiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) ); - m_dx11Context->Unmap( updateSoftBodiesKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &updateSoftBodiesKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_triangleData.m_dx11VertexIndices.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_triangleData.m_dx11Normal.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_triangleData.m_dx11Area.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( updateSoftBodiesKernel.kernel, NULL, 0 ); - - int numBlocks = (numTriangles + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::executeUpdateSoftBodies - -void btDX11SoftBodySolver::updateSoftBodies() -{ - using namespace Vectormath::Aos; - - - int numVertices = m_vertexData.getNumVertices(); - int numTriangles = m_triangleData.getNumTriangles(); - - // Ensure data is on accelerator - m_vertexData.moveToAccelerator(); - m_triangleData.moveToAccelerator(); - - resetNormalsAndAreas( numVertices ); - - - // Go through triangle batches so updates occur correctly - for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex ) - { - - int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].start; - int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].length; - - executeUpdateSoftBodies( startTriangle, numTriangles ); - } - - - normalizeNormalsAndAreas( numVertices ); - - -} // btDX11SoftBodySolver::updateSoftBodies - - -Vectormath::Aos::Vector3 btDX11SoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ) -{ - return a*Vectormath::Aos::dot(v, a); -} - -void btDX11SoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ) -{ - float dtInverseMass = solverdt*inverseMass; - if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) ) - { - vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass; - } else { - vertexForce += force; - } -} - -void btDX11SoftBodySolver::applyForces( float solverdt ) -{ - using namespace Vectormath::Aos; - - - // Ensure data is on accelerator - m_vertexData.moveToAccelerator(); - m_dx11PerClothAcceleration.moveToGPU(); - m_dx11PerClothLiftFactor.moveToGPU(); - m_dx11PerClothDragFactor.moveToGPU(); - m_dx11PerClothMediumDensity.moveToGPU(); - m_dx11PerClothWindVelocity.moveToGPU(); - - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - ApplyForcesCB constBuffer; - - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.solverdt = solverdt; - constBuffer.epsilon = FLT_EPSILON; - - // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(ApplyForcesCB) ); - m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexNormal.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexArea.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); - m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothLiftFactor.getSRV()) ); - m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11PerClothDragFactor.getSRV()) ); - m_dx11Context->CSSetShaderResources( 6, 1, &(m_dx11PerClothWindVelocity.getSRV()) ); - m_dx11Context->CSSetShaderResources( 7, 1, &(m_dx11PerClothAcceleration.getSRV()) ); - m_dx11Context->CSSetShaderResources( 8, 1, &(m_dx11PerClothMediumDensity.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( applyForcesKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 6, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 7, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 8, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::applyForces - -/** - * Integrate motion on the solver. - */ -void btDX11SoftBodySolver::integrate( float solverdt ) -{ - // TEMPORARY COPIES - m_vertexData.moveToAccelerator(); - - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - IntegrateCB constBuffer; - - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.solverdt = solverdt; - - // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(IntegrateCB) ); - m_dx11Context->Unmap( integrateKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( integrateKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::integrate - -float btDX11SoftBodySolver::computeTriangleArea( - const Vectormath::Aos::Point3 &vertex0, - const Vectormath::Aos::Point3 &vertex1, - const Vectormath::Aos::Point3 &vertex2 ) -{ - Vectormath::Aos::Vector3 a = vertex1 - vertex0; - Vectormath::Aos::Vector3 b = vertex2 - vertex0; - Vectormath::Aos::Vector3 crossProduct = cross(a, b); - float area = length( crossProduct ); - return area; -} // btDX11SoftBodySolver::computeTriangleArea - - -void btDX11SoftBodySolver::updateBounds() -{ - using Vectormath::Aos::Point3; - // Interpretation structure for float and int - - struct FPRep { - unsigned int mantissa : 23; - unsigned int exponent : 8; - unsigned int sign : 1; - }; - union FloatAsInt - { - float floatValue; - int intValue; - unsigned int uintValue; - FPRep fpRep; - }; - - - // Update bounds array to min and max int values to allow easy atomics - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - m_perClothMinBounds[softBodyIndex] = UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ); - m_perClothMaxBounds[softBodyIndex] = UIntVector3( 0, 0, 0 ); - } - - m_dx11PerClothMinBounds.moveToGPU(); - m_dx11PerClothMaxBounds.moveToGPU(); - - - computeBounds( ); - - - m_dx11PerClothMinBounds.moveFromGPU(); - m_dx11PerClothMaxBounds.moveFromGPU(); - - - - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - UIntVector3 minBoundUInt = m_perClothMinBounds[softBodyIndex]; - UIntVector3 maxBoundUInt = m_perClothMaxBounds[softBodyIndex]; - - // Convert back to float - FloatAsInt fai; - - btVector3 minBound; - fai.uintValue = minBoundUInt.x; - fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); - minBound.setX( fai.floatValue ); - fai.uintValue = minBoundUInt.y; - fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); - minBound.setY( fai.floatValue ); - fai.uintValue = minBoundUInt.z; - fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); - minBound.setZ( fai.floatValue ); - - btVector3 maxBound; - fai.uintValue = maxBoundUInt.x; - fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); - maxBound.setX( fai.floatValue ); - fai.uintValue = maxBoundUInt.y; - fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); - maxBound.setY( fai.floatValue ); - fai.uintValue = maxBoundUInt.z; - fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000); - maxBound.setZ( fai.floatValue ); - - // And finally assign to the soft body - m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound ); - } -} - -void btDX11SoftBodySolver::updateConstants( float timeStep ) -{ - using namespace Vectormath::Aos; - - if( m_updateSolverConstants ) - { - m_updateSolverConstants = false; - - // Will have to redo this if we change the structure (tear, maybe) or various other possible changes - - // Initialise link constants - const int numLinks = m_linkData.getNumLinks(); - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); - m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); - float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); - float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); - float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); - float massLSC = (invMass0 + invMass1)/linearStiffness; - m_linkData.getMassLSC(linkIndex) = massLSC; - float restLength = m_linkData.getRestLength(linkIndex); - float restLengthSquared = restLength*restLength; - m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; - } - } -} // btDX11SoftBodySolver::updateConstants - -/** - * Sort the collision object details array and generate indexing into it for the per-cloth collision object array. - */ -void btDX11SoftBodySolver::prepareCollisionConstraints() -{ - // First do a simple sort on the collision objects - btAlignedObjectArray numObjectsPerClothPrefixSum; - btAlignedObjectArray numObjectsPerCloth; - numObjectsPerCloth.resize( m_softBodySet.size(), 0 ); - numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 ); - - - class QuickSortCompare - { - public: - - bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const - { - return ( a.softBodyIdentifier < b.softBodyIdentifier ); - } - }; - - QuickSortCompare comparator; - m_collisionObjectDetails.quickSort( comparator ); - - // Generating indexing for perClothCollisionObjects - // First clear the previous values with the "no collision object for cloth" constant - for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex ) - { - m_perClothCollisionObjects[clothIndex].firstObject = -1; - m_perClothCollisionObjects[clothIndex].endObject = -1; - } - int currentCloth = 0; - int startIndex = 0; - for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject ) - { - int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier; - if( nextCloth != currentCloth ) - { - // Changed cloth in the array - // Set the end index and the range is what we need for currentCloth - m_perClothCollisionObjects[currentCloth].firstObject = startIndex; - m_perClothCollisionObjects[currentCloth].endObject = collisionObject; - currentCloth = nextCloth; - startIndex = collisionObject; - } - } - - // And update last cloth - m_perClothCollisionObjects[currentCloth].firstObject = startIndex; - m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size(); - -} // btDX11SoftBodySolver::prepareCollisionConstraints - - -void btDX11SoftBodySolver::solveConstraints( float solverdt ) -{ - - //std::cerr << "'GPU' solve constraints\n"; - using Vectormath::Aos::Vector3; - using Vectormath::Aos::Point3; - using Vectormath::Aos::lengthSqr; - using Vectormath::Aos::dot; - - // Prepare links - int numLinks = m_linkData.getNumLinks(); - int numVertices = m_vertexData.getNumVertices(); - - float kst = 1.f; - float ti = 0.f; - - - m_dx11PerClothDampingFactor.moveToGPU(); - m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU(); - - - // Ensure data is on accelerator - m_linkData.moveToAccelerator(); - m_vertexData.moveToAccelerator(); - - - prepareLinks(); - - for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration ) - { - for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) - { - int startLink = m_linkData.m_batchStartLengths[i].start; - int numLinks = m_linkData.m_batchStartLengths[i].length; - - solveLinksForVelocity( startLink, numLinks, kst ); - } - } - - - prepareCollisionConstraints(); - - // Compute new positions from velocity - // Also update the previous position so that our position computation is now based on the new position from the velocity solution - // rather than based directly on the original positions - if( m_numberOfVelocityIterations > 0 ) - { - updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt ); - } else { - updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt ); - } - - - // Solve drift - for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - { - for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) - { - int startLink = m_linkData.m_batchStartLengths[i].start; - int numLinks = m_linkData.m_batchStartLengths[i].length; - - solveLinksForPosition( startLink, numLinks, kst, ti ); - } - - } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - - // At this point assume that the force array is blank - we will overwrite it - solveCollisionsAndUpdateVelocities( 1.f/solverdt ); -} // btDX11SoftBodySolver::solveConstraints - - - - -////////////////////////////////////// -// Kernel dispatches -void btDX11SoftBodySolver::prepareLinks() -{ - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - PrepareLinksCB constBuffer; - - constBuffer.numLinks = m_linkData.getNumLinks(); - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( prepareLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(PrepareLinksCB) ); - m_dx11Context->Unmap( prepareLinksKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &prepareLinksKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_linkData.m_dx11LinksLengthRatio.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_linkData.m_dx11LinksCLength.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( prepareLinksKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numLinks + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::prepareLinks - - -void btDX11SoftBodySolver::updatePositionsFromVelocities( float solverdt ) -{ - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - UpdatePositionsFromVelocitiesCB constBuffer; - - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.solverSDT = solverdt; - - // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( updatePositionsFromVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(UpdatePositionsFromVelocitiesCB) ); - m_dx11Context->Unmap( updatePositionsFromVelocitiesKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &updatePositionsFromVelocitiesKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( updatePositionsFromVelocitiesKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::updatePositionsFromVelocities - -void btDX11SoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti ) -{ - // Copy kernel parameters to GPU - SolvePositionsFromLinksKernelCB constBuffer; - - // Set the first link of the batch - // and the batch size - constBuffer.startLink = startLink; - constBuffer.numLinks = numLinks; - - constBuffer.kst = kst; - constBuffer.ti = ti; - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) ); - m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numLinks + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } - -} // btDX11SoftBodySolver::solveLinksForPosition - -void btDX11SoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst ) -{ - // Copy kernel parameters to GPU - VSolveLinksCB constBuffer; - - // Set the first link of the batch - // and the batch size - - constBuffer.startLink = startLink; - constBuffer.numLinks = numLinks; - constBuffer.kst = kst; - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( vSolveLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(VSolveLinksCB) ); - m_dx11Context->Unmap( vSolveLinksKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &vSolveLinksKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksLengthRatio.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksCLength.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( vSolveLinksKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numLinks + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SoftBodySolver::solveLinksForVelocity - - -void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt ) -{ - // Copy kernel parameters to GPU - UpdateVelocitiesFromPositionsWithVelocitiesCB constBuffer; - - // Set the first link of the batch - // and the batch size - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.isolverdt = isolverdt; - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); - m_dx11Context->Unmap( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothVelocityCorrectionCoefficient.getSRV()) ); - m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); - - - // Execute the kernel - m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } - -} // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities - -void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ) -{ - // Copy kernel parameters to GPU - UpdateVelocitiesFromPositionsWithoutVelocitiesCB constBuffer; - - // Set the first link of the batch - // and the batch size - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.isolverdt = isolverdt; - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); - m_dx11Context->Unmap( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); - - - // Execute the kernel - m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } - -} // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities - - -void btDX11SoftBodySolver::computeBounds( ) -{ - ComputeBoundsCB constBuffer; - m_vertexData.moveToAccelerator(); - - // Set the first link of the batch - // and the batch size - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.numSoftBodies = m_softBodySet.size(); - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( computeBoundsKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(ComputeBoundsCB) ); - m_dx11Context->Unmap( computeBoundsKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &computeBoundsKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_dx11PerClothMinBounds.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_dx11PerClothMaxBounds.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( computeBoundsKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} - -void btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt ) -{ - - // Copy kernel parameters to GPU - m_vertexData.moveToAccelerator(); - m_dx11PerClothFriction.moveToGPU(); - m_dx11PerClothDampingFactor.moveToGPU(); - m_dx11PerClothCollisionObjects.moveToGPU(); - m_dx11CollisionObjectDetails.moveToGPU(); - - SolveCollisionsAndUpdateVelocitiesCB constBuffer; - - // Set the first link of the batch - // and the batch size - constBuffer.numNodes = m_vertexData.getNumVertices(); - constBuffer.isolverdt = isolverdt; - - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); - m_dx11Context->Unmap( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &solveCollisionsAndUpdateVelocitiesKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_dx11PerClothFriction.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) ); - m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothCollisionObjects.getSRV()) ); - m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11CollisionObjectDetails.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( solveCollisionsAndUpdateVelocitiesKernel.kernel, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL ); - m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } - -} // btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities - -// End kernel dispatches -///////////////////////////////////// - - - - - - - - - - - - - - -btDX11SoftBodySolver::btAcceleratedSoftBodyInterface *btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) -{ - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; - if( softBodyInterface->getSoftBody() == softBody ) - return softBodyInterface; - } - return 0; -} - -const btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * const btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) const -{ - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; - if( softBodyInterface->getSoftBody() == softBody ) - return softBodyInterface; - } - return 0; -} - -int btDX11SoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody ) -{ - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex]; - if( softBodyInterface->getSoftBody() == softBody ) - return softBodyIndex; - } - return 1; -} - - -void btSoftBodySolverOutputDXtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) -{ - - - btSoftBodySolver *solver = softBody->getSoftBodySolver(); - btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER ); - btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver ); - - btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody ); - btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData ); - - - const int firstVertex = currentCloth->getFirstVertex(); - const int lastVertex = firstVertex + currentCloth->getNumVertices(); - - if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) - { - // If we're doing a CPU-buffer copy must copy the data back to the host first - vertexData.m_dx11VertexPosition.copyFromGPU(); - vertexData.m_dx11VertexNormal.copyFromGPU(); - - const int firstVertex = currentCloth->getFirstVertex(); - const int lastVertex = firstVertex + currentCloth->getNumVertices(); - const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); - float *basePointer = cpuVertexBuffer->getBasePointer(); - - if( vertexBuffer->hasVertexPositions() ) - { - const int vertexOffset = cpuVertexBuffer->getVertexOffset(); - const int vertexStride = cpuVertexBuffer->getVertexStride(); - float *vertexPointer = basePointer + vertexOffset; - - for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) - { - Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex); - *(vertexPointer + 0) = position.getX(); - *(vertexPointer + 1) = position.getY(); - *(vertexPointer + 2) = position.getZ(); - vertexPointer += vertexStride; - } - } - if( vertexBuffer->hasNormals() ) - { - const int normalOffset = cpuVertexBuffer->getNormalOffset(); - const int normalStride = cpuVertexBuffer->getNormalStride(); - float *normalPointer = basePointer + normalOffset; - - for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) - { - Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex); - *(normalPointer + 0) = normal.getX(); - *(normalPointer + 1) = normal.getY(); - *(normalPointer + 2) = normal.getZ(); - normalPointer += normalStride; - } - } - } -} // btDX11SoftBodySolver::outputToVertexBuffers - - - -bool btSoftBodySolverOutputDXtoDX::checkInitialized() -{ - if( !m_shadersInitialized ) - if( buildShaders() ) - m_shadersInitialized = true; - - return m_shadersInitialized; -} - -void btSoftBodySolverOutputDXtoDX::releaseKernels() -{ - SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.constBuffer ); - SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.kernel ); - SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.constBuffer ); - SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.kernel ); - - m_shadersInitialized = false; -} - - -bool btSoftBodySolverOutputDXtoDX::buildShaders() -{ - // Ensure current kernels are released first - releaseKernels(); - - bool returnVal = true; - - if( m_shadersInitialized ) - return true; - - - outputToVertexArrayWithNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithNormalsKernel", sizeof(OutputToVertexArrayCB) ); - if( !outputToVertexArrayWithNormalsKernel.constBuffer) - returnVal = false; - outputToVertexArrayWithoutNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithoutNormalsKernel", sizeof(OutputToVertexArrayCB) ); - if( !outputToVertexArrayWithoutNormalsKernel.constBuffer ) - returnVal = false; - - - if( returnVal ) - m_shadersInitialized = true; - - return returnVal; -} - - -void btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) -{ - - - btSoftBodySolver *solver = softBody->getSoftBodySolver(); - btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER ); - btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver ); - checkInitialized(); - btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody ); - btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData ); - - - const int firstVertex = currentCloth->getFirstVertex(); - const int lastVertex = firstVertex + currentCloth->getNumVertices(); - - if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) - { - btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( softBody, vertexBuffer ); - } else if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::DX11_BUFFER ) - { - // Do a DX11 copy shader DX to DX copy - - const btDX11VertexBufferDescriptor *dx11VertexBuffer = static_cast< btDX11VertexBufferDescriptor* >(vertexBuffer); - - // No need to batch link solver, it is entirely parallel - // Copy kernel parameters to GPU - OutputToVertexArrayCB constBuffer; - ID3D11ComputeShader* outputToVertexArrayShader = outputToVertexArrayWithoutNormalsKernel.kernel; - ID3D11Buffer* outputToVertexArrayConstBuffer = outputToVertexArrayWithoutNormalsKernel.constBuffer; - - constBuffer.startNode = firstVertex; - constBuffer.numNodes = currentCloth->getNumVertices(); - constBuffer.positionOffset = vertexBuffer->getVertexOffset(); - constBuffer.positionStride = vertexBuffer->getVertexStride(); - if( vertexBuffer->hasNormals() ) - { - constBuffer.normalOffset = vertexBuffer->getNormalOffset(); - constBuffer.normalStride = vertexBuffer->getNormalStride(); - outputToVertexArrayShader = outputToVertexArrayWithNormalsKernel.kernel; - outputToVertexArrayConstBuffer = outputToVertexArrayWithNormalsKernel.constBuffer; - } - - // TODO: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - dxFunctions.m_dx11Context->Map( outputToVertexArrayConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(OutputToVertexArrayCB) ); - dxFunctions.m_dx11Context->Unmap( outputToVertexArrayConstBuffer, 0 ); - dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &outputToVertexArrayConstBuffer ); - - // Set resources and dispatch - dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &(vertexData.m_dx11VertexPosition.getSRV()) ); - dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &(vertexData.m_dx11VertexNormal.getSRV()) ); - - ID3D11UnorderedAccessView* dx11UAV = dx11VertexBuffer->getDX11UAV(); - dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(dx11UAV), NULL ); - - // Execute the kernel - dxFunctions.m_dx11Context->CSSetShader( outputToVertexArrayShader, NULL, 0 ); - - int numBlocks = (constBuffer.numNodes + (128-1)) / 128; - dxFunctions.m_dx11Context->Dispatch(numBlocks, 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } - } -} // btDX11SoftBodySolver::outputToVertexBuffers - - - - -DXFunctions::KernelDesc DXFunctions::compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros ) -{ - const char *cs5String = "cs_5_0"; - - HRESULT hr = S_OK; - ID3DBlob* pErrorBlob = NULL; - ID3DBlob* pBlob = NULL; - ID3D11ComputeShader* kernelPointer = 0; - - hr = m_dx11CompileFromMemory( - shaderString, - strlen(shaderString), - shaderName, - compileMacros, - NULL, - shaderName, - cs5String, - D3D10_SHADER_ENABLE_STRICTNESS, - NULL, - NULL, - &pBlob, - &pErrorBlob, - NULL - ); - - if( FAILED(hr) ) - { - if( pErrorBlob ) { - btAssert( "Compilation of compute shader failed\n" ); - char *debugString = (char*)pErrorBlob->GetBufferPointer(); - OutputDebugStringA( debugString ); - } - - SAFE_RELEASE( pErrorBlob ); - SAFE_RELEASE( pBlob ); - - DXFunctions::KernelDesc descriptor; - descriptor.kernel = 0; - descriptor.constBuffer = 0; - return descriptor; - } - - // Create the Compute Shader - hr = m_dx11Device->CreateComputeShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &kernelPointer ); - if( FAILED( hr ) ) - { - DXFunctions::KernelDesc descriptor; - descriptor.kernel = 0; - descriptor.constBuffer = 0; - return descriptor; - } - - ID3D11Buffer* constBuffer = 0; - if( constBufferSize > 0 ) - { - // Create the constant buffer - D3D11_BUFFER_DESC constant_buffer_desc; - ZeroMemory(&constant_buffer_desc, sizeof(constant_buffer_desc)); - constant_buffer_desc.ByteWidth = constBufferSize; - constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; - constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - m_dx11Device->CreateBuffer(&constant_buffer_desc, NULL, &constBuffer); - if( FAILED( hr ) ) - { - KernelDesc descriptor; - descriptor.kernel = 0; - descriptor.constBuffer = 0; - return descriptor; - } - } - - SAFE_RELEASE( pErrorBlob ); - SAFE_RELEASE( pBlob ); - - DXFunctions::KernelDesc descriptor; - descriptor.kernel = kernelPointer; - descriptor.constBuffer = constBuffer; - return descriptor; -} // compileComputeShader - - - -bool btDX11SoftBodySolver::buildShaders() -{ - // Ensure current kernels are released first - releaseKernels(); - - bool returnVal = true; - - if( m_shadersInitialized ) - return true; - - prepareLinksKernel = dxFunctions.compileComputeShaderFromString( PrepareLinksHLSLString, "PrepareLinksKernel", sizeof(PrepareLinksCB) ); - if( !prepareLinksKernel.constBuffer ) - returnVal = false; - updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) ); - if( !updatePositionsFromVelocitiesKernel.constBuffer ) - returnVal = false; - solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB) ); - if( !updatePositionsFromVelocitiesKernel.constBuffer ) - returnVal = false; - vSolveLinksKernel = dxFunctions.compileComputeShaderFromString( VSolveLinksHLSLString, "VSolveLinksKernel", sizeof(VSolveLinksCB) ); - if( !vSolveLinksKernel.constBuffer ) - returnVal = false; - updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); - if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ) - returnVal = false; - updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); - if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ) - returnVal = false; - integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) ); - if( !integrateKernel.constBuffer ) - returnVal = false; - applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) ); - if( !applyForcesKernel.constBuffer ) - returnVal = false; - solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); - if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer ) - returnVal = false; - - // TODO: Rename to UpdateSoftBodies - resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); - if( !resetNormalsAndAreasKernel.constBuffer ) - returnVal = false; - normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); - if( !normalizeNormalsAndAreasKernel.constBuffer ) - returnVal = false; - updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) ); - if( !updateSoftBodiesKernel.constBuffer ) - returnVal = false; - - computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) ); - if( !computeBoundsKernel.constBuffer ) - returnVal = false; - - - - if( returnVal ) - m_shadersInitialized = true; - - return returnVal; -} - - -static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) -{ - Vectormath::Aos::Transform3 outTransform; - outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); - outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); - outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); - outTransform.setCol(3, toVector3(transform.getOrigin())); - return outTransform; -} - - -void btDX11SoftBodySolver::btAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ) -{ - float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin(); - btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin ); - m_softBody->m_bounds[0] = lowerBound - vectorMargin; - m_softBody->m_bounds[1] = upperBound + vectorMargin; -} - -void btDX11SoftBodySolver::processCollision( btSoftBody*, btSoftBody* ) -{ - -} - -// Add the collision object to the set to deal with for a particular soft body -void btDX11SoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObject ) -{ - int softBodyIndex = findSoftBodyIndex( softBody ); - - if( softBodyIndex >= 0 ) - { - const btCollisionShape *collisionShape = collisionObject->getCollisionShape(); - float friction = collisionObject->getCollisionObject()->getFriction(); - int shapeType = collisionShape->getShapeType(); - if( shapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Add to the list of expected collision objects - CollisionShapeDescription newCollisionShapeDescription; - newCollisionShapeDescription.softBodyIdentifier = softBodyIndex; - newCollisionShapeDescription.collisionShapeType = shapeType; - // TODO: May need to transpose this matrix either here or in HLSL - newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform()); - const btCapsuleShape *capsule = static_cast( collisionShape ); - newCollisionShapeDescription.radius = capsule->getRadius(); - newCollisionShapeDescription.halfHeight = capsule->getHalfHeight(); - newCollisionShapeDescription.margin = capsule->getMargin(); - newCollisionShapeDescription.friction = friction; - const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() ); - newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity()); - newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity()); - m_collisionObjectDetails.push_back( newCollisionShapeDescription ); - - } else { -#ifdef _DEBUG - printf("Unsupported collision shape type\n"); -#endif - } - } else { - btAssert("Unknown soft body"); - } -} // btDX11SoftBodySolver::processCollision - - - -void btDX11SoftBodySolver::predictMotion( float timeStep ) -{ - // Clear the collision shape array for the next frame - // Ensure that the DX11 ones are moved off the device so they will be updated correctly - m_dx11CollisionObjectDetails.changedOnCPU(); - m_dx11PerClothCollisionObjects.changedOnCPU(); - m_collisionObjectDetails.clear(); - - // Fill the force arrays with current acceleration data etc - m_perClothWindVelocity.resize( m_softBodySet.size() ); - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); - - m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); - } - m_dx11PerClothWindVelocity.changedOnCPU(); - - // Apply forces that we know about to the cloths - applyForces( timeStep * getTimeScale() ); - - // Itegrate motion for all soft bodies dealt with by the solver - integrate( timeStep * getTimeScale() ); - - // Update bounds - // Will update the bounds for all softBodies being dealt with by the solver and - // set the values in the btSoftBody object - if (m_enableUpdateBounds) - updateBounds(); - - // End prediction work for solvers -} - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h deleted file mode 100644 index 0f50ecf7..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11.h +++ /dev/null @@ -1,691 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H -#define BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H - - -#include "vectormath/vmInclude.h" -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "btSoftBodySolverVertexBuffer_DX11.h" -#include "btSoftBodySolverLinkData_DX11.h" -#include "btSoftBodySolverVertexData_DX11.h" -#include "btSoftBodySolverTriangleData_DX11.h" - - - -class DXFunctions -{ -public: - - typedef HRESULT (WINAPI * CompileFromMemoryFunc)(LPCSTR,SIZE_T,LPCSTR,const D3D10_SHADER_MACRO*,LPD3D10INCLUDE,LPCSTR,LPCSTR,UINT,UINT,ID3DX11ThreadPump*,ID3D10Blob**,ID3D10Blob**,HRESULT*); - - ID3D11Device * m_dx11Device; - ID3D11DeviceContext* m_dx11Context; - CompileFromMemoryFunc m_dx11CompileFromMemory; - - DXFunctions(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, CompileFromMemoryFunc dx11CompileFromMemory) : - m_dx11Device( dx11Device ), - m_dx11Context( dx11Context ), - m_dx11CompileFromMemory( dx11CompileFromMemory ) - { - - } - - class KernelDesc - { - protected: - - - public: - ID3D11ComputeShader* kernel; - ID3D11Buffer* constBuffer; - - KernelDesc() - { - kernel = 0; - constBuffer = 0; - } - - virtual ~KernelDesc() - { - // TODO: this should probably destroy its kernel but we need to be careful - // in case KernelDescs are copied - } - }; - - /** - * Compile a compute shader kernel from a string and return the appropriate KernelDesc object. - */ - KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros = 0 ); - -}; - -class btDX11SoftBodySolver : public btSoftBodySolver -{ -protected: - /** - * Entry in the collision shape array. - * Specifies the shape type, the transform matrix and the necessary details of the collisionShape. - */ - struct CollisionShapeDescription - { - Vectormath::Aos::Transform3 shapeTransform; - Vectormath::Aos::Vector3 linearVelocity; - Vectormath::Aos::Vector3 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - // Both needed for capsule - float radius; - float halfHeight; - - float margin; - float friction; - - CollisionShapeDescription() - { - collisionShapeType = 0; - margin = 0; - friction = 0; - } - }; - - struct UIntVector3 - { - UIntVector3() - { - x = 0; - y = 0; - z = 0; - _padding = 0; - } - - UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ ) - { - x = x_; - y = y_; - z = z_; - _padding = 0; - } - - unsigned int x; - unsigned int y; - unsigned int z; - unsigned int _padding; - }; - - - -public: - /** - * SoftBody class to maintain information about a soft body instance - * within a solver. - * This data addresses the main solver arrays. - */ - class btAcceleratedSoftBodyInterface - { - protected: - /** Current number of vertices that are part of this cloth */ - int m_numVertices; - /** Maximum number of vertices allocated to be part of this cloth */ - int m_maxVertices; - /** Current number of triangles that are part of this cloth */ - int m_numTriangles; - /** Maximum number of triangles allocated to be part of this cloth */ - int m_maxTriangles; - /** Index of first vertex in the world allocated to this cloth */ - int m_firstVertex; - /** Index of first triangle in the world allocated to this cloth */ - int m_firstTriangle; - /** Index of first link in the world allocated to this cloth */ - int m_firstLink; - /** Maximum number of links allocated to this cloth */ - int m_maxLinks; - /** Current number of links allocated to this cloth */ - int m_numLinks; - - /** The actual soft body this data represents */ - btSoftBody *m_softBody; - - - public: - btAcceleratedSoftBodyInterface( btSoftBody *softBody ) : - m_softBody( softBody ) - { - m_numVertices = 0; - m_maxVertices = 0; - m_numTriangles = 0; - m_maxTriangles = 0; - m_firstVertex = 0; - m_firstTriangle = 0; - m_firstLink = 0; - m_maxLinks = 0; - m_numLinks = 0; - } - int getNumVertices() const - { - return m_numVertices; - } - - int getNumTriangles() const - { - return m_numTriangles; - } - - int getMaxVertices() const - { - return m_maxVertices; - } - - int getMaxTriangles() const - { - return m_maxTriangles; - } - - int getFirstVertex() const - { - return m_firstVertex; - } - - int getFirstTriangle() const - { - return m_firstTriangle; - } - - - /** - * Update the bounds in the btSoftBody object - */ - void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ); - - - // TODO: All of these set functions will have to do checks and - // update the world because restructuring of the arrays will be necessary - // Reasonable use of "friend"? - void setNumVertices( int numVertices ) - { - m_numVertices = numVertices; - } - - void setNumTriangles( int numTriangles ) - { - m_numTriangles = numTriangles; - } - - void setMaxVertices( int maxVertices ) - { - m_maxVertices = maxVertices; - } - - void setMaxTriangles( int maxTriangles ) - { - m_maxTriangles = maxTriangles; - } - - void setFirstVertex( int firstVertex ) - { - m_firstVertex = firstVertex; - } - - void setFirstTriangle( int firstTriangle ) - { - m_firstTriangle = firstTriangle; - } - - void setMaxLinks( int maxLinks ) - { - m_maxLinks = maxLinks; - } - - void setNumLinks( int numLinks ) - { - m_numLinks = numLinks; - } - - void setFirstLink( int firstLink ) - { - m_firstLink = firstLink; - } - - int getMaxLinks() - { - return m_maxLinks; - } - - int getNumLinks() - { - return m_numLinks; - } - - int getFirstLink() - { - return m_firstLink; - } - - btSoftBody* getSoftBody() - { - return m_softBody; - } - - }; - - - struct CollisionObjectIndices - { - CollisionObjectIndices( int f, int e ) - { - firstObject = f; - endObject = e; - } - - int firstObject; - int endObject; - }; - - - - - - struct PrepareLinksCB - { - int numLinks; - int padding0; - int padding1; - int padding2; - }; - - struct SolvePositionsFromLinksKernelCB - { - int startLink; - int numLinks; - float kst; - float ti; - }; - - struct IntegrateCB - { - int numNodes; - float solverdt; - int padding1; - int padding2; - }; - - struct UpdatePositionsFromVelocitiesCB - { - int numNodes; - float solverSDT; - int padding1; - int padding2; - }; - - struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB - { - int numNodes; - float isolverdt; - int padding1; - int padding2; - }; - - struct UpdateVelocitiesFromPositionsWithVelocitiesCB - { - int numNodes; - float isolverdt; - int padding1; - int padding2; - }; - - struct UpdateSoftBodiesCB - { - int numNodes; - int startFace; - int numFaces; - float epsilon; - }; - - - struct ApplyForcesCB - { - unsigned int numNodes; - float solverdt; - float epsilon; - int padding3; - }; - - struct AddVelocityCB - { - int startNode; - int lastNode; - float velocityX; - float velocityY; - float velocityZ; - int padding1; - int padding2; - int padding3; - }; - - struct VSolveLinksCB - { - int startLink; - int numLinks; - float kst; - int padding; - }; - - struct ComputeBoundsCB - { - int numNodes; - int numSoftBodies; - int padding1; - int padding2; - }; - - struct SolveCollisionsAndUpdateVelocitiesCB - { - unsigned int numNodes; - float isolverdt; - int padding0; - int padding1; - }; - - - - -protected: - ID3D11Device * m_dx11Device; - ID3D11DeviceContext* m_dx11Context; - - DXFunctions dxFunctions; -public: - /** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */ - btSoftBodyLinkDataDX11 m_linkData; - btSoftBodyVertexDataDX11 m_vertexData; - btSoftBodyTriangleDataDX11 m_triangleData; - -protected: - - /** Variable to define whether we need to update solver constants on the next iteration */ - bool m_updateSolverConstants; - - bool m_shadersInitialized; - - /** - * Cloths owned by this solver. - * Only our cloths are in this array. - */ - btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet; - - /** Acceleration value to be applied to all non-static vertices in the solver. - * Index n is cloth n, array sized by number of cloths in the world not the solver. - */ - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration; - btDX11Buffer m_dx11PerClothAcceleration; - - /** Wind velocity to be applied normal to all non-static vertices in the solver. - * Index n is cloth n, array sized by number of cloths in the world not the solver. - */ - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity; - btDX11Buffer m_dx11PerClothWindVelocity; - - /** Velocity damping factor */ - btAlignedObjectArray< float > m_perClothDampingFactor; - btDX11Buffer m_dx11PerClothDampingFactor; - - /** Velocity correction coefficient */ - btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient; - btDX11Buffer m_dx11PerClothVelocityCorrectionCoefficient; - - /** Lift parameter for wind effect on cloth. */ - btAlignedObjectArray< float > m_perClothLiftFactor; - btDX11Buffer m_dx11PerClothLiftFactor; - - /** Drag parameter for wind effect on cloth. */ - btAlignedObjectArray< float > m_perClothDragFactor; - btDX11Buffer m_dx11PerClothDragFactor; - - /** Density of the medium in which each cloth sits */ - btAlignedObjectArray< float > m_perClothMediumDensity; - btDX11Buffer m_dx11PerClothMediumDensity; - - - /** - * Collision shape details: pair of index of first collision shape for the cloth and number of collision objects. - */ - btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects; - btDX11Buffer m_dx11PerClothCollisionObjects; - - /** - * Collision shapes being passed across to the cloths in this solver. - */ - btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails; - btDX11Buffer< CollisionShapeDescription > m_dx11CollisionObjectDetails; - - /** - * Minimum bounds for each cloth. - * Updated by GPU and returned for use by broad phase. - * These are int vectors as a reminder that they store the int representation of a float, not a float. - * Bit 31 is inverted - is floats are stored with int-sortable values. - */ - btAlignedObjectArray< UIntVector3 > m_perClothMinBounds; - btDX11Buffer< UIntVector3 > m_dx11PerClothMinBounds; - - /** - * Maximum bounds for each cloth. - * Updated by GPU and returned for use by broad phase. - * These are int vectors as a reminder that they store the int representation of a float, not a float. - * Bit 31 is inverted - is floats are stored with int-sortable values. - */ - btAlignedObjectArray< UIntVector3 > m_perClothMaxBounds; - btDX11Buffer< UIntVector3 > m_dx11PerClothMaxBounds; - - - /** - * Friction coefficient for each cloth - */ - btAlignedObjectArray< float > m_perClothFriction; - btDX11Buffer< float > m_dx11PerClothFriction; - - DXFunctions::KernelDesc prepareLinksKernel; - DXFunctions::KernelDesc solvePositionsFromLinksKernel; - DXFunctions::KernelDesc vSolveLinksKernel; - DXFunctions::KernelDesc integrateKernel; - DXFunctions::KernelDesc addVelocityKernel; - DXFunctions::KernelDesc updatePositionsFromVelocitiesKernel; - DXFunctions::KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel; - DXFunctions::KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel; - DXFunctions::KernelDesc solveCollisionsAndUpdateVelocitiesKernel; - DXFunctions::KernelDesc resetNormalsAndAreasKernel; - DXFunctions::KernelDesc normalizeNormalsAndAreasKernel; - DXFunctions::KernelDesc computeBoundsKernel; - DXFunctions::KernelDesc updateSoftBodiesKernel; - - DXFunctions::KernelDesc applyForcesKernel; - - bool m_enableUpdateBounds; - - /** - * Integrate motion on the solver. - */ - virtual void integrate( float solverdt ); - float computeTriangleArea( - const Vectormath::Aos::Point3 &vertex0, - const Vectormath::Aos::Point3 &vertex1, - const Vectormath::Aos::Point3 &vertex2 ); - - - virtual bool buildShaders(); - - void resetNormalsAndAreas( int numVertices ); - - void normalizeNormalsAndAreas( int numVertices ); - - void executeUpdateSoftBodies( int firstTriangle, int numTriangles ); - - void prepareCollisionConstraints(); - - Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ); - - void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ); - - virtual void applyForces( float solverdt ); - - virtual void updateConstants( float timeStep ); - int findSoftBodyIndex( const btSoftBody* const softBody ); - - ////////////////////////////////////// - // Kernel dispatches - virtual void prepareLinks(); - - void updatePositionsFromVelocities( float solverdt ); - void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); - void solveLinksForVelocity( int startLink, int numLinks, float kst ); - - void updateVelocitiesFromPositionsWithVelocities( float isolverdt ); - void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ); - void computeBounds( ); - void solveCollisionsAndUpdateVelocities( float isolverdt ); - - // End kernel dispatches - ///////////////////////////////////// - - void updateBounds(); - - - void releaseKernels(); - -public: - btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory); - - virtual ~btDX11SoftBodySolver(); - - - virtual SolverTypes getSolverType() const - { - return DX_SOLVER; - } - - void setEnableUpdateBounds(bool enableBounds) - { - m_enableUpdateBounds = enableBounds; - } - bool getEnableUpdateBounds() const - { - return m_enableUpdateBounds; - } - - - - virtual btSoftBodyLinkData &getLinkData(); - - virtual btSoftBodyVertexData &getVertexData(); - - virtual btSoftBodyTriangleData &getTriangleData(); - - - - - - btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody ); - const btAcceleratedSoftBodyInterface * const findSoftBodyInterface( const btSoftBody* const softBody ) const; - - virtual bool checkInitialized(); - - virtual void updateSoftBodies( ); - - virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); - - virtual void copyBackToSoftBodies(bool bMove = true); - - virtual void solveConstraints( float solverdt ); - - virtual void predictMotion( float solverdt ); - - - virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* ); - - virtual void processCollision( btSoftBody*, btSoftBody* ); - -}; - - - -/** - * Class to manage movement of data from a solver to a given target. - * This version is the DX to CPU version. - */ -class btSoftBodySolverOutputDXtoCPU : public btSoftBodySolverOutput -{ -protected: - -public: - btSoftBodySolverOutputDXtoCPU() - { - } - - /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ - virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); -}; - -/** - * Class to manage movement of data from a solver to a given target. - * This version is the DX to DX version and subclasses DX to CPU so that it works for that too. - */ -class btSoftBodySolverOutputDXtoDX : public btSoftBodySolverOutputDXtoCPU -{ -protected: - struct OutputToVertexArrayCB - { - int startNode; - int numNodes; - int positionOffset; - int positionStride; - - int normalOffset; - int normalStride; - int padding1; - int padding2; - }; - - DXFunctions dxFunctions; - DXFunctions::KernelDesc outputToVertexArrayWithNormalsKernel; - DXFunctions::KernelDesc outputToVertexArrayWithoutNormalsKernel; - - - bool m_shadersInitialized; - - bool checkInitialized(); - bool buildShaders(); - void releaseKernels(); - -public: - btSoftBodySolverOutputDXtoDX(ID3D11Device *dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory) : - dxFunctions( dx11Device, dx11Context, dx11CompileFromMemory ) - { - m_shadersInitialized = false; - } - - ~btSoftBodySolverOutputDXtoDX() - { - releaseKernels(); - } - - /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ - virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); -}; - -#endif // #ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp deleted file mode 100644 index 5c73ee5d..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.cpp +++ /dev/null @@ -1,1051 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include - - -#define WAVEFRONT_SIZE 32 -#define WAVEFRONT_BLOCK_MULTIPLIER 2 -#define GROUP_SIZE (WAVEFRONT_SIZE*WAVEFRONT_BLOCK_MULTIPLIER) -#define LINKS_PER_SIMD_LANE 16 - -#define STRINGIFY( S ) STRINGIFY2( S ) -#define STRINGIFY2( S ) #S - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "vectormath/vmInclude.h" - -#include "btSoftBodySolverLinkData_DX11SIMDAware.h" -#include "btSoftBodySolver_DX11SIMDAware.h" -#include "btSoftBodySolverVertexBuffer_DX11.h" -#include "BulletSoftBody/btSoftBody.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" - -#define MSTRINGIFY(A) #A -static char* UpdatePositionsFromVelocitiesHLSLString = -#include "HLSL/UpdatePositionsFromVelocities.hlsl" -static char* SolvePositionsSIMDBatchedHLSLString = -#include "HLSL/SolvePositionsSIMDBatched.hlsl" -static char* UpdateNodesHLSLString = -#include "HLSL/UpdateNodes.hlsl" -static char* UpdatePositionsHLSLString = -#include "HLSL/UpdatePositions.hlsl" -static char* UpdateConstantsHLSLString = -#include "HLSL/UpdateConstants.hlsl" -static char* IntegrateHLSLString = -#include "HLSL/Integrate.hlsl" -static char* ApplyForcesHLSLString = -#include "HLSL/ApplyForces.hlsl" -static char* UpdateNormalsHLSLString = -#include "HLSL/UpdateNormals.hlsl" -static char* OutputToVertexArrayHLSLString = -#include "HLSL/OutputToVertexArray.hlsl" -static char* VSolveLinksHLSLString = -#include "HLSL/VSolveLinks.hlsl" -static char* ComputeBoundsHLSLString = -#include "HLSL/ComputeBounds.hlsl" -static char* SolveCollisionsAndUpdateVelocitiesHLSLString = -#include "HLSL/solveCollisionsAndUpdateVelocitiesSIMDBatched.hlsl" - - - -btSoftBodyLinkDataDX11SIMDAware::btSoftBodyLinkDataDX11SIMDAware( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : - m_d3dDevice( d3dDevice ), - m_d3dDeviceContext( d3dDeviceContext ), - m_wavefrontSize( WAVEFRONT_SIZE ), - m_linksPerWorkItem( LINKS_PER_SIMD_LANE ), - m_maxBatchesWithinWave( 0 ), - m_maxLinksPerWavefront( m_wavefrontSize * m_linksPerWorkItem ), - m_numWavefronts( 0 ), - m_maxVertex( 0 ), - m_dx11NumBatchesAndVerticesWithinWaves( d3dDevice, d3dDeviceContext, &m_numBatchesAndVerticesWithinWaves, true ), - m_dx11WavefrontVerticesGlobalAddresses( d3dDevice, d3dDeviceContext, &m_wavefrontVerticesGlobalAddresses, true ), - m_dx11LinkVerticesLocalAddresses( d3dDevice, d3dDeviceContext, &m_linkVerticesLocalAddresses, true ), - m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, true ), - m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, true ), - m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, true ), - m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, true ), - m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, true ) -{ - m_d3dDevice = d3dDevice; - m_d3dDeviceContext = d3dDeviceContext; -} - -btSoftBodyLinkDataDX11SIMDAware::~btSoftBodyLinkDataDX11SIMDAware() -{ -} - -static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) -{ - Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); - return outVec; -} - -void btSoftBodyLinkDataDX11SIMDAware::createLinks( int numLinks ) -{ - int previousSize = m_links.size(); - int newSize = previousSize + numLinks; - - btSoftBodyLinkData::createLinks( numLinks ); - - // Resize the link addresses array as well - m_linkAddresses.resize( newSize ); -} - -void btSoftBodyLinkDataDX11SIMDAware::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex ) -{ - btSoftBodyLinkData::setLinkAt( link, linkIndex ); - - if( link.getVertex0() > m_maxVertex ) - m_maxVertex = link.getVertex0(); - if( link.getVertex1() > m_maxVertex ) - m_maxVertex = link.getVertex1(); - - // Set the link index correctly for initialisation - m_linkAddresses[linkIndex] = linkIndex; -} - -bool btSoftBodyLinkDataDX11SIMDAware::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyLinkDataDX11SIMDAware::moveToAccelerator() -{ - bool success = true; - - success = success && m_dx11NumBatchesAndVerticesWithinWaves.moveToGPU(); - success = success && m_dx11WavefrontVerticesGlobalAddresses.moveToGPU(); - success = success && m_dx11LinkVerticesLocalAddresses.moveToGPU(); - success = success && m_dx11LinkStrength.moveToGPU(); - success = success && m_dx11LinksMassLSC.moveToGPU(); - success = success && m_dx11LinksRestLengthSquared.moveToGPU(); - success = success && m_dx11LinksRestLength.moveToGPU(); - success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -bool btSoftBodyLinkDataDX11SIMDAware::moveFromAccelerator() -{ - bool success = true; - success = success && m_dx11NumBatchesAndVerticesWithinWaves.moveFromGPU(); - success = success && m_dx11WavefrontVerticesGlobalAddresses.moveFromGPU(); - success = success && m_dx11LinkVerticesLocalAddresses.moveFromGPU(); - success = success && m_dx11LinkStrength.moveFromGPU(); - success = success && m_dx11LinksMassLSC.moveFromGPU(); - success = success && m_dx11LinksRestLengthSquared.moveFromGPU(); - success = success && m_dx11LinksRestLength.moveFromGPU(); - success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU(); - - if( success ) - m_onGPU = false; - - return success; -} - - - - - - - - - - - - - - - -btDX11SIMDAwareSoftBodySolver::btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) : - btDX11SoftBodySolver( dx11Device, dx11Context, dx11CompileFromMemory ), - m_linkData(m_dx11Device, m_dx11Context) -{ - // Initial we will clearly need to update solver constants - // For now this is global for the cloths linked with this solver - we should probably make this body specific - // for performance in future once we understand more clearly when constants need to be updated - m_updateSolverConstants = true; - - m_shadersInitialized = false; -} - -btDX11SIMDAwareSoftBodySolver::~btDX11SIMDAwareSoftBodySolver() -{ - releaseKernels(); -} - - -btSoftBodyLinkData &btDX11SIMDAwareSoftBodySolver::getLinkData() -{ - // TODO: Consider setting link data to "changed" here - return m_linkData; -} - - - -void btDX11SIMDAwareSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate) -{ - if(forceUpdate || m_softBodySet.size() != softBodies.size() ) - { - // Have a change in the soft body set so update, reloading all the data - getVertexData().clear(); - getTriangleData().clear(); - getLinkData().clear(); - m_softBodySet.resize(0); - - - for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) - { - btSoftBody *softBody = softBodies[ softBodyIndex ]; - using Vectormath::Aos::Matrix3; - using Vectormath::Aos::Point3; - - // Create SoftBody that will store the information within the solver - btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody ); - m_softBodySet.push_back( newSoftBody ); - - m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); - m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); - m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); - m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); - m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); - m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); - // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time - m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) ); - m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) ); - m_perClothFriction.push_back( softBody->getFriction() ); - m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); - - // Add space for new vertices and triangles in the default solver for now - // TODO: Include space here for tearing too later - int firstVertex = getVertexData().getNumVertices(); - int numVertices = softBody->m_nodes.size(); - // Round maxVertices to a multiple of the workgroup size so we know we're safe to run over in a given group - // maxVertices can be increased to allow tearing, but should be used sparingly because these extra verts will always be processed - int maxVertices = GROUP_SIZE*((numVertices+GROUP_SIZE)/GROUP_SIZE); - // Allocate space for new vertices in all the vertex arrays - getVertexData().createVertices( numVertices, softBodyIndex, maxVertices ); - - int firstTriangle = getTriangleData().getNumTriangles(); - int numTriangles = softBody->m_faces.size(); - int maxTriangles = numTriangles; - getTriangleData().createTriangles( maxTriangles ); - - // Copy vertices from softbody into the solver - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); - btSoftBodyVertexData::VertexDescription desc; - - // TODO: Position in the softbody might be pre-transformed - // or we may need to adapt for the pose. - //desc.setPosition( cloth.getMeshTransform()*multPoint ); - desc.setPosition( multPoint ); - - float vertexInverseMass = softBody->m_nodes[vertex].m_im; - desc.setInverseMass(vertexInverseMass); - getVertexData().setVertexAt( desc, firstVertex + vertex ); - } - - // Copy triangles similarly - // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene - for( int triangle = 0; triangle < numTriangles; ++triangle ) - { - // Note that large array storage is relative to the array not to the cloth - // So we need to add firstVertex to each value - int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); - int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); - int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); - btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); - getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); - - // Increase vertex triangle counts for this triangle - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; - } - - int firstLink = getLinkData().getNumLinks(); - int numLinks = softBody->m_links.size(); - int maxLinks = numLinks; - - // Allocate space for the links - getLinkData().createLinks( numLinks ); - - // Add the links - for( int link = 0; link < numLinks; ++link ) - { - int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); - int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); - - btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); - newLink.setLinkStrength(1.f); - getLinkData().setLinkAt(newLink, firstLink + link); - } - - newSoftBody->setFirstVertex( firstVertex ); - newSoftBody->setFirstTriangle( firstTriangle ); - newSoftBody->setNumVertices( numVertices ); - newSoftBody->setMaxVertices( maxVertices ); - newSoftBody->setNumTriangles( numTriangles ); - newSoftBody->setMaxTriangles( maxTriangles ); - newSoftBody->setFirstLink( firstLink ); - newSoftBody->setNumLinks( numLinks ); - } - - - - updateConstants(0.f); - - - m_linkData.generateBatches(); - m_triangleData.generateBatches(); - - - // Build the shaders to match the batching parameters - buildShaders(); - } - -} - - - -void btDX11SIMDAwareSoftBodySolver::solveConstraints( float solverdt ) -{ - - //std::cerr << "'GPU' solve constraints\n"; - using Vectormath::Aos::Vector3; - using Vectormath::Aos::Point3; - using Vectormath::Aos::lengthSqr; - using Vectormath::Aos::dot; - - // Prepare links - int numLinks = m_linkData.getNumLinks(); - int numVertices = m_vertexData.getNumVertices(); - - float kst = 1.f; - float ti = 0.f; - - - m_dx11PerClothDampingFactor.moveToGPU(); - m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU(); - - - - // Ensure data is on accelerator - m_linkData.moveToAccelerator(); - m_vertexData.moveToAccelerator(); - - - - prepareCollisionConstraints(); - - - // Solve drift - for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - { - - for( int i = 0; i < m_linkData.m_wavefrontBatchStartLengths.size(); ++i ) - { - int startWave = m_linkData.m_wavefrontBatchStartLengths[i].start; - int numWaves = m_linkData.m_wavefrontBatchStartLengths[i].length; - - solveLinksForPosition( startWave, numWaves, kst, ti ); - } - - } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - - - - - // At this point assume that the force array is blank - we will overwrite it - solveCollisionsAndUpdateVelocities( 1.f/solverdt ); - -} // btDX11SIMDAwareSoftBodySolver::solveConstraints - - -void btDX11SIMDAwareSoftBodySolver::updateConstants( float timeStep ) -{ - using namespace Vectormath::Aos; - - if( m_updateSolverConstants ) - { - m_updateSolverConstants = false; - - // Will have to redo this if we change the structure (tear, maybe) or various other possible changes - - // Initialise link constants - const int numLinks = m_linkData.getNumLinks(); - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); - m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); - float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); - float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); - float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); - float massLSC = (invMass0 + invMass1)/linearStiffness; - m_linkData.getMassLSC(linkIndex) = massLSC; - float restLength = m_linkData.getRestLength(linkIndex); - float restLengthSquared = restLength*restLength; - m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; - } - } -} // btDX11SIMDAwareSoftBodySolver::updateConstants - -////////////////////////////////////// -// Kernel dispatches - - -void btDX11SIMDAwareSoftBodySolver::solveLinksForPosition( int startWave, int numWaves, float kst, float ti ) -{ - - - m_vertexData.moveToAccelerator(); - m_linkData.moveToAccelerator(); - - // Copy kernel parameters to GPU - SolvePositionsFromLinksKernelCB constBuffer; - - // Set the first wave of the batch and the number of waves - constBuffer.startWave = startWave; - constBuffer.numWaves = numWaves; - - constBuffer.kst = kst; - constBuffer.ti = ti; - - D3D11_MAPPED_SUBRESOURCE MappedResource = {0}; - m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); - memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) ); - m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 ); - m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer ); - - // Set resources and dispatch - m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11NumBatchesAndVerticesWithinWaves.getSRV()) ); - m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11WavefrontVerticesGlobalAddresses.getSRV()) ); - m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) ); - m_dx11Context->CSSetShaderResources( 3, 1, &(m_linkData.m_dx11LinkVerticesLocalAddresses.getSRV()) ); - m_dx11Context->CSSetShaderResources( 4, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) ); - m_dx11Context->CSSetShaderResources( 5, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) ); - - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL ); - - // Execute the kernel - m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 ); - - int numBlocks = ((constBuffer.numWaves + WAVEFRONT_BLOCK_MULTIPLIER - 1) / WAVEFRONT_BLOCK_MULTIPLIER ); - m_dx11Context->Dispatch(numBlocks , 1, 1 ); - - { - // Tidy up - ID3D11ShaderResourceView* pViewNULL = NULL; - m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL ); - m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL ); - - ID3D11UnorderedAccessView* pUAViewNULL = NULL; - m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL ); - - ID3D11Buffer *pBufferNull = NULL; - m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull ); - } -} // btDX11SIMDAwareSoftBodySolver::solveLinksForPosition - - - -// End kernel dispatches -///////////////////////////////////// - - - - - - - - - -bool btDX11SIMDAwareSoftBodySolver::buildShaders() -{ - // Ensure current kernels are released first - releaseKernels(); - - bool returnVal = true; - - - if( m_shadersInitialized ) - return true; - - - updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) ); - if( !updatePositionsFromVelocitiesKernel.constBuffer ) - returnVal = false; - - char maxVerticesPerWavefront[20]; - char maxBatchesPerWavefront[20]; - char waveFrontSize[20]; - char waveFrontBlockMultiplier[20]; - char blockSize[20]; - - sprintf(maxVerticesPerWavefront, "%d", m_linkData.getMaxVerticesPerWavefront()); - sprintf(maxBatchesPerWavefront, "%d", m_linkData.getMaxBatchesPerWavefront()); - sprintf(waveFrontSize, "%d", m_linkData.getWavefrontSize()); - sprintf(waveFrontBlockMultiplier, "%d", WAVEFRONT_BLOCK_MULTIPLIER); - sprintf(blockSize, "%d", WAVEFRONT_BLOCK_MULTIPLIER*m_linkData.getWavefrontSize()); - - D3D10_SHADER_MACRO solvePositionsMacros[6] = { "MAX_NUM_VERTICES_PER_WAVE", maxVerticesPerWavefront, "MAX_BATCHES_PER_WAVE", maxBatchesPerWavefront, "WAVEFRONT_SIZE", waveFrontSize, "WAVEFRONT_BLOCK_MULTIPLIER", waveFrontBlockMultiplier, "BLOCK_SIZE", blockSize, 0, 0 }; - - solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsSIMDBatchedHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB), solvePositionsMacros ); - if( !solvePositionsFromLinksKernel.constBuffer ) - returnVal = false; - - updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) ); - if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer ) - returnVal = false; - updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB)); - if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer ) - returnVal = false; - integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) ); - if( !integrateKernel.constBuffer ) - returnVal = false; - applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) ); - if( !applyForcesKernel.constBuffer ) - returnVal = false; - solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) ); - if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer ) - returnVal = false; - resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); - if( !resetNormalsAndAreasKernel.constBuffer ) - returnVal = false; - normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) ); - if( !normalizeNormalsAndAreasKernel.constBuffer ) - returnVal = false; - updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) ); - if( !updateSoftBodiesKernel.constBuffer ) - returnVal = false; - - computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) ); - if( !computeBoundsKernel.constBuffer ) - returnVal = false; - - if( returnVal ) - m_shadersInitialized = true; - - return returnVal; -} // btDX11SIMDAwareSoftBodySolver::buildShaders - -static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) -{ - Vectormath::Aos::Transform3 outTransform; - outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); - outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); - outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); - outTransform.setCol(3, toVector3(transform.getOrigin())); - return outTransform; -} - - - - - - - - - - - - -static void generateBatchesOfWavefronts( btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, btSoftBodyLinkData &linkData, int numVertices, btAlignedObjectArray < btAlignedObjectArray > &wavefrontBatches ) -{ - // A per-batch map of truth values stating whether a given vertex is in that batch - // This allows us to significantly optimize the batching - btAlignedObjectArray > mapOfVerticesInBatches; - - for( int waveIndex = 0; waveIndex < linksForWavefronts.size(); ++waveIndex ) - { - btAlignedObjectArray &wavefront( linksForWavefronts[waveIndex] ); - - int batch = 0; - bool placed = false; - while( batch < wavefrontBatches.size() && !placed ) - { - // Test the current batch, see if this wave shares any vertex with the waves in the batch - bool foundSharedVertex = false; - for( int link = 0; link < wavefront.size(); ++link ) - { - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); - if( (mapOfVerticesInBatches[batch])[vertices.vertex0] || (mapOfVerticesInBatches[batch])[vertices.vertex1] ) - { - foundSharedVertex = true; - } - } - - if( !foundSharedVertex ) - { - wavefrontBatches[batch].push_back( waveIndex ); - // Insert vertices into this batch too - for( int link = 0; link < wavefront.size(); ++link ) - { - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); - (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; - (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; - } - placed = true; - } - batch++; - } - if( batch == wavefrontBatches.size() && !placed ) - { - wavefrontBatches.resize( batch + 1 ); - wavefrontBatches[batch].push_back( waveIndex ); - - // And resize map as well - mapOfVerticesInBatches.resize( batch + 1 ); - - // Resize maps with total number of vertices - mapOfVerticesInBatches[batch].resize( numVertices+1, false ); - - // Insert vertices into this batch too - for( int link = 0; link < wavefront.size(); ++link ) - { - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); - (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; - (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; - } - } - } - mapOfVerticesInBatches.clear(); -} - -// Function to remove an object from a vector maintaining correct ordering of the vector -template< typename T > static void removeFromVector( btAlignedObjectArray< T > &vectorToUpdate, int indexToRemove ) -{ - int currentSize = vectorToUpdate.size(); - for( int i = indexToRemove; i < (currentSize-1); ++i ) - { - vectorToUpdate[i] = vectorToUpdate[i+1]; - } - if( currentSize > 0 ) - vectorToUpdate.resize( currentSize - 1 ); -} - -/** - * Insert element into vectorToUpdate at index index. - */ -template< typename T > static void insertAtIndex( btAlignedObjectArray< T > &vectorToUpdate, int index, T element ) -{ - vectorToUpdate.resize( vectorToUpdate.size() + 1 ); - for( int i = (vectorToUpdate.size() - 1); i > index; --i ) - { - vectorToUpdate[i] = vectorToUpdate[i-1]; - } - vectorToUpdate[index] = element; -} - -/** - * Insert into btAlignedObjectArray assuming the array is ordered and maintaining both ordering and uniqueness. - * ie it treats vectorToUpdate as an ordered set. - */ -template< typename T > static void insertUniqueAndOrderedIntoVector( btAlignedObjectArray &vectorToUpdate, T element ) -{ - int index = 0; - while( index < vectorToUpdate.size() && vectorToUpdate[index] < element ) - { - index++; - } - if( index == vectorToUpdate.size() || vectorToUpdate[index] != element ) - insertAtIndex( vectorToUpdate, index, element ); -} - -static void generateLinksPerVertex( int numVertices, btSoftBodyLinkData &linkData, btAlignedObjectArray< int > &listOfLinksPerVertex, btAlignedObjectArray &numLinksPerVertex, int &maxLinks ) -{ - for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); - numLinksPerVertex[nodes.vertex0]++; - numLinksPerVertex[nodes.vertex1]++; - } - int maxLinksPerVertex = 0; - for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) - { - maxLinksPerVertex = btMax(numLinksPerVertex[vertexIndex], maxLinksPerVertex); - } - maxLinks = maxLinksPerVertex; - - btAlignedObjectArray< int > linksFoundPerVertex; - linksFoundPerVertex.resize( numVertices, 0 ); - - listOfLinksPerVertex.resize( maxLinksPerVertex * numVertices ); - - for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); - { - // Do vertex 0 - int vertexIndex = nodes.vertex0; - int linkForVertex = linksFoundPerVertex[nodes.vertex0]; - int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; - - listOfLinksPerVertex[linkAddress] = linkIndex; - - linksFoundPerVertex[nodes.vertex0] = linkForVertex + 1; - } - { - // Do vertex 1 - int vertexIndex = nodes.vertex1; - int linkForVertex = linksFoundPerVertex[nodes.vertex1]; - int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; - - listOfLinksPerVertex[linkAddress] = linkIndex; - - linksFoundPerVertex[nodes.vertex1] = linkForVertex + 1; - } - } -} - -static void computeBatchingIntoWavefronts( - btSoftBodyLinkData &linkData, - int wavefrontSize, - int linksPerWorkItem, - int maxLinksPerWavefront, - btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, - btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > &batchesWithinWaves, /* wave, batch, links in batch */ - btAlignedObjectArray< btAlignedObjectArray< int > > &verticesForWavefronts /* wavefront, vertex */ - ) -{ - - - // Attempt generation of larger batches of links. - btAlignedObjectArray< bool > processedLink; - processedLink.resize( linkData.getNumLinks() ); - btAlignedObjectArray< int > listOfLinksPerVertex; - int maxLinksPerVertex = 0; - - // Count num vertices - int numVertices = 0; - for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); - numVertices = btMax( numVertices, nodes.vertex0 + 1 ); - numVertices = btMax( numVertices, nodes.vertex1 + 1 ); - } - - // Need list of links per vertex - // Compute valence of each vertex - btAlignedObjectArray numLinksPerVertex; - numLinksPerVertex.resize(0); - numLinksPerVertex.resize( numVertices, 0 ); - - generateLinksPerVertex( numVertices, linkData, listOfLinksPerVertex, numLinksPerVertex, maxLinksPerVertex ); - - - // At this point we know what links we have for each vertex so we can start batching - - // We want a vertex to start with, let's go with 0 - int currentVertex = 0; - int linksProcessed = 0; - - btAlignedObjectArray verticesToProcess; - - while( linksProcessed < linkData.getNumLinks() ) - { - // Next wavefront - int nextWavefront = linksForWavefronts.size(); - linksForWavefronts.resize( nextWavefront + 1 ); - btAlignedObjectArray &linksForWavefront(linksForWavefronts[nextWavefront]); - verticesForWavefronts.resize( nextWavefront + 1 ); - btAlignedObjectArray &vertexSet( verticesForWavefronts[nextWavefront] ); - - linksForWavefront.resize(0); - - // Loop to find enough links to fill the wavefront - // Stopping if we either run out of links, or fill it - while( linksProcessed < linkData.getNumLinks() && linksForWavefront.size() < maxLinksPerWavefront ) - { - // Go through the links for the current vertex - for( int link = 0; link < numLinksPerVertex[currentVertex] && linksForWavefront.size() < maxLinksPerWavefront; ++link ) - { - int linkAddress = currentVertex * maxLinksPerVertex + link; - int linkIndex = listOfLinksPerVertex[linkAddress]; - - // If we have not already processed this link, add it to the wavefront - // Claim it as another processed link - // Add the vertex at the far end to the list of vertices to process. - if( !processedLink[linkIndex] ) - { - linksForWavefront.push_back( linkIndex ); - linksProcessed++; - processedLink[linkIndex] = true; - int v0 = linkData.getVertexPair(linkIndex).vertex0; - int v1 = linkData.getVertexPair(linkIndex).vertex1; - if( v0 == currentVertex ) - verticesToProcess.push_back( v1 ); - else - verticesToProcess.push_back( v0 ); - } - } - if( verticesToProcess.size() > 0 ) - { - // Get the element on the front of the queue and remove it - currentVertex = verticesToProcess[0]; - removeFromVector( verticesToProcess, 0 ); - } else { - // If we've not yet processed all the links, find the first unprocessed one - // and select one of its vertices as the current vertex - if( linksProcessed < linkData.getNumLinks() ) - { - int searchLink = 0; - while( processedLink[searchLink] ) - searchLink++; - currentVertex = linkData.getVertexPair(searchLink).vertex0; - } - } - } - - // We have either finished or filled a wavefront - for( int link = 0; link < linksForWavefront.size(); ++link ) - { - int v0 = linkData.getVertexPair( linksForWavefront[link] ).vertex0; - int v1 = linkData.getVertexPair( linksForWavefront[link] ).vertex1; - insertUniqueAndOrderedIntoVector( vertexSet, v0 ); - insertUniqueAndOrderedIntoVector( vertexSet, v1 ); - } - // Iterate over links mapped to the wave and batch those - // We can run a batch on each cycle trivially - - batchesWithinWaves.resize( batchesWithinWaves.size() + 1 ); - btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWave( batchesWithinWaves[batchesWithinWaves.size()-1] ); - - - for( int link = 0; link < linksForWavefront.size(); ++link ) - { - int linkIndex = linksForWavefront[link]; - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( linkIndex ); - - int batch = 0; - bool placed = false; - while( batch < batchesWithinWave.size() && !placed ) - { - bool foundSharedVertex = false; - if( batchesWithinWave[batch].size() >= wavefrontSize ) - { - // If we have already filled this batch, move on to another - foundSharedVertex = true; - } else { - for( int link2 = 0; link2 < batchesWithinWave[batch].size(); ++link2 ) - { - btSoftBodyLinkData::LinkNodePair vertices2 = linkData.getVertexPair( (batchesWithinWave[batch])[link2] ); - - if( vertices.vertex0 == vertices2.vertex0 || - vertices.vertex1 == vertices2.vertex0 || - vertices.vertex0 == vertices2.vertex1 || - vertices.vertex1 == vertices2.vertex1 ) - { - foundSharedVertex = true; - break; - } - } - } - if( !foundSharedVertex ) - { - batchesWithinWave[batch].push_back( linkIndex ); - placed = true; - } else { - ++batch; - } - } - if( batch == batchesWithinWave.size() && !placed ) - { - batchesWithinWave.resize( batch + 1 ); - batchesWithinWave[batch].push_back( linkIndex ); - } - } - - } - -} - -void btSoftBodyLinkDataDX11SIMDAware::generateBatches() -{ - btAlignedObjectArray < btAlignedObjectArray > linksForWavefronts; - btAlignedObjectArray < btAlignedObjectArray > wavefrontBatches; - btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > batchesWithinWaves; - btAlignedObjectArray< btAlignedObjectArray< int > > verticesForWavefronts; // wavefronts, vertices in wavefront as an ordered set - - // Group the links into wavefronts - computeBatchingIntoWavefronts( *this, m_wavefrontSize, m_linksPerWorkItem, m_maxLinksPerWavefront, linksForWavefronts, batchesWithinWaves, verticesForWavefronts ); - - - // Batch the wavefronts - generateBatchesOfWavefronts( linksForWavefronts, *this, m_maxVertex, wavefrontBatches ); - - m_numWavefronts = linksForWavefronts.size(); - - // At this point we have a description of which links we need to process in each wavefront - - // First correctly fill the batch ranges vector - int numBatches = wavefrontBatches.size(); - m_wavefrontBatchStartLengths.resize(0); - int prefixSum = 0; - for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) - { - int wavesInBatch = wavefrontBatches[batchIndex].size(); - int nextPrefixSum = prefixSum + wavesInBatch; - m_wavefrontBatchStartLengths.push_back( BatchPair( prefixSum, nextPrefixSum - prefixSum ) ); - - prefixSum += wavesInBatch; - } - - // Also find max number of batches within a wave - m_maxBatchesWithinWave = 0; - m_maxVerticesWithinWave = 0; - m_numBatchesAndVerticesWithinWaves.resize( m_numWavefronts ); - for( int waveIndex = 0; waveIndex < m_numWavefronts; ++waveIndex ) - { - // See if the number of batches in this wave is greater than the current maxium - int batchesInCurrentWave = batchesWithinWaves[waveIndex].size(); - int verticesInCurrentWave = verticesForWavefronts[waveIndex].size(); - m_maxBatchesWithinWave = btMax( batchesInCurrentWave, m_maxBatchesWithinWave ); - m_maxVerticesWithinWave = btMax( verticesInCurrentWave, m_maxVerticesWithinWave ); - } - - // Add padding values both for alignment and as dudd addresses within LDS to compute junk rather than branch around - m_maxVerticesWithinWave = 16*((m_maxVerticesWithinWave/16)+2); - - // Now we know the maximum number of vertices per-wave we can resize the global vertices array - m_wavefrontVerticesGlobalAddresses.resize( m_maxVerticesWithinWave * m_numWavefronts ); - - // Grab backup copies of all the link data arrays for the sorting process - btAlignedObjectArray m_links_Backup(m_links); - btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); - btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); - btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); - //btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); - //btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); - btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); - btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); - - // Resize to a wavefront sized batch per batch per wave so we get perfectly coherent memory accesses. - m_links.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linkVerticesLocalAddresses.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linkStrength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksMassLSC.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksRestLengthSquared.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksRestLength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksMaterialLinearStiffnessCoefficient.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - - // Then re-order links into wavefront blocks - - // Total number of wavefronts moved. This will decide the ordering of sorted wavefronts. - int wavefrontCount = 0; - - // Iterate over batches of wavefronts, then wavefronts in the batch - for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) - { - btAlignedObjectArray &batch( wavefrontBatches[batchIndex] ); - int wavefrontsInBatch = batch.size(); - - - for( int wavefrontIndex = 0; wavefrontIndex < wavefrontsInBatch; ++wavefrontIndex ) - { - - int originalWavefrontIndex = batch[wavefrontIndex]; - btAlignedObjectArray< int > &wavefrontVertices( verticesForWavefronts[originalWavefrontIndex] ); - int verticesUsedByWavefront = wavefrontVertices.size(); - - // Copy the set of vertices into the correctly structured array for use on the device - // Fill the non-vertices with -1s - // so we can mask out those reads - for( int vertex = 0; vertex < verticesUsedByWavefront; ++vertex ) - { - m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = wavefrontVertices[vertex]; - } - for( int vertex = verticesUsedByWavefront; vertex < m_maxVerticesWithinWave; ++vertex ) - { - m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = -1; - } - - // Obtain the set of batches within the current wavefront - btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWavefront( batchesWithinWaves[originalWavefrontIndex] ); - // Set the size of the batches for use in the solver, correctly ordered - NumBatchesVerticesPair batchesAndVertices; - batchesAndVertices.numBatches = batchesWithinWavefront.size(); - batchesAndVertices.numVertices = verticesUsedByWavefront; - m_numBatchesAndVerticesWithinWaves[wavefrontCount] = batchesAndVertices; - - - // Now iterate over batches within the wavefront to structure the links correctly - for( int wavefrontBatch = 0; wavefrontBatch < batchesWithinWavefront.size(); ++wavefrontBatch ) - { - btAlignedObjectArray &linksInBatch( batchesWithinWavefront[wavefrontBatch] ); - int wavefrontBatchSize = linksInBatch.size(); - - int batchAddressInTarget = m_maxBatchesWithinWave * m_wavefrontSize * wavefrontCount + m_wavefrontSize * wavefrontBatch; - - for( int linkIndex = 0; linkIndex < wavefrontBatchSize; ++linkIndex ) - { - int originalLinkAddress = linksInBatch[linkIndex]; - // Reorder simple arrays trivially - m_links[batchAddressInTarget + linkIndex] = m_links_Backup[originalLinkAddress]; - m_linkStrength[batchAddressInTarget + linkIndex] = m_linkStrength_Backup[originalLinkAddress]; - m_linksMassLSC[batchAddressInTarget + linkIndex] = m_linksMassLSC_Backup[originalLinkAddress]; - m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = m_linksRestLengthSquared_Backup[originalLinkAddress]; - m_linksRestLength[batchAddressInTarget + linkIndex] = m_linksRestLength_Backup[originalLinkAddress]; - m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = m_linksMaterialLinearStiffnessCoefficient_Backup[originalLinkAddress]; - - // The local address is more complicated. We need to work out where a given vertex will end up - // by searching the set of vertices for this link and using the index as the local address - btSoftBodyLinkData::LinkNodePair localPair; - btSoftBodyLinkData::LinkNodePair globalPair = m_links[batchAddressInTarget + linkIndex]; - localPair.vertex0 = wavefrontVertices.findLinearSearch( globalPair.vertex0 ); - localPair.vertex1 = wavefrontVertices.findLinearSearch( globalPair.vertex1 ); - m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; - } - for( int linkIndex = wavefrontBatchSize; linkIndex < m_wavefrontSize; ++linkIndex ) - { - // Put 0s into these arrays for padding for cleanliness - m_links[batchAddressInTarget + linkIndex] = btSoftBodyLinkData::LinkNodePair(0, 0); - m_linkStrength[batchAddressInTarget + linkIndex] = 0.f; - m_linksMassLSC[batchAddressInTarget + linkIndex] = 0.f; - m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = 0.f; - m_linksRestLength[batchAddressInTarget + linkIndex] = 0.f; - m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = 0.f; - - - // For local addresses of junk data choose a set of addresses just above the range of valid ones - // and cycling tyhrough % 16 so that we don't have bank conficts between all dud addresses - // The valid addresses will do scatter and gather in the valid range, the junk ones should happily work - // off the end of that range so we need no control - btSoftBodyLinkData::LinkNodePair localPair; - localPair.vertex0 = verticesUsedByWavefront + (linkIndex % 16); - localPair.vertex1 = verticesUsedByWavefront + (linkIndex % 16); - m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; - } - - } - - - wavefrontCount++; - } - - - } - -} // void btSoftBodyLinkDataDX11SIMDAware::generateBatches() diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h deleted file mode 100644 index 34881973..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/btSoftBodySolver_DX11SIMDAware.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "vectormath/vmInclude.h" -#include "btSoftBodySolver_DX11.h" -#include "btSoftBodySolverVertexBuffer_DX11.h" -#include "btSoftBodySolverLinkData_DX11SIMDAware.h" -#include "btSoftBodySolverVertexData_DX11.h" -#include "btSoftBodySolverTriangleData_DX11.h" - - -#ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H -#define BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H - -class btDX11SIMDAwareSoftBodySolver : public btDX11SoftBodySolver -{ -protected: - struct SolvePositionsFromLinksKernelCB - { - int startWave; - int numWaves; - float kst; - float ti; - }; - - - /** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */ - btSoftBodyLinkDataDX11SIMDAware m_linkData; - - /** Variable to define whether we need to update solver constants on the next iteration */ - bool m_updateSolverConstants; - - - virtual bool buildShaders(); - - void updateConstants( float timeStep ); - - - ////////////////////////////////////// - // Kernel dispatches - - - void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); - - // End kernel dispatches - ///////////////////////////////////// - - - -public: - btDX11SIMDAwareSoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory = &D3DX11CompileFromMemory); - - virtual ~btDX11SIMDAwareSoftBodySolver(); - - virtual btSoftBodyLinkData &getLinkData(); - - virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); - - virtual void solveConstraints( float solverdt ); - - virtual SolverTypes getSolverType() const - { - return DX_SIMD_SOLVER; - } - -}; - -#endif // #ifndef BT_SOFT_BODY_DX11_SOLVER_SIMDAWARE_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua deleted file mode 100644 index 4625306d..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/premake4.lua +++ /dev/null @@ -1,23 +0,0 @@ - -hasDX11 = findDirectX11() - -if (hasDX11) then - - project "BulletSoftBodyDX11Solvers" - - initDirectX11() - - kind "StaticLib" - - targetdir "../../../../lib" - - includedirs { - ".", - "../../.." - } - files { - "**.cpp", - "**.h" - } - -end diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt deleted file mode 100644 index 1fc07328..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ - -INCLUDE_DIRECTORIES( - ${BULLET_PHYSICS_SOURCE_DIR}/src - ${AMD_OPENCL_INCLUDES} -) - -ADD_DEFINITIONS(-DUSE_AMD_OPENCL) -ADD_DEFINITIONS(-DCL_PLATFORM_AMD) - - - -SET(BulletSoftBodyOpenCLSolvers_SRCS - ../btSoftBodySolver_OpenCL.cpp - ../btSoftBodySolver_OpenCLSIMDAware.cpp - ../btSoftBodySolverOutputCLtoGL.cpp -) - -SET(BulletSoftBodyOpenCLSolvers_HDRS - ../btSoftBodySolver_OpenCL.h - ../btSoftBodySolver_OpenCLSIMDAware.h - ../../Shared/btSoftBodySolverData.h - ../btSoftBodySolverVertexData_OpenCL.h - ../btSoftBodySolverTriangleData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCLSIMDAware.h - ../btSoftBodySolverBuffer_OpenCL.h - ../btSoftBodySolverVertexBuffer_OpenGL.h - ../btSoftBodySolverOutputCLtoGL.h -) - - - - -ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_AMD - ${BulletSoftBodyOpenCLSolvers_SRCS} - ${BulletSoftBodyOpenCLSolvers_HDRS} -) - -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_AMD BulletSoftBody) -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_AMD - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -#headers are already installed by BulletMultiThreaded library - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_AMD PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua deleted file mode 100644 index 8c663a8c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/AMD/premake4.lua +++ /dev/null @@ -1,27 +0,0 @@ - -hasCL = findOpenCL_AMD() - -if (hasCL) then - - project "BulletSoftBodySolvers_OpenCL_AMD" - - defines { "USE_AMD_OPENCL","CL_PLATFORM_AMD"} - - initOpenCL_AMD() - - kind "StaticLib" - - targetdir "../../../../../lib" - - includedirs { - ".", - "../../../..", - "../../../../../Glut" - } - files { - "../btSoftBodySolver_OpenCL.cpp", - "../btSoftBodySolver_OpenCLSIMDAware.cpp", - "../btSoftBodySolverOutputCLtoGL.cpp" - } - -end diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt deleted file mode 100644 index 6e593a99..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Apple/CMakeLists.txt +++ /dev/null @@ -1,80 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src -) - - - - -SET(BulletSoftBodyOpenCLSolvers_SRCS - ../btSoftBodySolver_OpenCL.cpp - ../btSoftBodySolver_OpenCLSIMDAware.cpp -) - -SET(BulletSoftBodyOpenCLSolvers_HDRS - ../btSoftBodySolver_OpenCL.h - ../../Shared/btSoftBodySolverData.h - ../btSoftBodySolverVertexData_OpenCL.h - ../btSoftBodySolverTriangleData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCL.h - ../btSoftBodySolverBuffer_OpenCL.h -) - -# OpenCL and HLSL Shaders. -# Build rules generated to stringify these into headers -# which are needed by some of the sources -SET(BulletSoftBodyOpenCLSolvers_Shaders -# OutputToVertexArray - UpdateNormals - Integrate - UpdatePositions - UpdateNodes - SolvePositions - UpdatePositionsFromVelocities - ApplyForces - PrepareLinks - VSolveLinks -) - -foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) - LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") -endforeach(f) - - - -ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Apple - ${BulletSoftBodyOpenCLSolvers_SRCS} - ${BulletSoftBodyOpenCLSolvers_HDRS} - ${BulletSoftBodyOpenCLSolvers_OpenCLC} -) - -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - IF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) ) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES LINK_FLAGS "-framework OpenCL") - ENDIF (APPLE AND (BUILD_SHARED_LIBS OR FRAMEWORK) ) - TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Apple BulletSoftBody) -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Apple - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -#headers are already installed by BulletMultiThreaded library - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Apple PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt deleted file mode 100644 index cf9a0be2..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ - SUBDIRS( MiniCL ) - -IF(BUILD_INTEL_OPENCL_DEMOS) - SUBDIRS(Intel) -ENDIF() - -IF(BUILD_AMD_OPENCL_DEMOS) - SUBDIRS(AMD) -ENDIF() - -IF(BUILD_NVIDIA_OPENCL_DEMOS) - SUBDIRS(NVidia) -ENDIF() - -IF(APPLE AND OPENCL_LIBRARY) - SUBDIRS(Apple) -ENDIF() diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt deleted file mode 100644 index ecca1813..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/CMakeLists.txt +++ /dev/null @@ -1,85 +0,0 @@ - -INCLUDE_DIRECTORIES( - ${BULLET_PHYSICS_SOURCE_DIR}/src - ${INTEL_OPENCL_INCLUDES} -) - -ADD_DEFINITIONS(-DUSE_INTEL_OPENCL) -ADD_DEFINITIONS(-DCL_PLATFORM_INTEL) - - - -SET(BulletSoftBodyOpenCLSolvers_SRCS - ../btSoftBodySolver_OpenCL.cpp - ../btSoftBodySolver_OpenCLSIMDAware.cpp - ../btSoftBodySolverOutputCLtoGL.cpp -) - -SET(BulletSoftBodyOpenCLSolvers_HDRS - ../btSoftBodySolver_OpenCL.h - ../btSoftBodySolver_OpenCLSIMDAware.h - ../../Shared/btSoftBodySolverData.h - ../btSoftBodySolverVertexData_OpenCL.h - ../btSoftBodySolverTriangleData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCLSIMDAware.h - ../btSoftBodySolverBuffer_OpenCL.h - ../btSoftBodySolverVertexBuffer_OpenGL.h - ../btSoftBodySolverOutputCLtoGL.h -) - -# OpenCL and HLSL Shaders. -# Build rules generated to stringify these into headers -# which are needed by some of the sources -SET(BulletSoftBodyOpenCLSolvers_Shaders -# OutputToVertexArray - UpdateNormals - Integrate - UpdatePositions - UpdateNodes - SolvePositions - UpdatePositionsFromVelocities - ApplyForces - PrepareLinks - VSolveLinks -) - -foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) - LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") -endforeach(f) - - - -ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Intel - ${BulletSoftBodyOpenCLSolvers_SRCS} - ${BulletSoftBodyOpenCLSolvers_HDRS} - ${BulletSoftBodyOpenCLSolvers_OpenCLC} -) - -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Intel BulletSoftBody) -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Intel - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -#headers are already installed by BulletMultiThreaded library - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Intel PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua deleted file mode 100644 index 668886d1..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/Intel/premake4.lua +++ /dev/null @@ -1,27 +0,0 @@ - -hasCL = findOpenCL_Intel() - -if (hasCL) then - - project "BulletSoftBodySolvers_OpenCL_Intel" - - defines { "USE_INTEL_OPENCL","CL_PLATFORM_INTEL"} - - initOpenCL_Intel() - - kind "StaticLib" - - targetdir "../../../../../lib" - - includedirs { - ".", - "../../../..", - "../../../../../Glut" - } - files { - "../btSoftBodySolver_OpenCL.cpp", - "../btSoftBodySolver_OpenCLSIMDAware.cpp", - "../btSoftBodySolverOutputCLtoGL.cpp" - } - -end diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt deleted file mode 100644 index 97deb7e4..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src -) - -ADD_DEFINITIONS(-DUSE_MINICL) - - - - -SET(BulletSoftBodyOpenCLSolvers_SRCS - ../btSoftBodySolver_OpenCL.cpp -) - -SET(BulletSoftBodyOpenCLSolvers_HDRS - ../btSoftBodySolver_OpenCL.h - ../../Shared/btSoftBodySolverData.h - ../btSoftBodySolverVertexData_OpenCL.h - ../btSoftBodySolverTriangleData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCL.h - ../btSoftBodySolverBuffer_OpenCL.h -) - -# OpenCL and HLSL Shaders. -# Build rules generated to stringify these into headers -# which are needed by some of the sources -SET(BulletSoftBodyOpenCLSolvers_Shaders -# OutputToVertexArray - UpdateNormals - Integrate - UpdatePositions - UpdateNodes - SolvePositions - UpdatePositionsFromVelocities - ApplyForces - PrepareLinks - VSolveLinks -) - -foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) - LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") -endforeach(f) - - - -ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_Mini - ${BulletSoftBodyOpenCLSolvers_SRCS} - ${BulletSoftBodyOpenCLSolvers_HDRS} - ${BulletSoftBodyOpenCLSolvers_OpenCLC} -) - -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_Mini MiniCL BulletMultiThreaded BulletSoftBody) -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_Mini - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -#headers are already installed by BulletMultiThreaded library - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_Mini PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp deleted file mode 100644 index dfa60e66..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/MiniCLTaskWrap.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 - -#define MSTRINGIFY(A) A -#include "../OpenCLC10/ApplyForces.cl" -#include "../OpenCLC10/Integrate.cl" -#include "../OpenCLC10/PrepareLinks.cl" -#include "../OpenCLC10/SolvePositions.cl" -#include "../OpenCLC10/UpdateNodes.cl" -#include "../OpenCLC10/UpdateNormals.cl" -#include "../OpenCLC10/UpdatePositions.cl" -#include "../OpenCLC10/UpdatePositionsFromVelocities.cl" -#include "../OpenCLC10/VSolveLinks.cl" -#include "../OpenCLC10/UpdateFixedVertexPositions.cl" -//#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl" - - -MINICL_REGISTER(PrepareLinksKernel) -MINICL_REGISTER(VSolveLinksKernel) -MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel) -MINICL_REGISTER(SolvePositionsFromLinksKernel) -MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel) -MINICL_REGISTER(updateVelocitiesFromPositionsWithoutVelocitiesKernel) -MINICL_REGISTER(IntegrateKernel) -MINICL_REGISTER(ApplyForcesKernel) -MINICL_REGISTER(ResetNormalsAndAreasKernel) -MINICL_REGISTER(NormalizeNormalsAndAreasKernel) -MINICL_REGISTER(UpdateSoftBodiesKernel) -MINICL_REGISTER(UpdateFixedVertexPositions) - -float mydot3a(float4 a, float4 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -} - - -typedef struct -{ - int firstObject; - int endObject; -} CollisionObjectIndices; - -typedef struct -{ - float4 shapeTransform[4]; // column major 4x4 matrix - float4 linearVelocity; - float4 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - - // Shape information - // Compressed from the union - float radius; - float halfHeight; - int upAxis; - - float margin; - float friction; - - int padding0; - -} CollisionShapeDescription; - -// From btBroadphaseProxy.h -__constant int CAPSULE_SHAPE_PROXYTYPE = 10; - -// Multiply column-major matrix against vector -float4 matrixVectorMul( float4 matrix[4], float4 vector ) -{ - float4 returnVector; - float4 row0 = float4(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); - float4 row1 = float4(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); - float4 row2 = float4(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); - float4 row3 = float4(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); - returnVector.x = dot(row0, vector); - returnVector.y = dot(row1, vector); - returnVector.z = dot(row2, vector); - returnVector.w = dot(row3, vector); - return returnVector; -} - -__kernel void -SolveCollisionsAndUpdateVelocitiesKernel( - const int numNodes, - const float isolverdt, - __global int *g_vertexClothIdentifier, - __global float4 *g_vertexPreviousPositions, - __global float * g_perClothFriction, - __global float * g_clothDampingFactor, - __global CollisionObjectIndices * g_perClothCollisionObjectIndices, - __global CollisionShapeDescription * g_collisionObjectDetails, - __global float4 * g_vertexForces, - __global float4 *g_vertexVelocities, - __global float4 *g_vertexPositions GUID_ARG) -{ - int nodeID = get_global_id(0); - float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); - - if( get_global_id(0) < numNodes ) - { - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - - // Abort if this is not a valid cloth - if( clothIdentifier < 0 ) - return; - - - float4 position (g_vertexPositions[nodeID].xyz, 1.f); - float4 previousPosition (g_vertexPreviousPositions[nodeID].xyz, 1.f); - - float clothFriction = g_perClothFriction[clothIdentifier]; - float dampingFactor = g_clothDampingFactor[clothIdentifier]; - float velocityCoefficient = (1.f - dampingFactor); - float4 difference = position - previousPosition; - float4 velocity = difference*velocityCoefficient*isolverdt; - - CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; - - int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; - - if( numObjects > 0 ) - { - // We have some possible collisions to deal with - for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) - { - CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; - float colliderFriction = shapeDescription.friction; - - if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Colliding with a capsule - - float capsuleHalfHeight = shapeDescription.halfHeight; - float capsuleRadius = shapeDescription.radius; - float capsuleMargin = shapeDescription.margin; - int capsuleupAxis = shapeDescription.upAxis; - - // Four columns of worldTransform matrix - float4 worldTransform[4]; - worldTransform[0] = shapeDescription.shapeTransform[0]; - worldTransform[1] = shapeDescription.shapeTransform[1]; - worldTransform[2] = shapeDescription.shapeTransform[2]; - worldTransform[3] = shapeDescription.shapeTransform[3]; - - // Correctly define capsule centerline vector - float4 c1 (0.f, 0.f, 0.f, 1.f); - float4 c2 (0.f, 0.f, 0.f, 1.f); - c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); - c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); - c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); - c2.x = -c1.x; - c2.y = -c1.y; - c2.z = -c1.z; - - - float4 worldC1 = matrixVectorMul(worldTransform, c1); - float4 worldC2 = matrixVectorMul(worldTransform, c2); - float4 segment = (worldC2 - worldC1); - - // compute distance of tangent to vertex along line segment in capsule - float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) ); - - float4 closestPoint = (worldC1 + (segment * distanceAlongSegment)); - float distanceFromLine = length(position - closestPoint); - float distanceFromC1 = length(worldC1 - position); - float distanceFromC2 = length(worldC2 - position); - - // Final distance from collision, point to push from, direction to push in - // for impulse force - float dist; - float4 normalVector; - if( distanceAlongSegment < 0 ) - { - dist = distanceFromC1; - normalVector = float4(normalize(position - worldC1).xyz, 0.f); - } else if( distanceAlongSegment > 1.f ) { - dist = distanceFromC2; - normalVector = float4(normalize(position - worldC2).xyz, 0.f); - } else { - dist = distanceFromLine; - normalVector = float4(normalize(position - closestPoint).xyz, 0.f); - } - - float4 colliderLinearVelocity = shapeDescription.linearVelocity; - float4 colliderAngularVelocity = shapeDescription.angularVelocity; - float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - float4(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); - - float minDistance = capsuleRadius + capsuleMargin; - - // In case of no collision, this is the value of velocity - velocity = (position - previousPosition) * velocityCoefficient * isolverdt; - - - // Check for a collision - if( dist < minDistance ) - { - // Project back to surface along normal - position = position + float4(normalVector*(minDistance - dist)*0.9f); - velocity = (position - previousPosition) * velocityCoefficient * isolverdt; - float4 relativeVelocity = velocity - velocityOfSurfacePoint; - - float4 p1 = normalize(cross(normalVector, segment)); - float4 p2 = normalize(cross(p1, normalVector)); - // Full friction is sum of velocities in each direction of plane - float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); - - // Real friction is peak friction corrected by friction coefficients - frictionVector = frictionVector * (colliderFriction*clothFriction); - - float approachSpeed = dot(relativeVelocity, normalVector); - - if( approachSpeed <= 0.0f ) - forceOnVertex -= frictionVector; - } - } - } - } - - g_vertexVelocities[nodeID] = float4(velocity.xyz, 0.f); - - // Update external force - g_vertexForces[nodeID] = float4(forceOnVertex.xyz, 0.f); - - g_vertexPositions[nodeID] = float4(position.xyz, 0.f); - } -} - - -MINICL_REGISTER(SolveCollisionsAndUpdateVelocitiesKernel); - - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt deleted file mode 100644 index 884a0ffe..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/CMakeLists.txt +++ /dev/null @@ -1,84 +0,0 @@ - -ADD_DEFINITIONS(-DUSE_NVIDIA_OPENCL) -ADD_DEFINITIONS(-DCL_PLATFORM_NVIDIA) - -INCLUDE_DIRECTORIES( - ${BULLET_PHYSICS_SOURCE_DIR}/src - ${NVIDIA_OPENCL_INCLUDES} -) - - - -SET(BulletSoftBodyOpenCLSolvers_SRCS - ../btSoftBodySolver_OpenCL.cpp - ../btSoftBodySolver_OpenCLSIMDAware.cpp - ../btSoftBodySolverOutputCLtoGL.cpp -) - -SET(BulletSoftBodyOpenCLSolvers_HDRS - ../btSoftBodySolver_OpenCL.h - ../../Shared/btSoftBodySolverData.h - ../btSoftBodySolverVertexData_OpenCL.h - ../btSoftBodySolverTriangleData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCL.h - ../btSoftBodySolverLinkData_OpenCLSIMDAware.h - ../btSoftBodySolverBuffer_OpenCL.h - ../btSoftBodySolverVertexBuffer_OpenGL.h - ../btSoftBodySolverOutputCLtoGL.h -) - -# OpenCL and HLSL Shaders. -# Build rules generated to stringify these into headers -# which are needed by some of the sources -SET(BulletSoftBodyOpenCLSolvers_Shaders -# OutputToVertexArray - UpdateNormals - Integrate - UpdatePositions - UpdateNodes - SolvePositions - UpdatePositionsFromVelocities - ApplyForces - PrepareLinks - VSolveLinks -) - -foreach(f ${BulletSoftBodyOpenCLSolvers_Shaders}) - LIST(APPEND BulletSoftBodyOpenCLSolvers_OpenCLC "../OpenCLC10/${f}.cl") -endforeach(f) - - - -ADD_LIBRARY(BulletSoftBodySolvers_OpenCL_NVidia - ${BulletSoftBodyOpenCLSolvers_SRCS} - ${BulletSoftBodyOpenCLSolvers_HDRS} - ${BulletSoftBodyOpenCLSolvers_OpenCLC} -) - -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_OpenCL_NVidia BulletSoftBody BulletDynamics) -ENDIF (BUILD_SHARED_LIBS) - - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBodySolvers_OpenCL_NVidia - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -#headers are already installed by BulletMultiThreaded library - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBodySolvers_OpenCL_NVidia PROPERTIES PUBLIC_HEADER "${BulletSoftBodyOpenCLSolvers_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua deleted file mode 100644 index 0bab1e30..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/NVidia/premake4.lua +++ /dev/null @@ -1,27 +0,0 @@ - -hasCL = findOpenCL_NVIDIA() - -if (hasCL) then - - project "BulletSoftBodySolvers_OpenCL_NVIDIA" - - defines { "USE_NVIDIA_OPENCL","CL_PLATFORM_NVIDIA"} - - initOpenCL_NVIDIA() - - kind "StaticLib" - - targetdir "../../../../../lib" - - includedirs { - ".", - "../../../..", - "../../../../../Glut" - } - files { - "../btSoftBodySolver_OpenCL.cpp", - "../btSoftBodySolver_OpenCLSIMDAware.cpp", - "../btSoftBodySolverOutputCLtoGL.cpp" - } - -end diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl deleted file mode 100644 index f9bcb88e..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ApplyForces.cl +++ /dev/null @@ -1,102 +0,0 @@ -MSTRINGIFY( - - -float adot3(float4 a, float4 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -} - -float alength3(float4 a) -{ - a.w = 0; - return length(a); -} - -float4 anormalize3(float4 a) -{ - a.w = 0; - return normalize(a); -} - -float4 projectOnAxis( float4 v, float4 a ) -{ - return (a*adot3(v, a)); -} - -__kernel void -ApplyForcesKernel( - const uint numNodes, - const float solverdt, - const float epsilon, - __global int * g_vertexClothIdentifier, - __global float4 * g_vertexNormal, - __global float * g_vertexArea, - __global float * g_vertexInverseMass, - __global float * g_clothLiftFactor, - __global float * g_clothDragFactor, - __global float4 * g_clothWindVelocity, - __global float4 * g_clothAcceleration, - __global float * g_clothMediumDensity, - __global float4 * g_vertexForceAccumulator, - __global float4 * g_vertexVelocity GUID_ARG) -{ - unsigned int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - int clothId = g_vertexClothIdentifier[nodeID]; - float nodeIM = g_vertexInverseMass[nodeID]; - - if( nodeIM > 0.0f ) - { - float4 nodeV = g_vertexVelocity[nodeID]; - float4 normal = g_vertexNormal[nodeID]; - float area = g_vertexArea[nodeID]; - float4 nodeF = g_vertexForceAccumulator[nodeID]; - - // Read per-cloth values - float4 clothAcceleration = g_clothAcceleration[clothId]; - float4 clothWindVelocity = g_clothWindVelocity[clothId]; - float liftFactor = g_clothLiftFactor[clothId]; - float dragFactor = g_clothDragFactor[clothId]; - float mediumDensity = g_clothMediumDensity[clothId]; - - // Apply the acceleration to the cloth rather than do this via a force - nodeV += (clothAcceleration*solverdt); - - g_vertexVelocity[nodeID] = nodeV; - - // Aerodynamics - float4 rel_v = nodeV - clothWindVelocity; - float rel_v_len = alength3(rel_v); - float rel_v2 = dot(rel_v, rel_v); - - if( rel_v2 > epsilon ) - { - float4 rel_v_nrm = anormalize3(rel_v); - float4 nrm = normal; - - nrm = nrm * (dot(nrm, rel_v) < 0 ? -1.f : 1.f); - - float4 fDrag = (float4)(0.f, 0.f, 0.f, 0.f); - float4 fLift = (float4)(0.f, 0.f, 0.f, 0.f); - - float n_dot_v = dot(nrm, rel_v_nrm); - - // drag force - if ( dragFactor > 0.f ) - fDrag = 0.5f * dragFactor * mediumDensity * rel_v2 * area * n_dot_v * (-1.0f) * rel_v_nrm; - - // lift force - // Check angle of attack - // cos(10º) = 0.98480 - if ( 0 < n_dot_v && n_dot_v < 0.98480f) - fLift = 0.5f * liftFactor * mediumDensity * rel_v_len * area * sqrt(1.0f-n_dot_v*n_dot_v) * (cross(cross(nrm, rel_v_nrm), rel_v_nrm)); - - nodeF += fDrag + fLift; - g_vertexForceAccumulator[nodeID] = nodeF; - } - } - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl deleted file mode 100644 index 2ae7148a..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/ComputeBounds.cl +++ /dev/null @@ -1,82 +0,0 @@ -MSTRINGIFY( -#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n -#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n - -__kernel void -ComputeBoundsKernel( - const int numNodes, - const int numSoftBodies, - __global int * g_vertexClothIdentifier, - __global float4 * g_vertexPositions, - /* Unfortunately, to get the atomics below to work these arrays cannot be */ - /* uint4, though that is the layout of the data */ - /* Therefore this is little-endian-only code */ - volatile __global uint * g_clothMinBounds, - volatile __global uint * g_clothMaxBounds, - volatile __local uint * clothMinBounds, - volatile __local uint * clothMaxBounds) -{ - // Init min and max bounds arrays - if( get_local_id(0) < numSoftBodies ) - { - - clothMinBounds[get_local_id(0)*4] = UINT_MAX; - clothMinBounds[get_local_id(0)*4+1] = UINT_MAX; - clothMinBounds[get_local_id(0)*4+2] = UINT_MAX; - clothMinBounds[get_local_id(0)*4+3] = UINT_MAX; - clothMaxBounds[get_local_id(0)*4] = 0; - clothMaxBounds[get_local_id(0)*4+1] = 0; - clothMaxBounds[get_local_id(0)*4+2] = 0; - clothMaxBounds[get_local_id(0)*4+3] = 0; - - } - - barrier(CLK_LOCAL_MEM_FENCE); - - int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - if( clothIdentifier >= 0 ) - { - - float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f); - - /* Reinterpret position as uint */ - uint4 positionUInt = (uint4)(as_uint(position.x), as_uint(position.y), as_uint(position.z), 0); - - /* Invert sign bit of positives and whole of negatives to allow comparison as unsigned ints */ - positionUInt.x ^= (1+~(positionUInt.x >> 31) | 0x80000000); - positionUInt.y ^= (1+~(positionUInt.y >> 31) | 0x80000000); - positionUInt.z ^= (1+~(positionUInt.z >> 31) | 0x80000000); - - // Min/max with the LDS values - atom_min(&(clothMinBounds[clothIdentifier*4]), positionUInt.x); - atom_min(&(clothMinBounds[clothIdentifier*4+1]), positionUInt.y); - atom_min(&(clothMinBounds[clothIdentifier*4+2]), positionUInt.z); - - atom_max(&(clothMaxBounds[clothIdentifier*4]), positionUInt.x); - atom_max(&(clothMaxBounds[clothIdentifier*4+1]), positionUInt.y); - atom_max(&(clothMaxBounds[clothIdentifier*4+2]), positionUInt.z); - } - } - - barrier(CLK_LOCAL_MEM_FENCE); - - - /* Use global atomics to update the global versions of the data */ - if( get_local_id(0) < numSoftBodies ) - { - /*atom_min(&(g_clothMinBounds[get_local_id(0)].x), clothMinBounds[get_local_id(0)].x);*/ - atom_min(&(g_clothMinBounds[get_local_id(0)*4]), clothMinBounds[get_local_id(0)*4]); - atom_min(&(g_clothMinBounds[get_local_id(0)*4+1]), clothMinBounds[get_local_id(0)*4+1]); - atom_min(&(g_clothMinBounds[get_local_id(0)*4+2]), clothMinBounds[get_local_id(0)*4+2]); - - atom_max(&(g_clothMaxBounds[get_local_id(0)*4]), clothMaxBounds[get_local_id(0)*4]); - atom_max(&(g_clothMaxBounds[get_local_id(0)*4+1]), clothMaxBounds[get_local_id(0)*4+1]); - atom_max(&(g_clothMaxBounds[get_local_id(0)*4+2]), clothMaxBounds[get_local_id(0)*4+2]); - } -} - - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl deleted file mode 100644 index bb2d98a5..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/Integrate.cl +++ /dev/null @@ -1,35 +0,0 @@ -MSTRINGIFY( - -// Node indices for each link - - - -__kernel void -IntegrateKernel( - const int numNodes, - const float solverdt, - __global float * g_vertexInverseMasses, - __global float4 * g_vertexPositions, - __global float4 * g_vertexVelocity, - __global float4 * g_vertexPreviousPositions, - __global float4 * g_vertexForceAccumulator GUID_ARG) -{ - int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID]; - float4 velocity = g_vertexVelocity[nodeID]; - float4 force = g_vertexForceAccumulator[nodeID]; - float inverseMass = g_vertexInverseMasses[nodeID]; - - g_vertexPreviousPositions[nodeID] = position; - velocity += force * inverseMass * solverdt; - position += velocity * solverdt; - - g_vertexForceAccumulator[nodeID] = (float4)(0.f, 0.f, 0.f, 0.0f); - g_vertexPositions[nodeID] = position; - g_vertexVelocity[nodeID] = velocity; - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl deleted file mode 100644 index 98913777..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/OutputToVertexArray.cl +++ /dev/null @@ -1,46 +0,0 @@ -MSTRINGIFY( - -__kernel void -OutputToVertexArrayWithNormalsKernel( - const int startNode, const int numNodes, __global float *g_vertexBuffer, - const int positionOffset, const int positionStride, const __global float4* g_vertexPositions, - const int normalOffset, const int normalStride, const __global float4* g_vertexNormals ) -{ - int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID + startNode]; - float4 normal = g_vertexNormals[nodeID + startNode]; - - // Stride should account for the float->float4 conversion - int positionDestination = nodeID * positionStride + positionOffset; - g_vertexBuffer[positionDestination] = position.x; - g_vertexBuffer[positionDestination+1] = position.y; - g_vertexBuffer[positionDestination+2] = position.z; - - int normalDestination = nodeID * normalStride + normalOffset; - g_vertexBuffer[normalDestination] = normal.x; - g_vertexBuffer[normalDestination+1] = normal.y; - g_vertexBuffer[normalDestination+2] = normal.z; - } -} - -__kernel void -OutputToVertexArrayWithoutNormalsKernel( - const int startNode, const int numNodes, __global float *g_vertexBuffer, - const int positionOffset, const int positionStride, const __global float4* g_vertexPositions ) -{ - int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID + startNode]; - - // Stride should account for the float->float4 conversion - int positionDestination = nodeID * positionStride + positionOffset; - g_vertexBuffer[positionDestination] = position.x; - g_vertexBuffer[positionDestination+1] = position.y; - g_vertexBuffer[positionDestination+2] = position.z; - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl deleted file mode 100644 index 542a11ec..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/PrepareLinks.cl +++ /dev/null @@ -1,38 +0,0 @@ -MSTRINGIFY( - - - -__kernel void -PrepareLinksKernel( - const int numLinks, - __global int2 * g_linksVertexIndices, - __global float * g_linksMassLSC, - __global float4 * g_nodesPreviousPosition, - __global float * g_linksLengthRatio, - __global float4 * g_linksCurrentLength GUID_ARG) -{ - int linkID = get_global_id(0); - if( linkID < numLinks ) - { - - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - - float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0]; - float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1]; - - float massLSC = g_linksMassLSC[linkID]; - - float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0; - linkCurrentLength.w = 0.f; - - float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC; - linkLengthRatio = 1.0f/linkLengthRatio; - - g_linksCurrentLength[linkID] = linkCurrentLength; - g_linksLengthRatio[linkID] = linkLengthRatio; - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl deleted file mode 100644 index 92fb939d..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocities.cl +++ /dev/null @@ -1,204 +0,0 @@ -MSTRINGIFY( - - - -float mydot3a(float4 a, float4 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -} - - -typedef struct -{ - int firstObject; - int endObject; -} CollisionObjectIndices; - -typedef struct -{ - float4 shapeTransform[4]; // column major 4x4 matrix - float4 linearVelocity; - float4 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - - // Shape information - // Compressed from the union - float radius; - float halfHeight; - int upAxis; - - float margin; - float friction; - - int padding0; - -} CollisionShapeDescription; - -// From btBroadphaseProxy.h -__constant int CAPSULE_SHAPE_PROXYTYPE = 10; - -// Multiply column-major matrix against vector -float4 matrixVectorMul( float4 matrix[4], float4 vector ) -{ - float4 returnVector; - float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); - float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); - float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); - float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); - returnVector.x = dot(row0, vector); - returnVector.y = dot(row1, vector); - returnVector.z = dot(row2, vector); - returnVector.w = dot(row3, vector); - return returnVector; -} - -__kernel void -SolveCollisionsAndUpdateVelocitiesKernel( - const int numNodes, - const float isolverdt, - __global int *g_vertexClothIdentifier, - __global float4 *g_vertexPreviousPositions, - __global float * g_perClothFriction, - __global float * g_clothDampingFactor, - __global CollisionObjectIndices * g_perClothCollisionObjectIndices, - __global CollisionShapeDescription * g_collisionObjectDetails, - __global float4 * g_vertexForces, - __global float4 *g_vertexVelocities, - __global float4 *g_vertexPositions GUID_ARG) -{ - int nodeID = get_global_id(0); - float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); - - if( get_global_id(0) < numNodes ) - { - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - - // Abort if this is not a valid cloth - if( clothIdentifier < 0 ) - return; - - - float4 position = (float4)(g_vertexPositions[nodeID].xyz, 1.f); - float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 1.f); - - float clothFriction = g_perClothFriction[clothIdentifier]; - float dampingFactor = g_clothDampingFactor[clothIdentifier]; - float velocityCoefficient = (1.f - dampingFactor); - float4 difference = position - previousPosition; - float4 velocity = difference*velocityCoefficient*isolverdt; - - CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; - - int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; - - if( numObjects > 0 ) - { - // We have some possible collisions to deal with - for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision ) - { - CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision]; - float colliderFriction = shapeDescription.friction; - - if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Colliding with a capsule - - float capsuleHalfHeight = shapeDescription.halfHeight; - float capsuleRadius = shapeDescription.radius; - float capsuleMargin = shapeDescription.margin; - int capsuleupAxis = shapeDescription.upAxis; - - // Four columns of worldTransform matrix - float4 worldTransform[4]; - worldTransform[0] = shapeDescription.shapeTransform[0]; - worldTransform[1] = shapeDescription.shapeTransform[1]; - worldTransform[2] = shapeDescription.shapeTransform[2]; - worldTransform[3] = shapeDescription.shapeTransform[3]; - - // Correctly define capsule centerline vector - float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f); - float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f); - c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); - c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); - c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); - c2.x = -c1.x; - c2.y = -c1.y; - c2.z = -c1.z; - - - float4 worldC1 = matrixVectorMul(worldTransform, c1); - float4 worldC2 = matrixVectorMul(worldTransform, c2); - float4 segment = (worldC2 - worldC1); - - // compute distance of tangent to vertex along line segment in capsule - float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) ); - - float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment)); - float distanceFromLine = length(position - closestPoint); - float distanceFromC1 = length(worldC1 - position); - float distanceFromC2 = length(worldC2 - position); - - // Final distance from collision, point to push from, direction to push in - // for impulse force - float dist; - float4 normalVector; - if( distanceAlongSegment < 0 ) - { - dist = distanceFromC1; - normalVector = (float4)(normalize(position - worldC1).xyz, 0.f); - } else if( distanceAlongSegment > 1.f ) { - dist = distanceFromC2; - normalVector = (float4)(normalize(position - worldC2).xyz, 0.f); - } else { - dist = distanceFromLine; - normalVector = (float4)(normalize(position - closestPoint).xyz, 0.f); - } - - float4 colliderLinearVelocity = shapeDescription.linearVelocity; - float4 colliderAngularVelocity = shapeDescription.angularVelocity; - float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); - - float minDistance = capsuleRadius + capsuleMargin; - - // In case of no collision, this is the value of velocity - velocity = (position - previousPosition) * velocityCoefficient * isolverdt; - - - // Check for a collision - if( dist < minDistance ) - { - // Project back to surface along normal - position = position + (float4)((minDistance - dist)*normalVector*0.9f); - velocity = (position - previousPosition) * velocityCoefficient * isolverdt; - float4 relativeVelocity = velocity - velocityOfSurfacePoint; - - float4 p1 = normalize(cross(normalVector, segment)); - float4 p2 = normalize(cross(p1, normalVector)); - // Full friction is sum of velocities in each direction of plane - float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); - - // Real friction is peak friction corrected by friction coefficients - frictionVector = frictionVector * (colliderFriction*clothFriction); - - float approachSpeed = dot(relativeVelocity, normalVector); - - if( approachSpeed <= 0.0f ) - forceOnVertex -= frictionVector; - } - } - } - } - - g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f); - - // Update external force - g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f); - - g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f); - } -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl deleted file mode 100644 index 8720b72e..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl +++ /dev/null @@ -1,242 +0,0 @@ -MSTRINGIFY( - -//#pragma OPENCL EXTENSION cl_amd_printf:enable\n - -float mydot3a(float4 a, float4 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -} - -float mylength3(float4 a) -{ - a.w = 0; - return length(a); -} - -float4 mynormalize3(float4 a) -{ - a.w = 0; - return normalize(a); -} - -typedef struct -{ - int firstObject; - int endObject; -} CollisionObjectIndices; - -typedef struct -{ - float4 shapeTransform[4]; // column major 4x4 matrix - float4 linearVelocity; - float4 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - - // Shape information - // Compressed from the union - float radius; - float halfHeight; - int upAxis; - - float margin; - float friction; - - int padding0; - -} CollisionShapeDescription; - -// From btBroadphaseProxy.h -__constant int CAPSULE_SHAPE_PROXYTYPE = 10; - -// Multiply column-major matrix against vector -float4 matrixVectorMul( float4 matrix[4], float4 vector ) -{ - float4 returnVector; - float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x); - float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y); - float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z); - float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w); - returnVector.x = dot(row0, vector); - returnVector.y = dot(row1, vector); - returnVector.z = dot(row2, vector); - returnVector.w = dot(row3, vector); - return returnVector; -} - -__kernel void -SolveCollisionsAndUpdateVelocitiesKernel( - const int numNodes, - const float isolverdt, - __global int *g_vertexClothIdentifier, - __global float4 *g_vertexPreviousPositions, - __global float * g_perClothFriction, - __global float * g_clothDampingFactor, - __global CollisionObjectIndices * g_perClothCollisionObjectIndices, - __global CollisionShapeDescription * g_collisionObjectDetails, - __global float4 * g_vertexForces, - __global float4 *g_vertexVelocities, - __global float4 *g_vertexPositions, - __local CollisionShapeDescription *localCollisionShapes, - __global float * g_vertexInverseMasses) -{ - int nodeID = get_global_id(0); - float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f); - - int clothIdentifier = g_vertexClothIdentifier[nodeID]; - - // Abort if this is not a valid cloth - if( clothIdentifier < 0 ) - return; - - - float4 position = (float4)(g_vertexPositions[nodeID].xyz, 0.f); - float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 0.f); - - float clothFriction = g_perClothFriction[clothIdentifier]; - float dampingFactor = g_clothDampingFactor[clothIdentifier]; - float velocityCoefficient = (1.f - dampingFactor); - float4 difference = position - previousPosition; - float4 velocity = difference*velocityCoefficient*isolverdt; - float inverseMass = g_vertexInverseMasses[nodeID]; - - CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier]; - - int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; - - if( numObjects > 0 ) - { - // We have some possible collisions to deal with - - // First load all of the collision objects into LDS - int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject; - if( get_local_id(0) < numObjects ) - { - localCollisionShapes[get_local_id(0)] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + get_local_id(0) ]; - } - } - - // Safe as the vertices are padded so that not more than one soft body is in a group - barrier(CLK_LOCAL_MEM_FENCE); - - // Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this - if( numObjects > 0 ) - { - - - // We have some possible collisions to deal with - for( int collision = 0; collision < numObjects; ++collision ) - { - CollisionShapeDescription shapeDescription = localCollisionShapes[collision]; - float colliderFriction = localCollisionShapes[collision].friction; - - if( localCollisionShapes[collision].collisionShapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Colliding with a capsule - - float capsuleHalfHeight = localCollisionShapes[collision].halfHeight; - float capsuleRadius = localCollisionShapes[collision].radius; - float capsuleMargin = localCollisionShapes[collision].margin; - int capsuleupAxis = localCollisionShapes[collision].upAxis; - - if ( capsuleHalfHeight <= 0 ) - capsuleHalfHeight = 0.0001f; - float4 worldTransform[4]; - worldTransform[0] = localCollisionShapes[collision].shapeTransform[0]; - worldTransform[1] = localCollisionShapes[collision].shapeTransform[1]; - worldTransform[2] = localCollisionShapes[collision].shapeTransform[2]; - worldTransform[3] = localCollisionShapes[collision].shapeTransform[3]; - - // Correctly define capsule centerline vector - float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f); - float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f); - c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 ); - c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 ); - c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 ); - c2.x = -c1.x; - c2.y = -c1.y; - c2.z = -c1.z; - - float4 worldC1 = matrixVectorMul(worldTransform, c1); - float4 worldC2 = matrixVectorMul(worldTransform, c2); - float4 segment = (float4)((worldC2 - worldC1).xyz, 0.f); - - float4 segmentNormalized = mynormalize3(segment); - float distanceAlongSegment =mydot3a( (position - worldC1), segmentNormalized ); - - float4 closestPointOnSegment = (worldC1 + (float4)(segmentNormalized * distanceAlongSegment)); - float distanceFromLine = mylength3(position - closestPointOnSegment); - float distanceFromC1 = mylength3(worldC1 - position); - float distanceFromC2 = mylength3(worldC2 - position); - - // Final distance from collision, point to push from, direction to push in - // for impulse force - float dist; - float4 normalVector; - - if( distanceAlongSegment < 0 ) - { - dist = distanceFromC1; - normalVector = (float4)(normalize(position - worldC1).xyz, 0.f); - } else if( distanceAlongSegment > length(segment) ) { - dist = distanceFromC2; - normalVector = (float4)(normalize(position - worldC2).xyz, 0.f); - } else { - dist = distanceFromLine; - normalVector = (float4)(normalize(position - closestPointOnSegment).xyz, 0.f); - } - - float minDistance = capsuleRadius + capsuleMargin; - float4 closestPointOnSurface = (float4)((position + (minDistance - dist) * normalVector).xyz, 0.f); - - float4 colliderLinearVelocity = shapeDescription.linearVelocity; - float4 colliderAngularVelocity = shapeDescription.angularVelocity; - float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, closestPointOnSurface - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f)); - - - // Check for a collision - if( dist < minDistance ) - { - // Project back to surface along normal - position = closestPointOnSurface; - velocity = (position - previousPosition) * velocityCoefficient * isolverdt; - float4 relativeVelocity = velocity - velocityOfSurfacePoint; - - float4 p1 = mynormalize3(cross(normalVector, segment)); - float4 p2 = mynormalize3(cross(p1, normalVector)); - - float4 tangentialVel = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2); - float frictionCoef = (colliderFriction * clothFriction); - if (frictionCoef>1.f) - frictionCoef = 1.f; - - //only apply friction if objects are not moving apart - float projVel = mydot3a(relativeVelocity,normalVector); - if ( projVel >= -0.001f) - { - if ( inverseMass > 0 ) - { - //float4 myforceOnVertex = -tangentialVel * frictionCoef * isolverdt * (1.0f / inverseMass); - position += (-tangentialVel * frictionCoef) / (isolverdt); - } - } - - // In case of no collision, this is the value of velocity - velocity = (position - previousPosition) * velocityCoefficient * isolverdt; - - } - } - } - } - - g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f); - - // Update external force - g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f); - - g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f); -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl deleted file mode 100644 index e4a5341c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositions.cl +++ /dev/null @@ -1,57 +0,0 @@ - - - -MSTRINGIFY( - - -float mydot3(float4 a, float4 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -} - - -__kernel void -SolvePositionsFromLinksKernel( - const int startLink, - const int numLinks, - const float kst, - const float ti, - __global int2 * g_linksVertexIndices, - __global float * g_linksMassLSC, - __global float * g_linksRestLengthSquared, - __global float * g_verticesInverseMass, - __global float4 * g_vertexPositions GUID_ARG) - -{ - int linkID = get_global_id(0) + startLink; - if( get_global_id(0) < numLinks ) - { - float massLSC = g_linksMassLSC[linkID]; - float restLengthSquared = g_linksRestLengthSquared[linkID]; - - if( massLSC > 0.0f ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - - float4 position0 = g_vertexPositions[node0]; - float4 position1 = g_vertexPositions[node1]; - - float inverseMass0 = g_verticesInverseMass[node0]; - float inverseMass1 = g_verticesInverseMass[node1]; - - float4 del = position1 - position0; - float len = mydot3(del, del); - float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; - position0 = position0 - del*(k*inverseMass0); - position1 = position1 + del*(k*inverseMass1); - - g_vertexPositions[node0] = position0; - g_vertexPositions[node1] = position1; - - } - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl deleted file mode 100644 index e99bbf23..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/SolvePositionsSIMDBatched.cl +++ /dev/null @@ -1,130 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -MSTRINGIFY( - -float mydot3(float4 a, float4 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -} - -__kernel __attribute__((reqd_work_group_size(WAVEFRONT_BLOCK_MULTIPLIER*WAVEFRONT_SIZE, 1, 1))) -void -SolvePositionsFromLinksKernel( - const int startWaveInBatch, - const int numWaves, - const float kst, - const float ti, - __global int2 *g_wavefrontBatchCountsVertexCounts, - __global int *g_vertexAddressesPerWavefront, - __global int2 * g_linksVertexIndices, - __global float * g_linksMassLSC, - __global float * g_linksRestLengthSquared, - __global float * g_verticesInverseMass, - __global float4 * g_vertexPositions, - __local int2 *wavefrontBatchCountsVertexCounts, - __local float4 *vertexPositionSharedData, - __local float *vertexInverseMassSharedData) -{ - const int laneInWavefront = (get_global_id(0) & (WAVEFRONT_SIZE-1)); - const int wavefront = startWaveInBatch + (get_global_id(0) / WAVEFRONT_SIZE); - const int firstWavefrontInBlock = startWaveInBatch + get_group_id(0) * WAVEFRONT_BLOCK_MULTIPLIER; - const int localWavefront = wavefront - firstWavefrontInBlock; - - // Mask out in case there's a stray "wavefront" at the end that's been forced in through the multiplier - if( wavefront < (startWaveInBatch + numWaves) ) - { - // Load the batch counts for the wavefronts - - int2 batchesAndVerticesWithinWavefront = g_wavefrontBatchCountsVertexCounts[wavefront]; - int batchesWithinWavefront = batchesAndVerticesWithinWavefront.x; - int verticesUsedByWave = batchesAndVerticesWithinWavefront.y; - - // Load the vertices for the wavefronts - for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) - { - int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; - - vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_vertexPositions[vertexAddress]; - vertexInverseMassSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex] = g_verticesInverseMass[vertexAddress]; - } - - barrier(CLK_LOCAL_MEM_FENCE); - - // Loop through the batches performing the solve on each in LDS - int baseDataLocationForWave = WAVEFRONT_SIZE * wavefront * MAX_BATCHES_PER_WAVE; - - //for( int batch = 0; batch < batchesWithinWavefront; ++batch ) - - int batch = 0; - do - { - int baseDataLocation = baseDataLocationForWave + WAVEFRONT_SIZE * batch; - int locationOfValue = baseDataLocation + laneInWavefront; - - - // These loads should all be perfectly linear across the WF - int2 localVertexIndices = g_linksVertexIndices[locationOfValue]; - float massLSC = g_linksMassLSC[locationOfValue]; - float restLengthSquared = g_linksRestLengthSquared[locationOfValue]; - - // LDS vertex addresses based on logical wavefront number in block and loaded index - int vertexAddress0 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.x; - int vertexAddress1 = MAX_NUM_VERTICES_PER_WAVE * localWavefront + localVertexIndices.y; - - float4 position0 = vertexPositionSharedData[vertexAddress0]; - float4 position1 = vertexPositionSharedData[vertexAddress1]; - - float inverseMass0 = vertexInverseMassSharedData[vertexAddress0]; - float inverseMass1 = vertexInverseMassSharedData[vertexAddress1]; - - float4 del = position1 - position0; - float len = mydot3(del, del); - - float k = 0; - if( massLSC > 0.0f ) - { - k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst; - } - - position0 = position0 - del*(k*inverseMass0); - position1 = position1 + del*(k*inverseMass1); - - // Ensure compiler does not re-order memory operations - barrier(CLK_LOCAL_MEM_FENCE); - - vertexPositionSharedData[vertexAddress0] = position0; - vertexPositionSharedData[vertexAddress1] = position1; - - // Ensure compiler does not re-order memory operations - barrier(CLK_LOCAL_MEM_FENCE); - - - ++batch; - } while( batch < batchesWithinWavefront ); - - // Update the global memory vertices for the wavefronts - for( int vertex = laneInWavefront; vertex < verticesUsedByWave; vertex+=WAVEFRONT_SIZE ) - { - int vertexAddress = g_vertexAddressesPerWavefront[wavefront*MAX_NUM_VERTICES_PER_WAVE + vertex]; - - g_vertexPositions[vertexAddress] = (float4)(vertexPositionSharedData[localWavefront*MAX_NUM_VERTICES_PER_WAVE + vertex].xyz, 0.f); - } - - } - -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl deleted file mode 100644 index 1d925a31..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateConstants.cl +++ /dev/null @@ -1,44 +0,0 @@ -MSTRINGIFY( - -/*#define float3 float4 - -float dot3(float3 a, float3 b) -{ - return a.x*b.x + a.y*b.y + a.z*b.z; -}*/ - -__kernel void -UpdateConstantsKernel( - const int numLinks, - __global int2 * g_linksVertexIndices, - __global float4 * g_vertexPositions, - __global float * g_vertexInverseMasses, - __global float * g_linksMaterialLSC, - __global float * g_linksMassLSC, - __global float * g_linksRestLengthSquared, - __global float * g_linksRestLengths) -{ - int linkID = get_global_id(0); - if( linkID < numLinks ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ]; - - float3 position0 = g_vertexPositions[node0].xyz; - float3 position1 = g_vertexPositions[node1].xyz; - float inverseMass0 = g_vertexInverseMasses[node0]; - float inverseMass1 = g_vertexInverseMasses[node1]; - - float3 difference = position0 - position1; - float length2 = dot(difference, difference); - float length = sqrt(length2); - - g_linksRestLengths[linkID] = length; - g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient; - g_linksRestLengthSquared[linkID] = length*length; - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl deleted file mode 100644 index 3b2516e7..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateFixedVertexPositions.cl +++ /dev/null @@ -1,25 +0,0 @@ -MSTRINGIFY( - -__kernel void -UpdateFixedVertexPositions( - const uint numNodes, - __global int * g_anchorIndex, - __global float4 * g_vertexPositions, - __global float4 * g_anchorPositions GUID_ARG) -{ - unsigned int nodeID = get_global_id(0); - - if( nodeID < numNodes ) - { - int anchorIndex = g_anchorIndex[nodeID]; - float4 position = g_vertexPositions[nodeID]; - - if ( anchorIndex >= 0 ) - { - float4 anchorPosition = g_anchorPositions[anchorIndex]; - g_vertexPositions[nodeID] = anchorPosition; - } - } -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl deleted file mode 100644 index aa7c778a..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNodes.cl +++ /dev/null @@ -1,39 +0,0 @@ -MSTRINGIFY( - - -__kernel void -updateVelocitiesFromPositionsWithVelocitiesKernel( - int numNodes, - float isolverdt, - __global float4 * g_vertexPositions, - __global float4 * g_vertexPreviousPositions, - __global int * g_vertexClothIndices, - __global float *g_clothVelocityCorrectionCoefficients, - __global float * g_clothDampingFactor, - __global float4 * g_vertexVelocities, - __global float4 * g_vertexForces GUID_ARG) -{ - int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID]; - float4 previousPosition = g_vertexPreviousPositions[nodeID]; - float4 velocity = g_vertexVelocities[nodeID]; - int clothIndex = g_vertexClothIndices[nodeID]; - float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex]; - float dampingFactor = g_clothDampingFactor[clothIndex]; - float velocityCoefficient = (1.f - dampingFactor); - - float4 difference = position - previousPosition; - - velocity += difference*velocityCorrectionCoefficient*isolverdt; - - // Damp the velocity - velocity *= velocityCoefficient; - - g_vertexVelocities[nodeID] = velocity; - g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl deleted file mode 100644 index d277b683..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdateNormals.cl +++ /dev/null @@ -1,102 +0,0 @@ -MSTRINGIFY( - -float length3(float4 a) -{ - a.w = 0; - return length(a); -} - -float4 normalize3(float4 a) -{ - a.w = 0; - return normalize(a); -} - -__kernel void -ResetNormalsAndAreasKernel( - const unsigned int numNodes, - __global float4 * g_vertexNormals, - __global float * g_vertexArea GUID_ARG) -{ - if( get_global_id(0) < numNodes ) - { - g_vertexNormals[get_global_id(0)] = (float4)(0.0f, 0.0f, 0.0f, 0.0f); - g_vertexArea[get_global_id(0)] = 0.0f; - } -} - - -__kernel void -UpdateSoftBodiesKernel( - const unsigned int startFace, - const unsigned int numFaces, - __global int4 * g_triangleVertexIndexSet, - __global float4 * g_vertexPositions, - __global float4 * g_vertexNormals, - __global float * g_vertexArea, - __global float4 * g_triangleNormals, - __global float * g_triangleArea GUID_ARG) -{ - int faceID = get_global_id(0) + startFace; - if( get_global_id(0) < numFaces ) - { - int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ]; - int nodeIndex0 = triangleIndexSet.x; - int nodeIndex1 = triangleIndexSet.y; - int nodeIndex2 = triangleIndexSet.z; - - float4 node0 = g_vertexPositions[nodeIndex0]; - float4 node1 = g_vertexPositions[nodeIndex1]; - float4 node2 = g_vertexPositions[nodeIndex2]; - float4 nodeNormal0 = g_vertexNormals[nodeIndex0]; - float4 nodeNormal1 = g_vertexNormals[nodeIndex1]; - float4 nodeNormal2 = g_vertexNormals[nodeIndex2]; - float vertexArea0 = g_vertexArea[nodeIndex0]; - float vertexArea1 = g_vertexArea[nodeIndex1]; - float vertexArea2 = g_vertexArea[nodeIndex2]; - - float4 vector0 = node1 - node0; - float4 vector1 = node2 - node0; - - float4 faceNormal = cross(vector0, vector1); - float triangleArea = length(faceNormal); - - nodeNormal0 = nodeNormal0 + faceNormal; - nodeNormal1 = nodeNormal1 + faceNormal; - nodeNormal2 = nodeNormal2 + faceNormal; - vertexArea0 = vertexArea0 + triangleArea; - vertexArea1 = vertexArea1 + triangleArea; - vertexArea2 = vertexArea2 + triangleArea; - - g_triangleNormals[faceID] = normalize3(faceNormal); - g_vertexNormals[nodeIndex0] = nodeNormal0; - g_vertexNormals[nodeIndex1] = nodeNormal1; - g_vertexNormals[nodeIndex2] = nodeNormal2; - g_triangleArea[faceID] = triangleArea; - g_vertexArea[nodeIndex0] = vertexArea0; - g_vertexArea[nodeIndex1] = vertexArea1; - g_vertexArea[nodeIndex2] = vertexArea2; - } -} - -__kernel void -NormalizeNormalsAndAreasKernel( - const unsigned int numNodes, - __global int * g_vertexTriangleCount, - __global float4 * g_vertexNormals, - __global float * g_vertexArea GUID_ARG) -{ - if( get_global_id(0) < numNodes ) - { - float4 normal = g_vertexNormals[get_global_id(0)]; - float area = g_vertexArea[get_global_id(0)]; - int numTriangles = g_vertexTriangleCount[get_global_id(0)]; - - float vectorLength = length3(normal); - - g_vertexNormals[get_global_id(0)] = normalize3(normal); - g_vertexArea[get_global_id(0)] = area/(float)(numTriangles); - } -} - -); diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl deleted file mode 100644 index a2610314..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositions.cl +++ /dev/null @@ -1,34 +0,0 @@ -MSTRINGIFY( - -__kernel void -updateVelocitiesFromPositionsWithoutVelocitiesKernel( - const int numNodes, - const float isolverdt, - __global float4 * g_vertexPositions, - __global float4 * g_vertexPreviousPositions, - __global int * g_vertexClothIndices, - __global float * g_clothDampingFactor, - __global float4 * g_vertexVelocities, - __global float4 * g_vertexForces GUID_ARG) - -{ - int nodeID = get_global_id(0); - if( nodeID < numNodes ) - { - float4 position = g_vertexPositions[nodeID]; - float4 previousPosition = g_vertexPreviousPositions[nodeID]; - float4 velocity = g_vertexVelocities[nodeID]; - int clothIndex = g_vertexClothIndices[nodeID]; - float dampingFactor = g_clothDampingFactor[clothIndex]; - float velocityCoefficient = (1.f - dampingFactor); - - float4 difference = position - previousPosition; - - velocity = difference*velocityCoefficient*isolverdt; - - g_vertexVelocities[nodeID] = velocity; - g_vertexForces[nodeID] = (float4)(0.f, 0.f, 0.f, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl deleted file mode 100644 index ec1f4878..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/UpdatePositionsFromVelocities.cl +++ /dev/null @@ -1,28 +0,0 @@ - -MSTRINGIFY( - - - - -__kernel void -UpdatePositionsFromVelocitiesKernel( - const int numNodes, - const float solverSDT, - __global float4 * g_vertexVelocities, - __global float4 * g_vertexPreviousPositions, - __global float4 * g_vertexCurrentPosition GUID_ARG) -{ - int vertexID = get_global_id(0); - if( vertexID < numNodes ) - { - float4 previousPosition = g_vertexPreviousPositions[vertexID]; - float4 velocity = g_vertexVelocities[vertexID]; - - float4 newPosition = previousPosition + velocity*solverSDT; - - g_vertexCurrentPosition[vertexID] = newPosition; - g_vertexPreviousPositions[vertexID] = newPosition; - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl deleted file mode 100644 index 19224bda..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/OpenCLC10/VSolveLinks.cl +++ /dev/null @@ -1,45 +0,0 @@ -MSTRINGIFY( - -__kernel void -VSolveLinksKernel( - int startLink, - int numLinks, - float kst, - __global int2 * g_linksVertexIndices, - __global float * g_linksLengthRatio, - __global float4 * g_linksCurrentLength, - __global float * g_vertexInverseMass, - __global float4 * g_vertexVelocity GUID_ARG) -{ - int linkID = get_global_id(0) + startLink; - if( get_global_id(0) < numLinks ) - { - int2 nodeIndices = g_linksVertexIndices[linkID]; - int node0 = nodeIndices.x; - int node1 = nodeIndices.y; - - float linkLengthRatio = g_linksLengthRatio[linkID]; - float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz; - - float3 vertexVelocity0 = g_vertexVelocity[node0].xyz; - float3 vertexVelocity1 = g_vertexVelocity[node1].xyz; - - float vertexInverseMass0 = g_vertexInverseMass[node0]; - float vertexInverseMass1 = g_vertexInverseMass[node1]; - - float3 nodeDifference = vertexVelocity0 - vertexVelocity1; - float dotResult = dot(linkCurrentLength, nodeDifference); - float j = -dotResult*linkLengthRatio*kst; - - float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0); - float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1); - - vertexVelocity0 += velocityChange0; - vertexVelocity1 -= velocityChange1; - - g_vertexVelocity[node0] = (float4)(vertexVelocity0, 0.f); - g_vertexVelocity[node1] = (float4)(vertexVelocity1, 0.f); - } -} - -); \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h deleted file mode 100644 index f824f281..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverBuffer_OpenCL.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H -#define BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H - -// OpenCL support - -#ifdef USE_MINICL - #include "MiniCL/cl.h" -#else //USE_MINICL - #ifdef __APPLE__ - #include - #else - #include - #endif //__APPLE__ -#endif//USE_MINICL - -#ifndef SAFE_RELEASE -#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } -#endif - -template class btOpenCLBuffer -{ -public: - - cl_command_queue m_cqCommandQue; - cl_context m_clContext; - cl_mem m_buffer; - - - - btAlignedObjectArray< ElementType > * m_CPUBuffer; - - int m_gpuSize; - bool m_onGPU; - bool m_readOnlyOnGPU; - bool m_allocated; - - - bool createBuffer( cl_mem* preexistingBuffer = 0) - { - - cl_int err; - - - if( preexistingBuffer ) - { - m_buffer = *preexistingBuffer; - } - else { - - cl_mem_flags flags= m_readOnlyOnGPU ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE; - - size_t size = m_CPUBuffer->size() * sizeof(ElementType); - // At a minimum the buffer must exist - if( size == 0 ) - size = sizeof(ElementType); - m_buffer = clCreateBuffer(m_clContext, flags, size, 0, &err); - if( err != CL_SUCCESS ) - { - btAssert( "Buffer::Buffer(m_buffer)"); - } - } - - m_gpuSize = m_CPUBuffer->size(); - - return true; - } - -public: - btOpenCLBuffer( cl_command_queue commandQue,cl_context ctx, btAlignedObjectArray< ElementType >* CPUBuffer, bool readOnly) - :m_cqCommandQue(commandQue), - m_clContext(ctx), - m_buffer(0), - m_CPUBuffer(CPUBuffer), - m_gpuSize(0), - m_onGPU(false), - m_readOnlyOnGPU(readOnly), - m_allocated(false) - { - } - - ~btOpenCLBuffer() - { - clReleaseMemObject(m_buffer); - } - - - bool moveToGPU() - { - - - cl_int err; - - if( (m_CPUBuffer->size() != m_gpuSize) ) - { - m_onGPU = false; - } - - if( !m_allocated && m_CPUBuffer->size() == 0 ) - { - // If it isn't on the GPU and yet there is no data on the CPU side this may cause a problem with some kernels. - // We should create *something* on the device side - if (!createBuffer()) { - return false; - } - m_allocated = true; - } - - if( !m_onGPU && m_CPUBuffer->size() > 0 ) - { - if (!m_allocated || (m_CPUBuffer->size() != m_gpuSize)) { - if (!createBuffer()) { - return false; - } - m_allocated = true; - } - - size_t size = m_CPUBuffer->size() * sizeof(ElementType); - err = clEnqueueWriteBuffer(m_cqCommandQue,m_buffer, - CL_FALSE, - 0, - size, - &((*m_CPUBuffer)[0]),0,0,0); - if( err != CL_SUCCESS ) - { - btAssert( "CommandQueue::enqueueWriteBuffer(m_buffer)" ); - } - - m_onGPU = true; - } - - return true; - - } - - bool moveFromGPU() - { - - cl_int err; - - if (m_CPUBuffer->size() > 0) { - if (m_onGPU && !m_readOnlyOnGPU) { - size_t size = m_CPUBuffer->size() * sizeof(ElementType); - err = clEnqueueReadBuffer(m_cqCommandQue, - m_buffer, - CL_TRUE, - 0, - size, - &((*m_CPUBuffer)[0]),0,0,0); - - if( err != CL_SUCCESS ) - { - btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)" ); - } - - m_onGPU = false; - } - } - - return true; - } - - bool copyFromGPU() - { - - cl_int err; - size_t size = m_CPUBuffer->size() * sizeof(ElementType); - - if (m_CPUBuffer->size() > 0) { - if (m_onGPU && !m_readOnlyOnGPU) { - err = clEnqueueReadBuffer(m_cqCommandQue, - m_buffer, - CL_TRUE, - 0,size, - &((*m_CPUBuffer)[0]),0,0,0); - - if( err != CL_SUCCESS ) - { - btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)"); - } - - } - } - - return true; - } - - virtual void changedOnCPU() - { - m_onGPU = false; - } -}; // class btOpenCLBuffer - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h deleted file mode 100644 index 6921f7da..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCL.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_OpenCL.h" - - -#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H -#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H - - -class btSoftBodyLinkDataOpenCL : public btSoftBodyLinkData -{ -public: - bool m_onGPU; - - cl_command_queue m_cqCommandQue; - - - btOpenCLBuffer m_clLinks; - btOpenCLBuffer m_clLinkStrength; - btOpenCLBuffer m_clLinksMassLSC; - btOpenCLBuffer m_clLinksRestLengthSquared; - btOpenCLBuffer m_clLinksCLength; - btOpenCLBuffer m_clLinksLengthRatio; - btOpenCLBuffer m_clLinksRestLength; - btOpenCLBuffer m_clLinksMaterialLinearStiffnessCoefficient; - - struct BatchPair - { - int start; - int length; - - BatchPair() : - start(0), - length(0) - { - } - - BatchPair( int s, int l ) : - start( s ), - length( l ) - { - } - }; - - /** - * Link addressing information for each cloth. - * Allows link locations to be computed independently of data batching. - */ - btAlignedObjectArray< int > m_linkAddresses; - - /** - * Start and length values for computation batches over link data. - */ - btAlignedObjectArray< BatchPair > m_batchStartLengths; - - btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx); - - virtual ~btSoftBodyLinkDataOpenCL(); - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createLinks( int numLinks ); - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setLinkAt( - const LinkDescription &link, - int linkIndex ); - - virtual bool onAccelerator(); - - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(); - - /** - * Generate (and later update) the batching for the entire link set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ - void generateBatches(); -}; - - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h deleted file mode 100644 index b20e8055..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverLinkData_OpenCLSIMDAware.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_OpenCL.h" - - -#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H -#define BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H - - -class btSoftBodyLinkDataOpenCLSIMDAware : public btSoftBodyLinkData -{ -public: - bool m_onGPU; - - cl_command_queue m_cqCommandQue; - - const int m_wavefrontSize; - const int m_linksPerWorkItem; - const int m_maxLinksPerWavefront; - int m_maxBatchesWithinWave; - int m_maxVerticesWithinWave; - int m_numWavefronts; - - int m_maxVertex; - - struct NumBatchesVerticesPair - { - int numBatches; - int numVertices; - }; - - btAlignedObjectArray m_linksPerWavefront; - btAlignedObjectArray m_numBatchesAndVerticesWithinWaves; - btOpenCLBuffer< NumBatchesVerticesPair > m_clNumBatchesAndVerticesWithinWaves; - - // All arrays here will contain batches of m_maxLinksPerWavefront links - // ordered by wavefront. - // with either global vertex pairs or local vertex pairs - btAlignedObjectArray< int > m_wavefrontVerticesGlobalAddresses; // List of global vertices per wavefront - btOpenCLBuffer m_clWavefrontVerticesGlobalAddresses; - btAlignedObjectArray< LinkNodePair > m_linkVerticesLocalAddresses; // Vertex pair for the link - btOpenCLBuffer m_clLinkVerticesLocalAddresses; - btOpenCLBuffer m_clLinkStrength; - btOpenCLBuffer m_clLinksMassLSC; - btOpenCLBuffer m_clLinksRestLengthSquared; - btOpenCLBuffer m_clLinksRestLength; - btOpenCLBuffer m_clLinksMaterialLinearStiffnessCoefficient; - - struct BatchPair - { - int start; - int length; - - BatchPair() : - start(0), - length(0) - { - } - - BatchPair( int s, int l ) : - start( s ), - length( l ) - { - } - }; - - /** - * Link addressing information for each cloth. - * Allows link locations to be computed independently of data batching. - */ - btAlignedObjectArray< int > m_linkAddresses; - - /** - * Start and length values for computation batches over link data. - */ - btAlignedObjectArray< BatchPair > m_wavefrontBatchStartLengths; - - btSoftBodyLinkDataOpenCLSIMDAware(cl_command_queue queue, cl_context ctx); - - virtual ~btSoftBodyLinkDataOpenCLSIMDAware(); - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createLinks( int numLinks ); - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setLinkAt( - const LinkDescription &link, - int linkIndex ); - - virtual bool onAccelerator(); - - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(); - - /** - * Generate (and later update) the batching for the entire link set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ - void generateBatches(); - - int getMaxVerticesPerWavefront() - { - return m_maxVerticesWithinWave; - } - - int getWavefrontSize() - { - return m_wavefrontSize; - } - - int getLinksPerWorkItem() - { - return m_linksPerWorkItem; - } - - int getMaxLinksPerWavefront() - { - return m_maxLinksPerWavefront; - } - - int getMaxBatchesPerWavefront() - { - return m_maxBatchesWithinWave; - } - - int getNumWavefronts() - { - return m_numWavefronts; - } - - NumBatchesVerticesPair getNumBatchesAndVerticesWithinWavefront( int wavefront ) - { - return m_numBatchesAndVerticesWithinWaves[wavefront]; - } - - int getVertexGlobalAddresses( int vertexIndex ) - { - return m_wavefrontVerticesGlobalAddresses[vertexIndex]; - } - - /** - * Get post-batching local addresses of the vertex pair for a link assuming all vertices used by a wavefront are loaded locally. - */ - LinkNodePair getVertexPairLocalAddresses( int linkIndex ) - { - return m_linkVerticesLocalAddresses[linkIndex]; - } -}; - - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_OPENCL_SIMDAWARE_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp deleted file mode 100644 index 1000440b..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "btSoftBodySolverOutputCLtoGL.h" -#include //@todo: remove the debugging printf at some stage -#include "btSoftBodySolver_OpenCL.h" -#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" -#include "btSoftBodySolverVertexBuffer_OpenGL.h" -#include "BulletSoftBody/btSoftBody.h" - -////OpenCL 1.0 kernels don't use float3 -#define MSTRINGIFY(A) #A -static char* OutputToVertexArrayCLString = -#include "OpenCLC10/OutputToVertexArray.cl" - - -#define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }} - -static const size_t workGroupSize = 128; - -void btSoftBodySolverOutputCLtoGL::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) -{ - - btSoftBodySolver *solver = softBody->getSoftBodySolver(); - btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); - btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); - checkInitialized(); - btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); - btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); - - const int firstVertex = currentCloth->getFirstVertex(); - const int lastVertex = firstVertex + currentCloth->getNumVertices(); - - if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::OPENGL_BUFFER ) { - - const btOpenGLInteropVertexBufferDescriptor *openGLVertexBuffer = static_cast< btOpenGLInteropVertexBufferDescriptor* >(vertexBuffer); - cl_int ciErrNum = CL_SUCCESS; - - cl_mem clBuffer = openGLVertexBuffer->getBuffer(); - cl_kernel outputKernel = outputToVertexArrayWithNormalsKernel; - if( !vertexBuffer->hasNormals() ) - outputKernel = outputToVertexArrayWithoutNormalsKernel; - - ciErrNum = clEnqueueAcquireGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, NULL); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); - } - - int numVertices = currentCloth->getNumVertices(); - - ciErrNum = clSetKernelArg(outputKernel, 0, sizeof(int), &firstVertex ); - ciErrNum = clSetKernelArg(outputKernel, 1, sizeof(int), &numVertices ); - ciErrNum = clSetKernelArg(outputKernel, 2, sizeof(cl_mem), (void*)&clBuffer ); - if( vertexBuffer->hasVertexPositions() ) - { - int vertexOffset = vertexBuffer->getVertexOffset(); - int vertexStride = vertexBuffer->getVertexStride(); - ciErrNum = clSetKernelArg(outputKernel, 3, sizeof(int), &vertexOffset ); - ciErrNum = clSetKernelArg(outputKernel, 4, sizeof(int), &vertexStride ); - ciErrNum = clSetKernelArg(outputKernel, 5, sizeof(cl_mem), (void*)&vertexData.m_clVertexPosition.m_buffer ); - - } - if( vertexBuffer->hasNormals() ) - { - int normalOffset = vertexBuffer->getNormalOffset(); - int normalStride = vertexBuffer->getNormalStride(); - ciErrNum = clSetKernelArg(outputKernel, 6, sizeof(int), &normalOffset ); - ciErrNum = clSetKernelArg(outputKernel, 7, sizeof(int), &normalStride ); - ciErrNum = clSetKernelArg(outputKernel, 8, sizeof(cl_mem), (void*)&vertexData.m_clVertexNormal.m_buffer ); - - } - size_t numWorkItems = workGroupSize*((vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, outputKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(copySoftBodyToVertexBuffer)"); - } - - ciErrNum = clEnqueueReleaseGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, 0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "clEnqueueReleaseGLObjects(copySoftBodyToVertexBuffer)"); - } - } else { - btAssert( "Undefined output for this solver output" == false ); - } - - // clFinish in here may not be the best thing. It's possible that we should have a waitForFrameComplete function. - clFinish(m_cqCommandQue); - -} // btSoftBodySolverOutputCLtoGL::outputToVertexBuffers - -bool btSoftBodySolverOutputCLtoGL::buildShaders() -{ - // Ensure current kernels are released first - releaseKernels(); - - bool returnVal = true; - - if( m_shadersInitialized ) - return true; - - outputToVertexArrayWithNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl"); - outputToVertexArrayWithoutNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithoutNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl"); - - - if( returnVal ) - m_shadersInitialized = true; - - return returnVal; -} // btSoftBodySolverOutputCLtoGL::buildShaders - -void btSoftBodySolverOutputCLtoGL::releaseKernels() -{ - RELEASE_CL_KERNEL( outputToVertexArrayWithNormalsKernel ); - RELEASE_CL_KERNEL( outputToVertexArrayWithoutNormalsKernel ); - - m_shadersInitialized = false; -} // btSoftBodySolverOutputCLtoGL::releaseKernels - -bool btSoftBodySolverOutputCLtoGL::checkInitialized() -{ - if( !m_shadersInitialized ) - if( buildShaders() ) - m_shadersInitialized = true; - - return m_shadersInitialized; -} \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h deleted file mode 100644 index ab3ea264..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverOutputCLtoGL.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H -#define BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H - -#include "btSoftBodySolver_OpenCL.h" - -/** - * Class to manage movement of data from a solver to a given target. - * This version is the CL to GL interop version. - */ -class btSoftBodySolverOutputCLtoGL : public btSoftBodySolverOutput -{ -protected: - cl_command_queue m_cqCommandQue; - cl_context m_cxMainContext; - CLFunctions clFunctions; - - cl_kernel outputToVertexArrayWithNormalsKernel; - cl_kernel outputToVertexArrayWithoutNormalsKernel; - - bool m_shadersInitialized; - - virtual bool checkInitialized(); - virtual bool buildShaders(); - void releaseKernels(); -public: - btSoftBodySolverOutputCLtoGL(cl_command_queue cqCommandQue, cl_context cxMainContext) : - m_cqCommandQue( cqCommandQue ), - m_cxMainContext( cxMainContext ), - clFunctions(cqCommandQue, cxMainContext), - outputToVertexArrayWithNormalsKernel( 0 ), - outputToVertexArrayWithoutNormalsKernel( 0 ), - m_shadersInitialized( false ) - { - } - - virtual ~btSoftBodySolverOutputCLtoGL() - { - releaseKernels(); - } - - /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ - virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); -}; - - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_OUTPUT_CL_TO_GL_H \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h deleted file mode 100644 index 7e376785..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverTriangleData_OpenCL.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_OpenCL.h" - - -#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H -#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H - - -class btSoftBodyTriangleDataOpenCL : public btSoftBodyTriangleData -{ -public: - bool m_onGPU; - cl_command_queue m_queue; - - btOpenCLBuffer m_clVertexIndices; - btOpenCLBuffer m_clArea; - btOpenCLBuffer m_clNormal; - - /** - * Link addressing information for each cloth. - * Allows link locations to be computed independently of data batching. - */ - btAlignedObjectArray< int > m_triangleAddresses; - - /** - * Start and length values for computation batches over link data. - */ - struct btSomePair - { - btSomePair() {} - btSomePair(int f,int s) - :first(f),second(s) - { - } - int first; - int second; - }; - btAlignedObjectArray< btSomePair > m_batchStartLengths; - -public: - btSoftBodyTriangleDataOpenCL( cl_command_queue queue, cl_context ctx ); - - virtual ~btSoftBodyTriangleDataOpenCL(); - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createTriangles( int numTriangles ); - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ); - - virtual bool onAccelerator(); - - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(); - - /** - * Generate (and later update) the batching for the entire triangle set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ - void generateBatches(); -}; // class btSoftBodyTriangleDataOpenCL - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_OPENCL_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h deleted file mode 100644 index 7c223ecc..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexBuffer_OpenGL.h +++ /dev/null @@ -1,166 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H -#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H - - -#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" -#ifdef USE_MINICL - #include "MiniCL/cl.h" -#else //USE_MINICL - #ifdef __APPLE__ - #include - #else - #include - #include - #endif //__APPLE__ -#endif//USE_MINICL - - -#ifdef _WIN32//for glut.h -#include -#endif - -//think different -#if defined(__APPLE__) && !defined (VMDMESA) -#include -#include -#include -#include -#else - - -#ifdef _WINDOWS -#include -#include -#include -#else -#include -#endif //_WINDOWS -#endif //APPLE - - - -class btOpenGLInteropVertexBufferDescriptor : public btVertexBufferDescriptor -{ -protected: - /** OpenCL context */ - cl_context m_context; - - /** OpenCL command queue */ - cl_command_queue m_commandQueue; - - /** OpenCL interop buffer */ - cl_mem m_buffer; - - /** VBO in GL that is the basis of the interop buffer */ - GLuint m_openGLVBO; - - -public: - /** - * context is the OpenCL context this interop buffer will work in. - * queue is the command queue that kernels and data movement will be enqueued into. - * openGLVBO is the OpenGL vertex buffer data will be copied into. - * vertexOffset is the offset in floats to the first vertex. - * vertexStride is the stride in floats between vertices. - */ - btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride ) - { -#ifndef USE_MINICL - cl_int ciErrNum = CL_SUCCESS; - m_context = context; - m_commandQueue = cqCommandQue; - - m_vertexOffset = vertexOffset; - m_vertexStride = vertexStride; - - m_openGLVBO = openGLVBO; - - m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); - } - - m_hasVertexPositions = true; -#else - btAssert(0);//MiniCL shouldn't get here -#endif - } - - /** - * context is the OpenCL context this interop buffer will work in. - * queue is the command queue that kernels and data movement will be enqueued into. - * openGLVBO is the OpenGL vertex buffer data will be copied into. - * vertexOffset is the offset in floats to the first vertex. - * vertexStride is the stride in floats between vertices. - * normalOffset is the offset in floats to the first normal. - * normalStride is the stride in floats between normals. - */ - btOpenGLInteropVertexBufferDescriptor( cl_command_queue cqCommandQue, cl_context context, GLuint openGLVBO, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) - { -#ifndef USE_MINICL - cl_int ciErrNum = CL_SUCCESS; - m_context = context; - m_commandQueue = cqCommandQue; - - m_openGLVBO = openGLVBO; - - m_buffer = clCreateFromGLBuffer(m_context, CL_MEM_WRITE_ONLY, openGLVBO, &ciErrNum); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)"); - } - - m_vertexOffset = vertexOffset; - m_vertexStride = vertexStride; - m_hasVertexPositions = true; - - m_normalOffset = normalOffset; - m_normalStride = normalStride; - m_hasNormals = true; -#else - btAssert(0); -#endif //USE_MINICL - - } - - virtual ~btOpenGLInteropVertexBufferDescriptor() - { - clReleaseMemObject( m_buffer ); - } - - /** - * Return the type of the vertex buffer descriptor. - */ - virtual BufferTypes getBufferType() const - { - return OPENGL_BUFFER; - } - - virtual cl_context getContext() const - { - return m_context; - } - - virtual cl_mem getBuffer() const - { - return m_buffer; - } -}; - -#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_OPENGL_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h deleted file mode 100644 index 531c3427..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolverVertexData_OpenCL.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h" -#include "btSoftBodySolverBuffer_OpenCL.h" - -#ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H -#define BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H - - -class btSoftBodyVertexDataOpenCL : public btSoftBodyVertexData -{ -protected: - bool m_onGPU; - cl_command_queue m_queue; - -public: - btOpenCLBuffer m_clClothIdentifier; - btOpenCLBuffer m_clVertexPosition; - btOpenCLBuffer m_clVertexPreviousPosition; - btOpenCLBuffer m_clVertexVelocity; - btOpenCLBuffer m_clVertexForceAccumulator; - btOpenCLBuffer m_clVertexNormal; - btOpenCLBuffer m_clVertexInverseMass; - btOpenCLBuffer m_clVertexArea; - btOpenCLBuffer m_clVertexTriangleCount; -public: - btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx); - - virtual ~btSoftBodyVertexDataOpenCL(); - - virtual bool onAccelerator(); - - virtual bool moveToAccelerator(); - - virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true); -}; - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp deleted file mode 100644 index e5f4ebb2..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.cpp +++ /dev/null @@ -1,1820 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "vectormath/vmInclude.h" -#include //@todo: remove the debugging printf at some stage -#include "btSoftBodySolver_OpenCL.h" -#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" -#include "BulletSoftBody/btSoftBody.h" -#include "BulletSoftBody/btSoftBodyInternals.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "LinearMath/btQuickprof.h" -#include -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - -#define BT_SUPPRESS_OPENCL_ASSERTS - -#ifdef USE_MINICL - #include "MiniCL/cl.h" -#else //USE_MINICL - #ifdef __APPLE__ - #include - #else - #include - #endif //__APPLE__ -#endif//USE_MINICL - -#define BT_DEFAULT_WORKGROUPSIZE 64 - - -#define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }} - - -//CL_VERSION_1_1 seems broken on NVidia SDK so just disable it - -////OpenCL 1.0 kernels don't use float3 -#define MSTRINGIFY(A) #A -static const char* PrepareLinksCLString = -#include "OpenCLC10/PrepareLinks.cl" -static const char* UpdatePositionsFromVelocitiesCLString = -#include "OpenCLC10/UpdatePositionsFromVelocities.cl" -static const char* SolvePositionsCLString = -#include "OpenCLC10/SolvePositions.cl" -static const char* UpdateNodesCLString = -#include "OpenCLC10/UpdateNodes.cl" -static const char* UpdatePositionsCLString = -#include "OpenCLC10/UpdatePositions.cl" -static const char* UpdateConstantsCLString = -#include "OpenCLC10/UpdateConstants.cl" -static const char* IntegrateCLString = -#include "OpenCLC10/Integrate.cl" -static const char* ApplyForcesCLString = -#include "OpenCLC10/ApplyForces.cl" -static const char* UpdateFixedVertexPositionsCLString = -#include "OpenCLC10/UpdateFixedVertexPositions.cl" -static const char* UpdateNormalsCLString = -#include "OpenCLC10/UpdateNormals.cl" -static const char* VSolveLinksCLString = -#include "OpenCLC10/VSolveLinks.cl" -static const char* SolveCollisionsAndUpdateVelocitiesCLString = -#include "OpenCLC10/SolveCollisionsAndUpdateVelocities.cl" - - -btSoftBodyVertexDataOpenCL::btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx) : - m_queue(queue), - m_clClothIdentifier( queue, ctx, &m_clothIdentifier, false ), - m_clVertexPosition( queue, ctx, &m_vertexPosition, false ), - m_clVertexPreviousPosition( queue, ctx, &m_vertexPreviousPosition, false ), - m_clVertexVelocity( queue, ctx, &m_vertexVelocity, false ), - m_clVertexForceAccumulator( queue, ctx, &m_vertexForceAccumulator, false ), - m_clVertexNormal( queue, ctx, &m_vertexNormal, false ), - m_clVertexInverseMass( queue, ctx, &m_vertexInverseMass, false ), - m_clVertexArea( queue, ctx, &m_vertexArea, false ), - m_clVertexTriangleCount( queue, ctx, &m_vertexTriangleCount, false ) -{ -} - -btSoftBodyVertexDataOpenCL::~btSoftBodyVertexDataOpenCL() -{ - -} - -bool btSoftBodyVertexDataOpenCL::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyVertexDataOpenCL::moveToAccelerator() -{ - bool success = true; - success = success && m_clClothIdentifier.moveToGPU(); - success = success && m_clVertexPosition.moveToGPU(); - success = success && m_clVertexPreviousPosition.moveToGPU(); - success = success && m_clVertexVelocity.moveToGPU(); - success = success && m_clVertexForceAccumulator.moveToGPU(); - success = success && m_clVertexNormal.moveToGPU(); - success = success && m_clVertexInverseMass.moveToGPU(); - success = success && m_clVertexArea.moveToGPU(); - success = success && m_clVertexTriangleCount.moveToGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -bool btSoftBodyVertexDataOpenCL::moveFromAccelerator(bool bCopy, bool bCopyMinimum) -{ - bool success = true; - - if (!bCopy) - { - success = success && m_clClothIdentifier.moveFromGPU(); - success = success && m_clVertexPosition.moveFromGPU(); - success = success && m_clVertexPreviousPosition.moveFromGPU(); - success = success && m_clVertexVelocity.moveFromGPU(); - success = success && m_clVertexForceAccumulator.moveFromGPU(); - success = success && m_clVertexNormal.moveFromGPU(); - success = success && m_clVertexInverseMass.moveFromGPU(); - success = success && m_clVertexArea.moveFromGPU(); - success = success && m_clVertexTriangleCount.moveFromGPU(); - } - else - { - if (bCopyMinimum) - { - success = success && m_clVertexPosition.copyFromGPU(); - success = success && m_clVertexNormal.copyFromGPU(); - } - else - { - success = success && m_clClothIdentifier.copyFromGPU(); - success = success && m_clVertexPosition.copyFromGPU(); - success = success && m_clVertexPreviousPosition.copyFromGPU(); - success = success && m_clVertexVelocity.copyFromGPU(); - success = success && m_clVertexForceAccumulator.copyFromGPU(); - success = success && m_clVertexNormal.copyFromGPU(); - success = success && m_clVertexInverseMass.copyFromGPU(); - success = success && m_clVertexArea.copyFromGPU(); - success = success && m_clVertexTriangleCount.copyFromGPU(); - } - } - - if( success ) - m_onGPU = true; - - return success; -} - -btSoftBodyLinkDataOpenCL::btSoftBodyLinkDataOpenCL(cl_command_queue queue, cl_context ctx) -:m_cqCommandQue(queue), - m_clLinks( queue, ctx, &m_links, false ), - m_clLinkStrength( queue, ctx, &m_linkStrength, false ), - m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ), - m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ), - m_clLinksCLength( queue, ctx, &m_linksCLength, false ), - m_clLinksLengthRatio( queue, ctx, &m_linksLengthRatio, false ), - m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ), - m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false ) -{ -} - -btSoftBodyLinkDataOpenCL::~btSoftBodyLinkDataOpenCL() -{ -} - -static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) -{ - Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); - return outVec; -} - -/** Allocate enough space in all link-related arrays to fit numLinks links */ -void btSoftBodyLinkDataOpenCL::createLinks( int numLinks ) -{ - int previousSize = m_links.size(); - int newSize = previousSize + numLinks; - - btSoftBodyLinkData::createLinks( numLinks ); - - // Resize the link addresses array as well - m_linkAddresses.resize( newSize ); -} - -/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ -void btSoftBodyLinkDataOpenCL::setLinkAt( - const LinkDescription &link, - int linkIndex ) -{ - btSoftBodyLinkData::setLinkAt( link, linkIndex ); - - // Set the link index correctly for initialisation - m_linkAddresses[linkIndex] = linkIndex; -} - -bool btSoftBodyLinkDataOpenCL::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyLinkDataOpenCL::moveToAccelerator() -{ - bool success = true; - success = success && m_clLinks.moveToGPU(); - success = success && m_clLinkStrength.moveToGPU(); - success = success && m_clLinksMassLSC.moveToGPU(); - success = success && m_clLinksRestLengthSquared.moveToGPU(); - success = success && m_clLinksCLength.moveToGPU(); - success = success && m_clLinksLengthRatio.moveToGPU(); - success = success && m_clLinksRestLength.moveToGPU(); - success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU(); - - if( success ) { - m_onGPU = true; - } - - return success; -} - -bool btSoftBodyLinkDataOpenCL::moveFromAccelerator() -{ - bool success = true; - success = success && m_clLinks.moveFromGPU(); - success = success && m_clLinkStrength.moveFromGPU(); - success = success && m_clLinksMassLSC.moveFromGPU(); - success = success && m_clLinksRestLengthSquared.moveFromGPU(); - success = success && m_clLinksCLength.moveFromGPU(); - success = success && m_clLinksLengthRatio.moveFromGPU(); - success = success && m_clLinksRestLength.moveFromGPU(); - success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU(); - - if( success ) { - m_onGPU = false; - } - - return success; -} - -/** - * Generate (and later update) the batching for the entire link set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ -void btSoftBodyLinkDataOpenCL::generateBatches() -{ - int numLinks = getNumLinks(); - - // Do the graph colouring here temporarily - btAlignedObjectArray< int > batchValues; - batchValues.resize( numLinks, 0 ); - - // Find the maximum vertex value internally for now - int maxVertex = 0; - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - int vertex0 = getVertexPair(linkIndex).vertex0; - int vertex1 = getVertexPair(linkIndex).vertex1; - if( vertex0 > maxVertex ) - maxVertex = vertex0; - if( vertex1 > maxVertex ) - maxVertex = vertex1; - } - int numVertices = maxVertex + 1; - - // Set of lists, one for each node, specifying which colours are connected - // to that node. - // No two edges into a node can share a colour. - btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; - vertexConnectedColourLists.resize(numVertices); - - // Simple algorithm that chooses the lowest batch number - // that none of the links attached to either of the connected - // nodes is in - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - int linkLocation = m_linkAddresses[linkIndex]; - - int vertex0 = getVertexPair(linkLocation).vertex0; - int vertex1 = getVertexPair(linkLocation).vertex1; - - // Get the two node colour lists - btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); - btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); - - // Choose the minimum colour that is in neither list - int colour = 0; - while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ) - ++colour; - // i should now be the minimum colour in neither list - // Add to the two lists so that future edges don't share - // And store the colour against this edge - - colourListVertex0.push_back(colour); - colourListVertex1.push_back(colour); - batchValues[linkIndex] = colour; - } - - // Check the colour counts - btAlignedObjectArray< int > batchCounts; - for( int i = 0; i < numLinks; ++i ) - { - int batch = batchValues[i]; - if( batch >= batchCounts.size() ) - batchCounts.push_back(1); - else - ++(batchCounts[batch]); - } - - m_batchStartLengths.resize(batchCounts.size()); - if( m_batchStartLengths.size() > 0 ) - { - m_batchStartLengths.resize(batchCounts.size()); - m_batchStartLengths[0] = BatchPair(0, 0); - - int sum = 0; - for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) - { - m_batchStartLengths[batchIndex].start = sum; - m_batchStartLengths[batchIndex].length = batchCounts[batchIndex]; - sum += batchCounts[batchIndex]; - } - } - - ///////////////////////////// - // Sort data based on batches - - // Create source arrays by copying originals - btAlignedObjectArray m_links_Backup(m_links); - btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); - btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); - btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); - btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); - btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); - btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); - btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); - - - for( int batch = 0; batch < batchCounts.size(); ++batch ) - batchCounts[batch] = 0; - - // Do sort as single pass into destination arrays - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - // To maintain locations run off the original link locations rather than the current position. - // It's not cache efficient, but as we run this rarely that should not matter. - // It's faster than searching the link location array for the current location and then updating it. - // The other alternative would be to unsort before resorting, but this is equivalent to doing that. - int linkLocation = m_linkAddresses[linkIndex]; - - // Obtain batch and calculate target location for the - // next element in that batch, incrementing the batch counter - // afterwards - int batch = batchValues[linkIndex]; - int newLocation = m_batchStartLengths[batch].start + batchCounts[batch]; - - batchCounts[batch] = batchCounts[batch] + 1; - m_links[newLocation] = m_links_Backup[linkLocation]; -#if 1 - m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation]; - m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation]; - m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation]; - m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation]; - m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation]; - m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation]; -#endif - // Update the locations array to account for the moved entry - m_linkAddresses[linkIndex] = newLocation; - } - - -} // void generateBatches() - - - - - -btSoftBodyTriangleDataOpenCL::btSoftBodyTriangleDataOpenCL( cl_command_queue queue , cl_context ctx) : - m_queue( queue ), - m_clVertexIndices( queue, ctx, &m_vertexIndices, false ), - m_clArea( queue, ctx, &m_area, false ), - m_clNormal( queue, ctx, &m_normal, false ) -{ -} - -btSoftBodyTriangleDataOpenCL::~btSoftBodyTriangleDataOpenCL() -{ -} - -/** Allocate enough space in all link-related arrays to fit numLinks links */ -void btSoftBodyTriangleDataOpenCL::createTriangles( int numTriangles ) -{ - int previousSize = getNumTriangles(); - int newSize = previousSize + numTriangles; - - btSoftBodyTriangleData::createTriangles( numTriangles ); - - // Resize the link addresses array as well - m_triangleAddresses.resize( newSize ); -} - -/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ -void btSoftBodyTriangleDataOpenCL::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex ) -{ - btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex ); - - m_triangleAddresses[triangleIndex] = triangleIndex; -} - -bool btSoftBodyTriangleDataOpenCL::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyTriangleDataOpenCL::moveToAccelerator() -{ - bool success = true; - success = success && m_clVertexIndices.moveToGPU(); - success = success && m_clArea.moveToGPU(); - success = success && m_clNormal.moveToGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -bool btSoftBodyTriangleDataOpenCL::moveFromAccelerator() -{ - bool success = true; - success = success && m_clVertexIndices.moveFromGPU(); - success = success && m_clArea.moveFromGPU(); - success = success && m_clNormal.moveFromGPU(); - - if( success ) - m_onGPU = true; - - return success; -} - -/** - * Generate (and later update) the batching for the entire triangle set. - * This redoes a lot of work because it batches the entire set when each cloth is inserted. - * In theory we could delay it until just before we need the cloth. - * It's a one-off overhead, though, so that is a later optimisation. - */ -void btSoftBodyTriangleDataOpenCL::generateBatches() -{ - int numTriangles = getNumTriangles(); - if( numTriangles == 0 ) - return; - - // Do the graph colouring here temporarily - btAlignedObjectArray< int > batchValues; - batchValues.resize( numTriangles ); - - // Find the maximum vertex value internally for now - int maxVertex = 0; - for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) - { - int vertex0 = getVertexSet(triangleIndex).vertex0; - int vertex1 = getVertexSet(triangleIndex).vertex1; - int vertex2 = getVertexSet(triangleIndex).vertex2; - - if( vertex0 > maxVertex ) - maxVertex = vertex0; - if( vertex1 > maxVertex ) - maxVertex = vertex1; - if( vertex2 > maxVertex ) - maxVertex = vertex2; - } - int numVertices = maxVertex + 1; - - // Set of lists, one for each node, specifying which colours are connected - // to that node. - // No two edges into a node can share a colour. - btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists; - vertexConnectedColourLists.resize(numVertices); - - - //std::cout << "\n"; - // Simple algorithm that chooses the lowest batch number - // that none of the faces attached to either of the connected - // nodes is in - for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) - { - // To maintain locations run off the original link locations rather than the current position. - // It's not cache efficient, but as we run this rarely that should not matter. - // It's faster than searching the link location array for the current location and then updating it. - // The other alternative would be to unsort before resorting, but this is equivalent to doing that. - int triangleLocation = m_triangleAddresses[triangleIndex]; - - int vertex0 = getVertexSet(triangleLocation).vertex0; - int vertex1 = getVertexSet(triangleLocation).vertex1; - int vertex2 = getVertexSet(triangleLocation).vertex2; - - // Get the three node colour lists - btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] ); - btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] ); - btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] ); - - // Choose the minimum colour that is in none of the lists - int colour = 0; - while( - colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || - colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() || - colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() ) - { - ++colour; - } - // i should now be the minimum colour in neither list - // Add to the three lists so that future edges don't share - // And store the colour against this face - colourListVertex0.push_back(colour); - colourListVertex1.push_back(colour); - colourListVertex2.push_back(colour); - - batchValues[triangleIndex] = colour; - } - - - // Check the colour counts - btAlignedObjectArray< int > batchCounts; - for( int i = 0; i < numTriangles; ++i ) - { - int batch = batchValues[i]; - if( batch >= batchCounts.size() ) - batchCounts.push_back(1); - else - ++(batchCounts[batch]); - } - - - m_batchStartLengths.resize(batchCounts.size()); - m_batchStartLengths[0] = btSomePair(0,0); - - - int sum = 0; - for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex ) - { - m_batchStartLengths[batchIndex].first = sum; - m_batchStartLengths[batchIndex].second = batchCounts[batchIndex]; - sum += batchCounts[batchIndex]; - } - - ///////////////////////////// - // Sort data based on batches - - // Create source arrays by copying originals - btAlignedObjectArray m_vertexIndices_Backup(m_vertexIndices); - btAlignedObjectArray m_area_Backup(m_area); - btAlignedObjectArray m_normal_Backup(m_normal); - - - for( int batch = 0; batch < batchCounts.size(); ++batch ) - batchCounts[batch] = 0; - - // Do sort as single pass into destination arrays - for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex ) - { - // To maintain locations run off the original link locations rather than the current position. - // It's not cache efficient, but as we run this rarely that should not matter. - // It's faster than searching the link location array for the current location and then updating it. - // The other alternative would be to unsort before resorting, but this is equivalent to doing that. - int triangleLocation = m_triangleAddresses[triangleIndex]; - - // Obtain batch and calculate target location for the - // next element in that batch, incrementing the batch counter - // afterwards - int batch = batchValues[triangleIndex]; - int newLocation = m_batchStartLengths[batch].first + batchCounts[batch]; - - batchCounts[batch] = batchCounts[batch] + 1; - m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation]; - m_area[newLocation] = m_area_Backup[triangleLocation]; - m_normal[newLocation] = m_normal_Backup[triangleLocation]; - - // Update the locations array to account for the moved entry - m_triangleAddresses[triangleIndex] = newLocation; - } -} // btSoftBodyTriangleDataOpenCL::generateBatches - - - - - - - -btOpenCLSoftBodySolver::btOpenCLSoftBodySolver(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) : - m_linkData(queue, ctx), - m_vertexData(queue, ctx), - m_triangleData(queue, ctx), - m_defaultCLFunctions(queue, ctx), - m_currentCLFunctions(&m_defaultCLFunctions), - m_clPerClothAcceleration(queue, ctx, &m_perClothAcceleration, true ), - m_clPerClothWindVelocity(queue, ctx, &m_perClothWindVelocity, true ), - m_clPerClothDampingFactor(queue,ctx, &m_perClothDampingFactor, true ), - m_clPerClothVelocityCorrectionCoefficient(queue, ctx,&m_perClothVelocityCorrectionCoefficient, true ), - m_clPerClothLiftFactor(queue, ctx,&m_perClothLiftFactor, true ), - m_clPerClothDragFactor(queue, ctx,&m_perClothDragFactor, true ), - m_clPerClothMediumDensity(queue, ctx,&m_perClothMediumDensity, true ), - m_clPerClothCollisionObjects( queue, ctx, &m_perClothCollisionObjects, true ), - m_clCollisionObjectDetails( queue, ctx, &m_collisionObjectDetails, true ), - m_clPerClothFriction( queue, ctx, &m_perClothFriction, false ), - m_clAnchorPosition( queue, ctx, &m_anchorPosition, true ), - m_clAnchorIndex( queue, ctx, &m_anchorIndex, true), - m_cqCommandQue( queue ), - m_cxMainContext(ctx), - m_defaultWorkGroupSize(BT_DEFAULT_WORKGROUPSIZE), - m_bUpdateAnchoredNodePos(bUpdateAchchoredNodePos) -{ - - // Initial we will clearly need to update solver constants - // For now this is global for the cloths linked with this solver - we should probably make this body specific - // for performance in future once we understand more clearly when constants need to be updated - m_updateSolverConstants = true; - - m_shadersInitialized = false; - - m_prepareLinksKernel = 0; - m_solvePositionsFromLinksKernel = 0; - m_updateConstantsKernel = 0; - m_integrateKernel = 0; - m_addVelocityKernel = 0; - m_updatePositionsFromVelocitiesKernel = 0; - m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = 0; - m_updateVelocitiesFromPositionsWithVelocitiesKernel = 0; - m_vSolveLinksKernel = 0; - m_solveCollisionsAndUpdateVelocitiesKernel = 0; - m_resetNormalsAndAreasKernel = 0; - m_updateSoftBodiesKernel = 0; - m_normalizeNormalsAndAreasKernel = 0; - m_outputToVertexArrayKernel = 0; - m_applyForcesKernel = 0; - m_updateFixedVertexPositionsKernel = 0; -} - -btOpenCLSoftBodySolver::~btOpenCLSoftBodySolver() -{ - releaseKernels(); -} - -void btOpenCLSoftBodySolver::releaseKernels() -{ - RELEASE_CL_KERNEL( m_prepareLinksKernel ); - RELEASE_CL_KERNEL( m_solvePositionsFromLinksKernel ); - RELEASE_CL_KERNEL( m_updateConstantsKernel ); - RELEASE_CL_KERNEL( m_integrateKernel ); - RELEASE_CL_KERNEL( m_addVelocityKernel ); - RELEASE_CL_KERNEL( m_updatePositionsFromVelocitiesKernel ); - RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithoutVelocitiesKernel ); - RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithVelocitiesKernel ); - RELEASE_CL_KERNEL( m_vSolveLinksKernel ); - RELEASE_CL_KERNEL( m_solveCollisionsAndUpdateVelocitiesKernel ); - RELEASE_CL_KERNEL( m_resetNormalsAndAreasKernel ); - RELEASE_CL_KERNEL( m_normalizeNormalsAndAreasKernel ); - RELEASE_CL_KERNEL( m_outputToVertexArrayKernel ); - RELEASE_CL_KERNEL( m_applyForcesKernel ); - RELEASE_CL_KERNEL( m_updateFixedVertexPositionsKernel ); - - m_shadersInitialized = false; -} - -void btOpenCLSoftBodySolver::copyBackToSoftBodies(bool bMove) -{ - - // Move the vertex data back to the host first - m_vertexData.moveFromAccelerator(!bMove); - - // Loop over soft bodies, copying all the vertex positions back for each body in turn - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btOpenCLAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ]; - btSoftBody *softBody = softBodyInterface->getSoftBody(); - - int firstVertex = softBodyInterface->getFirstVertex(); - int numVertices = softBodyInterface->getNumVertices(); - - // Copy vertices from solver back into the softbody - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - using Vectormath::Aos::Point3; - Point3 vertexPosition( m_vertexData.getVertexPositions()[firstVertex + vertex] ); - Point3 normal(m_vertexData.getNormal(firstVertex + vertex)); - - softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() ); - softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() ); - softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() ); - - softBody->m_nodes[vertex].m_n.setX( normal.getX() ); - softBody->m_nodes[vertex].m_n.setY( normal.getY() ); - softBody->m_nodes[vertex].m_n.setZ( normal.getZ() ); - } - } -} // btOpenCLSoftBodySolver::copyBackToSoftBodies - -void btOpenCLSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate ) -{ - if( forceUpdate || m_softBodySet.size() != softBodies.size() ) - { - // Have a change in the soft body set so update, reloading all the data - getVertexData().clear(); - getTriangleData().clear(); - getLinkData().clear(); - m_softBodySet.resize(0); - m_anchorIndex.clear(); - - int maxPiterations = 0; - int maxViterations = 0; - - for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) - { - btSoftBody *softBody = softBodies[ softBodyIndex ]; - using Vectormath::Aos::Matrix3; - using Vectormath::Aos::Point3; - - // Create SoftBody that will store the information within the solver - btOpenCLAcceleratedSoftBodyInterface *newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody ); - m_softBodySet.push_back( newSoftBody ); - - m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); - m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); - m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); - m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); - m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); - m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); - // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time - m_perClothFriction.push_back(softBody->m_cfg.kDF); - m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); - - // Add space for new vertices and triangles in the default solver for now - // TODO: Include space here for tearing too later - int firstVertex = getVertexData().getNumVertices(); - int numVertices = softBody->m_nodes.size(); - int maxVertices = numVertices; - // Allocate space for new vertices in all the vertex arrays - getVertexData().createVertices( maxVertices, softBodyIndex ); - - int firstTriangle = getTriangleData().getNumTriangles(); - int numTriangles = softBody->m_faces.size(); - int maxTriangles = numTriangles; - getTriangleData().createTriangles( maxTriangles ); - - // Copy vertices from softbody into the solver - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); - btSoftBodyVertexData::VertexDescription desc; - - // TODO: Position in the softbody might be pre-transformed - // or we may need to adapt for the pose. - //desc.setPosition( cloth.getMeshTransform()*multPoint ); - desc.setPosition( multPoint ); - - float vertexInverseMass = softBody->m_nodes[vertex].m_im; - desc.setInverseMass(vertexInverseMass); - getVertexData().setVertexAt( desc, firstVertex + vertex ); - - m_anchorIndex.push_back(-1); - } - - // Copy triangles similarly - // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene - for( int triangle = 0; triangle < numTriangles; ++triangle ) - { - // Note that large array storage is relative to the array not to the cloth - // So we need to add firstVertex to each value - int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); - int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); - int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); - btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); - getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); - - // Increase vertex triangle counts for this triangle - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; - } - - int firstLink = getLinkData().getNumLinks(); - int numLinks = softBody->m_links.size(); -// int maxLinks = numLinks; - - // Allocate space for the links - getLinkData().createLinks( numLinks ); - - // Add the links - for( int link = 0; link < numLinks; ++link ) - { - int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); - int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); - - btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); - newLink.setLinkStrength(1.f); - getLinkData().setLinkAt(newLink, firstLink + link); - } - - newSoftBody->setFirstVertex( firstVertex ); - newSoftBody->setFirstTriangle( firstTriangle ); - newSoftBody->setNumVertices( numVertices ); - newSoftBody->setMaxVertices( maxVertices ); - newSoftBody->setNumTriangles( numTriangles ); - newSoftBody->setMaxTriangles( maxTriangles ); - newSoftBody->setFirstLink( firstLink ); - newSoftBody->setNumLinks( numLinks ); - - // Find maximum piterations and viterations - int piterations = softBody->m_cfg.piterations; - - if ( piterations > maxPiterations ) - maxPiterations = piterations; - - int viterations = softBody->m_cfg.viterations; - - if ( viterations > maxViterations ) - maxViterations = viterations; - - // zero mass - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - if ( softBody->m_nodes[vertex].m_im == 0 ) - { - AnchorNodeInfoCL nodeInfo; - nodeInfo.clVertexIndex = firstVertex + vertex; - nodeInfo.pNode = &softBody->m_nodes[vertex]; - - m_anchorNodeInfoArray.push_back(nodeInfo); - } - } - - // anchor position - if ( numVertices > 0 ) - { - for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ ) - { - btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node; - btSoftBody::Node* firstNode = &softBody->m_nodes[0]; - - AnchorNodeInfoCL nodeInfo; - nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode); - nodeInfo.pNode = anchorNode; - - m_anchorNodeInfoArray.push_back(nodeInfo); - } - } - } - - - m_anchorPosition.clear(); - m_anchorPosition.resize(m_anchorNodeInfoArray.size()); - - for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ ) - { - const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode]; - m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode; - getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f; - } - - updateConstants(0.f); - - // set position and velocity iterations - setNumberOfPositionIterations(maxPiterations); - setNumberOfVelocityIterations(maxViterations); - - // set wind velocity - m_perClothWindVelocity.resize( m_softBodySet.size() ); - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); - m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); - } - - m_clPerClothWindVelocity.changedOnCPU(); - - // generate batches - m_linkData.generateBatches(); - m_triangleData.generateBatches(); - - // Build the shaders to match the batching parameters - buildShaders(); - } -} - - -btSoftBodyLinkData &btOpenCLSoftBodySolver::getLinkData() -{ - // TODO: Consider setting link data to "changed" here - return m_linkData; -} - -btSoftBodyVertexData &btOpenCLSoftBodySolver::getVertexData() -{ - // TODO: Consider setting vertex data to "changed" here - return m_vertexData; -} - -btSoftBodyTriangleData &btOpenCLSoftBodySolver::getTriangleData() -{ - // TODO: Consider setting triangle data to "changed" here - return m_triangleData; -} - -void btOpenCLSoftBodySolver::resetNormalsAndAreas( int numVertices ) -{ - cl_int ciErrNum; - ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 0, sizeof(numVertices), (void*)&numVertices); //oclCHECKERROR(ciErrNum, CL_SUCCESS); - ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 1, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexNormal.m_buffer);//oclCHECKERROR(ciErrNum, CL_SUCCESS); - ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 2, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexArea.m_buffer); //oclCHECKERROR(ciErrNum, CL_SUCCESS); - size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_resetNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0 ); - - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_resetNormalsAndAreasKernel)" ); - } - } - -} - -void btOpenCLSoftBodySolver::normalizeNormalsAndAreas( int numVertices ) -{ - cl_int ciErrNum; - - ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 0, sizeof(int),(void*) &numVertices); - ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 1, sizeof(cl_mem), &m_vertexData.m_clVertexTriangleCount.m_buffer); - ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); - ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); - size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_normalizeNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)"); - } - } - -} - -void btOpenCLSoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles ) -{ - cl_int ciErrNum; - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 0, sizeof(int), (void*) &firstTriangle); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 1, sizeof(int), &numTriangles); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 2, sizeof(cl_mem), &m_triangleData.m_clVertexIndices.m_buffer); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 6, sizeof(cl_mem), &m_triangleData.m_clNormal.m_buffer); - ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 7, sizeof(cl_mem), &m_triangleData.m_clArea.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((numTriangles + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_updateSoftBodiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)"); - } - -} - -void btOpenCLSoftBodySolver::updateSoftBodies() -{ - using namespace Vectormath::Aos; - - - int numVertices = m_vertexData.getNumVertices(); -// int numTriangles = m_triangleData.getNumTriangles(); - - // Ensure data is on accelerator - m_vertexData.moveToAccelerator(); - m_triangleData.moveToAccelerator(); - - resetNormalsAndAreas( numVertices ); - - - // Go through triangle batches so updates occur correctly - for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex ) - { - - int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].first; - int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].second; - - executeUpdateSoftBodies( startTriangle, numTriangles ); - } - - - normalizeNormalsAndAreas( numVertices ); -} // updateSoftBodies - - -Vectormath::Aos::Vector3 btOpenCLSoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ) -{ - return a*Vectormath::Aos::dot(v, a); -} - -void btOpenCLSoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ) -{ - float dtInverseMass = solverdt*inverseMass; - if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) ) - { - vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass; - } else { - vertexForce += force; - } -} - -void btOpenCLSoftBodySolver::updateFixedVertexPositions() -{ - // Ensure data is on accelerator - m_vertexData.moveToAccelerator(); - m_clAnchorPosition.moveToGPU(); - m_clAnchorIndex.moveToGPU(); - - cl_int ciErrNum ; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel, 0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,1, sizeof(cl_mem), &m_clAnchorIndex.m_buffer); - ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,3, sizeof(cl_mem), &m_clAnchorPosition.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateFixedVertexPositionsKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_updateFixedVertexPositionsKernel)"); - } - } - -} - -void btOpenCLSoftBodySolver::applyForces( float solverdt ) -{ - // Ensure data is on accelerator - m_vertexData.moveToAccelerator(); - m_clPerClothAcceleration.moveToGPU(); - m_clPerClothLiftFactor.moveToGPU(); - m_clPerClothDragFactor.moveToGPU(); - m_clPerClothMediumDensity.moveToGPU(); - m_clPerClothWindVelocity.moveToGPU(); - - cl_int ciErrNum ; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 1, sizeof(float), &solverdt); - float fl = FLT_EPSILON; - ciErrNum = clSetKernelArg(m_applyForcesKernel, 2, sizeof(float), &fl); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 7, sizeof(cl_mem), &m_clPerClothLiftFactor.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 8 ,sizeof(cl_mem), &m_clPerClothDragFactor.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel, 9, sizeof(cl_mem), &m_clPerClothWindVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel,10, sizeof(cl_mem), &m_clPerClothAcceleration.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel,11, sizeof(cl_mem), &m_clPerClothMediumDensity.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel,12, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); - ciErrNum = clSetKernelArg(m_applyForcesKernel,13, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_applyForcesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_applyForcesKernel)"); - } - } - -} - -/** - * Integrate motion on the solver. - */ -void btOpenCLSoftBodySolver::integrate( float solverdt ) -{ - // Ensure data is on accelerator - m_vertexData.moveToAccelerator(); - - cl_int ciErrNum; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_integrateKernel, 0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_integrateKernel, 1, sizeof(float), &solverdt); - ciErrNum = clSetKernelArg(m_integrateKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); - ciErrNum = clSetKernelArg(m_integrateKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - ciErrNum = clSetKernelArg(m_integrateKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_integrateKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_integrateKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_integrateKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_integrateKernel)"); - } - } - -} - -float btOpenCLSoftBodySolver::computeTriangleArea( - const Vectormath::Aos::Point3 &vertex0, - const Vectormath::Aos::Point3 &vertex1, - const Vectormath::Aos::Point3 &vertex2 ) -{ - Vectormath::Aos::Vector3 a = vertex1 - vertex0; - Vectormath::Aos::Vector3 b = vertex2 - vertex0; - Vectormath::Aos::Vector3 crossProduct = cross(a, b); - float area = length( crossProduct ); - return area; -} - - -void btOpenCLSoftBodySolver::updateBounds() -{ - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btVector3 minBound(-1e30,-1e30,-1e30), maxBound(1e30,1e30,1e30); - m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound ); - } - -} // btOpenCLSoftBodySolver::updateBounds - - -void btOpenCLSoftBodySolver::updateConstants( float timeStep ) -{ - - using namespace Vectormath::Aos; - - if( m_updateSolverConstants ) - { - m_updateSolverConstants = false; - - // Will have to redo this if we change the structure (tear, maybe) or various other possible changes - - // Initialise link constants - const int numLinks = m_linkData.getNumLinks(); - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); - m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); - float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); - float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); - float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); - float massLSC = (invMass0 + invMass1)/linearStiffness; - m_linkData.getMassLSC(linkIndex) = massLSC; - float restLength = m_linkData.getRestLength(linkIndex); - float restLengthSquared = restLength*restLength; - m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; - } - } - -} - -class QuickSortCompare -{ - public: - - bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const - { - return ( a.softBodyIdentifier < b.softBodyIdentifier ); - } -}; - - -/** - * Sort the collision object details array and generate indexing into it for the per-cloth collision object array. - */ -void btOpenCLSoftBodySolver::prepareCollisionConstraints() -{ - // First do a simple sort on the collision objects - btAlignedObjectArray numObjectsPerClothPrefixSum; - btAlignedObjectArray numObjectsPerCloth; - numObjectsPerCloth.resize( m_softBodySet.size(), 0 ); - numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 ); - - - - m_collisionObjectDetails.quickSort( QuickSortCompare() ); - - if (!m_perClothCollisionObjects.size()) - return; - - // Generating indexing for perClothCollisionObjects - // First clear the previous values with the "no collision object for cloth" constant - for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex ) - { - m_perClothCollisionObjects[clothIndex].firstObject = -1; - m_perClothCollisionObjects[clothIndex].endObject = -1; - } - int currentCloth = 0; - int startIndex = 0; - for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject ) - { - int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier; - if( nextCloth != currentCloth ) - { - // Changed cloth in the array - // Set the end index and the range is what we need for currentCloth - m_perClothCollisionObjects[currentCloth].firstObject = startIndex; - m_perClothCollisionObjects[currentCloth].endObject = collisionObject; - currentCloth = nextCloth; - startIndex = collisionObject; - } - } - - // And update last cloth - m_perClothCollisionObjects[currentCloth].firstObject = startIndex; - m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size(); - -} // btOpenCLSoftBodySolver::prepareCollisionConstraints - - - -void btOpenCLSoftBodySolver::solveConstraints( float solverdt ) -{ - - using Vectormath::Aos::Vector3; - using Vectormath::Aos::Point3; - using Vectormath::Aos::lengthSqr; - using Vectormath::Aos::dot; - - // Prepare links -// int numLinks = m_linkData.getNumLinks(); -// int numVertices = m_vertexData.getNumVertices(); - - float kst = 1.f; - float ti = 0.f; - - - m_clPerClothDampingFactor.moveToGPU(); - m_clPerClothVelocityCorrectionCoefficient.moveToGPU(); - - - // Ensure data is on accelerator - m_linkData.moveToAccelerator(); - m_vertexData.moveToAccelerator(); - - prepareLinks(); - - - - for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration ) - { - for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) - { - int startLink = m_linkData.m_batchStartLengths[i].start; - int numLinks = m_linkData.m_batchStartLengths[i].length; - - solveLinksForVelocity( startLink, numLinks, kst ); - } - } - - - prepareCollisionConstraints(); - - // Compute new positions from velocity - // Also update the previous position so that our position computation is now based on the new position from the velocity solution - // rather than based directly on the original positions - if( m_numberOfVelocityIterations > 0 ) - { - updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt ); - } else { - updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt ); - } - - // Solve position - for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - { - for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i ) - { - int startLink = m_linkData.m_batchStartLengths[i].start; - int numLinks = m_linkData.m_batchStartLengths[i].length; - - solveLinksForPosition( startLink, numLinks, kst, ti ); - } - - } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - - - // At this point assume that the force array is blank - we will overwrite it - solveCollisionsAndUpdateVelocities( 1.f/solverdt ); - -} - - -////////////////////////////////////// -// Kernel dispatches -void btOpenCLSoftBodySolver::prepareLinks() -{ - cl_int ciErrNum; - int numLinks = m_linkData.getNumLinks(); - ciErrNum = clSetKernelArg(m_prepareLinksKernel,0, sizeof(int), &numLinks); - ciErrNum = clSetKernelArg(m_prepareLinksKernel,1, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); - ciErrNum = clSetKernelArg(m_prepareLinksKernel,2, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); - ciErrNum = clSetKernelArg(m_prepareLinksKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_prepareLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer); - ciErrNum = clSetKernelArg(m_prepareLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_linkData.getNumLinks() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_prepareLinksKernel, 1 , NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_prepareLinksKernel)"); - } - -} - -void btOpenCLSoftBodySolver::updatePositionsFromVelocities( float solverdt ) -{ - cl_int ciErrNum; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,1, sizeof(float), &solverdt); - ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,4, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updatePositionsFromVelocitiesKernel, 1, NULL, &numWorkItems,&m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_updatePositionsFromVelocitiesKernel)"); - } - -} - -void btOpenCLSoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti ) -{ - cl_int ciErrNum; - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startLink); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numLinks); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&m_defaultWorkGroupSize,0,0,0); - if( ciErrNum!= CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)"); - } - -} // solveLinksForPosition - - -void btOpenCLSoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst ) -{ - cl_int ciErrNum; - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 0, sizeof(int), &startLink); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 1, sizeof(int), &numLinks); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 2, sizeof(float), &kst); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 3, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); - ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_vSolveLinksKernel,1,NULL,&numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_vSolveLinksKernel)"); - } - -} - -void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt ) -{ - cl_int ciErrNum; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel,0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, sizeof(float), &isolverdt); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 5, sizeof(cl_mem), &m_clPerClothVelocityCorrectionCoefficient.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 6, sizeof(cl_mem), &m_clPerClothDampingFactor.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 8, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithVelocitiesKernel)"); - } - - -} // updateVelocitiesFromPositionsWithVelocities - -void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ) -{ - cl_int ciErrNum; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, sizeof(float), &isolverdt); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 4, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 6, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 7, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)"); - } - -} // updateVelocitiesFromPositionsWithoutVelocities - - - -void btOpenCLSoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt ) -{ - // Copy kernel parameters to GPU - m_vertexData.moveToAccelerator(); - m_clPerClothFriction.moveToGPU(); - m_clPerClothDampingFactor.moveToGPU(); - m_clPerClothCollisionObjects.moveToGPU(); - m_clCollisionObjectDetails.moveToGPU(); - - cl_int ciErrNum; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); - - size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize); - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0); - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)"); - } - } - -} // btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities - - - -// End kernel dispatches -///////////////////////////////////// - - -void btSoftBodySolverOutputCLtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) -{ - - btSoftBodySolver *solver = softBody->getSoftBodySolver(); - btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER ); - btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver ); - - btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody ); - btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData ); - - - const int firstVertex = currentCloth->getFirstVertex(); - const int lastVertex = firstVertex + currentCloth->getNumVertices(); - - if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) - { - const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); - float *basePointer = cpuVertexBuffer->getBasePointer(); - - vertexData.m_clVertexPosition.copyFromGPU(); - vertexData.m_clVertexNormal.copyFromGPU(); - - if( vertexBuffer->hasVertexPositions() ) - { - const int vertexOffset = cpuVertexBuffer->getVertexOffset(); - const int vertexStride = cpuVertexBuffer->getVertexStride(); - float *vertexPointer = basePointer + vertexOffset; - - for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) - { - Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex); - *(vertexPointer + 0) = position.getX(); - *(vertexPointer + 1) = position.getY(); - *(vertexPointer + 2) = position.getZ(); - vertexPointer += vertexStride; - } - } - if( vertexBuffer->hasNormals() ) - { - const int normalOffset = cpuVertexBuffer->getNormalOffset(); - const int normalStride = cpuVertexBuffer->getNormalStride(); - float *normalPointer = basePointer + normalOffset; - - for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex ) - { - Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex); - *(normalPointer + 0) = normal.getX(); - *(normalPointer + 1) = normal.getY(); - *(normalPointer + 2) = normal.getZ(); - normalPointer += normalStride; - } - } - } - -} // btSoftBodySolverOutputCLtoCPU::outputToVertexBuffers - - - -cl_kernel CLFunctions::compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros ,const char* orgSrcFileNameForCaching) -{ - printf("compiling kernelName: %s ",kernelName); - cl_kernel kernel=0; - cl_int ciErrNum; - size_t program_length = strlen(kernelSource); - - cl_program m_cpProgram = clCreateProgramWithSource(m_cxMainContext, 1, (const char**)&kernelSource, &program_length, &ciErrNum); -// oclCHECKERROR(ciErrNum, CL_SUCCESS); - - // Build the program with 'mad' Optimization option - - -#ifdef MAC - char* flags = "-cl-mad-enable -DMAC -DGUID_ARG"; -#else - //const char* flags = "-DGUID_ARG= -fno-alias"; - const char* flags = "-DGUID_ARG= "; -#endif - - char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5]; - sprintf(compileFlags, "%s %s", flags, additionalMacros); - ciErrNum = clBuildProgram(m_cpProgram, 0, NULL, compileFlags, NULL, NULL); - if (ciErrNum != CL_SUCCESS) - { - size_t numDevices; - clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, 0, 0, &numDevices ); - cl_device_id *devices = new cl_device_id[numDevices]; - clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, numDevices, devices, &numDevices ); - for( int i = 0; i < 2; ++i ) - { - char *build_log; - size_t ret_val_size; - clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); - build_log = new char[ret_val_size+1]; - clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL); - - // to be carefully, terminate with \0 - // there's no information in the reference whether the string is 0 terminated or not - build_log[ret_val_size] = '\0'; - - - printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log); - delete[] build_log; - } -#ifndef BT_SUPPRESS_OPENCL_ASSERTS - btAssert(0); -#endif //BT_SUPPRESS_OPENCL_ASSERTS - m_kernelCompilationFailures++; - return 0; - } - - - // Create the kernel - kernel = clCreateKernel(m_cpProgram, kernelName, &ciErrNum); - if (ciErrNum != CL_SUCCESS) - { - const char* msg = ""; - switch(ciErrNum) - { - case CL_INVALID_PROGRAM: - msg = "Program is not a valid program object."; - break; - case CL_INVALID_PROGRAM_EXECUTABLE: - msg = "There is no successfully built executable for program."; - break; - case CL_INVALID_KERNEL_NAME: - msg = "kernel_name is not found in program."; - break; - case CL_INVALID_KERNEL_DEFINITION: - msg = "the function definition for __kernel function given by kernel_name such as the number of arguments, the argument types are not the same for all devices for which the program executable has been built."; - break; - case CL_INVALID_VALUE: - msg = "kernel_name is NULL."; - break; - case CL_OUT_OF_HOST_MEMORY: - msg = "Failure to allocate resources required by the OpenCL implementation on the host."; - break; - default: - { - } - } - - printf("Error in clCreateKernel for kernel '%s', error is \"%s\", Line %u in file %s !!!\n\n", kernelName, msg, __LINE__, __FILE__); - -#ifndef BT_SUPPRESS_OPENCL_ASSERTS - btAssert(0); -#endif //BT_SUPPRESS_OPENCL_ASSERTS - m_kernelCompilationFailures++; - return 0; - } - - printf("ready. \n"); - delete [] compileFlags; - if (!kernel) - m_kernelCompilationFailures++; - return kernel; - -} - -void btOpenCLSoftBodySolver::predictMotion( float timeStep ) -{ - // Clear the collision shape array for the next frame - // Ensure that the DX11 ones are moved off the device so they will be updated correctly - m_clCollisionObjectDetails.changedOnCPU(); - m_clPerClothCollisionObjects.changedOnCPU(); - m_collisionObjectDetails.clear(); - - if ( m_bUpdateAnchoredNodePos ) - { - // In OpenCL cloth solver, if softbody node has zero inverse mass(infinite mass) or anchor attached, - // we need to update the node position in case the node or anchor is animated externally. - // If there is no such node, we can eliminate the unnecessary CPU-to-GPU data trasferring. - for ( int i = 0; i < m_anchorNodeInfoArray.size(); i++ ) - { - const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[i]; - btSoftBody::Node* node = anchorNodeInfo.pNode; - - using Vectormath::Aos::Point3; - Point3 pos((float)node->m_x.getX(), (float)node->m_x.getY(), (float)node->m_x.getZ()); - m_anchorPosition[i] = pos; - } - - if ( m_anchorNodeInfoArray.size() > 0 ) - m_clAnchorPosition.changedOnCPU(); - - updateFixedVertexPositions(); - } - - { - BT_PROFILE("applyForces"); - // Apply forces that we know about to the cloths - applyForces( timeStep * getTimeScale() ); - } - - { - BT_PROFILE("integrate"); - // Itegrate motion for all soft bodies dealt with by the solver - integrate( timeStep * getTimeScale() ); - } - - { - BT_PROFILE("updateBounds"); - updateBounds(); - } - // End prediction work for solvers -} - -static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) -{ - Vectormath::Aos::Transform3 outTransform; - outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); - outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); - outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); - outTransform.setCol(3, toVector3(transform.getOrigin())); - return outTransform; -} - -void btOpenCLAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ) -{ - float scalarMargin = (float)getSoftBody()->getCollisionShape()->getMargin(); - btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin ); - m_softBody->m_bounds[0] = lowerBound - vectorMargin; - m_softBody->m_bounds[1] = upperBound + vectorMargin; -} // btOpenCLSoftBodySolver::btDX11AcceleratedSoftBodyInterface::updateBounds - -void btOpenCLSoftBodySolver::processCollision( btSoftBody*, btSoftBody* ) -{ - -} - -// Add the collision object to the set to deal with for a particular soft body -void btOpenCLSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObject ) -{ - int softBodyIndex = findSoftBodyIndex( softBody ); - - if( softBodyIndex >= 0 ) - { - const btCollisionShape *collisionShape = collisionObject->getCollisionShape(); - float friction = collisionObject->getCollisionObject()->getFriction(); - int shapeType = collisionShape->getShapeType(); - if( shapeType == CAPSULE_SHAPE_PROXYTYPE ) - { - // Add to the list of expected collision objects - CollisionShapeDescription newCollisionShapeDescription; - newCollisionShapeDescription.softBodyIdentifier = softBodyIndex; - newCollisionShapeDescription.collisionShapeType = shapeType; - // TODO: May need to transpose this matrix either here or in HLSL - newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform()); - const btCapsuleShape *capsule = static_cast( collisionShape ); - newCollisionShapeDescription.radius = capsule->getRadius(); - newCollisionShapeDescription.halfHeight = capsule->getHalfHeight(); - newCollisionShapeDescription.margin = capsule->getMargin(); - newCollisionShapeDescription.upAxis = capsule->getUpAxis(); - newCollisionShapeDescription.friction = friction; - const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() ); - newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity()); - newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity()); - m_collisionObjectDetails.push_back( newCollisionShapeDescription ); - - } - else { -#ifdef _DEBUG - printf("Unsupported collision shape type\n"); -#endif - //btAssert(0 && "Unsupported collision shape type\n"); - } - } else { - btAssert(0 && "Unknown soft body"); - } -} // btOpenCLSoftBodySolver::processCollision - - - - - -btOpenCLAcceleratedSoftBodyInterface* btOpenCLSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) -{ - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex]; - if( softBodyInterface->getSoftBody() == softBody ) - return softBodyInterface; - } - return 0; -} - - -int btOpenCLSoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody ) -{ - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex]; - if( softBodyInterface->getSoftBody() == softBody ) - return softBodyIndex; - } - return 1; -} - -bool btOpenCLSoftBodySolver::checkInitialized() -{ - if( !m_shadersInitialized ) - if( buildShaders() ) - m_shadersInitialized = true; - - return m_shadersInitialized; -} - -bool btOpenCLSoftBodySolver::buildShaders() -{ - if( m_shadersInitialized ) - return true; - - const char* additionalMacros=""; - - // Ensure current kernels are released first - releaseKernels(); - - m_currentCLFunctions->clearKernelCompilationFailures(); - - m_prepareLinksKernel = m_currentCLFunctions->compileCLKernelFromString( PrepareLinksCLString, "PrepareLinksKernel",additionalMacros,"OpenCLC10/PrepareLinks.cl" ); - m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl"); - m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel",additionalMacros,"OpenCLC10/SolvePositions.cl" ); - m_vSolveLinksKernel = m_currentCLFunctions->compileCLKernelFromString( VSolveLinksCLString, "VSolveLinksKernel" ,additionalMacros,"OpenCLC10/VSolveLinks.cl"); - m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdateNodes.cl"); - m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositions.cl"); - m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel" ,additionalMacros,"OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"); - m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel" ,additionalMacros,"OpenCLC10/Integrate.cl"); - m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel" ,additionalMacros,"OpenCLC10/ApplyForces.cl"); - m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" , additionalMacros, "OpenCLC10/UpdateFixedVertexPositions.cl"); - - // TODO: Rename to UpdateSoftBodies - m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); - m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); - m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl"); - - - if( m_currentCLFunctions->getKernelCompilationFailures()==0 ) - m_shadersInitialized = true; - - return m_shadersInitialized; -} - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h deleted file mode 100644 index 6de58c4f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCL.h +++ /dev/null @@ -1,527 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_OPENCL_H -#define BT_SOFT_BODY_SOLVER_OPENCL_H - -#include "stddef.h" //for size_t -#include "vectormath/vmInclude.h" - -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "BulletSoftBody/btSoftBody.h" -#include "btSoftBodySolverBuffer_OpenCL.h" -#include "btSoftBodySolverLinkData_OpenCL.h" -#include "btSoftBodySolverVertexData_OpenCL.h" -#include "btSoftBodySolverTriangleData_OpenCL.h" - -class CLFunctions -{ -protected: - cl_command_queue m_cqCommandQue; - cl_context m_cxMainContext; - - int m_kernelCompilationFailures; - - -public: - CLFunctions(cl_command_queue cqCommandQue, cl_context cxMainContext) : - m_cqCommandQue( cqCommandQue ), - m_cxMainContext( cxMainContext ), - m_kernelCompilationFailures(0) - { - } - - int getKernelCompilationFailures() const - { - return m_kernelCompilationFailures; - } - - /** - * Compile a compute shader kernel from a string and return the appropriate cl_kernel object. - */ - virtual cl_kernel compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros, const char* srcFileNameForCaching); - - void clearKernelCompilationFailures() - { - m_kernelCompilationFailures=0; - } -}; - -/** - * Entry in the collision shape array. - * Specifies the shape type, the transform matrix and the necessary details of the collisionShape. - */ -struct CollisionShapeDescription -{ - Vectormath::Aos::Transform3 shapeTransform; - Vectormath::Aos::Vector3 linearVelocity; - Vectormath::Aos::Vector3 angularVelocity; - - int softBodyIdentifier; - int collisionShapeType; - - // Both needed for capsule - float radius; - float halfHeight; - int upAxis; - - float margin; - float friction; - - CollisionShapeDescription() - { - collisionShapeType = 0; - margin = 0; - friction = 0; - } -}; - -/** - * SoftBody class to maintain information about a soft body instance - * within a solver. - * This data addresses the main solver arrays. - */ -class btOpenCLAcceleratedSoftBodyInterface -{ -protected: - /** Current number of vertices that are part of this cloth */ - int m_numVertices; - /** Maximum number of vertices allocated to be part of this cloth */ - int m_maxVertices; - /** Current number of triangles that are part of this cloth */ - int m_numTriangles; - /** Maximum number of triangles allocated to be part of this cloth */ - int m_maxTriangles; - /** Index of first vertex in the world allocated to this cloth */ - int m_firstVertex; - /** Index of first triangle in the world allocated to this cloth */ - int m_firstTriangle; - /** Index of first link in the world allocated to this cloth */ - int m_firstLink; - /** Maximum number of links allocated to this cloth */ - int m_maxLinks; - /** Current number of links allocated to this cloth */ - int m_numLinks; - - /** The actual soft body this data represents */ - btSoftBody *m_softBody; - - -public: - btOpenCLAcceleratedSoftBodyInterface( btSoftBody *softBody ) : - m_softBody( softBody ) - { - m_numVertices = 0; - m_maxVertices = 0; - m_numTriangles = 0; - m_maxTriangles = 0; - m_firstVertex = 0; - m_firstTriangle = 0; - m_firstLink = 0; - m_maxLinks = 0; - m_numLinks = 0; - } - int getNumVertices() - { - return m_numVertices; - } - - int getNumTriangles() - { - return m_numTriangles; - } - - int getMaxVertices() - { - return m_maxVertices; - } - - int getMaxTriangles() - { - return m_maxTriangles; - } - - int getFirstVertex() - { - return m_firstVertex; - } - - int getFirstTriangle() - { - return m_firstTriangle; - } - - /** - * Update the bounds in the btSoftBody object - */ - void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound ); - - // TODO: All of these set functions will have to do checks and - // update the world because restructuring of the arrays will be necessary - // Reasonable use of "friend"? - void setNumVertices( int numVertices ) - { - m_numVertices = numVertices; - } - - void setNumTriangles( int numTriangles ) - { - m_numTriangles = numTriangles; - } - - void setMaxVertices( int maxVertices ) - { - m_maxVertices = maxVertices; - } - - void setMaxTriangles( int maxTriangles ) - { - m_maxTriangles = maxTriangles; - } - - void setFirstVertex( int firstVertex ) - { - m_firstVertex = firstVertex; - } - - void setFirstTriangle( int firstTriangle ) - { - m_firstTriangle = firstTriangle; - } - - void setMaxLinks( int maxLinks ) - { - m_maxLinks = maxLinks; - } - - void setNumLinks( int numLinks ) - { - m_numLinks = numLinks; - } - - void setFirstLink( int firstLink ) - { - m_firstLink = firstLink; - } - - int getMaxLinks() - { - return m_maxLinks; - } - - int getNumLinks() - { - return m_numLinks; - } - - int getFirstLink() - { - return m_firstLink; - } - - btSoftBody* getSoftBody() - { - return m_softBody; - } - -}; - - - -class btOpenCLSoftBodySolver : public btSoftBodySolver -{ -public: - - - struct UIntVector3 - { - UIntVector3() - { - x = 0; - y = 0; - z = 0; - _padding = 0; - } - - UIntVector3( unsigned int x_, unsigned int y_, unsigned int z_ ) - { - x = x_; - y = y_; - z = z_; - _padding = 0; - } - - unsigned int x; - unsigned int y; - unsigned int z; - unsigned int _padding; - }; - - struct CollisionObjectIndices - { - CollisionObjectIndices( int f, int e ) - { - firstObject = f; - endObject = e; - } - - int firstObject; - int endObject; - }; - - btSoftBodyLinkDataOpenCL m_linkData; - btSoftBodyVertexDataOpenCL m_vertexData; - btSoftBodyTriangleDataOpenCL m_triangleData; - -protected: - - CLFunctions m_defaultCLFunctions; - CLFunctions* m_currentCLFunctions; - - /** Variable to define whether we need to update solver constants on the next iteration */ - bool m_updateSolverConstants; - - bool m_shadersInitialized; - - /** - * Cloths owned by this solver. - * Only our cloths are in this array. - */ - btAlignedObjectArray< btOpenCLAcceleratedSoftBodyInterface * > m_softBodySet; - - /** Acceleration value to be applied to all non-static vertices in the solver. - * Index n is cloth n, array sized by number of cloths in the world not the solver. - */ - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration; - btOpenCLBuffer m_clPerClothAcceleration; - - /** Wind velocity to be applied normal to all non-static vertices in the solver. - * Index n is cloth n, array sized by number of cloths in the world not the solver. - */ - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity; - btOpenCLBuffer m_clPerClothWindVelocity; - - /** Velocity damping factor */ - btAlignedObjectArray< float > m_perClothDampingFactor; - btOpenCLBuffer m_clPerClothDampingFactor; - - /** Velocity correction coefficient */ - btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient; - btOpenCLBuffer m_clPerClothVelocityCorrectionCoefficient; - - /** Lift parameter for wind effect on cloth. */ - btAlignedObjectArray< float > m_perClothLiftFactor; - btOpenCLBuffer m_clPerClothLiftFactor; - - /** Drag parameter for wind effect on cloth. */ - btAlignedObjectArray< float > m_perClothDragFactor; - btOpenCLBuffer m_clPerClothDragFactor; - - /** Density of the medium in which each cloth sits */ - btAlignedObjectArray< float > m_perClothMediumDensity; - btOpenCLBuffer m_clPerClothMediumDensity; - - /** - * Collision shape details: pair of index of first collision shape for the cloth and number of collision objects. - */ - btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects; - btOpenCLBuffer m_clPerClothCollisionObjects; - - /** - * Collision shapes being passed across to the cloths in this solver. - */ - btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails; - btOpenCLBuffer< CollisionShapeDescription > m_clCollisionObjectDetails; - - - - /** - * Friction coefficient for each cloth - */ - btAlignedObjectArray< float > m_perClothFriction; - btOpenCLBuffer< float > m_clPerClothFriction; - - // anchor node info - struct AnchorNodeInfoCL - { - int clVertexIndex; - btSoftBody::Node* pNode; - }; - - btAlignedObjectArray m_anchorNodeInfoArray; - btAlignedObjectArray m_anchorPosition; - btOpenCLBuffer m_clAnchorPosition; - btAlignedObjectArray m_anchorIndex; - btOpenCLBuffer m_clAnchorIndex; - - bool m_bUpdateAnchoredNodePos; - - cl_kernel m_prepareLinksKernel; - cl_kernel m_solvePositionsFromLinksKernel; - cl_kernel m_updateConstantsKernel; - cl_kernel m_integrateKernel; - cl_kernel m_addVelocityKernel; - cl_kernel m_updatePositionsFromVelocitiesKernel; - cl_kernel m_updateVelocitiesFromPositionsWithoutVelocitiesKernel; - cl_kernel m_updateVelocitiesFromPositionsWithVelocitiesKernel; - cl_kernel m_vSolveLinksKernel; - cl_kernel m_solveCollisionsAndUpdateVelocitiesKernel; - cl_kernel m_resetNormalsAndAreasKernel; - cl_kernel m_normalizeNormalsAndAreasKernel; - cl_kernel m_updateSoftBodiesKernel; - - cl_kernel m_outputToVertexArrayKernel; - cl_kernel m_applyForcesKernel; - cl_kernel m_updateFixedVertexPositionsKernel; - - cl_command_queue m_cqCommandQue; - cl_context m_cxMainContext; - - size_t m_defaultWorkGroupSize; - - - virtual bool buildShaders(); - - void resetNormalsAndAreas( int numVertices ); - - void normalizeNormalsAndAreas( int numVertices ); - - void executeUpdateSoftBodies( int firstTriangle, int numTriangles ); - - void prepareCollisionConstraints(); - - Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a ); - - void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce ); - - - int findSoftBodyIndex( const btSoftBody* const softBody ); - - virtual void applyForces( float solverdt ); - - void updateFixedVertexPositions(); - - /** - * Integrate motion on the solver. - */ - virtual void integrate( float solverdt ); - - virtual void updateConstants( float timeStep ); - - float computeTriangleArea( - const Vectormath::Aos::Point3 &vertex0, - const Vectormath::Aos::Point3 &vertex1, - const Vectormath::Aos::Point3 &vertex2 ); - - - ////////////////////////////////////// - // Kernel dispatches - void prepareLinks(); - - void solveLinksForVelocity( int startLink, int numLinks, float kst ); - - void updatePositionsFromVelocities( float solverdt ); - - virtual void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); - - void updateVelocitiesFromPositionsWithVelocities( float isolverdt ); - - void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt ); - virtual void solveCollisionsAndUpdateVelocities( float isolverdt ); - - // End kernel dispatches - ///////////////////////////////////// - - void updateBounds(); - - void releaseKernels(); - -public: - btOpenCLSoftBodySolver(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false); - - virtual ~btOpenCLSoftBodySolver(); - - - - btOpenCLAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody ); - - virtual btSoftBodyLinkData &getLinkData(); - - virtual btSoftBodyVertexData &getVertexData(); - - virtual btSoftBodyTriangleData &getTriangleData(); - - virtual SolverTypes getSolverType() const - { - return CL_SOLVER; - } - - - virtual bool checkInitialized(); - - virtual void updateSoftBodies( ); - - virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); - - virtual void copyBackToSoftBodies(bool bMove = true); - - virtual void solveConstraints( float solverdt ); - - virtual void predictMotion( float solverdt ); - - virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* ); - - virtual void processCollision( btSoftBody*, btSoftBody* ); - - virtual void setDefaultWorkgroupSize(size_t workGroupSize) - { - m_defaultWorkGroupSize = workGroupSize; - } - virtual size_t getDefaultWorkGroupSize() const - { - return m_defaultWorkGroupSize; - } - - void setCLFunctions(CLFunctions* funcs) - { - if (funcs) - m_currentCLFunctions = funcs; - else - m_currentCLFunctions = &m_defaultCLFunctions; - } - -}; // btOpenCLSoftBodySolver - - -/** - * Class to manage movement of data from a solver to a given target. - * This version is the CL to CPU version. - */ -class btSoftBodySolverOutputCLtoCPU : public btSoftBodySolverOutput -{ -protected: - -public: - btSoftBodySolverOutputCLtoCPU() - { - } - - /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ - virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ); -}; - - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp deleted file mode 100644 index 0380a6dd..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "vectormath/vmInclude.h" -#include //@todo: remove the debugging printf at some stage -#include "btSoftBodySolver_OpenCLSIMDAware.h" -#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h" -#include "BulletSoftBody/btSoftBody.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" -#include - -#define WAVEFRONT_SIZE 32 -#define WAVEFRONT_BLOCK_MULTIPLIER 2 -#define GROUP_SIZE (WAVEFRONT_SIZE*WAVEFRONT_BLOCK_MULTIPLIER) -#define LINKS_PER_SIMD_LANE 16 - -static const size_t workGroupSize = GROUP_SIZE; - - -//CL_VERSION_1_1 seems broken on NVidia SDK so just disable it - -////OpenCL 1.0 kernels don't use float3 -#define MSTRINGIFY(A) #A -static const char* UpdatePositionsFromVelocitiesCLString = -#include "OpenCLC10/UpdatePositionsFromVelocities.cl" -static const char* SolvePositionsCLString = -#include "OpenCLC10/SolvePositionsSIMDBatched.cl" -static const char* UpdateNodesCLString = -#include "OpenCLC10/UpdateNodes.cl" -static const char* UpdatePositionsCLString = -#include "OpenCLC10/UpdatePositions.cl" -static const char* UpdateConstantsCLString = -#include "OpenCLC10/UpdateConstants.cl" -static const char* IntegrateCLString = -#include "OpenCLC10/Integrate.cl" -static const char* ApplyForcesCLString = -#include "OpenCLC10/ApplyForces.cl" -static const char* UpdateFixedVertexPositionsCLString = -#include "OpenCLC10/UpdateFixedVertexPositions.cl" -static const char* UpdateNormalsCLString = -#include "OpenCLC10/UpdateNormals.cl" -static const char* VSolveLinksCLString = -#include "OpenCLC10/VSolveLinks.cl" -static const char* SolveCollisionsAndUpdateVelocitiesCLString = -#include "OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl" -static const char* OutputToVertexArrayCLString = -#include "OpenCLC10/OutputToVertexArray.cl" - - - -btSoftBodyLinkDataOpenCLSIMDAware::btSoftBodyLinkDataOpenCLSIMDAware(cl_command_queue queue, cl_context ctx) : - m_cqCommandQue(queue), - m_wavefrontSize( WAVEFRONT_SIZE ), - m_linksPerWorkItem( LINKS_PER_SIMD_LANE ), - m_maxBatchesWithinWave( 0 ), - m_maxLinksPerWavefront( m_wavefrontSize * m_linksPerWorkItem ), - m_numWavefronts( 0 ), - m_maxVertex( 0 ), - m_clNumBatchesAndVerticesWithinWaves( queue, ctx, &m_numBatchesAndVerticesWithinWaves, true ), - m_clWavefrontVerticesGlobalAddresses( queue, ctx, &m_wavefrontVerticesGlobalAddresses, true ), - m_clLinkVerticesLocalAddresses( queue, ctx, &m_linkVerticesLocalAddresses, true ), - m_clLinkStrength( queue, ctx, &m_linkStrength, false ), - m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ), - m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ), - m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ), - m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false ) -{ -} - -btSoftBodyLinkDataOpenCLSIMDAware::~btSoftBodyLinkDataOpenCLSIMDAware() -{ -} - -static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec ) -{ - Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() ); - return outVec; -} - -/** Allocate enough space in all link-related arrays to fit numLinks links */ -void btSoftBodyLinkDataOpenCLSIMDAware::createLinks( int numLinks ) -{ - int previousSize = m_links.size(); - int newSize = previousSize + numLinks; - - btSoftBodyLinkData::createLinks( numLinks ); - - // Resize the link addresses array as well - m_linkAddresses.resize( newSize ); -} - -/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ -void btSoftBodyLinkDataOpenCLSIMDAware::setLinkAt( - const LinkDescription &link, - int linkIndex ) -{ - btSoftBodyLinkData::setLinkAt( link, linkIndex ); - - if( link.getVertex0() > m_maxVertex ) - m_maxVertex = link.getVertex0(); - if( link.getVertex1() > m_maxVertex ) - m_maxVertex = link.getVertex1(); - - // Set the link index correctly for initialisation - m_linkAddresses[linkIndex] = linkIndex; -} - -bool btSoftBodyLinkDataOpenCLSIMDAware::onAccelerator() -{ - return m_onGPU; -} - -bool btSoftBodyLinkDataOpenCLSIMDAware::moveToAccelerator() -{ - bool success = true; - success = success && m_clNumBatchesAndVerticesWithinWaves.moveToGPU(); - success = success && m_clWavefrontVerticesGlobalAddresses.moveToGPU(); - success = success && m_clLinkVerticesLocalAddresses.moveToGPU(); - success = success && m_clLinkStrength.moveToGPU(); - success = success && m_clLinksMassLSC.moveToGPU(); - success = success && m_clLinksRestLengthSquared.moveToGPU(); - success = success && m_clLinksRestLength.moveToGPU(); - success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU(); - - if( success ) { - m_onGPU = true; - } - - return success; -} - -bool btSoftBodyLinkDataOpenCLSIMDAware::moveFromAccelerator() -{ - bool success = true; - success = success && m_clNumBatchesAndVerticesWithinWaves.moveToGPU(); - success = success && m_clWavefrontVerticesGlobalAddresses.moveToGPU(); - success = success && m_clLinkVerticesLocalAddresses.moveToGPU(); - success = success && m_clLinkStrength.moveFromGPU(); - success = success && m_clLinksMassLSC.moveFromGPU(); - success = success && m_clLinksRestLengthSquared.moveFromGPU(); - success = success && m_clLinksRestLength.moveFromGPU(); - success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU(); - - if( success ) { - m_onGPU = false; - } - - return success; -} - - - - - - - - -btOpenCLSoftBodySolverSIMDAware::btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) : - btOpenCLSoftBodySolver( queue, ctx, bUpdateAchchoredNodePos ), - m_linkData(queue, ctx) -{ - // Initial we will clearly need to update solver constants - // For now this is global for the cloths linked with this solver - we should probably make this body specific - // for performance in future once we understand more clearly when constants need to be updated - m_updateSolverConstants = true; - - m_shadersInitialized = false; -} - -btOpenCLSoftBodySolverSIMDAware::~btOpenCLSoftBodySolverSIMDAware() -{ - releaseKernels(); -} - -void btOpenCLSoftBodySolverSIMDAware::optimize( btAlignedObjectArray< btSoftBody * > &softBodies ,bool forceUpdate) -{ - if( forceUpdate || m_softBodySet.size() != softBodies.size() ) - { - // Have a change in the soft body set so update, reloading all the data - getVertexData().clear(); - getTriangleData().clear(); - getLinkData().clear(); - m_softBodySet.resize(0); - m_anchorIndex.clear(); - - int maxPiterations = 0; - int maxViterations = 0; - - for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex ) - { - btSoftBody *softBody = softBodies[ softBodyIndex ]; - using Vectormath::Aos::Matrix3; - using Vectormath::Aos::Point3; - - // Create SoftBody that will store the information within the solver - btOpenCLAcceleratedSoftBodyInterface* newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody ); - m_softBodySet.push_back( newSoftBody ); - - m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) ); - m_perClothDampingFactor.push_back(softBody->m_cfg.kDP); - m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF ); - m_perClothLiftFactor.push_back( softBody->m_cfg.kLF ); - m_perClothDragFactor.push_back( softBody->m_cfg.kDG ); - m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density); - // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time - m_perClothFriction.push_back(softBody->m_cfg.kDF); - m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) ); - - // Add space for new vertices and triangles in the default solver for now - // TODO: Include space here for tearing too later - int firstVertex = getVertexData().getNumVertices(); - int numVertices = softBody->m_nodes.size(); - // Round maxVertices to a multiple of the workgroup size so we know we're safe to run over in a given group - // maxVertices can be increased to allow tearing, but should be used sparingly because these extra verts will always be processed - int maxVertices = GROUP_SIZE*((numVertices+GROUP_SIZE)/GROUP_SIZE); - // Allocate space for new vertices in all the vertex arrays - getVertexData().createVertices( numVertices, softBodyIndex, maxVertices ); - - - int firstTriangle = getTriangleData().getNumTriangles(); - int numTriangles = softBody->m_faces.size(); - int maxTriangles = numTriangles; - getTriangleData().createTriangles( maxTriangles ); - - // Copy vertices from softbody into the solver - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ()); - btSoftBodyVertexData::VertexDescription desc; - - // TODO: Position in the softbody might be pre-transformed - // or we may need to adapt for the pose. - //desc.setPosition( cloth.getMeshTransform()*multPoint ); - desc.setPosition( multPoint ); - - float vertexInverseMass = softBody->m_nodes[vertex].m_im; - desc.setInverseMass(vertexInverseMass); - getVertexData().setVertexAt( desc, firstVertex + vertex ); - - m_anchorIndex.push_back(-1); - } - for( int vertex = numVertices; vertex < maxVertices; ++vertex ) - { - m_anchorIndex.push_back(-1.0); - } - - // Copy triangles similarly - // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene - for( int triangle = 0; triangle < numTriangles; ++triangle ) - { - // Note that large array storage is relative to the array not to the cloth - // So we need to add firstVertex to each value - int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0])); - int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0])); - int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0])); - btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex); - getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle ); - - // Increase vertex triangle counts for this triangle - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++; - getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++; - } - - int firstLink = getLinkData().getNumLinks(); - int numLinks = softBody->m_links.size(); - int maxLinks = numLinks; - - // Allocate space for the links - getLinkData().createLinks( numLinks ); - - // Add the links - for( int link = 0; link < numLinks; ++link ) - { - int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]); - int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]); - - btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST); - newLink.setLinkStrength(1.f); - getLinkData().setLinkAt(newLink, firstLink + link); - } - - newSoftBody->setFirstVertex( firstVertex ); - newSoftBody->setFirstTriangle( firstTriangle ); - newSoftBody->setNumVertices( numVertices ); - newSoftBody->setMaxVertices( maxVertices ); - newSoftBody->setNumTriangles( numTriangles ); - newSoftBody->setMaxTriangles( maxTriangles ); - newSoftBody->setFirstLink( firstLink ); - newSoftBody->setNumLinks( numLinks ); - - // Find maximum piterations and viterations - int piterations = softBody->m_cfg.piterations; - - if ( piterations > maxPiterations ) - maxPiterations = piterations; - - int viterations = softBody->m_cfg.viterations; - - if ( viterations > maxViterations ) - maxViterations = viterations; - - // zero mass - for( int vertex = 0; vertex < numVertices; ++vertex ) - { - if ( softBody->m_nodes[vertex].m_im == 0 ) - { - AnchorNodeInfoCL nodeInfo; - nodeInfo.clVertexIndex = firstVertex + vertex; - nodeInfo.pNode = &softBody->m_nodes[vertex]; - - m_anchorNodeInfoArray.push_back(nodeInfo); - } - } - - // anchor position - if ( numVertices > 0 ) - { - for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ ) - { - btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node; - btSoftBody::Node* firstNode = &softBody->m_nodes[0]; - - AnchorNodeInfoCL nodeInfo; - nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode); - nodeInfo.pNode = anchorNode; - - m_anchorNodeInfoArray.push_back(nodeInfo); - } - } - } - - m_anchorPosition.clear(); - m_anchorPosition.resize(m_anchorNodeInfoArray.size()); - - for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ ) - { - const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode]; - m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode; - getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f; - } - - updateConstants(0.f); - - // set position and velocity iterations - setNumberOfPositionIterations(maxPiterations); - setNumberOfVelocityIterations(maxViterations); - - // set wind velocity - m_perClothWindVelocity.resize( m_softBodySet.size() ); - for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex ) - { - btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody(); - m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity()); - } - - m_clPerClothWindVelocity.changedOnCPU(); - - // generate batches - m_linkData.generateBatches(); - m_triangleData.generateBatches(); - - // Build the shaders to match the batching parameters - buildShaders(); - } -} - - -btSoftBodyLinkData &btOpenCLSoftBodySolverSIMDAware::getLinkData() -{ - // TODO: Consider setting link data to "changed" here - return m_linkData; -} - - - - -void btOpenCLSoftBodySolverSIMDAware::updateConstants( float timeStep ) -{ - - using namespace Vectormath::Aos; - - if( m_updateSolverConstants ) - { - m_updateSolverConstants = false; - - // Will have to redo this if we change the structure (tear, maybe) or various other possible changes - - // Initialise link constants - const int numLinks = m_linkData.getNumLinks(); - for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) ); - m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 ))); - float invMass0 = m_vertexData.getInverseMass(vertices.vertex0); - float invMass1 = m_vertexData.getInverseMass(vertices.vertex1); - float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex); - float massLSC = (invMass0 + invMass1)/linearStiffness; - m_linkData.getMassLSC(linkIndex) = massLSC; - float restLength = m_linkData.getRestLength(linkIndex); - float restLengthSquared = restLength*restLength; - m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared; - } - } - -} - - - -void btOpenCLSoftBodySolverSIMDAware::solveConstraints( float solverdt ) -{ - - using Vectormath::Aos::Vector3; - using Vectormath::Aos::Point3; - using Vectormath::Aos::lengthSqr; - using Vectormath::Aos::dot; - - // Prepare links - int numLinks = m_linkData.getNumLinks(); - int numVertices = m_vertexData.getNumVertices(); - - float kst = 1.f; - float ti = 0.f; - - - m_clPerClothDampingFactor.moveToGPU(); - m_clPerClothVelocityCorrectionCoefficient.moveToGPU(); - - - // Ensure data is on accelerator - m_linkData.moveToAccelerator(); - m_vertexData.moveToAccelerator(); - - - //prepareLinks(); - - prepareCollisionConstraints(); - - // Solve drift - for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - { - - for( int i = 0; i < m_linkData.m_wavefrontBatchStartLengths.size(); ++i ) - { - int startWave = m_linkData.m_wavefrontBatchStartLengths[i].start; - int numWaves = m_linkData.m_wavefrontBatchStartLengths[i].length; - solveLinksForPosition( startWave, numWaves, kst, ti ); - } - } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration ) - - - // At this point assume that the force array is blank - we will overwrite it - solveCollisionsAndUpdateVelocities( 1.f/solverdt ); -} - - -////////////////////////////////////// -// Kernel dispatches - - -void btOpenCLSoftBodySolverSIMDAware::solveLinksForPosition( int startWave, int numWaves, float kst, float ti ) -{ - cl_int ciErrNum; - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startWave); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numWaves); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti); - - - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clNumBatchesAndVerticesWithinWaves.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clWavefrontVerticesGlobalAddresses.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinkVerticesLocalAddresses.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer); - - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,9, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,10, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer); - - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,11, WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_int2), 0); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,12, m_linkData.getMaxVerticesPerWavefront()*WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_float4), 0); - ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,13, m_linkData.getMaxVerticesPerWavefront()*WAVEFRONT_BLOCK_MULTIPLIER*sizeof(cl_float), 0); - - size_t numWorkItems = workGroupSize*((numWaves*WAVEFRONT_SIZE + (workGroupSize-1)) / workGroupSize); - - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&workGroupSize,0,0,0); - - if( ciErrNum!= CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)"); - } - -} // solveLinksForPosition - -void btOpenCLSoftBodySolverSIMDAware::solveCollisionsAndUpdateVelocities( float isolverdt ) -{ - // Copy kernel parameters to GPU - m_vertexData.moveToAccelerator(); - m_clPerClothFriction.moveToGPU(); - m_clPerClothDampingFactor.moveToGPU(); - m_clPerClothCollisionObjects.moveToGPU(); - m_clCollisionObjectDetails.moveToGPU(); - - cl_int ciErrNum; - int numVerts = m_vertexData.getNumVertices(); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 11, sizeof(CollisionShapeDescription)*16,0); - ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 12, sizeof(cl_mem),&m_vertexData.m_clVertexInverseMass.m_buffer); - size_t numWorkItems = workGroupSize*((m_vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize); - - if (numWorkItems) - { - ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &workGroupSize,0,0,0); - - if( ciErrNum != CL_SUCCESS ) - { - btAssert( 0 && "enqueueNDRangeKernel(m_solveCollisionsAndUpdateVelocitiesKernel)"); - } - } - -} // btOpenCLSoftBodySolverSIMDAware::updateVelocitiesFromPositionsWithoutVelocities - -// End kernel dispatches -///////////////////////////////////// - - - -bool btOpenCLSoftBodySolverSIMDAware::buildShaders() -{ - releaseKernels(); - - if( m_shadersInitialized ) - return true; - - const char* additionalMacros=""; - - m_currentCLFunctions->clearKernelCompilationFailures(); - - char *wavefrontMacros = new char[256]; - - sprintf( - wavefrontMacros, - "-DMAX_NUM_VERTICES_PER_WAVE=%d -DMAX_BATCHES_PER_WAVE=%d -DWAVEFRONT_SIZE=%d -DWAVEFRONT_BLOCK_MULTIPLIER=%d -DBLOCK_SIZE=%d", - m_linkData.getMaxVerticesPerWavefront(), - m_linkData.getMaxBatchesPerWavefront(), - m_linkData.getWavefrontSize(), - WAVEFRONT_BLOCK_MULTIPLIER, - WAVEFRONT_BLOCK_MULTIPLIER*m_linkData.getWavefrontSize()); - - m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel", additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl"); - m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel", wavefrontMacros ,"OpenCLC10/SolvePositionsSIMDBatched.cl"); - m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", additionalMacros ,"OpenCLC10/UpdateNodes.cl"); - m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", additionalMacros,"OpenCLC10/UpdatePositions.cl"); - m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel", additionalMacros ,"OpenCLC10/Integrate.cl"); - m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel", additionalMacros,"OpenCLC10/ApplyForces.cl" ); - m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" ,additionalMacros,"OpenCLC10/UpdateFixedVertexPositions.cl"); - m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel", additionalMacros ,"OpenCLC10/SolveCollisionsAndUpdateVelocitiesSIMDBatched.cl"); - - // TODO: Rename to UpdateSoftBodies - m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); - m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); - m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel", additionalMacros ,"OpenCLC10/UpdateNormals.cl"); - - delete [] wavefrontMacros; - - if( m_currentCLFunctions->getKernelCompilationFailures()==0) - { - m_shadersInitialized = true; - } - - return m_shadersInitialized; -} - - - - -static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform ) -{ - Vectormath::Aos::Transform3 outTransform; - outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0))); - outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1))); - outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2))); - outTransform.setCol(3, toVector3(transform.getOrigin())); - return outTransform; -} - - -static void generateBatchesOfWavefronts( btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, btSoftBodyLinkData &linkData, int numVertices, btAlignedObjectArray < btAlignedObjectArray > &wavefrontBatches ) -{ - // A per-batch map of truth values stating whether a given vertex is in that batch - // This allows us to significantly optimize the batching - btAlignedObjectArray > mapOfVerticesInBatches; - - for( int waveIndex = 0; waveIndex < linksForWavefronts.size(); ++waveIndex ) - { - btAlignedObjectArray &wavefront( linksForWavefronts[waveIndex] ); - - int batch = 0; - bool placed = false; - while( batch < wavefrontBatches.size() && !placed ) - { - // Test the current batch, see if this wave shares any vertex with the waves in the batch - bool foundSharedVertex = false; - for( int link = 0; link < wavefront.size(); ++link ) - { - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); - if( (mapOfVerticesInBatches[batch])[vertices.vertex0] || (mapOfVerticesInBatches[batch])[vertices.vertex1] ) - { - foundSharedVertex = true; - } - } - - if( !foundSharedVertex ) - { - wavefrontBatches[batch].push_back( waveIndex ); - // Insert vertices into this batch too - for( int link = 0; link < wavefront.size(); ++link ) - { - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); - (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; - (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; - } - placed = true; - } - batch++; - } - if( batch == wavefrontBatches.size() && !placed ) - { - wavefrontBatches.resize( batch + 1 ); - wavefrontBatches[batch].push_back( waveIndex ); - - // And resize map as well - mapOfVerticesInBatches.resize( batch + 1 ); - - // Resize maps with total number of vertices - mapOfVerticesInBatches[batch].resize( numVertices+1, false ); - - // Insert vertices into this batch too - for( int link = 0; link < wavefront.size(); ++link ) - { - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( wavefront[link] ); - (mapOfVerticesInBatches[batch])[vertices.vertex0] = true; - (mapOfVerticesInBatches[batch])[vertices.vertex1] = true; - } - } - } - mapOfVerticesInBatches.clear(); -} - -// Function to remove an object from a vector maintaining correct ordering of the vector -template< typename T > static void removeFromVector( btAlignedObjectArray< T > &vectorToUpdate, int indexToRemove ) -{ - int currentSize = vectorToUpdate.size(); - for( int i = indexToRemove; i < (currentSize-1); ++i ) - { - vectorToUpdate[i] = vectorToUpdate[i+1]; - } - if( currentSize > 0 ) - vectorToUpdate.resize( currentSize - 1 ); -} - -/** - * Insert element into vectorToUpdate at index index. - */ -template< typename T > static void insertAtIndex( btAlignedObjectArray< T > &vectorToUpdate, int index, T element ) -{ - vectorToUpdate.resize( vectorToUpdate.size() + 1 ); - for( int i = (vectorToUpdate.size() - 1); i > index; --i ) - { - vectorToUpdate[i] = vectorToUpdate[i-1]; - } - vectorToUpdate[index] = element; -} - -/** - * Insert into btAlignedObjectArray assuming the array is ordered and maintaining both ordering and uniqueness. - * ie it treats vectorToUpdate as an ordered set. - */ -template< typename T > static void insertUniqueAndOrderedIntoVector( btAlignedObjectArray &vectorToUpdate, T element ) -{ - int index = 0; - while( index < vectorToUpdate.size() && vectorToUpdate[index] < element ) - { - index++; - } - if( index == vectorToUpdate.size() || vectorToUpdate[index] != element ) - insertAtIndex( vectorToUpdate, index, element ); -} - -static void generateLinksPerVertex( int numVertices, btSoftBodyLinkData &linkData, btAlignedObjectArray< int > &listOfLinksPerVertex, btAlignedObjectArray &numLinksPerVertex, int &maxLinks ) -{ - for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); - numLinksPerVertex[nodes.vertex0]++; - numLinksPerVertex[nodes.vertex1]++; - } - int maxLinksPerVertex = 0; - for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) - { - maxLinksPerVertex = btMax(numLinksPerVertex[vertexIndex], maxLinksPerVertex); - } - maxLinks = maxLinksPerVertex; - - btAlignedObjectArray< int > linksFoundPerVertex; - linksFoundPerVertex.resize( numVertices, 0 ); - - listOfLinksPerVertex.resize( maxLinksPerVertex * numVertices ); - - for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); - { - // Do vertex 0 - int vertexIndex = nodes.vertex0; - int linkForVertex = linksFoundPerVertex[nodes.vertex0]; - int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; - - listOfLinksPerVertex[linkAddress] = linkIndex; - - linksFoundPerVertex[nodes.vertex0] = linkForVertex + 1; - } - { - // Do vertex 1 - int vertexIndex = nodes.vertex1; - int linkForVertex = linksFoundPerVertex[nodes.vertex1]; - int linkAddress = vertexIndex * maxLinksPerVertex + linkForVertex; - - listOfLinksPerVertex[linkAddress] = linkIndex; - - linksFoundPerVertex[nodes.vertex1] = linkForVertex + 1; - } - } -} - -static void computeBatchingIntoWavefronts( - btSoftBodyLinkData &linkData, - int wavefrontSize, - int linksPerWorkItem, - int maxLinksPerWavefront, - btAlignedObjectArray < btAlignedObjectArray > &linksForWavefronts, - btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > &batchesWithinWaves, /* wave, batch, links in batch */ - btAlignedObjectArray< btAlignedObjectArray< int > > &verticesForWavefronts /* wavefront, vertex */ - ) -{ - - - // Attempt generation of larger batches of links. - btAlignedObjectArray< bool > processedLink; - processedLink.resize( linkData.getNumLinks() ); - btAlignedObjectArray< int > listOfLinksPerVertex; - int maxLinksPerVertex = 0; - - // Count num vertices - int numVertices = 0; - for( int linkIndex = 0; linkIndex < linkData.getNumLinks(); ++linkIndex ) - { - btSoftBodyLinkData::LinkNodePair nodes( linkData.getVertexPair(linkIndex) ); - numVertices = btMax( numVertices, nodes.vertex0 + 1 ); - numVertices = btMax( numVertices, nodes.vertex1 + 1 ); - } - - // Need list of links per vertex - // Compute valence of each vertex - btAlignedObjectArray numLinksPerVertex; - numLinksPerVertex.resize(0); - numLinksPerVertex.resize( numVertices, 0 ); - - generateLinksPerVertex( numVertices, linkData, listOfLinksPerVertex, numLinksPerVertex, maxLinksPerVertex ); - - if (!numVertices) - return; - - for( int vertex = 0; vertex < 10; ++vertex ) - { - for( int link = 0; link < numLinksPerVertex[vertex]; ++link ) - { - int linkAddress = vertex * maxLinksPerVertex + link; - } - } - - - // At this point we know what links we have for each vertex so we can start batching - - // We want a vertex to start with, let's go with 0 - int currentVertex = 0; - int linksProcessed = 0; - - btAlignedObjectArray verticesToProcess; - - while( linksProcessed < linkData.getNumLinks() ) - { - // Next wavefront - int nextWavefront = linksForWavefronts.size(); - linksForWavefronts.resize( nextWavefront + 1 ); - btAlignedObjectArray &linksForWavefront(linksForWavefronts[nextWavefront]); - verticesForWavefronts.resize( nextWavefront + 1 ); - btAlignedObjectArray &vertexSet( verticesForWavefronts[nextWavefront] ); - - linksForWavefront.resize(0); - - // Loop to find enough links to fill the wavefront - // Stopping if we either run out of links, or fill it - while( linksProcessed < linkData.getNumLinks() && linksForWavefront.size() < maxLinksPerWavefront ) - { - // Go through the links for the current vertex - for( int link = 0; link < numLinksPerVertex[currentVertex] && linksForWavefront.size() < maxLinksPerWavefront; ++link ) - { - int linkAddress = currentVertex * maxLinksPerVertex + link; - int linkIndex = listOfLinksPerVertex[linkAddress]; - - // If we have not already processed this link, add it to the wavefront - // Claim it as another processed link - // Add the vertex at the far end to the list of vertices to process. - if( !processedLink[linkIndex] ) - { - linksForWavefront.push_back( linkIndex ); - linksProcessed++; - processedLink[linkIndex] = true; - int v0 = linkData.getVertexPair(linkIndex).vertex0; - int v1 = linkData.getVertexPair(linkIndex).vertex1; - if( v0 == currentVertex ) - verticesToProcess.push_back( v1 ); - else - verticesToProcess.push_back( v0 ); - } - } - if( verticesToProcess.size() > 0 ) - { - // Get the element on the front of the queue and remove it - currentVertex = verticesToProcess[0]; - removeFromVector( verticesToProcess, 0 ); - } else { - // If we've not yet processed all the links, find the first unprocessed one - // and select one of its vertices as the current vertex - if( linksProcessed < linkData.getNumLinks() ) - { - int searchLink = 0; - while( processedLink[searchLink] ) - searchLink++; - currentVertex = linkData.getVertexPair(searchLink).vertex0; - } - } - } - - // We have either finished or filled a wavefront - for( int link = 0; link < linksForWavefront.size(); ++link ) - { - int v0 = linkData.getVertexPair( linksForWavefront[link] ).vertex0; - int v1 = linkData.getVertexPair( linksForWavefront[link] ).vertex1; - insertUniqueAndOrderedIntoVector( vertexSet, v0 ); - insertUniqueAndOrderedIntoVector( vertexSet, v1 ); - } - // Iterate over links mapped to the wave and batch those - // We can run a batch on each cycle trivially - - batchesWithinWaves.resize( batchesWithinWaves.size() + 1 ); - btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWave( batchesWithinWaves[batchesWithinWaves.size()-1] ); - - - for( int link = 0; link < linksForWavefront.size(); ++link ) - { - int linkIndex = linksForWavefront[link]; - btSoftBodyLinkData::LinkNodePair vertices = linkData.getVertexPair( linkIndex ); - - int batch = 0; - bool placed = false; - while( batch < batchesWithinWave.size() && !placed ) - { - bool foundSharedVertex = false; - if( batchesWithinWave[batch].size() >= wavefrontSize ) - { - // If we have already filled this batch, move on to another - foundSharedVertex = true; - } else { - for( int link2 = 0; link2 < batchesWithinWave[batch].size(); ++link2 ) - { - btSoftBodyLinkData::LinkNodePair vertices2 = linkData.getVertexPair( (batchesWithinWave[batch])[link2] ); - - if( vertices.vertex0 == vertices2.vertex0 || - vertices.vertex1 == vertices2.vertex0 || - vertices.vertex0 == vertices2.vertex1 || - vertices.vertex1 == vertices2.vertex1 ) - { - foundSharedVertex = true; - break; - } - } - } - if( !foundSharedVertex ) - { - batchesWithinWave[batch].push_back( linkIndex ); - placed = true; - } else { - ++batch; - } - } - if( batch == batchesWithinWave.size() && !placed ) - { - batchesWithinWave.resize( batch + 1 ); - batchesWithinWave[batch].push_back( linkIndex ); - } - } - - } - -} - -void btSoftBodyLinkDataOpenCLSIMDAware::generateBatches() -{ - btAlignedObjectArray < btAlignedObjectArray > linksForWavefronts; - btAlignedObjectArray < btAlignedObjectArray > wavefrontBatches; - btAlignedObjectArray< btAlignedObjectArray < btAlignedObjectArray > > batchesWithinWaves; - btAlignedObjectArray< btAlignedObjectArray< int > > verticesForWavefronts; // wavefronts, vertices in wavefront as an ordered set - - // Group the links into wavefronts - computeBatchingIntoWavefronts( *this, m_wavefrontSize, m_linksPerWorkItem, m_maxLinksPerWavefront, linksForWavefronts, batchesWithinWaves, verticesForWavefronts ); - - - // Batch the wavefronts - generateBatchesOfWavefronts( linksForWavefronts, *this, m_maxVertex, wavefrontBatches ); - - m_numWavefronts = linksForWavefronts.size(); - - // At this point we have a description of which links we need to process in each wavefront - - // First correctly fill the batch ranges vector - int numBatches = wavefrontBatches.size(); - m_wavefrontBatchStartLengths.resize(0); - int prefixSum = 0; - for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) - { - int wavesInBatch = wavefrontBatches[batchIndex].size(); - int nextPrefixSum = prefixSum + wavesInBatch; - m_wavefrontBatchStartLengths.push_back( BatchPair( prefixSum, nextPrefixSum - prefixSum ) ); - - prefixSum += wavesInBatch; - } - - // Also find max number of batches within a wave - m_maxBatchesWithinWave = 0; - m_maxVerticesWithinWave = 0; - m_numBatchesAndVerticesWithinWaves.resize( m_numWavefronts ); - for( int waveIndex = 0; waveIndex < m_numWavefronts; ++waveIndex ) - { - // See if the number of batches in this wave is greater than the current maxium - int batchesInCurrentWave = batchesWithinWaves[waveIndex].size(); - int verticesInCurrentWave = verticesForWavefronts[waveIndex].size(); - m_maxBatchesWithinWave = btMax( batchesInCurrentWave, m_maxBatchesWithinWave ); - m_maxVerticesWithinWave = btMax( verticesInCurrentWave, m_maxVerticesWithinWave ); - } - - // Add padding values both for alignment and as dudd addresses within LDS to compute junk rather than branch around - m_maxVerticesWithinWave = 16*((m_maxVerticesWithinWave/16)+2); - - // Now we know the maximum number of vertices per-wave we can resize the global vertices array - m_wavefrontVerticesGlobalAddresses.resize( m_maxVerticesWithinWave * m_numWavefronts ); - - // Grab backup copies of all the link data arrays for the sorting process - btAlignedObjectArray m_links_Backup(m_links); - btAlignedObjectArray m_linkStrength_Backup(m_linkStrength); - btAlignedObjectArray m_linksMassLSC_Backup(m_linksMassLSC); - btAlignedObjectArray m_linksRestLengthSquared_Backup(m_linksRestLengthSquared); - //btAlignedObjectArray m_linksCLength_Backup(m_linksCLength); - //btAlignedObjectArray m_linksLengthRatio_Backup(m_linksLengthRatio); - btAlignedObjectArray m_linksRestLength_Backup(m_linksRestLength); - btAlignedObjectArray m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient); - - // Resize to a wavefront sized batch per batch per wave so we get perfectly coherent memory accesses. - m_links.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linkVerticesLocalAddresses.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linkStrength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksMassLSC.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksRestLengthSquared.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksRestLength.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - m_linksMaterialLinearStiffnessCoefficient.resize( m_maxBatchesWithinWave * m_wavefrontSize * m_numWavefronts ); - - // Then re-order links into wavefront blocks - - // Total number of wavefronts moved. This will decide the ordering of sorted wavefronts. - int wavefrontCount = 0; - - // Iterate over batches of wavefronts, then wavefronts in the batch - for( int batchIndex = 0; batchIndex < numBatches; ++batchIndex ) - { - btAlignedObjectArray &batch( wavefrontBatches[batchIndex] ); - int wavefrontsInBatch = batch.size(); - - - for( int wavefrontIndex = 0; wavefrontIndex < wavefrontsInBatch; ++wavefrontIndex ) - { - - int originalWavefrontIndex = batch[wavefrontIndex]; - btAlignedObjectArray< int > &wavefrontVertices( verticesForWavefronts[originalWavefrontIndex] ); - int verticesUsedByWavefront = wavefrontVertices.size(); - - // Copy the set of vertices into the correctly structured array for use on the device - // Fill the non-vertices with -1s - // so we can mask out those reads - for( int vertex = 0; vertex < verticesUsedByWavefront; ++vertex ) - { - m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = wavefrontVertices[vertex]; - } - for( int vertex = verticesUsedByWavefront; vertex < m_maxVerticesWithinWave; ++vertex ) - { - m_wavefrontVerticesGlobalAddresses[m_maxVerticesWithinWave * wavefrontCount + vertex] = -1; - } - - // Obtain the set of batches within the current wavefront - btAlignedObjectArray < btAlignedObjectArray > &batchesWithinWavefront( batchesWithinWaves[originalWavefrontIndex] ); - // Set the size of the batches for use in the solver, correctly ordered - NumBatchesVerticesPair batchesAndVertices; - batchesAndVertices.numBatches = batchesWithinWavefront.size(); - batchesAndVertices.numVertices = verticesUsedByWavefront; - m_numBatchesAndVerticesWithinWaves[wavefrontCount] = batchesAndVertices; - - - // Now iterate over batches within the wavefront to structure the links correctly - for( int wavefrontBatch = 0; wavefrontBatch < batchesWithinWavefront.size(); ++wavefrontBatch ) - { - btAlignedObjectArray &linksInBatch( batchesWithinWavefront[wavefrontBatch] ); - int wavefrontBatchSize = linksInBatch.size(); - - int batchAddressInTarget = m_maxBatchesWithinWave * m_wavefrontSize * wavefrontCount + m_wavefrontSize * wavefrontBatch; - - for( int linkIndex = 0; linkIndex < wavefrontBatchSize; ++linkIndex ) - { - int originalLinkAddress = linksInBatch[linkIndex]; - // Reorder simple arrays trivially - m_links[batchAddressInTarget + linkIndex] = m_links_Backup[originalLinkAddress]; - m_linkStrength[batchAddressInTarget + linkIndex] = m_linkStrength_Backup[originalLinkAddress]; - m_linksMassLSC[batchAddressInTarget + linkIndex] = m_linksMassLSC_Backup[originalLinkAddress]; - m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = m_linksRestLengthSquared_Backup[originalLinkAddress]; - m_linksRestLength[batchAddressInTarget + linkIndex] = m_linksRestLength_Backup[originalLinkAddress]; - m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = m_linksMaterialLinearStiffnessCoefficient_Backup[originalLinkAddress]; - - // The local address is more complicated. We need to work out where a given vertex will end up - // by searching the set of vertices for this link and using the index as the local address - btSoftBodyLinkData::LinkNodePair localPair; - btSoftBodyLinkData::LinkNodePair globalPair = m_links[batchAddressInTarget + linkIndex]; - localPair.vertex0 = wavefrontVertices.findLinearSearch( globalPair.vertex0 ); - localPair.vertex1 = wavefrontVertices.findLinearSearch( globalPair.vertex1 ); - m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; - } - for( int linkIndex = wavefrontBatchSize; linkIndex < m_wavefrontSize; ++linkIndex ) - { - // Put 0s into these arrays for padding for cleanliness - m_links[batchAddressInTarget + linkIndex] = btSoftBodyLinkData::LinkNodePair(0, 0); - m_linkStrength[batchAddressInTarget + linkIndex] = 0.f; - m_linksMassLSC[batchAddressInTarget + linkIndex] = 0.f; - m_linksRestLengthSquared[batchAddressInTarget + linkIndex] = 0.f; - m_linksRestLength[batchAddressInTarget + linkIndex] = 0.f; - m_linksMaterialLinearStiffnessCoefficient[batchAddressInTarget + linkIndex] = 0.f; - - - // For local addresses of junk data choose a set of addresses just above the range of valid ones - // and cycling tyhrough % 16 so that we don't have bank conficts between all dud addresses - // The valid addresses will do scatter and gather in the valid range, the junk ones should happily work - // off the end of that range so we need no control - btSoftBodyLinkData::LinkNodePair localPair; - localPair.vertex0 = verticesUsedByWavefront + (linkIndex % 16); - localPair.vertex1 = verticesUsedByWavefront + (linkIndex % 16); - m_linkVerticesLocalAddresses[batchAddressInTarget + linkIndex] = localPair; - } - - } - - - wavefrontCount++; - } - - - } - -} // void btSoftBodyLinkDataDX11SIMDAware::generateBatches() - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h deleted file mode 100644 index 8cd838ad..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/btSoftBodySolver_OpenCLSIMDAware.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H -#define BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H - -#include "stddef.h" //for size_t -#include "vectormath/vmInclude.h" - -#include "btSoftBodySolver_OpenCL.h" -#include "btSoftBodySolverBuffer_OpenCL.h" -#include "btSoftBodySolverLinkData_OpenCLSIMDAware.h" -#include "btSoftBodySolverVertexData_OpenCL.h" -#include "btSoftBodySolverTriangleData_OpenCL.h" - - - - - -class btOpenCLSoftBodySolverSIMDAware : public btOpenCLSoftBodySolver -{ -protected: - - - btSoftBodyLinkDataOpenCLSIMDAware m_linkData; - - - - - virtual bool buildShaders(); - - - void updateConstants( float timeStep ); - - float computeTriangleArea( - const Vectormath::Aos::Point3 &vertex0, - const Vectormath::Aos::Point3 &vertex1, - const Vectormath::Aos::Point3 &vertex2 ); - - - ////////////////////////////////////// - // Kernel dispatches - void solveLinksForPosition( int startLink, int numLinks, float kst, float ti ); - - void solveCollisionsAndUpdateVelocities( float isolverdt ); - // End kernel dispatches - ///////////////////////////////////// - -public: - btOpenCLSoftBodySolverSIMDAware(cl_command_queue queue,cl_context ctx, bool bUpdateAchchoredNodePos = false); - - virtual ~btOpenCLSoftBodySolverSIMDAware(); - - virtual SolverTypes getSolverType() const - { - return CL_SIMD_SOLVER; - } - - - virtual btSoftBodyLinkData &getLinkData(); - - - virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false); - - virtual void solveConstraints( float solverdt ); - -}; // btOpenCLSoftBodySolverSIMDAware - -#endif // #ifndef BT_SOFT_BODY_SOLVER_OPENCL_SIMDAWARE_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h deleted file mode 100644 index ab6721fb..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h +++ /dev/null @@ -1,748 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_DATA_H -#define BT_SOFT_BODY_SOLVER_DATA_H - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "vectormath/vmInclude.h" - - -class btSoftBodyLinkData -{ -public: - /** - * Class representing a link as a set of three indices into the vertex array. - */ - class LinkNodePair - { - public: - int vertex0; - int vertex1; - - LinkNodePair() - { - vertex0 = 0; - vertex1 = 0; - } - - LinkNodePair( int v0, int v1 ) - { - vertex0 = v0; - vertex1 = v1; - } - }; - - /** - * Class describing a link for input into the system. - */ - class LinkDescription - { - protected: - int m_vertex0; - int m_vertex1; - float m_linkLinearStiffness; - float m_linkStrength; - - public: - - LinkDescription() - { - m_vertex0 = 0; - m_vertex1 = 0; - m_linkLinearStiffness = 1.0; - m_linkStrength = 1.0; - } - - LinkDescription( int newVertex0, int newVertex1, float linkLinearStiffness ) - { - m_vertex0 = newVertex0; - m_vertex1 = newVertex1; - m_linkLinearStiffness = linkLinearStiffness; - m_linkStrength = 1.0; - } - - LinkNodePair getVertexPair() const - { - LinkNodePair nodes; - nodes.vertex0 = m_vertex0; - nodes.vertex1 = m_vertex1; - return nodes; - } - - void setVertex0( int vertex ) - { - m_vertex0 = vertex; - } - - void setVertex1( int vertex ) - { - m_vertex1 = vertex; - } - - void setLinkLinearStiffness( float linearStiffness ) - { - m_linkLinearStiffness = linearStiffness; - } - - void setLinkStrength( float strength ) - { - m_linkStrength = strength; - } - - int getVertex0() const - { - return m_vertex0; - } - - int getVertex1() const - { - return m_vertex1; - } - - float getLinkStrength() const - { - return m_linkStrength; - } - - float getLinkLinearStiffness() const - { - return m_linkLinearStiffness; - } - }; - - -protected: - // NOTE: - // Vertex reference data is stored relative to global array, not relative to individual cloth. - // Values must be correct if being passed into single-cloth VBOs or when migrating from one solver - // to another. - - btAlignedObjectArray< LinkNodePair > m_links; // Vertex pair for the link - btAlignedObjectArray< float > m_linkStrength; // Strength of each link - // (inverseMassA + inverseMassB)/ linear stiffness coefficient - btAlignedObjectArray< float > m_linksMassLSC; - btAlignedObjectArray< float > m_linksRestLengthSquared; - // Current vector length of link - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_linksCLength; - // 1/(current length * current length * massLSC) - btAlignedObjectArray< float > m_linksLengthRatio; - btAlignedObjectArray< float > m_linksRestLength; - btAlignedObjectArray< float > m_linksMaterialLinearStiffnessCoefficient; - -public: - btSoftBodyLinkData() - { - } - - virtual ~btSoftBodyLinkData() - { - } - - virtual void clear() - { - m_links.resize(0); - m_linkStrength.resize(0); - m_linksMassLSC.resize(0); - m_linksRestLengthSquared.resize(0); - m_linksLengthRatio.resize(0); - m_linksRestLength.resize(0); - m_linksMaterialLinearStiffnessCoefficient.resize(0); - } - - int getNumLinks() - { - return m_links.size(); - } - - /** Allocate enough space in all link-related arrays to fit numLinks links */ - virtual void createLinks( int numLinks ) - { - int previousSize = m_links.size(); - int newSize = previousSize + numLinks; - - // Resize all the arrays that store link data - m_links.resize( newSize ); - m_linkStrength.resize( newSize ); - m_linksMassLSC.resize( newSize ); - m_linksRestLengthSquared.resize( newSize ); - m_linksCLength.resize( newSize ); - m_linksLengthRatio.resize( newSize ); - m_linksRestLength.resize( newSize ); - m_linksMaterialLinearStiffnessCoefficient.resize( newSize ); - } - - /** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */ - virtual void setLinkAt( const LinkDescription &link, int linkIndex ) - { - m_links[linkIndex] = link.getVertexPair(); - m_linkStrength[linkIndex] = link.getLinkStrength(); - m_linksMassLSC[linkIndex] = 0.f; - m_linksRestLengthSquared[linkIndex] = 0.f; - m_linksCLength[linkIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); - m_linksLengthRatio[linkIndex] = 0.f; - m_linksRestLength[linkIndex] = 0.f; - m_linksMaterialLinearStiffnessCoefficient[linkIndex] = link.getLinkLinearStiffness(); - } - - - /** - * Return true if data is on the accelerator. - * The CPU version of this class will return true here because - * the CPU is the same as the accelerator. - */ - virtual bool onAccelerator() - { - return true; - } - - /** - * Move data from host memory to the accelerator. - * The CPU version will always return that it has moved it. - */ - virtual bool moveToAccelerator() - { - return true; - } - - /** - * Move data from host memory from the accelerator. - * The CPU version will always return that it has moved it. - */ - virtual bool moveFromAccelerator() - { - return true; - } - - - - /** - * Return reference to the vertex index pair for link linkIndex as stored on the host. - */ - LinkNodePair &getVertexPair( int linkIndex ) - { - return m_links[linkIndex]; - } - - /** - * Return reference to strength of link linkIndex as stored on the host. - */ - float &getStrength( int linkIndex ) - { - return m_linkStrength[linkIndex]; - } - - /** - * Return a reference to the strength of the link corrected for link sorting. - * This is important if we are using data on an accelerator which has the data sorted in some fashion. - */ - virtual float &getStrengthCorrected( int linkIndex ) - { - return getStrength( linkIndex ); - } - - /** - * Return reference to the rest length of link linkIndex as stored on the host. - */ - float &getRestLength( int linkIndex ) - { - return m_linksRestLength[linkIndex]; - } - - /** - * Return reference to linear stiffness coefficient for link linkIndex as stored on the host. - */ - float &getLinearStiffnessCoefficient( int linkIndex ) - { - return m_linksMaterialLinearStiffnessCoefficient[linkIndex]; - } - - /** - * Return reference to the MassLSC value for link linkIndex as stored on the host. - */ - float &getMassLSC( int linkIndex ) - { - return m_linksMassLSC[linkIndex]; - } - - /** - * Return reference to rest length squared for link linkIndex as stored on the host. - */ - float &getRestLengthSquared( int linkIndex ) - { - return m_linksRestLengthSquared[linkIndex]; - } - - /** - * Return reference to current length of link linkIndex as stored on the host. - */ - Vectormath::Aos::Vector3 &getCurrentLength( int linkIndex ) - { - return m_linksCLength[linkIndex]; - } - - /** - * Return the link length ratio from for link linkIndex as stored on the host. - */ - float &getLinkLengthRatio( int linkIndex ) - { - return m_linksLengthRatio[linkIndex]; - } -}; - - - -/** - * Wrapper for vertex data information. - * By wrapping it like this we stand a good chance of being able to optimise for storage format easily. - * It should also help us make sure all the data structures remain consistent. - */ -class btSoftBodyVertexData -{ -public: - /** - * Class describing a vertex for input into the system. - */ - class VertexDescription - { - private: - Vectormath::Aos::Point3 m_position; - /** Inverse mass. If this is 0f then the mass was 0 because that simplifies calculations. */ - float m_inverseMass; - - public: - VertexDescription() - { - m_position = Vectormath::Aos::Point3( 0.f, 0.f, 0.f ); - m_inverseMass = 0.f; - } - - VertexDescription( const Vectormath::Aos::Point3 &position, float mass ) - { - m_position = position; - if( mass > 0.f ) - m_inverseMass = 1.0f/mass; - else - m_inverseMass = 0.f; - } - - void setPosition( const Vectormath::Aos::Point3 &position ) - { - m_position = position; - } - - void setInverseMass( float inverseMass ) - { - m_inverseMass = inverseMass; - } - - void setMass( float mass ) - { - if( mass > 0.f ) - m_inverseMass = 1.0f/mass; - else - m_inverseMass = 0.f; - } - - Vectormath::Aos::Point3 getPosition() const - { - return m_position; - } - - float getInverseMass() const - { - return m_inverseMass; - } - - float getMass() const - { - if( m_inverseMass == 0.f ) - return 0.f; - else - return 1.0f/m_inverseMass; - } - }; -protected: - - // identifier for the individual cloth - // For the CPU we don't really need this as we can grab the cloths and iterate over only their vertices - // For a parallel accelerator knowing on a per-vertex basis which cloth we're part of will help for obtaining - // per-cloth data - // For sorting etc it might also be helpful to be able to use in-array data such as this. - btAlignedObjectArray< int > m_clothIdentifier; - btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPosition; // vertex positions - btAlignedObjectArray< Vectormath::Aos::Point3 > m_vertexPreviousPosition; // vertex positions - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexVelocity; // Velocity - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexForceAccumulator; // Force accumulator - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_vertexNormal; // Normals - btAlignedObjectArray< float > m_vertexInverseMass; // Inverse mass - btAlignedObjectArray< float > m_vertexArea; // Area controlled by the vertex - btAlignedObjectArray< int > m_vertexTriangleCount; // Number of triangles touching this vertex - -public: - btSoftBodyVertexData() - { - } - - virtual ~btSoftBodyVertexData() - { - } - - virtual void clear() - { - m_clothIdentifier.resize(0); - m_vertexPosition.resize(0); - m_vertexPreviousPosition.resize(0); - m_vertexVelocity.resize(0); - m_vertexForceAccumulator.resize(0); - m_vertexNormal.resize(0); - m_vertexInverseMass.resize(0); - m_vertexArea.resize(0); - m_vertexTriangleCount.resize(0); - } - - int getNumVertices() - { - return m_vertexPosition.size(); - } - - int getClothIdentifier( int vertexIndex ) - { - return m_clothIdentifier[vertexIndex]; - } - - void setVertexAt( const VertexDescription &vertex, int vertexIndex ) - { - m_vertexPosition[vertexIndex] = vertex.getPosition(); - m_vertexPreviousPosition[vertexIndex] = vertex.getPosition(); - m_vertexVelocity[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); - m_vertexForceAccumulator[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); - m_vertexNormal[vertexIndex] = Vectormath::Aos::Vector3(0.f, 0.f, 0.f); - m_vertexInverseMass[vertexIndex] = vertex.getInverseMass(); - m_vertexArea[vertexIndex] = 0.f; - m_vertexTriangleCount[vertexIndex] = 0; - } - - /** - * Create numVertices new vertices for cloth clothIdentifier - * maxVertices allows a buffer zone of extra vertices for alignment or tearing reasons. - */ - void createVertices( int numVertices, int clothIdentifier, int maxVertices = 0 ) - { - int previousSize = m_vertexPosition.size(); - if( maxVertices == 0 ) - maxVertices = numVertices; - int newSize = previousSize + maxVertices; - - // Resize all the arrays that store vertex data - m_clothIdentifier.resize( newSize ); - m_vertexPosition.resize( newSize ); - m_vertexPreviousPosition.resize( newSize ); - m_vertexVelocity.resize( newSize ); - m_vertexForceAccumulator.resize( newSize ); - m_vertexNormal.resize( newSize ); - m_vertexInverseMass.resize( newSize ); - m_vertexArea.resize( newSize ); - m_vertexTriangleCount.resize( newSize ); - - for( int vertexIndex = previousSize; vertexIndex < newSize; ++vertexIndex ) - m_clothIdentifier[vertexIndex] = clothIdentifier; - for( int vertexIndex = (previousSize + numVertices); vertexIndex < newSize; ++vertexIndex ) - m_clothIdentifier[vertexIndex] = -1; - } - - // Get and set methods in header so they can be inlined - - /** - * Return a reference to the position of vertex vertexIndex as stored on the host. - */ - Vectormath::Aos::Point3 &getPosition( int vertexIndex ) - { - return m_vertexPosition[vertexIndex]; - } - - Vectormath::Aos::Point3 getPosition( int vertexIndex ) const - { - return m_vertexPosition[vertexIndex]; - } - - /** - * Return a reference to the previous position of vertex vertexIndex as stored on the host. - */ - Vectormath::Aos::Point3 &getPreviousPosition( int vertexIndex ) - { - return m_vertexPreviousPosition[vertexIndex]; - } - - /** - * Return a reference to the velocity of vertex vertexIndex as stored on the host. - */ - Vectormath::Aos::Vector3 &getVelocity( int vertexIndex ) - { - return m_vertexVelocity[vertexIndex]; - } - - /** - * Return a reference to the force accumulator of vertex vertexIndex as stored on the host. - */ - Vectormath::Aos::Vector3 &getForceAccumulator( int vertexIndex ) - { - return m_vertexForceAccumulator[vertexIndex]; - } - - /** - * Return a reference to the normal of vertex vertexIndex as stored on the host. - */ - Vectormath::Aos::Vector3 &getNormal( int vertexIndex ) - { - return m_vertexNormal[vertexIndex]; - } - - Vectormath::Aos::Vector3 getNormal( int vertexIndex ) const - { - return m_vertexNormal[vertexIndex]; - } - - /** - * Return a reference to the inverse mass of vertex vertexIndex as stored on the host. - */ - float &getInverseMass( int vertexIndex ) - { - return m_vertexInverseMass[vertexIndex]; - } - - /** - * Get access to the area controlled by this vertex. - */ - float &getArea( int vertexIndex ) - { - return m_vertexArea[vertexIndex]; - } - - /** - * Get access to the array of how many triangles touch each vertex. - */ - int &getTriangleCount( int vertexIndex ) - { - return m_vertexTriangleCount[vertexIndex]; - } - - - - /** - * Return true if data is on the accelerator. - * The CPU version of this class will return true here because - * the CPU is the same as the accelerator. - */ - virtual bool onAccelerator() - { - return true; - } - - /** - * Move data from host memory to the accelerator. - * The CPU version will always return that it has moved it. - */ - virtual bool moveToAccelerator() - { - return true; - } - - /** - * Move data to host memory from the accelerator if bCopy is false. - * If bCopy is true, copy data to host memory from the accelerator so that data - * won't be moved to accelerator when moveToAccelerator() is called next time. - * If bCopyMinimum is true, only vertex position and normal are copied. - * bCopyMinimum will be meaningful only if bCopy is true. - * The CPU version will always return that it has moved it. - */ - virtual bool moveFromAccelerator(bool bCopy = false, bool bCopyMinimum = true) - { - return true; - } - - btAlignedObjectArray< Vectormath::Aos::Point3 > &getVertexPositions() - { - return m_vertexPosition; - } -}; - - -class btSoftBodyTriangleData -{ -public: - /** - * Class representing a triangle as a set of three indices into the - * vertex array. - */ - class TriangleNodeSet - { - public: - int vertex0; - int vertex1; - int vertex2; - int _padding; - - TriangleNodeSet( ) - { - vertex0 = 0; - vertex1 = 0; - vertex2 = 0; - _padding = -1; - } - - TriangleNodeSet( int newVertex0, int newVertex1, int newVertex2 ) - { - vertex0 = newVertex0; - vertex1 = newVertex1; - vertex2 = newVertex2; - } - }; - - class TriangleDescription - { - protected: - int m_vertex0; - int m_vertex1; - int m_vertex2; - - public: - TriangleDescription() - { - m_vertex0 = 0; - m_vertex1 = 0; - m_vertex2 = 0; - } - - TriangleDescription( int newVertex0, int newVertex1, int newVertex2 ) - { - m_vertex0 = newVertex0; - m_vertex1 = newVertex1; - m_vertex2 = newVertex2; - } - - TriangleNodeSet getVertexSet() const - { - btSoftBodyTriangleData::TriangleNodeSet nodes; - nodes.vertex0 = m_vertex0; - nodes.vertex1 = m_vertex1; - nodes.vertex2 = m_vertex2; - return nodes; - } - }; - -protected: - // NOTE: - // Vertex reference data is stored relative to global array, not relative to individual cloth. - // Values must be correct if being passed into single-cloth VBOs or when migrating from one solver - // to another. - btAlignedObjectArray< TriangleNodeSet > m_vertexIndices; - btAlignedObjectArray< float > m_area; - btAlignedObjectArray< Vectormath::Aos::Vector3 > m_normal; - -public: - btSoftBodyTriangleData() - { - } - - virtual ~btSoftBodyTriangleData() - { - - } - - virtual void clear() - { - m_vertexIndices.resize(0); - m_area.resize(0); - m_normal.resize(0); - } - - int getNumTriangles() - { - return m_vertexIndices.size(); - } - - virtual void setTriangleAt( const TriangleDescription &triangle, int triangleIndex ) - { - m_vertexIndices[triangleIndex] = triangle.getVertexSet(); - } - - virtual void createTriangles( int numTriangles ) - { - int previousSize = m_vertexIndices.size(); - int newSize = previousSize + numTriangles; - - // Resize all the arrays that store triangle data - m_vertexIndices.resize( newSize ); - m_area.resize( newSize ); - m_normal.resize( newSize ); - } - - /** - * Return the vertex index set for triangle triangleIndex as stored on the host. - */ - const TriangleNodeSet &getVertexSet( int triangleIndex ) - { - return m_vertexIndices[triangleIndex]; - } - - /** - * Get access to the triangle area. - */ - float &getTriangleArea( int triangleIndex ) - { - return m_area[triangleIndex]; - } - - /** - * Get access to the normal vector for this triangle. - */ - Vectormath::Aos::Vector3 &getNormal( int triangleIndex ) - { - return m_normal[triangleIndex]; - } - - /** - * Return true if data is on the accelerator. - * The CPU version of this class will return true here because - * the CPU is the same as the accelerator. - */ - virtual bool onAccelerator() - { - return true; - } - - /** - * Move data from host memory to the accelerator. - * The CPU version will always return that it has moved it. - */ - virtual bool moveToAccelerator() - { - return true; - } - - /** - * Move data from host memory from the accelerator. - * The CPU version will always return that it has moved it. - */ - virtual bool moveFromAccelerator() - { - return true; - } -}; - - -#endif // #ifndef BT_SOFT_BODY_SOLVER_DATA_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/HeapManager.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/HeapManager.h deleted file mode 100644 index b2da4ef5..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/HeapManager.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - -#ifndef BT_HEAP_MANAGER_H__ -#define BT_HEAP_MANAGER_H__ - -#ifdef __SPU__ - #define HEAP_STACK_SIZE 32 -#else - #define HEAP_STACK_SIZE 64 -#endif - -#define MIN_ALLOC_SIZE 16 - - -class HeapManager -{ -private: - ATTRIBUTE_ALIGNED16(unsigned char *mHeap); - ATTRIBUTE_ALIGNED16(unsigned int mHeapBytes); - ATTRIBUTE_ALIGNED16(unsigned char *mPoolStack[HEAP_STACK_SIZE]); - ATTRIBUTE_ALIGNED16(unsigned int mCurStack); - -public: - enum {ALIGN16,ALIGN128}; - - HeapManager(unsigned char *buf,int bytes) - { - mHeap = buf; - mHeapBytes = bytes; - clear(); - } - - ~HeapManager() - { - } - - int getAllocated() - { - return (int)(mPoolStack[mCurStack]-mHeap); - } - - int getRest() - { - return mHeapBytes-getAllocated(); - } - - void *allocate(size_t bytes,int alignment = ALIGN16) - { - if(bytes <= 0) bytes = MIN_ALLOC_SIZE; - btAssert(mCurStack < (HEAP_STACK_SIZE-1)); - - -#if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__) - unsigned long long p = (unsigned long long )mPoolStack[mCurStack]; - if(alignment == ALIGN128) { - p = ((p+127) & 0xffffffffffffff80); - bytes = (bytes+127) & 0xffffffffffffff80; - } - else { - bytes = (bytes+15) & 0xfffffffffffffff0; - } - - btAssert(bytes <=(mHeapBytes-(p-(unsigned long long )mHeap)) ); - -#else - unsigned long p = (unsigned long )mPoolStack[mCurStack]; - if(alignment == ALIGN128) { - p = ((p+127) & 0xffffff80); - bytes = (bytes+127) & 0xffffff80; - } - else { - bytes = (bytes+15) & 0xfffffff0; - } - btAssert(bytes <=(mHeapBytes-(p-(unsigned long)mHeap)) ); -#endif - unsigned char * bla = (unsigned char *)(p + bytes); - mPoolStack[++mCurStack] = bla; - return (void*)p; - } - - void deallocate(void *p) - { - (void) p; - mCurStack--; - } - - void clear() - { - mPoolStack[0] = mHeap; - mCurStack = 0; - } - -// void printStack() -// { -// for(unsigned int i=0;i<=mCurStack;i++) { -// PRINTF("memStack %2d 0x%x\n",i,(uint32_t)mPoolStack[i]); -// } -// } - -}; - -#endif //BT_HEAP_MANAGER_H__ - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PlatformDefinitions.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PlatformDefinitions.h deleted file mode 100644 index 9bf8c96f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PlatformDefinitions.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef BT_TYPE_DEFINITIONS_H -#define BT_TYPE_DEFINITIONS_H - -///This file provides some platform/compiler checks for common definitions -#include "LinearMath/btScalar.h" -#include "LinearMath/btMinMax.h" - -#ifdef PFX_USE_FREE_VECTORMATH -#include "physics_effects/base_level/base/pfx_vectormath_include.win32.h" -typedef Vectormath::Aos::Vector3 vmVector3; -typedef Vectormath::Aos::Quat vmQuat; -typedef Vectormath::Aos::Matrix3 vmMatrix3; -typedef Vectormath::Aos::Transform3 vmTransform3; -typedef Vectormath::Aos::Point3 vmPoint3; -#else -#include "vectormath/vmInclude.h" -#endif//PFX_USE_FREE_VECTORMATH - - - - - -#ifdef _WIN32 - -typedef union -{ - unsigned int u; - void *p; -} addr64; - -#define USE_WIN32_THREADING 1 - - #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) - #else - #endif //__MINGW32__ - - typedef unsigned char uint8_t; -#ifndef __PHYSICS_COMMON_H__ -#ifndef PFX_USE_FREE_VECTORMATH -#ifndef __BT_SKIP_UINT64_H -#if defined(_WIN64) && defined(_MSC_VER) - typedef unsigned __int64 uint64_t; -#else - typedef unsigned long int uint64_t; -#endif -#endif //__BT_SKIP_UINT64_H -#endif //PFX_USE_FREE_VECTORMATH - typedef unsigned int uint32_t; -#endif //__PHYSICS_COMMON_H__ - typedef unsigned short uint16_t; - - #include - #define memalign(alignment, size) malloc(size); - -#include //memcpy - - - - #include - #define spu_printf printf - -#else - #include - #include - #include //for memcpy - -#if defined (__CELLOS_LV2__) - // Playstation 3 Cell SDK -#include - -#else - // posix system - -#define USE_PTHREADS (1) - -#ifdef USE_LIBSPE2 -#include -#define spu_printf printf -#define DWORD unsigned int - typedef union - { - unsigned long long ull; - unsigned int ui[2]; - void *p; - } addr64; -#endif // USE_LIBSPE2 - -#endif //__CELLOS_LV2__ - -#endif - -#ifdef __SPU__ -#include -#define printf spu_printf -#endif - -/* Included here because we need uint*_t typedefs */ -#include "PpuAddressSpace.h" - -#endif //BT_TYPE_DEFINITIONS_H - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.cpp deleted file mode 100644 index 81c0cf86..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 -#include "PosixThreadSupport.h" -#ifdef USE_PTHREADS -#include -#include - -#include "SpuCollisionTaskProcess.h" -#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" - -#define checkPThreadFunction(returnValue) \ - if(0 != returnValue) { \ - printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \ - } - -// The number of threads should be equal to the number of available cores -// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor. - -// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication -// Setup and initialize SPU/CELL/Libspe2 -PosixThreadSupport::PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo) -{ - startThreads(threadConstructionInfo); -} - -// cleanup/shutdown Libspe2 -PosixThreadSupport::~PosixThreadSupport() -{ - stopSPU(); -} - -#if (defined (__APPLE__)) -#define NAMED_SEMAPHORES -#endif - -// this semaphore will signal, if and how many threads are finished with their work -static sem_t* mainSemaphore=0; - -static sem_t* createSem(const char* baseName) -{ - static int semCount = 0; -#ifdef NAMED_SEMAPHORES - /// Named semaphore begin - char name[32]; - snprintf(name, 32, "/%s-%d-%4.4d", baseName, getpid(), semCount++); - sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0); - - if (tempSem != reinterpret_cast(SEM_FAILED)) - { -// printf("Created \"%s\" Semaphore %p\n", name, tempSem); - } - else - { - //printf("Error creating Semaphore %d\n", errno); - exit(-1); - } - /// Named semaphore end -#else - sem_t* tempSem = new sem_t; - checkPThreadFunction(sem_init(tempSem, 0, 0)); -#endif - return tempSem; -} - -static void destroySem(sem_t* semaphore) -{ -#ifdef NAMED_SEMAPHORES - checkPThreadFunction(sem_close(semaphore)); -#else - checkPThreadFunction(sem_destroy(semaphore)); - delete semaphore; -#endif -} - -static void *threadFunction(void *argument) -{ - - PosixThreadSupport::btSpuStatus* status = (PosixThreadSupport::btSpuStatus*)argument; - - - while (1) - { - checkPThreadFunction(sem_wait(status->startSemaphore)); - - void* userPtr = status->m_userPtr; - - if (userPtr) - { - btAssert(status->m_status); - status->m_userThreadFunc(userPtr,status->m_lsMemory); - status->m_status = 2; - checkPThreadFunction(sem_post(mainSemaphore)); - status->threadUsed++; - } else { - //exit Thread - status->m_status = 3; - checkPThreadFunction(sem_post(mainSemaphore)); - printf("Thread with taskId %i exiting\n",status->m_taskId); - break; - } - - } - - printf("Thread TERMINATED\n"); - return 0; - -} - -///send messages to SPUs -void PosixThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) -{ - /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (uint32_t) &taskDesc); - - ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished - - - - switch (uiCommand) - { - case CMD_GATHER_AND_PROCESS_PAIRLIST: - { - btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; - btAssert(taskId >= 0); - btAssert(taskId < m_activeSpuStatus.size()); - - spuStatus.m_commandId = uiCommand; - spuStatus.m_status = 1; - spuStatus.m_userPtr = (void*)uiArgument0; - - // fire event to start new task - checkPThreadFunction(sem_post(spuStatus.startSemaphore)); - break; - } - default: - { - ///not implemented - btAssert(0); - } - - }; - - -} - - -///check for messages from SPUs -void PosixThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) -{ - ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response - - ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' - - - btAssert(m_activeSpuStatus.size()); - - // wait for any of the threads to finish - checkPThreadFunction(sem_wait(mainSemaphore)); - - // get at least one thread which has finished - size_t last = -1; - - for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) { - if(2 == m_activeSpuStatus[t].m_status) { - last = t; - break; - } - } - - btSpuStatus& spuStatus = m_activeSpuStatus[last]; - - btAssert(spuStatus.m_status > 1); - spuStatus.m_status = 0; - - // need to find an active spu - btAssert(last >= 0); - - *puiArgument0 = spuStatus.m_taskId; - *puiArgument1 = spuStatus.m_status; -} - - - -void PosixThreadSupport::startThreads(ThreadConstructionInfo& threadConstructionInfo) -{ - printf("%s creating %i threads.\n", __FUNCTION__, threadConstructionInfo.m_numThreads); - m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); - - mainSemaphore = createSem("main"); - //checkPThreadFunction(sem_wait(mainSemaphore)); - - for (int i=0;i < threadConstructionInfo.m_numThreads;i++) - { - printf("starting thread %d\n",i); - - btSpuStatus& spuStatus = m_activeSpuStatus[i]; - - spuStatus.startSemaphore = createSem("threadLocal"); - - checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus)); - - spuStatus.m_userPtr=0; - - spuStatus.m_taskId = i; - spuStatus.m_commandId = 0; - spuStatus.m_status = 0; - spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); - spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; - spuStatus.threadUsed = 0; - - printf("started thread %d \n",i); - - } - -} - -void PosixThreadSupport::startSPU() -{ -} - - -///tell the task scheduler we are done with the SPU tasks -void PosixThreadSupport::stopSPU() -{ - for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) - { - btSpuStatus& spuStatus = m_activeSpuStatus[t]; - printf("%s: Thread %i used: %ld\n", __FUNCTION__, int(t), spuStatus.threadUsed); - - spuStatus.m_userPtr = 0; - checkPThreadFunction(sem_post(spuStatus.startSemaphore)); - checkPThreadFunction(sem_wait(mainSemaphore)); - - printf("destroy semaphore\n"); - destroySem(spuStatus.startSemaphore); - printf("semaphore destroyed\n"); - checkPThreadFunction(pthread_join(spuStatus.thread,0)); - - } - printf("destroy main semaphore\n"); - destroySem(mainSemaphore); - printf("main semaphore destroyed\n"); - m_activeSpuStatus.clear(); -} - -class PosixCriticalSection : public btCriticalSection -{ - pthread_mutex_t m_mutex; - -public: - PosixCriticalSection() - { - pthread_mutex_init(&m_mutex, NULL); - } - virtual ~PosixCriticalSection() - { - pthread_mutex_destroy(&m_mutex); - } - - ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]); - - virtual unsigned int getSharedParam(int i) - { - return mCommonBuff[i]; - } - virtual void setSharedParam(int i,unsigned int p) - { - mCommonBuff[i] = p; - } - - virtual void lock() - { - pthread_mutex_lock(&m_mutex); - } - virtual void unlock() - { - pthread_mutex_unlock(&m_mutex); - } -}; - - -#if defined(_POSIX_BARRIERS) && (_POSIX_BARRIERS - 20012L) >= 0 -/* OK to use barriers on this platform */ -class PosixBarrier : public btBarrier -{ - pthread_barrier_t m_barr; - int m_numThreads; -public: - PosixBarrier() - :m_numThreads(0) { } - virtual ~PosixBarrier() { - pthread_barrier_destroy(&m_barr); - } - - virtual void sync() - { - int rc = pthread_barrier_wait(&m_barr); - if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf("Could not wait on barrier\n"); - exit(-1); - } - } - virtual void setMaxCount(int numThreads) - { - int result = pthread_barrier_init(&m_barr, NULL, numThreads); - m_numThreads = numThreads; - btAssert(result==0); - } - virtual int getMaxCount() - { - return m_numThreads; - } -}; -#else -/* Not OK to use barriers on this platform - insert alternate code here */ -class PosixBarrier : public btBarrier -{ - pthread_mutex_t m_mutex; - pthread_cond_t m_cond; - - int m_numThreads; - int m_called; - -public: - PosixBarrier() - :m_numThreads(0) - { - } - virtual ~PosixBarrier() - { - if (m_numThreads>0) - { - pthread_mutex_destroy(&m_mutex); - pthread_cond_destroy(&m_cond); - } - } - - virtual void sync() - { - pthread_mutex_lock(&m_mutex); - m_called++; - if (m_called == m_numThreads) { - m_called = 0; - pthread_cond_broadcast(&m_cond); - } else { - pthread_cond_wait(&m_cond,&m_mutex); - } - pthread_mutex_unlock(&m_mutex); - - } - virtual void setMaxCount(int numThreads) - { - if (m_numThreads>0) - { - pthread_mutex_destroy(&m_mutex); - pthread_cond_destroy(&m_cond); - } - m_called = 0; - pthread_mutex_init(&m_mutex,NULL); - pthread_cond_init(&m_cond,NULL); - m_numThreads = numThreads; - } - virtual int getMaxCount() - { - return m_numThreads; - } -}; - -#endif//_POSIX_BARRIERS - - - -btBarrier* PosixThreadSupport::createBarrier() -{ - PosixBarrier* barrier = new PosixBarrier(); - barrier->setMaxCount(getNumTasks()); - return barrier; -} - -btCriticalSection* PosixThreadSupport::createCriticalSection() -{ - return new PosixCriticalSection(); -} - -void PosixThreadSupport::deleteBarrier(btBarrier* barrier) -{ - delete barrier; -} - -void PosixThreadSupport::deleteCriticalSection(btCriticalSection* cs) -{ - delete cs; -} -#endif // USE_PTHREADS - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.h deleted file mode 100644 index bf7578f5..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PosixThreadSupport.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_POSIX_THREAD_SUPPORT_H -#define BT_POSIX_THREAD_SUPPORT_H - - -#include "LinearMath/btScalar.h" -#include "PlatformDefinitions.h" - -#ifdef USE_PTHREADS //platform specifc defines are defined in PlatformDefinitions.h - -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html -#endif //_XOPEN_SOURCE -#include -#include - - - -#include "LinearMath/btAlignedObjectArray.h" - -#include "btThreadSupportInterface.h" - - -typedef void (*PosixThreadFunc)(void* userPtr,void* lsMemory); -typedef void* (*PosixlsMemorySetupFunc)(); - -// PosixThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication -class PosixThreadSupport : public btThreadSupportInterface -{ -public: - typedef enum sStatus { - STATUS_BUSY, - STATUS_READY, - STATUS_FINISHED - } Status; - - // placeholder, until libspe2 support is there - struct btSpuStatus - { - uint32_t m_taskId; - uint32_t m_commandId; - uint32_t m_status; - - PosixThreadFunc m_userThreadFunc; - void* m_userPtr; //for taskDesc etc - void* m_lsMemory; //initialized using PosixLocalStoreMemorySetupFunc - - pthread_t thread; - sem_t* startSemaphore; - - unsigned long threadUsed; - }; -private: - - btAlignedObjectArray m_activeSpuStatus; -public: - ///Setup and initialize SPU/CELL/Libspe2 - - - - struct ThreadConstructionInfo - { - ThreadConstructionInfo(const char* uniqueName, - PosixThreadFunc userThreadFunc, - PosixlsMemorySetupFunc lsMemoryFunc, - int numThreads=1, - int threadStackSize=65535 - ) - :m_uniqueName(uniqueName), - m_userThreadFunc(userThreadFunc), - m_lsMemoryFunc(lsMemoryFunc), - m_numThreads(numThreads), - m_threadStackSize(threadStackSize) - { - - } - - const char* m_uniqueName; - PosixThreadFunc m_userThreadFunc; - PosixlsMemorySetupFunc m_lsMemoryFunc; - int m_numThreads; - int m_threadStackSize; - - }; - - PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo); - -///cleanup/shutdown Libspe2 - virtual ~PosixThreadSupport(); - - void startThreads(ThreadConstructionInfo& threadInfo); - - -///send messages to SPUs - virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); - -///check for messages from SPUs - virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); - -///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) - virtual void startSPU(); - -///tell the task scheduler we are done with the SPU tasks - virtual void stopSPU(); - - virtual void setNumTasks(int numTasks) {} - - virtual int getNumTasks() const - { - return m_activeSpuStatus.size(); - } - - virtual btBarrier* createBarrier(); - - virtual btCriticalSection* createCriticalSection(); - - virtual void deleteBarrier(btBarrier* barrier); - - virtual void deleteCriticalSection(btCriticalSection* criticalSection); - - - virtual void* getThreadLocalMemory(int taskId) - { - return m_activeSpuStatus[taskId].m_lsMemory; - } - -}; - -#endif // USE_PTHREADS - -#endif // BT_POSIX_THREAD_SUPPORT_H - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PpuAddressSpace.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/PpuAddressSpace.h deleted file mode 100644 index 6f228274..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/PpuAddressSpace.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2010 Erwin Coumans http://bulletphysics.org - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#ifndef BT_PPU_ADDRESS_SPACE_H -#define BT_PPU_ADDRESS_SPACE_H - - -#ifdef _WIN32 -//stop those casting warnings until we have a better solution for ppu_address_t / void* / uint64 conversions -#pragma warning (disable: 4311) -#pragma warning (disable: 4312) -#endif //_WIN32 - - -#if defined(_WIN64) - typedef unsigned __int64 ppu_address_t; -#elif defined(__LP64__) || defined(__x86_64__) - typedef uint64_t ppu_address_t; -#else - typedef uint32_t ppu_address_t; -#endif //defined(_WIN64) - -#endif //BT_PPU_ADDRESS_SPACE_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.cpp deleted file mode 100644 index 19992772..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 "SequentialThreadSupport.h" - - -#include "SpuCollisionTaskProcess.h" -#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" - -SequentialThreadSupport::SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo) -{ - startThreads(threadConstructionInfo); -} - -///cleanup/shutdown Libspe2 -SequentialThreadSupport::~SequentialThreadSupport() -{ - stopSPU(); -} - -#include - -///send messages to SPUs -void SequentialThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) -{ - switch (uiCommand) - { - case CMD_GATHER_AND_PROCESS_PAIRLIST: - { - btSpuStatus& spuStatus = m_activeSpuStatus[0]; - spuStatus.m_userPtr=(void*)uiArgument0; - spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); - } - break; - default: - { - ///not implemented - btAssert(0 && "Not implemented"); - } - - }; - - -} - -///check for messages from SPUs -void SequentialThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) -{ - btAssert(m_activeSpuStatus.size()); - btSpuStatus& spuStatus = m_activeSpuStatus[0]; - *puiArgument0 = spuStatus.m_taskId; - *puiArgument1 = spuStatus.m_status; -} - -void SequentialThreadSupport::startThreads(SequentialThreadConstructionInfo& threadConstructionInfo) -{ - m_activeSpuStatus.resize(1); - printf("STS: Not starting any threads\n"); - btSpuStatus& spuStatus = m_activeSpuStatus[0]; - spuStatus.m_userPtr = 0; - spuStatus.m_taskId = 0; - spuStatus.m_commandId = 0; - spuStatus.m_status = 0; - spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); - spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; - printf("STS: Created local store at %p for task %s\n", spuStatus.m_lsMemory, threadConstructionInfo.m_uniqueName); -} - -void SequentialThreadSupport::startSPU() -{ -} - -void SequentialThreadSupport::stopSPU() -{ - m_activeSpuStatus.clear(); -} - -void SequentialThreadSupport::setNumTasks(int numTasks) -{ - printf("SequentialThreadSupport::setNumTasks(%d) is not implemented and has no effect\n",numTasks); -} - - - - -class btDummyBarrier : public btBarrier -{ -private: - -public: - btDummyBarrier() - { - } - - virtual ~btDummyBarrier() - { - } - - void sync() - { - } - - virtual void setMaxCount(int n) {} - virtual int getMaxCount() {return 1;} -}; - -class btDummyCriticalSection : public btCriticalSection -{ - -public: - btDummyCriticalSection() - { - } - - virtual ~btDummyCriticalSection() - { - } - - unsigned int getSharedParam(int i) - { - btAssert(i>=0&&i<31); - return mCommonBuff[i+1]; - } - - void setSharedParam(int i,unsigned int p) - { - btAssert(i>=0&&i<31); - mCommonBuff[i+1] = p; - } - - void lock() - { - mCommonBuff[0] = 1; - } - - void unlock() - { - mCommonBuff[0] = 0; - } -}; - - - - -btBarrier* SequentialThreadSupport::createBarrier() -{ - return new btDummyBarrier(); -} - -btCriticalSection* SequentialThreadSupport::createCriticalSection() -{ - return new btDummyCriticalSection(); - -} - -void SequentialThreadSupport::deleteBarrier(btBarrier* barrier) -{ - delete barrier; -} - -void SequentialThreadSupport::deleteCriticalSection(btCriticalSection* criticalSection) -{ - delete criticalSection; -} - - - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.h deleted file mode 100644 index a188ef21..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SequentialThreadSupport.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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/btScalar.h" -#include "PlatformDefinitions.h" - - -#ifndef BT_SEQUENTIAL_THREAD_SUPPORT_H -#define BT_SEQUENTIAL_THREAD_SUPPORT_H - -#include "LinearMath/btAlignedObjectArray.h" - -#include "btThreadSupportInterface.h" - -typedef void (*SequentialThreadFunc)(void* userPtr,void* lsMemory); -typedef void* (*SequentiallsMemorySetupFunc)(); - - - -///The SequentialThreadSupport is a portable non-parallel implementation of the btThreadSupportInterface -///This is useful for debugging and porting SPU Tasks to other platforms. -class SequentialThreadSupport : public btThreadSupportInterface -{ -public: - struct btSpuStatus - { - uint32_t m_taskId; - uint32_t m_commandId; - uint32_t m_status; - - SequentialThreadFunc m_userThreadFunc; - - void* m_userPtr; //for taskDesc etc - void* m_lsMemory; //initialized using SequentiallsMemorySetupFunc - }; -private: - btAlignedObjectArray m_activeSpuStatus; - btAlignedObjectArray m_completeHandles; -public: - struct SequentialThreadConstructionInfo - { - SequentialThreadConstructionInfo (const char* uniqueName, - SequentialThreadFunc userThreadFunc, - SequentiallsMemorySetupFunc lsMemoryFunc - ) - :m_uniqueName(uniqueName), - m_userThreadFunc(userThreadFunc), - m_lsMemoryFunc(lsMemoryFunc) - { - - } - - const char* m_uniqueName; - SequentialThreadFunc m_userThreadFunc; - SequentiallsMemorySetupFunc m_lsMemoryFunc; - }; - - SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo); - virtual ~SequentialThreadSupport(); - void startThreads(SequentialThreadConstructionInfo& threadInfo); -///send messages to SPUs - virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); -///check for messages from SPUs - virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); -///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) - virtual void startSPU(); -///tell the task scheduler we are done with the SPU tasks - virtual void stopSPU(); - - virtual void setNumTasks(int numTasks); - - virtual int getNumTasks() const - { - return 1; - } - virtual btBarrier* createBarrier(); - - virtual btCriticalSection* createCriticalSection(); - - virtual void deleteBarrier(btBarrier* barrier); - - virtual void deleteCriticalSection(btCriticalSection* criticalSection); - - -}; - -#endif //BT_SEQUENTIAL_THREAD_SUPPORT_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp deleted file mode 100644 index 182aa269..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 "SpuCollisionObjectWrapper.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" - -SpuCollisionObjectWrapper::SpuCollisionObjectWrapper () -{ -} - -#ifndef __SPU__ -SpuCollisionObjectWrapper::SpuCollisionObjectWrapper (const btCollisionObject* collisionObject) -{ - m_shapeType = collisionObject->getCollisionShape()->getShapeType (); - m_collisionObjectPtr = (ppu_address_t)collisionObject; - m_margin = collisionObject->getCollisionShape()->getMargin (); -} -#endif - -int -SpuCollisionObjectWrapper::getShapeType () const -{ - return m_shapeType; -} - -float -SpuCollisionObjectWrapper::getCollisionMargin () const -{ - return m_margin; -} - -ppu_address_t -SpuCollisionObjectWrapper::getCollisionObjectPtr () const -{ - return m_collisionObjectPtr; -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h deleted file mode 100644 index f90da277..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionObjectWrapper.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_SPU_COLLISION_OBJECT_WRAPPER_H -#define BT_SPU_COLLISION_OBJECT_WRAPPER_H - -#include "PlatformDefinitions.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" - -ATTRIBUTE_ALIGNED16(class) SpuCollisionObjectWrapper -{ -protected: - int m_shapeType; - float m_margin; - ppu_address_t m_collisionObjectPtr; - -public: - SpuCollisionObjectWrapper (); - - SpuCollisionObjectWrapper (const btCollisionObject* collisionObject); - - int getShapeType () const; - float getCollisionMargin () const; - ppu_address_t getCollisionObjectPtr () const; -}; - - -#endif //BT_SPU_COLLISION_OBJECT_WRAPPER_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp deleted file mode 100644 index f606d136..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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. -*/ - - -//#define DEBUG_SPU_TASK_SCHEDULING 1 - - -//class OptimizedBvhNode; - -#include "SpuCollisionTaskProcess.h" - - - - -void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks) -{ - if (int(m_maxNumOutstandingTasks) != maxNumTasks) - { - m_maxNumOutstandingTasks = maxNumTasks; - m_taskBusy.resize(m_maxNumOutstandingTasks); - m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks); - - for (int i = 0; i < m_taskBusy.size(); i++) - { - m_taskBusy[i] = false; - } - - ///re-allocate task memory buffers - if (m_workUnitTaskBuffers != 0) - { - btAlignedFree(m_workUnitTaskBuffers); - } - - m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128); - } - -} - - - -SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks) -:m_threadInterface(threadInterface), -m_maxNumOutstandingTasks(0) -{ - m_workUnitTaskBuffers = (unsigned char *)0; - setNumTasks(maxNumOutstandingTasks); - m_numBusyTasks = 0; - m_currentTask = 0; - m_currentPage = 0; - m_currentPageEntry = 0; - -#ifdef DEBUG_SpuCollisionTaskProcess - m_initialized = false; -#endif - - m_threadInterface->startSPU(); - - //printf("sizeof vec_float4: %d\n", sizeof(vec_float4)); - printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput))); - -} - -SpuCollisionTaskProcess::~SpuCollisionTaskProcess() -{ - - if (m_workUnitTaskBuffers != 0) - { - btAlignedFree(m_workUnitTaskBuffers); - m_workUnitTaskBuffers = 0; - } - - - - m_threadInterface->stopSPU(); - -} - - - -void SpuCollisionTaskProcess::initialize2(bool useEpa) -{ - -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("SpuCollisionTaskProcess::initialize()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - - for (int i = 0; i < int (m_maxNumOutstandingTasks); i++) - { - m_taskBusy[i] = false; - } - m_numBusyTasks = 0; - m_currentTask = 0; - m_currentPage = 0; - m_currentPageEntry = 0; - m_useEpa = useEpa; - -#ifdef DEBUG_SpuCollisionTaskProcess - m_initialized = true; - btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE); -#endif -} - - -void SpuCollisionTaskProcess::issueTask2() -{ - -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask); -#endif //DEBUG_SPU_TASK_SCHEDULING - - m_taskBusy[m_currentTask] = true; - m_numBusyTasks++; - - - SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask]; - taskDesc.m_useEpa = m_useEpa; - - { - // send task description in event message - // no error checking here... - // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. - - taskDesc.m_inPairPtr = reinterpret_cast(MIDPHASE_TASK_PTR(m_currentTask)); - - taskDesc.taskId = m_currentTask; - taskDesc.numPages = m_currentPage+1; - taskDesc.numOnLastPage = m_currentPageEntry; - } - - - - m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask); - - // if all tasks busy, wait for spu event to clear the task. - - - if (m_numBusyTasks >= m_maxNumOutstandingTasks) - { - unsigned int taskId; - unsigned int outputSize; - - - for (int i=0;i=0); - - - m_threadInterface->waitForResponse(&taskId, &outputSize); - -// printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks); - - //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); - - //postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - -} - -void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex) -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("#"); -#endif //DEBUG_SPU_TASK_SCHEDULING - -#ifdef DEBUG_SpuCollisionTaskProcess - btAssert(m_initialized); - btAssert(m_workUnitTaskBuffers); - -#endif - - bool batch = true; - - if (batch) - { - if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE) - { - if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1) - { - // task buffer is full, issue current task. - // if all task buffers busy, this waits until SPU is done. - issueTask2(); - - // find new task buffer - for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) - { - if (!m_taskBusy[i]) - { - m_currentTask = i; - //init the task data - - break; - } - } - - m_currentPage = 0; - } - else - { - m_currentPage++; - } - - m_currentPageEntry = 0; - } - } - - { - - - - SpuGatherAndProcessWorkUnitInput &wuInput = - *(reinterpret_cast - (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry))); - - wuInput.m_pairArrayPtr = reinterpret_cast(pairArrayPtr); - wuInput.m_startIndex = startIndex; - wuInput.m_endIndex = endIndex; - - - - m_currentPageEntry++; - - if (!batch) - { - issueTask2(); - - // find new task buffer - for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) - { - if (!m_taskBusy[i]) - { - m_currentTask = i; - //init the task data - - break; - } - } - - m_currentPage = 0; - m_currentPageEntry =0; - } - } -} - - -void -SpuCollisionTaskProcess::flush2() -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("\nSpuCollisionTaskProcess::flush()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - - // if there's a partially filled task buffer, submit that task - if (m_currentPage > 0 || m_currentPageEntry > 0) - { - issueTask2(); - } - - - // all tasks are issued, wait for all tasks to be complete - while(m_numBusyTasks > 0) - { - // Consolidating SPU code - unsigned int taskId=-1; - unsigned int outputSize; - - for (int i=0;i=0); - - - { - - // SPURS support. - m_threadInterface->waitForResponse(&taskId, &outputSize); - } -// printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks); - //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); - - //postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - - -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.h deleted file mode 100644 index 23b5b05a..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuCollisionTaskProcess.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_SPU_COLLISION_TASK_PROCESS_H -#define BT_SPU_COLLISION_TASK_PROCESS_H - -#include - -#include "LinearMath/btScalar.h" - -#include "PlatformDefinitions.h" -#include "LinearMath/btAlignedObjectArray.h" -#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory - -#include "btThreadSupportInterface.h" - - -//#include "SPUAssert.h" -#include - - -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" - -#include "LinearMath/btAlignedAllocator.h" - -#include - - -#define DEBUG_SpuCollisionTaskProcess 1 - - -#define CMD_GATHER_AND_PROCESS_PAIRLIST 1 - -class btCollisionObject; -class btPersistentManifold; -class btDispatcher; - - -/////Task Description for SPU collision detection -//struct SpuGatherAndProcessPairsTaskDesc -//{ -// uint64_t inPtr;//m_pairArrayPtr; -// //mutex variable -// uint32_t m_someMutexVariableInMainMemory; -// -// uint64_t m_dispatcher; -// -// uint32_t numOnLastPage; -// -// uint16_t numPages; -// uint16_t taskId; -// -// struct CollisionTask_LocalStoreMemory* m_lsMemory; -//} -// -//#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) -//__attribute__ ((aligned (16))) -//#endif -//; - - -///MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input, to be processed by the SPU. -ATTRIBUTE_ALIGNED16(struct) SpuGatherAndProcessWorkUnitInput -{ - uint64_t m_pairArrayPtr; - int m_startIndex; - int m_endIndex; -}; - - - - -/// SpuCollisionTaskProcess handles SPU processing of collision pairs. -/// Maintains a set of task buffers. -/// When the task is full, the task is issued for SPUs to process. Contact output goes into btPersistentManifold -/// associated with each task. -/// When PPU issues a task, it will look for completed task buffers -/// PPU will do postprocessing, dependent on workunit output (not likely) -class SpuCollisionTaskProcess -{ - - unsigned char *m_workUnitTaskBuffers; - - - // track task buffers that are being used, and total busy tasks - btAlignedObjectArray m_taskBusy; - btAlignedObjectArray m_spuGatherTaskDesc; - - class btThreadSupportInterface* m_threadInterface; - - unsigned int m_maxNumOutstandingTasks; - - unsigned int m_numBusyTasks; - - // the current task and the current entry to insert a new work unit - unsigned int m_currentTask; - unsigned int m_currentPage; - unsigned int m_currentPageEntry; - - bool m_useEpa; - -#ifdef DEBUG_SpuCollisionTaskProcess - bool m_initialized; -#endif - void issueTask2(); - //void postProcess(unsigned int taskId, int outputSize); - -public: - SpuCollisionTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks); - - ~SpuCollisionTaskProcess(); - - ///call initialize in the beginning of the frame, before addCollisionPairToTask - void initialize2(bool useEpa = false); - - ///batch up additional work to a current task for SPU processing. When batch is full, it issues the task. - void addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex); - - ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished - void flush2(); - - /// set the maximum number of SPU tasks allocated - void setNumTasks(int maxNumTasks); - - int getNumTasks() const - { - return m_maxNumOutstandingTasks; - } -}; - - - -#define MIDPHASE_TASK_PTR(task) (&m_workUnitTaskBuffers[0] + MIDPHASE_WORKUNIT_TASK_SIZE*task) -#define MIDPHASE_ENTRY_PTR(task,page,entry) (MIDPHASE_TASK_PTR(task) + MIDPHASE_WORKUNIT_PAGE_SIZE*page + sizeof(SpuGatherAndProcessWorkUnitInput)*entry) -#define MIDPHASE_OUTPUT_PTR(task) (&m_contactOutputBuffers[0] + MIDPHASE_MAX_CONTACT_BUFFER_SIZE*task) -#define MIDPHASE_TREENODES_PTR(task) (&m_complexShapeBuffers[0] + MIDPHASE_COMPLEX_SHAPE_BUFFER_SIZE*task) - - -#define MIDPHASE_WORKUNIT_PAGE_SIZE (16) -//#define MIDPHASE_WORKUNIT_PAGE_SIZE (128) - -#define MIDPHASE_NUM_WORKUNIT_PAGES 1 -#define MIDPHASE_WORKUNIT_TASK_SIZE (MIDPHASE_WORKUNIT_PAGE_SIZE*MIDPHASE_NUM_WORKUNIT_PAGES) -#define MIDPHASE_NUM_WORKUNITS_PER_PAGE (MIDPHASE_WORKUNIT_PAGE_SIZE / sizeof(SpuGatherAndProcessWorkUnitInput)) -#define MIDPHASE_NUM_WORKUNITS_PER_TASK (MIDPHASE_NUM_WORKUNITS_PER_PAGE*MIDPHASE_NUM_WORKUNIT_PAGES) - - -#endif // BT_SPU_COLLISION_TASK_PROCESS_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp deleted file mode 100644 index 62cf4f0f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 "SpuContactManifoldCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" - - - - -void SpuContactManifoldCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - btAssert(0); -} - -btScalar SpuContactManifoldCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - btAssert(0); - return 1.f; -} - -#ifndef __SPU__ -SpuContactManifoldCollisionAlgorithm::SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObject* body0,const btCollisionObject* body1) -:btCollisionAlgorithm(ci) -#ifdef USE_SEPDISTANCE_UTIL -,m_sepDistance(body0->getCollisionShape()->getAngularMotionDisc(),body1->getCollisionShape()->getAngularMotionDisc()) -#endif //USE_SEPDISTANCE_UTIL -{ - m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); - m_shapeType0 = body0->getCollisionShape()->getShapeType(); - m_shapeType1 = body1->getCollisionShape()->getShapeType(); - m_collisionMargin0 = body0->getCollisionShape()->getMargin(); - m_collisionMargin1 = body1->getCollisionShape()->getMargin(); - m_collisionObject0 = body0; - m_collisionObject1 = body1; - - if (body0->getCollisionShape()->isPolyhedral()) - { - btPolyhedralConvexShape* convex0 = (btPolyhedralConvexShape*)body0->getCollisionShape(); - m_shapeDimensions0 = convex0->getImplicitShapeDimensions(); - } - if (body1->getCollisionShape()->isPolyhedral()) - { - btPolyhedralConvexShape* convex1 = (btPolyhedralConvexShape*)body1->getCollisionShape(); - m_shapeDimensions1 = convex1->getImplicitShapeDimensions(); - } -} -#endif //__SPU__ - - -SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm() -{ - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h deleted file mode 100644 index 14b0a945..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H -#define BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "LinearMath/btTransformUtil.h" -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - -class btPersistentManifold; - -//#define USE_SEPDISTANCE_UTIL 1 - -/// SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU. -ATTRIBUTE_ALIGNED16(class) SpuContactManifoldCollisionAlgorithm : public btCollisionAlgorithm -{ - btVector3 m_shapeDimensions0; - btVector3 m_shapeDimensions1; - btPersistentManifold* m_manifoldPtr; - int m_shapeType0; - int m_shapeType1; - float m_collisionMargin0; - float m_collisionMargin1; - - const btCollisionObject* m_collisionObject0; - const btCollisionObject* m_collisionObject1; - - - - -public: - - virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - - SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObject* body0,const btCollisionObject* body1); -#ifdef USE_SEPDISTANCE_UTIL - btConvexSeparatingDistanceUtil m_sepDistance; -#endif //USE_SEPDISTANCE_UTIL - - virtual ~SpuContactManifoldCollisionAlgorithm(); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr) - manifoldArray.push_back(m_manifoldPtr); - } - - btPersistentManifold* getContactManifoldPtr() - { - return m_manifoldPtr; - } - - const btCollisionObject* getCollisionObject0() - { - return m_collisionObject0; - } - - const btCollisionObject* getCollisionObject1() - { - return m_collisionObject1; - } - - int getShapeType0() const - { - return m_shapeType0; - } - - int getShapeType1() const - { - return m_shapeType1; - } - float getCollisionMargin0() const - { - return m_collisionMargin0; - } - float getCollisionMargin1() const - { - return m_collisionMargin1; - } - - const btVector3& getShapeDimensions0() const - { - return m_shapeDimensions0; - } - - const btVector3& getShapeDimensions1() const - { - return m_shapeDimensions1; - } - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(SpuContactManifoldCollisionAlgorithm)); - return new(mem) SpuContactManifoldCollisionAlgorithm(ci,body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); - } - }; - -}; - -#endif //BT_SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuDoubleBuffer.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuDoubleBuffer.h deleted file mode 100644 index 558d6152..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuDoubleBuffer.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_DOUBLE_BUFFER_H -#define BT_DOUBLE_BUFFER_H - -#include "SpuFakeDma.h" -#include "LinearMath/btScalar.h" - - -///DoubleBuffer -template -class DoubleBuffer -{ -#if defined(__SPU__) || defined(USE_LIBSPE2) - ATTRIBUTE_ALIGNED128( T m_buffer0[size] ) ; - ATTRIBUTE_ALIGNED128( T m_buffer1[size] ) ; -#else - T m_buffer0[size]; - T m_buffer1[size]; -#endif - - T *m_frontBuffer; - T *m_backBuffer; - - unsigned int m_dmaTag; - bool m_dmaPending; -public: - bool isPending() const { return m_dmaPending;} - DoubleBuffer(); - - void init (); - - // dma get and put commands - void backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag); - void backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag); - - // gets pointer to a buffer - T *getFront(); - T *getBack(); - - // if back buffer dma was started, wait for it to complete - // then move back to front and vice versa - T *swapBuffers(); -}; - -template -DoubleBuffer::DoubleBuffer() -{ - init (); -} - -template -void DoubleBuffer::init() -{ - this->m_dmaPending = false; - this->m_frontBuffer = &this->m_buffer0[0]; - this->m_backBuffer = &this->m_buffer1[0]; -} - -template -void -DoubleBuffer::backBufferDmaGet(uint64_t ea, unsigned int numBytes, unsigned int tag) -{ - m_dmaPending = true; - m_dmaTag = tag; - if (numBytes) - { - m_backBuffer = (T*)cellDmaLargeGetReadOnly(m_backBuffer, ea, numBytes, tag, 0, 0); - } -} - -template -void -DoubleBuffer::backBufferDmaPut(uint64_t ea, unsigned int numBytes, unsigned int tag) -{ - m_dmaPending = true; - m_dmaTag = tag; - cellDmaLargePut(m_backBuffer, ea, numBytes, tag, 0, 0); -} - -template -T * -DoubleBuffer::getFront() -{ - return m_frontBuffer; -} - -template -T * -DoubleBuffer::getBack() -{ - return m_backBuffer; -} - -template -T * -DoubleBuffer::swapBuffers() -{ - if (m_dmaPending) - { - cellDmaWaitTagStatusAll(1< //for btAssert -//Disabling memcpy sometimes helps debugging DMA - -#define USE_MEMCPY 1 -#ifdef USE_MEMCPY - -#endif - - -void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) -{ - -#if defined (__SPU__) || defined (USE_LIBSPE2) - cellDmaLargeGet(ls,ea,size,tag,tid,rid); - return ls; -#else - return (void*)(ppu_address_t)ea; -#endif -} - -void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) -{ -#if defined (__SPU__) || defined (USE_LIBSPE2) - mfc_get(ls,ea,size,tag,0,0); - return ls; -#else - return (void*)(ppu_address_t)ea; -#endif -} - - - - -void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid) -{ -#if defined (__SPU__) || defined (USE_LIBSPE2) - cellDmaGet(ls,ea,size,tag,tid,rid); - return ls; -#else - return (void*)(ppu_address_t)ea; -#endif -} - - -///this unalignedDma should not be frequently used, only for small data. It handles alignment and performs check on size (<16 bytes) -int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size) -{ - - btAssert(size<32); - - ATTRIBUTE_ALIGNED16(char tmpBuffer[32]); - - - char* localStore = (char*)ls; - uint32_t i; - - - ///make sure last 4 bits are the same, for cellDmaSmallGet - uint32_t last4BitsOffset = ea & 0x0f; - char* tmpTarget = tmpBuffer + last4BitsOffset; - -#if defined (__SPU__) || defined (USE_LIBSPE2) - - int remainingSize = size; - -//#define FORCE_cellDmaUnalignedGet 1 -#ifdef FORCE_cellDmaUnalignedGet - cellDmaUnalignedGet(tmpTarget,ea,size,DMA_TAG(1),0,0); -#else - char* remainingTmpTarget = tmpTarget; - uint64_t remainingEa = ea; - - while (remainingSize) - { - switch (remainingSize) - { - case 1: - case 2: - case 4: - case 8: - case 16: - { - mfc_get(remainingTmpTarget,remainingEa,remainingSize,DMA_TAG(1),0,0); - remainingSize=0; - break; - } - default: - { - //spu_printf("unaligned DMA with non-natural size:%d\n",remainingSize); - int actualSize = 0; - - if (remainingSize > 16) - actualSize = 16; - else - if (remainingSize >8) - actualSize=8; - else - if (remainingSize >4) - actualSize=4; - else - if (remainingSize >2) - actualSize=2; - mfc_get(remainingTmpTarget,remainingEa,actualSize,DMA_TAG(1),0,0); - remainingSize-=actualSize; - remainingTmpTarget+=actualSize; - remainingEa += actualSize; - } - } - } -#endif//FORCE_cellDmaUnalignedGet - -#else - char* mainMem = (char*)ea; - //copy into final destination -#ifdef USE_MEMCPY - - memcpy(tmpTarget,mainMem,size); -#else - for ( i=0;i -#include - -#define DMA_TAG(xfer) (xfer + 1) -#define DMA_MASK(xfer) (1 << DMA_TAG(xfer)) - -#else // !USE_LIBSPE2 - -#define DMA_TAG(xfer) (xfer + 1) -#define DMA_MASK(xfer) (1 << DMA_TAG(xfer)) - -#include - -#define DEBUG_DMA -#ifdef DEBUG_DMA -#define dUASSERT(a,b) if (!(a)) { printf(b);} -#define uintsize ppu_address_t - -#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ - dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ - dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ - dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ - dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ - dUASSERT(size < 16384, "size too big: "); \ - dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ - dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ - printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ - } \ - mfc_get(ls, ea, size, tag, tid, rid) -#define cellDmaGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ - dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ - dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ - dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ - dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ - dUASSERT(size < 16384, "size too big: "); \ - dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ - dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ - printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ - } \ - mfc_get(ls, ea, size, tag, tid, rid) -#define cellDmaLargePut(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ - dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ - dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ - dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ - dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ - dUASSERT(size < 16384, "size too big: "); \ - dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ - dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ - printf("PUT %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ls,(unsigned int)ea,(unsigned int)size); \ - } \ - mfc_put(ls, ea, size, tag, tid, rid) -#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) if ( (((uintsize)ls%16) != ((uintsize)ea%16)) || ((((uintsize)ea%16) || ((uintsize)ls%16)) && (( ((uintsize)ls%16) != ((uintsize)size%16) ) || ( ((uintsize)ea%16) != ((uintsize)size%16) ) ) ) || ( ((uintsize)size%16) && ((uintsize)size!=1) && ((uintsize)size!=2) && ((uintsize)size!=4) && ((uintsize)size!=8) ) || (size >= 16384) || !(uintsize)ls || !(uintsize)ea) { \ - dUASSERT( (((uintsize)ea % 16) == 0) || (size < 16), "XDR Address not aligned: "); \ - dUASSERT( (((uintsize)ls % 16) == 0) || (size < 16), "LS Address not aligned: "); \ - dUASSERT( ((((uintsize)ls % size) == 0) && (((uintsize)ea % size) == 0)) || (size > 16), "Not naturally aligned: "); \ - dUASSERT((size == 1) || (size == 2) || (size == 4) || (size == 8) || ((size % 16) == 0), "size not a multiple of 16byte: "); \ - dUASSERT(size < 16384, "size too big: "); \ - dUASSERT( ((uintsize)ea%16)==((uintsize)ls%16), "wrong Quadword alignment of LS and EA: "); \ - dUASSERT(ea != 0, "Nullpointer EA: "); dUASSERT(ls != 0, "Nullpointer LS: ");\ - printf("GET %s:%d from: 0x%x, to: 0x%x - %d bytes\n", __FILE__, __LINE__, (unsigned int)ea,(unsigned int)ls,(unsigned int)size);\ - } \ - mfc_get(ls, ea, size, tag, tid, rid) -#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all() - -#else -#define cellDmaLargeGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) -#define cellDmaGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) -#define cellDmaLargePut(ls, ea, size, tag, tid, rid) mfc_put(ls, ea, size, tag, tid, rid) -#define cellDmaSmallGet(ls, ea, size, tag, tid, rid) mfc_get(ls, ea, size, tag, tid, rid) -#define cellDmaWaitTagStatusAll(ignore) mfc_write_tag_mask(ignore) ; mfc_read_tag_status_all() -#endif // DEBUG_DMA - - - - - - - - -#endif // USE_LIBSPE2 -#else // !__SPU__ -//Simulate DMA using memcpy or direct access on non-CELL platforms that don't have DMAs and SPUs (Win32, Mac, Linux etc) -//Potential to add networked simulation using this interface - -#define DMA_TAG(a) (a) -#define DMA_MASK(a) (a) - - /// cellDmaLargeGet Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) - int cellDmaLargeGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); - int cellDmaGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); - /// cellDmaLargePut Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) - int cellDmaLargePut(const void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); - /// cellDmaWaitTagStatusAll Win32 replacements for Cell DMA to allow simulating most of the SPU code (just memcpy) - void cellDmaWaitTagStatusAll(int ignore); - - -#endif //__CELLOS_LV2__ - -///stallingUnalignedDmaSmallGet internally uses DMA_TAG(1) -int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size); - - -void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); -void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); -void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid); - - -#endif //BT_FAKE_DMA_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp deleted file mode 100644 index c8712dab..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 "SpuGatheringCollisionDispatcher.h" -#include "SpuCollisionTaskProcess.h" - - -#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" -#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" -#include "SpuContactManifoldCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "LinearMath/btQuickprof.h" -#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h" -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - - - - -SpuGatheringCollisionDispatcher::SpuGatheringCollisionDispatcher(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration) -:btCollisionDispatcher(collisionConfiguration), -m_spuCollisionTaskProcess(0), -m_threadInterface(threadInterface), -m_maxNumOutstandingTasks(maxNumOutstandingTasks) -{ - -} - - -bool SpuGatheringCollisionDispatcher::supportsDispatchPairOnSpu(int proxyType0,int proxyType1) -{ - bool supported0 = ( - (proxyType0 == BOX_SHAPE_PROXYTYPE) || - (proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) || - (proxyType0 == SPHERE_SHAPE_PROXYTYPE) || - (proxyType0 == CAPSULE_SHAPE_PROXYTYPE) || - (proxyType0 == CYLINDER_SHAPE_PROXYTYPE) || -// (proxyType0 == CONE_SHAPE_PROXYTYPE) || - (proxyType0 == TRIANGLE_MESH_SHAPE_PROXYTYPE) || - (proxyType0 == CONVEX_HULL_SHAPE_PROXYTYPE)|| - (proxyType0 == STATIC_PLANE_PROXYTYPE)|| - (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) - ); - - bool supported1 = ( - (proxyType1 == BOX_SHAPE_PROXYTYPE) || - (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE) || - (proxyType1 == SPHERE_SHAPE_PROXYTYPE) || - (proxyType1 == CAPSULE_SHAPE_PROXYTYPE) || - (proxyType1 == CYLINDER_SHAPE_PROXYTYPE) || -// (proxyType1 == CONE_SHAPE_PROXYTYPE) || - (proxyType1 == TRIANGLE_MESH_SHAPE_PROXYTYPE) || - (proxyType1 == CONVEX_HULL_SHAPE_PROXYTYPE) || - (proxyType1 == STATIC_PLANE_PROXYTYPE) || - (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) - ); - - - return supported0 && supported1; -} - - - -SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher() -{ - if (m_spuCollisionTaskProcess) - delete m_spuCollisionTaskProcess; - -} - -#include "stdio.h" - - - -///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) -///this is useful for the collision dispatcher. -class btSpuCollisionPairCallback : public btOverlapCallback -{ - const btDispatcherInfo& m_dispatchInfo; - SpuGatheringCollisionDispatcher* m_dispatcher; - -public: - - btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher* dispatcher) - :m_dispatchInfo(dispatchInfo), - m_dispatcher(dispatcher) - { - } - - virtual bool processOverlap(btBroadphasePair& collisionPair) - { - - - //PPU version - //(*m_dispatcher->getNearCallback())(collisionPair,*m_dispatcher,m_dispatchInfo); - - //only support discrete collision detection for now, we could fallback on PPU/unoptimized version for TOI/CCD - btAssert(m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE); - - //by default, Bullet will use this near callback - { - ///userInfo is used to determine if the SPU has to handle this case or not (skip PPU tasks) - if (!collisionPair.m_internalTmpValue) - { - collisionPair.m_internalTmpValue = 1; - } - if (!collisionPair.m_algorithm) - { - btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; - btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; - - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher1 = m_dispatcher; - ci.m_manifold = 0; - - if (m_dispatcher->needsCollision(colObj0,colObj1)) - { - int proxyType0 = colObj0->getCollisionShape()->getShapeType(); - int proxyType1 = colObj1->getCollisionShape()->getShapeType(); - bool supportsSpuDispatch = m_dispatcher->supportsDispatchPairOnSpu(proxyType0,proxyType1) - && ((colObj0->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0) - && ((colObj1->getCollisionFlags() & btCollisionObject::CF_DISABLE_SPU_COLLISION_PROCESSING) == 0); - - if (proxyType0 == COMPOUND_SHAPE_PROXYTYPE) - { - btCompoundShape* compound = (btCompoundShape*)colObj0->getCollisionShape(); - if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) - { - //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); - supportsSpuDispatch = false; - } - } - - if (proxyType1 == COMPOUND_SHAPE_PROXYTYPE) - { - btCompoundShape* compound = (btCompoundShape*)colObj1->getCollisionShape(); - if (compound->getNumChildShapes()>MAX_SPU_COMPOUND_SUBSHAPES) - { - //printf("PPU fallback, compound->getNumChildShapes(%d)>%d\n",compound->getNumChildShapes(),MAX_SPU_COMPOUND_SUBSHAPES); - supportsSpuDispatch = false; - } - } - - if (supportsSpuDispatch) - { - - int so = sizeof(SpuContactManifoldCollisionAlgorithm); -#ifdef ALLOCATE_SEPARATELY - void* mem = btAlignedAlloc(so,16);//m_dispatcher->allocateCollisionAlgorithm(so); -#else - void* mem = m_dispatcher->allocateCollisionAlgorithm(so); -#endif - collisionPair.m_algorithm = new(mem) SpuContactManifoldCollisionAlgorithm(ci,colObj0,colObj1); - collisionPair.m_internalTmpValue = 2; - } else - { - btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1); - btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1); - - collisionPair.m_algorithm = m_dispatcher->findAlgorithm(&ob0,&ob1); - collisionPair.m_internalTmpValue = 3; - } - } - } - } - return false; - } -}; - -void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) -{ - - if (dispatchInfo.m_enableSPU) - { - m_maxNumOutstandingTasks = m_threadInterface->getNumTasks(); - - { - BT_PROFILE("processAllOverlappingPairs"); - - if (!m_spuCollisionTaskProcess) - m_spuCollisionTaskProcess = new SpuCollisionTaskProcess(m_threadInterface,m_maxNumOutstandingTasks); - - m_spuCollisionTaskProcess->setNumTasks(m_maxNumOutstandingTasks); - // printf("m_maxNumOutstandingTasks =%d\n",m_maxNumOutstandingTasks); - - m_spuCollisionTaskProcess->initialize2(dispatchInfo.m_useEpa); - - - ///modified version of btCollisionDispatcher::dispatchAllCollisionPairs: - { - btSpuCollisionPairCallback collisionCallback(dispatchInfo,this); - - pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); - } - } - - //send one big batch - int numTotalPairs = pairCache->getNumOverlappingPairs(); - if (numTotalPairs) - { - btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr(); - int i; - { - int pairRange = SPU_BATCHSIZE_BROADPHASE_PAIRS; - if (numTotalPairs < (m_spuCollisionTaskProcess->getNumTasks()*SPU_BATCHSIZE_BROADPHASE_PAIRS)) - { - pairRange = (numTotalPairs/m_spuCollisionTaskProcess->getNumTasks())+1; - } - - BT_PROFILE("addWorkToTask"); - for (i=0;iaddWorkToTask(pairPtr,i,endIndex); - i = endIndex; - } - } - { - BT_PROFILE("PPU fallback"); - //handle PPU fallback pairs - for (i=0;im_clientObject; - btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; - - if (dispatcher->needsCollision(colObj0,colObj1)) - { - //discrete collision detection query - btCollisionObjectWrapper ob0(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1); - btCollisionObjectWrapper ob1(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1); - - btManifoldResult contactPointResult(&ob0,&ob1); - - if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) - { - - collisionPair.m_algorithm->processCollision(&ob0,&ob1,dispatchInfo,&contactPointResult); - } else - { - //continuous collision detection query, time of impact (toi) - btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); - if (dispatchInfo.m_timeOfImpact > toi) - dispatchInfo.m_timeOfImpact = toi; - - } - } - } - } - } - } - } - { - BT_PROFILE("flush2"); - //make sure all SPU work is done - m_spuCollisionTaskProcess->flush2(); - } - - } else - { - ///PPU fallback - ///!Need to make sure to clear all 'algorithms' when switching between SPU and PPU - btCollisionDispatcher::dispatchAllCollisionPairs(pairCache,dispatchInfo,dispatcher); - } -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h deleted file mode 100644 index f8bc7da6..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_SPU_GATHERING_COLLISION__DISPATCHER_H -#define BT_SPU_GATHERING_COLLISION__DISPATCHER_H - -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" - - -///Tuning value to optimized SPU utilization -///Too small value means Task overhead is large compared to computation (too fine granularity) -///Too big value might render some SPUs are idle, while a few other SPUs are doing all work. -//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8 -//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16 -//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64 -#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128 -//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256 -//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 512 -//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024 - - - -class SpuCollisionTaskProcess; - -///SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection -///Time of Impact, Closest Points and Penetration Depth. -class SpuGatheringCollisionDispatcher : public btCollisionDispatcher -{ - - SpuCollisionTaskProcess* m_spuCollisionTaskProcess; - -protected: - - class btThreadSupportInterface* m_threadInterface; - - unsigned int m_maxNumOutstandingTasks; - - -public: - - //can be used by SPU collision algorithms - SpuCollisionTaskProcess* getSpuCollisionTaskProcess() - { - return m_spuCollisionTaskProcess; - } - - SpuGatheringCollisionDispatcher (class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration); - - virtual ~SpuGatheringCollisionDispatcher(); - - bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1); - - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; - -}; - - - -#endif //BT_SPU_GATHERING_COLLISION__DISPATCHER_H - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.cpp deleted file mode 100644 index a312450e..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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. -*/ - -#ifdef USE_LIBSPE2 - -#include "SpuLibspe2Support.h" - - - - -//SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication -///Setup and initialize SPU/CELL/Libspe2 -SpuLibspe2Support::SpuLibspe2Support(spe_program_handle_t *speprog, int numThreads) -{ - this->program = speprog; - this->numThreads = ((numThreads <= spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)) ? numThreads : spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)); -} - -///cleanup/shutdown Libspe2 -SpuLibspe2Support::~SpuLibspe2Support() -{ - - stopSPU(); -} - - - -///send messages to SPUs -void SpuLibspe2Support::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1) -{ - spe_context_ptr_t context; - - switch (uiCommand) - { - case CMD_SAMPLE_TASK_COMMAND: - { - //get taskdescription - SpuSampleTaskDesc* taskDesc = (SpuSampleTaskDesc*) uiArgument0; - - btAssert(taskDesc->m_taskIdm_taskId]; - - //set data for spuStatus - spuStatus.m_commandId = uiCommand; - spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" - spuStatus.m_taskDesc.p = taskDesc; - - //get context - context = data[taskDesc->m_taskId].context; - - - taskDesc->m_mainMemoryPtr = reinterpret_cast (spuStatus.m_lsMemory.p); - - - break; - } - case CMD_GATHER_AND_PROCESS_PAIRLIST: - { - //get taskdescription - SpuGatherAndProcessPairsTaskDesc* taskDesc = (SpuGatherAndProcessPairsTaskDesc*) uiArgument0; - - btAssert(taskDesc->taskIdtaskId]; - - //set data for spuStatus - spuStatus.m_commandId = uiCommand; - spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" - spuStatus.m_taskDesc.p = taskDesc; - - //get context - context = data[taskDesc->taskId].context; - - - taskDesc->m_lsMemory = (CollisionTask_LocalStoreMemory*)spuStatus.m_lsMemory.p; - - break; - } - default: - { - ///not implemented - btAssert(0); - } - - }; - - - //write taskdescription in mailbox - unsigned int event = Spu_Mailbox_Event_Task; - spe_in_mbox_write(context, &event, 1, SPE_MBOX_ANY_NONBLOCKING); - -} - -///check for messages from SPUs -void SpuLibspe2Support::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) -{ - ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response - - ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' - - btAssert(m_activeSpuStatus.size()); - - - int last = -1; - - //find an active spu/thread - while(last < 0) - { - for (int i=0;i=0); - - - - *puiArgument0 = spuStatus.m_taskId; - *puiArgument1 = spuStatus.m_status; - - -} - - -void SpuLibspe2Support::startSPU() -{ - this->internal_startSPU(); -} - - - -///start the spus group (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) -void SpuLibspe2Support::internal_startSPU() -{ - m_activeSpuStatus.resize(numThreads); - - - for (int i=0; i < numThreads; i++) - { - - if(data[i].context == NULL) - { - - /* Create context */ - if ((data[i].context = spe_context_create(0, NULL)) == NULL) - { - perror ("Failed creating context"); - exit(1); - } - - /* Load program into context */ - if(spe_program_load(data[i].context, this->program)) - { - perror ("Failed loading program"); - exit(1); - } - - m_activeSpuStatus[i].m_status = Spu_Status_Startup; - m_activeSpuStatus[i].m_taskId = i; - m_activeSpuStatus[i].m_commandId = 0; - m_activeSpuStatus[i].m_lsMemory.p = NULL; - - - data[i].entry = SPE_DEFAULT_ENTRY; - data[i].flags = 0; - data[i].argp.p = &m_activeSpuStatus[i]; - data[i].envp.p = NULL; - - /* Create thread for each SPE context */ - if (pthread_create(&data[i].pthread, NULL, &ppu_pthread_function, &(data[i]) )) - { - perror ("Failed creating thread"); - exit(1); - } - /* - else - { - printf("started thread %d\n",i); - }*/ - } - } - - - for (int i=0; i < numThreads; i++) - { - if(data[i].context != NULL) - { - while( m_activeSpuStatus[i].m_status == Spu_Status_Startup) - { - // wait for spu to set up - sched_yield(); - } - printf("Spu %d is ready\n", i); - } - } -} - -///tell the task scheduler we are done with the SPU tasks -void SpuLibspe2Support::stopSPU() -{ - // wait for all threads to finish - int i; - for ( i = 0; i < this->numThreads; i++ ) - { - - unsigned int event = Spu_Mailbox_Event_Shutdown; - spe_context_ptr_t context = data[i].context; - spe_in_mbox_write(context, &event, 1, SPE_MBOX_ALL_BLOCKING); - pthread_join (data[i].pthread, NULL); - - } - // close SPE program - spe_image_close(program); - // destroy SPE contexts - for ( i = 0; i < this->numThreads; i++ ) - { - if(data[i].context != NULL) - { - spe_context_destroy (data[i].context); - } - } - - m_activeSpuStatus.clear(); - -} - - - -#endif //USE_LIBSPE2 - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.h deleted file mode 100644 index 37a5e79f..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuLibspe2Support.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_SPU_LIBSPE2_SUPPORT_H -#define BT_SPU_LIBSPE2_SUPPORT_H - -#include //for uint32_t etc. - -#ifdef USE_LIBSPE2 - -#include -#include -//#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" -#include "PlatformDefinitions.h" - - -//extern struct SpuGatherAndProcessPairsTaskDesc; - -enum -{ - Spu_Mailbox_Event_Nothing = 0, - Spu_Mailbox_Event_Task = 1, - Spu_Mailbox_Event_Shutdown = 2, - - Spu_Mailbox_Event_ForceDword = 0xFFFFFFFF - -}; - -enum -{ - Spu_Status_Free = 0, - Spu_Status_Occupied = 1, - Spu_Status_Startup = 2, - - Spu_Status_ForceDword = 0xFFFFFFFF - -}; - - -struct btSpuStatus -{ - uint32_t m_taskId; - uint32_t m_commandId; - uint32_t m_status; - - addr64 m_taskDesc; - addr64 m_lsMemory; - -} -__attribute__ ((aligned (128))) -; - - - -#ifndef __SPU__ - -#include "LinearMath/btAlignedObjectArray.h" -#include "SpuCollisionTaskProcess.h" -#include "SpuSampleTaskProcess.h" -#include "btThreadSupportInterface.h" -#include -#include -#include - -#define MAX_SPUS 4 - -typedef struct ppu_pthread_data -{ - spe_context_ptr_t context; - pthread_t pthread; - unsigned int entry; - unsigned int flags; - addr64 argp; - addr64 envp; - spe_stop_info_t stopinfo; -} ppu_pthread_data_t; - - -static void *ppu_pthread_function(void *arg) -{ - ppu_pthread_data_t * datap = (ppu_pthread_data_t *)arg; - /* - int rc; - do - {*/ - spe_context_run(datap->context, &datap->entry, datap->flags, datap->argp.p, datap->envp.p, &datap->stopinfo); - if (datap->stopinfo.stop_reason == SPE_EXIT) - { - if (datap->stopinfo.result.spe_exit_code != 0) - { - perror("FAILED: SPE returned a non-zero exit status: \n"); - exit(1); - } - } - else - { - perror("FAILED: SPE abnormally terminated\n"); - exit(1); - } - - - //} while (rc > 0); // loop until exit or error, and while any stop & signal - pthread_exit(NULL); -} - - - - - - -///SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication -class SpuLibspe2Support : public btThreadSupportInterface -{ - - btAlignedObjectArray m_activeSpuStatus; - -public: - //Setup and initialize SPU/CELL/Libspe2 - SpuLibspe2Support(spe_program_handle_t *speprog,int numThreads); - - // SPE program handle ptr. - spe_program_handle_t *program; - - // SPE program data - ppu_pthread_data_t data[MAX_SPUS]; - - //cleanup/shutdown Libspe2 - ~SpuLibspe2Support(); - - ///send messages to SPUs - void sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1=0); - - //check for messages from SPUs - void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); - - //start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) - virtual void startSPU(); - - //tell the task scheduler we are done with the SPU tasks - virtual void stopSPU(); - - virtual void setNumTasks(int numTasks) - { - //changing the number of tasks after initialization is not implemented (yet) - } - -private: - - ///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) - void internal_startSPU(); - - - - - int numThreads; - -}; - -#endif // NOT __SPU__ - -#endif //USE_LIBSPE2 - -#endif //BT_SPU_LIBSPE2_SUPPORT_H - - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h deleted file mode 100644 index e5179611..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. - All rights reserved. - -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 __BOX_H__ -#define __BOX_H__ - - -#ifndef PE_REF -#define PE_REF(a) a& -#endif - -#include - - -#include "../PlatformDefinitions.h" - - - - -enum FeatureType { F, E, V }; - -//---------------------------------------------------------------------------- -// Box -//---------------------------------------------------------------------------- -///The Box is an internal class used by the boxBoxDistance calculation. -class Box -{ -public: - vmVector3 mHalf; - - inline Box() - {} - inline Box(PE_REF(vmVector3) half_); - inline Box(float hx, float hy, float hz); - - inline void Set(PE_REF(vmVector3) half_); - inline void Set(float hx, float hy, float hz); - - inline vmVector3 GetAABB(const vmMatrix3& rotation) const; -}; - -inline -Box::Box(PE_REF(vmVector3) half_) -{ - Set(half_); -} - -inline -Box::Box(float hx, float hy, float hz) -{ - Set(hx, hy, hz); -} - -inline -void -Box::Set(PE_REF(vmVector3) half_) -{ - mHalf = half_; -} - -inline -void -Box::Set(float hx, float hy, float hz) -{ - mHalf = vmVector3(hx, hy, hz); -} - -inline -vmVector3 -Box::GetAABB(const vmMatrix3& rotation) const -{ - return absPerElem(rotation) * mHalf; -} - -//------------------------------------------------------------------------------------------------- -// BoxPoint -//------------------------------------------------------------------------------------------------- - -///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation. -class BoxPoint -{ -public: - BoxPoint() : localPoint(0.0f) {} - - vmPoint3 localPoint; - FeatureType featureType; - int featureIdx; - - inline void setVertexFeature(int plusX, int plusY, int plusZ); - inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1); - inline void setFaceFeature(int dim, int plus); - - inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const; - inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const; - inline void getFaceFeature(int & dim, int & plus) const; -}; - -inline -void -BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ) -{ - featureType = V; - featureIdx = plusX << 2 | plusY << 1 | plusZ; -} - -inline -void -BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1) -{ - featureType = E; - - if (dim0 > dim1) { - featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0; - } else { - featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1; - } -} - -inline -void -BoxPoint::setFaceFeature(int dim, int plus) -{ - featureType = F; - featureIdx = plus << 2 | dim; -} - -inline -void -BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const -{ - plusX = featureIdx >> 2; - plusY = featureIdx >> 1 & 1; - plusZ = featureIdx & 1; -} - -inline -void -BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const -{ - plus0 = featureIdx >> 5; - dim0 = featureIdx >> 3 & 3; - plus1 = featureIdx >> 2 & 1; - dim1 = featureIdx & 3; -} - -inline -void -BoxPoint::getFaceFeature(int & dim, int & plus) const -{ - plus = featureIdx >> 2; - dim = featureIdx & 3; -} - -#endif /* __BOX_H__ */ diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp deleted file mode 100644 index 8d755b22..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "SpuCollisionShapes.h" - -///not supported on IBM SDK, until we fix the alignment of btVector3 -#if defined (__CELLOS_LV2__) && defined (__SPU__) -#include -static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 ) -{ - vec_float4 result; - result = spu_mul( vec0, vec1 ); - result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result ); - return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result ); -} -#endif //__SPU__ - - -void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform) -{ - //calculate the aabb, given the types... - switch (shapeType) - { - case CYLINDER_SHAPE_PROXYTYPE: - /* fall through */ - case BOX_SHAPE_PROXYTYPE: - { - btScalar margin=convexShape->getMarginNV(); - btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); - halfExtents += btVector3(margin,margin,margin); - const btTransform& t = xform; - btMatrix3x3 abs_b = t.getBasis().absolute(); - btVector3 center = t.getOrigin(); - btVector3 extent = halfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] ); - - aabbMin = center - extent; - aabbMax = center + extent; - break; - } - case CAPSULE_SHAPE_PROXYTYPE: - { - btScalar margin=convexShape->getMarginNV(); - btVector3 halfExtents = convexShape->getImplicitShapeDimensions(); - //add the radius to y-axis to get full height - btScalar radius = halfExtents[0]; - halfExtents[1] += radius; - halfExtents += btVector3(margin,margin,margin); -#if 0 - int capsuleUpAxis = convexShape->getUpAxis(); - btScalar halfHeight = convexShape->getHalfHeight(); - btScalar radius = convexShape->getRadius(); - halfExtents[capsuleUpAxis] = radius + halfHeight; -#endif - const btTransform& t = xform; - btMatrix3x3 abs_b = t.getBasis().absolute(); - btVector3 center = t.getOrigin(); - btVector3 extent = halfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] ); - - aabbMin = center - extent; - aabbMax = center + extent; - break; - } - case SPHERE_SHAPE_PROXYTYPE: - { - btScalar radius = convexShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX(); - btScalar margin = radius + convexShape->getMarginNV(); - const btTransform& t = xform; - const btVector3& center = t.getOrigin(); - btVector3 extent(margin,margin,margin); - aabbMin = center - extent; - aabbMax = center + extent; - break; - } - case CONVEX_HULL_SHAPE_PROXYTYPE: - { - ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); - cellDmaGet(&convexHullShape0, convexShapePtr , sizeof(btConvexHullShape), DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - btConvexHullShape* localPtr = (btConvexHullShape*)&convexHullShape0; - const btTransform& t = xform; - btScalar margin = convexShape->getMarginNV(); - localPtr->getNonvirtualAabb(t,aabbMin,aabbMax,margin); - //spu_printf("SPU convex aabbMin=%f,%f,%f=\n",aabbMin.getX(),aabbMin.getY(),aabbMin.getZ()); - //spu_printf("SPU convex aabbMax=%f,%f,%f=\n",aabbMax.getX(),aabbMax.getY(),aabbMax.getZ()); - break; - } - default: - { - // spu_printf("SPU: unsupported shapetype %d in AABB calculation\n"); - } - }; -} - -void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape) -{ - register int dmaSize; - register ppu_address_t dmaPpuAddress2; - - dmaSize = sizeof(btTriangleIndexVertexArray); - dmaPpuAddress2 = reinterpret_cast(triMeshShape->getMeshInterface()); - // spu_printf("trimeshShape->getMeshInterface() == %llx\n",dmaPpuAddress2); -#ifdef __SPU__ - cellDmaGet(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - bvhMeshShape->gTriangleMeshInterfacePtr = &bvhMeshShape->gTriangleMeshInterfaceStorage; -#else - bvhMeshShape->gTriangleMeshInterfacePtr = (btTriangleIndexVertexArray*)cellDmaGetReadOnly(&bvhMeshShape->gTriangleMeshInterfaceStorage, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); -#endif - - //cellDmaWaitTagStatusAll(DMA_MASK(1)); - - ///now DMA over the BVH - - dmaSize = sizeof(btOptimizedBvh); - dmaPpuAddress2 = reinterpret_cast(triMeshShape->getOptimizedBvh()); - //spu_printf("trimeshShape->getOptimizedBvh() == %llx\n",dmaPpuAddress2); - cellDmaGet(&bvhMeshShape->gOptimizedBvh, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0); - //cellDmaWaitTagStatusAll(DMA_MASK(2)); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); -} - -void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag) -{ - cellDmaGet(IndexMesh, (ppu_address_t)&indexArray[index] , sizeof(btIndexedMesh), DMA_TAG(dmaTag), 0, 0); - -} - -void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag) -{ - cellDmaGet(subTreeHeaders, subTreePtr, batchSize * sizeof(btBvhSubtreeInfo), DMA_TAG(dmaTag), 0, 0); -} - -void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag) -{ - cellDmaGet(nodes, reinterpret_cast(&nodeArray[subtree.m_rootNodeIndex]) , subtree.m_subtreeSize* sizeof(btQuantizedBvhNode), DMA_TAG(2), 0, 0); -} - -///getShapeTypeSize could easily be optimized, but it is not likely a bottleneck -int getShapeTypeSize(int shapeType) -{ - - - switch (shapeType) - { - case CYLINDER_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btCylinderShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - case BOX_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btBoxShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - case SPHERE_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btSphereShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - case TRIANGLE_MESH_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btBvhTriangleMeshShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - case CAPSULE_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btCapsuleShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - - case CONVEX_HULL_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btConvexHullShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - - case COMPOUND_SHAPE_PROXYTYPE: - { - int shapeSize = sizeof(btCompoundShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - case STATIC_PLANE_PROXYTYPE: - { - int shapeSize = sizeof(btStaticPlaneShape); - btAssert(shapeSize < MAX_SHAPE_SIZE); - return shapeSize; - } - - default: - btAssert(0); - //unsupported shapetype, please add here - return 0; - } -} - -void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU) -{ - convexVertexData->gNumConvexPoints = convexShapeSPU->getNumPoints(); - if (convexVertexData->gNumConvexPoints>MAX_NUM_SPU_CONVEX_POINTS) - { - btAssert(0); - // spu_printf("SPU: Error: MAX_NUM_SPU_CONVEX_POINTS(%d) exceeded: %d\n",MAX_NUM_SPU_CONVEX_POINTS,convexVertexData->gNumConvexPoints); - return; - } - - register int dmaSize = convexVertexData->gNumConvexPoints*sizeof(btVector3); - ppu_address_t pointsPPU = (ppu_address_t) convexShapeSPU->getUnscaledPoints(); - cellDmaGet(&convexVertexData->g_convexPointBuffer[0], pointsPPU , dmaSize, DMA_TAG(2), 0, 0); -} - -void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType) -{ - register int dmaSize = getShapeTypeSize(shapeType); - cellDmaGet(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0); - //cellDmaGetReadOnly(collisionShapeLocation, collisionShapePtr , dmaSize, DMA_TAG(dmaTag), 0, 0); - //cellDmaWaitTagStatusAll(DMA_MASK(dmaTag)); -} - -void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag) -{ - register int dmaSize; - register ppu_address_t dmaPpuAddress2; - int childShapeCount = spuCompoundShape->getNumChildShapes(); - dmaSize = childShapeCount * sizeof(btCompoundShapeChild); - dmaPpuAddress2 = (ppu_address_t)spuCompoundShape->getChildList(); - cellDmaGet(&compoundShapeLocation->gSubshapes[0], dmaPpuAddress2, dmaSize, DMA_TAG(dmaTag), 0, 0); -} - -void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag) -{ - int childShapeCount = spuCompoundShape->getNumChildShapes(); - int i; - // DMA all the subshapes - for ( i = 0; i < childShapeCount; ++i) - { - btCompoundShapeChild& childShape = compoundShapeLocation->gSubshapes[i]; - dmaCollisionShape (&compoundShapeLocation->gSubshapeShape[i],(ppu_address_t)childShape.m_childShape, dmaTag, childShape.m_childShapeType); - } -} - - -void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex) -{ - - int curIndex = startNodeIndex; - int walkIterations = 0; -#ifdef BT_DEBUG - int subTreeSize = endNodeIndex - startNodeIndex; -#endif - - int escapeIndex; - - unsigned int aabbOverlap, isLeafNode; - - while (curIndex < endNodeIndex) - { - //catch bugs in tree data - btAssert (walkIterations < subTreeSize); - - walkIterations++; - aabbOverlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); - isLeafNode = rootNode->isLeafNode(); - - if (isLeafNode && aabbOverlap) - { - //printf("overlap with node %d\n",rootNode->getTriangleIndex()); - nodeCallback->processNode(0,rootNode->getTriangleIndex()); - // spu_printf("SPU: overlap detected with triangleIndex:%d\n",rootNode->getTriangleIndex()); - } - - if (aabbOverlap || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->getEscapeIndex(); - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h deleted file mode 100644 index aa8a2910..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -#ifndef __SPU_COLLISION_SHAPES_H -#define __SPU_COLLISION_SHAPES_H - -#include "../SpuDoubleBuffer.h" - -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" -#include "BulletCollision/CollisionShapes/btCylinderShape.h" -#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" - -#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" - -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" - -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btConvexHullShape.h" -#include "BulletCollision/CollisionShapes/btCompoundShape.h" - -#define MAX_NUM_SPU_CONVEX_POINTS 128 //@fallback to PPU if a btConvexHullShape has more than MAX_NUM_SPU_CONVEX_POINTS points -#define MAX_SPU_COMPOUND_SUBSHAPES 16 //@fallback on PPU if compound has more than MAX_SPU_COMPOUND_SUBSHAPES child shapes -#define MAX_SHAPE_SIZE 256 //@todo: assert on this - -ATTRIBUTE_ALIGNED16(struct) SpuConvexPolyhedronVertexData -{ - void* gSpuConvexShapePtr; - btVector3* gConvexPoints; - int gNumConvexPoints; - int unused; - ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]); -}; - - - -ATTRIBUTE_ALIGNED16(struct) CollisionShape_LocalStoreMemory -{ - ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]); -}; - -ATTRIBUTE_ALIGNED16(struct) CompoundShape_LocalStoreMemory -{ - // Compound data - - ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]); - ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]); -}; - -ATTRIBUTE_ALIGNED16(struct) bvhMeshShape_LocalStoreMemory -{ - //ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh); - ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]); - btOptimizedBvh* getOptimizedBvh() - { - return (btOptimizedBvh*) gOptimizedBvh; - } - - ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage); - btTriangleIndexVertexArray* gTriangleMeshInterfacePtr; - ///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment - ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh); - #define MAX_SPU_SUBTREE_HEADERS 32 - //1024 - ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]); - ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]); -}; - - -void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform); -void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape); -void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag); -void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag); -void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag); - -int getShapeTypeSize(int shapeType); -void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU); -void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType); -void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag); -void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag); - - -#define USE_BRANCHFREE_TEST 1 -#ifdef USE_BRANCHFREE_TEST -SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) -{ -#if defined(__CELLOS_LV2__) && defined (__SPU__) - vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0}; - vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0}; - vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax); - return spu_extract(spu_gather(isGt),0)==0; - -#else - return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) - & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) - & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), - 1, 0); -#endif -} -#else - -SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) -{ - unsigned int overlap = 1; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap; - return overlap; -} -#endif - -void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex); - -#endif diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp deleted file mode 100644 index 8584e74c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SpuContactResult.h" - -//#define DEBUG_SPU_COLLISION_DETECTION 1 - -#ifdef DEBUG_SPU_COLLISION_DETECTION -#ifndef __SPU__ -#include -#define spu_printf printf -#endif -#endif //DEBUG_SPU_COLLISION_DETECTION - -SpuContactResult::SpuContactResult() -{ - m_manifoldAddress = 0; - m_spuManifold = NULL; - m_RequiresWriteBack = false; -} - - SpuContactResult::~SpuContactResult() -{ - g_manifoldDmaExport.swapBuffers(); -} - - ///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; -inline btScalar calculateCombinedFriction(btScalar friction0,btScalar friction1) -{ - btScalar friction = friction0*friction1; - - const btScalar MAX_FRICTION = btScalar(10.); - - if (friction < -MAX_FRICTION) - friction = -MAX_FRICTION; - if (friction > MAX_FRICTION) - friction = MAX_FRICTION; - return friction; - -} - -inline btScalar calculateCombinedRestitution(btScalar restitution0,btScalar restitution1) -{ - return restitution0*restitution1; -} - - - - void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction1, bool isSwapped) - { - //spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress); - m_rootWorldTransform0 = worldTrans0; - m_rootWorldTransform1 = worldTrans1; - m_manifoldAddress = manifoldAddress; - m_spuManifold = spuManifold; - - m_combinedFriction = calculateCombinedFriction(friction0,friction1); - m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1); - m_isSwapped = isSwapped; - } - - void SpuContactResult::setShapeIdentifiersA(int partId0,int index0) - { - - } - - void SpuContactResult::setShapeIdentifiersB(int partId1,int index1) - { - - } - - - - ///return true if it requires a dma transfer back -bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld, - const btVector3& pointInWorld, - float depth, - btPersistentManifold* manifoldPtr, - btTransform& transA, - btTransform& transB, - btScalar combinedFriction, - btScalar combinedRestitution, - bool isSwapped) -{ - -// float contactTreshold = manifoldPtr->getContactBreakingThreshold(); - - //spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr); - -#ifdef DEBUG_SPU_COLLISION_DETECTION - spu_printf("SPU: contactTreshold %f\n",contactTreshold); -#endif //DEBUG_SPU_COLLISION_DETECTION - if (depth > manifoldPtr->getContactBreakingThreshold()) - return false; - - //if (depth > manifoldPtr->getContactProcessingThreshold()) - // return false; - - - - btVector3 pointA; - btVector3 localA; - btVector3 localB; - btVector3 normal; - - - if (isSwapped) - { - normal = normalOnBInWorld * -1; - pointA = pointInWorld + normal * depth; - localA = transA.invXform(pointA ); - localB = transB.invXform(pointInWorld); - } - else - { - normal = normalOnBInWorld; - pointA = pointInWorld + normal * depth; - localA = transA.invXform(pointA ); - localB = transB.invXform(pointInWorld); - } - - btManifoldPoint newPt(localA,localB,normal,depth); - newPt.m_positionWorldOnA = pointA; - newPt.m_positionWorldOnB = pointInWorld; - - newPt.m_combinedFriction = combinedFriction; - newPt.m_combinedRestitution = combinedRestitution; - - - int insertIndex = manifoldPtr->getCacheEntry(newPt); - if (insertIndex >= 0) - { - // we need to replace the current contact point, otherwise small errors will accumulate (spheres start rolling etc) - manifoldPtr->replaceContactPoint(newPt,insertIndex); - return true; - - } else - { - - /* - ///@todo: SPU callbacks, either immediate (local on the SPU), or deferred - //User can override friction and/or restitution - if (gContactAddedCallback && - //and if either of the two bodies requires custom material - ((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) || - (m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback))) - { - //experimental feature info, for per-triangle material etc. - (*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1); - } - */ - - manifoldPtr->addManifoldPoint(newPt); - return true; - - } - return false; - -} - - -void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold) -{ - ///only write back the contact information on SPU. Other platforms avoid copying, and use the data in-place - ///see SpuFakeDma.cpp 'cellDmaLargeGetReadOnly' -#if defined (__SPU__) || defined (USE_LIBSPE2) - memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold)); - - g_manifoldDmaExport.swapBuffers(); - ppu_address_t mmAddr = (ppu_address_t)mmManifold; - g_manifoldDmaExport.backBufferDmaPut(mmAddr, sizeof(btPersistentManifold), DMA_TAG(9)); - // Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon? - //no, the swapBuffers does the wait -#endif -} - -void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) -{ -#ifdef DEBUG_SPU_COLLISION_DETECTION - spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth); - spu_printf("*** normal = %f,%f,%f\n",normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ()); - spu_printf("*** position = %f,%f,%f\n",pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ()); -#endif //DEBUG_SPU_COLLISION_DETECTION - - -#ifdef DEBUG_SPU_COLLISION_DETECTION - // int sman = sizeof(rage::phManifold); -// spu_printf("sizeof_manifold = %i\n",sman); -#endif //DEBUG_SPU_COLLISION_DETECTION - - btPersistentManifold* localManifold = m_spuManifold; - - btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ()); - btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ()); - - //process the contact point - const bool retVal = ManifoldResultAddContactPoint(normalB, - pointWrld, - depth, - localManifold, - m_rootWorldTransform0, - m_rootWorldTransform1, - m_combinedFriction, - m_combinedRestitution, - m_isSwapped); - m_RequiresWriteBack = m_RequiresWriteBack || retVal; -} - -void SpuContactResult::flush() -{ - - if (m_spuManifold && m_spuManifold->getNumContacts()) - { - m_spuManifold->refreshContactPoints(m_rootWorldTransform0,m_rootWorldTransform1); - m_RequiresWriteBack = true; - } - - - if (m_RequiresWriteBack) - { -#ifdef DEBUG_SPU_COLLISION_DETECTION - spu_printf("SPU: Start SpuContactResult::flush (Put) DMA\n"); - spu_printf("Num contacts:%d\n", m_spuManifold->getNumContacts()); - spu_printf("Manifold address: %llu\n", m_manifoldAddress); -#endif //DEBUG_SPU_COLLISION_DETECTION - // spu_printf("writeDoubleBufferedManifold\n"); - writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress); -#ifdef DEBUG_SPU_COLLISION_DETECTION - spu_printf("SPU: Finished (Put) DMA\n"); -#endif //DEBUG_SPU_COLLISION_DETECTION - } - m_spuManifold = NULL; - m_RequiresWriteBack = false; -} - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h deleted file mode 100644 index 394f56dc..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SPU_CONTACT_RESULT2_H -#define SPU_CONTACT_RESULT2_H - - -#ifndef _WIN32 -#include -#endif - - - -#include "../SpuDoubleBuffer.h" - - -#include "LinearMath/btTransform.h" - - -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" - -class btCollisionShape; - - -struct SpuCollisionPairInput -{ - ppu_address_t m_collisionShapes[2]; - btCollisionShape* m_spuCollisionShapes[2]; - - ppu_address_t m_persistentManifoldPtr; - btVector3 m_primitiveDimensions0; - btVector3 m_primitiveDimensions1; - int m_shapeType0; - int m_shapeType1; - float m_collisionMargin0; - float m_collisionMargin1; - - btTransform m_worldTransform0; - btTransform m_worldTransform1; - - bool m_isSwapped; - bool m_useEpa; -}; - - -struct SpuClosestPointInput : public btDiscreteCollisionDetectorInterface::ClosestPointInput -{ - struct SpuConvexPolyhedronVertexData* m_convexVertexData[2]; -}; - -///SpuContactResult exports the contact points using double-buffered DMA transfers, only when needed -///So when an existing contact point is duplicated, no transfer/refresh is performed. -class SpuContactResult : public btDiscreteCollisionDetectorInterface::Result -{ - btTransform m_rootWorldTransform0; - btTransform m_rootWorldTransform1; - ppu_address_t m_manifoldAddress; - - btPersistentManifold* m_spuManifold; - bool m_RequiresWriteBack; - btScalar m_combinedFriction; - btScalar m_combinedRestitution; - - bool m_isSwapped; - - DoubleBuffer g_manifoldDmaExport; - - public: - SpuContactResult(); - virtual ~SpuContactResult(); - - btPersistentManifold* GetSpuManifold() const - { - return m_spuManifold; - } - - virtual void setShapeIdentifiersA(int partId0,int index0); - virtual void setShapeIdentifiersB(int partId1,int index1); - - void setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction01, bool isSwapped); - - - void writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold); - - virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); - - void flush(); -}; - - - -#endif //SPU_CONTACT_RESULT2_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h deleted file mode 100644 index b1bd53d9..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h +++ /dev/null @@ -1,50 +0,0 @@ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#ifndef SPU_CONVEX_PENETRATION_DEPTH_H -#define SPU_CONVEX_PENETRATION_DEPTH_H - - - -class btIDebugDraw; -#include "BulletCollision/NarrowphaseCollision/btConvexPenetrationDepthSolver.h" - -#include "LinearMath/btTransform.h" - - -///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. -class SpuConvexPenetrationDepthSolver : public btConvexPenetrationDepthSolver -{ -public: - - virtual ~SpuConvexPenetrationDepthSolver() {}; - virtual bool calcPenDepth( SpuVoronoiSimplexSolver& simplexSolver, - void* convexA,void* convexB,int shapeTypeA, int shapeTypeB, float marginA, float marginB, - btTransform& transA,const btTransform& transB, - btVector3& v, btVector3& pa, btVector3& pb, - class btIDebugDraw* debugDraw, - struct SpuConvexPolyhedronVertexData* convexVertexDataA, - struct SpuConvexPolyhedronVertexData* convexVertexDataB - ) const = 0; - - -}; - - - -#endif //SPU_CONVEX_PENETRATION_DEPTH_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp deleted file mode 100644 index c2fe2905..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp +++ /dev/null @@ -1,1432 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SpuGatheringCollisionTask.h" - -//#define DEBUG_SPU_COLLISION_DETECTION 1 -#include "../SpuDoubleBuffer.h" - -#include "../SpuCollisionTaskProcess.h" -#include "../SpuGatheringCollisionDispatcher.h" //for SPU_BATCHSIZE_BROADPHASE_PAIRS - -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "../SpuContactManifoldCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "SpuContactResult.h" -#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.h" - -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" - -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btConvexHullShape.h" -#include "BulletCollision/CollisionShapes/btCompoundShape.h" - -#include "SpuMinkowskiPenetrationDepthSolver.h" -//#include "SpuEpaPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" - - -#include "boxBoxDistance.h" -#include "BulletMultiThreaded/vectormath2bullet.h" -#include "SpuCollisionShapes.h" //definition of SpuConvexPolyhedronVertexData -#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" -#include "BulletCollision/CollisionShapes/btTriangleShape.h" - -#ifdef __SPU__ -///Software caching from the IBM Cell SDK, it reduces 25% SPU time for our test cases -#ifndef USE_LIBSPE2 -//#define USE_SOFTWARE_CACHE 1 -#endif -#endif //__SPU__ - -int gSkippedCol = 0; -int gProcessedCol = 0; - -//////////////////////////////////////////////// -/// software caching -#if USE_SOFTWARE_CACHE -#include -#include -#include -#include -#define SPE_CACHE_NWAY 4 -//#define SPE_CACHE_NSETS 32, 16 -#define SPE_CACHE_NSETS 8 -//#define SPE_CACHELINE_SIZE 512 -#define SPE_CACHELINE_SIZE 128 -#define SPE_CACHE_SET_TAGID(set) 15 -///make sure that spe_cache.h is below those defines! -#include "../Extras/software_cache/cache/include/spe_cache.h" - - -int g_CacheMisses=0; -int g_CacheHits=0; - -#if 0 // Added to allow cache misses and hits to be tracked, change this to 1 to restore unmodified version -#define spe_cache_read(ea) _spe_cache_lookup_xfer_wait_(ea, 0, 1) -#else -#define spe_cache_read(ea) \ -({ \ - int set, idx, line, byte; \ - _spe_cache_nway_lookup_(ea, set, idx); \ - \ - if (btUnlikely(idx < 0)) { \ - ++g_CacheMisses; \ - idx = _spe_cache_miss_(ea, set, -1); \ - spu_writech(22, SPE_CACHE_SET_TAGMASK(set)); \ - spu_mfcstat(MFC_TAG_UPDATE_ALL); \ - } \ - else \ - { \ - ++g_CacheHits; \ - } \ - line = _spe_cacheline_num_(set, idx); \ - byte = _spe_cacheline_byte_offset_(ea); \ - (void *) &spe_cache_mem[line + byte]; \ -}) - -#endif - -#endif // USE_SOFTWARE_CACHE - -bool gUseEpa = false; - -#ifdef USE_SN_TUNER -#include -#endif //USE_SN_TUNER - -#if defined (__SPU__) && !defined (USE_LIBSPE2) -#include -#elif defined (USE_LIBSPE2) -#define spu_printf(a) -#else -#define IGNORE_ALIGNMENT 1 -#include -#include -#define spu_printf printf - -#endif - -//int gNumConvexPoints0=0; - -///Make sure no destructors are called on this memory -ATTRIBUTE_ALIGNED16(struct) CollisionTask_LocalStoreMemory -{ - ///This CollisionTask_LocalStoreMemory is mainly used for the SPU version, using explicit DMA - ///Other platforms can use other memory programming models. - - ATTRIBUTE_ALIGNED16(btBroadphasePair gBroadphasePairsBuffer[SPU_BATCHSIZE_BROADPHASE_PAIRS]); - DoubleBuffer g_workUnitTaskBuffers; - ATTRIBUTE_ALIGNED16(char gSpuContactManifoldAlgoBuffer [sizeof(SpuContactManifoldCollisionAlgorithm)+16]); - ATTRIBUTE_ALIGNED16(char gColObj0Buffer [sizeof(btCollisionObject)+16]); - ATTRIBUTE_ALIGNED16(char gColObj1Buffer [sizeof(btCollisionObject)+16]); - ///we reserve 32bit integer indices, even though they might be 16bit - ATTRIBUTE_ALIGNED16(int spuIndices[16]); - btPersistentManifold gPersistentManifoldBuffer; - CollisionShape_LocalStoreMemory gCollisionShapes[2]; - bvhMeshShape_LocalStoreMemory bvhShapeData; - ATTRIBUTE_ALIGNED16(SpuConvexPolyhedronVertexData convexVertexData[2]); - CompoundShape_LocalStoreMemory compoundShapeData[2]; - - ///The following pointers might either point into this local store memory, or to the original/other memory locations. - ///See SpuFakeDma for implementation of cellDmaSmallGetReadOnly. - btCollisionObject* m_lsColObj0Ptr; - btCollisionObject* m_lsColObj1Ptr; - btBroadphasePair* m_pairsPointer; - btPersistentManifold* m_lsManifoldPtr; - SpuContactManifoldCollisionAlgorithm* m_lsCollisionAlgorithmPtr; - - bool needsDmaPutContactManifoldAlgo; - - btCollisionObject* getColObj0() - { - return m_lsColObj0Ptr; - } - btCollisionObject* getColObj1() - { - return m_lsColObj1Ptr; - } - - - btBroadphasePair* getBroadphasePairPtr() - { - return m_pairsPointer; - } - - SpuContactManifoldCollisionAlgorithm* getlocalCollisionAlgorithm() - { - return m_lsCollisionAlgorithmPtr; - } - - btPersistentManifold* getContactManifoldPtr() - { - return m_lsManifoldPtr; - } -}; - - -#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) - -ATTRIBUTE_ALIGNED16(CollisionTask_LocalStoreMemory gLocalStoreMemory); - -void* createCollisionLocalStoreMemory() -{ - return &gLocalStoreMemory; -} -void deleteCollisionLocalStoreMemory() -{ -} -#else - -btAlignedObjectArray sLocalStorePointers; - -void* createCollisionLocalStoreMemory() -{ - CollisionTask_LocalStoreMemory* localStore = (CollisionTask_LocalStoreMemory*)btAlignedAlloc( sizeof(CollisionTask_LocalStoreMemory),16); - sLocalStorePointers.push_back(localStore); - return localStore; -} - -void deleteCollisionLocalStoreMemory() -{ - for (int i=0;ibvhShapeData.gIndexMesh.m_indexType == PHY_SHORT) - { - unsigned short int* indexBasePtr = (unsigned short int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride); - ATTRIBUTE_ALIGNED16(unsigned short int tmpIndices[3]); - - small_cache_read_triple(&tmpIndices[0],(ppu_address_t)&indexBasePtr[0], - &tmpIndices[1],(ppu_address_t)&indexBasePtr[1], - &tmpIndices[2],(ppu_address_t)&indexBasePtr[2], - sizeof(unsigned short int)); - - m_lsMemPtr->spuIndices[0] = int(tmpIndices[0]); - m_lsMemPtr->spuIndices[1] = int(tmpIndices[1]); - m_lsMemPtr->spuIndices[2] = int(tmpIndices[2]); - } else - { - unsigned int* indexBasePtr = (unsigned int*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexBase+triangleIndex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_triangleIndexStride); - - small_cache_read_triple(&m_lsMemPtr->spuIndices[0],(ppu_address_t)&indexBasePtr[0], - &m_lsMemPtr->spuIndices[1],(ppu_address_t)&indexBasePtr[1], - &m_lsMemPtr->spuIndices[2],(ppu_address_t)&indexBasePtr[2], - sizeof(int)); - } - - // spu_printf("SPU index0=%d ,",spuIndices[0]); - // spu_printf("SPU index1=%d ,",spuIndices[1]); - // spu_printf("SPU index2=%d ,",spuIndices[2]); - // spu_printf("SPU: indexBasePtr=%llx\n",indexBasePtr); - - const btVector3& meshScaling = m_lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getScaling(); - for (int j=2;btLikely( j>=0 );j--) - { - int graphicsindex = m_lsMemPtr->spuIndices[j]; - - // spu_printf("SPU index=%d ,",graphicsindex); - btScalar* graphicsbasePtr = (btScalar*)(m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexBase+graphicsindex*m_lsMemPtr->bvhShapeData.gIndexMesh.m_vertexStride); - // spu_printf("SPU graphicsbasePtr=%llx\n",graphicsbasePtr); - - - ///handle un-aligned vertices... - - //another DMA for each vertex - small_cache_read_triple(&spuUnscaledVertex[0],(ppu_address_t)&graphicsbasePtr[0], - &spuUnscaledVertex[1],(ppu_address_t)&graphicsbasePtr[1], - &spuUnscaledVertex[2],(ppu_address_t)&graphicsbasePtr[2], - sizeof(btScalar)); - - m_tmpTriangleShape.getVertexPtr(j).setValue(spuUnscaledVertex[0]*meshScaling.getX(), - spuUnscaledVertex[1]*meshScaling.getY(), - spuUnscaledVertex[2]*meshScaling.getZ()); - - // spu_printf("SPU:triangle vertices:%f,%f,%f\n",spuTriangleVertices[j].x(),spuTriangleVertices[j].y(),spuTriangleVertices[j].z()); - } - - - SpuCollisionPairInput triangleConcaveInput(*m_wuInput); -// triangleConcaveInput.m_spuCollisionShapes[1] = &spuTriangleVertices[0]; - triangleConcaveInput.m_spuCollisionShapes[1] = &m_tmpTriangleShape; - triangleConcaveInput.m_shapeType1 = TRIANGLE_SHAPE_PROXYTYPE; - - m_spuContacts.setShapeIdentifiersB(subPart,triangleIndex); - - // m_spuContacts.flush(); - - ProcessSpuConvexConvexCollision(&triangleConcaveInput, m_lsMemPtr,m_spuContacts); - ///this flush should be automatic - // m_spuContacts.flush(); - } - -}; - - - -void btConvexPlaneCollideSingleContact (SpuCollisionPairInput* wuInput,CollisionTask_LocalStoreMemory* lsMemPtr,SpuContactResult& spuContacts) -{ - - btConvexShape* convexShape = (btConvexShape*) wuInput->m_spuCollisionShapes[0]; - btStaticPlaneShape* planeShape = (btStaticPlaneShape*) wuInput->m_spuCollisionShapes[1]; - - bool hasCollision = false; - const btVector3& planeNormal = planeShape->getPlaneNormal(); - const btScalar& planeConstant = planeShape->getPlaneConstant(); - - - btTransform convexWorldTransform = wuInput->m_worldTransform0; - btTransform convexInPlaneTrans; - convexInPlaneTrans= wuInput->m_worldTransform1.inverse() * convexWorldTransform; - btTransform planeInConvex; - planeInConvex= convexWorldTransform.inverse() * wuInput->m_worldTransform1; - - //btVector3 vtx = convexShape->localGetSupportVertexWithoutMarginNonVirtual(planeInConvex.getBasis()*-planeNormal); - btVector3 vtx = convexShape->localGetSupportVertexNonVirtual(planeInConvex.getBasis()*-planeNormal); - - btVector3 vtxInPlane = convexInPlaneTrans(vtx); - btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); - - btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; - btVector3 vtxInPlaneWorld = wuInput->m_worldTransform1 * vtxInPlaneProjected; - - hasCollision = distance < lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold(); - //resultOut->setPersistentManifold(m_manifoldPtr); - if (hasCollision) - { - /// report a contact. internally this will be kept persistent, and contact reduction is done - btVector3 normalOnSurfaceB =wuInput->m_worldTransform1.getBasis() * planeNormal; - btVector3 pOnB = vtxInPlaneWorld; - spuContacts.addContactPoint(normalOnSurfaceB,pOnB,distance); - } -} - -void ProcessConvexPlaneSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) -{ - - register int dmaSize = 0; - register ppu_address_t dmaPpuAddress2; - btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr; - - ///DMA in the vertices for convex shapes - ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); - ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]); - - if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - // spu_printf("SPU: DMA btConvexHullShape\n"); - - dmaSize = sizeof(btConvexHullShape); - dmaPpuAddress2 = wuInput->m_collisionShapes[0]; - - cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - //cellDmaWaitTagStatusAll(DMA_MASK(1)); - } - - if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - // spu_printf("SPU: DMA btConvexHullShape\n"); - dmaSize = sizeof(btConvexHullShape); - dmaPpuAddress2 = wuInput->m_collisionShapes[1]; - cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - //cellDmaWaitTagStatusAll(DMA_MASK(1)); - } - - if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(1)); - dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0); - lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0]; - } - - - if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(1)); - dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1); - lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1]; - } - - - btConvexPointCloudShape cpc0,cpc1; - - if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(2)); - lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0]; - btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0]; - const btVector3& localScaling = ch->getLocalScalingNV(); - cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling); - wuInput->m_spuCollisionShapes[0] = &cpc0; - } - - if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(2)); - lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0]; - btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1]; - const btVector3& localScaling = ch->getLocalScalingNV(); - cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling); - wuInput->m_spuCollisionShapes[1] = &cpc1; - - } - - -// const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0]; -// const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1]; -// int shapeType0 = wuInput->m_shapeType0; -// int shapeType1 = wuInput->m_shapeType1; - float marginA = wuInput->m_collisionMargin0; - float marginB = wuInput->m_collisionMargin1; - - SpuClosestPointInput cpInput; - cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0]; - cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1]; - cpInput.m_transformA = wuInput->m_worldTransform0; - cpInput.m_transformB = wuInput->m_worldTransform1; - float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold()); - cpInput.m_maximumDistanceSquared = sumMargin * sumMargin; - - ppu_address_t manifoldAddress = (ppu_address_t)manifold; - - btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr(); - //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped); - spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(), - lsMemPtr->getColObj1()->getWorldTransform(), - lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(), - lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(), - wuInput->m_isSwapped); - - - btConvexPlaneCollideSingleContact(wuInput,lsMemPtr,spuContacts); - - - - -} - - - - -//////////////////////// -/// Convex versus Concave triangle mesh collision detection (handles concave triangle mesh versus sphere, box, cylinder, triangle, cone, convex polyhedron etc) -/////////////////// -void ProcessConvexConcaveSpuCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) -{ - //order: first collision shape is convex, second concave. m_isSwapped is true, if the original order was opposite - - btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)wuInput->m_spuCollisionShapes[1]; - //need the mesh interface, for access to triangle vertices - dmaBvhShapeData (&lsMemPtr->bvhShapeData, trimeshShape); - - btVector3 aabbMin(-1,-400,-1); - btVector3 aabbMax(1,400,1); - - - //recalc aabbs - btTransform convexInTriangleSpace; - convexInTriangleSpace = wuInput->m_worldTransform1.inverse() * wuInput->m_worldTransform0; - btConvexInternalShape* convexShape = (btConvexInternalShape*)wuInput->m_spuCollisionShapes[0]; - - computeAabb (aabbMin, aabbMax, convexShape, wuInput->m_collisionShapes[0], wuInput->m_shapeType0, convexInTriangleSpace); - - - //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); - //convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); - - // btScalar extraMargin = collisionMarginTriangle; - // btVector3 extra(extraMargin,extraMargin,extraMargin); - // aabbMax += extra; - // aabbMin -= extra; - - ///quantize query AABB - unsigned short int quantizedQueryAabbMin[3]; - unsigned short int quantizedQueryAabbMax[3]; - lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0); - lsMemPtr->bvhShapeData.getOptimizedBvh()->quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1); - - QuantizedNodeArray& nodeArray = lsMemPtr->bvhShapeData.getOptimizedBvh()->getQuantizedNodeArray(); - //spu_printf("SPU: numNodes = %d\n",nodeArray.size()); - - BvhSubtreeInfoArray& subTrees = lsMemPtr->bvhShapeData.getOptimizedBvh()->getSubtreeInfoArray(); - - - spuNodeCallback nodeCallback(wuInput,lsMemPtr,spuContacts); - IndexedMeshArray& indexArray = lsMemPtr->bvhShapeData.gTriangleMeshInterfacePtr->getIndexedMeshArray(); - //spu_printf("SPU:indexArray.size() = %d\n",indexArray.size()); - - // spu_printf("SPU: numSubTrees = %d\n",subTrees.size()); - //not likely to happen - if (subTrees.size() && indexArray.size() == 1) - { - ///DMA in the index info - dmaBvhIndexedMesh (&lsMemPtr->bvhShapeData.gIndexMesh, indexArray, 0 /* index into indexArray */, 1 /* dmaTag */); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - //display the headers - int numBatch = subTrees.size(); - for (int i=0;ibvhShapeData.gSubtreeHeaders[0], (ppu_address_t)(&subTrees[i]), nextBatch, 1); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - - // spu_printf("nextBatch = %d\n",nextBatch); - - for (int j=0;jbvhShapeData.gSubtreeHeaders[j]; - - unsigned int overlap = spuTestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) - { - btAssert(subtree.m_subtreeSize); - - //dma the actual nodes of this subtree - dmaBvhSubTreeNodes (&lsMemPtr->bvhShapeData.gSubtreeNodes[0], subtree, nodeArray, 2); - cellDmaWaitTagStatusAll(DMA_MASK(2)); - - /* Walk this subtree */ - spuWalkStacklessQuantizedTree(&nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, - &lsMemPtr->bvhShapeData.gSubtreeNodes[0], - 0, - subtree.m_subtreeSize); - } - // spu_printf("subtreeSize = %d\n",gSubtreeHeaders[j].m_subtreeSize); - } - - // unsigned short int m_quantizedAabbMin[3]; - // unsigned short int m_quantizedAabbMax[3]; - // int m_rootNodeIndex; - // int m_subtreeSize; - i+=nextBatch; - } - - //pre-fetch first tree, then loop and double buffer - } - -} - - -#define MAX_DEGENERATE_STATS 15 -int stats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -int degenerateStats[MAX_DEGENERATE_STATS]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - - -//////////////////////// -/// Convex versus Convex collision detection (handles collision between sphere, box, cylinder, triangle, cone, convex polyhedron etc) -/////////////////// -void ProcessSpuConvexConvexCollision(SpuCollisionPairInput* wuInput, CollisionTask_LocalStoreMemory* lsMemPtr, SpuContactResult& spuContacts) -{ - register int dmaSize; - register ppu_address_t dmaPpuAddress2; - -#ifdef DEBUG_SPU_COLLISION_DETECTION - //spu_printf("SPU: ProcessSpuConvexConvexCollision\n"); -#endif //DEBUG_SPU_COLLISION_DETECTION - //CollisionShape* shape0 = (CollisionShape*)wuInput->m_collisionShapes[0]; - //CollisionShape* shape1 = (CollisionShape*)wuInput->m_collisionShapes[1]; - btPersistentManifold* manifold = (btPersistentManifold*)wuInput->m_persistentManifoldPtr; - - bool genericGjk = true; - - if (genericGjk) - { - //try generic GJK - - - - //SpuConvexPenetrationDepthSolver* penetrationSolver=0; - btVoronoiSimplexSolver simplexSolver; - btGjkEpaPenetrationDepthSolver epaPenetrationSolver2; - - btConvexPenetrationDepthSolver* penetrationSolver = &epaPenetrationSolver2; - - //SpuMinkowskiPenetrationDepthSolver minkowskiPenetrationSolver; -#ifdef ENABLE_EPA - if (gUseEpa) - { - penetrationSolver = &epaPenetrationSolver2; - } else -#endif - { - //penetrationSolver = &minkowskiPenetrationSolver; - } - - - ///DMA in the vertices for convex shapes - ATTRIBUTE_ALIGNED16(char convexHullShape0[sizeof(btConvexHullShape)]); - ATTRIBUTE_ALIGNED16(char convexHullShape1[sizeof(btConvexHullShape)]); - - if ( btLikely( wuInput->m_shapeType0== CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - // spu_printf("SPU: DMA btConvexHullShape\n"); - - dmaSize = sizeof(btConvexHullShape); - dmaPpuAddress2 = wuInput->m_collisionShapes[0]; - - cellDmaGet(&convexHullShape0, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - //cellDmaWaitTagStatusAll(DMA_MASK(1)); - } - - if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - // spu_printf("SPU: DMA btConvexHullShape\n"); - dmaSize = sizeof(btConvexHullShape); - dmaPpuAddress2 = wuInput->m_collisionShapes[1]; - cellDmaGet(&convexHullShape1, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - //cellDmaWaitTagStatusAll(DMA_MASK(1)); - } - - if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(1)); - dmaConvexVertexData (&lsMemPtr->convexVertexData[0], (btConvexHullShape*)&convexHullShape0); - lsMemPtr->convexVertexData[0].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[0]; - } - - - if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(1)); - dmaConvexVertexData (&lsMemPtr->convexVertexData[1], (btConvexHullShape*)&convexHullShape1); - lsMemPtr->convexVertexData[1].gSpuConvexShapePtr = wuInput->m_spuCollisionShapes[1]; - } - - - btConvexPointCloudShape cpc0,cpc1; - - if ( btLikely( wuInput->m_shapeType0 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(2)); - lsMemPtr->convexVertexData[0].gConvexPoints = &lsMemPtr->convexVertexData[0].g_convexPointBuffer[0]; - btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[0]; - const btVector3& localScaling = ch->getLocalScalingNV(); - cpc0.setPoints(lsMemPtr->convexVertexData[0].gConvexPoints,lsMemPtr->convexVertexData[0].gNumConvexPoints,false,localScaling); - wuInput->m_spuCollisionShapes[0] = &cpc0; - } - - if ( btLikely( wuInput->m_shapeType1 == CONVEX_HULL_SHAPE_PROXYTYPE ) ) - { - cellDmaWaitTagStatusAll(DMA_MASK(2)); - lsMemPtr->convexVertexData[1].gConvexPoints = &lsMemPtr->convexVertexData[1].g_convexPointBuffer[0]; - btConvexHullShape* ch = (btConvexHullShape*)wuInput->m_spuCollisionShapes[1]; - const btVector3& localScaling = ch->getLocalScalingNV(); - cpc1.setPoints(lsMemPtr->convexVertexData[1].gConvexPoints,lsMemPtr->convexVertexData[1].gNumConvexPoints,false,localScaling); - wuInput->m_spuCollisionShapes[1] = &cpc1; - - } - - - const btConvexShape* shape0Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[0]; - const btConvexShape* shape1Ptr = (const btConvexShape*)wuInput->m_spuCollisionShapes[1]; - int shapeType0 = wuInput->m_shapeType0; - int shapeType1 = wuInput->m_shapeType1; - float marginA = wuInput->m_collisionMargin0; - float marginB = wuInput->m_collisionMargin1; - - SpuClosestPointInput cpInput; - cpInput.m_convexVertexData[0] = &lsMemPtr->convexVertexData[0]; - cpInput.m_convexVertexData[1] = &lsMemPtr->convexVertexData[1]; - cpInput.m_transformA = wuInput->m_worldTransform0; - cpInput.m_transformB = wuInput->m_worldTransform1; - float sumMargin = (marginA+marginB+lsMemPtr->getContactManifoldPtr()->getContactBreakingThreshold()); - cpInput.m_maximumDistanceSquared = sumMargin * sumMargin; - - ppu_address_t manifoldAddress = (ppu_address_t)manifold; - - btPersistentManifold* spuManifold=lsMemPtr->getContactManifoldPtr(); - //spuContacts.setContactInfo(spuManifold,manifoldAddress,wuInput->m_worldTransform0,wuInput->m_worldTransform1,wuInput->m_isSwapped); - spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMemPtr->getColObj0()->getWorldTransform(), - lsMemPtr->getColObj1()->getWorldTransform(), - lsMemPtr->getColObj0()->getRestitution(),lsMemPtr->getColObj1()->getRestitution(), - lsMemPtr->getColObj0()->getFriction(),lsMemPtr->getColObj1()->getFriction(), - wuInput->m_isSwapped); - - { - btGjkPairDetector gjk(shape0Ptr,shape1Ptr,shapeType0,shapeType1,marginA,marginB,&simplexSolver,penetrationSolver);//&vsSolver,penetrationSolver); - gjk.getClosestPoints(cpInput,spuContacts,0);//,debugDraw); - - btAssert(gjk.m_lastUsedMethod getContactBreakingThreshold(); - lsMemPtr->getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(gjk.getCachedSeparatingAxis(),sepDist,wuInput->m_worldTransform0,wuInput->m_worldTransform1); - lsMemPtr->needsDmaPutContactManifoldAlgo = true; -#endif //USE_SEPDISTANCE_UTIL - - } - - } - - -} - - -template void DoSwap(T& a, T& b) -{ - char tmp[sizeof(T)]; - memcpy(tmp, &a, sizeof(T)); - memcpy(&a, &b, sizeof(T)); - memcpy(&b, tmp, sizeof(T)); -} - -SIMD_FORCE_INLINE void dmaAndSetupCollisionObjects(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem) -{ - register int dmaSize; - register ppu_address_t dmaPpuAddress2; - - dmaSize = sizeof(btCollisionObject);//btTransform); - dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr1->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject0(); - lsMem.m_lsColObj0Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj0Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - - dmaSize = sizeof(btCollisionObject);//btTransform); - dmaPpuAddress2 = /*collisionPairInput.m_isSwapped ? (ppu_address_t)lsMem.gProxyPtr0->m_clientObject :*/ (ppu_address_t)lsMem.getlocalCollisionAlgorithm()->getCollisionObject1(); - lsMem.m_lsColObj1Ptr = (btCollisionObject*)cellDmaGetReadOnly(&lsMem.gColObj1Buffer, dmaPpuAddress2 , dmaSize, DMA_TAG(2), 0, 0); - - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - - btCollisionObject* ob0 = lsMem.getColObj0(); - btCollisionObject* ob1 = lsMem.getColObj1(); - - collisionPairInput.m_worldTransform0 = ob0->getWorldTransform(); - collisionPairInput.m_worldTransform1 = ob1->getWorldTransform(); -} - - - -void handleCollisionPair(SpuCollisionPairInput& collisionPairInput, CollisionTask_LocalStoreMemory& lsMem, - SpuContactResult &spuContacts, - ppu_address_t collisionShape0Ptr, void* collisionShape0Loc, - ppu_address_t collisionShape1Ptr, void* collisionShape1Loc, bool dmaShapes = true) -{ - - if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0) - && btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1)) - { - if (dmaShapes) - { - dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); - dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - } - - btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; - btConvexInternalShape* spuConvexShape1 = (btConvexInternalShape*)collisionShape1Loc; - - btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); - btVector3 dim1 = spuConvexShape1->getImplicitShapeDimensions(); - - collisionPairInput.m_primitiveDimensions0 = dim0; - collisionPairInput.m_primitiveDimensions1 = dim1; - collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; - collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; - collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; - collisionPairInput.m_spuCollisionShapes[1] = spuConvexShape1; - ProcessSpuConvexConvexCollision(&collisionPairInput,&lsMem,spuContacts); - } - else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) && - btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1)) - { - //snPause(); - - dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); - dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - - // Both are compounds, do N^2 CD for now - ///@todo: add some AABB-based pruning (probably not -> slower) - - btCompoundShape* spuCompoundShape0 = (btCompoundShape*)collisionShape0Loc; - btCompoundShape* spuCompoundShape1 = (btCompoundShape*)collisionShape1Loc; - - dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape0, 1); - dmaCompoundShapeInfo (&lsMem.compoundShapeData[1], spuCompoundShape1, 2); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - - - dmaCompoundSubShapes (&lsMem.compoundShapeData[0], spuCompoundShape0, 1); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - dmaCompoundSubShapes (&lsMem.compoundShapeData[1], spuCompoundShape1, 1); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - int childShapeCount0 = spuCompoundShape0->getNumChildShapes(); - btAssert(childShapeCount0< MAX_SPU_COMPOUND_SUBSHAPES); - int childShapeCount1 = spuCompoundShape1->getNumChildShapes(); - btAssert(childShapeCount1< MAX_SPU_COMPOUND_SUBSHAPES); - - // Start the N^2 - for (int i = 0; i < childShapeCount0; ++i) - { - btCompoundShapeChild& childShape0 = lsMem.compoundShapeData[0].gSubshapes[i]; - btAssert(!btBroadphaseProxy::isCompound(childShape0.m_childShapeType)); - - for (int j = 0; j < childShapeCount1; ++j) - { - btCompoundShapeChild& childShape1 = lsMem.compoundShapeData[1].gSubshapes[j]; - btAssert(!btBroadphaseProxy::isCompound(childShape1.m_childShapeType)); - - - /* Create a new collision pair input struct using the two child shapes */ - SpuCollisionPairInput cinput (collisionPairInput); - - cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape0.m_transform; - cinput.m_shapeType0 = childShape0.m_childShapeType; - cinput.m_collisionMargin0 = childShape0.m_childMargin; - - cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape1.m_transform; - cinput.m_shapeType1 = childShape1.m_childShapeType; - cinput.m_collisionMargin1 = childShape1.m_childMargin; - /* Recursively call handleCollisionPair () with new collision pair input */ - - handleCollisionPair(cinput, lsMem, spuContacts, - (ppu_address_t)childShape0.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], - (ppu_address_t)childShape1.m_childShape, lsMem.compoundShapeData[1].gSubshapeShape[j], false); - } - } - } - else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType0) ) - { - //snPause(); - - dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); - dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - - // object 0 compound, object 1 non-compound - btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape0Loc; - dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - int childShapeCount = spuCompoundShape->getNumChildShapes(); - btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES); - - for (int i = 0; i < childShapeCount; ++i) - { - btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i]; - btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType)); - // Dma the child shape - dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - SpuCollisionPairInput cinput (collisionPairInput); - cinput.m_worldTransform0 = collisionPairInput.m_worldTransform0 * childShape.m_transform; - cinput.m_shapeType0 = childShape.m_childShapeType; - cinput.m_collisionMargin0 = childShape.m_childMargin; - - handleCollisionPair(cinput, lsMem, spuContacts, - (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], - collisionShape1Ptr, collisionShape1Loc, false); - } - } - else if (btBroadphaseProxy::isCompound(collisionPairInput.m_shapeType1) ) - { - //snPause(); - - dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); - dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - // object 0 non-compound, object 1 compound - btCompoundShape* spuCompoundShape = (btCompoundShape*)collisionShape1Loc; - dmaCompoundShapeInfo (&lsMem.compoundShapeData[0], spuCompoundShape, 1); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - int childShapeCount = spuCompoundShape->getNumChildShapes(); - btAssert(childShapeCount< MAX_SPU_COMPOUND_SUBSHAPES); - - - for (int i = 0; i < childShapeCount; ++i) - { - btCompoundShapeChild& childShape = lsMem.compoundShapeData[0].gSubshapes[i]; - btAssert(!btBroadphaseProxy::isCompound(childShape.m_childShapeType)); - // Dma the child shape - dmaCollisionShape (&lsMem.compoundShapeData[0].gSubshapeShape[i], (ppu_address_t)childShape.m_childShape, 1, childShape.m_childShapeType); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - SpuCollisionPairInput cinput (collisionPairInput); - cinput.m_worldTransform1 = collisionPairInput.m_worldTransform1 * childShape.m_transform; - cinput.m_shapeType1 = childShape.m_childShapeType; - cinput.m_collisionMargin1 = childShape.m_childMargin; - handleCollisionPair(cinput, lsMem, spuContacts, - collisionShape0Ptr, collisionShape0Loc, - (ppu_address_t)childShape.m_childShape, lsMem.compoundShapeData[0].gSubshapeShape[i], false); - } - - } - else - { - //a non-convex shape is involved - bool handleConvexConcave = false; - - //snPause(); - - if (btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType0) && - btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType1)) - { - // Swap stuff - DoSwap(collisionShape0Ptr, collisionShape1Ptr); - DoSwap(collisionShape0Loc, collisionShape1Loc); - DoSwap(collisionPairInput.m_shapeType0, collisionPairInput.m_shapeType1); - DoSwap(collisionPairInput.m_worldTransform0, collisionPairInput.m_worldTransform1); - DoSwap(collisionPairInput.m_collisionMargin0, collisionPairInput.m_collisionMargin1); - - collisionPairInput.m_isSwapped = true; - } - - if (btBroadphaseProxy::isConvex(collisionPairInput.m_shapeType0)&& - btBroadphaseProxy::isConcave(collisionPairInput.m_shapeType1)) - { - handleConvexConcave = true; - } - if (handleConvexConcave) - { - if (dmaShapes) - { - dmaCollisionShape (collisionShape0Loc, collisionShape0Ptr, 1, collisionPairInput.m_shapeType0); - dmaCollisionShape (collisionShape1Loc, collisionShape1Ptr, 2, collisionPairInput.m_shapeType1); - cellDmaWaitTagStatusAll(DMA_MASK(1) | DMA_MASK(2)); - } - - if (collisionPairInput.m_shapeType1 == STATIC_PLANE_PROXYTYPE) - { - btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; - btStaticPlaneShape* planeShape= (btStaticPlaneShape*)collisionShape1Loc; - - btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); - collisionPairInput.m_primitiveDimensions0 = dim0; - collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; - collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; - collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; - collisionPairInput.m_spuCollisionShapes[1] = planeShape; - - ProcessConvexPlaneSpuCollision(&collisionPairInput,&lsMem,spuContacts); - } else - { - btConvexInternalShape* spuConvexShape0 = (btConvexInternalShape*)collisionShape0Loc; - btBvhTriangleMeshShape* trimeshShape = (btBvhTriangleMeshShape*)collisionShape1Loc; - - btVector3 dim0 = spuConvexShape0->getImplicitShapeDimensions(); - collisionPairInput.m_primitiveDimensions0 = dim0; - collisionPairInput.m_collisionShapes[0] = collisionShape0Ptr; - collisionPairInput.m_collisionShapes[1] = collisionShape1Ptr; - collisionPairInput.m_spuCollisionShapes[0] = spuConvexShape0; - collisionPairInput.m_spuCollisionShapes[1] = trimeshShape; - - ProcessConvexConcaveSpuCollision(&collisionPairInput,&lsMem,spuContacts); - } - } - - } - - spuContacts.flush(); - -} - - -void processCollisionTask(void* userPtr, void* lsMemPtr) -{ - - SpuGatherAndProcessPairsTaskDesc* taskDescPtr = (SpuGatherAndProcessPairsTaskDesc*)userPtr; - SpuGatherAndProcessPairsTaskDesc& taskDesc = *taskDescPtr; - CollisionTask_LocalStoreMemory* colMemPtr = (CollisionTask_LocalStoreMemory*)lsMemPtr; - CollisionTask_LocalStoreMemory& lsMem = *(colMemPtr); - - gUseEpa = taskDesc.m_useEpa; - - // spu_printf("taskDescPtr=%llx\n",taskDescPtr); - - SpuContactResult spuContacts; - - //////////////////// - - ppu_address_t dmaInPtr = taskDesc.m_inPairPtr; - unsigned int numPages = taskDesc.numPages; - unsigned int numOnLastPage = taskDesc.numOnLastPage; - - // prefetch first set of inputs and wait - lsMem.g_workUnitTaskBuffers.init(); - - unsigned int nextNumOnPage = (numPages > 1)? MIDPHASE_NUM_WORKUNITS_PER_PAGE : numOnLastPage; - lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3)); - dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE; - - - register unsigned char *inputPtr; - register unsigned int numOnPage; - register unsigned int j; - SpuGatherAndProcessWorkUnitInput* wuInputs; - register int dmaSize; - register ppu_address_t dmaPpuAddress; - register ppu_address_t dmaPpuAddress2; - - int numPairs; - register int p; - SpuCollisionPairInput collisionPairInput; - - for (unsigned int i = 0; btLikely(i < numPages); i++) - { - - // wait for back buffer dma and swap buffers - inputPtr = lsMem.g_workUnitTaskBuffers.swapBuffers(); - - // number on current page is number prefetched last iteration - numOnPage = nextNumOnPage; - - - // prefetch next set of inputs -#if MIDPHASE_NUM_WORKUNIT_PAGES > 2 - if ( btLikely( i < numPages-1 ) ) -#else - if ( btUnlikely( i < numPages-1 ) ) -#endif - { - nextNumOnPage = (i == numPages-2)? numOnLastPage : MIDPHASE_NUM_WORKUNITS_PER_PAGE; - lsMem.g_workUnitTaskBuffers.backBufferDmaGet(dmaInPtr, nextNumOnPage*sizeof(SpuGatherAndProcessWorkUnitInput), DMA_TAG(3)); - dmaInPtr += MIDPHASE_WORKUNIT_PAGE_SIZE; - } - - wuInputs = reinterpret_cast(inputPtr); - - - for (j = 0; btLikely( j < numOnPage ); j++) - { -#ifdef DEBUG_SPU_COLLISION_DETECTION - // printMidphaseInput(&wuInputs[j]); -#endif //DEBUG_SPU_COLLISION_DETECTION - - - numPairs = wuInputs[j].m_endIndex - wuInputs[j].m_startIndex; - - if ( btLikely( numPairs ) ) - { - dmaSize = numPairs*sizeof(btBroadphasePair); - dmaPpuAddress = wuInputs[j].m_pairArrayPtr+wuInputs[j].m_startIndex * sizeof(btBroadphasePair); - lsMem.m_pairsPointer = (btBroadphasePair*)cellDmaGetReadOnly(&lsMem.gBroadphasePairsBuffer, dmaPpuAddress , dmaSize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - - for (p=0;pm_userInfo = %d\n",pair.m_userInfo); - spu_printf("pair->m_algorithm = %d\n",pair.m_algorithm); - spu_printf("pair->m_pProxy0 = %d\n",pair.m_pProxy0); - spu_printf("pair->m_pProxy1 = %d\n",pair.m_pProxy1); -#endif //DEBUG_SPU_COLLISION_DETECTION - - if (pair.m_internalTmpValue == 2 && pair.m_algorithm && pair.m_pProxy0 && pair.m_pProxy1) - { - dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm); - dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm; - lsMem.m_lsCollisionAlgorithmPtr = (SpuContactManifoldCollisionAlgorithm*)cellDmaGetReadOnly(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - lsMem.needsDmaPutContactManifoldAlgo = false; - - collisionPairInput.m_persistentManifoldPtr = (ppu_address_t) lsMem.getlocalCollisionAlgorithm()->getContactManifoldPtr(); - collisionPairInput.m_isSwapped = false; - - if (1) - { - - ///can wait on the combined DMA_MASK, or dma on the same tag - - -#ifdef DEBUG_SPU_COLLISION_DETECTION - // spu_printf("SPU collisionPairInput->m_shapeType0 = %d\n",collisionPairInput->m_shapeType0); - // spu_printf("SPU collisionPairInput->m_shapeType1 = %d\n",collisionPairInput->m_shapeType1); -#endif //DEBUG_SPU_COLLISION_DETECTION - - - dmaSize = sizeof(btPersistentManifold); - - dmaPpuAddress2 = collisionPairInput.m_persistentManifoldPtr; - lsMem.m_lsManifoldPtr = (btPersistentManifold*)cellDmaGetReadOnly(&lsMem.gPersistentManifoldBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - - collisionPairInput.m_shapeType0 = lsMem.getlocalCollisionAlgorithm()->getShapeType0(); - collisionPairInput.m_shapeType1 = lsMem.getlocalCollisionAlgorithm()->getShapeType1(); - collisionPairInput.m_collisionMargin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); - collisionPairInput.m_collisionMargin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); - - - - //??cellDmaWaitTagStatusAll(DMA_MASK(1)); - - - if (1) - { - //snPause(); - - // Get the collision objects - dmaAndSetupCollisionObjects(collisionPairInput, lsMem); - - if (lsMem.getColObj0()->isActive() || lsMem.getColObj1()->isActive()) - { - - lsMem.needsDmaPutContactManifoldAlgo = true; -#ifdef USE_SEPDISTANCE_UTIL - lsMem.getlocalCollisionAlgorithm()->m_sepDistance.updateSeparatingDistance(collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1); -#endif //USE_SEPDISTANCE_UTIL - -#define USE_DEDICATED_BOX_BOX 1 -#ifdef USE_DEDICATED_BOX_BOX - bool boxbox = ((lsMem.getlocalCollisionAlgorithm()->getShapeType0()==BOX_SHAPE_PROXYTYPE)&& - (lsMem.getlocalCollisionAlgorithm()->getShapeType1()==BOX_SHAPE_PROXYTYPE)); - if (boxbox) - { - //spu_printf("boxbox dist = %f\n",distance); - btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr(); - btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr; - ppu_address_t manifoldAddress = (ppu_address_t)manifold; - - spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(), - lsMem.getColObj1()->getWorldTransform(), - lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(), - lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(), - collisionPairInput.m_isSwapped); - - - //float distance=0.f; - btVector3 normalInB; - - - if (//!gUseEpa && -#ifdef USE_SEPDISTANCE_UTIL - lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f -#else - 1 -#endif - ) - { -//#define USE_PE_BOX_BOX 1 -#ifdef USE_PE_BOX_BOX - { - - //getCollisionMargin0 - btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); - btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); - btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0); - btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1); -/* - //Box boxA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ()); - vmVector3 vmPos0 = getVmVector3(collisionPairInput.m_worldTransform0.getOrigin()); - vmVector3 vmPos1 = getVmVector3(collisionPairInput.m_worldTransform1.getOrigin()); - vmMatrix3 vmMatrix0 = getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis()); - vmMatrix3 vmMatrix1 = getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis()); - - vmTransform3 transformA(vmMatrix0,vmPos0); - Box boxB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ()); - vmTransform3 transformB(vmMatrix1,vmPos1); - BoxPoint resultClosestBoxPointA; - BoxPoint resultClosestBoxPointB; - vmVector3 resultNormal; - */ - -#ifdef USE_SEPDISTANCE_UTIL - float distanceThreshold = FLT_MAX -#else - //float distanceThreshold = 0.f; -#endif - - - vmVector3 n; - Box boxA; - vmVector3 hA(shapeDim0.getX(),shapeDim0.getY(),shapeDim0.getZ()); - vmVector3 hB(shapeDim1.getX(),shapeDim1.getY(),shapeDim1.getZ()); - boxA.mHalf= hA; - vmTransform3 trA; - trA.setTranslation(getVmVector3(collisionPairInput.m_worldTransform0.getOrigin())); - trA.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform0.getBasis())); - Box boxB; - boxB.mHalf = hB; - vmTransform3 trB; - trB.setTranslation(getVmVector3(collisionPairInput.m_worldTransform1.getOrigin())); - trB.setUpper3x3(getVmMatrix3(collisionPairInput.m_worldTransform1.getBasis())); - - float distanceThreshold = spuManifold->getContactBreakingThreshold();//0.001f; - - - BoxPoint ptA,ptB; - float dist = boxBoxDistance(n, ptA, ptB, - boxA, trA, boxB, trB, - distanceThreshold ); - - -// float distance = boxBoxDistance(resultNormal,resultClosestBoxPointA,resultClosestBoxPointB, boxA, transformA, boxB,transformB,distanceThreshold); - - normalInB = -getBtVector3(n);//resultNormal); - - //if(dist < distanceThreshold)//spuManifold->getContactBreakingThreshold()) - if(dist < spuManifold->getContactBreakingThreshold()) - { - btVector3 pointOnB = collisionPairInput.m_worldTransform1(getBtVector3(ptB.localPoint)); - - spuContacts.addContactPoint( - normalInB, - pointOnB, - dist); - } - } -#else - { - - btScalar margin0 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin0(); - btScalar margin1 = lsMem.getlocalCollisionAlgorithm()->getCollisionMargin1(); - btVector3 shapeDim0 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions0()+btVector3(margin0,margin0,margin0); - btVector3 shapeDim1 = lsMem.getlocalCollisionAlgorithm()->getShapeDimensions1()+btVector3(margin1,margin1,margin1); - - - btBoxShape box0(shapeDim0); - btBoxShape box1(shapeDim1); - - struct SpuBridgeContactCollector : public btDiscreteCollisionDetectorInterface::Result - { - SpuContactResult& m_spuContacts; - - virtual void setShapeIdentifiersA(int partId0,int index0) - { - m_spuContacts.setShapeIdentifiersA(partId0,index0); - } - virtual void setShapeIdentifiersB(int partId1,int index1) - { - m_spuContacts.setShapeIdentifiersB(partId1,index1); - } - virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) - { - m_spuContacts.addContactPoint(normalOnBInWorld,pointInWorld,depth); - } - - SpuBridgeContactCollector(SpuContactResult& spuContacts) - :m_spuContacts(spuContacts) - { - - } - }; - - SpuBridgeContactCollector bridgeOutput(spuContacts); - - btDiscreteCollisionDetectorInterface::ClosestPointInput input; - input.m_maximumDistanceSquared = BT_LARGE_FLOAT; - input.m_transformA = collisionPairInput.m_worldTransform0; - input.m_transformB = collisionPairInput.m_worldTransform1; - - btBoxBoxDetector detector(&box0,&box1); - - detector.getClosestPoints(input,bridgeOutput,0); - - } -#endif //USE_PE_BOX_BOX - - lsMem.needsDmaPutContactManifoldAlgo = true; -#ifdef USE_SEPDISTANCE_UTIL - btScalar sepDist2 = distance+spuManifold->getContactBreakingThreshold(); - lsMem.getlocalCollisionAlgorithm()->m_sepDistance.initSeparatingDistance(normalInB,sepDist2,collisionPairInput.m_worldTransform0,collisionPairInput.m_worldTransform1); -#endif //USE_SEPDISTANCE_UTIL - gProcessedCol++; - } else - { - gSkippedCol++; - } - - spuContacts.flush(); - - - } else -#endif //USE_DEDICATED_BOX_BOX - { - if ( -#ifdef USE_SEPDISTANCE_UTIL - lsMem.getlocalCollisionAlgorithm()->m_sepDistance.getConservativeSeparatingDistance()<=0.f -#else - 1 -#endif //USE_SEPDISTANCE_UTIL - ) - { - handleCollisionPair(collisionPairInput, lsMem, spuContacts, - (ppu_address_t)lsMem.getColObj0()->getCollisionShape(), &lsMem.gCollisionShapes[0].collisionShape, - (ppu_address_t)lsMem.getColObj1()->getCollisionShape(), &lsMem.gCollisionShapes[1].collisionShape); - } else - { - //spu_printf("boxbox dist = %f\n",distance); - btPersistentManifold* spuManifold=lsMem.getContactManifoldPtr(); - btPersistentManifold* manifold = (btPersistentManifold*)collisionPairInput.m_persistentManifoldPtr; - ppu_address_t manifoldAddress = (ppu_address_t)manifold; - - spuContacts.setContactInfo(spuManifold,manifoldAddress,lsMem.getColObj0()->getWorldTransform(), - lsMem.getColObj1()->getWorldTransform(), - lsMem.getColObj0()->getRestitution(),lsMem.getColObj1()->getRestitution(), - lsMem.getColObj0()->getFriction(),lsMem.getColObj1()->getFriction(), - collisionPairInput.m_isSwapped); - - spuContacts.flush(); - } - } - - } - - } - } - -#ifdef USE_SEPDISTANCE_UTIL -#if defined (__SPU__) || defined (USE_LIBSPE2) - if (lsMem.needsDmaPutContactManifoldAlgo) - { - dmaSize = sizeof(SpuContactManifoldCollisionAlgorithm); - dmaPpuAddress2 = (ppu_address_t)pair.m_algorithm; - cellDmaLargePut(&lsMem.gSpuContactManifoldAlgoBuffer, dmaPpuAddress2 , dmaSize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - } -#endif -#endif //#ifdef USE_SEPDISTANCE_UTIL - - } - } - } - } //end for (j = 0; j < numOnPage; j++) - - }// for - - - - return; -} - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h deleted file mode 100644 index 64af964c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SPU_GATHERING_COLLISION_TASK_H -#define SPU_GATHERING_COLLISION_TASK_H - -#include "../PlatformDefinitions.h" -//#define DEBUG_SPU_COLLISION_DETECTION 1 - - -///Task Description for SPU collision detection -struct SpuGatherAndProcessPairsTaskDesc -{ - ppu_address_t m_inPairPtr;//m_pairArrayPtr; - //mutex variable - uint32_t m_someMutexVariableInMainMemory; - - ppu_address_t m_dispatcher; - - uint32_t numOnLastPage; - - uint16_t numPages; - uint16_t taskId; - bool m_useEpa; - - struct CollisionTask_LocalStoreMemory* m_lsMemory; -} - -#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) -__attribute__ ((aligned (128))) -#endif -; - - -void processCollisionTask(void* userPtr, void* lsMemory); - -void* createCollisionLocalStoreMemory(); -void deleteCollisionLocalStoreMemory(); - -#if defined(USE_LIBSPE2) && defined(__SPU__) -#include "../SpuLibspe2Support.h" -#include -#include -#include - -//#define DEBUG_LIBSPE2_SPU_TASK - - - -int main(unsigned long long speid, addr64 argp, addr64 envp) -{ - printf("SPU: hello \n"); - - ATTRIBUTE_ALIGNED128(btSpuStatus status); - ATTRIBUTE_ALIGNED16( SpuGatherAndProcessPairsTaskDesc taskDesc ) ; - unsigned int received_message = Spu_Mailbox_Event_Nothing; - bool shutdown = false; - - cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - status.m_status = Spu_Status_Free; - status.m_lsMemory.p = createCollisionLocalStoreMemory(); - - cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - - while ( btLikely( !shutdown ) ) - { - - received_message = spu_read_in_mbox(); - - if( btLikely( received_message == Spu_Mailbox_Event_Task )) - { -#ifdef DEBUG_LIBSPE2_SPU_TASK - printf("SPU: received Spu_Mailbox_Event_Task\n"); -#endif //DEBUG_LIBSPE2_SPU_TASK - - // refresh the status - cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - btAssert(status.m_status==Spu_Status_Occupied); - - cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuGatherAndProcessPairsTaskDesc), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); -#ifdef DEBUG_LIBSPE2_SPU_TASK - printf("SPU:processCollisionTask\n"); -#endif //DEBUG_LIBSPE2_SPU_TASK - processCollisionTask((void*)&taskDesc, taskDesc.m_lsMemory); - -#ifdef DEBUG_LIBSPE2_SPU_TASK - printf("SPU:finished processCollisionTask\n"); -#endif //DEBUG_LIBSPE2_SPU_TASK - } - else - { -#ifdef DEBUG_LIBSPE2_SPU_TASK - printf("SPU: received ShutDown\n"); -#endif //DEBUG_LIBSPE2_SPU_TASK - if( btLikely( received_message == Spu_Mailbox_Event_Shutdown ) ) - { - shutdown = true; - } - else - { - //printf("SPU - Sth. recieved\n"); - } - } - - // set to status free and wait for next task - status.m_status = Spu_Status_Free; - cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - - } - - printf("SPU: shutdown\n"); - return 0; -} -#endif // USE_LIBSPE2 - - -#endif //SPU_GATHERING_COLLISION_TASK_H - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h deleted file mode 100644 index 8b89de03..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h +++ /dev/null @@ -1,19 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp deleted file mode 100644 index 166a38f6..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SpuMinkowskiPenetrationDepthSolver.h" -#include "SpuContactResult.h" -#include "SpuPreferredPenetrationDirections.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" -#include "SpuCollisionShapes.h" - -#define NUM_UNITSPHERE_POINTS 42 -static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = -{ -btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), -btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), -btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), -btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), -btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), -btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), -btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), -btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), -btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), -btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), -btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), -btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), -btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), -btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), -btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), -btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), -btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), -btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), -btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), -btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), -btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), -btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), -btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), -btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), -btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), -btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), -btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), -btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), -btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), -btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), -btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), -btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), -btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), -btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), -btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), -btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), -btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), -btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), -btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), -btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), -btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), -btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) -}; - - -bool SpuMinkowskiPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* convexA,const btConvexShape* convexB, - const btTransform& transA,const btTransform& transB, - btVector3& v, btVector3& pa, btVector3& pb, - class btIDebugDraw* debugDraw) -{ -#if 0 - (void)v; - - - struct btIntermediateResult : public SpuContactResult - { - - btIntermediateResult():m_hasResult(false) - { - } - - btVector3 m_normalOnBInWorld; - btVector3 m_pointInWorld; - btScalar m_depth; - bool m_hasResult; - - virtual void setShapeIdentifiersA(int partId0,int index0) - { - (void)partId0; - (void)index0; - } - - virtual void setShapeIdentifiersB(int partId1,int index1) - { - (void)partId1; - (void)index1; - } - void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) - { - m_normalOnBInWorld = normalOnBInWorld; - m_pointInWorld = pointInWorld; - m_depth = depth; - m_hasResult = true; - } - }; - - //just take fixed number of orientation, and sample the penetration depth in that direction - btScalar minProj = btScalar(BT_LARGE_FLOAT); - btVector3 minNorm(0.f,0.f,0.f); - btVector3 minVertex; - btVector3 minA,minB; - btVector3 seperatingAxisInA,seperatingAxisInB; - btVector3 pInA,qInB,pWorld,qWorld,w; - -//#define USE_BATCHED_SUPPORT 1 -#ifdef USE_BATCHED_SUPPORT - - btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - int i; - - int numSampleDirections = NUM_UNITSPHERE_POINTS; - - for (i=0;igetNumPreferredPenetrationDirections(); - if (numPDA) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - norm = transA.getBasis() * norm; - sPenetrationDirections[numSampleDirections] = norm; - seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); - seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); - numSampleDirections++; - } - } - } - - { - int numPDB = convexB->getNumPreferredPenetrationDirections(); - if (numPDB) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - norm = transB.getBasis() * norm; - sPenetrationDirections[numSampleDirections] = norm; - seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); - seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); - numSampleDirections++; - } - } - } - - - - convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); - convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); - - for (i=0;ilocalGetSupportVertexWithoutMarginNonVirtual( seperatingAxisInA);//, NULL); - qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);//, NULL); - - // pInA = convexA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); - // qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); - - pWorld = transA(pInA); - qWorld = transB(qInB); - w = qWorld - pWorld; - btScalar delta = norm.dot(w); - //find smallest delta - if (delta < minProj) - { - minProj = delta; - minNorm = norm; - minA = pWorld; - minB = qWorld; - } - } -#endif //USE_BATCHED_SUPPORT - - //add the margins - - minA += minNorm*marginA; - minB -= minNorm*marginB; - //no penetration - if (minProj < btScalar(0.)) - return false; - - minProj += (marginA + marginB) + btScalar(1.00); - - - - - -//#define DEBUG_DRAW 1 -#ifdef DEBUG_DRAW - if (debugDraw) - { - btVector3 color(0,1,0); - debugDraw->drawLine(minA,minB,color); - color = btVector3 (1,1,1); - btVector3 vec = minB-minA; - btScalar prj2 = minNorm.dot(vec); - debugDraw->drawLine(minA,minA+(minNorm*minProj),color); - - } -#endif //DEBUG_DRAW - - - btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); - - btScalar offsetDist = minProj; - btVector3 offset = minNorm * offsetDist; - - - SpuClosestPointInput input; - input.m_convexVertexData[0] = convexVertexDataA; - input.m_convexVertexData[1] = convexVertexDataB; - btVector3 newOrg = transA.getOrigin() + offset; - - btTransform displacedTrans = transA; - displacedTrans.setOrigin(newOrg); - - input.m_transformA = displacedTrans; - input.m_transformB = transB; - input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj; - - btIntermediateResult res; - gjkdet.getClosestPoints(input,res,0); - - btScalar correctedMinNorm = minProj - res.m_depth; - - - //the penetration depth is over-estimated, relax it - btScalar penetration_relaxation= btScalar(1.); - minNorm*=penetration_relaxation; - - if (res.m_hasResult) - { - - pa = res.m_pointInWorld - minNorm * correctedMinNorm; - pb = res.m_pointInWorld; - -#ifdef DEBUG_DRAW - if (debugDraw) - { - btVector3 color(1,0,0); - debugDraw->drawLine(pa,pb,color); - } -#endif//DEBUG_DRAW - - - } else { - // could not seperate shapes - //btAssert (false); - } - return res.m_hasResult; -#endif - return false; -} - - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h deleted file mode 100644 index 98c4fc68..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h +++ /dev/null @@ -1,47 +0,0 @@ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H -#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H - - -#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" - -class btIDebugDraw; -class btVoronoiSimplexSolver; -class btConvexShape; - -///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. -///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. -class SpuMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver -{ -public: - SpuMinkowskiPenetrationDepthSolver() {} - virtual ~SpuMinkowskiPenetrationDepthSolver() {}; - - virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* convexA,const btConvexShape* convexB, - const btTransform& transA,const btTransform& transB, - btVector3& v, btVector3& pa, btVector3& pb, - class btIDebugDraw* debugDraw - ); - - -}; - - -#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h deleted file mode 100644 index 774a0cb2..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef _SPU_PREFERRED_PENETRATION_DIRECTIONS_H -#define _SPU_PREFERRED_PENETRATION_DIRECTIONS_H - - -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" - -int spuGetNumPreferredPenetrationDirections(int shapeType, void* shape) -{ - switch (shapeType) - { - case TRIANGLE_SHAPE_PROXYTYPE: - { - return 2; - //spu_printf("2\n"); - break; - } - default: - { -#if __ASSERT - spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType); -#endif // __ASSERT - } - } - - return 0; -} - -void spuGetPreferredPenetrationDirection(int shapeType, void* shape, int index, btVector3& penetrationVector) -{ - - - switch (shapeType) - { - case TRIANGLE_SHAPE_PROXYTYPE: - { - btVector3* vertices = (btVector3*)shape; - ///calcNormal - penetrationVector = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); - penetrationVector.normalize(); - if (index) - penetrationVector *= btScalar(-1.); - break; - } - default: - { - -#if __ASSERT - spu_printf("spuGetNumPreferredPenetrationDirections() - Unsupported bound type: %d.\n", shapeType); -#endif // __ASSERT - } - } - -} - -#endif //_SPU_PREFERRED_PENETRATION_DIRECTIONS_H diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp deleted file mode 100644 index 5e1202c0..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp +++ /dev/null @@ -1,1160 +0,0 @@ -/* - Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. - All rights reserved. - -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 "PfxContactBoxBox.h" - -#include -#include "../PlatformDefinitions.h" -#include "boxBoxDistance.h" - -static inline float sqr( float a ) -{ - return (a * a); -} - -enum BoxSepAxisType -{ - A_AXIS, B_AXIS, CROSS_AXIS -}; - -//------------------------------------------------------------------------------------------------- -// voronoiTol: bevels Voronoi planes slightly which helps when features are parallel. -//------------------------------------------------------------------------------------------------- - -static const float voronoiTol = -1.0e-5f; - -//------------------------------------------------------------------------------------------------- -// separating axis tests: gaps along each axis are computed, and the axis with the maximum -// gap is stored. cross product axes are normalized. -//------------------------------------------------------------------------------------------------- - -#define AaxisTest( dim, letter, first ) \ -{ \ - if ( first ) \ - { \ - maxGap = gap = gapsA.get##letter(); \ - if ( gap > distanceThreshold ) return gap; \ - axisType = A_AXIS; \ - faceDimA = dim; \ - axisA = identity.getCol##dim(); \ - } \ - else \ - { \ - gap = gapsA.get##letter(); \ - if ( gap > distanceThreshold ) return gap; \ - else if ( gap > maxGap ) \ - { \ - maxGap = gap; \ - axisType = A_AXIS; \ - faceDimA = dim; \ - axisA = identity.getCol##dim(); \ - } \ - } \ -} - - -#define BaxisTest( dim, letter ) \ -{ \ - gap = gapsB.get##letter(); \ - if ( gap > distanceThreshold ) return gap; \ - else if ( gap > maxGap ) \ - { \ - maxGap = gap; \ - axisType = B_AXIS; \ - faceDimB = dim; \ - axisB = identity.getCol##dim(); \ - } \ -} - -#define CrossAxisTest( dima, dimb, letterb ) \ -{ \ - const float lsqr_tolerance = 1.0e-30f; \ - float lsqr; \ - \ - lsqr = lsqrs.getCol##dima().get##letterb(); \ - \ - if ( lsqr > lsqr_tolerance ) \ - { \ - float l_recip = 1.0f / sqrtf( lsqr ); \ - gap = float(gapsAxB.getCol##dima().get##letterb()) * l_recip; \ - \ - if ( gap > distanceThreshold ) \ - { \ - return gap; \ - } \ - \ - if ( gap > maxGap ) \ - { \ - maxGap = gap; \ - axisType = CROSS_AXIS; \ - edgeDimA = dima; \ - edgeDimB = dimb; \ - axisA = cross(identity.getCol##dima(),matrixAB.getCol##dimb()) * l_recip; \ - } \ - } \ -} - -//------------------------------------------------------------------------------------------------- -// tests whether a vertex of box B and a face of box A are the closest features -//------------------------------------------------------------------------------------------------- - -inline -float -VertexBFaceATest( - bool & inVoronoi, - float & t0, - float & t1, - const vmVector3 & hA, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesB ) -{ - // compute a corner of box B in A's coordinate system - - vmVector3 corner = - vmVector3( faceOffsetAB + matrixAB.getCol0() * scalesB.getX() + matrixAB.getCol1() * scalesB.getY() ); - - // compute the parameters of the point on A, closest to this corner - - t0 = corner[0]; - t1 = corner[1]; - - if ( t0 > hA[0] ) - t0 = hA[0]; - else if ( t0 < -hA[0] ) - t0 = -hA[0]; - if ( t1 > hA[1] ) - t1 = hA[1]; - else if ( t1 < -hA[1] ) - t1 = -hA[1]; - - // do the Voronoi test: already know the point on B is in the Voronoi region of the - // point on A, check the reverse. - - vmVector3 facePointB = - vmVector3( mulPerElem( faceOffsetBA + matrixBA.getCol0() * t0 + matrixBA.getCol1() * t1 - scalesB, signsB ) ); - - inVoronoi = ( ( facePointB[0] >= voronoiTol * facePointB[2] ) && - ( facePointB[1] >= voronoiTol * facePointB[0] ) && - ( facePointB[2] >= voronoiTol * facePointB[1] ) ); - - return (sqr( corner[0] - t0 ) + sqr( corner[1] - t1 ) + sqr( corner[2] )); -} - -#define VertexBFaceA_SetNewMin() \ -{ \ - minDistSqr = distSqr; \ - localPointA.setX(t0); \ - localPointA.setY(t1); \ - localPointB.setX( scalesB.getX() ); \ - localPointB.setY( scalesB.getY() ); \ - featureA = F; \ - featureB = V; \ -} - -void -VertexBFaceATests( - bool & done, - float & minDistSqr, - vmPoint3 & localPointA, - vmPoint3 & localPointB, - FeatureType & featureA, - FeatureType & featureB, - const vmVector3 & hA, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesB, - bool first ) -{ - - float t0, t1; - float distSqr; - - distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsB, scalesB ); - - if ( first ) { - VertexBFaceA_SetNewMin(); - } else { - if ( distSqr < minDistSqr ) { - VertexBFaceA_SetNewMin(); - } - } - - if ( done ) - return; - - signsB.setX( -signsB.getX() ); - scalesB.setX( -scalesB.getX() ); - - distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsB, scalesB ); - - if ( distSqr < minDistSqr ) { - VertexBFaceA_SetNewMin(); - } - - if ( done ) - return; - - signsB.setY( -signsB.getY() ); - scalesB.setY( -scalesB.getY() ); - - distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsB, scalesB ); - - if ( distSqr < minDistSqr ) { - VertexBFaceA_SetNewMin(); - } - - if ( done ) - return; - - signsB.setX( -signsB.getX() ); - scalesB.setX( -scalesB.getX() ); - - distSqr = VertexBFaceATest( done, t0, t1, hA, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsB, scalesB ); - - if ( distSqr < minDistSqr ) { - VertexBFaceA_SetNewMin(); - } -} - -//------------------------------------------------------------------------------------------------- -// VertexAFaceBTest: tests whether a vertex of box A and a face of box B are the closest features -//------------------------------------------------------------------------------------------------- - -inline -float -VertexAFaceBTest( - bool & inVoronoi, - float & t0, - float & t1, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) scalesA ) -{ - vmVector3 corner = - vmVector3( faceOffsetBA + matrixBA.getCol0() * scalesA.getX() + matrixBA.getCol1() * scalesA.getY() ); - - t0 = corner[0]; - t1 = corner[1]; - - if ( t0 > hB[0] ) - t0 = hB[0]; - else if ( t0 < -hB[0] ) - t0 = -hB[0]; - if ( t1 > hB[1] ) - t1 = hB[1]; - else if ( t1 < -hB[1] ) - t1 = -hB[1]; - - vmVector3 facePointA = - vmVector3( mulPerElem( faceOffsetAB + matrixAB.getCol0() * t0 + matrixAB.getCol1() * t1 - scalesA, signsA ) ); - - inVoronoi = ( ( facePointA[0] >= voronoiTol * facePointA[2] ) && - ( facePointA[1] >= voronoiTol * facePointA[0] ) && - ( facePointA[2] >= voronoiTol * facePointA[1] ) ); - - return (sqr( corner[0] - t0 ) + sqr( corner[1] - t1 ) + sqr( corner[2] )); -} - -#define VertexAFaceB_SetNewMin() \ -{ \ - minDistSqr = distSqr; \ - localPointB.setX(t0); \ - localPointB.setY(t1); \ - localPointA.setX( scalesA.getX() ); \ - localPointA.setY( scalesA.getY() ); \ - featureA = V; \ - featureB = F; \ -} - -void -VertexAFaceBTests( - bool & done, - float & minDistSqr, - vmPoint3 & localPointA, - vmPoint3 & localPointB, - FeatureType & featureA, - FeatureType & featureB, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) scalesA, - bool first ) -{ - float t0, t1; - float distSqr; - - distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, scalesA ); - - if ( first ) { - VertexAFaceB_SetNewMin(); - } else { - if ( distSqr < minDistSqr ) { - VertexAFaceB_SetNewMin(); - } - } - - if ( done ) - return; - - signsA.setX( -signsA.getX() ); - scalesA.setX( -scalesA.getX() ); - - distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, scalesA ); - - if ( distSqr < minDistSqr ) { - VertexAFaceB_SetNewMin(); - } - - if ( done ) - return; - - signsA.setY( -signsA.getY() ); - scalesA.setY( -scalesA.getY() ); - - distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, scalesA ); - - if ( distSqr < minDistSqr ) { - VertexAFaceB_SetNewMin(); - } - - if ( done ) - return; - - signsA.setX( -signsA.getX() ); - scalesA.setX( -scalesA.getX() ); - - distSqr = VertexAFaceBTest( done, t0, t1, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, scalesA ); - - if ( distSqr < minDistSqr ) { - VertexAFaceB_SetNewMin(); - } -} - -//------------------------------------------------------------------------------------------------- -// CustomEdgeEdgeTest: -// -// tests whether a pair of edges are the closest features -// -// note on the shorthand: -// 'a' & 'b' refer to the edges. -// 'c' is the dimension of the axis that points from the face center to the edge Center -// 'd' is the dimension of the edge Direction -// the dimension of the face normal is 2 -//------------------------------------------------------------------------------------------------- - -#define CustomEdgeEdgeTest( ac, ac_letter, ad, ad_letter, bc, bc_letter, bd, bd_letter ) \ -{ \ - vmVector3 edgeOffsetAB; \ - vmVector3 edgeOffsetBA; \ - \ - edgeOffsetAB = faceOffsetAB + matrixAB.getCol##bc() * scalesB.get##bc_letter(); \ - edgeOffsetAB.set##ac_letter( edgeOffsetAB.get##ac_letter() - scalesA.get##ac_letter() ); \ - \ - edgeOffsetBA = faceOffsetBA + matrixBA.getCol##ac() * scalesA.get##ac_letter(); \ - edgeOffsetBA.set##bc_letter( edgeOffsetBA.get##bc_letter() - scalesB.get##bc_letter() ); \ - \ - float dirDot = matrixAB.getCol##bd().get##ad_letter(); \ - float denom = 1.0f - dirDot*dirDot; \ - float edgeOffsetAB_ad = edgeOffsetAB.get##ad_letter(); \ - float edgeOffsetBA_bd = edgeOffsetBA.get##bd_letter(); \ - \ - if ( denom == 0.0f ) \ - { \ - tA = 0.0f; \ - } \ - else \ - { \ - tA = ( edgeOffsetAB_ad + edgeOffsetBA_bd * dirDot ) / denom; \ - } \ - \ - if ( tA < -hA[ad] ) tA = -hA[ad]; \ - else if ( tA > hA[ad] ) tA = hA[ad]; \ - \ - tB = tA * dirDot + edgeOffsetBA_bd; \ - \ - if ( tB < -hB[bd] ) \ - { \ - tB = -hB[bd]; \ - tA = tB * dirDot + edgeOffsetAB_ad; \ - \ - if ( tA < -hA[ad] ) tA = -hA[ad]; \ - else if ( tA > hA[ad] ) tA = hA[ad]; \ - } \ - else if ( tB > hB[bd] ) \ - { \ - tB = hB[bd]; \ - tA = tB * dirDot + edgeOffsetAB_ad; \ - \ - if ( tA < -hA[ad] ) tA = -hA[ad]; \ - else if ( tA > hA[ad] ) tA = hA[ad]; \ - } \ - \ - vmVector3 edgeOffAB = vmVector3( mulPerElem( edgeOffsetAB + matrixAB.getCol##bd() * tB, signsA ) );\ - vmVector3 edgeOffBA = vmVector3( mulPerElem( edgeOffsetBA + matrixBA.getCol##ad() * tA, signsB ) );\ - \ - inVoronoi = ( edgeOffAB[ac] >= voronoiTol * edgeOffAB[2] ) && \ - ( edgeOffAB[2] >= voronoiTol * edgeOffAB[ac] ) && \ - ( edgeOffBA[bc] >= voronoiTol * edgeOffBA[2] ) && \ - ( edgeOffBA[2] >= voronoiTol * edgeOffBA[bc] ); \ - \ - edgeOffAB[ad] -= tA; \ - edgeOffBA[bd] -= tB; \ - \ - return dot(edgeOffAB,edgeOffAB); \ -} - -float -CustomEdgeEdgeTest_0101( - bool & inVoronoi, - float & tA, - float & tB, - const vmVector3 & hA, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesA, - PE_REF(vmVector3) scalesB ) -{ - CustomEdgeEdgeTest( 0, X, 1, Y, 0, X, 1, Y ); -} - -float -CustomEdgeEdgeTest_0110( - bool & inVoronoi, - float & tA, - float & tB, - const vmVector3 & hA, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesA, - PE_REF(vmVector3) scalesB ) -{ - CustomEdgeEdgeTest( 0, X, 1, Y, 1, Y, 0, X ); -} - -float -CustomEdgeEdgeTest_1001( - bool & inVoronoi, - float & tA, - float & tB, - const vmVector3 & hA, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesA, - PE_REF(vmVector3) scalesB ) -{ - CustomEdgeEdgeTest( 1, Y, 0, X, 0, X, 1, Y ); -} - -float -CustomEdgeEdgeTest_1010( - bool & inVoronoi, - float & tA, - float & tB, - const vmVector3 & hA, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesA, - PE_REF(vmVector3) scalesB ) -{ - CustomEdgeEdgeTest( 1, Y, 0, X, 1, Y, 0, X ); -} - -#define EdgeEdge_SetNewMin( ac_letter, ad_letter, bc_letter, bd_letter ) \ -{ \ - minDistSqr = distSqr; \ - localPointA.set##ac_letter(scalesA.get##ac_letter()); \ - localPointA.set##ad_letter(tA); \ - localPointB.set##bc_letter(scalesB.get##bc_letter()); \ - localPointB.set##bd_letter(tB); \ - otherFaceDimA = testOtherFaceDimA; \ - otherFaceDimB = testOtherFaceDimB; \ - featureA = E; \ - featureB = E; \ -} - -void -EdgeEdgeTests( - bool & done, - float & minDistSqr, - vmPoint3 & localPointA, - vmPoint3 & localPointB, - int & otherFaceDimA, - int & otherFaceDimB, - FeatureType & featureA, - FeatureType & featureB, - const vmVector3 & hA, - const vmVector3 & hB, - PE_REF(vmVector3) faceOffsetAB, - PE_REF(vmVector3) faceOffsetBA, - const vmMatrix3 & matrixAB, - const vmMatrix3 & matrixBA, - PE_REF(vmVector3) signsA, - PE_REF(vmVector3) signsB, - PE_REF(vmVector3) scalesA, - PE_REF(vmVector3) scalesB, - bool first ) -{ - - float distSqr; - float tA, tB; - - int testOtherFaceDimA, testOtherFaceDimB; - - testOtherFaceDimA = 0; - testOtherFaceDimB = 0; - - distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( first ) { - EdgeEdge_SetNewMin( X, Y, X, Y ); - } else { - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, X, Y ); - } - } - - if ( done ) - return; - - signsA.setX( -signsA.getX() ); - scalesA.setX( -scalesA.getX() ); - - distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, X, Y ); - } - - if ( done ) - return; - - signsB.setX( -signsB.getX() ); - scalesB.setX( -scalesB.getX() ); - - distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, X, Y ); - } - - if ( done ) - return; - - signsA.setX( -signsA.getX() ); - scalesA.setX( -scalesA.getX() ); - - distSqr = CustomEdgeEdgeTest_0101( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, X, Y ); - } - - if ( done ) - return; - - testOtherFaceDimA = 1; - testOtherFaceDimB = 0; - signsB.setX( -signsB.getX() ); - scalesB.setX( -scalesB.getX() ); - - distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, X, Y ); - } - - if ( done ) - return; - - signsA.setY( -signsA.getY() ); - scalesA.setY( -scalesA.getY() ); - - distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, X, Y ); - } - - if ( done ) - return; - - signsB.setX( -signsB.getX() ); - scalesB.setX( -scalesB.getX() ); - - distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, X, Y ); - } - - if ( done ) - return; - - signsA.setY( -signsA.getY() ); - scalesA.setY( -scalesA.getY() ); - - distSqr = CustomEdgeEdgeTest_1001( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, X, Y ); - } - - if ( done ) - return; - - testOtherFaceDimA = 0; - testOtherFaceDimB = 1; - signsB.setX( -signsB.getX() ); - scalesB.setX( -scalesB.getX() ); - - distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, Y, X ); - } - - if ( done ) - return; - - signsA.setX( -signsA.getX() ); - scalesA.setX( -scalesA.getX() ); - - distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, Y, X ); - } - - if ( done ) - return; - - signsB.setY( -signsB.getY() ); - scalesB.setY( -scalesB.getY() ); - - distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, Y, X ); - } - - if ( done ) - return; - - signsA.setX( -signsA.getX() ); - scalesA.setX( -scalesA.getX() ); - - distSqr = CustomEdgeEdgeTest_0110( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( X, Y, Y, X ); - } - - if ( done ) - return; - - testOtherFaceDimA = 1; - testOtherFaceDimB = 1; - signsB.setY( -signsB.getY() ); - scalesB.setY( -scalesB.getY() ); - - distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, Y, X ); - } - - if ( done ) - return; - - signsA.setY( -signsA.getY() ); - scalesA.setY( -scalesA.getY() ); - - distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, Y, X ); - } - - if ( done ) - return; - - signsB.setY( -signsB.getY() ); - scalesB.setY( -scalesB.getY() ); - - distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, Y, X ); - } - - if ( done ) - return; - - signsA.setY( -signsA.getY() ); - scalesA.setY( -scalesA.getY() ); - - distSqr = CustomEdgeEdgeTest_1010( done, tA, tB, hA, hB, faceOffsetAB, faceOffsetBA, - matrixAB, matrixBA, signsA, signsB, scalesA, scalesB ); - - if ( distSqr < minDistSqr ) { - EdgeEdge_SetNewMin( Y, X, Y, X ); - } -} - - -float -boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB, - PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB, - const vmTransform3 & transformB, - float distanceThreshold) -{ - vmMatrix3 identity; - identity = vmMatrix3::identity(); - vmVector3 ident[3]; - ident[0] = identity.getCol0(); - ident[1] = identity.getCol1(); - ident[2] = identity.getCol2(); - - // get relative transformations - - vmTransform3 transformAB, transformBA; - vmMatrix3 matrixAB, matrixBA; - vmVector3 offsetAB, offsetBA; - - transformAB = orthoInverse(transformA) * transformB; - transformBA = orthoInverse(transformAB); - - matrixAB = transformAB.getUpper3x3(); - offsetAB = transformAB.getTranslation(); - matrixBA = transformBA.getUpper3x3(); - offsetBA = transformBA.getTranslation(); - - vmMatrix3 absMatrixAB = absPerElem(matrixAB); - vmMatrix3 absMatrixBA = absPerElem(matrixBA); - - // find separating axis with largest gap between projections - - BoxSepAxisType axisType; - vmVector3 axisA(0.0f), axisB(0.0f); - float gap, maxGap; - int faceDimA = 0, faceDimB = 0, edgeDimA = 0, edgeDimB = 0; - - // face axes - - vmVector3 gapsA = absPerElem(offsetAB) - boxA.mHalf - absMatrixAB * boxB.mHalf; - - AaxisTest(0,X,true); - AaxisTest(1,Y,false); - AaxisTest(2,Z,false); - - vmVector3 gapsB = absPerElem(offsetBA) - boxB.mHalf - absMatrixBA * boxA.mHalf; - - BaxisTest(0,X); - BaxisTest(1,Y); - BaxisTest(2,Z); - - // cross product axes - - // ŠOÏ‚ª‚O‚Ì‚Æ‚«‚Ì‘Îô - absMatrixAB += vmMatrix3(1.0e-5f); - absMatrixBA += vmMatrix3(1.0e-5f); - - vmMatrix3 lsqrs, projOffset, projAhalf, projBhalf; - - lsqrs.setCol0( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + - mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) ); - lsqrs.setCol1( mulPerElem( matrixBA.getCol2(), matrixBA.getCol2() ) + - mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); - lsqrs.setCol2( mulPerElem( matrixBA.getCol1(), matrixBA.getCol1() ) + - mulPerElem( matrixBA.getCol0(), matrixBA.getCol0() ) ); - - projOffset.setCol0(matrixBA.getCol1() * offsetAB.getZ() - matrixBA.getCol2() * offsetAB.getY()); - projOffset.setCol1(matrixBA.getCol2() * offsetAB.getX() - matrixBA.getCol0() * offsetAB.getZ()); - projOffset.setCol2(matrixBA.getCol0() * offsetAB.getY() - matrixBA.getCol1() * offsetAB.getX()); - - projAhalf.setCol0(absMatrixBA.getCol1() * boxA.mHalf.getZ() + absMatrixBA.getCol2() * boxA.mHalf.getY()); - projAhalf.setCol1(absMatrixBA.getCol2() * boxA.mHalf.getX() + absMatrixBA.getCol0() * boxA.mHalf.getZ()); - projAhalf.setCol2(absMatrixBA.getCol0() * boxA.mHalf.getY() + absMatrixBA.getCol1() * boxA.mHalf.getX()); - - projBhalf.setCol0(absMatrixAB.getCol1() * boxB.mHalf.getZ() + absMatrixAB.getCol2() * boxB.mHalf.getY()); - projBhalf.setCol1(absMatrixAB.getCol2() * boxB.mHalf.getX() + absMatrixAB.getCol0() * boxB.mHalf.getZ()); - projBhalf.setCol2(absMatrixAB.getCol0() * boxB.mHalf.getY() + absMatrixAB.getCol1() * boxB.mHalf.getX()); - - vmMatrix3 gapsAxB = absPerElem(projOffset) - projAhalf - transpose(projBhalf); - - CrossAxisTest(0,0,X); - CrossAxisTest(0,1,Y); - CrossAxisTest(0,2,Z); - CrossAxisTest(1,0,X); - CrossAxisTest(1,1,Y); - CrossAxisTest(1,2,Z); - CrossAxisTest(2,0,X); - CrossAxisTest(2,1,Y); - CrossAxisTest(2,2,Z); - - // need to pick the face on each box whose normal best matches the separating axis. - // will transform vectors to be in the coordinate system of this face to simplify things later. - // for this, a permutation matrix can be used, which the next section computes. - - int dimA[3], dimB[3]; - - if ( axisType == A_AXIS ) { - if ( dot(axisA,offsetAB) < 0.0f ) - axisA = -axisA; - axisB = matrixBA * -axisA; - - vmVector3 absAxisB = vmVector3(absPerElem(axisB)); - - if ( ( absAxisB[0] > absAxisB[1] ) && ( absAxisB[0] > absAxisB[2] ) ) - faceDimB = 0; - else if ( absAxisB[1] > absAxisB[2] ) - faceDimB = 1; - else - faceDimB = 2; - } else if ( axisType == B_AXIS ) { - if ( dot(axisB,offsetBA) < 0.0f ) - axisB = -axisB; - axisA = matrixAB * -axisB; - - vmVector3 absAxisA = vmVector3(absPerElem(axisA)); - - if ( ( absAxisA[0] > absAxisA[1] ) && ( absAxisA[0] > absAxisA[2] ) ) - faceDimA = 0; - else if ( absAxisA[1] > absAxisA[2] ) - faceDimA = 1; - else - faceDimA = 2; - } - - if ( axisType == CROSS_AXIS ) { - if ( dot(axisA,offsetAB) < 0.0f ) - axisA = -axisA; - axisB = matrixBA * -axisA; - - vmVector3 absAxisA = vmVector3(absPerElem(axisA)); - vmVector3 absAxisB = vmVector3(absPerElem(axisB)); - - dimA[1] = edgeDimA; - dimB[1] = edgeDimB; - - if ( edgeDimA == 0 ) { - if ( absAxisA[1] > absAxisA[2] ) { - dimA[0] = 2; - dimA[2] = 1; - } else { - dimA[0] = 1; - dimA[2] = 2; - } - } else if ( edgeDimA == 1 ) { - if ( absAxisA[2] > absAxisA[0] ) { - dimA[0] = 0; - dimA[2] = 2; - } else { - dimA[0] = 2; - dimA[2] = 0; - } - } else { - if ( absAxisA[0] > absAxisA[1] ) { - dimA[0] = 1; - dimA[2] = 0; - } else { - dimA[0] = 0; - dimA[2] = 1; - } - } - - if ( edgeDimB == 0 ) { - if ( absAxisB[1] > absAxisB[2] ) { - dimB[0] = 2; - dimB[2] = 1; - } else { - dimB[0] = 1; - dimB[2] = 2; - } - } else if ( edgeDimB == 1 ) { - if ( absAxisB[2] > absAxisB[0] ) { - dimB[0] = 0; - dimB[2] = 2; - } else { - dimB[0] = 2; - dimB[2] = 0; - } - } else { - if ( absAxisB[0] > absAxisB[1] ) { - dimB[0] = 1; - dimB[2] = 0; - } else { - dimB[0] = 0; - dimB[2] = 1; - } - } - } else { - dimA[2] = faceDimA; - dimA[0] = (faceDimA+1)%3; - dimA[1] = (faceDimA+2)%3; - dimB[2] = faceDimB; - dimB[0] = (faceDimB+1)%3; - dimB[1] = (faceDimB+2)%3; - } - - vmMatrix3 aperm_col, bperm_col; - - aperm_col.setCol0(ident[dimA[0]]); - aperm_col.setCol1(ident[dimA[1]]); - aperm_col.setCol2(ident[dimA[2]]); - - bperm_col.setCol0(ident[dimB[0]]); - bperm_col.setCol1(ident[dimB[1]]); - bperm_col.setCol2(ident[dimB[2]]); - - vmMatrix3 aperm_row, bperm_row; - - aperm_row = transpose(aperm_col); - bperm_row = transpose(bperm_col); - - // permute all box parameters to be in the face coordinate systems - - vmMatrix3 matrixAB_perm = aperm_row * matrixAB * bperm_col; - vmMatrix3 matrixBA_perm = transpose(matrixAB_perm); - - vmVector3 offsetAB_perm, offsetBA_perm; - - offsetAB_perm = aperm_row * offsetAB; - offsetBA_perm = bperm_row * offsetBA; - - vmVector3 halfA_perm, halfB_perm; - - halfA_perm = aperm_row * boxA.mHalf; - halfB_perm = bperm_row * boxB.mHalf; - - // compute the vector between the centers of each face, in each face's coordinate frame - - vmVector3 signsA_perm, signsB_perm, scalesA_perm, scalesB_perm, faceOffsetAB_perm, faceOffsetBA_perm; - - signsA_perm = copySignPerElem(vmVector3(1.0f),aperm_row * axisA); - signsB_perm = copySignPerElem(vmVector3(1.0f),bperm_row * axisB); - scalesA_perm = mulPerElem( signsA_perm, halfA_perm ); - scalesB_perm = mulPerElem( signsB_perm, halfB_perm ); - - faceOffsetAB_perm = offsetAB_perm + matrixAB_perm.getCol2() * scalesB_perm.getZ(); - faceOffsetAB_perm.setZ( faceOffsetAB_perm.getZ() - scalesA_perm.getZ() ); - - faceOffsetBA_perm = offsetBA_perm + matrixBA_perm.getCol2() * scalesA_perm.getZ(); - faceOffsetBA_perm.setZ( faceOffsetBA_perm.getZ() - scalesB_perm.getZ() ); - - if ( maxGap < 0.0f ) { - // if boxes overlap, this will separate the faces for finding points of penetration. - - faceOffsetAB_perm -= aperm_row * axisA * maxGap * 1.01f; - faceOffsetBA_perm -= bperm_row * axisB * maxGap * 1.01f; - } - - // for each vertex/face or edge/edge pair of the two faces, find the closest points. - // - // these points each have an associated box feature (vertex, edge, or face). if each - // point is in the external Voronoi region of the other's feature, they are the - // closest points of the boxes, and the algorithm can exit. - // - // the feature pairs are arranged so that in the general case, the first test will - // succeed. degenerate cases (parallel faces) may require up to all tests in the - // worst case. - // - // if for some reason no case passes the Voronoi test, the features with the minimum - // distance are returned. - - vmPoint3 localPointA_perm, localPointB_perm; - float minDistSqr; - bool done; - - vmVector3 hA_perm( halfA_perm ), hB_perm( halfB_perm ); - - localPointA_perm.setZ( scalesA_perm.getZ() ); - localPointB_perm.setZ( scalesB_perm.getZ() ); - scalesA_perm.setZ(0.0f); - scalesB_perm.setZ(0.0f); - - int otherFaceDimA, otherFaceDimB; - FeatureType featureA, featureB; - - if ( axisType == CROSS_AXIS ) { - EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, - otherFaceDimA, otherFaceDimB, featureA, featureB, - hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, - scalesA_perm, scalesB_perm, true ); - - if ( !done ) { - VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, - featureA, featureB, - hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); - - if ( !done ) { - VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, - featureA, featureB, - hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); - } - } - } else if ( axisType == B_AXIS ) { - VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, - featureA, featureB, - hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, true ); - - if ( !done ) { - VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, - featureA, featureB, - hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, false ); - - if ( !done ) { - EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, - otherFaceDimA, otherFaceDimB, featureA, featureB, - hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, - scalesA_perm, scalesB_perm, false ); - } - } - } else { - VertexBFaceATests( done, minDistSqr, localPointA_perm, localPointB_perm, - featureA, featureB, - hA_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsB_perm, scalesB_perm, true ); - - if ( !done ) { - VertexAFaceBTests( done, minDistSqr, localPointA_perm, localPointB_perm, - featureA, featureB, - hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsA_perm, scalesA_perm, false ); - - if ( !done ) { - EdgeEdgeTests( done, minDistSqr, localPointA_perm, localPointB_perm, - otherFaceDimA, otherFaceDimB, featureA, featureB, - hA_perm, hB_perm, faceOffsetAB_perm, faceOffsetBA_perm, - matrixAB_perm, matrixBA_perm, signsA_perm, signsB_perm, - scalesA_perm, scalesB_perm, false ); - } - } - } - - // convert local points from face-local to box-local coordinate system - - - boxPointA.localPoint = vmPoint3( aperm_col * vmVector3( localPointA_perm )) ; - boxPointB.localPoint = vmPoint3( bperm_col * vmVector3( localPointB_perm )) ; - -#if 0 - // find which features of the boxes are involved. - // the only feature pairs which occur in this function are VF, FV, and EE, even though the - // closest points might actually lie on sub-features, as in a VF contact might be used for - // what's actually a VV contact. this means some feature pairs could possibly seem distinct - // from others, although their contact positions are the same. don't know yet whether this - // matters. - - int sA[3], sB[3]; - - sA[0] = boxPointA.localPoint.getX() > 0.0f; - sA[1] = boxPointA.localPoint.getY() > 0.0f; - sA[2] = boxPointA.localPoint.getZ() > 0.0f; - - sB[0] = boxPointB.localPoint.getX() > 0.0f; - sB[1] = boxPointB.localPoint.getY() > 0.0f; - sB[2] = boxPointB.localPoint.getZ() > 0.0f; - - if ( featureA == F ) { - boxPointA.setFaceFeature( dimA[2], sA[dimA[2]] ); - } else if ( featureA == E ) { - boxPointA.setEdgeFeature( dimA[2], sA[dimA[2]], dimA[otherFaceDimA], sA[dimA[otherFaceDimA]] ); - } else { - boxPointA.setVertexFeature( sA[0], sA[1], sA[2] ); - } - - if ( featureB == F ) { - boxPointB.setFaceFeature( dimB[2], sB[dimB[2]] ); - } else if ( featureB == E ) { - boxPointB.setEdgeFeature( dimB[2], sB[dimB[2]], dimB[otherFaceDimB], sB[dimB[otherFaceDimB]] ); - } else { - boxPointB.setVertexFeature( sB[0], sB[1], sB[2] ); - } -#endif - - normal = transformA * axisA; - - if ( maxGap < 0.0f ) { - return (maxGap); - } else { - return (sqrtf( minDistSqr )); - } -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h deleted file mode 100644 index 0d4957de..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2006, 2008 Sony Computer Entertainment Inc. - All rights reserved. - -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 __BOXBOXDISTANCE_H__ -#define __BOXBOXDISTANCE_H__ - - -#include "Box.h" - - -//--------------------------------------------------------------------------- -// boxBoxDistance: -// -// description: -// this computes info that can be used for the collision response of two boxes. when the boxes -// do not overlap, the points are set to the closest points of the boxes, and a positive -// distance between them is returned. if the boxes do overlap, a negative distance is returned -// and the points are set to two points that would touch after the boxes are translated apart. -// the contact normal gives the direction to repel or separate the boxes when they touch or -// overlap (it's being approximated here as one of the 15 "separating axis" directions). -// -// returns: -// positive or negative distance between two boxes. -// -// args: -// vmVector3& normal: set to a unit contact normal pointing from box A to box B. -// -// BoxPoint& boxPointA, BoxPoint& boxPointB: -// set to a closest point or point of penetration on each box. -// -// Box boxA, Box boxB: -// boxes, represented as 3 half-widths -// -// const vmTransform3& transformA, const vmTransform3& transformB: -// box transformations, in world coordinates -// -// float distanceThreshold: -// the algorithm will exit early if it finds that the boxes are more distant than this -// threshold, and not compute a contact normal or points. if this distance returned -// exceeds the threshold, all the other output data may not have been computed. by -// default, this is set to MAX_FLOAT so it will have no effect. -// -//--------------------------------------------------------------------------- - -float -boxBoxDistance(vmVector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB, - PE_REF(Box) boxA, const vmTransform3 & transformA, PE_REF(Box) boxB, - const vmTransform3 & transformB, - float distanceThreshold = FLT_MAX ); - -#endif /* __BOXBOXDISTANCE_H__ */ diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt deleted file mode 100644 index 5b4a9070..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Empty placeholder for future Libspe2 SPU task diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp deleted file mode 100644 index fe619555..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans - -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 "SpuSampleTask.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "../PlatformDefinitions.h" -#include "../SpuFakeDma.h" -#include "LinearMath/btMinMax.h" - -#ifdef __SPU__ -#include -#else -#include -#define spu_printf printf -#endif - -#define MAX_NUM_BODIES 8192 - -struct SampleTask_LocalStoreMemory -{ - ATTRIBUTE_ALIGNED16(char gLocalRigidBody [sizeof(btRigidBody)+16]); - ATTRIBUTE_ALIGNED16(void* gPointerArray[MAX_NUM_BODIES]); - -}; - - - - -//-- MAIN METHOD -void processSampleTask(void* userPtr, void* lsMemory) -{ - // BT_PROFILE("processSampleTask"); - - SampleTask_LocalStoreMemory* localMemory = (SampleTask_LocalStoreMemory*)lsMemory; - - SpuSampleTaskDesc* taskDescPtr = (SpuSampleTaskDesc*)userPtr; - SpuSampleTaskDesc& taskDesc = *taskDescPtr; - - switch (taskDesc.m_sampleCommand) - { - case CMD_SAMPLE_INTEGRATE_BODIES: - { - btTransform predictedTrans; - btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr; - - int batchSize = taskDesc.m_sampleValue; - if (batchSize>MAX_NUM_BODIES) - { - spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n"); - break; - } - int dmaArraySize = batchSize*sizeof(void*); - - uint64_t ppuArrayAddress = reinterpret_cast(eaPtr); - - // spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize); - - if (dmaArraySize>=16) - { - cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - } else - { - stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize); - } - - - for ( int i=0;igLocalRigidBody[0]; - void* shortAdd = localMemory->gPointerArray[i]; - uint64_t ppuRigidBodyAddress = reinterpret_cast(shortAdd); - - // spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr); - - int dmaBodySize = sizeof(btRigidBody); - - cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - - float timeStep = 1.f/60.f; - - btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj); - if (body) - { - if (body->isActive() && (!body->isStaticOrKinematicObject())) - { - body->predictIntegratedTransform(timeStep, predictedTrans); - body->proceedToTransform( predictedTrans); - void* ptr = (void*)localPtr; - // spu_printf("cellDmaLargePut from %llx to LS %llx\n",ptr,ppuRigidBodyAddress); - - cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - } - } - - } - break; - } - - - case CMD_SAMPLE_PREDICT_MOTION_BODIES: - { - btTransform predictedTrans; - btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr; - - int batchSize = taskDesc.m_sampleValue; - int dmaArraySize = batchSize*sizeof(void*); - - if (batchSize>MAX_NUM_BODIES) - { - spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n"); - break; - } - - uint64_t ppuArrayAddress = reinterpret_cast(eaPtr); - - // spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize); - - if (dmaArraySize>=16) - { - cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - } else - { - stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize); - } - - - for ( int i=0;igLocalRigidBody[0]; - void* shortAdd = localMemory->gPointerArray[i]; - uint64_t ppuRigidBodyAddress = reinterpret_cast(shortAdd); - - // spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr); - - int dmaBodySize = sizeof(btRigidBody); - - cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - - - float timeStep = 1.f/60.f; - - btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj); - if (body) - { - if (!body->isStaticOrKinematicObject()) - { - if (body->isActive()) - { - body->integrateVelocities( timeStep); - //damping - body->applyDamping(timeStep); - - body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); - - void* ptr = (void*)localPtr; - cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(1)); - } - } - } - - } - break; - } - - - - default: - { - - } - }; -} - - -#if defined(__CELLOS_LV2__) || defined (LIBSPE2) - -ATTRIBUTE_ALIGNED16(SampleTask_LocalStoreMemory gLocalStoreMemory); - -void* createSampleLocalStoreMemory() -{ - return &gLocalStoreMemory; -} -#else -void* createSampleLocalStoreMemory() -{ - return new SampleTask_LocalStoreMemory; -}; - -#endif diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h deleted file mode 100644 index c8ebdfd6..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans - -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 SPU_SAMPLE_TASK_H -#define SPU_SAMPLE_TASK_H - -#include "../PlatformDefinitions.h" -#include "LinearMath/btScalar.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btMatrix3x3.h" - -#include "LinearMath/btAlignedAllocator.h" - - -enum -{ - CMD_SAMPLE_INTEGRATE_BODIES = 1, - CMD_SAMPLE_PREDICT_MOTION_BODIES -}; - - - -ATTRIBUTE_ALIGNED16(struct) SpuSampleTaskDesc -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - uint32_t m_sampleCommand; - uint32_t m_taskId; - - uint64_t m_mainMemoryPtr; - int m_sampleValue; - - -}; - - -void processSampleTask(void* userPtr, void* lsMemory); -void* createSampleLocalStoreMemory(); - - -#endif //SPU_SAMPLE_TASK_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/readme.txt b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/readme.txt deleted file mode 100644 index 5b4a9070..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTask/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Empty placeholder for future Libspe2 SPU task diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp deleted file mode 100644 index 11cb9e7c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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. -*/ - -//#define __CELLOS_LV2__ 1 - -#define USE_SAMPLE_PROCESS 1 -#ifdef USE_SAMPLE_PROCESS - - -#include "SpuSampleTaskProcess.h" -#include - -#ifdef __SPU__ - - - -void SampleThreadFunc(void* userPtr,void* lsMemory) -{ - //do nothing - printf("hello world\n"); -} - - -void* SamplelsMemoryFunc() -{ - //don't create local store memory, just return 0 - return 0; -} - - -#else - - -#include "btThreadSupportInterface.h" - -//# include "SPUAssert.h" -#include - - - -extern "C" { - extern char SPU_SAMPLE_ELF_SYMBOL[]; -} - - - - - -SpuSampleTaskProcess::SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks) -:m_threadInterface(threadInterface), -m_maxNumOutstandingTasks(maxNumOutstandingTasks) -{ - - m_taskBusy.resize(m_maxNumOutstandingTasks); - m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks); - - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - m_taskBusy[i] = false; - } - m_numBusyTasks = 0; - m_currentTask = 0; - - m_initialized = false; - - m_threadInterface->startSPU(); - - -} - -SpuSampleTaskProcess::~SpuSampleTaskProcess() -{ - m_threadInterface->stopSPU(); - -} - - - -void SpuSampleTaskProcess::initialize() -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("SpuSampleTaskProcess::initialize()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - m_taskBusy[i] = false; - } - m_numBusyTasks = 0; - m_currentTask = 0; - m_initialized = true; - -} - - -void SpuSampleTaskProcess::issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand) -{ - -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("SpuSampleTaskProcess::issueTask (m_currentTask= %d\)n", m_currentTask); -#endif //DEBUG_SPU_TASK_SCHEDULING - - m_taskBusy[m_currentTask] = true; - m_numBusyTasks++; - - SpuSampleTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask]; - { - // send task description in event message - // no error checking here... - // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. - - taskDesc.m_mainMemoryPtr = reinterpret_cast(sampleMainMemPtr); - taskDesc.m_sampleValue = sampleValue; - taskDesc.m_sampleCommand = sampleCommand; - - //some bookkeeping to recognize finished tasks - taskDesc.m_taskId = m_currentTask; - } - - - m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc, m_currentTask); - - // if all tasks busy, wait for spu event to clear the task. - - if (m_numBusyTasks >= m_maxNumOutstandingTasks) - { - unsigned int taskId; - unsigned int outputSize; - - for (int i=0;iwaitForResponse(&taskId, &outputSize); - - //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); - - postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - - // find new task buffer - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - if (!m_taskBusy[i]) - { - m_currentTask = i; - break; - } - } -} - - -///Optional PPU-size post processing for each task -void SpuSampleTaskProcess::postProcess(int taskId, int outputSize) -{ - -} - - -void SpuSampleTaskProcess::flush() -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("\nSpuCollisionTaskProcess::flush()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - - - // all tasks are issued, wait for all tasks to be complete - while(m_numBusyTasks > 0) - { -// Consolidating SPU code - unsigned int taskId; - unsigned int outputSize; - - for (int i=0;iwaitForResponse(&taskId, &outputSize); - } - - //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); - - postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - - -} - -#endif - - -#endif //USE_SAMPLE_PROCESS diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.h deleted file mode 100644 index 6173225a..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSampleTaskProcess.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_SPU_SAMPLE_TASK_PROCESS_H -#define BT_SPU_SAMPLE_TASK_PROCESS_H - -#include - - -#include "PlatformDefinitions.h" - -#include - -#include "LinearMath/btAlignedObjectArray.h" - - -#include "SpuSampleTask/SpuSampleTask.h" - - -//just add your commands here, try to keep them globally unique for debugging purposes -#define CMD_SAMPLE_TASK_COMMAND 10 - - - -/// SpuSampleTaskProcess handles SPU processing of collision pairs. -/// When PPU issues a task, it will look for completed task buffers -/// PPU will do postprocessing, dependent on workunit output (not likely) -class SpuSampleTaskProcess -{ - // track task buffers that are being used, and total busy tasks - btAlignedObjectArray m_taskBusy; - btAlignedObjectArraym_spuSampleTaskDesc; - - int m_numBusyTasks; - - // the current task and the current entry to insert a new work unit - int m_currentTask; - - bool m_initialized; - - void postProcess(int taskId, int outputSize); - - class btThreadSupportInterface* m_threadInterface; - - int m_maxNumOutstandingTasks; - - - -public: - SpuSampleTaskProcess(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks); - - ~SpuSampleTaskProcess(); - - ///call initialize in the beginning of the frame, before addCollisionPairToTask - void initialize(); - - void issueTask(void* sampleMainMemPtr,int sampleValue,int sampleCommand); - - ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished - void flush(); -}; - - -#if defined(USE_LIBSPE2) && defined(__SPU__) -////////////////////MAIN///////////////////////////// -#include "../SpuLibspe2Support.h" -#include -#include -#include - -void * SamplelsMemoryFunc(); -void SampleThreadFunc(void* userPtr,void* lsMemory); - -//#define DEBUG_LIBSPE2_MAINLOOP - -int main(unsigned long long speid, addr64 argp, addr64 envp) -{ - printf("SPU is up \n"); - - ATTRIBUTE_ALIGNED128(btSpuStatus status); - ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ; - unsigned int received_message = Spu_Mailbox_Event_Nothing; - bool shutdown = false; - - cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - status.m_status = Spu_Status_Free; - status.m_lsMemory.p = SamplelsMemoryFunc(); - - cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - - while (!shutdown) - { - received_message = spu_read_in_mbox(); - - - - switch(received_message) - { - case Spu_Mailbox_Event_Shutdown: - shutdown = true; - break; - case Spu_Mailbox_Event_Task: - // refresh the status -#ifdef DEBUG_LIBSPE2_MAINLOOP - printf("SPU recieved Task \n"); -#endif //DEBUG_LIBSPE2_MAINLOOP - cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - btAssert(status.m_status==Spu_Status_Occupied); - - cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - SampleThreadFunc((void*)&taskDesc, reinterpret_cast (taskDesc.m_mainMemoryPtr) ); - break; - case Spu_Mailbox_Event_Nothing: - default: - break; - } - - // set to status free and wait for next task - status.m_status = Spu_Status_Free; - cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - - } - return 0; -} -////////////////////////////////////////////////////// -#endif - - - -#endif // BT_SPU_SAMPLE_TASK_PROCESS_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSync.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSync.h deleted file mode 100644 index 4157b8f0..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/SpuSync.h +++ /dev/null @@ -1,149 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2007 Starbreeze Studios - -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. - -Written by: Marten Svanfeldt -*/ - -#ifndef BT_SPU_SYNC_H -#define BT_SPU_SYNC_H - - -#include "PlatformDefinitions.h" - - -#if defined(WIN32) - -#define WIN32_LEAN_AND_MEAN -#ifdef _XBOX -#include -#else -#include -#endif - -///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms. -class btSpinlock -{ -public: - //typedef volatile LONG SpinVariable; - typedef CRITICAL_SECTION SpinVariable; - - btSpinlock (SpinVariable* var) - : spinVariable (var) - {} - - void Init () - { - //*spinVariable = 0; - InitializeCriticalSection(spinVariable); - } - - void Lock () - { - EnterCriticalSection(spinVariable); - } - - void Unlock () - { - LeaveCriticalSection(spinVariable); - } - -private: - SpinVariable* spinVariable; -}; - - -#elif defined (__CELLOS_LV2__) - -//#include -#include - -///The btSpinlock is a structure to allow multi-platform synchronization. This allows to port the SPU tasks to other platforms. -class btSpinlock -{ -public: - typedef CellSyncMutex SpinVariable; - - btSpinlock (SpinVariable* var) - : spinVariable (var) - {} - - void Init () - { -#ifndef __SPU__ - //*spinVariable = 1; - cellSyncMutexInitialize(spinVariable); -#endif - } - - - - void Lock () - { -#ifdef __SPU__ - // lock semaphore - /*while (cellAtomicTestAndDecr32(atomic_buf, (uint64_t)spinVariable) == 0) - { - - };*/ - cellSyncMutexLock((uint64_t)spinVariable); -#endif - } - - void Unlock () - { -#ifdef __SPU__ - //cellAtomicIncr32(atomic_buf, (uint64_t)spinVariable); - cellSyncMutexUnlock((uint64_t)spinVariable); -#endif - } - - -private: - SpinVariable* spinVariable; - ATTRIBUTE_ALIGNED128(uint32_t atomic_buf[32]); -}; - -#else -//create a dummy implementation (without any locking) useful for serial processing -class btSpinlock -{ -public: - typedef int SpinVariable; - - btSpinlock (SpinVariable* var) - : spinVariable (var) - {} - - void Init () - { - } - - void Lock () - { - } - - void Unlock () - { - } - -private: - SpinVariable* spinVariable; -}; - - -#endif - - -#endif //BT_SPU_SYNC_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbDynBody.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbDynBody.h deleted file mode 100644 index a7f4bf1b..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbDynBody.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - -#ifndef BT_RB_DYN_BODY_H__ -#define BT_RB_DYN_BODY_H__ - -#include "vectormath/vmInclude.h" -using namespace Vectormath::Aos; - -#include "TrbStateVec.h" - -class CollObject; - -class TrbDynBody -{ -public: - TrbDynBody() - { - fMass = 0.0f; - fCollObject = NULL; - fElasticity = 0.2f; - fFriction = 0.8f; - } - - // Get methods - float getMass() const {return fMass;}; - float getElasticity() const {return fElasticity;} - float getFriction() const {return fFriction;} - CollObject* getCollObject() const {return fCollObject;} - const Matrix3 &getBodyInertia() const {return fIBody;} - const Matrix3 &getBodyInertiaInv() const {return fIBodyInv;} - float getMassInv() const {return fMassInv;} - - // Set methods - void setMass(float mass) {fMass=mass;fMassInv=mass>0.0f?1.0f/mass:0.0f;} - void setBodyInertia(const Matrix3 bodyInertia) {fIBody = bodyInertia;fIBodyInv = inverse(bodyInertia);} - void setElasticity(float elasticity) {fElasticity = elasticity;} - void setFriction(float friction) {fFriction = friction;} - void setCollObject(CollObject *collObj) {fCollObject = collObj;} - - void setBodyInertiaInv(const Matrix3 bodyInertiaInv) - { - fIBody = inverse(bodyInertiaInv); - fIBodyInv = bodyInertiaInv; - } - void setMassInv(float invMass) { - fMass= invMass>0.0f ? 1.0f/invMass :0.0f; - fMassInv=invMass; - } - - -private: - // Rigid Body constants - float fMass; // Rigid Body mass - float fMassInv; // Inverse of mass - Matrix3 fIBody; // Inertia matrix in body's coords - Matrix3 fIBodyInv; // Inertia matrix inverse in body's coords - float fElasticity; // Coefficient of restitution - float fFriction; // Coefficient of friction - -public: - CollObject* fCollObject; // Collision object corresponding the RB -} __attribute__ ((aligned(16))); - -#endif //BT_RB_DYN_BODY_H__ - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbStateVec.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbStateVec.h deleted file mode 100644 index b6d895e1..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/TrbStateVec.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - -#ifndef BT_TRBSTATEVEC_H__ -#define BT_TRBSTATEVEC_H__ - -#include -#ifdef PFX_USE_FREE_VECTORMATH -#include "vecmath/vmInclude.h" -#else -#include "vectormath/vmInclude.h" -#endif //PFX_USE_FREE_VECTORMATH - - -#include "PlatformDefinitions.h" - - -static inline vmVector3 read_Vector3(const float* p) -{ - vmVector3 v; - loadXYZ(v, p); - return v; -} - -static inline vmQuat read_Quat(const float* p) -{ - vmQuat vq; - loadXYZW(vq, p); - return vq; -} - -static inline void store_Vector3(const vmVector3 &src, float* p) -{ - vmVector3 v = src; - storeXYZ(v, p); -} - -static inline void store_Quat(const vmQuat &src, float* p) -{ - vmQuat vq = src; - storeXYZW(vq, p); -} - -// Motion Type -enum { - PfxMotionTypeFixed = 0, - PfxMotionTypeActive, - PfxMotionTypeKeyframe, - PfxMotionTypeOneWay, - PfxMotionTypeTrigger, - PfxMotionTypeCount -}; - -#define PFX_MOTION_MASK_DYNAMIC 0x0a // Active,OneWay -#define PFX_MOTION_MASK_STATIC 0x95 // Fixed,Keyframe,Trigger,Sleeping -#define PFX_MOTION_MASK_SLEEP 0x0e // Can sleep -#define PFX_MOTION_MASK_TYPE 0x7f - -// -// Rigid Body state -// - -#ifdef __CELLOS_LV2__ -ATTRIBUTE_ALIGNED128(class) TrbState -#else -ATTRIBUTE_ALIGNED16(class) TrbState -#endif - -{ -public: - TrbState() - { - setMotionType(PfxMotionTypeActive); - contactFilterSelf=contactFilterTarget=0xffffffff; - deleted = 0; - mSleeping = 0; - useSleep = 1; - trbBodyIdx=0; - mSleepCount=0; - useCcd = 0; - useContactCallback = 0; - useSleepCallback = 0; - linearDamping = 1.0f; - angularDamping = 0.99f; - } - - TrbState(const uint8_t m, const vmVector3& x, const vmQuat& q, const vmVector3& v, const vmVector3& omega ); - - uint16_t mSleepCount; - uint8_t mMotionType; - uint8_t deleted : 1; - uint8_t mSleeping : 1; - uint8_t useSleep : 1; - uint8_t useCcd : 1; - uint8_t useContactCallback : 1; - uint8_t useSleepCallback : 1; - - uint16_t trbBodyIdx; - uint32_t contactFilterSelf; - uint32_t contactFilterTarget; - - float center[3]; // AABB center(World) - float half[3]; // AABB half(World) - - float linearDamping; - float angularDamping; - - float deltaLinearVelocity[3]; - float deltaAngularVelocity[3]; - - float fX[3]; // position - float fQ[4]; // orientation - float fV[3]; // velocity - float fOmega[3]; // angular velocity - - inline void setZero(); // Zeroes out the elements - inline void setIdentity(); // Sets the rotation to identity and zeroes out the other elements - - bool isDeleted() const {return deleted==1;} - - uint16_t getRigidBodyId() const {return trbBodyIdx;} - void setRigidBodyId(uint16_t i) {trbBodyIdx = i;} - - - uint32_t getContactFilterSelf() const {return contactFilterSelf;} - void setContactFilterSelf(uint32_t filter) {contactFilterSelf = filter;} - - uint32_t getContactFilterTarget() const {return contactFilterTarget;} - void setContactFilterTarget(uint32_t filter) {contactFilterTarget = filter;} - - float getLinearDamping() const {return linearDamping;} - float getAngularDamping() const {return angularDamping;} - - void setLinearDamping(float damping) {linearDamping=damping;} - void setAngularDamping(float damping) {angularDamping=damping;} - - - uint8_t getMotionType() const {return mMotionType;} - void setMotionType(uint8_t t) {mMotionType = t;mSleeping=0;mSleepCount=0;} - - uint8_t getMotionMask() const {return (1< - -#include "SpuCollisionTaskProcess.h" - -#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" - - - -///The number of threads should be equal to the number of available cores -///@todo: each worker should be linked to a single core, using SetThreadIdealProcessor. - -///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication -///Setup and initialize SPU/CELL/Libspe2 -Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo) -{ - m_maxNumTasks = threadConstructionInfo.m_numThreads; - startThreads(threadConstructionInfo); -} - -///cleanup/shutdown Libspe2 -Win32ThreadSupport::~Win32ThreadSupport() -{ - stopSPU(); -} - - - - -#include - -DWORD WINAPI Thread_no_1( LPVOID lpParam ) -{ - - Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam; - - - while (1) - { - WaitForSingleObject(status->m_eventStartHandle,INFINITE); - - void* userPtr = status->m_userPtr; - - if (userPtr) - { - btAssert(status->m_status); - status->m_userThreadFunc(userPtr,status->m_lsMemory); - status->m_status = 2; - SetEvent(status->m_eventCompletetHandle); - } else - { - //exit Thread - status->m_status = 3; - printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle); - SetEvent(status->m_eventCompletetHandle); - break; - } - - } - - printf("Thread TERMINATED\n"); - return 0; - -} - -///send messages to SPUs -void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) -{ - /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc); - - ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished - - - - switch (uiCommand) - { - case CMD_GATHER_AND_PROCESS_PAIRLIST: - { - - -//#define SINGLE_THREADED 1 -#ifdef SINGLE_THREADED - - btSpuStatus& spuStatus = m_activeSpuStatus[0]; - spuStatus.m_userPtr=(void*)uiArgument0; - spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); - HANDLE handle =0; -#else - - - btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; - btAssert(taskId>=0); - btAssert(int(taskId) 1); - spuStatus.m_status = 0; - - ///need to find an active spu - btAssert(last>=0); - -#else - last=0; - btSpuStatus& spuStatus = m_activeSpuStatus[last]; -#endif //SINGLE_THREADED - - - - *puiArgument0 = spuStatus.m_taskId; - *puiArgument1 = spuStatus.m_status; - - -} - - -///check for messages from SPUs -bool Win32ThreadSupport::isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds) -{ - ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response - - ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' - - - btAssert(m_activeSpuStatus.size()); - - int last = -1; -#ifndef SINGLE_THREADED - DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, timeOutInMilliseconds); - - if ((res != STATUS_TIMEOUT) && (res != WAIT_FAILED)) - { - - btAssert(res != WAIT_FAILED); - last = res - WAIT_OBJECT_0; - - btSpuStatus& spuStatus = m_activeSpuStatus[last]; - btAssert(spuStatus.m_threadHandle); - btAssert(spuStatus.m_eventCompletetHandle); - - //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); - btAssert(spuStatus.m_status > 1); - spuStatus.m_status = 0; - - ///need to find an active spu - btAssert(last>=0); - - #else - last=0; - btSpuStatus& spuStatus = m_activeSpuStatus[last]; - #endif //SINGLE_THREADED - - - - *puiArgument0 = spuStatus.m_taskId; - *puiArgument1 = spuStatus.m_status; - - return true; - } - - return false; -} - - -void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo) -{ - - m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); - m_completeHandles.resize(threadConstructionInfo.m_numThreads); - - m_maxNumTasks = threadConstructionInfo.m_numThreads; - - for (int i=0;i0) - { - WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); - } - - - spuStatus.m_userPtr = 0; - SetEvent(spuStatus.m_eventStartHandle); - WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); - - CloseHandle(spuStatus.m_eventCompletetHandle); - CloseHandle(spuStatus.m_eventStartHandle); - CloseHandle(spuStatus.m_threadHandle); - - } - - m_activeSpuStatus.clear(); - m_completeHandles.clear(); - -} - - - -class btWin32Barrier : public btBarrier -{ -private: - CRITICAL_SECTION mExternalCriticalSection; - CRITICAL_SECTION mLocalCriticalSection; - HANDLE mRunEvent,mNotifyEvent; - int mCounter,mEnableCounter; - int mMaxCount; - -public: - btWin32Barrier() - { - mCounter = 0; - mMaxCount = 1; - mEnableCounter = 0; - InitializeCriticalSection(&mExternalCriticalSection); - InitializeCriticalSection(&mLocalCriticalSection); - mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - } - - virtual ~btWin32Barrier() - { - DeleteCriticalSection(&mExternalCriticalSection); - DeleteCriticalSection(&mLocalCriticalSection); - CloseHandle(mRunEvent); - CloseHandle(mNotifyEvent); - } - - void sync() - { - int eventId; - - EnterCriticalSection(&mExternalCriticalSection); - - //PFX_PRINTF("enter taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); - - if(mEnableCounter > 0) { - ResetEvent(mNotifyEvent); - LeaveCriticalSection(&mExternalCriticalSection); - WaitForSingleObject(mNotifyEvent,INFINITE); - EnterCriticalSection(&mExternalCriticalSection); - } - - eventId = mCounter; - mCounter++; - - if(eventId == mMaxCount-1) { - SetEvent(mRunEvent); - - mEnableCounter = mCounter-1; - mCounter = 0; - } - else { - ResetEvent(mRunEvent); - LeaveCriticalSection(&mExternalCriticalSection); - WaitForSingleObject(mRunEvent,INFINITE); - EnterCriticalSection(&mExternalCriticalSection); - mEnableCounter--; - } - - if(mEnableCounter == 0) { - SetEvent(mNotifyEvent); - } - - //PFX_PRINTF("leave taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); - - LeaveCriticalSection(&mExternalCriticalSection); - } - - virtual void setMaxCount(int n) {mMaxCount = n;} - virtual int getMaxCount() {return mMaxCount;} -}; - -class btWin32CriticalSection : public btCriticalSection -{ -private: - CRITICAL_SECTION mCriticalSection; - -public: - btWin32CriticalSection() - { - InitializeCriticalSection(&mCriticalSection); - } - - ~btWin32CriticalSection() - { - DeleteCriticalSection(&mCriticalSection); - } - - unsigned int getSharedParam(int i) - { - btAssert(i>=0&&i<31); - return mCommonBuff[i+1]; - } - - void setSharedParam(int i,unsigned int p) - { - btAssert(i>=0&&i<31); - mCommonBuff[i+1] = p; - } - - void lock() - { - EnterCriticalSection(&mCriticalSection); - mCommonBuff[0] = 1; - } - - void unlock() - { - mCommonBuff[0] = 0; - LeaveCriticalSection(&mCriticalSection); - } -}; - - -btBarrier* Win32ThreadSupport::createBarrier() -{ - unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16); - btWin32Barrier* barrier = new(mem) btWin32Barrier(); - barrier->setMaxCount(getNumTasks()); - return barrier; -} - -btCriticalSection* Win32ThreadSupport::createCriticalSection() -{ - unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16); - btWin32CriticalSection* cs = new(mem) btWin32CriticalSection(); - return cs; -} - -void Win32ThreadSupport::deleteBarrier(btBarrier* barrier) -{ - barrier->~btBarrier(); - btAlignedFree(barrier); -} - -void Win32ThreadSupport::deleteCriticalSection(btCriticalSection* criticalSection) -{ - criticalSection->~btCriticalSection(); - btAlignedFree(criticalSection); -} - - -#endif //USE_WIN32_THREADING - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.h deleted file mode 100644 index f688e6c8..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/Win32ThreadSupport.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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/btScalar.h" -#include "PlatformDefinitions.h" - -#ifdef USE_WIN32_THREADING //platform specific defines are defined in PlatformDefinitions.h - -#ifndef BT_WIN32_THREAD_SUPPORT_H -#define BT_WIN32_THREAD_SUPPORT_H - -#include "LinearMath/btAlignedObjectArray.h" - -#include "btThreadSupportInterface.h" - - -typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory); -typedef void* (*Win32lsMemorySetupFunc)(); - - -///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication -class Win32ThreadSupport : public btThreadSupportInterface -{ -public: - ///placeholder, until libspe2 support is there - struct btSpuStatus - { - uint32_t m_taskId; - uint32_t m_commandId; - uint32_t m_status; - - Win32ThreadFunc m_userThreadFunc; - void* m_userPtr; //for taskDesc etc - void* m_lsMemory; //initialized using Win32LocalStoreMemorySetupFunc - - void* m_threadHandle; //this one is calling 'Win32ThreadFunc' - - void* m_eventStartHandle; - char m_eventStartHandleName[32]; - - void* m_eventCompletetHandle; - char m_eventCompletetHandleName[32]; - - - }; -private: - - btAlignedObjectArray m_activeSpuStatus; - btAlignedObjectArray m_completeHandles; - - int m_maxNumTasks; -public: - ///Setup and initialize SPU/CELL/Libspe2 - - struct Win32ThreadConstructionInfo - { - Win32ThreadConstructionInfo(const char* uniqueName, - Win32ThreadFunc userThreadFunc, - Win32lsMemorySetupFunc lsMemoryFunc, - int numThreads=1, - int threadStackSize=65535 - ) - :m_uniqueName(uniqueName), - m_userThreadFunc(userThreadFunc), - m_lsMemoryFunc(lsMemoryFunc), - m_numThreads(numThreads), - m_threadStackSize(threadStackSize) - { - - } - - const char* m_uniqueName; - Win32ThreadFunc m_userThreadFunc; - Win32lsMemorySetupFunc m_lsMemoryFunc; - int m_numThreads; - int m_threadStackSize; - - }; - - - - Win32ThreadSupport(const Win32ThreadConstructionInfo& threadConstructionInfo); - -///cleanup/shutdown Libspe2 - virtual ~Win32ThreadSupport(); - - void startThreads(const Win32ThreadConstructionInfo& threadInfo); - - -///send messages to SPUs - virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1); - -///check for messages from SPUs - virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1); - - virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds); - -///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) - virtual void startSPU(); - -///tell the task scheduler we are done with the SPU tasks - virtual void stopSPU(); - - virtual void setNumTasks(int numTasks) - { - m_maxNumTasks = numTasks; - } - - virtual int getNumTasks() const - { - return m_maxNumTasks; - } - - virtual void* getThreadLocalMemory(int taskId) - { - return m_activeSpuStatus[taskId].m_lsMemory; - } - virtual btBarrier* createBarrier(); - - virtual btCriticalSection* createCriticalSection(); - - virtual void deleteBarrier(btBarrier* barrier); - - virtual void deleteCriticalSection(btCriticalSection* criticalSection); -}; - -#endif //BT_WIN32_THREAD_SUPPORT_H - -#endif //USE_WIN32_THREADING diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp deleted file mode 100644 index e1d0219d..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org -Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. - -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. -*/ - -///The 3 following lines include the CPU implementation of the kernels, keep them in this order. -#include "BulletMultiThreaded/btGpuDefines.h" -#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h" -#include "BulletMultiThreaded/btGpuUtilsSharedCode.h" - - - -#include "LinearMath/btAlignedAllocator.h" -#include "LinearMath/btQuickprof.h" -#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" - - - -#include "btGpuDefines.h" -#include "btGpuUtilsSharedDefs.h" - -#include "btGpu3DGridBroadphaseSharedDefs.h" - -#include "btGpu3DGridBroadphase.h" -#include //for memset - - -#include - - - -static bt3DGridBroadphaseParams s3DGridBroadphaseParams; - - - -btGpu3DGridBroadphase::btGpu3DGridBroadphase( const btVector3& worldAabbMin,const btVector3& worldAabbMax, - int gridSizeX, int gridSizeY, int gridSizeZ, - int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, - int maxBodiesPerCell, - btScalar cellFactorAABB) : - btSimpleBroadphase(maxSmallProxies, -// new (btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16)) btSortedOverlappingPairCache), - new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache), - m_bInitialized(false), - m_numBodies(0) -{ - _initialize(worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, - maxSmallProxies, maxLargeProxies, maxPairsPerBody, - maxBodiesPerCell, cellFactorAABB); -} - - - -btGpu3DGridBroadphase::btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, - const btVector3& worldAabbMin,const btVector3& worldAabbMax, - int gridSizeX, int gridSizeY, int gridSizeZ, - int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, - int maxBodiesPerCell, - btScalar cellFactorAABB) : - btSimpleBroadphase(maxSmallProxies, overlappingPairCache), - m_bInitialized(false), - m_numBodies(0) -{ - _initialize(worldAabbMin, worldAabbMax, gridSizeX, gridSizeY, gridSizeZ, - maxSmallProxies, maxLargeProxies, maxPairsPerBody, - maxBodiesPerCell, cellFactorAABB); -} - - - -btGpu3DGridBroadphase::~btGpu3DGridBroadphase() -{ - //btSimpleBroadphase will free memory of btSortedOverlappingPairCache, because m_ownsPairCache - btAssert(m_bInitialized); - _finalize(); -} - - - -void btGpu3DGridBroadphase::_initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, - int gridSizeX, int gridSizeY, int gridSizeZ, - int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, - int maxBodiesPerCell, - btScalar cellFactorAABB) -{ - // set various paramerers - m_ownsPairCache = true; - m_params.m_gridSizeX = gridSizeX; - m_params.m_gridSizeY = gridSizeY; - m_params.m_gridSizeZ = gridSizeZ; - m_params.m_numCells = m_params.m_gridSizeX * m_params.m_gridSizeY * m_params.m_gridSizeZ; - btVector3 w_org = worldAabbMin; - m_params.m_worldOriginX = w_org.getX(); - m_params.m_worldOriginY = w_org.getY(); - m_params.m_worldOriginZ = w_org.getZ(); - btVector3 w_size = worldAabbMax - worldAabbMin; - m_params.m_cellSizeX = w_size.getX() / m_params.m_gridSizeX; - m_params.m_cellSizeY = w_size.getY() / m_params.m_gridSizeY; - m_params.m_cellSizeZ = w_size.getZ() / m_params.m_gridSizeZ; - m_maxRadius = btMin(btMin(m_params.m_cellSizeX, m_params.m_cellSizeY), m_params.m_cellSizeZ); - m_maxRadius *= btScalar(0.5f); - m_params.m_numBodies = m_numBodies; - m_params.m_maxBodiesPerCell = maxBodiesPerCell; - - m_numLargeHandles = 0; - m_maxLargeHandles = maxLargeProxies; - - m_maxPairsPerBody = maxPairsPerBody; - - m_cellFactorAABB = cellFactorAABB; - - m_LastLargeHandleIndex = -1; - - btAssert(!m_bInitialized); - // allocate host storage - m_hBodiesHash = new unsigned int[m_maxHandles * 2]; - memset(m_hBodiesHash, 0x00, m_maxHandles*2*sizeof(unsigned int)); - - m_hCellStart = new unsigned int[m_params.m_numCells]; - memset(m_hCellStart, 0x00, m_params.m_numCells * sizeof(unsigned int)); - - m_hPairBuffStartCurr = new unsigned int[m_maxHandles * 2 + 2]; - // --------------- for now, init with m_maxPairsPerBody for each body - m_hPairBuffStartCurr[0] = 0; - m_hPairBuffStartCurr[1] = 0; - for(int i = 1; i <= m_maxHandles; i++) - { - m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; - m_hPairBuffStartCurr[i * 2 + 1] = 0; - } - //---------------- - unsigned int numAABB = m_maxHandles + m_maxLargeHandles; - m_hAABB = new bt3DGrid3F1U[numAABB * 2]; // AABB Min & Max - - m_hPairBuff = new unsigned int[m_maxHandles * m_maxPairsPerBody]; - memset(m_hPairBuff, 0x00, m_maxHandles * m_maxPairsPerBody * sizeof(unsigned int)); // needed? - - m_hPairScan = new unsigned int[m_maxHandles + 1]; - - m_hPairOut = new unsigned int[m_maxHandles * m_maxPairsPerBody]; - -// large proxies - - // allocate handles buffer and put all handles on free list - m_pLargeHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * m_maxLargeHandles, 16); - m_pLargeHandles = new(m_pLargeHandlesRawPtr) btSimpleBroadphaseProxy[m_maxLargeHandles]; - m_firstFreeLargeHandle = 0; - { - for (int i = m_firstFreeLargeHandle; i < m_maxLargeHandles; i++) - { - m_pLargeHandles[i].SetNextFree(i + 1); - m_pLargeHandles[i].m_uniqueId = m_maxHandles+2+i; - } - m_pLargeHandles[m_maxLargeHandles - 1].SetNextFree(0); - } - -// debug data - m_numPairsAdded = 0; - m_numOverflows = 0; - - m_bInitialized = true; -} - - - -void btGpu3DGridBroadphase::_finalize() -{ - btAssert(m_bInitialized); - delete [] m_hBodiesHash; - delete [] m_hCellStart; - delete [] m_hPairBuffStartCurr; - delete [] m_hAABB; - delete [] m_hPairBuff; - delete [] m_hPairScan; - delete [] m_hPairOut; - btAlignedFree(m_pLargeHandlesRawPtr); - m_bInitialized = false; -} - - - -void btGpu3DGridBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) -{ - if(m_numHandles <= 0) - { - BT_PROFILE("addLarge2LargePairsToCache"); - addLarge2LargePairsToCache(dispatcher); - return; - } - // update constants - setParameters(&m_params); - // prepare AABB array - prepareAABB(); - // calculate hash - calcHashAABB(); - // sort bodies based on hash - sortHash(); - // find start of each cell - findCellStart(); - // findOverlappingPairs (small/small) - findOverlappingPairs(); - // findOverlappingPairs (small/large) - findPairsLarge(); - // add pairs to CPU cache - computePairCacheChanges(); - scanOverlappingPairBuff(); - squeezeOverlappingPairBuff(); - addPairsToCache(dispatcher); - // find and add large/large pairs to CPU cache - addLarge2LargePairsToCache(dispatcher); - return; -} - - - -void btGpu3DGridBroadphase::addPairsToCache(btDispatcher* dispatcher) -{ - m_numPairsAdded = 0; - m_numPairsRemoved = 0; - for(int i = 0; i < m_numHandles; i++) - { - unsigned int num = m_hPairScan[i+1] - m_hPairScan[i]; - if(!num) - { - continue; - } - unsigned int* pInp = m_hPairOut + m_hPairScan[i]; - unsigned int index0 = m_hAABB[i * 2].uw; - btSimpleBroadphaseProxy* proxy0 = &m_pHandles[index0]; - for(unsigned int j = 0; j < num; j++) - { - unsigned int indx1_s = pInp[j]; - unsigned int index1 = indx1_s & (~BT_3DGRID_PAIR_ANY_FLG); - btSimpleBroadphaseProxy* proxy1; - if(index1 < (unsigned int)m_maxHandles) - { - proxy1 = &m_pHandles[index1]; - } - else - { - index1 -= m_maxHandles; - btAssert((index1 >= 0) && (index1 < (unsigned int)m_maxLargeHandles)); - proxy1 = &m_pLargeHandles[index1]; - } - if(indx1_s & BT_3DGRID_PAIR_NEW_FLG) - { - m_pairCache->addOverlappingPair(proxy0,proxy1); - m_numPairsAdded++; - } - else - { - m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); - m_numPairsRemoved++; - } - } - } -} - - - -btBroadphaseProxy* btGpu3DGridBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) -{ - btBroadphaseProxy* proxy; - bool bIsLarge = isLargeProxy(aabbMin, aabbMax); - if(bIsLarge) - { - if (m_numLargeHandles >= m_maxLargeHandles) - { - ///you have to increase the cell size, so 'large' proxies become 'small' proxies (fitting a cell) - btAssert(0); - return 0; //should never happen, but don't let the game crash ;-) - } - btAssert((aabbMin[0]<= aabbMax[0]) && (aabbMin[1]<= aabbMax[1]) && (aabbMin[2]<= aabbMax[2])); - int newHandleIndex = allocLargeHandle(); - proxy = new (&m_pLargeHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); - } - else - { - proxy = btSimpleBroadphase::createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher, multiSapProxy); - } - return proxy; -} - - - -void btGpu3DGridBroadphase::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) -{ - bool bIsLarge = isLargeProxy(proxy); - if(bIsLarge) - { - - btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); - freeLargeHandle(proxy0); - m_pairCache->removeOverlappingPairsContainingProxy(proxy,dispatcher); - } - else - { - btSimpleBroadphase::destroyProxy(proxy, dispatcher); - } - return; -} - - - -void btGpu3DGridBroadphase::resetPool(btDispatcher* dispatcher) -{ - m_hPairBuffStartCurr[0] = 0; - m_hPairBuffStartCurr[1] = 0; - for(int i = 1; i <= m_maxHandles; i++) - { - m_hPairBuffStartCurr[i * 2] = m_hPairBuffStartCurr[(i-1) * 2] + m_maxPairsPerBody; - m_hPairBuffStartCurr[i * 2 + 1] = 0; - } -} - - - -bool btGpu3DGridBroadphase::isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax) -{ - btVector3 diag = aabbMax - aabbMin; - - ///use the bounding sphere radius of this bounding box, to include rotation - btScalar radius = diag.length() * btScalar(0.5f); - radius *= m_cellFactorAABB; // user-defined factor - - return (radius > m_maxRadius); -} - - - -bool btGpu3DGridBroadphase::isLargeProxy(btBroadphaseProxy* proxy) -{ - return (proxy->getUid() >= (m_maxHandles+2)); -} - - - -void btGpu3DGridBroadphase::addLarge2LargePairsToCache(btDispatcher* dispatcher) -{ - int i,j; - if (m_numLargeHandles <= 0) - { - return; - } - int new_largest_index = -1; - for(i = 0; i <= m_LastLargeHandleIndex; i++) - { - btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; - if(!proxy0->m_clientObject) - { - continue; - } - new_largest_index = i; - for(j = i + 1; j <= m_LastLargeHandleIndex; j++) - { - btSimpleBroadphaseProxy* proxy1 = &m_pLargeHandles[j]; - if(!proxy1->m_clientObject) - { - continue; - } - btAssert(proxy0 != proxy1); - btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); - btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); - if(aabbOverlap(p0,p1)) - { - if (!m_pairCache->findPair(proxy0,proxy1)) - { - m_pairCache->addOverlappingPair(proxy0,proxy1); - } - } - else - { - if(m_pairCache->findPair(proxy0,proxy1)) - { - m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); - } - } - } - } - m_LastLargeHandleIndex = new_largest_index; - return; -} - - - -void btGpu3DGridBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax) -{ - btSimpleBroadphase::rayTest(rayFrom, rayTo, rayCallback); - for (int i=0; i <= m_LastLargeHandleIndex; i++) - { - btSimpleBroadphaseProxy* proxy = &m_pLargeHandles[i]; - if(!proxy->m_clientObject) - { - continue; - } - rayCallback.process(proxy); - } -} - - - -// -// overrides for CPU version -// - - - -void btGpu3DGridBroadphase::prepareAABB() -{ - BT_PROFILE("prepareAABB"); - bt3DGrid3F1U* pBB = m_hAABB; - int i; - int new_largest_index = -1; - unsigned int num_small = 0; - for(i = 0; i <= m_LastHandleIndex; i++) - { - btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i]; - if(!proxy0->m_clientObject) - { - continue; - } - new_largest_index = i; - pBB->fx = proxy0->m_aabbMin.getX(); - pBB->fy = proxy0->m_aabbMin.getY(); - pBB->fz = proxy0->m_aabbMin.getZ(); - pBB->uw = i; - pBB++; - pBB->fx = proxy0->m_aabbMax.getX(); - pBB->fy = proxy0->m_aabbMax.getY(); - pBB->fz = proxy0->m_aabbMax.getZ(); - pBB->uw = num_small; - pBB++; - num_small++; - } - m_LastHandleIndex = new_largest_index; - new_largest_index = -1; - unsigned int num_large = 0; - for(i = 0; i <= m_LastLargeHandleIndex; i++) - { - btSimpleBroadphaseProxy* proxy0 = &m_pLargeHandles[i]; - if(!proxy0->m_clientObject) - { - continue; - } - new_largest_index = i; - pBB->fx = proxy0->m_aabbMin.getX(); - pBB->fy = proxy0->m_aabbMin.getY(); - pBB->fz = proxy0->m_aabbMin.getZ(); - pBB->uw = i + m_maxHandles; - pBB++; - pBB->fx = proxy0->m_aabbMax.getX(); - pBB->fy = proxy0->m_aabbMax.getY(); - pBB->fz = proxy0->m_aabbMax.getZ(); - pBB->uw = num_large + m_maxHandles; - pBB++; - num_large++; - } - m_LastLargeHandleIndex = new_largest_index; - // paranoid checks - btAssert(num_small == m_numHandles); - btAssert(num_large == m_numLargeHandles); - return; -} - - - -void btGpu3DGridBroadphase::setParameters(bt3DGridBroadphaseParams* hostParams) -{ - s3DGridBroadphaseParams = *hostParams; - return; -} - - - -void btGpu3DGridBroadphase::calcHashAABB() -{ - BT_PROFILE("bt3DGrid_calcHashAABB"); - btGpu_calcHashAABB(m_hAABB, m_hBodiesHash, m_numHandles); - return; -} - - - -void btGpu3DGridBroadphase::sortHash() -{ - class bt3DGridHashKey - { - public: - unsigned int hash; - unsigned int index; - void quickSort(bt3DGridHashKey* pData, int lo, int hi) - { - int i=lo, j=hi; - bt3DGridHashKey x = pData[(lo+hi)/2]; - do - { - while(pData[i].hash > x.hash) i++; - while(x.hash > pData[j].hash) j--; - if(i <= j) - { - bt3DGridHashKey t = pData[i]; - pData[i] = pData[j]; - pData[j] = t; - i++; j--; - } - } while(i <= j); - if(lo < j) pData->quickSort(pData, lo, j); - if(i < hi) pData->quickSort(pData, i, hi); - } - }; - BT_PROFILE("bt3DGrid_sortHash"); - bt3DGridHashKey* pHash = (bt3DGridHashKey*)m_hBodiesHash; - pHash->quickSort(pHash, 0, m_numHandles - 1); - return; -} - - - -void btGpu3DGridBroadphase::findCellStart() -{ - BT_PROFILE("bt3DGrid_findCellStart"); - btGpu_findCellStart(m_hBodiesHash, m_hCellStart, m_numHandles, m_params.m_numCells); - return; -} - - - -void btGpu3DGridBroadphase::findOverlappingPairs() -{ - BT_PROFILE("bt3DGrid_findOverlappingPairs"); - btGpu_findOverlappingPairs(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles); - return; -} - - - -void btGpu3DGridBroadphase::findPairsLarge() -{ - BT_PROFILE("bt3DGrid_findPairsLarge"); - btGpu_findPairsLarge(m_hAABB, m_hBodiesHash, m_hCellStart, m_hPairBuff, m_hPairBuffStartCurr, m_numHandles, m_numLargeHandles); - return; -} - - - -void btGpu3DGridBroadphase::computePairCacheChanges() -{ - BT_PROFILE("bt3DGrid_computePairCacheChanges"); - btGpu_computePairCacheChanges(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScan, m_hAABB, m_numHandles); - return; -} - - - -void btGpu3DGridBroadphase::scanOverlappingPairBuff() -{ - BT_PROFILE("bt3DGrid_scanOverlappingPairBuff"); - m_hPairScan[0] = 0; - for(int i = 1; i <= m_numHandles; i++) - { - unsigned int delta = m_hPairScan[i]; - m_hPairScan[i] = m_hPairScan[i-1] + delta; - } - return; -} - - - -void btGpu3DGridBroadphase::squeezeOverlappingPairBuff() -{ - BT_PROFILE("bt3DGrid_squeezeOverlappingPairBuff"); - btGpu_squeezeOverlappingPairBuff(m_hPairBuff, m_hPairBuffStartCurr, m_hPairScan, m_hPairOut, m_hAABB, m_numHandles); - return; -} - - - -#include "btGpu3DGridBroadphaseSharedCode.h" - - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.h deleted file mode 100644 index 1154a5fa..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphase.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org -Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. - -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 BTGPU3DGRIDBROADPHASE_H -#define BTGPU3DGRIDBROADPHASE_H - -//---------------------------------------------------------------------------------------- - -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" - -#include "btGpu3DGridBroadphaseSharedTypes.h" - -//---------------------------------------------------------------------------------------- - -///The btGpu3DGridBroadphase uses GPU-style code compiled for CPU to compute overlapping pairs - -class btGpu3DGridBroadphase : public btSimpleBroadphase -{ -protected: - bool m_bInitialized; - unsigned int m_numBodies; - unsigned int m_numCells; - unsigned int m_maxPairsPerBody; - btScalar m_cellFactorAABB; - unsigned int m_maxBodiesPerCell; - bt3DGridBroadphaseParams m_params; - btScalar m_maxRadius; - // CPU data - unsigned int* m_hBodiesHash; - unsigned int* m_hCellStart; - unsigned int* m_hPairBuffStartCurr; - bt3DGrid3F1U* m_hAABB; - unsigned int* m_hPairBuff; - unsigned int* m_hPairScan; - unsigned int* m_hPairOut; -// large proxies - int m_numLargeHandles; - int m_maxLargeHandles; - int m_LastLargeHandleIndex; - btSimpleBroadphaseProxy* m_pLargeHandles; - void* m_pLargeHandlesRawPtr; - int m_firstFreeLargeHandle; - int allocLargeHandle() - { - btAssert(m_numLargeHandles < m_maxLargeHandles); - int freeLargeHandle = m_firstFreeLargeHandle; - m_firstFreeLargeHandle = m_pLargeHandles[freeLargeHandle].GetNextFree(); - m_numLargeHandles++; - if(freeLargeHandle > m_LastLargeHandleIndex) - { - m_LastLargeHandleIndex = freeLargeHandle; - } - return freeLargeHandle; - } - void freeLargeHandle(btSimpleBroadphaseProxy* proxy) - { - int handle = int(proxy - m_pLargeHandles); - btAssert((handle >= 0) && (handle < m_maxHandles)); - if(handle == m_LastLargeHandleIndex) - { - m_LastLargeHandleIndex--; - } - proxy->SetNextFree(m_firstFreeLargeHandle); - m_firstFreeLargeHandle = handle; - proxy->m_clientObject = 0; - m_numLargeHandles--; - } - bool isLargeProxy(const btVector3& aabbMin, const btVector3& aabbMax); - bool isLargeProxy(btBroadphaseProxy* proxy); -// debug - unsigned int m_numPairsAdded; - unsigned int m_numPairsRemoved; - unsigned int m_numOverflows; -// -public: - btGpu3DGridBroadphase(const btVector3& worldAabbMin,const btVector3& worldAabbMax, - int gridSizeX, int gridSizeY, int gridSizeZ, - int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, - int maxBodiesPerCell = 8, - btScalar cellFactorAABB = btScalar(1.0f)); - btGpu3DGridBroadphase( btOverlappingPairCache* overlappingPairCache, - const btVector3& worldAabbMin,const btVector3& worldAabbMax, - int gridSizeX, int gridSizeY, int gridSizeZ, - int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, - int maxBodiesPerCell = 8, - btScalar cellFactorAABB = btScalar(1.0f)); - virtual ~btGpu3DGridBroadphase(); - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - - virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0)); - - - virtual void resetPool(btDispatcher* dispatcher); - -protected: - void _initialize( const btVector3& worldAabbMin,const btVector3& worldAabbMax, - int gridSizeX, int gridSizeY, int gridSizeZ, - int maxSmallProxies, int maxLargeProxies, int maxPairsPerBody, - int maxBodiesPerCell = 8, - btScalar cellFactorAABB = btScalar(1.0f)); - void _finalize(); - void addPairsToCache(btDispatcher* dispatcher); - void addLarge2LargePairsToCache(btDispatcher* dispatcher); - -// overrides for CPU version - virtual void setParameters(bt3DGridBroadphaseParams* hostParams); - virtual void prepareAABB(); - virtual void calcHashAABB(); - virtual void sortHash(); - virtual void findCellStart(); - virtual void findOverlappingPairs(); - virtual void findPairsLarge(); - virtual void computePairCacheChanges(); - virtual void scanOverlappingPairBuff(); - virtual void squeezeOverlappingPairBuff(); -}; - -//---------------------------------------------------------------------------------------- - -#endif //BTGPU3DGRIDBROADPHASE_H - -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h deleted file mode 100644 index e0afb87b..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedCode.h +++ /dev/null @@ -1,430 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org -Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. - -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. -*/ - -//---------------------------------------------------------------------------------------- - -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -// K E R N E L F U N C T I O N S -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- - -// calculate position in uniform grid -BT_GPU___device__ int3 bt3DGrid_calcGridPos(float4 p) -{ - int3 gridPos; - gridPos.x = (int)floor((p.x - BT_GPU_params.m_worldOriginX) / BT_GPU_params.m_cellSizeX); - gridPos.y = (int)floor((p.y - BT_GPU_params.m_worldOriginY) / BT_GPU_params.m_cellSizeY); - gridPos.z = (int)floor((p.z - BT_GPU_params.m_worldOriginZ) / BT_GPU_params.m_cellSizeZ); - return gridPos; -} // bt3DGrid_calcGridPos() - -//---------------------------------------------------------------------------------------- - -// calculate address in grid from position (clamping to edges) -BT_GPU___device__ uint bt3DGrid_calcGridHash(int3 gridPos) -{ - gridPos.x = BT_GPU_max(0, BT_GPU_min(gridPos.x, (int)BT_GPU_params.m_gridSizeX - 1)); - gridPos.y = BT_GPU_max(0, BT_GPU_min(gridPos.y, (int)BT_GPU_params.m_gridSizeY - 1)); - gridPos.z = BT_GPU_max(0, BT_GPU_min(gridPos.z, (int)BT_GPU_params.m_gridSizeZ - 1)); - return BT_GPU___mul24(BT_GPU___mul24(gridPos.z, BT_GPU_params.m_gridSizeY), BT_GPU_params.m_gridSizeX) + BT_GPU___mul24(gridPos.y, BT_GPU_params.m_gridSizeX) + gridPos.x; -} // bt3DGrid_calcGridHash() - -//---------------------------------------------------------------------------------------- - -// calculate grid hash value for each body using its AABB -BT_GPU___global__ void calcHashAABBD(bt3DGrid3F1U* pAABB, uint2* pHash, uint numBodies) -{ - int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; - if(index >= (int)numBodies) - { - return; - } - bt3DGrid3F1U bbMin = pAABB[index*2]; - bt3DGrid3F1U bbMax = pAABB[index*2 + 1]; - float4 pos; - pos.x = (bbMin.fx + bbMax.fx) * 0.5f; - pos.y = (bbMin.fy + bbMax.fy) * 0.5f; - pos.z = (bbMin.fz + bbMax.fz) * 0.5f; - // get address in grid - int3 gridPos = bt3DGrid_calcGridPos(pos); - uint gridHash = bt3DGrid_calcGridHash(gridPos); - // store grid hash and body index - pHash[index] = BT_GPU_make_uint2(gridHash, index); -} // calcHashAABBD() - -//---------------------------------------------------------------------------------------- - -BT_GPU___global__ void findCellStartD(uint2* pHash, uint* cellStart, uint numBodies) -{ - int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; - if(index >= (int)numBodies) - { - return; - } - uint2 sortedData = pHash[index]; - // Load hash data into shared memory so that we can look - // at neighboring body's hash value without loading - // two hash values per thread - BT_GPU___shared__ uint sharedHash[257]; - sharedHash[BT_GPU_threadIdx.x+1] = sortedData.x; - if((index > 0) && (BT_GPU_threadIdx.x == 0)) - { - // first thread in block must load neighbor body hash - volatile uint2 prevData = pHash[index-1]; - sharedHash[0] = prevData.x; - } - BT_GPU___syncthreads(); - if((index == 0) || (sortedData.x != sharedHash[BT_GPU_threadIdx.x])) - { - cellStart[sortedData.x] = index; - } -} // findCellStartD() - -//---------------------------------------------------------------------------------------- - -BT_GPU___device__ uint cudaTestAABBOverlap(bt3DGrid3F1U min0, bt3DGrid3F1U max0, bt3DGrid3F1U min1, bt3DGrid3F1U max1) -{ - return (min0.fx <= max1.fx)&& (min1.fx <= max0.fx) && - (min0.fy <= max1.fy)&& (min1.fy <= max0.fy) && - (min0.fz <= max1.fz)&& (min1.fz <= max0.fz); -} // cudaTestAABBOverlap() - -//---------------------------------------------------------------------------------------- - -BT_GPU___device__ void findPairsInCell( int3 gridPos, - uint index, - uint2* pHash, - uint* pCellStart, - bt3DGrid3F1U* pAABB, - uint* pPairBuff, - uint2* pPairBuffStartCurr, - uint numBodies) -{ - if ( (gridPos.x < 0) || (gridPos.x > (int)BT_GPU_params.m_gridSizeX - 1) - || (gridPos.y < 0) || (gridPos.y > (int)BT_GPU_params.m_gridSizeY - 1) - || (gridPos.z < 0) || (gridPos.z > (int)BT_GPU_params.m_gridSizeZ - 1)) - { - return; - } - uint gridHash = bt3DGrid_calcGridHash(gridPos); - // get start of bucket for this cell - uint bucketStart = pCellStart[gridHash]; - if (bucketStart == 0xffffffff) - { - return; // cell empty - } - // iterate over bodies in this cell - uint2 sortedData = pHash[index]; - uint unsorted_indx = sortedData.y; - bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); - bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); - uint handleIndex = min0.uw; - uint2 start_curr = pPairBuffStartCurr[handleIndex]; - uint start = start_curr.x; - uint curr = start_curr.y; - uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; - uint curr_max = start_curr_next.x - start - 1; - uint bucketEnd = bucketStart + BT_GPU_params.m_maxBodiesPerCell; - bucketEnd = (bucketEnd > numBodies) ? numBodies : bucketEnd; - for(uint index2 = bucketStart; index2 < bucketEnd; index2++) - { - uint2 cellData = pHash[index2]; - if (cellData.x != gridHash) - { - break; // no longer in same bucket - } - uint unsorted_indx2 = cellData.y; - if (unsorted_indx2 < unsorted_indx) // check not colliding with self - { - bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2); - bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, unsorted_indx2*2 + 1); - if(cudaTestAABBOverlap(min0, max0, min1, max1)) - { - uint handleIndex2 = min1.uw; - uint k; - for(k = 0; k < curr; k++) - { - uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); - if(old_pair == handleIndex2) - { - pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; - break; - } - } - if(k == curr) - { - if(curr >= curr_max) - { // not a good solution, but let's avoid crash - break; - } - pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; - curr++; - } - } - } - } - pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); - return; -} // findPairsInCell() - -//---------------------------------------------------------------------------------------- - -BT_GPU___global__ void findOverlappingPairsD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, - uint* pPairBuff, uint2* pPairBuffStartCurr, uint numBodies) -{ - int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; - if(index >= (int)numBodies) - { - return; - } - uint2 sortedData = pHash[index]; - uint unsorted_indx = sortedData.y; - bt3DGrid3F1U bbMin = BT_GPU_FETCH(pAABB, unsorted_indx*2); - bt3DGrid3F1U bbMax = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); - float4 pos; - pos.x = (bbMin.fx + bbMax.fx) * 0.5f; - pos.y = (bbMin.fy + bbMax.fy) * 0.5f; - pos.z = (bbMin.fz + bbMax.fz) * 0.5f; - // get address in grid - int3 gridPos = bt3DGrid_calcGridPos(pos); - // examine only neighbouring cells - for(int z=-1; z<=1; z++) { - for(int y=-1; y<=1; y++) { - for(int x=-1; x<=1; x++) { - findPairsInCell(gridPos + BT_GPU_make_int3(x, y, z), index, pHash, pCellStart, pAABB, pPairBuff, pPairBuffStartCurr, numBodies); - } - } - } -} // findOverlappingPairsD() - -//---------------------------------------------------------------------------------------- - -BT_GPU___global__ void findPairsLargeD( bt3DGrid3F1U* pAABB, uint2* pHash, uint* pCellStart, uint* pPairBuff, - uint2* pPairBuffStartCurr, uint numBodies, uint numLarge) -{ - int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; - if(index >= (int)numBodies) - { - return; - } - uint2 sortedData = pHash[index]; - uint unsorted_indx = sortedData.y; - bt3DGrid3F1U min0 = BT_GPU_FETCH(pAABB, unsorted_indx*2); - bt3DGrid3F1U max0 = BT_GPU_FETCH(pAABB, unsorted_indx*2 + 1); - uint handleIndex = min0.uw; - uint2 start_curr = pPairBuffStartCurr[handleIndex]; - uint start = start_curr.x; - uint curr = start_curr.y; - uint2 start_curr_next = pPairBuffStartCurr[handleIndex+1]; - uint curr_max = start_curr_next.x - start - 1; - for(uint i = 0; i < numLarge; i++) - { - uint indx2 = numBodies + i; - bt3DGrid3F1U min1 = BT_GPU_FETCH(pAABB, indx2*2); - bt3DGrid3F1U max1 = BT_GPU_FETCH(pAABB, indx2*2 + 1); - if(cudaTestAABBOverlap(min0, max0, min1, max1)) - { - uint k; - uint handleIndex2 = min1.uw; - for(k = 0; k < curr; k++) - { - uint old_pair = pPairBuff[start+k] & (~BT_3DGRID_PAIR_ANY_FLG); - if(old_pair == handleIndex2) - { - pPairBuff[start+k] |= BT_3DGRID_PAIR_FOUND_FLG; - break; - } - } - if(k == curr) - { - pPairBuff[start+curr] = handleIndex2 | BT_3DGRID_PAIR_NEW_FLG; - if(curr >= curr_max) - { // not a good solution, but let's avoid crash - break; - } - curr++; - } - } - } - pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, curr); - return; -} // findPairsLargeD() - -//---------------------------------------------------------------------------------------- - -BT_GPU___global__ void computePairCacheChangesD(uint* pPairBuff, uint2* pPairBuffStartCurr, - uint* pPairScan, bt3DGrid3F1U* pAABB, uint numBodies) -{ - int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; - if(index >= (int)numBodies) - { - return; - } - bt3DGrid3F1U bbMin = pAABB[index * 2]; - uint handleIndex = bbMin.uw; - uint2 start_curr = pPairBuffStartCurr[handleIndex]; - uint start = start_curr.x; - uint curr = start_curr.y; - uint *pInp = pPairBuff + start; - uint num_changes = 0; - for(uint k = 0; k < curr; k++, pInp++) - { - if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) - { - num_changes++; - } - } - pPairScan[index+1] = num_changes; -} // computePairCacheChangesD() - -//---------------------------------------------------------------------------------------- - -BT_GPU___global__ void squeezeOverlappingPairBuffD(uint* pPairBuff, uint2* pPairBuffStartCurr, uint* pPairScan, - uint* pPairOut, bt3DGrid3F1U* pAABB, uint numBodies) -{ - int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x; - if(index >= (int)numBodies) - { - return; - } - bt3DGrid3F1U bbMin = pAABB[index * 2]; - uint handleIndex = bbMin.uw; - uint2 start_curr = pPairBuffStartCurr[handleIndex]; - uint start = start_curr.x; - uint curr = start_curr.y; - uint* pInp = pPairBuff + start; - uint* pOut = pPairOut + pPairScan[index]; - uint* pOut2 = pInp; - uint num = 0; - for(uint k = 0; k < curr; k++, pInp++) - { - if(!((*pInp) & BT_3DGRID_PAIR_FOUND_FLG)) - { - *pOut = *pInp; - pOut++; - } - if((*pInp) & BT_3DGRID_PAIR_ANY_FLG) - { - *pOut2 = (*pInp) & (~BT_3DGRID_PAIR_ANY_FLG); - pOut2++; - num++; - } - } - pPairBuffStartCurr[handleIndex] = BT_GPU_make_uint2(start, num); -} // squeezeOverlappingPairBuffD() - - -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -// E N D O F K E R N E L F U N C T I O N S -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------- - -extern "C" -{ - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies) -{ - int numThreads, numBlocks; - BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); - // execute the kernel - BT_GPU_EXECKERNEL(numBlocks, numThreads, calcHashAABBD, (pAABB, (uint2*)hash, numBodies)); - // check if kernel invocation generated an error - BT_GPU_CHECK_ERROR("calcHashAABBD kernel execution failed"); -} // calcHashAABB() - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(findCellStart(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells)) -{ - int numThreads, numBlocks; - BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); - BT_GPU_SAFE_CALL(BT_GPU_Memset(cellStart, 0xffffffff, numCells*sizeof(uint))); - BT_GPU_EXECKERNEL(numBlocks, numThreads, findCellStartD, ((uint2*)hash, (uint*)cellStart, numBodies)); - BT_GPU_CHECK_ERROR("Kernel execution failed: findCellStartD"); -} // findCellStart() - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(findOverlappingPairs(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies)) -{ -#if B_CUDA_USE_TEX - BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, numBodies * 2 * sizeof(bt3DGrid3F1U))); -#endif - int numThreads, numBlocks; - BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); - BT_GPU_EXECKERNEL(numBlocks, numThreads, findOverlappingPairsD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies)); - BT_GPU_CHECK_ERROR("Kernel execution failed: bt_CudaFindOverlappingPairsD"); -#if B_CUDA_USE_TEX - BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); -#endif -} // findOverlappingPairs() - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(findPairsLarge(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge)) -{ -#if B_CUDA_USE_TEX - BT_GPU_SAFE_CALL(cudaBindTexture(0, pAABBTex, pAABB, (numBodies+numLarge) * 2 * sizeof(bt3DGrid3F1U))); -#endif - int numThreads, numBlocks; - BT_GPU_PREF(computeGridSize)(numBodies, 64, numBlocks, numThreads); - BT_GPU_EXECKERNEL(numBlocks, numThreads, findPairsLargeD, (pAABB,(uint2*)pHash,(uint*)pCellStart,(uint*)pPairBuff,(uint2*)pPairBuffStartCurr,numBodies,numLarge)); - BT_GPU_CHECK_ERROR("Kernel execution failed: btCuda_findPairsLargeD"); -#if B_CUDA_USE_TEX - BT_GPU_SAFE_CALL(cudaUnbindTexture(pAABBTex)); -#endif -} // findPairsLarge() - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(computePairCacheChanges(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies)) -{ - int numThreads, numBlocks; - BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); - BT_GPU_EXECKERNEL(numBlocks, numThreads, computePairCacheChangesD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,pAABB,numBodies)); - BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaComputePairCacheChangesD"); -} // computePairCacheChanges() - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(squeezeOverlappingPairBuff(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies)) -{ - int numThreads, numBlocks; - BT_GPU_PREF(computeGridSize)(numBodies, 256, numBlocks, numThreads); - BT_GPU_EXECKERNEL(numBlocks, numThreads, squeezeOverlappingPairBuffD, ((uint*)pPairBuff,(uint2*)pPairBuffStartCurr,(uint*)pPairScan,(uint*)pPairOut,pAABB,numBodies)); - BT_GPU_CHECK_ERROR("Kernel execution failed: btCudaSqueezeOverlappingPairBuffD"); -} // btCuda_squeezeOverlappingPairBuff() - -//------------------------------------------------------------------------------------------------ - -} // extern "C" - -//------------------------------------------------------------------------------------------------ -//------------------------------------------------------------------------------------------------ -//------------------------------------------------------------------------------------------------ diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h deleted file mode 100644 index 607bda7e..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedDefs.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org -Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. - -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. -*/ - -//---------------------------------------------------------------------------------------- - -// Shared definitions for GPU-based 3D Grid collision detection broadphase - -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// Keep this file free from Bullet headers -// it is included into both CUDA and CPU code -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -//---------------------------------------------------------------------------------------- - -#ifndef BTGPU3DGRIDBROADPHASESHAREDDEFS_H -#define BTGPU3DGRIDBROADPHASESHAREDDEFS_H - -//---------------------------------------------------------------------------------------- - -#include "btGpu3DGridBroadphaseSharedTypes.h" - -//---------------------------------------------------------------------------------------- - -extern "C" -{ - -//---------------------------------------------------------------------------------------- - -void BT_GPU_PREF(calcHashAABB)(bt3DGrid3F1U* pAABB, unsigned int* hash, unsigned int numBodies); - -void BT_GPU_PREF(findCellStart)(unsigned int* hash, unsigned int* cellStart, unsigned int numBodies, unsigned int numCells); - -void BT_GPU_PREF(findOverlappingPairs)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies); - -void BT_GPU_PREF(findPairsLarge)(bt3DGrid3F1U* pAABB, unsigned int* pHash, unsigned int* pCellStart, unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int numBodies, unsigned int numLarge); - -void BT_GPU_PREF(computePairCacheChanges)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, bt3DGrid3F1U* pAABB, unsigned int numBodies); - -void BT_GPU_PREF(squeezeOverlappingPairBuff)(unsigned int* pPairBuff, unsigned int* pPairBuffStartCurr, unsigned int* pPairScan, unsigned int* pPairOut, bt3DGrid3F1U* pAABB, unsigned int numBodies); - - -//---------------------------------------------------------------------------------------- - -} // extern "C" - -//---------------------------------------------------------------------------------------- - -#endif // BTGPU3DGRIDBROADPHASESHAREDDEFS_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h deleted file mode 100644 index 616a4009..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpu3DGridBroadphaseSharedTypes.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org -Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. - -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. -*/ - -//---------------------------------------------------------------------------------------- - -// Shared definitions for GPU-based 3D Grid collision detection broadphase - -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// Keep this file free from Bullet headers -// it is included into both CUDA and CPU code -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -//---------------------------------------------------------------------------------------- - -#ifndef BTGPU3DGRIDBROADPHASESHAREDTYPES_H -#define BTGPU3DGRIDBROADPHASESHAREDTYPES_H - -//---------------------------------------------------------------------------------------- - -#define BT_3DGRID_PAIR_FOUND_FLG (0x40000000) -#define BT_3DGRID_PAIR_NEW_FLG (0x20000000) -#define BT_3DGRID_PAIR_ANY_FLG (BT_3DGRID_PAIR_FOUND_FLG | BT_3DGRID_PAIR_NEW_FLG) - -//---------------------------------------------------------------------------------------- - -struct bt3DGridBroadphaseParams -{ - unsigned int m_gridSizeX; - unsigned int m_gridSizeY; - unsigned int m_gridSizeZ; - unsigned int m_numCells; - float m_worldOriginX; - float m_worldOriginY; - float m_worldOriginZ; - float m_cellSizeX; - float m_cellSizeY; - float m_cellSizeZ; - unsigned int m_numBodies; - unsigned int m_maxBodiesPerCell; -}; - -//---------------------------------------------------------------------------------------- - -struct bt3DGrid3F1U -{ - float fx; - float fy; - float fz; - unsigned int uw; -}; - -//---------------------------------------------------------------------------------------- - -#endif // BTGPU3DGRIDBROADPHASESHAREDTYPES_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuDefines.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuDefines.h deleted file mode 100644 index f9315ab6..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btGpuDefines.h +++ /dev/null @@ -1,211 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org -Copyright (C) 2006, 2009 Sony Computer Entertainment Inc. - -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. -*/ - - - -// definitions for "GPU on CPU" code - - -#ifndef BT_GPU_DEFINES_H -#define BT_GPU_DEFINES_H - -typedef unsigned int uint; - -struct int2 -{ - int x, y; -}; - -struct uint2 -{ - unsigned int x, y; -}; - -struct int3 -{ - int x, y, z; -}; - -struct uint3 -{ - unsigned int x, y, z; -}; - -struct float4 -{ - float x, y, z, w; -}; - -struct float3 -{ - float x, y, z; -}; - - -#define BT_GPU___device__ inline -#define BT_GPU___devdata__ -#define BT_GPU___constant__ -#define BT_GPU_max(a, b) ((a) > (b) ? (a) : (b)) -#define BT_GPU_min(a, b) ((a) < (b) ? (a) : (b)) -#define BT_GPU_params s3DGridBroadphaseParams -#define BT_GPU___mul24(a, b) ((a)*(b)) -#define BT_GPU___global__ inline -#define BT_GPU___shared__ static -#define BT_GPU___syncthreads() -#define CUDART_PI_F SIMD_PI - -static inline uint2 bt3dGrid_make_uint2(unsigned int x, unsigned int y) -{ - uint2 t; t.x = x; t.y = y; return t; -} -#define BT_GPU_make_uint2(x, y) bt3dGrid_make_uint2(x, y) - -static inline int3 bt3dGrid_make_int3(int x, int y, int z) -{ - int3 t; t.x = x; t.y = y; t.z = z; return t; -} -#define BT_GPU_make_int3(x, y, z) bt3dGrid_make_int3(x, y, z) - -static inline float3 bt3dGrid_make_float3(float x, float y, float z) -{ - float3 t; t.x = x; t.y = y; t.z = z; return t; -} -#define BT_GPU_make_float3(x, y, z) bt3dGrid_make_float3(x, y, z) - -static inline float3 bt3dGrid_make_float34(float4 f) -{ - float3 t; t.x = f.x; t.y = f.y; t.z = f.z; return t; -} -#define BT_GPU_make_float34(f) bt3dGrid_make_float34(f) - -static inline float3 bt3dGrid_make_float31(float f) -{ - float3 t; t.x = t.y = t.z = f; return t; -} -#define BT_GPU_make_float31(x) bt3dGrid_make_float31(x) - -static inline float4 bt3dGrid_make_float42(float3 v, float f) -{ - float4 t; t.x = v.x; t.y = v.y; t.z = v.z; t.w = f; return t; -} -#define BT_GPU_make_float42(a, b) bt3dGrid_make_float42(a, b) - -static inline float4 bt3dGrid_make_float44(float a, float b, float c, float d) -{ - float4 t; t.x = a; t.y = b; t.z = c; t.w = d; return t; -} -#define BT_GPU_make_float44(a, b, c, d) bt3dGrid_make_float44(a, b, c, d) - -inline int3 operator+(int3 a, int3 b) -{ - return bt3dGrid_make_int3(a.x + b.x, a.y + b.y, a.z + b.z); -} - -inline float4 operator+(const float4& a, const float4& b) -{ - float4 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; r.w = a.w+b.w; return r; -} -inline float4 operator*(const float4& a, float fact) -{ - float4 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; r.w = a.w*fact; return r; -} -inline float4 operator*(float fact, float4& a) -{ - return (a * fact); -} -inline float4& operator*=(float4& a, float fact) -{ - a = fact * a; - return a; -} -inline float4& operator+=(float4& a, const float4& b) -{ - a = a + b; - return a; -} - -inline float3 operator+(const float3& a, const float3& b) -{ - float3 r; r.x = a.x+b.x; r.y = a.y+b.y; r.z = a.z+b.z; return r; -} -inline float3 operator-(const float3& a, const float3& b) -{ - float3 r; r.x = a.x-b.x; r.y = a.y-b.y; r.z = a.z-b.z; return r; -} -static inline float bt3dGrid_dot(float3& a, float3& b) -{ - return a.x*b.x+a.y*b.y+a.z*b.z; -} -#define BT_GPU_dot(a,b) bt3dGrid_dot(a,b) - -static inline float bt3dGrid_dot4(float4& a, float4& b) -{ - return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w; -} -#define BT_GPU_dot4(a,b) bt3dGrid_dot4(a,b) - -static inline float3 bt3dGrid_cross(const float3& a, const float3& b) -{ - float3 r; r.x = a.y*b.z-a.z*b.y; r.y = -a.x*b.z+a.z*b.x; r.z = a.x*b.y-a.y*b.x; return r; -} -#define BT_GPU_cross(a,b) bt3dGrid_cross(a,b) - - -inline float3 operator*(const float3& a, float fact) -{ - float3 r; r.x = a.x*fact; r.y = a.y*fact; r.z = a.z*fact; return r; -} - - -inline float3& operator+=(float3& a, const float3& b) -{ - a = a + b; - return a; -} -inline float3& operator-=(float3& a, const float3& b) -{ - a = a - b; - return a; -} -inline float3& operator*=(float3& a, float fact) -{ - a = a * fact; - return a; -} -inline float3 operator-(const float3& v) -{ - float3 r; r.x = -v.x; r.y = -v.y; r.z = -v.z; return r; -} - - -#define BT_GPU_FETCH(a, b) a[b] -#define BT_GPU_FETCH4(a, b) a[b] -#define BT_GPU_PREF(func) btGpu_##func -#define BT_GPU_SAFE_CALL(func) func -#define BT_GPU_Memset memset -#define BT_GPU_MemcpyToSymbol(a, b, c) memcpy(&a, b, c) -#define BT_GPU_BindTexture(a, b, c, d) -#define BT_GPU_UnbindTexture(a) - -static uint2 s_blockIdx, s_blockDim, s_threadIdx; -#define BT_GPU_blockIdx s_blockIdx -#define BT_GPU_blockDim s_blockDim -#define BT_GPU_threadIdx s_threadIdx -#define BT_GPU_EXECKERNEL(numb, numt, kfunc, args) {s_blockDim.x=numt;for(int nb=0;nb c.m_upperLimit) - { - deltaImpulse = c.m_upperLimit-c.m_appliedImpulse; - c.m_appliedImpulse = c.m_upperLimit; - } - else - { - c.m_appliedImpulse = sum; - } - - - if (body1.mMassInv) - { - btVector3 linearComponent = c.m_contactNormal1*body1.mMassInv; - body1.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse); - btVector3 tmp=c.m_angularComponentA*(btVector3(deltaImpulse,deltaImpulse,deltaImpulse)); - body1.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ()); - } - - if (body2.mMassInv) - { - btVector3 linearComponent = c.m_contactNormal2*body2.mMassInv; - body2.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse); - btVector3 tmp = c.m_angularComponentB*((btVector3(deltaImpulse,deltaImpulse,deltaImpulse)));//*m_angularFactor); - body2.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ()); - } - - //body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); - //body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); - -} - - -static SIMD_FORCE_INLINE -void pfxSolveLinearConstraintRow(btConstraintRow &constraint, - vmVector3 &deltaLinearVelocityA,vmVector3 &deltaAngularVelocityA, - float massInvA,const vmMatrix3 &inertiaInvA,const vmVector3 &rA, - vmVector3 &deltaLinearVelocityB,vmVector3 &deltaAngularVelocityB, - float massInvB,const vmMatrix3 &inertiaInvB,const vmVector3 &rB) -{ - const vmVector3 normal(btReadVector3(constraint.m_normal)); - btScalar deltaImpulse = constraint.m_rhs; - vmVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA); - vmVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB); - deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB); - btScalar oldImpulse = constraint.m_accumImpulse; - constraint.m_accumImpulse = btClamped(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit); - deltaImpulse = constraint.m_accumImpulse - oldImpulse; - deltaLinearVelocityA += deltaImpulse * massInvA * normal; - deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal); - deltaLinearVelocityB -= deltaImpulse * massInvB * normal; - deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal); - -} - -void btSolveContactConstraint( - btConstraintRow &constraintResponse, - btConstraintRow &constraintFriction1, - btConstraintRow &constraintFriction2, - const vmVector3 &contactPointA, - const vmVector3 &contactPointB, - PfxSolverBody &solverBodyA, - PfxSolverBody &solverBodyB, - float friction - ) -{ - vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA); - vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB); - - pfxSolveLinearConstraintRow(constraintResponse, - solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, - solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); - - float mf = friction*fabsf(constraintResponse.m_accumImpulse); - constraintFriction1.m_lowerLimit = -mf; - constraintFriction1.m_upperLimit = mf; - constraintFriction2.m_lowerLimit = -mf; - constraintFriction2.m_upperLimit = mf; - - pfxSolveLinearConstraintRow(constraintFriction1, - solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, - solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); - - pfxSolveLinearConstraintRow(constraintFriction2, - solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA, - solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB); -} - - -void CustomSolveConstraintsTaskParallel( - const PfxParallelGroup *contactParallelGroup,const PfxParallelBatch *contactParallelBatches, - PfxConstraintPair *contactPairs,uint32_t numContactPairs, - btPersistentManifold* offsetContactManifolds, - btConstraintRow* offsetContactConstraintRows, - const PfxParallelGroup *jointParallelGroup,const PfxParallelBatch *jointParallelBatches, - PfxConstraintPair *jointPairs,uint32_t numJointPairs, - btSolverConstraint* offsetSolverConstraints, - TrbState *offsetRigStates, - PfxSolverBody *offsetSolverBodies, - uint32_t numRigidBodies, - int iteration,unsigned int taskId,unsigned int numTasks,btBarrier *barrier) -{ - - PfxSolverBody staticBody; - staticBody.mMassInv = 0.f; - staticBody.mDeltaAngularVelocity=vmVector3(0,0,0); - staticBody.mDeltaLinearVelocity =vmVector3(0,0,0); - - - for(int k=0;knumPhases;phaseId++) { - for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { - uint32_t numPairs = jointParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; - if(batchId%numTasks == taskId && numPairs > 0) { - const PfxParallelBatch &batch = jointParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; - for(uint32_t i=0;isync(); - } - - // Contact - for(uint32_t phaseId=0;phaseIdnumPhases;phaseId++) { - for(uint32_t batchId=0;batchIdnumBatches[phaseId];batchId++) { - uint32_t numPairs = contactParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; - if(batchId%numTasks == taskId && numPairs > 0) { - const PfxParallelBatch &batch = contactParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId]; - for(uint32_t i=0;isync(); - } - } -} - -void CustomPostSolverTask( - TrbState *states, - PfxSolverBody *solverBodies, - uint32_t numRigidBodies) -{ - for(uint32_t i=0;i 0.707f) { - // choose p in y-z plane - float a = n[1]*n[1] + n[2]*n[2]; - float k = 1.0f/sqrtf(a); - p[0] = 0; - p[1] = -n[2]*k; - p[2] = n[1]*k; - // set q = n x p - q[0] = a*k; - q[1] = -n[0]*p[2]; - q[2] = n[0]*p[1]; - } - else { - // choose p in x-y plane - float a = n[0]*n[0] + n[1]*n[1]; - float k = 1.0f/sqrtf(a); - p[0] = -n[1]*k; - p[1] = n[0]*k; - p[2] = 0; - // set q = n x p - q[0] = -n[2]*p[1]; - q[1] = n[2]*p[0]; - q[2] = a*k; - } -} - - - -#define PFX_CONTACT_SLOP 0.001f - -void btSetupContactConstraint( - btConstraintRow &constraintResponse, - btConstraintRow &constraintFriction1, - btConstraintRow &constraintFriction2, - float penetrationDepth, - float restitution, - float friction, - const vmVector3 &contactNormal, - const vmVector3 &contactPointA, - const vmVector3 &contactPointB, - const TrbState &stateA, - const TrbState &stateB, - PfxSolverBody &solverBodyA, - PfxSolverBody &solverBodyB, - const vmVector3& linVelA, - const vmVector3& angVelA, - const vmVector3& linVelB, - const vmVector3& angVelB, - - float separateBias, - float timeStep - ) -{ - vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA); - vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB); - - vmMatrix3 K = vmMatrix3::scale(vmVector3(solverBodyA.mMassInv + solverBodyB.mMassInv)) - - crossMatrix(rA) * solverBodyA.mInertiaInv * crossMatrix(rA) - - crossMatrix(rB) * solverBodyB.mInertiaInv * crossMatrix(rB); - - //use the velocities without the applied (gravity and external) forces for restitution computation - vmVector3 vArestitution = linVelA + cross(angVelA,rA); - vmVector3 vBrestitution = linVelB + cross(angVelB,rB); - vmVector3 vABrestitution = vArestitution-vBrestitution; - - vmVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); - vmVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); - vmVector3 vAB = vA-vB; - - - vmVector3 tangent1,tangent2; - btPlaneSpace1(contactNormal,tangent1,tangent2); - -// constraintResponse.m_accumImpulse = 0.f; -// constraintFriction1.m_accumImpulse = 0.f; -// constraintFriction2.m_accumImpulse = 0.f; - - // Contact Constraint - { - vmVector3 normal = contactNormal; - - float denom = dot(K*normal,normal); - - constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error - constraintResponse.m_rhs -= (separateBias * btMin(0.0f,penetrationDepth+PFX_CONTACT_SLOP)) / timeStep; // position error - constraintResponse.m_rhs /= denom; - constraintResponse.m_jacDiagInv = 1.0f/denom; - constraintResponse.m_lowerLimit = 0.0f; - constraintResponse.m_upperLimit = SIMD_INFINITY; - btStoreVector3(normal,constraintResponse.m_normal); - } - - // Friction Constraint 1 - { - vmVector3 normal = tangent1; - - float denom = dot(K*normal,normal); - - constraintFriction1.m_jacDiagInv = 1.0f/denom; - constraintFriction1.m_rhs = -dot(vAB,normal); - constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv; - constraintFriction1.m_lowerLimit = 0.0f; - constraintFriction1.m_upperLimit = SIMD_INFINITY; - btStoreVector3(normal,constraintFriction1.m_normal); - } - - // Friction Constraint 2 - { - vmVector3 normal = tangent2; - - float denom = dot(K*normal,normal); - - constraintFriction2.m_jacDiagInv = 1.0f/denom; - constraintFriction2.m_rhs = -dot(vAB,normal); - constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv; - constraintFriction2.m_lowerLimit = 0.0f; - constraintFriction2.m_upperLimit = SIMD_INFINITY; - btStoreVector3(normal,constraintFriction2.m_normal); - } -} - - -void CustomSetupContactConstraintsTask( - PfxConstraintPair *contactPairs,uint32_t numContactPairs, - btPersistentManifold* offsetContactManifolds, - btConstraintRow* offsetContactConstraintRows, - TrbState *offsetRigStates, - PfxSolverBody *offsetSolverBodies, - uint32_t numRigidBodies, - float separateBias, - float timeStep) -{ - for(uint32_t i=0;i 1) restitution = 0.0f; - - float friction = sqrtf(solverBodyA.friction * solverBodyB.friction); - - for(int j=0;jgetInvMass()>0.f)) - { - linVelA = rbA->getLinearVelocity(); - angVelA = rbA->getAngularVelocity(); - } else - { - linVelA.setValue(0,0,0); - angVelA.setValue(0,0,0); - } - - if (rbB && (rbB->getInvMass()>0.f)) - { - linVelB = rbB->getLinearVelocity(); - angVelB = rbB->getAngularVelocity(); - } else - { - linVelB.setValue(0,0,0); - angVelB.setValue(0,0,0); - } - - - - btSetupContactConstraint( - contactConstraintRows[j*3], - contactConstraintRows[j*3+1], - contactConstraintRows[j*3+2], - cp.getDistance(), - restitution, - friction, - btReadVector3(cp.m_normalWorldOnB),//.mConstraintRow[0].m_normal), - btReadVector3(cp.m_localPointA), - btReadVector3(cp.m_localPointB), - stateA, - stateB, - solverBodyA, - solverBodyB, - (const vmVector3&)linVelA, (const vmVector3&)angVelA, - (const vmVector3&)linVelB, (const vmVector3&)angVelB, - separateBias, - timeStep - ); - } - - //contact.setCompositeFriction(friction); - } -} - - -void CustomWritebackContactConstraintsTask( - PfxConstraintPair *contactPairs,uint32_t numContactPairs, - btPersistentManifold* offsetContactManifolds, - btConstraintRow* offsetContactConstraintRows, - TrbState *offsetRigStates, - PfxSolverBody *offsetSolverBodies, - uint32_t numRigidBodies, - float separateBias, - float timeStep) -{ - for(uint32_t i=0;iio); - btCriticalSection* criticalsection = io->setupContactConstraints.criticalSection; - - - //CustomCriticalSection *criticalsection = &io->m_cs; - switch(io->cmd) { - - case PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS: - CustomSolveConstraintsTaskParallel( - io->solveConstraints.contactParallelGroup, - io->solveConstraints.contactParallelBatches, - io->solveConstraints.contactPairs, - io->solveConstraints.numContactPairs, - io->solveConstraints.offsetContactManifolds, - io->solveConstraints.offsetContactConstraintRows, - - io->solveConstraints.jointParallelGroup, - io->solveConstraints.jointParallelBatches, - io->solveConstraints.jointPairs, - io->solveConstraints.numJointPairs, - io->solveConstraints.offsetSolverConstraints, - io->solveConstraints.offsetRigStates1, - io->solveConstraints.offsetSolverBodies, - io->solveConstraints.numRigidBodies, - io->solveConstraints.iteration, - - io->solveConstraints.taskId, - io->maxTasks1, - io->solveConstraints.barrier - ); - break; - - case PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER: - CustomPostSolverTask( io->postSolver.states,io->postSolver.solverBodies, io->postSolver.numRigidBodies); - break; - - - case PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS: - { - bool empty = false; - while(!empty) { - int start,batch; - - criticalsection->lock(); - - start = (int)criticalsection->getSharedParam(0); - batch = (int)criticalsection->getSharedParam(1); - - //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch); - - // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg - int nextStart = start + batch; - int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0); - int nextBatch = (rest > batch)?batch:rest; - - criticalsection->setSharedParam(0,nextStart); - criticalsection->setSharedParam(1,nextBatch); - - criticalsection->unlock(); - - if(batch > 0) { - CustomSetupContactConstraintsTask( - io->setupContactConstraints.offsetContactPairs+start,batch, - io->setupContactConstraints.offsetContactManifolds, - io->setupContactConstraints.offsetContactConstraintRows, - io->setupContactConstraints.offsetRigStates, -// io->setupContactConstraints.offsetRigBodies, - io->setupContactConstraints.offsetSolverBodies, - io->setupContactConstraints.numRigidBodies, - io->setupContactConstraints.separateBias, - io->setupContactConstraints.timeStep); - } - else { - empty = true; - } - } - } - break; - - case PFX_CONSTRAINT_SOLVER_CMD_WRITEBACK_APPLIED_IMPULSES_CONTACT_CONSTRAINTS: - { - bool empty = false; - while(!empty) { - int start,batch; - - criticalsection->lock(); - - start = (int)criticalsection->getSharedParam(0); - batch = (int)criticalsection->getSharedParam(1); - - //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch); - - // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg - int nextStart = start + batch; - int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0); - int nextBatch = (rest > batch)?batch:rest; - - criticalsection->setSharedParam(0,nextStart); - criticalsection->setSharedParam(1,nextBatch); - - criticalsection->unlock(); - - if(batch > 0) { - CustomWritebackContactConstraintsTask( - io->setupContactConstraints.offsetContactPairs+start,batch, - io->setupContactConstraints.offsetContactManifolds, - io->setupContactConstraints.offsetContactConstraintRows, - io->setupContactConstraints.offsetRigStates, -// io->setupContactConstraints.offsetRigBodies, - io->setupContactConstraints.offsetSolverBodies, - io->setupContactConstraints.numRigidBodies, - io->setupContactConstraints.separateBias, - io->setupContactConstraints.timeStep); - } - else { - empty = true; - } - } - } - break; - - default: - { - btAssert(0); - } - } - -} - - -void CustomSetupContactConstraintsNew( - PfxConstraintPair *contactPairs1,uint32_t numContactPairs, - btPersistentManifold *offsetContactManifolds, - btConstraintRow* offsetContactConstraintRows, - TrbState *offsetRigStates, - PfxSolverBody *offsetSolverBodies, - uint32_t numRigidBodies, - float separationBias, - float timeStep, - class btThreadSupportInterface* threadSupport, - btCriticalSection* criticalSection, - btConstraintSolverIO *io , - uint8_t cmd - ) -{ - int maxTasks = threadSupport->getNumTasks(); - - int div = (int)maxTasks * 4; - int batch = ((int)numContactPairs + div - 1) / div; -#ifdef __PPU__ - BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; -#endif - if (criticalSection) - { - criticalSection->setSharedParam(0,0); - criticalSection->setSharedParam(1,btMin(batch,64)); // batched number - } else - { -#ifdef __PPU__ - spursThread->setSharedParam(0,0); - spursThread->setSharedParam(1,btMin(batch,64)); // batched number -#endif //__PPU__ - } - - for(int t=0;tgetBarrierAddress(); - io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); -#endif - - -//#define SEQUENTIAL_SETUP -#ifdef SEQUENTIAL_SETUP - CustomSetupContactConstraintsTask(contactPairs1,numContactPairs,offsetContactManifolds,offsetRigStates,offsetSolverBodies,numRigidBodies,separationBias,timeStep); -#else - threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); -#endif - - } -#ifndef SEQUENTIAL_SETUP - unsigned int arg0,arg1; - for(int t=0;twaitForResponse(&arg0,&arg1); - } -#endif //SEQUENTIAL_SETUP - -} - - -void CustomSplitConstraints( - PfxConstraintPair *pairs,uint32_t numPairs, - PfxParallelGroup &group,PfxParallelBatch *batches, - uint32_t numTasks, - uint32_t numRigidBodies, - void *poolBuff, - uint32_t poolBytes - ) -{ - HeapManager pool((unsigned char*)poolBuff,poolBytes); - - // ƒXƒe[ƒgƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ - int bufSize = sizeof(uint8_t)*numRigidBodies; - bufSize = ((bufSize+127)>>7)<<7; // 128 bytes alignment - uint8_t *bodyTable = (uint8_t*)pool.allocate(bufSize,HeapManager::ALIGN128); - - // ƒyƒAƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹ - uint32_t *pairTable; - size_t allocSize = sizeof(uint32_t)*((numPairs+31)/32); - pairTable = (uint32_t*)pool.allocate(allocSize); - memset(pairTable,0,allocSize); - - // –Ú•W‚Æ‚·‚镪Š„” - uint32_t targetCount = btMax(uint32_t(PFX_MIN_SOLVER_PAIRS),btMin(numPairs / (numTasks*2),uint32_t(PFX_MAX_SOLVER_PAIRS))); - uint32_t startIndex = 0; - - uint32_t phaseId; - uint32_t batchId; - uint32_t totalCount=0; - - uint32_t maxBatches = btMin(numTasks,uint32_t(PFX_MAX_SOLVER_BATCHES)); - - for(phaseId=0;phaseId>5; - uint32_t maskP = 1L << (i & 31); - - //pair is already assigned to a phase/batch - if(pairTable[idxP] & maskP) { - continue; - } - - uint32_t idxA = pfxGetRigidBodyIdA(pairs[i]); - uint32_t idxB = pfxGetRigidBodyIdB(pairs[i]); - - // —¼•û‚Æ‚àƒAƒNƒeƒBƒu‚Å‚È‚¢A‚Ü‚½‚ÍÕ“Ë“_‚ª‚O‚̃yƒA‚Í“o˜^‘ÎÛ‚©‚ç‚Í‚¸‚· - if(!pfxGetActive(pairs[i]) || pfxGetNumConstraints(pairs[i]) == 0 || - ((pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_STATIC)) ) { - if(startIndexCheck) - startIndex++; - //assign pair -> skip it because it has no constraints - pairTable[idxP] |= maskP; - totalCount++; - continue; - } - - // ˆË‘¶«‚̃`ƒFƒbƒN - if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) || - (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) { - startIndexCheck = false; - //bodies of the pair are already assigned to another batch within this phase - continue; - } - - // ˆË‘¶«”»’èƒe[ƒuƒ‹‚É“o˜^ - if(pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_DYNAMIC) - bodyTable[idxA] = batchId; - if(pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_DYNAMIC) - bodyTable[idxB] = batchId; - - if(startIndexCheck) - startIndex++; - - pairTable[idxP] |= maskP; - //add the pair 'i' to the current batch - batch.pairIndices[pairId++] = i; - pairCount++; - } - - group.numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId] = (uint16_t)pairId; - totalCount += pairCount; - } - - group.numBatches[phaseId] = batchId; - } - - group.numPhases = phaseId; - - pool.clear(); -} - - - -void CustomSolveConstraintsParallel( - PfxConstraintPair *contactPairs,uint32_t numContactPairs, - - PfxConstraintPair *jointPairs,uint32_t numJointPairs, - btPersistentManifold* offsetContactManifolds, - btConstraintRow* offsetContactConstraintRows, - btSolverConstraint* offsetSolverConstraints, - TrbState *offsetRigStates, - PfxSolverBody *offsetSolverBodies, - uint32_t numRigidBodies, - struct btConstraintSolverIO* io, - class btThreadSupportInterface* threadSupport, - int iteration, - void* poolBuf, - int poolBytes, - class btBarrier* barrier) - { - - int maxTasks = threadSupport->getNumTasks(); -// config.taskManager->setTaskEntry(PFX_SOLVER_ENTRY); - - HeapManager pool((unsigned char*)poolBuf,poolBytes); - - { - PfxParallelGroup *cgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); - PfxParallelBatch *cbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128); - PfxParallelGroup *jgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup)); - PfxParallelBatch *jbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128); - - uint32_t tmpBytes = poolBytes - 2 * (sizeof(PfxParallelGroup) + sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES) + 128); - void *tmpBuff = pool.allocate(tmpBytes); - - { - BT_PROFILE("CustomSplitConstraints"); - CustomSplitConstraints(contactPairs,numContactPairs,*cgroup,cbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); - CustomSplitConstraints(jointPairs,numJointPairs,*jgroup,jbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes); - } - - { - BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS"); -//#define SOLVE_SEQUENTIAL -#ifdef SOLVE_SEQUENTIAL - CustomSolveConstraintsTask( - io->solveConstraints.contactParallelGroup, - io->solveConstraints.contactParallelBatches, - io->solveConstraints.contactPairs, - io->solveConstraints.numContactPairs, - io->solveConstraints.offsetContactManifolds, - - io->solveConstraints.jointParallelGroup, - io->solveConstraints.jointParallelBatches, - io->solveConstraints.jointPairs, - io->solveConstraints.numJointPairs, - io->solveConstraints.offsetSolverConstraints, - - io->solveConstraints.offsetRigStates1, - io->solveConstraints.offsetSolverBodies, - io->solveConstraints.numRigidBodies, - io->solveConstraints.iteration,0,1,0);//arg->taskId,1,0);//,arg->maxTasks,arg->barrier); -#else - for(int t=0;tgetBarrierAddress(); - io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); -#endif - - threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); - } - - unsigned int arg0,arg1; - for(int t=0;twaitForResponse(&arg0,&arg1); - } -#endif - } - pool.clear(); - } - - { - BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER"); - int batch = ((int)numRigidBodies + maxTasks - 1) / maxTasks; - int rest = (int)numRigidBodies; - int start = 0; - - for(int t=0;t 0 ? batch : rest; - io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER; - io[t].postSolver.states = offsetRigStates + start; - io[t].postSolver.solverBodies = offsetSolverBodies + start; - io[t].postSolver.numRigidBodies = (uint32_t)num; - io[t].maxTasks1 = maxTasks; -#ifdef __PPU__ - BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport; - io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress(); - io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress(); -#endif - -#ifdef SOLVE_SEQUENTIAL - CustomPostSolverTask( io[t].postSolver.states,io[t].postSolver.solverBodies, io[t].postSolver.numRigidBodies); -#else - threadSupport->sendRequest(1,(ppu_address_t)&io[t],t); -#endif - rest -= num; - start += num; - } - - unsigned int arg0,arg1; - for(int t=0;twaitForResponse(&arg0,&arg1); -#endif - } - } - -} - - - -void BPE_customConstraintSolverSequentialNew(unsigned int new_num, PfxBroadphasePair *new_pairs1 , - btPersistentManifold* offsetContactManifolds, - PfxConstraintRow* offsetContactConstraintRows, - TrbState* states,int numRigidBodies, - struct PfxSolverBody* solverBodies, - PfxConstraintPair* jointPairs, unsigned int numJoints, - btSolverConstraint* offsetSolverConstraints, - float separateBias, - float timeStep, - int iteration, - btThreadSupportInterface* solverThreadSupport, - btCriticalSection* criticalSection, - struct btConstraintSolverIO* solverIO, - btBarrier* barrier - ) -{ - - { - BT_PROFILE("pfxSetupConstraints"); - - for(uint32_t i=0;i m_mystates; - btAlignedObjectArray m_mysolverbodies; - btAlignedObjectArray m_mypairs; - btAlignedObjectArray m_jointPairs; - btAlignedObjectArray m_constraintRows; - -}; - - -btConstraintSolverIO* createSolverIO(int numThreads) -{ - return new btConstraintSolverIO[numThreads]; -} - -btParallelConstraintSolver::btParallelConstraintSolver(btThreadSupportInterface* solverThreadSupport) -{ - - m_solverThreadSupport = solverThreadSupport;//createSolverThreadSupport(maxNumThreads); - m_solverIO = createSolverIO(m_solverThreadSupport->getNumTasks()); - - m_barrier = m_solverThreadSupport->createBarrier(); - m_criticalSection = m_solverThreadSupport->createCriticalSection(); - - m_memoryCache = new btParallelSolverMemoryCache(); -} - -btParallelConstraintSolver::~btParallelConstraintSolver() -{ - delete m_memoryCache; - delete m_solverIO; - m_solverThreadSupport->deleteBarrier(m_barrier); - m_solverThreadSupport->deleteCriticalSection(m_criticalSection); -} - - - -btScalar btParallelConstraintSolver::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer,btDispatcher* dispatcher) -{ - -/* int sz = sizeof(PfxSolverBody); - int sz2 = sizeof(vmVector3); - int sz3 = sizeof(vmMatrix3); - int sz4 = sizeof(vmQuat); - int sz5 = sizeof(btConstraintRow); - int sz6 = sizeof(btSolverConstraint); - int sz7 = sizeof(TrbState); -*/ - - btPersistentManifold* offsetContactManifolds= (btPersistentManifold*) dispatcher->getInternalManifoldPool()->getPoolAddress(); - - - m_memoryCache->m_mysolverbodies.resize(numRigidBodies); - m_memoryCache->m_mystates.resize(numRigidBodies); - - { - BT_PROFILE("create states and solver bodies"); - for (int i=0;isetCompanionId(i); - - PfxSolverBody& solverBody = m_memoryCache->m_mysolverbodies[i]; - btRigidBody* rb = btRigidBody::upcast(obj); - TrbState& state = m_memoryCache->m_mystates[i]; - - state.reset(); - const btQuaternion& orgOri = obj->getWorldTransform().getRotation(); - vmQuat orn(orgOri.getX(),orgOri.getY(),orgOri.getZ(),orgOri.getW()); - state.setPosition(getVmVector3(obj->getWorldTransform().getOrigin())); - state.setOrientation(orn); - state.setPosition(state.getPosition()); - state.setRigidBodyId(i); - state.setAngularDamping(0); - state.setLinearDamping(0); - - - solverBody.mOrientation = state.getOrientation(); - solverBody.mDeltaLinearVelocity = vmVector3(0.0f); - solverBody.mDeltaAngularVelocity = vmVector3(0.0f); - solverBody.friction = obj->getFriction(); - solverBody.restitution = obj->getRestitution(); - - state.resetSleepCount(); - - //if(state.getMotionMask()&PFX_MOTION_MASK_DYNAMIC) { - if (rb && (rb->getInvMass()>0.f)) - { - btVector3 angVelPlusForces = rb->getAngularVelocity()+rb->getTotalTorque()*rb->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; - btVector3 linVelPlusForces = rb->getLinearVelocity()+rb->getTotalForce()*rb->getInvMass()*infoGlobal.m_timeStep; - - state.setAngularVelocity(btReadVector3(angVelPlusForces)); - state.setLinearVelocity(btReadVector3(linVelPlusForces)); - - state.setMotionType(PfxMotionTypeActive); - vmMatrix3 ori(solverBody.mOrientation); - vmMatrix3 localInvInertia = vmMatrix3::identity(); - localInvInertia.setCol(0,vmVector3(rb->getInvInertiaDiagLocal().getX(),0,0)); - localInvInertia.setCol(1,vmVector3(0, rb->getInvInertiaDiagLocal().getY(),0)); - localInvInertia.setCol(2,vmVector3(0,0, rb->getInvInertiaDiagLocal().getZ())); - - solverBody.mMassInv = rb->getInvMass(); - solverBody.mInertiaInv = ori * localInvInertia * transpose(ori); - } else - { - state.setAngularVelocity(vmVector3(0)); - state.setLinearVelocity(vmVector3(0)); - - state.setMotionType(PfxMotionTypeFixed); - m_memoryCache->m_mysolverbodies[i].mMassInv = 0.f; - m_memoryCache->m_mysolverbodies[i].mInertiaInv = vmMatrix3(0.0f); - } - - } - } - - - - int totalPoints = 0; -#ifndef USE_C_ARRAYS - m_memoryCache->m_mypairs.resize(numManifolds); - //4 points per manifold and 3 rows per point makes 12 rows per manifold - m_memoryCache->m_constraintRows.resize(numManifolds*12); - m_memoryCache->m_jointPairs.resize(numConstraints); -#endif//USE_C_ARRAYS - - int actualNumManifolds= 0; - { - BT_PROFILE("convert manifolds"); - for (int i1=0;i1getNumContacts()>0) - { - btPersistentManifold* m = manifoldPtr[i1]; - btCollisionObject* obA = (btCollisionObject*)m->getBody0(); - btCollisionObject* obB = (btCollisionObject*)m->getBody1(); - bool obAisActive = !obA->isStaticOrKinematicObject() && obA->isActive(); - bool obBisActive = !obB->isStaticOrKinematicObject() && obB->isActive(); - - if (!obAisActive && !obBisActive) - continue; - - - //int contactId = i1;//actualNumManifolds; - - PfxBroadphasePair& pair = m_memoryCache->m_mypairs[actualNumManifolds]; - //init those - // float compFric = obA->getFriction()*obB->getFriction();//@todo - int idA = obA->getCompanionId(); - int idB = obB->getCompanionId(); - - m->m_companionIdA = idA; - m->m_companionIdB = idB; - - - // if ((mysolverbodies[idA].mMassInv!=0)&&(mysolverbodies[idB].mMassInv!=0)) - // continue; - int numPosPoints=0; - for (int p=0;pgetNumContacts();p++) - { - //btManifoldPoint& pt = m->getContactPoint(p); - //float dist = pt.getDistance(); - //if (dist<0.001) - numPosPoints++; - } - - - totalPoints+=numPosPoints; - pfxSetRigidBodyIdA(pair,idA); - pfxSetRigidBodyIdB(pair,idB); - pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); - pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); - pfxSetActive(pair,numPosPoints>0); - - pfxSetBroadphaseFlag(pair,0); - int contactId = m-offsetContactManifolds; - //likely the contact pool is not contiguous, make sure to allocate large enough contact pool - btAssert(contactId>=0); - btAssert(contactIdgetInternalManifoldPool()->getMaxCount()); - - pfxSetContactId(pair,contactId); - pfxSetNumConstraints(pair,numPosPoints);//manifoldPtr[i]->getNumContacts()); - actualNumManifolds++; - } - - } - } - - PfxConstraintPair* jointPairs=0; - jointPairs = numConstraints? &m_memoryCache->m_jointPairs[0]:0; - int actualNumJoints=0; - - - btSolverConstraint* offsetSolverConstraints = 0; - - //if (1) - { - - { - BT_PROFILE("convert constraints"); - - int totalNumRows = 0; - int i; - - m_tmpConstraintSizesPool.resize(numConstraints); - //calculate the total number of contraint rows - for (i=0;igetInfo1(&info1); - totalNumRows += info1.m_numConstraintRows; - } - m_tmpSolverNonContactConstraintPool.resize(totalNumRows); - offsetSolverConstraints =totalNumRows? &m_tmpSolverNonContactConstraintPool[0]:0; - - - ///setup the btSolverConstraints - int currentRow = 0; - - for (i=0;igetRigidBodyA(); - btRigidBody& rbB = constraint->getRigidBodyB(); - - int idA = constraint->getRigidBodyA().getCompanionId(); - int idB = constraint->getRigidBodyB().getCompanionId(); - - - int j; - for ( j=0;jm_contactNormal1; - info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; - info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2; - info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; - info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this - ///the size of btSolverConstraint needs be a multiple of btScalar - btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); - info2.m_constraintError = ¤tConstraintRow->m_rhs; - currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; - info2.cfm = ¤tConstraintRow->m_cfm; - info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit; - info2.m_upperLimit = ¤tConstraintRow->m_upperLimit; - info2.m_numIterations = infoGlobal.m_numIterations; - constraints[i]->getInfo2(&info2); - - - - - ///finalize the constraint setup - for ( j=0;jgetRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); - } - { - const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; - solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); - } - - { - btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass(); - btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; - btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal? - btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; - - btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1); - sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); - sum += iMJlB.dot(solverConstraint.m_contactNormal2); - sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); - - solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; - } - - - ///fix rhs - ///todo: add force/torque accelerators - { - btScalar rel_vel; - btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()); - btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()); - - rel_vel = vel1Dotn+vel2Dotn; - - btScalar restitution = 0.f; - btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 - btScalar velocityError = restitution - rel_vel;// * damping; - btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; - solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; - solverConstraint.m_appliedImpulse = 0.f; - - } - } - - PfxConstraintPair& pair = jointPairs[actualNumJoints]; - - int numConstraintRows= info1.m_numConstraintRows; - pfxSetNumConstraints(pair,numConstraintRows); - - - - pfxSetRigidBodyIdA(pair,idA); - pfxSetRigidBodyIdB(pair,idB); - //is this needed? - if (idA>=0) - pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask()); - if (idB>=0) - pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask()); - - pfxSetActive(pair,true); - int id = currentConstraintRow-offsetSolverConstraints; - pfxSetContactId(pair,id); - actualNumJoints++; - - - } - currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows; - } - } - } - - - - float separateBias=0.1;//info.m_erp;//or m_erp2? - float timeStep=infoGlobal.m_timeStep; - int iteration=infoGlobal.m_numIterations; - - //create a pair for each constraints, copy over info etc - - - - - - { - BT_PROFILE("compute num contacts"); - int totalContacts =0; - - for (int i=0;im_mypairs[i]; - totalContacts += pfxGetNumConstraints(*pair); - } - //printf("numManifolds = %d\n",numManifolds); - //printf("totalContacts=%d\n",totalContacts); - } - - - -// printf("actualNumManifolds=%d\n",actualNumManifolds); - { - BT_PROFILE("BPE_customConstraintSolverSequentialNew"); - if (numRigidBodies>0 && (actualNumManifolds+actualNumJoints)>0) - { -// PFX_PRINTF("num points = %d\n",totalPoints); -// PFX_PRINTF("num points PFX = %d\n",total); - - - PfxConstraintRow* contactRows = actualNumManifolds? &m_memoryCache->m_constraintRows[0] : 0; - PfxBroadphasePair* actualPairs = m_memoryCache->m_mypairs.size() ? &m_memoryCache->m_mypairs[0] : 0; - BPE_customConstraintSolverSequentialNew( - actualNumManifolds, - actualPairs, - offsetContactManifolds, - contactRows, - &m_memoryCache->m_mystates[0],numRigidBodies, - &m_memoryCache->m_mysolverbodies[0], - jointPairs,actualNumJoints, - offsetSolverConstraints, - separateBias,timeStep,iteration, - m_solverThreadSupport,m_criticalSection,m_solverIO,m_barrier); - } - } - - //copy results back to bodies - { - BT_PROFILE("copy back"); - for (int i=0;im_mystates[i]; - if (rb && (rb->getInvMass()>0.f)) - { - rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ())); - rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ())); - } - } - } - - - return 0.f; -} diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.h deleted file mode 100644 index b5b475a1..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btParallelConstraintSolver.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - Copyright (C) 2010 Sony Computer Entertainment Inc. - All rights reserved. - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - -#ifndef __BT_PARALLEL_CONSTRAINT_SOLVER_H -#define __BT_PARALLEL_CONSTRAINT_SOLVER_H - -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" - - - - -#include "LinearMath/btScalar.h" -#include "PlatformDefinitions.h" - - -#define PFX_MAX_SOLVER_PHASES 64 -#define PFX_MAX_SOLVER_BATCHES 16 -#define PFX_MAX_SOLVER_PAIRS 128 -#define PFX_MIN_SOLVER_PAIRS 16 - -#ifdef __CELLOS_LV2__ -ATTRIBUTE_ALIGNED128(struct) PfxParallelBatch { -#else -ATTRIBUTE_ALIGNED16(struct) PfxParallelBatch { -#endif - uint16_t pairIndices[PFX_MAX_SOLVER_PAIRS]; -}; - -#ifdef __CELLOS_LV2__ -ATTRIBUTE_ALIGNED128(struct) PfxParallelGroup { -#else -ATTRIBUTE_ALIGNED16(struct) PfxParallelGroup { -#endif - uint16_t numPhases; - uint16_t numBatches[PFX_MAX_SOLVER_PHASES]; - uint16_t numPairs[PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES]; -}; - - - -ATTRIBUTE_ALIGNED16(struct) PfxSortData16 { - union { - uint8_t i8data[16]; - uint16_t i16data[8]; - uint32_t i32data[4]; -#ifdef __SPU__ - vec_uint4 vdata; -#endif - }; - -#ifdef __SPU__ - void set8(int elem,uint8_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uchar16)vdata,elem);} - void set16(int elem,uint16_t data) {vdata=(vec_uint4)spu_insert(data,(vec_ushort8)vdata,elem);} - void set32(int elem,uint32_t data) {vdata=(vec_uint4)spu_insert(data,(vec_uint4)vdata,elem);} - uint8_t get8(int elem) const {return spu_extract((vec_uchar16)vdata,elem);} - uint16_t get16(int elem) const {return spu_extract((vec_ushort8)vdata,elem);} - uint32_t get32(int elem) const {return spu_extract((vec_uint4)vdata,elem);} -#else - void set8(int elem,uint8_t data) {i8data[elem] = data;} - void set16(int elem,uint16_t data) {i16data[elem] = data;} - void set32(int elem,uint32_t data) {i32data[elem] = data;} - uint8_t get8(int elem) const {return i8data[elem];} - uint16_t get16(int elem) const {return i16data[elem];} - uint32_t get32(int elem) const {return i32data[elem];} -#endif -}; - -typedef PfxSortData16 PfxConstraintPair; - - -//J PfxBroadphasePair‚Æ‹¤’Ê - -SIMD_FORCE_INLINE void pfxSetConstraintId(PfxConstraintPair &pair,uint32_t i) {pair.set32(2,i);} -SIMD_FORCE_INLINE void pfxSetNumConstraints(PfxConstraintPair &pair,uint8_t n) {pair.set8(7,n);} - -SIMD_FORCE_INLINE uint32_t pfxGetConstraintId1(const PfxConstraintPair &pair) {return pair.get32(2);} -SIMD_FORCE_INLINE uint8_t pfxGetNumConstraints(const PfxConstraintPair &pair) {return pair.get8(7);} - -typedef PfxSortData16 PfxBroadphasePair; - -SIMD_FORCE_INLINE void pfxSetRigidBodyIdA(PfxBroadphasePair &pair,uint16_t i) {pair.set16(0,i);} -SIMD_FORCE_INLINE void pfxSetRigidBodyIdB(PfxBroadphasePair &pair,uint16_t i) {pair.set16(1,i);} -SIMD_FORCE_INLINE void pfxSetMotionMaskA(PfxBroadphasePair &pair,uint8_t i) {pair.set8(4,i);} -SIMD_FORCE_INLINE void pfxSetMotionMaskB(PfxBroadphasePair &pair,uint8_t i) {pair.set8(5,i);} -SIMD_FORCE_INLINE void pfxSetBroadphaseFlag(PfxBroadphasePair &pair,uint8_t f) {pair.set8(6,(pair.get8(6)&0xf0)|(f&0x0f));} -SIMD_FORCE_INLINE void pfxSetActive(PfxBroadphasePair &pair,bool b) {pair.set8(6,(pair.get8(6)&0x0f)|((b?1:0)<<4));} -SIMD_FORCE_INLINE void pfxSetContactId(PfxBroadphasePair &pair,uint32_t i) {pair.set32(2,i);} - -SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdA(const PfxBroadphasePair &pair) {return pair.get16(0);} -SIMD_FORCE_INLINE uint16_t pfxGetRigidBodyIdB(const PfxBroadphasePair &pair) {return pair.get16(1);} -SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskA(const PfxBroadphasePair &pair) {return pair.get8(4);} -SIMD_FORCE_INLINE uint8_t pfxGetMotionMaskB(const PfxBroadphasePair &pair) {return pair.get8(5);} -SIMD_FORCE_INLINE uint8_t pfxGetBroadphaseFlag(const PfxBroadphasePair &pair) {return pair.get8(6)&0x0f;} -SIMD_FORCE_INLINE bool pfxGetActive(const PfxBroadphasePair &pair) {return (pair.get8(6)>>4)!=0;} -SIMD_FORCE_INLINE uint32_t pfxGetContactId1(const PfxBroadphasePair &pair) {return pair.get32(2);} - - - -#if defined(__PPU__) || defined (__SPU__) -ATTRIBUTE_ALIGNED128(struct) PfxSolverBody { -#else -ATTRIBUTE_ALIGNED16(struct) PfxSolverBody { -#endif - vmVector3 mDeltaLinearVelocity; - vmVector3 mDeltaAngularVelocity; - vmMatrix3 mInertiaInv; - vmQuat mOrientation; - float mMassInv; - float friction; - float restitution; - float unused; - float unused2; - float unused3; - float unused4; - float unused5; -}; - - -#ifdef __PPU__ -#include "SpuDispatch/BulletPE2ConstraintSolverSpursSupport.h" -#endif - -static SIMD_FORCE_INLINE vmVector3 btReadVector3(const double* p) -{ - float tmp[3] = {float(p[0]),float(p[1]),float(p[2])}; - vmVector3 v; - loadXYZ(v, tmp); - return v; -} - -static SIMD_FORCE_INLINE vmQuat btReadQuat(const double* p) -{ - float tmp[4] = {float(p[0]),float(p[1]),float(p[2]),float(p[4])}; - vmQuat vq; - loadXYZW(vq, tmp); - return vq; -} - -static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, double* p) -{ - float tmp[3]; - vmVector3 v = src; - storeXYZ(v, tmp); - p[0] = tmp[0]; - p[1] = tmp[1]; - p[2] = tmp[2]; -} - - -static SIMD_FORCE_INLINE vmVector3 btReadVector3(const float* p) -{ - vmVector3 v; - loadXYZ(v, p); - return v; -} - -static SIMD_FORCE_INLINE vmQuat btReadQuat(const float* p) -{ - vmQuat vq; - loadXYZW(vq, p); - return vq; -} - -static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, float* p) -{ - vmVector3 v = src; - storeXYZ(v, p); -} - - - - -class btPersistentManifold; - -enum { - PFX_CONSTRAINT_SOLVER_CMD_SETUP_SOLVER_BODIES, - PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS, - PFX_CONSTRAINT_SOLVER_CMD_WRITEBACK_APPLIED_IMPULSES_CONTACT_CONSTRAINTS, - PFX_CONSTRAINT_SOLVER_CMD_SETUP_JOINT_CONSTRAINTS, - PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS, - PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER -}; - - -struct PfxSetupContactConstraintsIO { - PfxConstraintPair *offsetContactPairs; - uint32_t numContactPairs1; - btPersistentManifold* offsetContactManifolds; - btConstraintRow* offsetContactConstraintRows; - class TrbState *offsetRigStates; - struct PfxSolverBody *offsetSolverBodies; - uint32_t numRigidBodies; - float separateBias; - float timeStep; - class btCriticalSection* criticalSection; -}; - - - -struct PfxSolveConstraintsIO { - PfxParallelGroup *contactParallelGroup; - PfxParallelBatch *contactParallelBatches; - PfxConstraintPair *contactPairs; - uint32_t numContactPairs; - btPersistentManifold *offsetContactManifolds; - btConstraintRow* offsetContactConstraintRows; - PfxParallelGroup *jointParallelGroup; - PfxParallelBatch *jointParallelBatches; - PfxConstraintPair *jointPairs; - uint32_t numJointPairs; - struct btSolverConstraint* offsetSolverConstraints; - TrbState *offsetRigStates1; - PfxSolverBody *offsetSolverBodies; - uint32_t numRigidBodies; - uint32_t iteration; - - uint32_t taskId; - - class btBarrier* barrier; - -}; - -struct PfxPostSolverIO { - TrbState *states; - PfxSolverBody *solverBodies; - uint32_t numRigidBodies; -}; - -ATTRIBUTE_ALIGNED16(struct) btConstraintSolverIO { - uint8_t cmd; - union { - PfxSetupContactConstraintsIO setupContactConstraints; - PfxSolveConstraintsIO solveConstraints; - PfxPostSolverIO postSolver; - }; - - //SPU only - uint32_t barrierAddr2; - uint32_t criticalsectionAddr2; - uint32_t maxTasks1; -}; - - - - -void SolverThreadFunc(void* userPtr,void* lsMemory); -void* SolverlsMemoryFunc(); -///The btParallelConstraintSolver performs computations on constraint rows in parallel -///Using the cross-platform threading it supports Windows, Linux, Mac OSX and PlayStation 3 Cell SPUs -class btParallelConstraintSolver : public btSequentialImpulseConstraintSolver -{ - -protected: - struct btParallelSolverMemoryCache* m_memoryCache; - - class btThreadSupportInterface* m_solverThreadSupport; - - struct btConstraintSolverIO* m_solverIO; - class btBarrier* m_barrier; - class btCriticalSection* m_criticalSection; - - -public: - - btParallelConstraintSolver(class btThreadSupportInterface* solverThreadSupport); - - virtual ~btParallelConstraintSolver(); - - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher); - -}; - - - -#endif //__BT_PARALLEL_CONSTRAINT_SOLVER_H \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.cpp b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.cpp deleted file mode 100644 index 8192aa46..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 "btThreadSupportInterface.h" - -btThreadSupportInterface::~btThreadSupportInterface() -{ - -} - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.h deleted file mode 100644 index 54f1769c..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/btThreadSupportInterface.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 BT_THREAD_SUPPORT_INTERFACE_H -#define BT_THREAD_SUPPORT_INTERFACE_H - - -#include //for ATTRIBUTE_ALIGNED16 -#include "PlatformDefinitions.h" -#include "PpuAddressSpace.h" - -class btBarrier { -public: - btBarrier() {} - virtual ~btBarrier() {} - - virtual void sync() = 0; - virtual void setMaxCount(int n) = 0; - virtual int getMaxCount() = 0; -}; - -class btCriticalSection { -public: - btCriticalSection() {} - virtual ~btCriticalSection() {} - - ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]); - - virtual unsigned int getSharedParam(int i) = 0; - virtual void setSharedParam(int i,unsigned int p) = 0; - - virtual void lock() = 0; - virtual void unlock() = 0; -}; - - -class btThreadSupportInterface -{ -public: - - virtual ~btThreadSupportInterface(); - -///send messages to SPUs - virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1) =0; - -///check for messages from SPUs - virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) =0; - - - ///non-blocking test if a task is completed. First implement all versions, and then enable this API - ///virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)=0; - -///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded) - virtual void startSPU() =0; - -///tell the task scheduler we are done with the SPU tasks - virtual void stopSPU()=0; - - ///tell the task scheduler to use no more than numTasks tasks - virtual void setNumTasks(int numTasks)=0; - - virtual int getNumTasks() const = 0; - - virtual btBarrier* createBarrier() = 0; - - virtual btCriticalSection* createCriticalSection() = 0; - - virtual void deleteBarrier(btBarrier* barrier)=0; - - virtual void deleteCriticalSection(btCriticalSection* criticalSection)=0; - - virtual void* getThreadLocalMemory(int taskId) { return 0; } - -}; - -#endif //BT_THREAD_SUPPORT_INTERFACE_H - diff --git a/Code/Physics/Bullet Source/src/BulletMultiThreaded/vectormath2bullet.h b/Code/Physics/Bullet Source/src/BulletMultiThreaded/vectormath2bullet.h deleted file mode 100644 index 4cc72ac5..00000000 --- a/Code/Physics/Bullet Source/src/BulletMultiThreaded/vectormath2bullet.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef BT_AOS_VECTORMATH_BULLET_CONVERT_H -#define BT_AOS_VECTORMATH_BULLET_CONVERT_H - -#include "PlatformDefinitions.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btQuaternion.h" -#include "LinearMath/btMatrix3x3.h" - -inline Vectormath::Aos::Vector3 getVmVector3(const btVector3& bulletVec) -{ - return Vectormath::Aos::Vector3((float)bulletVec.getX(),(float)bulletVec.getY(),(float)bulletVec.getZ()); -} - -inline btVector3 getBtVector3(const Vectormath::Aos::Vector3& vmVec) -{ - return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ()); -} -inline btVector3 getBtVector3(const Vectormath::Aos::Point3& vmVec) -{ - return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ()); -} - -inline Vectormath::Aos::Quat getVmQuat(const btQuaternion& bulletQuat) -{ - Vectormath::Aos::Quat vmQuat((float)bulletQuat.getX(),(float)bulletQuat.getY(),(float)bulletQuat.getZ(),(float)bulletQuat.getW()); - return vmQuat; -} - -inline btQuaternion getBtQuat(const Vectormath::Aos::Quat& vmQuat) -{ - return btQuaternion (vmQuat.getX(),vmQuat.getY(),vmQuat.getZ(),vmQuat.getW()); -} - -inline Vectormath::Aos::Matrix3 getVmMatrix3(const btMatrix3x3& btMat) -{ - Vectormath::Aos::Matrix3 mat( - getVmVector3(btMat.getColumn(0)), - getVmVector3(btMat.getColumn(1)), - getVmVector3(btMat.getColumn(2))); - return mat; -} - - -#endif //BT_AOS_VECTORMATH_BULLET_CONVERT_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt b/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt deleted file mode 100644 index e66bd02d..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt +++ /dev/null @@ -1,67 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src - -) - -#SUBDIRS( Solvers ) - -SET(BulletSoftBody_SRCS - btSoftBody.cpp - btSoftBodyConcaveCollisionAlgorithm.cpp - btSoftBodyHelpers.cpp - btSoftBodyRigidBodyCollisionConfiguration.cpp - btSoftRigidCollisionAlgorithm.cpp - btSoftRigidDynamicsWorld.cpp - btSoftSoftCollisionAlgorithm.cpp - btDefaultSoftBodySolver.cpp - -) - -SET(BulletSoftBody_HDRS - btSoftBody.h - btSoftBodyData.h - btSoftBodyConcaveCollisionAlgorithm.h - btSoftBodyHelpers.h - btSoftBodyRigidBodyCollisionConfiguration.h - btSoftRigidCollisionAlgorithm.h - btSoftRigidDynamicsWorld.h - btSoftSoftCollisionAlgorithm.h - btSparseSDF.h - - btSoftBodySolvers.h - btDefaultSoftBodySolver.h - - btSoftBodySolverVertexBuffer.h -) - - - -ADD_LIBRARY(BulletSoftBody ${BulletSoftBody_SRCS} ${BulletSoftBody_HDRS}) -SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION}) -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics) -ENDIF (BUILD_SHARED_LIBS) - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBody DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS BulletSoftBody RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) - INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN -".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES FRAMEWORK true) - SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES PUBLIC_HEADER "${BulletSoftBody_HDRS}") - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.cpp deleted file mode 100644 index e90d24e6..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" - -#include "btDefaultSoftBodySolver.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" -#include "BulletSoftBody/btSoftBody.h" - - -btDefaultSoftBodySolver::btDefaultSoftBodySolver() -{ - // Initial we will clearly need to update solver constants - // For now this is global for the cloths linked with this solver - we should probably make this body specific - // for performance in future once we understand more clearly when constants need to be updated - m_updateSolverConstants = true; -} - -btDefaultSoftBodySolver::~btDefaultSoftBodySolver() -{ -} - -// In this case the data is already in the soft bodies so there is no need for us to do anything -void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove) -{ - -} - -void btDefaultSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate) -{ - m_softBodySet.copyFromArray( softBodies ); -} - -void btDefaultSoftBodySolver::updateSoftBodies( ) -{ - for ( int i=0; i < m_softBodySet.size(); i++) - { - btSoftBody* psb=(btSoftBody*)m_softBodySet[i]; - if (psb->isActive()) - { - psb->integrateMotion(); - } - } -} // updateSoftBodies - -bool btDefaultSoftBodySolver::checkInitialized() -{ - return true; -} - -void btDefaultSoftBodySolver::solveConstraints( float solverdt ) -{ - // Solve constraints for non-solver softbodies - for(int i=0; i < m_softBodySet.size(); ++i) - { - btSoftBody* psb = static_cast(m_softBodySet[i]); - if (psb->isActive()) - { - psb->solveConstraints(); - } - } -} // btDefaultSoftBodySolver::solveConstraints - - -void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer ) -{ - // Currently only support CPU output buffers - // TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer - // and use them together on a single kernel call if possible by setting up a - // per-cloth target buffer array for the copy kernel. - - if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER ) - { - const btAlignedObjectArray &clothVertices( softBody->m_nodes ); - int numVertices = clothVertices.size(); - - const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer); - float *basePointer = cpuVertexBuffer->getBasePointer(); - - if( vertexBuffer->hasVertexPositions() ) - { - const int vertexOffset = cpuVertexBuffer->getVertexOffset(); - const int vertexStride = cpuVertexBuffer->getVertexStride(); - float *vertexPointer = basePointer + vertexOffset; - - for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) - { - btVector3 position = clothVertices[vertexIndex].m_x; - *(vertexPointer + 0) = position.getX(); - *(vertexPointer + 1) = position.getY(); - *(vertexPointer + 2) = position.getZ(); - vertexPointer += vertexStride; - } - } - if( vertexBuffer->hasNormals() ) - { - const int normalOffset = cpuVertexBuffer->getNormalOffset(); - const int normalStride = cpuVertexBuffer->getNormalStride(); - float *normalPointer = basePointer + normalOffset; - - for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex ) - { - btVector3 normal = clothVertices[vertexIndex].m_n; - *(normalPointer + 0) = normal.getX(); - *(normalPointer + 1) = normal.getY(); - *(normalPointer + 2) = normal.getZ(); - normalPointer += normalStride; - } - } - } -} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer - -void btDefaultSoftBodySolver::processCollision( btSoftBody* softBody, btSoftBody* otherSoftBody) -{ - softBody->defaultCollisionHandler( otherSoftBody); -} - -// For the default solver just leave the soft body to do its collision processing -void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObjectWrap ) -{ - softBody->defaultCollisionHandler( collisionObjectWrap ); -} // btDefaultSoftBodySolver::processCollision - - -void btDefaultSoftBodySolver::predictMotion( float timeStep ) -{ - for ( int i=0; i < m_softBodySet.size(); ++i) - { - btSoftBody* psb = m_softBodySet[i]; - - if (psb->isActive()) - { - psb->predictMotion(timeStep); - } - } -} - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.h deleted file mode 100644 index 1c17ffcb..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btDefaultSoftBodySolver.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_DEFAULT_SOLVER_H -#define BT_SOFT_BODY_DEFAULT_SOLVER_H - - -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "btSoftBodySolverVertexBuffer.h" -struct btCollisionObjectWrapper; - -class btDefaultSoftBodySolver : public btSoftBodySolver -{ -protected: - /** Variable to define whether we need to update solver constants on the next iteration */ - bool m_updateSolverConstants; - - btAlignedObjectArray< btSoftBody * > m_softBodySet; - - -public: - btDefaultSoftBodySolver(); - - virtual ~btDefaultSoftBodySolver(); - - virtual SolverTypes getSolverType() const - { - return DEFAULT_SOLVER; - } - - virtual bool checkInitialized(); - - virtual void updateSoftBodies( ); - - virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies,bool forceUpdate=false ); - - virtual void copyBackToSoftBodies(bool bMove = true); - - virtual void solveConstraints( float solverdt ); - - virtual void predictMotion( float solverdt ); - - virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer ); - - virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* ); - - virtual void processCollision( btSoftBody*, btSoftBody* ); - -}; - -#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.cpp deleted file mode 100644 index a0c8cca4..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.cpp +++ /dev/null @@ -1,3655 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBody implementation by Nathanael Presson - -#include "btSoftBodyInternals.h" -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "btSoftBodyData.h" -#include "LinearMath/btSerializer.h" - - -// -btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) -:m_softBodySolver(0),m_worldInfo(worldInfo) -{ - /* Init */ - initDefaults(); - - /* Default material */ - Material* pm=appendMaterial(); - pm->m_kLST = 1; - pm->m_kAST = 1; - pm->m_kVST = 1; - pm->m_flags = fMaterial::Default; - - /* Nodes */ - const btScalar margin=getCollisionShape()->getMargin(); - m_nodes.resize(node_count); - for(int i=0,ni=node_count;i0?1/n.m_im:0; - n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); - n.m_material= pm; - } - updateBounds(); - -} - -btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo) -:m_worldInfo(worldInfo) -{ - initDefaults(); -} - - -void btSoftBody::initDefaults() -{ - m_internalType = CO_SOFT_BODY; - m_cfg.aeromodel = eAeroModel::V_Point; - m_cfg.kVCF = 1; - m_cfg.kDG = 0; - m_cfg.kLF = 0; - m_cfg.kDP = 0; - m_cfg.kPR = 0; - m_cfg.kVC = 0; - m_cfg.kDF = (btScalar)0.2; - m_cfg.kMT = 0; - m_cfg.kCHR = (btScalar)1.0; - m_cfg.kKHR = (btScalar)0.1; - m_cfg.kSHR = (btScalar)1.0; - m_cfg.kAHR = (btScalar)0.7; - m_cfg.kSRHR_CL = (btScalar)0.1; - m_cfg.kSKHR_CL = (btScalar)1; - m_cfg.kSSHR_CL = (btScalar)0.5; - m_cfg.kSR_SPLT_CL = (btScalar)0.5; - m_cfg.kSK_SPLT_CL = (btScalar)0.5; - m_cfg.kSS_SPLT_CL = (btScalar)0.5; - m_cfg.maxvolume = (btScalar)1; - m_cfg.timescale = 1; - m_cfg.viterations = 0; - m_cfg.piterations = 1; - m_cfg.diterations = 0; - m_cfg.citerations = 4; - m_cfg.collisions = fCollision::Default; - m_pose.m_bvolume = false; - m_pose.m_bframe = false; - m_pose.m_volume = 0; - m_pose.m_com = btVector3(0,0,0); - m_pose.m_rot.setIdentity(); - m_pose.m_scl.setIdentity(); - m_tag = 0; - m_timeacc = 0; - m_bUpdateRtCst = true; - m_bounds[0] = btVector3(0,0,0); - m_bounds[1] = btVector3(0,0,0); - m_worldTransform.setIdentity(); - setSolver(eSolverPresets::Positions); - - /* Collision shape */ - ///for now, create a collision shape internally - m_collisionShape = new btSoftBodyCollisionShape(this); - m_collisionShape->setMargin(0.25f); - - m_initialWorldTransform.setIdentity(); - - m_windVelocity = btVector3(0,0,0); - m_restLengthScale = btScalar(1.0); -} - -// -btSoftBody::~btSoftBody() -{ - //for now, delete the internal shape - delete m_collisionShape; - int i; - - releaseClusters(); - for(i=0;i0) - *pm=*m_materials[0]; - else - ZeroInitialize(*pm); - m_materials.push_back(pm); - return(pm); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - const btVector4& c, - Node* n0, - Node* n1, - Node* n2, - Node* n3) -{ - Note n; - ZeroInitialize(n); - n.m_rank = 0; - n.m_text = text; - n.m_offset = o; - n.m_coords[0] = c.x(); - n.m_coords[1] = c.y(); - n.m_coords[2] = c.z(); - n.m_coords[3] = c.w(); - n.m_nodes[0] = n0;n.m_rank+=n0?1:0; - n.m_nodes[1] = n1;n.m_rank+=n1?1:0; - n.m_nodes[2] = n2;n.m_rank+=n2?1:0; - n.m_nodes[3] = n3;n.m_rank+=n3?1:0; - m_notes.push_back(n); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - Node* feature) -{ - appendNote(text,o,btVector4(1,0,0,0),feature); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - Link* feature) -{ - static const btScalar w=1/(btScalar)2; - appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0], - feature->m_n[1]); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - Face* feature) -{ - static const btScalar w=1/(btScalar)3; - appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0], - feature->m_n[1], - feature->m_n[2]); -} - -// -void btSoftBody::appendNode( const btVector3& x,btScalar m) -{ - if(m_nodes.capacity()==m_nodes.size()) - { - pointersToIndices(); - m_nodes.reserve(m_nodes.size()*2+1); - indicesToPointers(); - } - const btScalar margin=getCollisionShape()->getMargin(); - m_nodes.push_back(Node()); - Node& n=m_nodes[m_nodes.size()-1]; - ZeroInitialize(n); - n.m_x = x; - n.m_q = n.m_x; - n.m_im = m>0?1/m:0; - n.m_material = m_materials[0]; - n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); -} - -// -void btSoftBody::appendLink(int model,Material* mat) -{ - Link l; - if(model>=0) - l=m_links[model]; - else - { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; } - m_links.push_back(l); -} - -// -void btSoftBody::appendLink( int node0, - int node1, - Material* mat, - bool bcheckexist) -{ - appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist); -} - -// -void btSoftBody::appendLink( Node* node0, - Node* node1, - Material* mat, - bool bcheckexist) -{ - if((!bcheckexist)||(!checkLink(node0,node1))) - { - appendLink(-1,mat); - Link& l=m_links[m_links.size()-1]; - l.m_n[0] = node0; - l.m_n[1] = node1; - l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); - m_bUpdateRtCst=true; - } -} - -// -void btSoftBody::appendFace(int model,Material* mat) -{ - Face f; - if(model>=0) - { f=m_faces[model]; } - else - { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; } - m_faces.push_back(f); -} - -// -void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) -{ - if (node0==node1) - return; - if (node1==node2) - return; - if (node2==node0) - return; - - appendFace(-1,mat); - Face& f=m_faces[m_faces.size()-1]; - btAssert(node0!=node1); - btAssert(node1!=node2); - btAssert(node2!=node0); - f.m_n[0] = &m_nodes[node0]; - f.m_n[1] = &m_nodes[node1]; - f.m_n[2] = &m_nodes[node2]; - f.m_ra = AreaOf( f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x); - m_bUpdateRtCst=true; -} - -// -void btSoftBody::appendTetra(int model,Material* mat) -{ -Tetra t; -if(model>=0) - t=m_tetras[model]; - else - { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; } -m_tetras.push_back(t); -} - -// -void btSoftBody::appendTetra(int node0, - int node1, - int node2, - int node3, - Material* mat) -{ - appendTetra(-1,mat); - Tetra& t=m_tetras[m_tetras.size()-1]; - t.m_n[0] = &m_nodes[node0]; - t.m_n[1] = &m_nodes[node1]; - t.m_n[2] = &m_nodes[node2]; - t.m_n[3] = &m_nodes[node3]; - t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x); - m_bUpdateRtCst=true; -} - -// - -void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence) -{ - btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x; - appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence); -} - -// -void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence) -{ - if (disableCollisionBetweenLinkedBodies) - { - if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size()) - { - m_collisionDisabledObjects.push_back(body); - } - } - - Anchor a; - a.m_node = &m_nodes[node]; - a.m_body = body; - a.m_local = localPivot; - a.m_node->m_battach = 1; - a.m_influence = influence; - m_anchors.push_back(a); -} - -// -void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1) -{ - LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint(); - pj->m_bodies[0] = body0; - pj->m_bodies[1] = body1; - pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position; - pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position; - pj->m_cfm = specs.cfm; - pj->m_erp = specs.erp; - pj->m_split = specs.split; - m_joints.push_back(pj); -} - -// -void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body) -{ - appendLinearJoint(specs,m_clusters[0],body); -} - -// -void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) -{ - appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); -} - -// -void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1) -{ - AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint(); - pj->m_bodies[0] = body0; - pj->m_bodies[1] = body1; - pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis; - pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis; - pj->m_cfm = specs.cfm; - pj->m_erp = specs.erp; - pj->m_split = specs.split; - pj->m_icontrol = specs.icontrol; - m_joints.push_back(pj); -} - -// -void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body) -{ - appendAngularJoint(specs,m_clusters[0],body); -} - -// -void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) -{ - appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); -} - -// -void btSoftBody::addForce(const btVector3& force) -{ - for(int i=0,ni=m_nodes.size();i0) - { - n.m_f += force; - } -} - -void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex) -{ - btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size()); - - const btScalar dt = m_sst.sdt; - const btScalar kLF = m_cfg.kLF; - const btScalar kDG = m_cfg.kDG; - //const btScalar kPR = m_cfg.kPR; - //const btScalar kVC = m_cfg.kVC; - const bool as_lift = kLF>0; - const bool as_drag = kDG>0; - const bool as_aero = as_lift || as_drag; - const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); - - Node& n = m_nodes[nodeIndex]; - - if( n.m_im>0 ) - { - btSoftBody::sMedium medium; - - EvaluateMedium(m_worldInfo, n.m_x, medium); - medium.m_velocity = windVelocity; - medium.m_density = m_worldInfo->air_density; - - /* Aerodynamics */ - if(as_vaero) - { - const btVector3 rel_v = n.m_v - medium.m_velocity; - const btScalar rel_v_len = rel_v.length(); - const btScalar rel_v2 = rel_v.length2(); - - if(rel_v2>SIMD_EPSILON) - { - const btVector3 rel_v_nrm = rel_v.normalized(); - btVector3 nrm = n.m_n; - - if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag) - { - nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); - btVector3 fDrag(0, 0, 0); - btVector3 fLift(0, 0, 0); - - btScalar n_dot_v = nrm.dot(rel_v_nrm); - btScalar tri_area = 0.5f * n.m_area; - - fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); - - // Check angle of attack - // cos(10º) = 0.98480 - if ( 0 < n_dot_v && n_dot_v < 0.98480f) - fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); - - // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node. - btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt; - btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2(); - btScalar v_len2 = n.m_v.length2(); - - if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0) - { - btScalar del_v_by_fDrag_len = del_v_by_fDrag.length(); - btScalar v_len = n.m_v.length(); - fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len); - } - - n.m_f += fDrag; - n.m_f += fLift; - } - else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided) - { - if (btSoftBody::eAeroModel::V_TwoSided) - nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); - - const btScalar dvn = btDot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) - { - btVector3 force(0,0,0); - const btScalar c0 = n.m_area * dvn * rel_v2/2; - const btScalar c1 = c0 * medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized() * (-c1 * kDG); - ApplyClampedForce(n, force, dt); - } - } - } - } - } -} - -void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex) -{ - const btScalar dt = m_sst.sdt; - const btScalar kLF = m_cfg.kLF; - const btScalar kDG = m_cfg.kDG; -// const btScalar kPR = m_cfg.kPR; -// const btScalar kVC = m_cfg.kVC; - const bool as_lift = kLF>0; - const bool as_drag = kDG>0; - const bool as_aero = as_lift || as_drag; - const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); - - if(as_faero) - { - btSoftBody::Face& f=m_faces[faceIndex]; - - btSoftBody::sMedium medium; - - const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; - const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; - EvaluateMedium(m_worldInfo,x,medium); - medium.m_velocity = windVelocity; - medium.m_density = m_worldInfo->air_density; - const btVector3 rel_v=v-medium.m_velocity; - const btScalar rel_v_len = rel_v.length(); - const btScalar rel_v2=rel_v.length2(); - - if(rel_v2>SIMD_EPSILON) - { - const btVector3 rel_v_nrm = rel_v.normalized(); - btVector3 nrm = f.m_normal; - - if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag) - { - nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); - - btVector3 fDrag(0, 0, 0); - btVector3 fLift(0, 0, 0); - - btScalar n_dot_v = nrm.dot(rel_v_nrm); - btScalar tri_area = 0.5f * f.m_ra; - - fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); - - // Check angle of attack - // cos(10º) = 0.98480 - if ( 0 < n_dot_v && n_dot_v < 0.98480f) - fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); - - fDrag /= 3; - fLift /= 3; - - for(int j=0;j<3;++j) - { - if (f.m_n[j]->m_im>0) - { - // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node. - btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt; - btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2(); - btScalar v_len2 = f.m_n[j]->m_v.length2(); - - if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0) - { - btScalar del_v_by_fDrag_len = del_v_by_fDrag.length(); - btScalar v_len = f.m_n[j]->m_v.length(); - fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len); - } - - f.m_n[j]->m_f += fDrag; - f.m_n[j]->m_f += fLift; - } - } - } - else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided) - { - if (btSoftBody::eAeroModel::F_TwoSided) - nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); - - const btScalar dvn=btDot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) - { - btVector3 force(0,0,0); - const btScalar c0 = f.m_ra*dvn*rel_v2; - const btScalar c1 = c0*medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized()*(-c1*kDG); - force /= 3; - for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); - } - } - } - } - -} - -// -void btSoftBody::addVelocity(const btVector3& velocity) -{ - for(int i=0,ni=m_nodes.size();i0) - { - n.m_v = velocity; - } - } -} - - -// -void btSoftBody::addVelocity(const btVector3& velocity,int node) -{ - Node& n=m_nodes[node]; - if(n.m_im>0) - { - n.m_v += velocity; - } -} - -// -void btSoftBody::setMass(int node,btScalar mass) -{ - m_nodes[node].m_im=mass>0?1/mass:0; - m_bUpdateRtCst=true; -} - -// -btScalar btSoftBody::getMass(int node) const -{ - return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); -} - -// -btScalar btSoftBody::getTotalMass() const -{ - btScalar mass=0; - for(int i=0;im_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x); - for(int j=0;j<3;++j) - { - f.m_n[j]->m_im+=twicearea; - } - } - for( i=0;i ranks; -ranks.resize(m_nodes.size(),0); -int i; - -for(i=0;im_im+=btFabs(t.m_rv); - ranks[int(t.m_n[j]-&m_nodes[0])]+=1; - } - } -for( i=0;i0) - { - m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im; - } - } -setTotalMass(mass,false); -} - -// -void btSoftBody::setVolumeDensity(btScalar density) -{ -btScalar volume=0; -for(int i=0;igetMargin(); - ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; - - for(int i=0,ni=m_nodes.size();igetMargin(); - ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; - - for(int i=0,ni=m_nodes.size();i0 ? - 1/(m_nodes[i].m_im*tmass) : - kmass/tmass; - } - /* Pos */ - const btVector3 com=evaluateCom(); - m_pose.m_pos.resize(m_nodes.size()); - for( i=0,ni=m_nodes.size();im_x-l.m_n[1]->m_x).length(); - l.m_c1 = l.m_rl*l.m_rl; - } -} - -// -btScalar btSoftBody::getVolume() const -{ - btScalar vol=0; - if(m_nodes.size()>0) - { - int i,ni; - - const btVector3 org=m_nodes[0].m_x; - for(i=0,ni=m_faces.size();im_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); - } - vol/=(btScalar)6; - } - return(vol); -} - -// -int btSoftBody::clusterCount() const -{ - return(m_clusters.size()); -} - -// -btVector3 btSoftBody::clusterCom(const Cluster* cluster) -{ - btVector3 com(0,0,0); - for(int i=0,ni=cluster->m_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; - } - return(com*cluster->m_imass); -} - -// -btVector3 btSoftBody::clusterCom(int cluster) const -{ - return(clusterCom(m_clusters[cluster])); -} - -// -btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) -{ - return(cluster->m_lv+btCross(cluster->m_av,rpos)); -} - -// -void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) -{ - const btVector3 li=cluster->m_imass*impulse; - const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse); - cluster->m_vimpulses[0]+=li;cluster->m_lv+=li; - cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; - cluster->m_nvimpulses++; -} - -// -void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) -{ - const btVector3 li=cluster->m_imass*impulse; - const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse); - cluster->m_dimpulses[0]+=li; - cluster->m_dimpulses[1]+=ai; - cluster->m_ndimpulses++; -} - -// -void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse) -{ - if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity); - if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift); -} - -// -void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse) -{ - const btVector3 ai=cluster->m_invwi*impulse; - cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; - cluster->m_nvimpulses++; -} - -// -void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse) -{ - const btVector3 ai=cluster->m_invwi*impulse; - cluster->m_dimpulses[1]+=ai; - cluster->m_ndimpulses++; -} - -// -void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse) -{ - if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity); - if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift); -} - -// -void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse) -{ - cluster->m_dimpulses[0]+=impulse*cluster->m_imass; - cluster->m_ndimpulses++; -} - -struct NodeLinks -{ - btAlignedObjectArray m_links; -}; - - - -// -int btSoftBody::generateBendingConstraints(int distance,Material* mat) -{ - int i,j; - - if(distance>1) - { - /* Build graph */ - const int n=m_nodes.size(); - const unsigned inf=(~(unsigned)0)>>1; - unsigned* adj=new unsigned[n*n]; - - -#define IDX(_x_,_y_) ((_y_)*n+(_x_)) - for(j=0;j nodeLinks; - - - /* Build node links */ - nodeLinks.resize(m_nodes.size()); - - for( i=0;isum) - { - adj[IDX(i,j)]=adj[IDX(j,i)]=sum; - } - } - - } - } - } - } else - { - ///generic Floyd's algorithm - for(int k=0;ksum) - { - adj[IDX(i,j)]=adj[IDX(j,i)]=sum; - } - } - } - } - } - - - /* Build links */ - int nlinks=0; - for(j=0;jm_leaf) m_cdbvt.remove(c->m_leaf); - c->~Cluster(); - btAlignedFree(c); - m_clusters.remove(c); -} - -// -void btSoftBody::releaseClusters() -{ - while(m_clusters.size()>0) releaseCluster(0); -} - -// -int btSoftBody::generateClusters(int k,int maxiterations) -{ - int i; - releaseClusters(); - m_clusters.resize(btMin(k,m_nodes.size())); - for(i=0;im_collide= true; - } - k=m_clusters.size(); - if(k>0) - { - /* Initialize */ - btAlignedObjectArray centers; - btVector3 cog(0,0,0); - int i; - for(i=0;im_nodes.push_back(&m_nodes[i]); - } - cog/=(btScalar)m_nodes.size(); - centers.resize(k,cog); - /* Iterate */ - const btScalar slope=16; - bool changed; - int iterations=0; - do { - const btScalar w=2-btMin(1,iterations/slope); - changed=false; - iterations++; - int i; - - for(i=0;im_nodes.size();++j) - { - c+=m_clusters[i]->m_nodes[j]->m_x; - } - if(m_clusters[i]->m_nodes.size()) - { - c /= (btScalar)m_clusters[i]->m_nodes.size(); - c = centers[i]+(c-centers[i])*w; - changed |= ((c-centers[i]).length2()>SIMD_EPSILON); - centers[i] = c; - m_clusters[i]->m_nodes.resize(0); - } - } - for(i=0;im_nodes.push_back(&m_nodes[i]); - } - } while(changed&&(iterations cids; - cids.resize(m_nodes.size(),-1); - for(i=0;im_nodes.size();++j) - { - cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; - } - } - for(i=0;im_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) - { - m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); - } - } - } - } - } - /* Master */ - if(m_clusters.size()>1) - { - Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); - pmaster->m_collide = false; - pmaster->m_nodes.reserve(m_nodes.size()); - for(int i=0;im_nodes.push_back(&m_nodes[i]); - m_clusters.push_back(pmaster); - btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]); - } - /* Terminate */ - for(i=0;im_nodes.size()==0) - { - releaseCluster(i--); - } - } - } else - { - //create a cluster for each tetrahedron (if tetrahedra exist) or each face - if (m_tetras.size()) - { - m_clusters.resize(m_tetras.size()); - for(i=0;im_collide= true; - } - for (i=0;im_nodes.push_back(m_tetras[i].m_n[j]); - } - } - - } else - { - m_clusters.resize(m_faces.size()); - for(i=0;im_collide= true; - } - - for(i=0;im_nodes.push_back(m_faces[i].m_n[j]); - } - } - } - } - - if (m_clusters.size()) - { - initializeClusters(); - updateClusters(); - - - //for self-collision - m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size()); - { - for (int c0=0;c0m_clusterIndex=c0; - for (int c1=0;c1m_nodes.size();i++) - { - for (int j=0;jm_nodes.size();j++) - { - if (cla->m_nodes[i] == clb->m_nodes[j]) - { - connected=true; - break; - } - } - } - m_clusterConnectivity[c0+c1*m_clusters.size()]=connected; - } - } - } - } - - return(m_clusters.size()); -} - -// -void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut) -{ - const Node* nbase = &m_nodes[0]; - int ncount = m_nodes.size(); - btSymMatrix edges(ncount,-2); - int newnodes=0; - int i,j,k,ni; - - /* Filter out */ - for(i=0;iEval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x))) - { - btSwap(m_links[i],m_links[m_links.size()-1]); - m_links.pop_back();--i; - } - } - } - /* Fill edges */ - for(i=0;i0) - { - const btVector3 x=Lerp(a.m_x,b.m_x,t); - const btVector3 v=Lerp(a.m_v,b.m_v,t); - btScalar m=0; - if(a.m_im>0) - { - if(b.m_im>0) - { - const btScalar ma=1/a.m_im; - const btScalar mb=1/b.m_im; - const btScalar mc=Lerp(ma,mb,t); - const btScalar f=(ma+mb)/(ma+mb+mc); - a.m_im=1/(ma*f); - b.m_im=1/(mb*f); - m=mc*f; - } - else - { a.m_im/=0.5f;m=1/a.m_im; } - } - else - { - if(b.m_im>0) - { b.m_im/=0.5f;m=1/b.m_im; } - else - m=0; - } - appendNode(x,m); - edges(i,j)=m_nodes.size()-1; - m_nodes[edges(i,j)].m_v=v; - ++newnodes; - } - } - } - } - nbase=&m_nodes[0]; - /* Refine links */ - for(i=0,ni=m_links.size();i0) - { - appendLink(i); - Link* pft[]={ &m_links[i], - &m_links[m_links.size()-1]}; - pft[0]->m_n[0]=&m_nodes[idx[0]]; - pft[0]->m_n[1]=&m_nodes[ni]; - pft[1]->m_n[0]=&m_nodes[ni]; - pft[1]->m_n[1]=&m_nodes[idx[1]]; - } - } - } - /* Refine faces */ - for(i=0;i0) - { - appendFace(i); - const int l=(k+1)%3; - Face* pft[]={ &m_faces[i], - &m_faces[m_faces.size()-1]}; - pft[0]->m_n[0]=&m_nodes[idx[l]]; - pft[0]->m_n[1]=&m_nodes[idx[j]]; - pft[0]->m_n[2]=&m_nodes[ni]; - pft[1]->m_n[0]=&m_nodes[ni]; - pft[1]->m_n[1]=&m_nodes[idx[k]]; - pft[1]->m_n[2]=&m_nodes[idx[l]]; - appendLink(ni,idx[l],pft[0]->m_material); - --i;break; - } - } - } - } - /* Cut */ - if(cut) - { - btAlignedObjectArray cnodes; - const int pcount=ncount; - int i; - ncount=m_nodes.size(); - cnodes.resize(ncount,0); - /* Nodes */ - for(i=0;i=pcount)||(btFabs(ifn->Eval(x))0) { m*=0.5f;m_nodes[i].m_im/=0.5f; } - appendNode(x,m); - cnodes[i]=m_nodes.size()-1; - m_nodes[cnodes[i]].m_v=v; - } - } - nbase=&m_nodes[0]; - /* Links */ - for(i=0,ni=m_links.size();iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)Eval(n[0]->m_x)Eval(n[1]->m_x)Eval(n[2]->m_x) ranks; - btAlignedObjectArray todelete; - ranks.resize(nnodes,0); - for(i=0,ni=m_links.size();i=0;--i) - { - if(!ranks[i]) todelete.push_back(i); - } - if(todelete.size()) - { - btAlignedObjectArray& map=ranks; - for(int i=0;im_v=v; - pn[1]->m_v=v; - for(i=0,ni=m_links.size();im_n[1]=pn[mtch]; - pft[1]->m_n[0]=pn[1-mtch]; - done=true; - } - } - for(i=0,ni=m_faces.size();im_n[l]=pn[mtch]; - pft[1]->m_n[k]=pn[1-mtch]; - appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); - appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); - } - } - } - if(!done) - { - m_ndbvt.remove(pn[0]->m_leaf); - m_ndbvt.remove(pn[1]->m_leaf); - m_nodes.pop_back(); - m_nodes.pop_back(); - } - return(done); -} - -// -bool btSoftBody::rayTest(const btVector3& rayFrom, - const btVector3& rayTo, - sRayCast& results) -{ - if(m_faces.size()&&m_fdbvt.empty()) - initializeFaceTree(); - - results.body = this; - results.fraction = 1.f; - results.feature = eFeature::None; - results.index = -1; - - return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0); -} - -// -void btSoftBody::setSolver(eSolverPresets::_ preset) -{ - m_cfg.m_vsequence.clear(); - m_cfg.m_psequence.clear(); - m_cfg.m_dsequence.clear(); - switch(preset) - { - case eSolverPresets::Positions: - m_cfg.m_psequence.push_back(ePSolver::Anchors); - m_cfg.m_psequence.push_back(ePSolver::RContacts); - m_cfg.m_psequence.push_back(ePSolver::SContacts); - m_cfg.m_psequence.push_back(ePSolver::Linear); - break; - case eSolverPresets::Velocities: - m_cfg.m_vsequence.push_back(eVSolver::Linear); - - m_cfg.m_psequence.push_back(ePSolver::Anchors); - m_cfg.m_psequence.push_back(ePSolver::RContacts); - m_cfg.m_psequence.push_back(ePSolver::SContacts); - - m_cfg.m_dsequence.push_back(ePSolver::Linear); - break; - } -} - -// -void btSoftBody::predictMotion(btScalar dt) -{ - - int i,ni; - - /* Update */ - if(m_bUpdateRtCst) - { - m_bUpdateRtCst=false; - updateConstants(); - m_fdbvt.clear(); - if(m_cfg.collisions&fCollision::VF_SS) - { - initializeFaceTree(); - } - } - - /* Prepare */ - m_sst.sdt = dt*m_cfg.timescale; - m_sst.isdt = 1/m_sst.sdt; - m_sst.velmrg = m_sst.sdt*3; - m_sst.radmrg = getCollisionShape()->getMargin(); - m_sst.updmrg = m_sst.radmrg*(btScalar)0.25; - /* Forces */ - addVelocity(m_worldInfo->m_gravity*m_sst.sdt); - applyForces(); - /* Integrate */ - for(i=0,ni=m_nodes.size();im_maxDisplacement; - btScalar clampDeltaV = maxDisplacement/m_sst.sdt; - for (int c=0;c<3;c++) - { - if (deltaV[c]>clampDeltaV) - { - deltaV[c] = clampDeltaV; - } - if (deltaV[c]<-clampDeltaV) - { - deltaV[c]=-clampDeltaV; - } - } - } - n.m_v += deltaV; - n.m_x += n.m_v*m_sst.sdt; - n.m_f = btVector3(0,0,0); - } - /* Clusters */ - updateClusters(); - /* Bounds */ - updateBounds(); - /* Nodes */ - ATTRIBUTE_ALIGNED16(btDbvtVolume) vol; - for(i=0,ni=m_nodes.size();im_v+ - f.m_n[1]->m_v+ - f.m_n[2]->m_v)/3; - vol = VolumeOf(f,m_sst.radmrg); - m_fdbvt.update( f.m_leaf, - vol, - v*m_sst.velmrg, - m_sst.updmrg); - } - } - /* Pose */ - updatePose(); - /* Match */ - if(m_pose.m_bframe&&(m_cfg.kMT>0)) - { - const btMatrix3x3 posetrs=m_pose.m_rot; - for(int i=0,ni=m_nodes.size();i0) - { - const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com; - n.m_x=Lerp(n.m_x,x,m_cfg.kMT); - } - } - } - /* Clear contacts */ - m_rcontacts.resize(0); - m_scontacts.resize(0); - /* Optimize dbvt's */ - m_ndbvt.optimizeIncremental(1); - m_fdbvt.optimizeIncremental(1); - m_cdbvt.optimizeIncremental(1); -} - -// -void btSoftBody::solveConstraints() -{ - - /* Apply clusters */ - applyClusters(false); - /* Prepare links */ - - int i,ni; - - for(i=0,ni=m_links.size();im_q-l.m_n[0]->m_q; - l.m_c2 = 1/(l.m_c3.length2()*l.m_c0); - } - /* Prepare anchors */ - for(i=0,ni=m_anchors.size();igetWorldTransform().getBasis()*a.m_local; - a.m_c0 = ImpulseMatrix( m_sst.sdt, - a.m_node->m_im, - a.m_body->getInvMass(), - a.m_body->getInvInertiaTensorWorld(), - ra); - a.m_c1 = ra; - a.m_c2 = m_sst.sdt*a.m_node->m_im; - a.m_body->activate(); - } - /* Solve velocities */ - if(m_cfg.viterations>0) - { - /* Solve */ - for(int isolve=0;isolve0) - { - for(int isolve=0;isolve0) - { - const btScalar vcf=m_cfg.kVCF*m_sst.isdt; - for(i=0,ni=m_nodes.size();i& bodies) -{ - const int nb=bodies.size(); - int iterations=0; - int i; - - for(i=0;im_cfg.citerations); - } - for(i=0;iprepareClusters(iterations); - } - for(i=0;isolveClusters(sor); - } - } - for(i=0;icleanupClusters(); - } -} - -// -void btSoftBody::integrateMotion() -{ - /* Update */ - updateNormals(); -} - -// -btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt) -{ - m_rayFrom = rayFrom; - m_rayNormalizedDirection = (rayTo-rayFrom); - m_rayTo = rayTo; - m_mint = mxt; - m_face = 0; - m_tests = 0; -} - -// -void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf) -{ - btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; - const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection, - f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x, - m_mint); - if((t>0)&&(tteps)&&(tceps) && - (btDot(n,btCross(b-hit,c-hit))>ceps) && - (btDot(n,btCross(c-hit,a-hit))>ceps)) - { - return(t); - } - } - } - return(-1); -} - -// -void btSoftBody::pointersToIndices() -{ -#define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) - btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0; - int i,ni; - - for(i=0,ni=m_nodes.size();idata=*(void**)&i; - } - } - for(i=0,ni=m_links.size();idata=*(void**)&i; - } - } - for(i=0,ni=m_anchors.size();idata=&m_nodes[i]; - } - } - for(i=0,ni=m_links.size();idata=&m_faces[i]; - } - } - for(i=0,ni=m_anchors.size();im_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x, - mint); - if(t>0) - { - ++cnt; - if(!bcountonly) - { - feature=btSoftBody::eFeature::Face; - index=i; - mint=t; - } - } - } - } - else - {/* Use dbvt */ - RayFromToCaster collider(rayFrom,rayTo,mint); - - btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider); - if(collider.m_face) - { - mint=collider.m_mint; - feature=btSoftBody::eFeature::Face; - index=(int)(collider.m_face-&m_faces[0]); - cnt=1; - } - } - - for (int i=0;im_x; - btVector3 v1=tet.m_n[index1]->m_x; - btVector3 v2=tet.m_n[index2]->m_x; - - - const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir, - v0,v1,v2, - mint); - if(t>0) - { - ++cnt; - if(!bcountonly) - { - feature=btSoftBody::eFeature::Tetra; - index=i; - mint=t; - } - } - } - } - return(cnt); -} - -// -void btSoftBody::initializeFaceTree() -{ - m_fdbvt.clear(); - for(int i=0;igetCollisionShape(); -// const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject()); - //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform(); - const btTransform &wtr = colObjWrap->getWorldTransform(); - //todo: check which transform is needed here - - btScalar dst = - m_worldInfo->m_sparsesdf.Evaluate( - wtr.invXform(x), - shp, - nrm, - margin); - if(dst<0) - { - cti.m_colObj = colObjWrap->getCollisionObject(); - cti.m_normal = wtr.getBasis()*nrm; - cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst ); - return(true); - } - return(false); -} - -// -void btSoftBody::updateNormals() -{ - - const btVector3 zv(0,0,0); - int i,ni; - - for(i=0,ni=m_nodes.size();im_x-f.m_n[0]->m_x, - f.m_n[2]->m_x-f.m_n[0]->m_x); - f.m_normal=n.normalized(); - f.m_n[0]->m_n+=n; - f.m_n[1]->m_n+=n; - f.m_n[2]->m_n+=n; - } - for(i=0,ni=m_nodes.size();iSIMD_EPSILON) - m_nodes[i].m_n /= len; - } -} - -// -void btSoftBody::updateBounds() -{ - /*if( m_acceleratedSoftBody ) - { - // If we have an accelerated softbody we need to obtain the bounds correctly - // For now (slightly hackily) just have a very large AABB - // TODO: Write get bounds kernel - // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could - // probably do a test and exchange reasonably efficiently. - - m_bounds[0] = btVector3(-1000, -1000, -1000); - m_bounds[1] = btVector3(1000, 1000, 1000); - - } else {*/ - if(m_ndbvt.m_root) - { - const btVector3& mins=m_ndbvt.m_root->volume.Mins(); - const btVector3& maxs=m_ndbvt.m_root->volume.Maxs(); - const btScalar csm=getCollisionShape()->getMargin(); - const btVector3 mrg=btVector3( csm, - csm, - csm)*1; // ??? to investigate... - m_bounds[0]=mins-mrg; - m_bounds[1]=maxs+mrg; - if(0!=getBroadphaseHandle()) - { - m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), - m_bounds[0], - m_bounds[1], - m_worldInfo->m_dispatcher); - } - } - else - { - m_bounds[0]= - m_bounds[1]=btVector3(0,0,0); - } - //} -} - - -// -void btSoftBody::updatePose() -{ - if(m_pose.m_bframe) - { - btSoftBody::Pose& pose=m_pose; - const btVector3 com=evaluateCom(); - /* Com */ - pose.m_com = com; - /* Rotation */ - btMatrix3x3 Apq; - const btScalar eps=SIMD_EPSILON; - Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); - Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); - for(int i=0,ni=m_nodes.size();i1) - { - const btScalar idet=Clamp( 1/pose.m_scl.determinant(), - 1,m_cfg.maxvolume); - pose.m_scl=Mul(pose.m_scl,idet); - } - - } -} - -// -void btSoftBody::updateArea(bool averageArea) -{ - int i,ni; - - /* Face area */ - for(i=0,ni=m_faces.size();im_x,f.m_n[1]->m_x,f.m_n[2]->m_x); - } - - /* Node area */ - - if (averageArea) - { - btAlignedObjectArray counts; - counts.resize(m_nodes.size(),0); - for(i=0,ni=m_nodes.size();im_area+=btFabs(f.m_ra); - } - } - for(i=0,ni=m_nodes.size();i0) - m_nodes[i].m_area/=(btScalar)counts[i]; - else - m_nodes[i].m_area=0; - } - } - else - { - // initialize node area as zero - for(i=0,ni=m_nodes.size();im_area += f.m_ra; - } - } - - for(i=0,ni=m_nodes.size();im_im+l.m_n[1]->m_im)/m.m_kLST; - } -} - -void btSoftBody::updateConstants() -{ - resetLinkRestLengths(); - updateLinkConstants(); - updateArea(); -} - - - -// -void btSoftBody::initializeClusters() -{ - int i; - - for( i=0;im_im==0) - { - c.m_containsAnchor = true; - c.m_masses[j] = BT_LARGE_FLOAT; - } else - { - c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im; - } - c.m_imass += c.m_masses[j]; - } - c.m_imass = btScalar(1.)/c.m_imass; - c.m_com = btSoftBody::clusterCom(&c); - c.m_lv = btVector3(0,0,0); - c.m_av = btVector3(0,0,0); - c.m_leaf = 0; - /* Inertia */ - btMatrix3x3& ii=c.m_locii; - ii[0]=ii[1]=ii[2]=btVector3(0,0,0); - { - int i,ni; - - for(i=0,ni=c.m_nodes.size();im_x-c.m_com; - const btVector3 q=k*k; - const btScalar m=c.m_masses[i]; - ii[0][0] += m*(q[1]+q[2]); - ii[1][1] += m*(q[0]+q[2]); - ii[2][2] += m*(q[0]+q[1]); - ii[0][1] -= m*k[0]*k[1]; - ii[0][2] -= m*k[0]*k[2]; - ii[1][2] -= m*k[1]*k[2]; - } - } - ii[1][0]=ii[0][1]; - ii[2][0]=ii[0][2]; - ii[2][1]=ii[1][2]; - - ii = ii.inverse(); - - /* Frame */ - c.m_framexform.setIdentity(); - c.m_framexform.setOrigin(c.m_com); - c.m_framerefs.resize(c.m_nodes.size()); - { - int i; - for(i=0;im_x-c.m_com; - } - } - } -} - -// -void btSoftBody::updateClusters() -{ - BT_PROFILE("UpdateClusters"); - int i; - - for(i=0;im_x-c.m_com; - const btVector3& b=c.m_framerefs[i]; - m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b; - } - PolarDecompose(m,r,s); - c.m_framexform.setOrigin(c.m_com); - c.m_framexform.setBasis(r); - /* Inertia */ -#if 1/* Constant */ - c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose(); -#else -#if 0/* Sphere */ - const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass); - const btVector3 inertia(rk,rk,rk); - const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0, - btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0, - btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0); - - c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose(); -#else/* Actual */ - c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0); - for(int i=0;im_x-c.m_com; - const btVector3 q=k*k; - const btScalar m=1/c.m_nodes[i]->m_im; - c.m_invwi[0][0] += m*(q[1]+q[2]); - c.m_invwi[1][1] += m*(q[0]+q[2]); - c.m_invwi[2][2] += m*(q[0]+q[1]); - c.m_invwi[0][1] -= m*k[0]*k[1]; - c.m_invwi[0][2] -= m*k[0]*k[2]; - c.m_invwi[1][2] -= m*k[1]*k[2]; - } - c.m_invwi[1][0]=c.m_invwi[0][1]; - c.m_invwi[2][0]=c.m_invwi[0][2]; - c.m_invwi[2][1]=c.m_invwi[1][2]; - c.m_invwi=c.m_invwi.inverse(); -#endif -#endif - /* Velocities */ - c.m_lv=btVector3(0,0,0); - c.m_av=btVector3(0,0,0); - { - int i; - - for(i=0;im_v*c.m_masses[i]; - c.m_lv += v; - c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v); - } - } - c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping); - c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping); - c.m_vimpulses[0] = - c.m_vimpulses[1] = btVector3(0,0,0); - c.m_dimpulses[0] = - c.m_dimpulses[1] = btVector3(0,0,0); - c.m_nvimpulses = 0; - c.m_ndimpulses = 0; - /* Matching */ - if(c.m_matching>0) - { - for(int j=0;jm_x; - btVector3 mx=mi; - for(int j=1;jm_x); - mx.setMax(c.m_nodes[j]->m_x); - } - ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); - if(c.m_leaf) - m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); - else - c.m_leaf=m_cdbvt.insert(bounds,&c); - } - } - } - - -} - - - - -// -void btSoftBody::cleanupClusters() -{ - for(int i=0;iTerminate(m_sst.sdt); - if(m_joints[i]->m_delete) - { - btAlignedFree(m_joints[i]); - m_joints.remove(m_joints[i--]); - } - } -} - -// -void btSoftBody::prepareClusters(int iterations) -{ - for(int i=0;iPrepare(m_sst.sdt,iterations); - } -} - - -// -void btSoftBody::solveClusters(btScalar sor) -{ - for(int i=0,ni=m_joints.size();iSolve(m_sst.sdt,sor); - } -} - -// -void btSoftBody::applyClusters(bool drift) -{ - BT_PROFILE("ApplyClusters"); -// const btScalar f0=m_sst.sdt; - //const btScalar f1=f0/2; - btAlignedObjectArray deltas; - btAlignedObjectArray weights; - deltas.resize(m_nodes.size(),btVector3(0,0,0)); - weights.resize(m_nodes.size(),0); - int i; - - if(drift) - { - for(i=0;im_x; - const btScalar q=c.m_masses[j]; - deltas[idx] += (v+btCross(w,x-c.m_com))*q; - weights[idx] += q; - } - } - } - for(i=0;i0) - { - m_nodes[i].m_x+=deltas[i]/weights[i]; - } - } -} - -// -void btSoftBody::dampClusters() -{ - int i; - - for(i=0;i0) - { - for(int j=0;j0) - { - const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com); - if(vx.length2()<=n.m_v.length2()) - { - n.m_v += c.m_ndamping*(vx-n.m_v); - } - } - } - } - } -} - -// -void btSoftBody::Joint::Prepare(btScalar dt,int) -{ - m_bodies[0].activate(); - m_bodies[1].activate(); -} - -// -void btSoftBody::LJoint::Prepare(btScalar dt,int iterations) -{ - static const btScalar maxdrift=4; - Joint::Prepare(dt,iterations); - m_rpos[0] = m_bodies[0].xform()*m_refs[0]; - m_rpos[1] = m_bodies[1].xform()*m_refs[1]; - m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt; - m_rpos[0] -= m_bodies[0].xform().getOrigin(); - m_rpos[1] -= m_bodies[1].xform().getOrigin(); - m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0], - m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]); - if(m_split>0) - { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; - } - m_drift /=(btScalar)iterations; -} - -// -void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor) -{ - const btVector3 va=m_bodies[0].velocity(m_rpos[0]); - const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); - const btVector3 vr=va-vb; - btSoftBody::Impulse impulse; - impulse.m_asVelocity = 1; - impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor; - m_bodies[0].applyImpulse(-impulse,m_rpos[0]); - m_bodies[1].applyImpulse( impulse,m_rpos[1]); -} - -// -void btSoftBody::LJoint::Terminate(btScalar dt) -{ - if(m_split>0) - { - m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); - m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); - } -} - -// -void btSoftBody::AJoint::Prepare(btScalar dt,int iterations) -{ - static const btScalar maxdrift=SIMD_PI/16; - m_icontrol->Prepare(this); - Joint::Prepare(dt,iterations); - m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0]; - m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1]; - m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0])); - m_drift *= btMin(maxdrift,btAcos(Clamp(btDot(m_axis[0],m_axis[1]),-1,+1))); - m_drift *= m_erp/dt; - m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia()); - if(m_split>0) - { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; - } - m_drift /=(btScalar)iterations; -} - -// -void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor) -{ - const btVector3 va=m_bodies[0].angularVelocity(); - const btVector3 vb=m_bodies[1].angularVelocity(); - const btVector3 vr=va-vb; - const btScalar sp=btDot(vr,m_axis[0]); - const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp); - btSoftBody::Impulse impulse; - impulse.m_asVelocity = 1; - impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor; - m_bodies[0].applyAImpulse(-impulse); - m_bodies[1].applyAImpulse( impulse); -} - -// -void btSoftBody::AJoint::Terminate(btScalar dt) -{ - if(m_split>0) - { - m_bodies[0].applyDAImpulse(-m_sdrift); - m_bodies[1].applyDAImpulse( m_sdrift); - } -} - -// -void btSoftBody::CJoint::Prepare(btScalar dt,int iterations) -{ - Joint::Prepare(dt,iterations); - const bool dodrift=(m_life==0); - m_delete=(++m_life)>m_maxlife; - if(dodrift) - { - m_drift=m_drift*m_erp/dt; - if(m_split>0) - { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; - } - m_drift/=(btScalar)iterations; - } - else - { - m_drift=m_sdrift=btVector3(0,0,0); - } -} - -// -void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor) -{ - const btVector3 va=m_bodies[0].velocity(m_rpos[0]); - const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); - const btVector3 vrel=va-vb; - const btScalar rvac=btDot(vrel,m_normal); - btSoftBody::Impulse impulse; - impulse.m_asVelocity = 1; - impulse.m_velocity = m_drift; - if(rvac<0) - { - const btVector3 iv=m_normal*rvac; - const btVector3 fv=vrel-iv; - impulse.m_velocity += iv+fv*m_friction; - } - impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor; - - if (m_bodies[0].m_soft==m_bodies[1].m_soft) - { - if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&& - (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ())) - { - if (impulse.m_asVelocity) - { - if (impulse.m_velocity.length() m_maxSelfCollisionImpulse) - { - - } else - { - m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]); - m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]); - } - } - } - } else - { - m_bodies[0].applyImpulse(-impulse,m_rpos[0]); - m_bodies[1].applyImpulse( impulse,m_rpos[1]); - } -} - -// -void btSoftBody::CJoint::Terminate(btScalar dt) -{ - if(m_split>0) - { - m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); - m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); - } -} - -// -void btSoftBody::applyForces() -{ - - BT_PROFILE("SoftBody applyForces"); -// const btScalar dt = m_sst.sdt; - const btScalar kLF = m_cfg.kLF; - const btScalar kDG = m_cfg.kDG; - const btScalar kPR = m_cfg.kPR; - const btScalar kVC = m_cfg.kVC; - const bool as_lift = kLF>0; - const bool as_drag = kDG>0; - const bool as_pressure = kPR!=0; - const bool as_volume = kVC>0; - const bool as_aero = as_lift || - as_drag ; - //const bool as_vaero = as_aero && - // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); - //const bool as_faero = as_aero && - // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); - const bool use_medium = as_aero; - const bool use_volume = as_pressure || - as_volume ; - btScalar volume = 0; - btScalar ivolumetp = 0; - btScalar dvolumetv = 0; - btSoftBody::sMedium medium; - if(use_volume) - { - volume = getVolume(); - ivolumetp = 1/btFabs(volume)*kPR; - dvolumetv = (m_pose.m_volume-volume)*kVC; - } - /* Per vertex forces */ - int i,ni; - - for(i=0,ni=m_nodes.size();i0) - { - if(use_medium) - { - /* Aerodynamics */ - addAeroForceToNode(m_windVelocity, i); - } - /* Pressure */ - if(as_pressure) - { - n.m_f += n.m_n*(n.m_area*ivolumetp); - } - /* Volume */ - if(as_volume) - { - n.m_f += n.m_n*(n.m_area*dvolumetv); - } - } - } - - /* Per face forces */ - for(i=0,ni=m_faces.size();im_cfg.kAHR*kst; - const btScalar dt=psb->m_sst.sdt; - for(int i=0,ni=psb->m_anchors.size();im_anchors[i]; - const btTransform& t=a.m_body->getWorldTransform(); - Node& n=*a.m_node; - const btVector3 wa=t*a.m_local; - const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; - const btVector3 vb=n.m_x-n.m_q; - const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; - const btVector3 impulse=a.m_c0*vr*a.m_influence; - n.m_x+=impulse*a.m_c2; - a.m_body->applyImpulse(-impulse,a.m_c1); - } -} - -// -void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti) -{ - const btScalar dt = psb->m_sst.sdt; - const btScalar mrg = psb->getCollisionShape()->getMargin(); - for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; - const sCti& cti = c.m_cti; - btRigidBody* tmpRigid = (btRigidBody*)btRigidBody::upcast(cti.m_colObj); - - const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); - const btVector3 vb = c.m_node->m_x-c.m_node->m_q; - const btVector3 vr = vb-va; - const btScalar dn = btDot(vr, cti.m_normal); - if(dn<=SIMD_EPSILON) - { - const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg ); - const btVector3 fv = vr - (cti.m_normal * dn); - // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient - const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst ); - c.m_node->m_x -= impulse * c.m_c2; - if (tmpRigid) - tmpRigid->applyImpulse(impulse,c.m_c1); - } - } -} - -// -void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) -{ - for(int i=0,ni=psb->m_scontacts.size();im_scontacts[i]; - const btVector3& nr=c.m_normal; - Node& n=*c.m_node; - Face& f=*c.m_face; - const btVector3 p=BaryEval( f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x, - c.m_weights); - const btVector3 q=BaryEval( f.m_n[0]->m_q, - f.m_n[1]->m_q, - f.m_n[2]->m_q, - c.m_weights); - const btVector3 vr=(n.m_x-n.m_q)-(p-q); - btVector3 corr(0,0,0); - btScalar dot = btDot(vr,nr); - if(dot<0) - { - const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p)); - corr+=c.m_normal*j; - } - corr -= ProjectOnPlane(vr,nr)*c.m_friction; - n.m_x += corr*c.m_cfm[0]; - f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x()); - f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y()); - f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z()); - } -} - -// -void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) -{ - for(int i=0,ni=psb->m_links.size();im_links[i]; - if(l.m_c0>0) - { - Node& a=*l.m_n[0]; - Node& b=*l.m_n[1]; - const btVector3 del=b.m_x-a.m_x; - const btScalar len=del.length2(); - if (l.m_c1+len > SIMD_EPSILON) - { - const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst; - a.m_x-=del*(k*a.m_im); - b.m_x+=del*(k*b.m_im); - } - } - } -} - -// -void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) -{ - for(int i=0,ni=psb->m_links.size();im_links[i]; - Node** n=l.m_n; - const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst; - n[0]->m_v+= l.m_c3*(j*n[0]->m_im); - n[1]->m_v-= l.m_c3*(j*n[1]->m_im); - } -} - -// -btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver) -{ - switch(solver) - { - case ePSolver::Anchors: - return(&btSoftBody::PSolve_Anchors); - case ePSolver::Linear: - return(&btSoftBody::PSolve_Links); - case ePSolver::RContacts: - return(&btSoftBody::PSolve_RContacts); - case ePSolver::SContacts: - return(&btSoftBody::PSolve_SContacts); - default: - { - } - } - return(0); -} - -// -btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) -{ - switch(solver) - { - case eVSolver::Linear: return(&btSoftBody::VSolve_Links); - default: - { - } - } - return(0); -} - -// -void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap) -{ - - switch(m_cfg.collisions&fCollision::RVSmask) - { - case fCollision::SDF_RS: - { - btSoftColliders::CollideSDF_RS docollide; - btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject()); - btTransform wtr=pcoWrap->getWorldTransform(); - - const btTransform ctr=pcoWrap->getWorldTransform(); - const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length(); - const btScalar basemargin=getCollisionShape()->getMargin(); - btVector3 mins; - btVector3 maxs; - ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; - pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(), - mins, - maxs); - volume=btDbvtVolume::FromMM(mins,maxs); - volume.Expand(btVector3(basemargin,basemargin,basemargin)); - docollide.psb = this; - docollide.m_colObj1Wrap = pcoWrap; - docollide.m_rigidBody = prb1; - - docollide.dynmargin = basemargin+timemargin; - docollide.stamargin = basemargin; - m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide); - } - break; - case fCollision::CL_RS: - { - btSoftColliders::CollideCL_RS collider; - collider.ProcessColObj(this,pcoWrap); - } - break; - } -} - -// -void btSoftBody::defaultCollisionHandler(btSoftBody* psb) -{ - const int cf=m_cfg.collisions&psb->m_cfg.collisions; - switch(cf&fCollision::SVSmask) - { - case fCollision::CL_SS: - { - - //support self-collision if CL_SELF flag set - if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF) - { - btSoftColliders::CollideCL_SS docollide; - docollide.ProcessSoftSoft(this,psb); - } - - } - break; - case fCollision::VF_SS: - { - //only self-collision for Cluster, not Vertex-Face yet - if (this!=psb) - { - btSoftColliders::CollideVF_SS docollide; - /* common */ - docollide.mrg= getCollisionShape()->getMargin()+ - psb->getCollisionShape()->getMargin(); - /* psb0 nodes vs psb1 faces */ - docollide.psb[0]=this; - docollide.psb[1]=psb; - docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, - docollide.psb[1]->m_fdbvt.m_root, - docollide); - /* psb1 nodes vs psb0 faces */ - docollide.psb[0]=psb; - docollide.psb[1]=this; - docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root, - docollide.psb[1]->m_fdbvt.m_root, - docollide); - } - } - break; - default: - { - - } - } -} - - - -void btSoftBody::setWindVelocity( const btVector3 &velocity ) -{ - m_windVelocity = velocity; -} - - -const btVector3& btSoftBody::getWindVelocity() -{ - return m_windVelocity; -} - - - -int btSoftBody::calculateSerializeBufferSize() const -{ - int sz = sizeof(btSoftBodyData); - return sz; -} - - ///fills the dataBuffer and returns the struct name (and 0 on failure) -const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const -{ - btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer; - - btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer); - - btHashMap m_nodeIndexMap; - - sbd->m_numMaterials = m_materials.size(); - sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0; - - if (sbd->m_materials) - { - int sz = sizeof(SoftBodyMaterialData*); - int numElem = sbd->m_numMaterials; - btChunk* chunk = serializer->allocate(sz,numElem); - //SoftBodyMaterialData** memPtr = chunk->m_oldPtr; - SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr; - for (int i=0;igetUniquePointer((void*)mat) : 0; - if (!serializer->findPointer(mat)) - { - //serialize it here - btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1); - SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr; - memPtr->m_flags = mat->m_flags; - memPtr->m_angularStiffness = mat->m_kAST; - memPtr->m_linearStiffness = mat->m_kLST; - memPtr->m_volumeStiffness = mat->m_kVST; - serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat); - } - } - serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials); - } - - - - - sbd->m_numNodes = m_nodes.size(); - sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0; - if (sbd->m_nodes) - { - int sz = sizeof(SoftBodyNodeData); - int numElem = sbd->m_numNodes; - btChunk* chunk = serializer->allocate(sz,numElem); - SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr; - for (int i=0;im_accumulatedForce); - memPtr->m_area = m_nodes[i].m_area; - memPtr->m_attach = m_nodes[i].m_battach; - memPtr->m_inverseMass = m_nodes[i].m_im; - memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0; - m_nodes[i].m_n.serializeFloat(memPtr->m_normal); - m_nodes[i].m_x.serializeFloat(memPtr->m_position); - m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition); - m_nodes[i].m_v.serializeFloat(memPtr->m_velocity); - m_nodeIndexMap.insert(&m_nodes[i],i); - } - serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes); - } - - sbd->m_numLinks = m_links.size(); - sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0; - if (sbd->m_links) - { - int sz = sizeof(SoftBodyLinkData); - int numElem = sbd->m_numLinks; - btChunk* chunk = serializer->allocate(sz,numElem); - SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr; - for (int i=0;im_bbending = m_links[i].m_bbending; - memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0; - memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1; - memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1; - btAssert(memPtr->m_nodeIndices[0]m_nodeIndices[1]m_restLength = m_links[i].m_rl; - } - serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]); - - } - - - sbd->m_numFaces = m_faces.size(); - sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0; - if (sbd->m_faces) - { - int sz = sizeof(SoftBodyFaceData); - int numElem = sbd->m_numFaces; - btChunk* chunk = serializer->allocate(sz,numElem); - SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr; - for (int i=0;im_material = m_faces[i].m_material ? (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0; - m_faces[i].m_normal.serializeFloat( memPtr->m_normal); - for (int j=0;j<3;j++) - { - memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1; - } - memPtr->m_restArea = m_faces[i].m_ra; - } - serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]); - } - - - sbd->m_numTetrahedra = m_tetras.size(); - sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0; - if (sbd->m_tetrahedra) - { - int sz = sizeof(SoftBodyTetraData); - int numElem = sbd->m_numTetrahedra; - btChunk* chunk = serializer->allocate(sz,numElem); - SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr; - for (int i=0;im_c0[j] ); - memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1; - } - memPtr->m_c1 = m_tetras[i].m_c1; - memPtr->m_c2 = m_tetras[i].m_c2; - memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0; - memPtr->m_restVolume = m_tetras[i].m_rv; - } - serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]); - } - - sbd->m_numAnchors = m_anchors.size(); - sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0; - if (sbd->m_anchors) - { - int sz = sizeof(SoftRigidAnchorData); - int numElem = sbd->m_numAnchors; - btChunk* chunk = serializer->allocate(sz,numElem); - SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr; - for (int i=0;im_c0); - m_anchors[i].m_c1.serializeFloat(memPtr->m_c1); - memPtr->m_c2 = m_anchors[i].m_c2; - m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame); - memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1; - - memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*) serializer->getUniquePointer((void*)m_anchors[i].m_body): 0; - btAssert(memPtr->m_nodeIndex < m_nodes.size()); - } - serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]); - } - - - sbd->m_config.m_dynamicFriction = m_cfg.kDF; - sbd->m_config.m_baumgarte = m_cfg.kVCF; - sbd->m_config.m_pressure = m_cfg.kPR; - sbd->m_config.m_aeroModel = this->m_cfg.aeromodel; - sbd->m_config.m_lift = m_cfg.kLF; - sbd->m_config.m_drag = m_cfg.kDG; - sbd->m_config.m_positionIterations = m_cfg.piterations; - sbd->m_config.m_driftIterations = m_cfg.diterations; - sbd->m_config.m_clusterIterations = m_cfg.citerations; - sbd->m_config.m_velocityIterations = m_cfg.viterations; - sbd->m_config.m_maxVolume = m_cfg.maxvolume; - sbd->m_config.m_damping = m_cfg.kDP; - sbd->m_config.m_poseMatch = m_cfg.kMT; - sbd->m_config.m_collisionFlags = m_cfg.collisions; - sbd->m_config.m_volume = m_cfg.kVC; - sbd->m_config.m_rigidContactHardness = m_cfg.kCHR; - sbd->m_config.m_kineticContactHardness = m_cfg.kKHR; - sbd->m_config.m_softContactHardness = m_cfg.kSHR; - sbd->m_config.m_anchorHardness = m_cfg.kAHR; - sbd->m_config.m_timeScale = m_cfg.timescale; - sbd->m_config.m_maxVolume = m_cfg.maxvolume; - sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL; - sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL; - sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL; - sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL; - sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL; - sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL; - - //pose for shape matching - { - sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose); - - int sz = sizeof(SoftBodyPoseData); - btChunk* chunk = serializer->allocate(sz,1); - SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr; - - m_pose.m_aqq.serializeFloat(memPtr->m_aqq); - memPtr->m_bframe = m_pose.m_bframe; - memPtr->m_bvolume = m_pose.m_bvolume; - m_pose.m_com.serializeFloat(memPtr->m_com); - - memPtr->m_numPositions = m_pose.m_pos.size(); - memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0; - if (memPtr->m_numPositions) - { - int numElem = memPtr->m_numPositions; - int sz = sizeof(btVector3Data); - btChunk* chunk = serializer->allocate(sz,numElem); - btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr; - for (int i=0;ifinalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]); - } - memPtr->m_restVolume = m_pose.m_volume; - m_pose.m_rot.serializeFloat(memPtr->m_rot); - m_pose.m_scl.serializeFloat(memPtr->m_scale); - - memPtr->m_numWeigts = m_pose.m_wgh.size(); - memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0; - if (memPtr->m_numWeigts) - { - - int numElem = memPtr->m_numWeigts; - int sz = sizeof(float); - btChunk* chunk = serializer->allocate(sz,numElem); - float* memPtr = (float*) chunk->m_oldPtr; - for (int i=0;ifinalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]); - } - - serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose); - } - - //clusters for convex-cluster collision detection - - sbd->m_numClusters = m_clusters.size(); - sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0; - if (sbd->m_numClusters) - { - int numElem = sbd->m_numClusters; - int sz = sizeof(SoftBodyClusterData); - btChunk* chunk = serializer->allocate(sz,numElem); - SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr; - for (int i=0;im_adamping= m_clusters[i]->m_adamping; - m_clusters[i]->m_av.serializeFloat(memPtr->m_av); - memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex; - memPtr->m_collide = m_clusters[i]->m_collide; - m_clusters[i]->m_com.serializeFloat(memPtr->m_com); - memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor; - m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]); - m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]); - m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform); - memPtr->m_idmass = m_clusters[i]->m_idmass; - memPtr->m_imass = m_clusters[i]->m_imass; - m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi); - memPtr->m_ldamping = m_clusters[i]->m_ldamping; - m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii); - m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv); - memPtr->m_matching = m_clusters[i]->m_matching; - memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse; - memPtr->m_ndamping = m_clusters[i]->m_ndamping; - memPtr->m_ldamping = m_clusters[i]->m_ldamping; - memPtr->m_adamping = m_clusters[i]->m_adamping; - memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor; - - memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size(); - memPtr->m_numMasses = m_clusters[i]->m_masses.size(); - memPtr->m_numNodes = m_clusters[i]->m_nodes.size(); - - memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses; - m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]); - m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]); - memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses; - - - - memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0; - if (memPtr->m_framerefs) - { - int numElem = memPtr->m_numFrameRefs; - int sz = sizeof(btVector3FloatData); - btChunk* chunk = serializer->allocate(sz,numElem); - btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr; - for (int j=0;jm_framerefs[j].serializeFloat(*memPtr); - } - serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]); - } - - memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0; - if (memPtr->m_masses) - { - int numElem = memPtr->m_numMasses; - int sz = sizeof(float); - btChunk* chunk = serializer->allocate(sz,numElem); - float* memPtr = (float*) chunk->m_oldPtr; - for (int j=0;jm_masses[j]; - } - serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]); - } - - memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0; - if (memPtr->m_nodeIndices ) - { - int numElem = memPtr->m_numMasses; - int sz = sizeof(int); - btChunk* chunk = serializer->allocate(sz,numElem); - int* memPtr = (int*) chunk->m_oldPtr; - for (int j=0;jm_nodes[j]); - btAssert(indexPtr); - *memPtr = *indexPtr; - } - serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes); - } - } - serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]); - - } - - - - sbd->m_numJoints = m_joints.size(); - sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0; - - if (sbd->m_joints) - { - int sz = sizeof(btSoftBodyJointData); - int numElem = m_joints.size(); - btChunk* chunk = serializer->allocate(sz,numElem); - btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr; - - for (int i=0;im_jointType = (int)m_joints[i]->Type(); - m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]); - m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]); - memPtr->m_cfm = m_joints[i]->m_cfm; - memPtr->m_erp = m_joints[i]->m_erp; - memPtr->m_split = m_joints[i]->m_split; - memPtr->m_delete = m_joints[i]->m_delete; - - for (int j=0;j<4;j++) - { - memPtr->m_relPosition[0].m_floats[j] = 0.f; - memPtr->m_relPosition[1].m_floats[j] = 0.f; - } - memPtr->m_bodyA = 0; - memPtr->m_bodyB = 0; - if (m_joints[i]->m_bodies[0].m_soft) - { - memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER; - memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft); - } - if (m_joints[i]->m_bodies[0].m_collisionObject) - { - memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT; - memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject); - } - if (m_joints[i]->m_bodies[0].m_rigid) - { - memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY; - memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid); - } - - if (m_joints[i]->m_bodies[1].m_soft) - { - memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER; - memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft); - } - if (m_joints[i]->m_bodies[1].m_collisionObject) - { - memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT; - memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject); - } - if (m_joints[i]->m_bodies[1].m_rigid) - { - memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY; - memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid); - } - } - serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]); - } - - - return btSoftBodyDataName; -} - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.h deleted file mode 100644 index ee1a3d95..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBody.h +++ /dev/null @@ -1,1000 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBody implementation by Nathanael Presson - -#ifndef _BT_SOFT_BODY_H -#define _BT_SOFT_BODY_H - -#include "LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btIDebugDraw.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" - -#include "BulletCollision/CollisionShapes/btConcaveShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -#include "btSparseSDF.h" -#include "BulletCollision/BroadphaseCollision/btDbvt.h" - -//#ifdef BT_USE_DOUBLE_PRECISION -//#define btRigidBodyData btRigidBodyDoubleData -//#define btRigidBodyDataName "btRigidBodyDoubleData" -//#else -#define btSoftBodyData btSoftBodyFloatData -#define btSoftBodyDataName "btSoftBodyFloatData" -//#endif //BT_USE_DOUBLE_PRECISION - -class btBroadphaseInterface; -class btDispatcher; -class btSoftBodySolver; - -/* btSoftBodyWorldInfo */ -struct btSoftBodyWorldInfo -{ - btScalar air_density; - btScalar water_density; - btScalar water_offset; - btScalar m_maxDisplacement; - btVector3 water_normal; - btBroadphaseInterface* m_broadphase; - btDispatcher* m_dispatcher; - btVector3 m_gravity; - btSparseSdf<3> m_sparsesdf; - - btSoftBodyWorldInfo() - :air_density((btScalar)1.2), - water_density(0), - water_offset(0), - m_maxDisplacement(1000.f),//avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame - water_normal(0,0,0), - m_broadphase(0), - m_dispatcher(0), - m_gravity(0,-10,0) - { - } -}; - - -///The btSoftBody is an class to simulate cloth and volumetric soft bodies. -///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject. -class btSoftBody : public btCollisionObject -{ -public: - btAlignedObjectArray m_collisionDisabledObjects; - - // The solver object that handles this soft body - btSoftBodySolver *m_softBodySolver; - - // - // Enumerations - // - - ///eAeroModel - struct eAeroModel { enum _ { - V_Point, ///Vertex normals are oriented toward velocity - V_TwoSided, ///Vertex normals are flipped to match velocity - V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied - V_OneSided, ///Vertex normals are taken as it is - F_TwoSided, ///Face normals are flipped to match velocity - F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied - F_OneSided, ///Face normals are taken as it is - END - };}; - - ///eVSolver : velocities solvers - struct eVSolver { enum _ { - Linear, ///Linear solver - END - };}; - - ///ePSolver : positions solvers - struct ePSolver { enum _ { - Linear, ///Linear solver - Anchors, ///Anchor solver - RContacts, ///Rigid contacts solver - SContacts, ///Soft contacts solver - END - };}; - - ///eSolverPresets - struct eSolverPresets { enum _ { - Positions, - Velocities, - Default = Positions, - END - };}; - - ///eFeature - struct eFeature { enum _ { - None, - Node, - Link, - Face, - Tetra, - END - };}; - - typedef btAlignedObjectArray tVSolverArray; - typedef btAlignedObjectArray tPSolverArray; - - // - // Flags - // - - ///fCollision - struct fCollision { enum _ { - RVSmask = 0x000f, ///Rigid versus soft mask - SDF_RS = 0x0001, ///SDF based rigid vs soft - CL_RS = 0x0002, ///Cluster vs convex rigid vs soft - - SVSmask = 0x0030, ///Rigid versus soft mask - VF_SS = 0x0010, ///Vertex vs face soft vs soft handling - CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling - CL_SELF = 0x0040, ///Cluster soft body self collision - /* presets */ - Default = SDF_RS, - END - };}; - - ///fMaterial - struct fMaterial { enum _ { - DebugDraw = 0x0001, /// Enable debug draw - /* presets */ - Default = DebugDraw, - END - };}; - - // - // API Types - // - - /* sRayCast */ - struct sRayCast - { - btSoftBody* body; /// soft body - eFeature::_ feature; /// feature type - int index; /// feature index - btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction) - }; - - /* ImplicitFn */ - struct ImplicitFn - { - virtual btScalar Eval(const btVector3& x)=0; - }; - - // - // Internal types - // - - typedef btAlignedObjectArray tScalarArray; - typedef btAlignedObjectArray tVector3Array; - - /* sCti is Softbody contact info */ - struct sCti - { - const btCollisionObject* m_colObj; /* Rigid body */ - btVector3 m_normal; /* Outward normal */ - btScalar m_offset; /* Offset from origin */ - }; - - /* sMedium */ - struct sMedium - { - btVector3 m_velocity; /* Velocity */ - btScalar m_pressure; /* Pressure */ - btScalar m_density; /* Density */ - }; - - /* Base type */ - struct Element - { - void* m_tag; // User data - Element() : m_tag(0) {} - }; - /* Material */ - struct Material : Element - { - btScalar m_kLST; // Linear stiffness coefficient [0,1] - btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] - btScalar m_kVST; // Volume stiffness coefficient [0,1] - int m_flags; // Flags - }; - - /* Feature */ - struct Feature : Element - { - Material* m_material; // Material - }; - /* Node */ - struct Node : Feature - { - btVector3 m_x; // Position - btVector3 m_q; // Previous step position - btVector3 m_v; // Velocity - btVector3 m_f; // Force accumulator - btVector3 m_n; // Normal - btScalar m_im; // 1/mass - btScalar m_area; // Area - btDbvtNode* m_leaf; // Leaf data - int m_battach:1; // Attached - }; - /* Link */ - struct Link : Feature - { - Node* m_n[2]; // Node pointers - btScalar m_rl; // Rest length - int m_bbending:1; // Bending link - btScalar m_c0; // (ima+imb)*kLST - btScalar m_c1; // rl^2 - btScalar m_c2; // |gradient|^2/c0 - btVector3 m_c3; // gradient - }; - /* Face */ - struct Face : Feature - { - Node* m_n[3]; // Node pointers - btVector3 m_normal; // Normal - btScalar m_ra; // Rest area - btDbvtNode* m_leaf; // Leaf data - }; - /* Tetra */ - struct Tetra : Feature - { - Node* m_n[4]; // Node pointers - btScalar m_rv; // Rest volume - btDbvtNode* m_leaf; // Leaf data - btVector3 m_c0[4]; // gradients - btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3) - btScalar m_c2; // m_c1/sum(|g0..3|^2) - }; - /* RContact */ - struct RContact - { - sCti m_cti; // Contact infos - Node* m_node; // Owner node - btMatrix3x3 m_c0; // Impulse matrix - btVector3 m_c1; // Relative anchor - btScalar m_c2; // ima*dt - btScalar m_c3; // Friction - btScalar m_c4; // Hardness - }; - /* SContact */ - struct SContact - { - Node* m_node; // Node - Face* m_face; // Face - btVector3 m_weights; // Weigths - btVector3 m_normal; // Normal - btScalar m_margin; // Margin - btScalar m_friction; // Friction - btScalar m_cfm[2]; // Constraint force mixing - }; - /* Anchor */ - struct Anchor - { - Node* m_node; // Node pointer - btVector3 m_local; // Anchor position in body space - btRigidBody* m_body; // Body - btScalar m_influence; - btMatrix3x3 m_c0; // Impulse matrix - btVector3 m_c1; // Relative anchor - btScalar m_c2; // ima*dt - }; - /* Note */ - struct Note : Element - { - const char* m_text; // Text - btVector3 m_offset; // Offset - int m_rank; // Rank - Node* m_nodes[4]; // Nodes - btScalar m_coords[4]; // Coordinates - }; - /* Pose */ - struct Pose - { - bool m_bvolume; // Is valid - bool m_bframe; // Is frame - btScalar m_volume; // Rest volume - tVector3Array m_pos; // Reference positions - tScalarArray m_wgh; // Weights - btVector3 m_com; // COM - btMatrix3x3 m_rot; // Rotation - btMatrix3x3 m_scl; // Scale - btMatrix3x3 m_aqq; // Base scaling - }; - /* Cluster */ - struct Cluster - { - tScalarArray m_masses; - btAlignedObjectArray m_nodes; - tVector3Array m_framerefs; - btTransform m_framexform; - btScalar m_idmass; - btScalar m_imass; - btMatrix3x3 m_locii; - btMatrix3x3 m_invwi; - btVector3 m_com; - btVector3 m_vimpulses[2]; - btVector3 m_dimpulses[2]; - int m_nvimpulses; - int m_ndimpulses; - btVector3 m_lv; - btVector3 m_av; - btDbvtNode* m_leaf; - btScalar m_ndamping; /* Node damping */ - btScalar m_ldamping; /* Linear damping */ - btScalar m_adamping; /* Angular damping */ - btScalar m_matching; - btScalar m_maxSelfCollisionImpulse; - btScalar m_selfCollisionImpulseFactor; - bool m_containsAnchor; - bool m_collide; - int m_clusterIndex; - Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) - ,m_maxSelfCollisionImpulse(100.f), - m_selfCollisionImpulseFactor(0.01f), - m_containsAnchor(false) - {} - }; - /* Impulse */ - struct Impulse - { - btVector3 m_velocity; - btVector3 m_drift; - int m_asVelocity:1; - int m_asDrift:1; - Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} - Impulse operator -() const - { - Impulse i=*this; - i.m_velocity=-i.m_velocity; - i.m_drift=-i.m_drift; - return(i); - } - Impulse operator*(btScalar x) const - { - Impulse i=*this; - i.m_velocity*=x; - i.m_drift*=x; - return(i); - } - }; - /* Body */ - struct Body - { - Cluster* m_soft; - btRigidBody* m_rigid; - const btCollisionObject* m_collisionObject; - - Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {} - Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {} - Body(const btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj) - { - m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject); - } - - void activate() const - { - if(m_rigid) - m_rigid->activate(); - if (m_collisionObject) - m_collisionObject->activate(); - - } - const btMatrix3x3& invWorldInertia() const - { - static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); - if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); - if(m_soft) return(m_soft->m_invwi); - return(iwi); - } - btScalar invMass() const - { - if(m_rigid) return(m_rigid->getInvMass()); - if(m_soft) return(m_soft->m_imass); - return(0); - } - const btTransform& xform() const - { - static const btTransform identity=btTransform::getIdentity(); - if(m_collisionObject) return(m_collisionObject->getWorldTransform()); - if(m_soft) return(m_soft->m_framexform); - return(identity); - } - btVector3 linearVelocity() const - { - if(m_rigid) return(m_rigid->getLinearVelocity()); - if(m_soft) return(m_soft->m_lv); - return(btVector3(0,0,0)); - } - btVector3 angularVelocity(const btVector3& rpos) const - { - if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos)); - if(m_soft) return(btCross(m_soft->m_av,rpos)); - return(btVector3(0,0,0)); - } - btVector3 angularVelocity() const - { - if(m_rigid) return(m_rigid->getAngularVelocity()); - if(m_soft) return(m_soft->m_av); - return(btVector3(0,0,0)); - } - btVector3 velocity(const btVector3& rpos) const - { - return(linearVelocity()+angularVelocity(rpos)); - } - void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const - { - if(m_rigid) m_rigid->applyImpulse(impulse,rpos); - if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); - } - void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const - { - if(m_rigid) m_rigid->applyImpulse(impulse,rpos); - if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); - } - void applyImpulse(const Impulse& impulse,const btVector3& rpos) const - { - if(impulse.m_asVelocity) - { -// printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ()); - applyVImpulse(impulse.m_velocity,rpos); - } - if(impulse.m_asDrift) - { -// printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ()); - applyDImpulse(impulse.m_drift,rpos); - } - } - void applyVAImpulse(const btVector3& impulse) const - { - if(m_rigid) m_rigid->applyTorqueImpulse(impulse); - if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); - } - void applyDAImpulse(const btVector3& impulse) const - { - if(m_rigid) m_rigid->applyTorqueImpulse(impulse); - if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); - } - void applyAImpulse(const Impulse& impulse) const - { - if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); - if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); - } - void applyDCImpulse(const btVector3& impulse) const - { - if(m_rigid) m_rigid->applyCentralImpulse(impulse); - if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); - } - }; - /* Joint */ - struct Joint - { - struct eType { enum _ { - Linear=0, - Angular, - Contact - };}; - struct Specs - { - Specs() : erp(1),cfm(1),split(1) {} - btScalar erp; - btScalar cfm; - btScalar split; - }; - Body m_bodies[2]; - btVector3 m_refs[2]; - btScalar m_cfm; - btScalar m_erp; - btScalar m_split; - btVector3 m_drift; - btVector3 m_sdrift; - btMatrix3x3 m_massmatrix; - bool m_delete; - virtual ~Joint() {} - Joint() : m_delete(false) {} - virtual void Prepare(btScalar dt,int iterations); - virtual void Solve(btScalar dt,btScalar sor)=0; - virtual void Terminate(btScalar dt)=0; - virtual eType::_ Type() const=0; - }; - /* LJoint */ - struct LJoint : Joint - { - struct Specs : Joint::Specs - { - btVector3 position; - }; - btVector3 m_rpos[2]; - void Prepare(btScalar dt,int iterations); - void Solve(btScalar dt,btScalar sor); - void Terminate(btScalar dt); - eType::_ Type() const { return(eType::Linear); } - }; - /* AJoint */ - struct AJoint : Joint - { - struct IControl - { - virtual void Prepare(AJoint*) {} - virtual btScalar Speed(AJoint*,btScalar current) { return(current); } - static IControl* Default() { static IControl def;return(&def); } - }; - struct Specs : Joint::Specs - { - Specs() : icontrol(IControl::Default()) {} - btVector3 axis; - IControl* icontrol; - }; - btVector3 m_axis[2]; - IControl* m_icontrol; - void Prepare(btScalar dt,int iterations); - void Solve(btScalar dt,btScalar sor); - void Terminate(btScalar dt); - eType::_ Type() const { return(eType::Angular); } - }; - /* CJoint */ - struct CJoint : Joint - { - int m_life; - int m_maxlife; - btVector3 m_rpos[2]; - btVector3 m_normal; - btScalar m_friction; - void Prepare(btScalar dt,int iterations); - void Solve(btScalar dt,btScalar sor); - void Terminate(btScalar dt); - eType::_ Type() const { return(eType::Contact); } - }; - /* Config */ - struct Config - { - eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) - btScalar kVCF; // Velocities correction factor (Baumgarte) - btScalar kDP; // Damping coefficient [0,1] - btScalar kDG; // Drag coefficient [0,+inf] - btScalar kLF; // Lift coefficient [0,+inf] - btScalar kPR; // Pressure coefficient [-inf,+inf] - btScalar kVC; // Volume conversation coefficient [0,+inf] - btScalar kDF; // Dynamic friction coefficient [0,1] - btScalar kMT; // Pose matching coefficient [0,1] - btScalar kCHR; // Rigid contacts hardness [0,1] - btScalar kKHR; // Kinetic contacts hardness [0,1] - btScalar kSHR; // Soft contacts hardness [0,1] - btScalar kAHR; // Anchors hardness [0,1] - btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) - btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only) - btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) - btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) - btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) - btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) - btScalar maxvolume; // Maximum volume ratio for pose - btScalar timescale; // Time scale - int viterations; // Velocities solver iterations - int piterations; // Positions solver iterations - int diterations; // Drift solver iterations - int citerations; // Cluster solver iterations - int collisions; // Collisions flags - tVSolverArray m_vsequence; // Velocity solvers sequence - tPSolverArray m_psequence; // Position solvers sequence - tPSolverArray m_dsequence; // Drift solvers sequence - }; - /* SolverState */ - struct SolverState - { - btScalar sdt; // dt*timescale - btScalar isdt; // 1/sdt - btScalar velmrg; // velocity margin - btScalar radmrg; // radial margin - btScalar updmrg; // Update margin - }; - /// RayFromToCaster takes a ray from, ray to (instead of direction!) - struct RayFromToCaster : btDbvt::ICollide - { - btVector3 m_rayFrom; - btVector3 m_rayTo; - btVector3 m_rayNormalizedDirection; - btScalar m_mint; - Face* m_face; - int m_tests; - RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt); - void Process(const btDbvtNode* leaf); - - static inline btScalar rayFromToTriangle(const btVector3& rayFrom, - const btVector3& rayTo, - const btVector3& rayNormalizedDirection, - const btVector3& a, - const btVector3& b, - const btVector3& c, - btScalar maxt=SIMD_INFINITY); - }; - - // - // Typedefs - // - - typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); - typedef void (*vsolver_t)(btSoftBody*,btScalar); - typedef btAlignedObjectArray tClusterArray; - typedef btAlignedObjectArray tNoteArray; - typedef btAlignedObjectArray tNodeArray; - typedef btAlignedObjectArray tLeafArray; - typedef btAlignedObjectArray tLinkArray; - typedef btAlignedObjectArray tFaceArray; - typedef btAlignedObjectArray tTetraArray; - typedef btAlignedObjectArray tAnchorArray; - typedef btAlignedObjectArray tRContactArray; - typedef btAlignedObjectArray tSContactArray; - typedef btAlignedObjectArray tMaterialArray; - typedef btAlignedObjectArray tJointArray; - typedef btAlignedObjectArray tSoftBodyArray; - - // - // Fields - // - - Config m_cfg; // Configuration - SolverState m_sst; // Solver state - Pose m_pose; // Pose - void* m_tag; // User data - btSoftBodyWorldInfo* m_worldInfo; // World info - tNoteArray m_notes; // Notes - tNodeArray m_nodes; // Nodes - tLinkArray m_links; // Links - tFaceArray m_faces; // Faces - tTetraArray m_tetras; // Tetras - tAnchorArray m_anchors; // Anchors - tRContactArray m_rcontacts; // Rigid contacts - tSContactArray m_scontacts; // Soft contacts - tJointArray m_joints; // Joints - tMaterialArray m_materials; // Materials - btScalar m_timeacc; // Time accumulator - btVector3 m_bounds[2]; // Spatial bounds - bool m_bUpdateRtCst; // Update runtime constants - btDbvt m_ndbvt; // Nodes tree - btDbvt m_fdbvt; // Faces tree - btDbvt m_cdbvt; // Clusters tree - tClusterArray m_clusters; // Clusters - - btAlignedObjectArraym_clusterConnectivity;//cluster connectivity, for self-collision - - btTransform m_initialWorldTransform; - - btVector3 m_windVelocity; - - btScalar m_restLengthScale; - - // - // Api - // - - /* ctor */ - btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m); - - /* ctor */ - btSoftBody( btSoftBodyWorldInfo* worldInfo); - - void initDefaults(); - - /* dtor */ - virtual ~btSoftBody(); - /* Check for existing link */ - - btAlignedObjectArray m_userIndexMapping; - - btSoftBodyWorldInfo* getWorldInfo() - { - return m_worldInfo; - } - - ///@todo: avoid internal softbody shape hack and move collision code to collision library - virtual void setCollisionShape(btCollisionShape* collisionShape) - { - - } - - bool checkLink( int node0, - int node1) const; - bool checkLink( const Node* node0, - const Node* node1) const; - /* Check for existring face */ - bool checkFace( int node0, - int node1, - int node2) const; - /* Append material */ - Material* appendMaterial(); - /* Append note */ - void appendNote( const char* text, - const btVector3& o, - const btVector4& c=btVector4(1,0,0,0), - Node* n0=0, - Node* n1=0, - Node* n2=0, - Node* n3=0); - void appendNote( const char* text, - const btVector3& o, - Node* feature); - void appendNote( const char* text, - const btVector3& o, - Link* feature); - void appendNote( const char* text, - const btVector3& o, - Face* feature); - /* Append node */ - void appendNode( const btVector3& x,btScalar m); - /* Append link */ - void appendLink(int model=-1,Material* mat=0); - void appendLink( int node0, - int node1, - Material* mat=0, - bool bcheckexist=false); - void appendLink( Node* node0, - Node* node1, - Material* mat=0, - bool bcheckexist=false); - /* Append face */ - void appendFace(int model=-1,Material* mat=0); - void appendFace( int node0, - int node1, - int node2, - Material* mat=0); - void appendTetra(int model,Material* mat); - // - void appendTetra(int node0, - int node1, - int node2, - int node3, - Material* mat=0); - - - /* Append anchor */ - void appendAnchor( int node, - btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); - void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); - /* Append linear joint */ - void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); - void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); - void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); - /* Append linear joint */ - void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); - void appendAngularJoint(const AJoint::Specs& specs,Body body=Body()); - void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); - /* Add force (or gravity) to the entire body */ - void addForce( const btVector3& force); - /* Add force (or gravity) to a node of the body */ - void addForce( const btVector3& force, - int node); - /* Add aero force to a node of the body */ - void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex); - - /* Add aero force to a face of the body */ - void addAeroForceToFace(const btVector3& windVelocity,int faceIndex); - - /* Add velocity to the entire body */ - void addVelocity( const btVector3& velocity); - - /* Set velocity for the entire body */ - void setVelocity( const btVector3& velocity); - - /* Add velocity to a node of the body */ - void addVelocity( const btVector3& velocity, - int node); - /* Set mass */ - void setMass( int node, - btScalar mass); - /* Get mass */ - btScalar getMass( int node) const; - /* Get total mass */ - btScalar getTotalMass() const; - /* Set total mass (weighted by previous masses) */ - void setTotalMass( btScalar mass, - bool fromfaces=false); - /* Set total density */ - void setTotalDensity(btScalar density); - /* Set volume mass (using tetrahedrons) */ - void setVolumeMass( btScalar mass); - /* Set volume density (using tetrahedrons) */ - void setVolumeDensity( btScalar density); - /* Transform */ - void transform( const btTransform& trs); - /* Translate */ - void translate( const btVector3& trs); - /* Rotate */ - void rotate( const btQuaternion& rot); - /* Scale */ - void scale( const btVector3& scl); - /* Get link resting lengths scale */ - btScalar getRestLengthScale(); - /* Scale resting length of all springs */ - void setRestLengthScale(btScalar restLength); - /* Set current state as pose */ - void setPose( bool bvolume, - bool bframe); - /* Set current link lengths as resting lengths */ - void resetLinkRestLengths(); - /* Return the volume */ - btScalar getVolume() const; - /* Cluster count */ - int clusterCount() const; - /* Cluster center of mass */ - static btVector3 clusterCom(const Cluster* cluster); - btVector3 clusterCom(int cluster) const; - /* Cluster velocity at rpos */ - static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); - /* Cluster impulse */ - static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); - static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); - static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); - static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); - static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); - static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); - static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); - /* Generate bending constraints based on distance in the adjency graph */ - int generateBendingConstraints( int distance, - Material* mat=0); - /* Randomize constraints to reduce solver bias */ - void randomizeConstraints(); - /* Release clusters */ - void releaseCluster(int index); - void releaseClusters(); - /* Generate clusters (K-mean) */ - ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle - ///otherwise an approximation will be used (better performance) - int generateClusters(int k,int maxiterations=8192); - /* Refine */ - void refine(ImplicitFn* ifn,btScalar accurary,bool cut); - /* CutLink */ - bool cutLink(int node0,int node1,btScalar position); - bool cutLink(const Node* node0,const Node* node1,btScalar position); - - ///Ray casting using rayFrom and rayTo in worldspace, (not direction!) - bool rayTest(const btVector3& rayFrom, - const btVector3& rayTo, - sRayCast& results); - /* Solver presets */ - void setSolver(eSolverPresets::_ preset); - /* predictMotion */ - void predictMotion(btScalar dt); - /* solveConstraints */ - void solveConstraints(); - /* staticSolve */ - void staticSolve(int iterations); - /* solveCommonConstraints */ - static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); - /* solveClusters */ - static void solveClusters(const btAlignedObjectArray& bodies); - /* integrateMotion */ - void integrateMotion(); - /* defaultCollisionHandlers */ - void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap); - void defaultCollisionHandler(btSoftBody* psb); - - - - // - // Functionality to deal with new accelerated solvers. - // - - /** - * Set a wind velocity for interaction with the air. - */ - void setWindVelocity( const btVector3 &velocity ); - - - /** - * Return the wind velocity for interaction with the air. - */ - const btVector3& getWindVelocity(); - - // - // Set the solver that handles this soft body - // Should not be allowed to get out of sync with reality - // Currently called internally on addition to the world - void setSoftBodySolver( btSoftBodySolver *softBodySolver ) - { - m_softBodySolver = softBodySolver; - } - - // - // Return the solver that handles this soft body - // - btSoftBodySolver *getSoftBodySolver() - { - return m_softBodySolver; - } - - // - // Return the solver that handles this soft body - // - btSoftBodySolver *getSoftBodySolver() const - { - return m_softBodySolver; - } - - - // - // Cast - // - - static const btSoftBody* upcast(const btCollisionObject* colObj) - { - if (colObj->getInternalType()==CO_SOFT_BODY) - return (const btSoftBody*)colObj; - return 0; - } - static btSoftBody* upcast(btCollisionObject* colObj) - { - if (colObj->getInternalType()==CO_SOFT_BODY) - return (btSoftBody*)colObj; - return 0; - } - - // - // ::btCollisionObject - // - - virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const - { - aabbMin = m_bounds[0]; - aabbMax = m_bounds[1]; - } - // - // Private - // - void pointersToIndices(); - void indicesToPointers(const int* map=0); - - int rayTest(const btVector3& rayFrom,const btVector3& rayTo, - btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; - void initializeFaceTree(); - btVector3 evaluateCom() const; - bool checkContact(const btCollisionObjectWrapper* colObjWrap,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; - void updateNormals(); - void updateBounds(); - void updatePose(); - void updateConstants(); - void updateLinkConstants(); - void updateArea(bool averageArea = true); - void initializeClusters(); - void updateClusters(); - void cleanupClusters(); - void prepareClusters(int iterations); - void solveClusters(btScalar sor); - void applyClusters(bool drift); - void dampClusters(); - void applyForces(); - static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); - static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti); - static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti); - static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); - static void VSolve_Links(btSoftBody* psb,btScalar kst); - static psolver_t getSolver(ePSolver::_ solver); - static vsolver_t getSolver(eVSolver::_ solver); - - - virtual int calculateSerializeBufferSize() const; - - ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; - - //virtual void serializeSingleObject(class btSerializer* serializer) const; - - -}; - - - - -#endif //_BT_SOFT_BODY_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp deleted file mode 100644 index 9f0d4452..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btSoftBodyConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionShapes/btConcaveShape.h" -#include "BulletCollision/CollisionDispatch/btManifoldResult.h" -#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" -#include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" -#include "BulletCollision/CollisionShapes/btConvexHullShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - - -#include "LinearMath/btIDebugDraw.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletSoftBody/btSoftBody.h" - -#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable - -btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) -: btCollisionAlgorithm(ci), -m_isSwapped(isSwapped), -m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped) -{ -} - - - -btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() -{ -} - - - -btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped): -m_dispatcher(dispatcher), -m_dispatchInfoPtr(0) -{ - m_softBody = (isSwapped? (btSoftBody*)body1Wrap->getCollisionObject():(btSoftBody*)body0Wrap->getCollisionObject()); - m_triBody = isSwapped? body0Wrap->getCollisionObject():body1Wrap->getCollisionObject(); - - // - // create the manifold from the dispatcher 'manifold pool' - // - // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); - - clearCache(); -} - -btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() -{ - clearCache(); - // m_dispatcher->releaseManifold( m_manifoldPtr ); - -} - - -void btSoftBodyTriangleCallback::clearCache() -{ - for (int i=0;im_childShape); - m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary? - delete tmp->m_childShape; - } - m_shapeCache.clear(); -} - - -void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) -{ - //just for debugging purposes - //printf("triangle %d",m_triangleCount++); - - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher1 = m_dispatcher; - - ///debug drawing of the overlapping triangles - if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe)) - { - btVector3 color(1,1,0); - const btTransform& tr = m_triBody->getWorldTransform(); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); - } - - btTriIndex triIndex(partId,triangleIndex,0); - btHashKey triKey(triIndex.getUid()); - - - btTriIndex* shapeIndex = m_shapeCache[triKey]; - if (shapeIndex) - { - btCollisionShape* tm = shapeIndex->m_childShape; - btAssert(tm); - - //copy over user pointers to temporary shape - tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer()); - - btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1); - //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//?? - btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex); - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr); - - colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->~btCollisionAlgorithm(); - ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); - - return; - } - - //aabb filter is already applied! - - //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); - - // if (m_softBody->getCollisionShape()->getShapeType()== - { - // btVector3 other; - btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); - normal.normalize(); - normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; - // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; - // other+=normal*22.f; - btVector3 pts[6] = {triangle[0]+normal, - triangle[1]+normal, - triangle[2]+normal, - triangle[0]-normal, - triangle[1]-normal, - triangle[2]-normal}; - - btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6); - - - // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); - - //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); - // tm.setMargin(m_collisionMarginTriangle); - - //copy over user pointers to temporary shape - tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer()); - - - btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1); - btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//?? - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr); - - colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->~btCollisionAlgorithm(); - ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); - - triIndex.m_childShape = tm; - m_shapeCache.insert(triKey,triIndex); - - } - - - -} - - - -void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - m_dispatchInfoPtr = &dispatchInfo; - m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); - m_resultOut = resultOut; - - - btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; - m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); - btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); - btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5); - - btTransform softTransform; - softTransform.setIdentity(); - softTransform.setOrigin(softBodyCenter); - - btTransform convexInTriangleSpace; - convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform; - btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax); -} - -void btSoftBodyConcaveCollisionAlgorithm::clearCache() -{ - m_btSoftBodyTriangleCallback.clearCache(); - -} - -void btSoftBodyConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - - - //btCollisionObject* convexBody = m_isSwapped ? body1 : body0; - const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap; - - if (triBody->getCollisionShape()->isConcave()) - { - - - const btCollisionObject* triOb = triBody->getCollisionObject(); - const btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); - - // if (convexBody->getCollisionShape()->isConvex()) - { - btScalar collisionMarginTriangle = concaveShape->getMargin(); - - // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); - m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,triBody,dispatchInfo,resultOut); - - - concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); - - // resultOut->refreshContactPoints(); - - } - - } - -} - - -btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - btCollisionObject* convexbody = m_isSwapped ? body1 : body0; - btCollisionObject* triBody = m_isSwapped ? body0 : body1; - - - //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) - - //only perform CCD above a certain threshold, this prevents blocking on the long run - //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... - btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); - if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) - { - return btScalar(1.); - } - - //const btVector3& from = convexbody->m_worldTransform.getOrigin(); - //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); - //todo: only do if the motion exceeds the 'radius' - - btTransform triInv = triBody->getWorldTransform().inverse(); - btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); - btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); - - struct LocalTriangleSphereCastCallback : public btTriangleCallback - { - btTransform m_ccdSphereFromTrans; - btTransform m_ccdSphereToTrans; - btTransform m_meshTransform; - - btScalar m_ccdSphereRadius; - btScalar m_hitFraction; - - - LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) - :m_ccdSphereFromTrans(from), - m_ccdSphereToTrans(to), - m_ccdSphereRadius(ccdSphereRadius), - m_hitFraction(hitFraction) - { - } - - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) - { - (void)partId; - (void)triangleIndex; - //do a swept sphere for now - btTransform ident; - ident.setIdentity(); - btConvexCast::CastResult castResult; - castResult.m_fraction = m_hitFraction; - btSphereShape pointShape(m_ccdSphereRadius); - btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); - btVoronoiSimplexSolver simplexSolver; - btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); - //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); - //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); - //local space? - - if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, - ident,ident,castResult)) - { - if (m_hitFraction > castResult.m_fraction) - m_hitFraction = castResult.m_fraction; - } - - } - - }; - - - - - - if (triBody->getCollisionShape()->isConcave()) - { - btVector3 rayAabbMin = convexFromLocal.getOrigin(); - rayAabbMin.setMin(convexToLocal.getOrigin()); - btVector3 rayAabbMax = convexFromLocal.getOrigin(); - rayAabbMax.setMax(convexToLocal.getOrigin()); - btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); - rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); - rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); - - btScalar curHitFraction = btScalar(1.); //is this available? - LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, - convexbody->getCcdSweptSphereRadius(),curHitFraction); - - raycastCallback.m_hitFraction = convexbody->getHitFraction(); - - btCollisionObject* concavebody = triBody; - - btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); - - if (triangleMesh) - { - triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); - } - - - - if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) - { - convexbody->setHitFraction( raycastCallback.m_hitFraction); - return raycastCallback.m_hitFraction; - } - } - - return btScalar(1.); - -} diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h deleted file mode 100644 index 11c7b88f..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H -#define BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -class btDispatcher; -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btSoftBody; -class btCollisionShape; - -#include "LinearMath/btHashMap.h" - -#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS - -struct btTriIndex -{ - int m_PartIdTriangleIndex; - class btCollisionShape* m_childShape; - - btTriIndex(int partId,int triangleIndex,btCollisionShape* shape) - { - m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; - m_childShape = shape; - } - - int getTriangleIndex() const - { - // Get only the lower bits where the triangle index is stored - unsigned int x = 0; - unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS); - return (m_PartIdTriangleIndex&~(y)); - } - int getPartId() const - { - // Get only the highest bits where the part index is stored - return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); - } - int getUid() const - { - return m_PartIdTriangleIndex; - } -}; - - -///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called. -class btSoftBodyTriangleCallback : public btTriangleCallback -{ - btSoftBody* m_softBody; - const btCollisionObject* m_triBody; - - btVector3 m_aabbMin; - btVector3 m_aabbMax ; - - btManifoldResult* m_resultOut; - - btDispatcher* m_dispatcher; - const btDispatcherInfo* m_dispatchInfoPtr; - btScalar m_collisionMarginTriangle; - - btHashMap,btTriIndex> m_shapeCache; - -public: - int m_triangleCount; - - // btPersistentManifold* m_manifoldPtr; - - btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); - - void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triObjWrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual ~btSoftBodyTriangleCallback(); - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); - - void clearCache(); - - SIMD_FORCE_INLINE const btVector3& getAabbMin() const - { - return m_aabbMin; - } - SIMD_FORCE_INLINE const btVector3& getAabbMax() const - { - return m_aabbMax; - } - -}; - - - - -/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes. -class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm -{ - - bool m_isSwapped; - - btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback; - -public: - - btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped); - - virtual ~btSoftBodyConcaveCollisionAlgorithm(); - - virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - //we don't add any manifolds - } - - void clearCache(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); - return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false); - } - }; - - struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); - return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true); - } - }; - -}; - -#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyData.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyData.h deleted file mode 100644 index 87d8841c..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyData.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFTBODY_FLOAT_DATA -#define BT_SOFTBODY_FLOAT_DATA - -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" - - -struct SoftBodyMaterialData -{ - float m_linearStiffness; - float m_angularStiffness; - float m_volumeStiffness; - int m_flags; -}; - -struct SoftBodyNodeData -{ - SoftBodyMaterialData *m_material; - btVector3FloatData m_position; - btVector3FloatData m_previousPosition; - btVector3FloatData m_velocity; - btVector3FloatData m_accumulatedForce; - btVector3FloatData m_normal; - float m_inverseMass; - float m_area; - int m_attach; - int m_pad; -}; - -struct SoftBodyLinkData -{ - SoftBodyMaterialData *m_material; - int m_nodeIndices[2]; // Node pointers - float m_restLength; // Rest length - int m_bbending; // Bending link -}; - -struct SoftBodyFaceData -{ - btVector3FloatData m_normal; // Normal - SoftBodyMaterialData *m_material; - int m_nodeIndices[3]; // Node pointers - float m_restArea; // Rest area -}; - -struct SoftBodyTetraData -{ - btVector3FloatData m_c0[4]; // gradients - SoftBodyMaterialData *m_material; - int m_nodeIndices[4]; // Node pointers - float m_restVolume; // Rest volume - float m_c1; // (4*kVST)/(im0+im1+im2+im3) - float m_c2; // m_c1/sum(|g0..3|^2) - int m_pad; -}; - -struct SoftRigidAnchorData -{ - btMatrix3x3FloatData m_c0; // Impulse matrix - btVector3FloatData m_c1; // Relative anchor - btVector3FloatData m_localFrame; // Anchor position in body space - btRigidBodyData *m_rigidBody; - int m_nodeIndex; // Node pointer - float m_c2; // ima*dt -}; - - - -struct SoftBodyConfigData -{ - int m_aeroModel; // Aerodynamic model (default: V_Point) - float m_baumgarte; // Velocities correction factor (Baumgarte) - float m_damping; // Damping coefficient [0,1] - float m_drag; // Drag coefficient [0,+inf] - float m_lift; // Lift coefficient [0,+inf] - float m_pressure; // Pressure coefficient [-inf,+inf] - float m_volume; // Volume conversation coefficient [0,+inf] - float m_dynamicFriction; // Dynamic friction coefficient [0,1] - float m_poseMatch; // Pose matching coefficient [0,1] - float m_rigidContactHardness; // Rigid contacts hardness [0,1] - float m_kineticContactHardness; // Kinetic contacts hardness [0,1] - float m_softContactHardness; // Soft contacts hardness [0,1] - float m_anchorHardness; // Anchors hardness [0,1] - float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only) - float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only) - float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only) - float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) - float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) - float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only) - float m_maxVolume; // Maximum volume ratio for pose - float m_timeScale; // Time scale - int m_velocityIterations; // Velocities solver iterations - int m_positionIterations; // Positions solver iterations - int m_driftIterations; // Drift solver iterations - int m_clusterIterations; // Cluster solver iterations - int m_collisionFlags; // Collisions flags -}; - -struct SoftBodyPoseData -{ - btMatrix3x3FloatData m_rot; // Rotation - btMatrix3x3FloatData m_scale; // Scale - btMatrix3x3FloatData m_aqq; // Base scaling - btVector3FloatData m_com; // COM - - btVector3FloatData *m_positions; // Reference positions - float *m_weights; // Weights - int m_numPositions; - int m_numWeigts; - - int m_bvolume; // Is valid - int m_bframe; // Is frame - float m_restVolume; // Rest volume - int m_pad; -}; - -struct SoftBodyClusterData -{ - btTransformFloatData m_framexform; - btMatrix3x3FloatData m_locii; - btMatrix3x3FloatData m_invwi; - btVector3FloatData m_com; - btVector3FloatData m_vimpulses[2]; - btVector3FloatData m_dimpulses[2]; - btVector3FloatData m_lv; - btVector3FloatData m_av; - - btVector3FloatData *m_framerefs; - int *m_nodeIndices; - float *m_masses; - - int m_numFrameRefs; - int m_numNodes; - int m_numMasses; - - float m_idmass; - float m_imass; - int m_nvimpulses; - int m_ndimpulses; - float m_ndamping; - float m_ldamping; - float m_adamping; - float m_matching; - float m_maxSelfCollisionImpulse; - float m_selfCollisionImpulseFactor; - int m_containsAnchor; - int m_collide; - int m_clusterIndex; -}; - - -enum btSoftJointBodyType -{ - BT_JOINT_SOFT_BODY_CLUSTER=1, - BT_JOINT_RIGID_BODY, - BT_JOINT_COLLISION_OBJECT -}; - -struct btSoftBodyJointData -{ - void *m_bodyA; - void *m_bodyB; - btVector3FloatData m_refs[2]; - float m_cfm; - float m_erp; - float m_split; - int m_delete; - btVector3FloatData m_relPosition[2];//linear - int m_bodyAtype; - int m_bodyBtype; - int m_jointType; - int m_pad; -}; - -///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 -struct btSoftBodyFloatData -{ - btCollisionObjectFloatData m_collisionObjectData; - - SoftBodyPoseData *m_pose; - SoftBodyMaterialData **m_materials; - SoftBodyNodeData *m_nodes; - SoftBodyLinkData *m_links; - SoftBodyFaceData *m_faces; - SoftBodyTetraData *m_tetrahedra; - SoftRigidAnchorData *m_anchors; - SoftBodyClusterData *m_clusters; - btSoftBodyJointData *m_joints; - - int m_numMaterials; - int m_numNodes; - int m_numLinks; - int m_numFaces; - int m_numTetrahedra; - int m_numAnchors; - int m_numClusters; - int m_numJoints; - SoftBodyConfigData m_config; -}; - -#endif //BT_SOFTBODY_FLOAT_DATA - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.cpp deleted file mode 100644 index 36f675a6..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBodyHelpers.cpp by Nathanael Presson - -#include "btSoftBodyInternals.h" -#include -#include -#include "btSoftBodyHelpers.h" -#include "LinearMath/btConvexHull.h" -#include "LinearMath/btConvexHullComputer.h" - - -// -static void drawVertex( btIDebugDraw* idraw, - const btVector3& x,btScalar s,const btVector3& c) -{ - idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); - idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); - idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); -} - -// -static void drawBox( btIDebugDraw* idraw, - const btVector3& mins, - const btVector3& maxs, - const btVector3& color) -{ - const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), - btVector3(maxs.x(),mins.y(),mins.z()), - btVector3(maxs.x(),maxs.y(),mins.z()), - btVector3(mins.x(),maxs.y(),mins.z()), - btVector3(mins.x(),mins.y(),maxs.z()), - btVector3(maxs.x(),mins.y(),maxs.z()), - btVector3(maxs.x(),maxs.y(),maxs.z()), - btVector3(mins.x(),maxs.y(),maxs.z())}; - idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); - idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); - idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); - idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); - idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); - idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); -} - -// -static void drawTree( btIDebugDraw* idraw, - const btDbvtNode* node, - int depth, - const btVector3& ncolor, - const btVector3& lcolor, - int mindepth, - int maxdepth) -{ - if(node) - { - if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); - drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); - } - if(depth>=mindepth) - { - const btScalar scl=(btScalar)(node->isinternal()?1:1); - const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; - const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; - drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); - } - } -} - -// -template -static inline T sum(const btAlignedObjectArray& items) -{ - T v; - if(items.size()) - { - v=items[0]; - for(int i=1,ni=items.size();i -static inline void add(btAlignedObjectArray& items,const Q& value) -{ - for(int i=0,ni=items.size();i -static inline void mul(btAlignedObjectArray& items,const Q& value) -{ - for(int i=0,ni=items.size();i -static inline T average(const btAlignedObjectArray& items) -{ - const btScalar n=(btScalar)(items.size()>0?items.size():1); - return(sum(items)/n); -} - -// -static inline btScalar tetravolume(const btVector3& x0, - const btVector3& x1, - const btVector3& x2, - const btVector3& x3) -{ - const btVector3 a=x1-x0; - const btVector3 b=x2-x0; - const btVector3 c=x3-x0; - return(btDot(a,btCross(b,c))); -} - -// -#if 0 -static btVector3 stresscolor(btScalar stress) -{ - static const btVector3 spectrum[]= { btVector3(1,0,1), - btVector3(0,0,1), - btVector3(0,1,1), - btVector3(0,1,0), - btVector3(1,1,0), - btVector3(1,0,0), - btVector3(1,0,0)}; - static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; - static const btScalar one=1; - stress=btMax(0,btMin(1,stress))*ncolors; - const int sel=(int)stress; - const btScalar frc=stress-sel; - return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); -} -#endif - -// -void btSoftBodyHelpers::Draw( btSoftBody* psb, - btIDebugDraw* idraw, - int drawflags) -{ - const btScalar scl=(btScalar)0.1; - const btScalar nscl=scl*5; - const btVector3 lcolor=btVector3(0,0,0); - const btVector3 ncolor=btVector3(1,1,1); - const btVector3 ccolor=btVector3(1,0,0); - int i,j,nj; - - /* Clusters */ - if(0!=(drawflags&fDrawFlags::Clusters)) - { - srand(1806); - for(i=0;im_clusters.size();++i) - { - if(psb->m_clusters[i]->m_collide) - { - btVector3 color( rand()/(btScalar)RAND_MAX, - rand()/(btScalar)RAND_MAX, - rand()/(btScalar)RAND_MAX); - color=color.normalized()*0.75; - btAlignedObjectArray vertices; - vertices.resize(psb->m_clusters[i]->m_nodes.size()); - for(j=0,nj=vertices.size();jm_clusters[i]->m_nodes[j]->m_x; - } -#define USE_NEW_CONVEX_HULL_COMPUTER -#ifdef USE_NEW_CONVEX_HULL_COMPUTER - btConvexHullComputer computer; - int stride = sizeof(btVector3); - int count = vertices.size(); - btScalar shrink=0.f; - btScalar shrinkClamp=0.f; - computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp); - for (int i=0;igetNextEdgeOfFace(); - - int v0 = firstEdge->getSourceVertex(); - int v1 = firstEdge->getTargetVertex(); - while (edge!=firstEdge) - { - int v2 = edge->getTargetVertex(); - idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1); - edge = edge->getNextEdgeOfFace(); - v0=v1; - v1=v2; - }; - } -#else - - HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); - HullResult hres; - HullLibrary hlib; - hdsc.mMaxVertices=vertices.size(); - hlib.CreateConvexHull(hdsc,hres); - const btVector3 center=average(hres.m_OutputVertices); - add(hres.m_OutputVertices,-center); - mul(hres.m_OutputVertices,(btScalar)1); - add(hres.m_OutputVertices,center); - for(j=0;j<(int)hres.mNumFaces;++j) - { - const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]}; - idraw->drawTriangle(hres.m_OutputVertices[idx[0]], - hres.m_OutputVertices[idx[1]], - hres.m_OutputVertices[idx[2]], - color,1); - } - hlib.ReleaseResult(hres); -#endif - - } - /* Velocities */ -#if 0 - for(int j=0;jm_clusters[i].m_nodes.size();++j) - { - const btSoftBody::Cluster& c=psb->m_clusters[i]; - const btVector3 r=c.m_nodes[j]->m_x-c.m_com; - const btVector3 v=c.m_lv+btCross(c.m_av,r); - idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0)); - } -#endif - /* Frame */ - // btSoftBody::Cluster& c=*psb->m_clusters[i]; - // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0)); - // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0)); - // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1)); - } - } - else - { - /* Nodes */ - if(0!=(drawflags&fDrawFlags::Nodes)) - { - for(i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); - idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); - idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); - } - } - /* Links */ - if(0!=(drawflags&fDrawFlags::Links)) - { - for(i=0;im_links.size();++i) - { - const btSoftBody::Link& l=psb->m_links[i]; - if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); - } - } - /* Normals */ - if(0!=(drawflags&fDrawFlags::Normals)) - { - for(i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 d=n.m_n*nscl; - idraw->drawLine(n.m_x,n.m_x+d,ncolor); - idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); - } - } - /* Contacts */ - if(0!=(drawflags&fDrawFlags::Contacts)) - { - static const btVector3 axis[]={btVector3(1,0,0), - btVector3(0,1,0), - btVector3(0,0,1)}; - for(i=0;im_rcontacts.size();++i) - { - const btSoftBody::RContact& c=psb->m_rcontacts[i]; - const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* - (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); - const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); - const btVector3 y=btCross(x,c.m_cti.m_normal).normalized(); - idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); - idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); - idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); - } - } - /* Faces */ - if(0!=(drawflags&fDrawFlags::Faces)) - { - const btScalar scl=(btScalar)0.8; - const btScalar alp=(btScalar)1; - const btVector3 col(0,(btScalar)0.7,0); - for(i=0;im_faces.size();++i) - { - const btSoftBody::Face& f=psb->m_faces[i]; - if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; - const btVector3 c=(x[0]+x[1]+x[2])/3; - idraw->drawTriangle((x[0]-c)*scl+c, - (x[1]-c)*scl+c, - (x[2]-c)*scl+c, - col,alp); - } - } - /* Tetras */ - if(0!=(drawflags&fDrawFlags::Tetras)) - { - const btScalar scl=(btScalar)0.8; - const btScalar alp=(btScalar)1; - const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7); - for(int i=0;im_tetras.size();++i) - { - const btSoftBody::Tetra& t=psb->m_tetras[i]; - if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x}; - const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4; - idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp); - idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp); - idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp); - idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp); - } - } - } - /* Anchors */ - if(0!=(drawflags&fDrawFlags::Anchors)) - { - for(i=0;im_anchors.size();++i) - { - const btSoftBody::Anchor& a=psb->m_anchors[i]; - const btVector3 q=a.m_body->getWorldTransform()*a.m_local; - drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); - drawVertex(idraw,q,0.25,btVector3(0,1,0)); - idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); - } - for(i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - if(n.m_im<=0) - { - drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); - } - } - } - - - /* Notes */ - if(0!=(drawflags&fDrawFlags::Notes)) - { - for(i=0;im_notes.size();++i) - { - const btSoftBody::Note& n=psb->m_notes[i]; - btVector3 p=n.m_offset; - for(int j=0;jm_x*n.m_coords[j]; - } - idraw->draw3dText(p,n.m_text); - } - } - /* Node tree */ - if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw); - /* Face tree */ - if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw); - /* Cluster tree */ - if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw); - /* Joints */ - if(0!=(drawflags&fDrawFlags::Joints)) - { - for(i=0;im_joints.size();++i) - { - const btSoftBody::Joint* pj=psb->m_joints[i]; - switch(pj->Type()) - { - case btSoftBody::Joint::eType::Linear: - { - const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj; - const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0]; - const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1]; - idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0)); - idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1)); - drawVertex(idraw,a0,0.25,btVector3(1,1,0)); - drawVertex(idraw,a1,0.25,btVector3(0,1,1)); - } - break; - case btSoftBody::Joint::eType::Angular: - { - //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj; - const btVector3 o0=pj->m_bodies[0].xform().getOrigin(); - const btVector3 o1=pj->m_bodies[1].xform().getOrigin(); - const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0]; - const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1]; - idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0)); - idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0)); - idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1)); - idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1)); - break; - } - default: - { - } - - } - } - } -} - -// -void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool /*stress*/) -{ - for(int i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - char text[2048]={0}; - char buff[1024]; - if(masses) - { - sprintf(buff," M(%.2f)",1/n.m_im); - strcat(text,buff); - } - if(areas) - { - sprintf(buff," A(%.2f)",n.m_area); - strcat(text,buff); - } - if(text[0]) idraw->draw3dText(n.m_x,text); - } -} - -// -void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ - drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ - drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ - drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, - btIDebugDraw* idraw) -{ - if(psb->m_pose.m_bframe) - { - static const btScalar ascl=10; - static const btScalar nscl=(btScalar)0.1; - const btVector3 com=psb->m_pose.m_com; - const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; - const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); - const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); - const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); - idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); - idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); - idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); - for(int i=0;im_pose.m_pos.size();++i) - { - const btVector3 x=com+trs*psb->m_pose.m_pos[i]; - drawVertex(idraw,x,nscl,btVector3(1,0,1)); - } - } -} - -// -btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, - const btVector3& to, - int res, - int fixeds) -{ - /* Create nodes */ - const int r=res+2; - btVector3* x=new btVector3[r]; - btScalar* m=new btScalar[r]; - int i; - - for(i=0;isetMass(0,0); - if(fixeds&2) psb->setMass(r-1,0); - delete[] x; - delete[] m; - /* Create links */ - for(i=1;iappendLink(i-1,i); - } - /* Finished */ - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags) -{ -#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) - /* Create nodes */ - if((resx<2)||(resy<2)) return(0); - const int rx=resx; - const int ry=resy; - const int tot=rx*ry; - btVector3* x=new btVector3[tot]; - btScalar* m=new btScalar[tot]; - int iy; - - for(iy=0;iysetMass(IDX(0,0),0); - if(fixeds&2) psb->setMass(IDX(rx-1,0),0); - if(fixeds&4) psb->setMass(IDX(0,ry-1),0); - if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); - delete[] x; - delete[] m; - /* Create links and faces */ - for(iy=0;iyappendLink(idx,IDX(ix+1,iy)); - if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); - if(mdx&&mdy) - { - if((ix+iy)&1) - { - psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); - psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); - if(gendiags) - { - psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); - } - } - else - { - psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); - psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); - if(gendiags) - { - psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); - } - } - } - } - } - /* Finished */ -#undef IDX - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo, - const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags, - float* tex_coords) -{ - - /* - * - * corners: - * - * [0][0] corner00 ------- corner01 [resx][0] - * | | - * | | - * [0][resy] corner10 -------- corner11 [resx][resy] - * - * - * - * - * - * - * "fixedgs" map: - * - * corner00 --> +1 - * corner01 --> +2 - * corner10 --> +4 - * corner11 --> +8 - * upper middle --> +16 - * left middle --> +32 - * right middle --> +64 - * lower middle --> +128 - * center --> +256 - * - * - * tex_coords size (resx-1)*(resy-1)*12 - * - * - * - * SINGLE QUAD INTERNALS - * - * 1) btSoftBody's nodes and links, - * diagonal link is optional ("gendiags") - * - * - * node00 ------ node01 - * | . - * | . - * | . - * | . - * | . - * node10 node11 - * - * - * - * 2) Faces: - * two triangles, - * UV Coordinates (hier example for single quad) - * - * (0,1) (0,1) (1,1) - * 1 |\ 3 \-----| 2 - * | \ \ | - * | \ \ | - * | \ \ | - * | \ \ | - * 2 |-----\ 3 \| 1 - * (0,0) (1,0) (1,0) - * - * - * - * - * - * - */ - -#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) - /* Create nodes */ - if((resx<2)||(resy<2)) return(0); - const int rx=resx; - const int ry=resy; - const int tot=rx*ry; - btVector3* x=new btVector3[tot]; - btScalar* m=new btScalar[tot]; - - int iy; - - for(iy=0;iysetMass(IDX(0,0),0); - if(fixeds&2) psb->setMass(IDX(rx-1,0),0); - if(fixeds&4) psb->setMass(IDX(0,ry-1),0); - if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); - if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0); - if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0); - if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0); - if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0); - if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0); - delete[] x; - delete[] m; - - - int z = 0; - /* Create links and faces */ - for(iy=0;iyappendLink(node00,node01); - if(mdy) psb->appendLink(node00,node10); - if(mdx&&mdy) - { - psb->appendFace(node00,node10,node11); - if (tex_coords) { - tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0); - tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1); - tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0); - tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2); - tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3); - tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2); - } - psb->appendFace(node11,node01,node00); - if (tex_coords) { - tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3); - tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2); - tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3); - tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1); - tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0); - tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1); - } - if (gendiags) psb->appendLink(node00,node11); - z += 12; - } - } - } - /* Finished */ -#undef IDX - return(psb); -} - -float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id) -{ - - /* - * - * - * node00 --- node01 - * | | - * node10 --- node11 - * - * - * ID map: - * - * node00 s --> 0 - * node00 t --> 1 - * - * node01 s --> 3 - * node01 t --> 1 - * - * node10 s --> 0 - * node10 t --> 2 - * - * node11 s --> 3 - * node11 t --> 2 - * - * - */ - - float tc=0.0f; - if (id == 0) { - tc = (1.0f/((resx-1))*ix); - } - else if (id==1) { - tc = (1.0f/((resy-1))*(resy-1-iy)); - } - else if (id==2) { - tc = (1.0f/((resy-1))*(resy-1-iy-1)); - } - else if (id==3) { - tc = (1.0f/((resx-1))*(ix+1)); - } - return tc; -} -// -btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, - const btVector3& radius, - int res) -{ - struct Hammersley - { - static void Generate(btVector3* x,int n) - { - for(int i=0;i>=1) if(j&1) t+=p; - btScalar w=2*t-1; - btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; - btScalar s=btSqrt(1-w*w); - *x++=btVector3(s*btCos(a),s*btSin(a),w); - } - } - }; - btAlignedObjectArray vtx; - vtx.resize(3+res); - Hammersley::Generate(&vtx[0],vtx.size()); - for(int i=0;i chks; - btAlignedObjectArray vtx; - chks.resize(maxidx*maxidx,false); - vtx.resize(maxidx); - for(i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); - } - } -#undef IDX - psb->appendFace(idx[0],idx[1],idx[2]); - } - - if (randomizeConstraints) - { - psb->randomizeConstraints(); - } - - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, - int nvertices, bool randomizeConstraints) -{ - HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); - HullResult hres; - HullLibrary hlib;/*??*/ - hdsc.mMaxVertices=nvertices; - hlib.CreateConvexHull(hdsc,hres); - btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, - &hres.m_OutputVertices[0],0); - for(int i=0;i<(int)hres.mNumFaces;++i) - { - const int idx[]={ static_cast(hres.m_Indices[i*3+0]), - static_cast(hres.m_Indices[i*3+1]), - static_cast(hres.m_Indices[i*3+2])}; - if(idx[0]appendLink( idx[0],idx[1]); - if(idx[1]appendLink( idx[1],idx[2]); - if(idx[2]appendLink( idx[2],idx[0]); - psb->appendFace(idx[0],idx[1],idx[2]); - } - hlib.ReleaseResult(hres); - if (randomizeConstraints) - { - psb->randomizeConstraints(); - } - return(psb); -} - - - - -static int nextLine(const char* buffer) -{ - int numBytesRead=0; - - while (*buffer != '\n') - { - buffer++; - numBytesRead++; - } - - - if (buffer[0]==0x0a) - { - buffer++; - numBytesRead++; - } - return numBytesRead; -} - -/* Create from TetGen .ele, .face, .node data */ -btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo, - const char* ele, - const char* face, - const char* node, - bool bfacelinks, - bool btetralinks, - bool bfacesfromtetras) -{ -btAlignedObjectArray pos; -int nnode=0; -int ndims=0; -int nattrb=0; -int hasbounds=0; -int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds); -result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds); -node += nextLine(node); - -pos.resize(nnode); -for(int i=0;i>index; -// sn>>x;sn>>y;sn>>z; - node += nextLine(node); - - //for(int j=0;j>a; - - //if(hasbounds) - // sn>>bound; - - pos[index].setX(btScalar(x)); - pos[index].setY(btScalar(y)); - pos[index].setZ(btScalar(z)); - } -btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0); -#if 0 -if(face&&face[0]) - { - int nface=0; - sf>>nface;sf>>hasbounds; - for(int i=0;i>index; - sf>>ni[0];sf>>ni[1];sf>>ni[2]; - sf>>bound; - psb->appendFace(ni[0],ni[1],ni[2]); - if(btetralinks) - { - psb->appendLink(ni[0],ni[1],0,true); - psb->appendLink(ni[1],ni[2],0,true); - psb->appendLink(ni[2],ni[0],0,true); - } - } - } -#endif - -if(ele&&ele[0]) - { - int ntetra=0; - int ncorner=0; - int neattrb=0; - sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb); - ele += nextLine(ele); - - //se>>ntetra;se>>ncorner;se>>neattrb; - for(int i=0;i>index; - //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3]; - sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]); - ele+=nextLine(ele); - //for(int j=0;j>a; - psb->appendTetra(ni[0],ni[1],ni[2],ni[3]); - if(btetralinks) - { - psb->appendLink(ni[0],ni[1],0,true); - psb->appendLink(ni[1],ni[2],0,true); - psb->appendLink(ni[2],ni[0],0,true); - psb->appendLink(ni[0],ni[3],0,true); - psb->appendLink(ni[1],ni[3],0,true); - psb->appendLink(ni[2],ni[3],0,true); - } - } - } -printf("Nodes: %u\r\n",psb->m_nodes.size()); -printf("Links: %u\r\n",psb->m_links.size()); -printf("Faces: %u\r\n",psb->m_faces.size()); -printf("Tetras: %u\r\n",psb->m_tetras.size()); -return(psb); -} - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.h deleted file mode 100644 index 620a52fe..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyHelpers.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_HELPERS_H -#define BT_SOFT_BODY_HELPERS_H - -#include "btSoftBody.h" - -// -// Helpers -// - -/* fDrawFlags */ -struct fDrawFlags { enum _ { - Nodes = 0x0001, - Links = 0x0002, - Faces = 0x0004, - Tetras = 0x0008, - Normals = 0x0010, - Contacts = 0x0020, - Anchors = 0x0040, - Notes = 0x0080, - Clusters = 0x0100, - NodeTree = 0x0200, - FaceTree = 0x0400, - ClusterTree = 0x0800, - Joints = 0x1000, - /* presets */ - Std = Links+Faces+Tetras+Anchors+Notes+Joints, - StdTetra = Std-Faces+Tetras -};}; - -struct btSoftBodyHelpers -{ - /* Draw body */ - static void Draw( btSoftBody* psb, - btIDebugDraw* idraw, - int drawflags=fDrawFlags::Std); - /* Draw body infos */ - static void DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool stress); - /* Draw node tree */ - static void DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); - /* Draw face tree */ - static void DrawFaceTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); - /* Draw cluster tree */ - static void DrawClusterTree(btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); - /* Draw rigid frame */ - static void DrawFrame( btSoftBody* psb, - btIDebugDraw* idraw); - /* Create a rope */ - static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, - const btVector3& from, - const btVector3& to, - int res, - int fixeds); - /* Create a patch */ - static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo, - const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags); - /* Create a patch with UV Texture Coordinates */ - static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo, - const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags, - float* tex_coords=0); - static float CalculateUV(int resx,int resy,int ix,int iy,int id); - /* Create an ellipsoid */ - static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, - const btVector3& center, - const btVector3& radius, - int res); - /* Create from trimesh */ - static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, - const btScalar* vertices, - const int* triangles, - int ntriangles, - bool randomizeConstraints = true); - /* Create from convex-hull */ - static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, - const btVector3* vertices, - int nvertices, - bool randomizeConstraints = true); - - - /* Export TetGen compatible .smesh file */ -// static void ExportAsSMeshFile( btSoftBody* psb, -// const char* filename); - /* Create from TetGen .ele, .face, .node files */ -// static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo, -// const char* ele, -// const char* face, -// const char* node, -// bool bfacelinks, -// bool btetralinks, -// bool bfacesfromtetras); - /* Create from TetGen .ele, .face, .node data */ - static btSoftBody* CreateFromTetGenData( btSoftBodyWorldInfo& worldInfo, - const char* ele, - const char* face, - const char* node, - bool bfacelinks, - bool btetralinks, - bool bfacesfromtetras); - -}; - -#endif //BT_SOFT_BODY_HELPERS_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyInternals.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyInternals.h deleted file mode 100644 index 19d0543e..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyInternals.h +++ /dev/null @@ -1,908 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBody implementation by Nathanael Presson - -#ifndef _BT_SOFT_BODY_INTERNALS_H -#define _BT_SOFT_BODY_INTERNALS_H - -#include "btSoftBody.h" - - -#include "LinearMath/btQuickprof.h" -#include "LinearMath/btPolarDecomposition.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" -#include //for memset -// -// btSymMatrix -// -template -struct btSymMatrix -{ - btSymMatrix() : dim(0) {} - btSymMatrix(int n,const T& init=T()) { resize(n,init); } - void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); } - int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r store; - int dim; -}; - -// -// btSoftBodyCollisionShape -// -class btSoftBodyCollisionShape : public btConcaveShape -{ -public: - btSoftBody* m_body; - - btSoftBodyCollisionShape(btSoftBody* backptr) - { - m_shapeType = SOFTBODY_SHAPE_PROXYTYPE; - m_body=backptr; - } - - virtual ~btSoftBodyCollisionShape() - { - - } - - void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const - { - //not yet - btAssert(0); - } - - ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */ - const btVector3 mins=m_body->m_bounds[0]; - const btVector3 maxs=m_body->m_bounds[1]; - const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), - t*btVector3(maxs.x(),mins.y(),mins.z()), - t*btVector3(maxs.x(),maxs.y(),mins.z()), - t*btVector3(mins.x(),maxs.y(),mins.z()), - t*btVector3(mins.x(),mins.y(),maxs.z()), - t*btVector3(maxs.x(),mins.y(),maxs.z()), - t*btVector3(maxs.x(),maxs.y(),maxs.z()), - t*btVector3(mins.x(),maxs.y(),maxs.z())}; - aabbMin=aabbMax=crns[0]; - for(int i=1;i<8;++i) - { - aabbMin.setMin(crns[i]); - aabbMax.setMax(crns[i]); - } - } - - - virtual void setLocalScaling(const btVector3& /*scaling*/) - { - ///na - } - virtual const btVector3& getLocalScaling() const - { - static const btVector3 dummy(1,1,1); - return dummy; - } - virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const - { - ///not yet - btAssert(0); - } - virtual const char* getName()const - { - return "SoftBody"; - } - -}; - -// -// btSoftClusterCollisionShape -// -class btSoftClusterCollisionShape : public btConvexInternalShape -{ -public: - const btSoftBody::Cluster* m_cluster; - - btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); } - - - virtual btVector3 localGetSupportingVertex(const btVector3& vec) const - { - btSoftBody::Node* const * n=&m_cluster->m_nodes[0]; - btScalar d=btDot(vec,n[0]->m_x); - int j=0; - for(int i=1,ni=m_cluster->m_nodes.size();im_x); - if(k>d) { d=k;j=i; } - } - return(n[j]->m_x); - } - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const - { - return(localGetSupportingVertex(vec)); - } - //notice that the vectors should be unit length - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const - {} - - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const - {} - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - {} - - virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } - - //debugging - virtual const char* getName()const {return "SOFTCLUSTER";} - - virtual void setMargin(btScalar margin) - { - btConvexInternalShape::setMargin(margin); - } - virtual btScalar getMargin() const - { - return getMargin(); - } -}; - -// -// Inline's -// - -// -template -static inline void ZeroInitialize(T& value) -{ - memset(&value,0,sizeof(T)); -} -// -template -static inline bool CompLess(const T& a,const T& b) -{ return(a -static inline bool CompGreater(const T& a,const T& b) -{ return(a>b); } -// -template -static inline T Lerp(const T& a,const T& b,btScalar t) -{ return(a+(b-a)*t); } -// -template -static inline T InvLerp(const T& a,const T& b,btScalar t) -{ return((b+a*t-b*t)/(a*b)); } -// -static inline btMatrix3x3 Lerp( const btMatrix3x3& a, - const btMatrix3x3& b, - btScalar t) -{ - btMatrix3x3 r; - r[0]=Lerp(a[0],b[0],t); - r[1]=Lerp(a[1],b[1],t); - r[2]=Lerp(a[2],b[2],t); - return(r); -} -// -static inline btVector3 Clamp(const btVector3& v,btScalar maxlength) -{ - const btScalar sql=v.length2(); - if(sql>(maxlength*maxlength)) - return((v*maxlength)/btSqrt(sql)); - else - return(v); -} -// -template -static inline T Clamp(const T& x,const T& l,const T& h) -{ return(xh?h:x); } -// -template -static inline T Sq(const T& x) -{ return(x*x); } -// -template -static inline T Cube(const T& x) -{ return(x*x*x); } -// -template -static inline T Sign(const T& x) -{ return((T)(x<0?-1:+1)); } -// -template -static inline bool SameSign(const T& x,const T& y) -{ return((x*y)>0); } -// -static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y) -{ - const btVector3 d=x-y; - return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); -} -// -static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) -{ - const btScalar xx=a.x()*a.x(); - const btScalar yy=a.y()*a.y(); - const btScalar zz=a.z()*a.z(); - const btScalar xy=a.x()*a.y(); - const btScalar yz=a.y()*a.z(); - const btScalar zx=a.z()*a.x(); - btMatrix3x3 m; - m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx); - m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz); - m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s); - return(m); -} -// -static inline btMatrix3x3 Cross(const btVector3& v) -{ - btMatrix3x3 m; - m[0]=btVector3(0,-v.z(),+v.y()); - m[1]=btVector3(+v.z(),0,-v.x()); - m[2]=btVector3(-v.y(),+v.x(),0); - return(m); -} -// -static inline btMatrix3x3 Diagonal(btScalar x) -{ - btMatrix3x3 m; - m[0]=btVector3(x,0,0); - m[1]=btVector3(0,x,0); - m[2]=btVector3(0,0,x); - return(m); -} -// -static inline btMatrix3x3 Add(const btMatrix3x3& a, - const btMatrix3x3& b) -{ - btMatrix3x3 r; - for(int i=0;i<3;++i) r[i]=a[i]+b[i]; - return(r); -} -// -static inline btMatrix3x3 Sub(const btMatrix3x3& a, - const btMatrix3x3& b) -{ - btMatrix3x3 r; - for(int i=0;i<3;++i) r[i]=a[i]-b[i]; - return(r); -} -// -static inline btMatrix3x3 Mul(const btMatrix3x3& a, - btScalar b) -{ - btMatrix3x3 r; - for(int i=0;i<3;++i) r[i]=a[i]*b; - return(r); -} -// -static inline void Orthogonalize(btMatrix3x3& m) -{ - m[2]=btCross(m[0],m[1]).normalized(); - m[1]=btCross(m[2],m[0]).normalized(); - m[0]=btCross(m[1],m[2]).normalized(); -} -// -static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r) -{ - const btMatrix3x3 cr=Cross(r); - return(Sub(Diagonal(im),cr*iwi*cr)); -} - -// -static inline btMatrix3x3 ImpulseMatrix( btScalar dt, - btScalar ima, - btScalar imb, - const btMatrix3x3& iwi, - const btVector3& r) -{ - return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse()); -} - -// -static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra, - btScalar imb,const btMatrix3x3& iib,const btVector3& rb) -{ - return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); -} - -// -static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, - const btMatrix3x3& iib) -{ - return(Add(iia,iib).inverse()); -} - -// -static inline btVector3 ProjectOnAxis( const btVector3& v, - const btVector3& a) -{ - return(a*btDot(v,a)); -} -// -static inline btVector3 ProjectOnPlane( const btVector3& v, - const btVector3& a) -{ - return(v-ProjectOnAxis(v,a)); -} - -// -static inline void ProjectOrigin( const btVector3& a, - const btVector3& b, - btVector3& prj, - btScalar& sqd) -{ - const btVector3 d=b-a; - const btScalar m2=d.length2(); - if(m2>SIMD_EPSILON) - { - const btScalar t=Clamp(-btDot(a,d)/m2,0,1); - const btVector3 p=a+d*t; - const btScalar l2=p.length2(); - if(l2SIMD_EPSILON) - { - const btVector3 n=q/btSqrt(m2); - const btScalar k=btDot(a,n); - const btScalar k2=k*k; - if(k20)&& - (btDot(btCross(b-p,c-p),q)>0)&& - (btDot(btCross(c-p,a-p),q)>0)) - { - prj=p; - sqd=k2; - } - else - { - ProjectOrigin(a,b,prj,sqd); - ProjectOrigin(b,c,prj,sqd); - ProjectOrigin(c,a,prj,sqd); - } - } - } -} - -// -template -static inline T BaryEval( const T& a, - const T& b, - const T& c, - const btVector3& coord) -{ - return(a*coord.x()+b*coord.y()+c*coord.z()); -} -// -static inline btVector3 BaryCoord( const btVector3& a, - const btVector3& b, - const btVector3& c, - const btVector3& p) -{ - const btScalar w[]={ btCross(a-p,b-p).length(), - btCross(b-p,c-p).length(), - btCross(c-p,a-p).length()}; - const btScalar isum=1/(w[0]+w[1]+w[2]); - return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum)); -} - -// -static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, - const btVector3& a, - const btVector3& b, - const btScalar accuracy, - const int maxiterations=256) -{ - btScalar span[2]={0,1}; - btScalar values[2]={fn->Eval(a),fn->Eval(b)}; - if(values[0]>values[1]) - { - btSwap(span[0],span[1]); - btSwap(values[0],values[1]); - } - if(values[0]>-accuracy) return(-1); - if(values[1]<+accuracy) return(-1); - for(int i=0;iEval(Lerp(a,b,t)); - if((t<=0)||(t>=1)) break; - if(btFabs(v)SIMD_EPSILON) - return(v/l); - else - return(btVector3(0,0,0)); -} - -// -static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f, - btScalar margin) -{ - const btVector3* pts[]={ &f.m_n[0]->m_x, - &f.m_n[1]->m_x, - &f.m_n[2]->m_x}; - btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3); - vol.Expand(btVector3(margin,margin,margin)); - return(vol); -} - -// -static inline btVector3 CenterOf( const btSoftBody::Face& f) -{ - return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3); -} - -// -static inline btScalar AreaOf( const btVector3& x0, - const btVector3& x1, - const btVector3& x2) -{ - const btVector3 a=x1-x0; - const btVector3 b=x2-x0; - const btVector3 cr=btCross(a,b); - const btScalar area=cr.length(); - return(area); -} - -// -static inline btScalar VolumeOf( const btVector3& x0, - const btVector3& x1, - const btVector3& x2, - const btVector3& x3) -{ - const btVector3 a=x1-x0; - const btVector3 b=x2-x0; - const btVector3 c=x3-x0; - return(btDot(a,btCross(b,c))); -} - -// -static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, - const btVector3& x, - btSoftBody::sMedium& medium) -{ - medium.m_velocity = btVector3(0,0,0); - medium.m_pressure = 0; - medium.m_density = wfi->air_density; - if(wfi->water_density>0) - { - const btScalar depth=-(btDot(x,wfi->water_normal)+wfi->water_offset); - if(depth>0) - { - medium.m_density = wfi->water_density; - medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); - } - } -} - -// -static inline void ApplyClampedForce( btSoftBody::Node& n, - const btVector3& f, - btScalar dt) -{ - const btScalar dtim=dt*n.m_im; - if((f*dtim).length2()>n.m_v.length2()) - {/* Clamp */ - n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim; - } - else - {/* Apply */ - n.m_f+=f; - } -} - -// -static inline int MatchEdge( const btSoftBody::Node* a, - const btSoftBody::Node* b, - const btSoftBody::Node* ma, - const btSoftBody::Node* mb) -{ - if((a==ma)&&(b==mb)) return(0); - if((a==mb)&&(b==ma)) return(1); - return(-1); -} - -// -// btEigen : Extract eigen system, -// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html -// outputs are NOT sorted. -// -struct btEigen -{ - static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) - { - static const int maxiterations=16; - static const btScalar accuracy=(btScalar)0.0001; - btMatrix3x3& v=*vectors; - int iterations=0; - vectors->setIdentity(); - do { - int p=0,q=1; - if(btFabs(a[p][q])accuracy) - { - const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]); - const btScalar z=btFabs(w); - const btScalar t=w/(z*(btSqrt(1+w*w)+z)); - if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ - { - const btScalar c=1/btSqrt(t*t+1); - const btScalar s=c*t; - mulPQ(a,c,s,p,q); - mulTPQ(a,c,s,p,q); - mulPQ(v,c,s,p,q); - } else break; - } else break; - } while((++iterations)data; - btSoftClusterCollisionShape cshape(cluster); - - const btConvexShape* rshape=(const btConvexShape*)m_colObjWrap->getCollisionShape(); - - ///don't collide an anchored cluster with a static/kinematic object - if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor) - return; - - btGjkEpaSolver2::sResults res; - if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), - rshape,m_colObjWrap->getWorldTransform(), - btVector3(1,0,0),res)) - { - btSoftBody::CJoint joint; - if(SolveContact(res,cluster,m_colObjWrap->getCollisionObject(),joint))//prb,joint)) - { - btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); - *pj=joint;psb->m_joints.push_back(pj); - if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject()) - { - pj->m_erp *= psb->m_cfg.kSKHR_CL; - pj->m_split *= psb->m_cfg.kSK_SPLT_CL; - } - else - { - pj->m_erp *= psb->m_cfg.kSRHR_CL; - pj->m_split *= psb->m_cfg.kSR_SPLT_CL; - } - } - } - } - void ProcessColObj(btSoftBody* ps,const btCollisionObjectWrapper* colObWrap) - { - psb = ps; - m_colObjWrap = colObWrap; - idt = ps->m_sst.isdt; - m_margin = m_colObjWrap->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin(); - ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful. - friction = btMin(psb->m_cfg.kDF,m_colObjWrap->getCollisionObject()->getFriction()); - btVector3 mins; - btVector3 maxs; - - ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; - colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(),mins,maxs); - volume=btDbvtVolume::FromMM(mins,maxs); - volume.Expand(btVector3(1,1,1)*m_margin); - ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this); - } - }; - // - // CollideCL_SS - // - struct CollideCL_SS : ClusterBase - { - btSoftBody* bodies[2]; - void Process(const btDbvtNode* la,const btDbvtNode* lb) - { - btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data; - btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; - - - bool connected=false; - if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size())) - { - connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex]; - } - - if (!connected) - { - btSoftClusterCollisionShape csa(cla); - btSoftClusterCollisionShape csb(clb); - btGjkEpaSolver2::sResults res; - if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(), - &csb,btTransform::getIdentity(), - cla->m_com-clb->m_com,res)) - { - btSoftBody::CJoint joint; - if(SolveContact(res,cla,clb,joint)) - { - btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); - *pj=joint;bodies[0]->m_joints.push_back(pj); - pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL); - pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2; - } - } - } else - { - static int count=0; - count++; - //printf("count=%d\n",count); - - } - } - void ProcessSoftSoft(btSoftBody* psa,btSoftBody* psb) - { - idt = psa->m_sst.isdt; - //m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2; - m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin()); - friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF); - bodies[0] = psa; - bodies[1] = psb; - psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); - } - }; - // - // CollideSDF_RS - // - struct CollideSDF_RS : btDbvt::ICollide - { - void Process(const btDbvtNode* leaf) - { - btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; - DoNode(*node); - } - void DoNode(btSoftBody::Node& n) const - { - const btScalar m=n.m_im>0?dynmargin:stamargin; - btSoftBody::RContact c; - - if( (!n.m_battach)&& - psb->checkContact(m_colObj1Wrap,n.m_x,m,c.m_cti)) - { - const btScalar ima=n.m_im; - const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f; - const btScalar ms=ima+imb; - if(ms>0) - { - const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform(); - static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0); - const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic; - const btVector3 ra=n.m_x-wtr.getOrigin(); - const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0); - const btVector3 vb=n.m_x-n.m_q; - const btVector3 vr=vb-va; - const btScalar dn=btDot(vr,c.m_cti.m_normal); - const btVector3 fv=vr-c.m_cti.m_normal*dn; - const btScalar fc=psb->m_cfg.kDF*m_colObj1Wrap->getCollisionObject()->getFriction(); - c.m_node = &n; - c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra); - c.m_c1 = ra; - c.m_c2 = ima*psb->m_sst.sdt; - c.m_c3 = fv.length2()<(dn*fc*dn*fc)?0:1-fc; - c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; - psb->m_rcontacts.push_back(c); - if (m_rigidBody) - m_rigidBody->activate(); - } - } - } - btSoftBody* psb; - const btCollisionObjectWrapper* m_colObj1Wrap; - btRigidBody* m_rigidBody; - btScalar dynmargin; - btScalar stamargin; - }; - // - // CollideVF_SS - // - struct CollideVF_SS : btDbvt::ICollide - { - void Process(const btDbvtNode* lnode, - const btDbvtNode* lface) - { - btSoftBody::Node* node=(btSoftBody::Node*)lnode->data; - btSoftBody::Face* face=(btSoftBody::Face*)lface->data; - btVector3 o=node->m_x; - btVector3 p; - btScalar d=SIMD_INFINITY; - ProjectOrigin( face->m_n[0]->m_x-o, - face->m_n[1]->m_x-o, - face->m_n[2]->m_x-o, - p,d); - const btScalar m=mrg+(o-node->m_q).length()*2; - if(d<(m*m)) - { - const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]}; - const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o); - const btScalar ma=node->m_im; - btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w); - if( (n[0]->m_im<=0)|| - (n[1]->m_im<=0)|| - (n[2]->m_im<=0)) - { - mb=0; - } - const btScalar ms=ma+mb; - if(ms>0) - { - btSoftBody::SContact c; - c.m_normal = p/-btSqrt(d); - c.m_margin = m; - c.m_node = node; - c.m_face = face; - c.m_weights = w; - c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF); - c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR; - c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR; - psb[0]->m_scontacts.push_back(c); - } - } - } - btSoftBody* psb[2]; - btScalar mrg; - }; -}; - -#endif //_BT_SOFT_BODY_INTERNALS_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp deleted file mode 100644 index f5a67f6d..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btSoftBodyRigidBodyCollisionConfiguration.h" -#include "btSoftRigidCollisionAlgorithm.h" -#include "btSoftBodyConcaveCollisionAlgorithm.h" -#include "btSoftSoftCollisionAlgorithm.h" - -#include "LinearMath/btPoolAllocator.h" - -#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1 - -btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) -:btDefaultCollisionConfiguration(constructionInfo) -{ - void* mem; - - mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16); - m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); - m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); - m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; - m_swappedSoftRigidConvexCreateFunc->m_swapped=true; - -#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS - mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); - m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); - m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc; - m_swappedSoftRigidConcaveCreateFunc->m_swapped=true; -#endif - - //replace pool by a new one, with potential larger size - - if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool) - { - int curElemSize = m_collisionAlgorithmPool->getElementSize(); - ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool - - - int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm); - int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm); - int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm); - - int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1); - collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2); - - if (collisionAlgorithmMaxElementSize > curElemSize) - { - m_collisionAlgorithmPool->~btPoolAllocator(); - btAlignedFree(m_collisionAlgorithmPool); - void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); - m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); - } - } - -} - -btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() -{ - m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_softSoftCreateFunc); - - m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_softRigidConvexCreateFunc); - - m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedSoftRigidConvexCreateFunc); - -#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS - m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_softRigidConcaveCreateFunc); - - m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedSoftRigidConcaveCreateFunc); -#endif -} - -///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation -btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) -{ - - ///try to handle the softbody interactions first - - if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE)) - { - return m_softSoftCreateFunc; - } - - ///softbody versus convex - if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_softRigidConvexCreateFunc; - } - - ///convex versus soft body - if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) - { - return m_swappedSoftRigidConvexCreateFunc; - } - -#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS - ///softbody versus convex - if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_softRigidConcaveCreateFunc; - } - - ///convex versus soft body - if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) - { - return m_swappedSoftRigidConcaveCreateFunc; - } -#endif - - ///fallback to the regular rigid collision shape - return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); -} diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h deleted file mode 100644 index 21addcfe..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION -#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION - -#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" - -class btVoronoiSimplexSolver; -class btGjkEpaPenetrationDepthSolver; - - -///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration -class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration -{ - - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc; - btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; - -public: - - btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); - - virtual ~btSoftBodyRigidBodyCollisionConfiguration(); - - ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation - virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); - -}; - -#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h deleted file mode 100644 index c4733d64..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H -#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H - - -class btVertexBufferDescriptor -{ -public: - enum BufferTypes - { - CPU_BUFFER, - DX11_BUFFER, - OPENGL_BUFFER - }; - -protected: - - bool m_hasVertexPositions; - bool m_hasNormals; - - int m_vertexOffset; - int m_vertexStride; - - int m_normalOffset; - int m_normalStride; - -public: - btVertexBufferDescriptor() - { - m_hasVertexPositions = false; - m_hasNormals = false; - m_vertexOffset = 0; - m_vertexStride = 0; - m_normalOffset = 0; - m_normalStride = 0; - } - - virtual ~btVertexBufferDescriptor() - { - - } - - virtual bool hasVertexPositions() const - { - return m_hasVertexPositions; - } - - virtual bool hasNormals() const - { - return m_hasNormals; - } - - /** - * Return the type of the vertex buffer descriptor. - */ - virtual BufferTypes getBufferType() const = 0; - - /** - * Return the vertex offset in floats from the base pointer. - */ - virtual int getVertexOffset() const - { - return m_vertexOffset; - } - - /** - * Return the vertex stride in number of floats between vertices. - */ - virtual int getVertexStride() const - { - return m_vertexStride; - } - - /** - * Return the vertex offset in floats from the base pointer. - */ - virtual int getNormalOffset() const - { - return m_normalOffset; - } - - /** - * Return the vertex stride in number of floats between vertices. - */ - virtual int getNormalStride() const - { - return m_normalStride; - } -}; - - -class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor -{ -protected: - float *m_basePointer; - -public: - /** - * vertexBasePointer is pointer to beginning of the buffer. - * vertexOffset is the offset in floats to the first vertex. - * vertexStride is the stride in floats between vertices. - */ - btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride ) - { - m_basePointer = basePointer; - m_vertexOffset = vertexOffset; - m_vertexStride = vertexStride; - m_hasVertexPositions = true; - } - - /** - * vertexBasePointer is pointer to beginning of the buffer. - * vertexOffset is the offset in floats to the first vertex. - * vertexStride is the stride in floats between vertices. - */ - btCPUVertexBufferDescriptor( float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride ) - { - m_basePointer = basePointer; - - m_vertexOffset = vertexOffset; - m_vertexStride = vertexStride; - m_hasVertexPositions = true; - - m_normalOffset = normalOffset; - m_normalStride = normalStride; - m_hasNormals = true; - } - - virtual ~btCPUVertexBufferDescriptor() - { - - } - - /** - * Return the type of the vertex buffer descriptor. - */ - virtual BufferTypes getBufferType() const - { - return CPU_BUFFER; - } - - /** - * Return the base pointer in memory to the first vertex. - */ - virtual float *getBasePointer() const - { - return m_basePointer; - } -}; - -#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolvers.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolvers.h deleted file mode 100644 index 6947bc27..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftBodySolvers.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_BODY_SOLVERS_H -#define BT_SOFT_BODY_SOLVERS_H - -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" - - -class btSoftBodyTriangleData; -class btSoftBodyLinkData; -class btSoftBodyVertexData; -class btVertexBufferDescriptor; -class btCollisionObject; -class btSoftBody; - - -class btSoftBodySolver -{ -public: - enum SolverTypes - { - DEFAULT_SOLVER, - CPU_SOLVER, - CL_SOLVER, - CL_SIMD_SOLVER, - DX_SOLVER, - DX_SIMD_SOLVER - }; - - -protected: - int m_numberOfPositionIterations; - int m_numberOfVelocityIterations; - // Simulation timescale - float m_timeScale; - -public: - btSoftBodySolver() : - m_numberOfPositionIterations( 10 ), - m_timeScale( 1 ) - { - m_numberOfVelocityIterations = 0; - m_numberOfPositionIterations = 5; - } - - virtual ~btSoftBodySolver() - { - } - - /** - * Return the type of the solver. - */ - virtual SolverTypes getSolverType() const = 0; - - - /** Ensure that this solver is initialized. */ - virtual bool checkInitialized() = 0; - - /** Optimize soft bodies in this solver. */ - virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false) = 0; - - /** Copy necessary data back to the original soft body source objects. */ - virtual void copyBackToSoftBodies(bool bMove = true) = 0; - - /** Predict motion of soft bodies into next timestep */ - virtual void predictMotion( float solverdt ) = 0; - - /** Solve constraints for a set of soft bodies */ - virtual void solveConstraints( float solverdt ) = 0; - - /** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */ - virtual void updateSoftBodies() = 0; - - /** Process a collision between one of the world's soft bodies and another collision object */ - virtual void processCollision( btSoftBody *, const struct btCollisionObjectWrapper* ) = 0; - - /** Process a collision between two soft bodies */ - virtual void processCollision( btSoftBody*, btSoftBody* ) = 0; - - /** Set the number of velocity constraint solver iterations this solver uses. */ - virtual void setNumberOfPositionIterations( int iterations ) - { - m_numberOfPositionIterations = iterations; - } - - /** Get the number of velocity constraint solver iterations this solver uses. */ - virtual int getNumberOfPositionIterations() - { - return m_numberOfPositionIterations; - } - - /** Set the number of velocity constraint solver iterations this solver uses. */ - virtual void setNumberOfVelocityIterations( int iterations ) - { - m_numberOfVelocityIterations = iterations; - } - - /** Get the number of velocity constraint solver iterations this solver uses. */ - virtual int getNumberOfVelocityIterations() - { - return m_numberOfVelocityIterations; - } - - /** Return the timescale that the simulation is using */ - float getTimeScale() - { - return m_timeScale; - } - -#if 0 - /** - * Add a collision object to be used by the indicated softbody. - */ - virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject ) = 0; -#endif -}; - -/** - * Class to manage movement of data from a solver to a given target. - * This version is abstract. Subclasses will have custom pairings for different combinations. - */ -class btSoftBodySolverOutput -{ -protected: - -public: - btSoftBodySolverOutput() - { - } - - virtual ~btSoftBodySolverOutput() - { - } - - - /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */ - virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer ) = 0; -}; - - -#endif // #ifndef BT_SOFT_BODY_SOLVERS_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp deleted file mode 100644 index 01c148a2..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btSoftRigidCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "btSoftBody.h" -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - -///TODO: include all the shapes that the softbody can collide with -///alternatively, implement special case collision algorithms (just like for rigid collision shapes) - -//#include - -btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* , bool isSwapped) -: btCollisionAlgorithm(ci), -//m_ownManifold(false), -//m_manifoldPtr(mf), -m_isSwapped(isSwapped) -{ -} - - -btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() -{ - - //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); - - /*if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } - */ - -} - - -#include - -void btSoftRigidCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)dispatchInfo; - (void)resultOut; - //printf("btSoftRigidCollisionAlgorithm\n"); -// const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap; -// const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap; - btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject(); - const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped? body0Wrap : body1Wrap; - - if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject())==softBody->m_collisionDisabledObjects.size()) - { - softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap); - } - - -} - -btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - (void)col0; - (void)col1; - - //not yet - return btScalar(1.); -} - - - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h deleted file mode 100644 index a9b513e3..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_RIGID_COLLISION_ALGORITHM_H -#define BT_SOFT_RIGID_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btPersistentManifold; -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" - -#include "LinearMath/btVector3.h" -class btSoftBody; - -/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody -class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm -{ - // bool m_ownManifold; - // btPersistentManifold* m_manifoldPtr; - - btSoftBody* m_softBody; - btCollisionObject* m_rigidCollisionObject; - - ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean - bool m_isSwapped; - -public: - - btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0,const btCollisionObjectWrapper* col1Wrap, bool isSwapped); - - virtual ~btSoftRigidCollisionAlgorithm(); - - virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - //we don't add any manifolds - } - - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm)); - if (!m_swapped) - { - return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false); - } else - { - return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true); - } - } - }; - -}; - -#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H - - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp deleted file mode 100644 index 5f359354..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btSoftRigidDynamicsWorld.h" -#include "LinearMath/btQuickprof.h" - -//softbody & helpers -#include "btSoftBody.h" -#include "btSoftBodyHelpers.h" -#include "btSoftBodySolvers.h" -#include "btDefaultSoftBodySolver.h" -#include "LinearMath/btSerializer.h" - - -btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld( - btDispatcher* dispatcher, - btBroadphaseInterface* pairCache, - btConstraintSolver* constraintSolver, - btCollisionConfiguration* collisionConfiguration, - btSoftBodySolver *softBodySolver ) : - btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration), - m_softBodySolver( softBodySolver ), - m_ownsSolver(false) -{ - if( !m_softBodySolver ) - { - void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16); - m_softBodySolver = new(ptr) btDefaultSoftBodySolver(); - m_ownsSolver = true; - } - - m_drawFlags = fDrawFlags::Std; - m_drawNodeTree = true; - m_drawFaceTree = false; - m_drawClusterTree = false; - m_sbi.m_broadphase = pairCache; - m_sbi.m_dispatcher = dispatcher; - m_sbi.m_sparsesdf.Initialize(); - m_sbi.m_sparsesdf.Reset(); - - m_sbi.air_density = (btScalar)1.2; - m_sbi.water_density = 0; - m_sbi.water_offset = 0; - m_sbi.water_normal = btVector3(0,0,0); - m_sbi.m_gravity.setValue(0,-10,0); - - m_sbi.m_sparsesdf.Initialize(); - - -} - -btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() -{ - if (m_ownsSolver) - { - m_softBodySolver->~btSoftBodySolver(); - btAlignedFree(m_softBodySolver); - } -} - -void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) -{ - btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep ); - { - BT_PROFILE("predictUnconstraintMotionSoftBody"); - m_softBodySolver->predictMotion( timeStep ); - } -} - -void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep ) -{ - - // Let the solver grab the soft bodies and if necessary optimize for it - m_softBodySolver->optimize( getSoftBodyArray() ); - - if( !m_softBodySolver->checkInitialized() ) - { - btAssert( "Solver initialization failed\n" ); - } - - btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); - - ///solve soft bodies constraints - solveSoftBodiesConstraints( timeStep ); - - //self collisions - for ( int i=0;idefaultCollisionHandler(psb); - } - - ///update soft bodies - m_softBodySolver->updateSoftBodies( ); - - // End solver-wise simulation step - // /////////////////////////////// - -} - -void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep ) -{ - BT_PROFILE("solveSoftConstraints"); - - if(m_softBodies.size()) - { - btSoftBody::solveClusters(m_softBodies); - } - - // Solve constraints solver-wise - m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() ); - -} - -void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask) -{ - m_softBodies.push_back(body); - - // Set the soft body solver that will deal with this body - // to be the world's solver - body->setSoftBodySolver( m_softBodySolver ); - - btCollisionWorld::addCollisionObject(body, - collisionFilterGroup, - collisionFilterMask); - -} - -void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body) -{ - m_softBodies.remove(body); - - btCollisionWorld::removeCollisionObject(body); -} - -void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject) -{ - btSoftBody* body = btSoftBody::upcast(collisionObject); - if (body) - removeSoftBody(body); - else - btDiscreteDynamicsWorld::removeCollisionObject(collisionObject); -} - -void btSoftRigidDynamicsWorld::debugDrawWorld() -{ - btDiscreteDynamicsWorld::debugDrawWorld(); - - if (getDebugDrawer()) - { - int i; - for ( i=0;im_softBodies.size();i++) - { - btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; - if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) - { - btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); - btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); - } - - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); - if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); - if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); - } - } - } -} - - - - -struct btSoftSingleRayCallback : public btBroadphaseRayCallback -{ - btVector3 m_rayFromWorld; - btVector3 m_rayToWorld; - btTransform m_rayFromTrans; - btTransform m_rayToTrans; - btVector3 m_hitNormal; - - const btSoftRigidDynamicsWorld* m_world; - btCollisionWorld::RayResultCallback& m_resultCallback; - - btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback) - :m_rayFromWorld(rayFromWorld), - m_rayToWorld(rayToWorld), - m_world(world), - m_resultCallback(resultCallback) - { - m_rayFromTrans.setIdentity(); - m_rayFromTrans.setOrigin(m_rayFromWorld); - m_rayToTrans.setIdentity(); - m_rayToTrans.setOrigin(m_rayToWorld); - - btVector3 rayDir = (rayToWorld-rayFromWorld); - - rayDir.normalize (); - ///what about division by zero? --> just set rayDirection[i] to INF/1e30 - m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0]; - m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1]; - m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2]; - m_signs[0] = m_rayDirectionInverse[0] < 0.0; - m_signs[1] = m_rayDirectionInverse[1] < 0.0; - m_signs[2] = m_rayDirectionInverse[2] < 0.0; - - m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld); - - } - - - - virtual bool process(const btBroadphaseProxy* proxy) - { - ///terminate further ray tests, once the closestHitFraction reached zero - if (m_resultCallback.m_closestHitFraction == btScalar(0.f)) - return false; - - btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject; - - //only perform raycast if filterMask matches - if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) - { - //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); - //btVector3 collisionObjectAabbMin,collisionObjectAabbMax; -#if 0 -#ifdef RECALCULATE_AABB - btVector3 collisionObjectAabbMin,collisionObjectAabbMax; - collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); -#else - //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax); - const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin; - const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax; -#endif -#endif - //btScalar hitLambda = m_resultCallback.m_closestHitFraction; - //culling already done by broadphase - //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal)) - { - m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans, - collisionObject, - collisionObject->getCollisionShape(), - collisionObject->getWorldTransform(), - m_resultCallback); - } - } - return true; - } -}; - -void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const -{ - BT_PROFILE("rayTest"); - /// use the broadphase to accelerate the search for objects, based on their aabb - /// and for each object with ray-aabb overlap, perform an exact ray test - btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback); - -#ifndef USE_BRUTEFORCE_RAYBROADPHASE - m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB); -#else - for (int i=0;igetNumCollisionObjects();i++) - { - rayCB.process(m_collisionObjects[i]->getBroadphaseHandle()); - } -#endif //USE_BRUTEFORCE_RAYBROADPHASE - -} - - -void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, - btCollisionObject* collisionObject, - const btCollisionShape* collisionShape, - const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback) -{ - if (collisionShape->isSoftBody()) { - btSoftBody* softBody = btSoftBody::upcast(collisionObject); - if (softBody) { - btSoftBody::sRayCast softResult; - if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) - { - - if (softResult.fraction<= resultCallback.m_closestHitFraction) - { - - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = 0; - shapeInfo.m_triangleIndex = softResult.index; - // get the normal - btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); - btVector3 normal=-rayDir; - normal.normalize(); - - if (softResult.feature == btSoftBody::eFeature::Face) - { - normal = softBody->m_faces[softResult.index].m_normal; - if (normal.dot(rayDir) > 0) { - // normal always point toward origin of the ray - normal = -normal; - } - } - - btCollisionWorld::LocalRayResult rayResult - (collisionObject, - &shapeInfo, - normal, - softResult.fraction); - bool normalInWorldSpace = true; - resultCallback.addSingleResult(rayResult,normalInWorldSpace); - } - } - } - } - else { - btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback); - } -} - - -void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer) -{ - int i; - //serialize all collision objects - for (i=0;igetInternalType() & btCollisionObject::CO_SOFT_BODY) - { - int len = colObj->calculateSerializeBufferSize(); - btChunk* chunk = serializer->allocate(len,1); - const char* structType = colObj->serialize(chunk->m_oldPtr, serializer); - serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj); - } - } - -} - -void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer) -{ - - serializer->startSerialization(); - - serializeDynamicsWorldInfo( serializer); - - serializeSoftBodies(serializer); - - serializeRigidBodies(serializer); - - serializeCollisionObjects(serializer); - - serializer->finishSerialization(); -} - - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.h deleted file mode 100644 index 3e0efafd..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftRigidDynamicsWorld.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H -#define BT_SOFT_RIGID_DYNAMICS_WORLD_H - -#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" -#include "btSoftBody.h" - -typedef btAlignedObjectArray btSoftBodyArray; - -class btSoftBodySolver; - -class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld -{ - - btSoftBodyArray m_softBodies; - int m_drawFlags; - bool m_drawNodeTree; - bool m_drawFaceTree; - bool m_drawClusterTree; - btSoftBodyWorldInfo m_sbi; - ///Solver classes that encapsulate multiple soft bodies for solving - btSoftBodySolver *m_softBodySolver; - bool m_ownsSolver; - -protected: - - virtual void predictUnconstraintMotion(btScalar timeStep); - - virtual void internalSingleStepSimulation( btScalar timeStep); - - void solveSoftBodiesConstraints( btScalar timeStep ); - - void serializeSoftBodies(btSerializer* serializer); - -public: - - btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver *softBodySolver = 0 ); - - virtual ~btSoftRigidDynamicsWorld(); - - virtual void debugDrawWorld(); - - void addSoftBody(btSoftBody* body,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); - - void removeSoftBody(btSoftBody* body); - - ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject - virtual void removeCollisionObject(btCollisionObject* collisionObject); - - int getDrawFlags() const { return(m_drawFlags); } - void setDrawFlags(int f) { m_drawFlags=f; } - - btSoftBodyWorldInfo& getWorldInfo() - { - return m_sbi; - } - const btSoftBodyWorldInfo& getWorldInfo() const - { - return m_sbi; - } - - virtual btDynamicsWorldType getWorldType() const - { - return BT_SOFT_RIGID_DYNAMICS_WORLD; - } - - btSoftBodyArray& getSoftBodyArray() - { - return m_softBodies; - } - - const btSoftBodyArray& getSoftBodyArray() const - { - return m_softBodies; - } - - - virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; - - /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. - /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. - /// This allows more customization. - static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, - btCollisionObject* collisionObject, - const btCollisionShape* collisionShape, - const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback); - - virtual void serialize(btSerializer* serializer); - -}; - -#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp deleted file mode 100644 index 72043e69..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btSoftSoftCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "btSoftBody.h" -#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" - -#define USE_PERSISTENT_CONTACTS 1 - -btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* /*obj0*/,const btCollisionObjectWrapper* /*obj1*/) -: btCollisionAlgorithm(ci) -//m_ownManifold(false), -//m_manifoldPtr(mf) -{ -} - -btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm() -{ -} - -void btSoftSoftCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) -{ - btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject(); - btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject(); - soft0->getSoftBodySolver()->processCollision(soft0, soft1); -} - -btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) -{ - //not yet - return 1.f; -} diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h deleted file mode 100644 index 43b1439c..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFT_SOFT_COLLISION_ALGORITHM_H -#define BT_SOFT_SOFT_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" - -class btPersistentManifold; -class btSoftBody; - -///collision detection between two btSoftBody shapes -class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - - btSoftBody* m_softBody0; - btSoftBody* m_softBody1; - - -public: - btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} - - virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - manifoldArray.push_back(m_manifoldPtr); - } - - btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); - - virtual ~btSoftSoftCollisionAlgorithm(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) - { - int bbsize = sizeof(btSoftSoftCollisionAlgorithm); - void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); - return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0Wrap,body1Wrap); - } - }; - -}; - -#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H - - diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/btSparseSDF.h b/Code/Physics/Bullet Source/src/BulletSoftBody/btSparseSDF.h deleted file mode 100644 index bcf0c798..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/btSparseSDF.h +++ /dev/null @@ -1,319 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSparseSdf implementation by Nathanael Presson - -#ifndef BT_SPARSE_SDF_H -#define BT_SPARSE_SDF_H - -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" - -// Modified Paul Hsieh hash -template -unsigned int HsiehHash(const void* pdata) -{ - const unsigned short* data=(const unsigned short*)pdata; - unsigned hash=DWORDLEN<<2,tmp; - for(int i=0;i>11; - } - hash^=hash<<3;hash+=hash>>5; - hash^=hash<<4;hash+=hash>>17; - hash^=hash<<25;hash+=hash>>6; - return(hash); -} - -template -struct btSparseSdf -{ - // - // Inner types - // - struct IntFrac - { - int b; - int i; - btScalar f; - }; - struct Cell - { - btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]; - int c[3]; - int puid; - unsigned hash; - const btCollisionShape* pclient; - Cell* next; - }; - // - // Fields - // - - btAlignedObjectArray cells; - btScalar voxelsz; - int puid; - int ncells; - int m_clampCells; - int nprobes; - int nqueries; - - // - // Methods - // - - // - void Initialize(int hashsize=2383, int clampCells = 256*1024) - { - //avoid a crash due to running out of memory, so clamp the maximum number of cells allocated - //if this limit is reached, the SDF is reset (at the cost of some performance during the reset) - m_clampCells = clampCells; - cells.resize(hashsize,0); - Reset(); - } - // - void Reset() - { - for(int i=0,ni=cells.size();inext; - delete pc; - pc=pn; - } - } - voxelsz =0.25; - puid =0; - ncells =0; - nprobes =1; - nqueries =1; - } - // - void GarbageCollect(int lifetime=256) - { - const int life=puid-lifetime; - for(int i=0;inext; - if(pc->puidnext=pn; else root=pn; - delete pc;pc=pp;--ncells; - } - pp=pc;pc=pn; - } - } - //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries); - nqueries=1; - nprobes=1; - ++puid; ///@todo: Reset puid's when int range limit is reached */ - /* else setup a priority list... */ - } - // - int RemoveReferences(btCollisionShape* pcs) - { - int refcount=0; - for(int i=0;inext; - if(pc->pclient==pcs) - { - if(pp) pp->next=pn; else root=pn; - delete pc;pc=pp;++refcount; - } - pp=pc;pc=pn; - } - } - return(refcount); - } - // - btScalar Evaluate( const btVector3& x, - const btCollisionShape* shape, - btVector3& normal, - btScalar margin) - { - /* Lookup cell */ - const btVector3 scx=x/voxelsz; - const IntFrac ix=Decompose(scx.x()); - const IntFrac iy=Decompose(scx.y()); - const IntFrac iz=Decompose(scx.z()); - const unsigned h=Hash(ix.b,iy.b,iz.b,shape); - Cell*& root=cells[static_cast(h%cells.size())]; - Cell* c=root; - ++nqueries; - while(c) - { - ++nprobes; - if( (c->hash==h) && - (c->c[0]==ix.b) && - (c->c[1]==iy.b) && - (c->c[2]==iz.b) && - (c->pclient==shape)) - { break; } - else - { c=c->next; } - } - if(!c) - { - ++nprobes; - ++ncells; - int sz = sizeof(Cell); - if (ncells>m_clampCells) - { - static int numResets=0; - numResets++; -// printf("numResets=%d\n",numResets); - Reset(); - } - - c=new Cell(); - c->next=root;root=c; - c->pclient=shape; - c->hash=h; - c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b; - BuildCell(*c); - } - c->puid=puid; - /* Extract infos */ - const int o[]={ ix.i,iy.i,iz.i}; - const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0], - c->d[o[0]+1][o[1]+0][o[2]+0], - c->d[o[0]+1][o[1]+1][o[2]+0], - c->d[o[0]+0][o[1]+1][o[2]+0], - c->d[o[0]+0][o[1]+0][o[2]+1], - c->d[o[0]+1][o[1]+0][o[2]+1], - c->d[o[0]+1][o[1]+1][o[2]+1], - c->d[o[0]+0][o[1]+1][o[2]+1]}; - /* Normal */ -#if 1 - const btScalar gx[]={ d[1]-d[0],d[2]-d[3], - d[5]-d[4],d[6]-d[7]}; - const btScalar gy[]={ d[3]-d[0],d[2]-d[1], - d[7]-d[4],d[6]-d[5]}; - const btScalar gz[]={ d[4]-d[0],d[5]-d[1], - d[7]-d[3],d[6]-d[2]}; - normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f), - Lerp(gx[2],gx[3],iy.f),iz.f)); - normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f), - Lerp(gy[2],gy[3],ix.f),iz.f)); - normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f), - Lerp(gz[2],gz[3],ix.f),iy.f)); - normal = normal.normalized(); -#else - normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); -#endif - /* Distance */ - const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), - Lerp(d[3],d[2],ix.f),iy.f); - const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f), - Lerp(d[7],d[6],ix.f),iy.f); - return(Lerp(d0,d1,iz.f)-margin); - } - // - void BuildCell(Cell& c) - { - const btVector3 org=btVector3( (btScalar)c.c[0], - (btScalar)c.c[1], - (btScalar)c.c[2]) * - CELLSIZE*voxelsz; - for(int k=0;k<=CELLSIZE;++k) - { - const btScalar z=voxelsz*k+org.z(); - for(int j=0;j<=CELLSIZE;++j) - { - const btScalar y=voxelsz*j+org.y(); - for(int i=0;i<=CELLSIZE;++i) - { - const btScalar x=voxelsz*i+org.x(); - c.d[i][j][k]=DistanceToShape( btVector3(x,y,z), - c.pclient); - } - } - } - } - // - static inline btScalar DistanceToShape(const btVector3& x, - const btCollisionShape* shape) - { - btTransform unit; - unit.setIdentity(); - if(shape->isConvex()) - { - btGjkEpaSolver2::sResults res; - const btConvexShape* csh=static_cast(shape); - return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res)); - } - return(0); - } - // - static inline IntFrac Decompose(btScalar x) - { - /* That one need a lot of improvements... */ - /* Remove test, faster floor... */ - IntFrac r; - x/=CELLSIZE; - const int o=x<0?(int)(-x+1):0; - x+=o;r.b=(int)x; - const btScalar k=(x-r.b)*CELLSIZE; - r.i=(int)k;r.f=k-r.i;r.b-=o; - return(r); - } - // - static inline btScalar Lerp(btScalar a,btScalar b,btScalar t) - { - return(a+(b-a)*t); - } - - - - // - static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape) - { - struct btS - { - int x,y,z; - void* p; - }; - - btS myset; - - myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape; - const void* ptr = &myset; - - unsigned int result = HsiehHash (ptr); - - - return result; - } -}; - - -#endif //BT_SPARSE_SDF_H diff --git a/Code/Physics/Bullet Source/src/BulletSoftBody/premake4.lua b/Code/Physics/Bullet Source/src/BulletSoftBody/premake4.lua deleted file mode 100644 index 339043f5..00000000 --- a/Code/Physics/Bullet Source/src/BulletSoftBody/premake4.lua +++ /dev/null @@ -1,11 +0,0 @@ - project "BulletSoftBody" - - kind "StaticLib" - targetdir "../../lib" - includedirs { - "..", - } - files { - "**.cpp", - "**.h" - } \ No newline at end of file diff --git a/Code/Physics/Bullet Source/src/CMakeLists.txt b/Code/Physics/Bullet Source/src/CMakeLists.txt deleted file mode 100644 index 3a736b42..00000000 --- a/Code/Physics/Bullet Source/src/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -SUBDIRS( BulletSoftBody BulletCollision BulletDynamics LinearMath ) - -IF(BUILD_MULTITHREADING) - SUBDIRS(MiniCL BulletMultiThreaded) -ENDIF() - -IF(INSTALL_LIBS) - #INSTALL of other files requires CMake 2.6 - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - # Don't actually need to install any common files, the frameworks include everything - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(FILES btBulletCollisionCommon.h btBulletDynamicsCommon.h Bullet-C-Api.h DESTINATION ${INCLUDE_INSTALL_DIR}) - INSTALL(FILES vectormath/vmInclude.h DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath) - INSTALL(FILES vectormath/scalar/boolInVec.h - vectormath/scalar/floatInVec.h - vectormath/scalar/mat_aos.h - vectormath/scalar/quat_aos.h - vectormath/scalar/vec_aos.h - vectormath/scalar/vectormath_aos.h - DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath/scalar) - INSTALL(FILES vectormath/sse/boolInVec.h - vectormath/sse/floatInVec.h - vectormath/sse/mat_aos.h - vectormath/sse/quat_aos.h - vectormath/sse/vec_aos.h - vectormath/sse/vecidx_aos.h - vectormath/sse/vectormath_aos.h - DESTINATION ${INCLUDE_INSTALL_DIR}/vectormath/sse) - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) -ENDIF(INSTALL_LIBS) diff --git a/Code/Physics/Bullet Source/src/Makefile.am b/Code/Physics/Bullet Source/src/Makefile.am deleted file mode 100644 index 0ecb5c9f..00000000 --- a/Code/Physics/Bullet Source/src/Makefile.am +++ /dev/null @@ -1,612 +0,0 @@ -bullet_includedir = $(includedir)/bullet -nobase_bullet_include_HEADERS = \ - btBulletDynamicsCommon.h \ - Bullet-C-Api.h \ - btBulletCollisionCommon.h - -if CONDITIONAL_BUILD_MULTITHREADED -nobase_bullet_include_HEADERS += \ - BulletMultiThreaded/PosixThreadSupport.h \ - BulletMultiThreaded/vectormath/scalar/cpp/mat_aos.h \ - BulletMultiThreaded/vectormath/scalar/cpp/vec_aos.h \ - BulletMultiThreaded/vectormath/scalar/cpp/quat_aos.h \ - BulletMultiThreaded/vectormath/scalar/cpp/vectormath_aos.h \ - BulletMultiThreaded/PpuAddressSpace.h \ - BulletMultiThreaded/SpuCollisionTaskProcess.h \ - BulletMultiThreaded/PlatformDefinitions.h \ - BulletMultiThreaded/vectormath2bullet.h \ - BulletMultiThreaded/SpuGatheringCollisionDispatcher.h \ - BulletMultiThreaded/SpuCollisionObjectWrapper.h \ - BulletMultiThreaded/SpuSampleTaskProcess.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h \ - BulletMultiThreaded/SpuSync.h \ - BulletMultiThreaded/btThreadSupportInterface.h \ - BulletMultiThreaded/SpuLibspe2Support.h \ - BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h \ - BulletMultiThreaded/SpuFakeDma.h \ - BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h \ - BulletMultiThreaded/SpuDoubleBuffer.h \ - BulletMultiThreaded/Win32ThreadSupport.h \ - BulletMultiThreaded/SequentialThreadSupport.h - -lib_LTLIBRARIES = libLinearMath.la libBulletCollision.la libBulletDynamics.la libBulletSoftBody.la libBulletMultiThreaded.la - -libBulletMultiThreaded_la_CXXFLAGS = ${CXXFLAGS} -I./BulletMultiThreaded/vectormath/scalar/cpp -libBulletMultiThreaded_la_SOURCES =\ - BulletMultiThreaded/SpuCollisionObjectWrapper.cpp \ - BulletMultiThreaded/SpuSampleTask/SpuSampleTask.cpp \ - BulletMultiThreaded/SpuLibspe2Support.cpp \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.cpp \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.cpp \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.cpp \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.cpp \ - BulletMultiThreaded/btThreadSupportInterface.cpp \ - BulletMultiThreaded/SequentialThreadSupport.cpp \ - BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp \ - BulletMultiThreaded/Win32ThreadSupport.cpp \ - BulletMultiThreaded/SpuFakeDma.cpp \ - BulletMultiThreaded/PosixThreadSupport.cpp \ - BulletMultiThreaded/SpuCollisionTaskProcess.cpp \ - BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp \ - BulletMultiThreaded/SpuSampleTaskProcess.cpp \ - BulletMultiThreaded/SpuSampleTask/SpuSampleTask.h \ - BulletMultiThreaded/PpuAddressSpace.h \ - BulletMultiThreaded/SpuSampleTaskProcess.h \ - BulletMultiThreaded/SequentialThreadSupport.h \ - BulletMultiThreaded/PlatformDefinitions.h \ - BulletMultiThreaded/Win32ThreadSupport.h \ - BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.h \ - BulletMultiThreaded/btThreadSupportInterface.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuConvexPenetrationDepthSolver.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuPreferredPenetrationDirections.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuLocalSupport.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuMinkowskiPenetrationDepthSolver.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuContactResult.h \ - BulletMultiThreaded/SpuGatheringCollisionDispatcher.h \ - BulletMultiThreaded/SpuFakeDma.h \ - BulletMultiThreaded/SpuSync.h \ - BulletMultiThreaded/SpuCollisionObjectWrapper.h \ - BulletMultiThreaded/SpuDoubleBuffer.h \ - BulletMultiThreaded/SpuCollisionTaskProcess.h \ - BulletMultiThreaded/PosixThreadSupport.h \ - BulletMultiThreaded/SpuLibspe2Support.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.h \ - BulletMultiThreaded/SpuNarrowPhaseCollisionTask/Box.h - -else -lib_LTLIBRARIES = libLinearMath.la libBulletCollision.la libBulletDynamics.la libBulletSoftBody.la -endif - - -libLinearMath_la_SOURCES = \ - LinearMath/btQuickprof.cpp \ - LinearMath/btGeometryUtil.cpp \ - LinearMath/btAlignedAllocator.cpp \ - LinearMath/btSerializer.cpp \ - LinearMath/btConvexHull.cpp \ - LinearMath/btPolarDecomposition.cpp \ - LinearMath/btVector3.cpp \ - LinearMath/btConvexHullComputer.cpp \ - LinearMath/btHashMap.h \ - LinearMath/btConvexHull.h \ - LinearMath/btAabbUtil2.h \ - LinearMath/btGeometryUtil.h \ - LinearMath/btQuadWord.h \ - LinearMath/btPoolAllocator.h \ - LinearMath/btPolarDecomposition.h \ - LinearMath/btScalar.h \ - LinearMath/btMinMax.h \ - LinearMath/btVector3.h \ - LinearMath/btList.h \ - LinearMath/btStackAlloc.h \ - LinearMath/btMatrix3x3.h \ - LinearMath/btMotionState.h \ - LinearMath/btAlignedAllocator.h \ - LinearMath/btQuaternion.h \ - LinearMath/btAlignedObjectArray.h \ - LinearMath/btQuickprof.h \ - LinearMath/btSerializer.h \ - LinearMath/btTransformUtil.h \ - LinearMath/btTransform.h \ - LinearMath/btDefaultMotionState.h \ - LinearMath/btIDebugDraw.h \ - LinearMath/btRandom.h - - -libBulletCollision_la_SOURCES = \ - BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp \ - BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp \ - BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp \ - BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp \ - BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp \ - BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp \ - BulletCollision/NarrowPhaseCollision/btConvexCast.cpp \ - BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp \ - BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp \ - BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp \ - BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp \ - BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp \ - BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btCollisionObject.cpp \ - BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btGhostObject.cpp \ - BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp \ - BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp \ - BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp \ - BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp \ - BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp \ - BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp \ - BulletCollision/CollisionDispatch/btManifoldResult.cpp \ - BulletCollision/CollisionDispatch/btCollisionWorld.cpp \ - BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btUnionFind.cpp \ - BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp \ - BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp \ - BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp \ - BulletCollision/CollisionShapes/btTetrahedronShape.cpp \ - BulletCollision/CollisionShapes/btShapeHull.cpp \ - BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp \ - BulletCollision/CollisionShapes/btCompoundShape.cpp \ - BulletCollision/CollisionShapes/btConeShape.cpp \ - BulletCollision/CollisionShapes/btConvexPolyhedron.cpp \ - BulletCollision/CollisionShapes/btMultiSphereShape.cpp \ - BulletCollision/CollisionShapes/btUniformScalingShape.cpp \ - BulletCollision/CollisionShapes/btSphereShape.cpp \ - BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp \ - BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp \ - BulletCollision/CollisionShapes/btTriangleMeshShape.cpp \ - BulletCollision/CollisionShapes/btTriangleBuffer.cpp \ - BulletCollision/CollisionShapes/btStaticPlaneShape.cpp \ - BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp \ - BulletCollision/CollisionShapes/btEmptyShape.cpp \ - BulletCollision/CollisionShapes/btCollisionShape.cpp \ - BulletCollision/CollisionShapes/btConvexShape.cpp \ - BulletCollision/CollisionShapes/btConvex2dShape.cpp \ - BulletCollision/CollisionShapes/btConvexInternalShape.cpp \ - BulletCollision/CollisionShapes/btConvexHullShape.cpp \ - BulletCollision/CollisionShapes/btTriangleCallback.cpp \ - BulletCollision/CollisionShapes/btCapsuleShape.cpp \ - BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp \ - BulletCollision/CollisionShapes/btConcaveShape.cpp \ - BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp \ - BulletCollision/CollisionShapes/btBoxShape.cpp \ - BulletCollision/CollisionShapes/btBox2dShape.cpp \ - BulletCollision/CollisionShapes/btOptimizedBvh.cpp \ - BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp \ - BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp \ - BulletCollision/CollisionShapes/btCylinderShape.cpp \ - BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp \ - BulletCollision/CollisionShapes/btStridingMeshInterface.cpp \ - BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp \ - BulletCollision/CollisionShapes/btTriangleMesh.cpp \ - BulletCollision/BroadphaseCollision/btAxisSweep3.cpp \ - BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp \ - BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp \ - BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp \ - BulletCollision/BroadphaseCollision/btDispatcher.cpp \ - BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp \ - BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp \ - BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp \ - BulletCollision/BroadphaseCollision/btDbvt.cpp \ - BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp \ - BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \ - BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \ - BulletCollision/NarrowPhaseCollision/btConvexCast.h \ - BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \ - BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \ - BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \ - BulletCollision/NarrowPhaseCollision/btPointCollector.h \ - BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \ - BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \ - BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \ - BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \ - BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \ - BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \ - BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \ - BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \ - BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \ - BulletCollision/CollisionDispatch/btCollisionObject.h \ - BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h \ - BulletCollision/CollisionDispatch/btGhostObject.h \ - BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \ - BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \ - BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \ - BulletCollision/CollisionDispatch/btBoxBoxDetector.h \ - BulletCollision/CollisionDispatch/btCollisionDispatcher.h \ - BulletCollision/CollisionDispatch/SphereTriangleDetector.h \ - BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btUnionFind.h \ - BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btHashedSimplePairCache.h \ - BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btSimulationIslandManager.h \ - BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \ - BulletCollision/CollisionDispatch/btCollisionWorld.h \ - BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \ - BulletCollision/CollisionDispatch/btManifoldResult.h \ - BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btCollisionConfiguration.h \ - BulletCollision/CollisionShapes/btConvexShape.h \ - BulletCollision/CollisionShapes/btConvex2dShape.h \ - BulletCollision/CollisionShapes/btTriangleCallback.h \ - BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \ - BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btCompoundShape.h \ - BulletCollision/CollisionShapes/btBoxShape.h \ - BulletCollision/CollisionShapes/btBox2dShape.h \ - BulletCollision/CollisionShapes/btMultiSphereShape.h \ - BulletCollision/CollisionShapes/btCollisionMargin.h \ - BulletCollision/CollisionShapes/btConcaveShape.h \ - BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btEmptyShape.h \ - BulletCollision/CollisionShapes/btUniformScalingShape.h \ - BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btMaterial.h \ - BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \ - BulletCollision/CollisionShapes/btTriangleInfoMap.h \ - BulletCollision/CollisionShapes/btSphereShape.h \ - BulletCollision/CollisionShapes/btConvexPointCloudShape.h \ - BulletCollision/CollisionShapes/btCapsuleShape.h \ - BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \ - BulletCollision/CollisionShapes/btCollisionShape.h \ - BulletCollision/CollisionShapes/btStaticPlaneShape.h \ - BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btStridingMeshInterface.h \ - BulletCollision/CollisionShapes/btTriangleMesh.h \ - BulletCollision/CollisionShapes/btTriangleBuffer.h \ - BulletCollision/CollisionShapes/btShapeHull.h \ - BulletCollision/CollisionShapes/btMinkowskiSumShape.h \ - BulletCollision/CollisionShapes/btOptimizedBvh.h \ - BulletCollision/CollisionShapes/btTriangleShape.h \ - BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \ - BulletCollision/CollisionShapes/btCylinderShape.h \ - BulletCollision/CollisionShapes/btTetrahedronShape.h \ - BulletCollision/CollisionShapes/btConvexInternalShape.h \ - BulletCollision/CollisionShapes/btConeShape.h \ - BulletCollision/CollisionShapes/btConvexHullShape.h \ - BulletCollision/BroadphaseCollision/btAxisSweep3.h \ - BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \ - BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \ - BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \ - BulletCollision/BroadphaseCollision/btDbvt.h \ - BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \ - BulletCollision/BroadphaseCollision/btDispatcher.h \ - BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \ - BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \ - BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \ - BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \ - BulletCollision/BroadphaseCollision/btQuantizedBvh.h \ - BulletCollision/Gimpact/btGImpactBvh.cpp\ - BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp\ - BulletCollision/Gimpact/btTriangleShapeEx.cpp\ - BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp\ - BulletCollision/Gimpact/btGImpactShape.cpp\ - BulletCollision/Gimpact/gim_box_set.cpp\ - BulletCollision/Gimpact/gim_contact.cpp\ - BulletCollision/Gimpact/gim_memory.cpp\ - BulletCollision/Gimpact/gim_tri_collision.cpp - -libBulletDynamics_la_SOURCES = \ - BulletDynamics/Dynamics/btRigidBody.cpp \ - BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp \ - BulletDynamics/Dynamics/Bullet-C-API.cpp \ - BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp \ - BulletDynamics/ConstraintSolver/btFixedConstraint.cpp \ - BulletDynamics/ConstraintSolver/btGearConstraint.cpp \ - BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp \ - BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp \ - BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp \ - BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp \ - BulletDynamics/ConstraintSolver/btTypedConstraint.cpp \ - BulletDynamics/ConstraintSolver/btContactConstraint.cpp \ - BulletDynamics/ConstraintSolver/btSliderConstraint.cpp \ - BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp \ - BulletDynamics/ConstraintSolver/btHingeConstraint.cpp \ - BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp \ - BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp \ - BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp \ - BulletDynamics/Vehicle/btWheelInfo.cpp \ - BulletDynamics/Vehicle/btRaycastVehicle.cpp \ - BulletDynamics/Character/btKinematicCharacterController.cpp \ - BulletDynamics/Character/btKinematicCharacterController.h \ - BulletDynamics/Character/btCharacterControllerInterface.h \ - BulletDynamics/Dynamics/btActionInterface.h \ - BulletDynamics/Dynamics/btSimpleDynamicsWorld.h \ - BulletDynamics/Dynamics/btRigidBody.h \ - BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h \ - BulletDynamics/Dynamics/btDynamicsWorld.h \ - BulletDynamics/ConstraintSolver/btSolverBody.h \ - BulletDynamics/ConstraintSolver/btConstraintSolver.h \ - BulletDynamics/ConstraintSolver/btConeTwistConstraint.h \ - BulletDynamics/ConstraintSolver/btTypedConstraint.h \ - BulletDynamics/ConstraintSolver/btContactSolverInfo.h \ - BulletDynamics/ConstraintSolver/btContactConstraint.h \ - BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h \ - BulletDynamics/ConstraintSolver/btJacobianEntry.h \ - BulletDynamics/ConstraintSolver/btSolverConstraint.h \ - BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h \ - BulletDynamics/ConstraintSolver/btGearConstraint.h \ - BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h \ - BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h \ - BulletDynamics/ConstraintSolver/btSliderConstraint.h \ - BulletDynamics/ConstraintSolver/btHingeConstraint.h \ - BulletDynamics/ConstraintSolver/btHinge2Constraint.h \ - BulletDynamics/ConstraintSolver/btUniversalConstraint.h \ - BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h \ - BulletDynamics/Vehicle/btVehicleRaycaster.h \ - BulletDynamics/Vehicle/btRaycastVehicle.h \ - BulletDynamics/Vehicle/btWheelInfo.h \ - BulletDynamics/Featherstone/btMultiBody.cpp \ - BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp \ - BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp \ - BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp \ - BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp \ - BulletDynamics/Featherstone/btMultiBodyJointMotor.h \ - BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h \ - BulletDynamics/Featherstone/btMultiBody.h \ - BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h \ - BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h \ - BulletDynamics/Featherstone/btMultiBodyLink.h \ - BulletDynamics/Featherstone/btMultiBodyLinkCollider.h \ - BulletDynamics/Featherstone/btMultiBodySolverConstraint.h \ - BulletDynamics/Featherstone/btMultiBodyConstraint.h \ - BulletDynamics/Featherstone/btMultiBodyPoint2Point.h \ - BulletDynamics/Featherstone/btMultiBodyConstraint.cpp \ - BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp \ - BulletDynamics/MLCPSolvers/btDantzigLCP.cpp \ - BulletDynamics/MLCPSolvers/btMLCPSolver.cpp \ - BulletDynamics/MLCPSolvers/btDantzigLCP.h \ - BulletDynamics/MLCPSolvers/btDantzigSolver.h \ - BulletDynamics/MLCPSolvers/btMLCPSolver.h \ - BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h \ - BulletDynamics/MLCPSolvers/btPATHSolver.h \ - BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h - - - - -libBulletSoftBody_la_SOURCES = \ - BulletSoftBody/btDefaultSoftBodySolver.cpp \ - BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp \ - BulletSoftBody/btSoftBody.cpp \ - BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp \ - BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp \ - BulletSoftBody/btSoftRigidDynamicsWorld.cpp \ - BulletSoftBody/btSoftBodyHelpers.cpp \ - BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp \ - BulletSoftBody/btSparseSDF.h \ - BulletSoftBody/btSoftRigidCollisionAlgorithm.h \ - BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h \ - BulletSoftBody/btSoftBody.h \ - BulletSoftBody/btSoftSoftCollisionAlgorithm.h \ - BulletSoftBody/btSoftBodyInternals.h \ - BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h \ - BulletSoftBody/btSoftRigidDynamicsWorld.h \ - BulletSoftBody/btSoftBodyHelpers.h - - - -nobase_bullet_include_HEADERS += \ - BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h \ - BulletSoftBody/btSoftBodyInternals.h \ - BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h \ - BulletSoftBody/btSoftSoftCollisionAlgorithm.h \ - BulletSoftBody/btSoftBody.h \ - BulletSoftBody/btSoftBodyHelpers.h \ - BulletSoftBody/btSparseSDF.h \ - BulletSoftBody/btSoftRigidCollisionAlgorithm.h \ - BulletSoftBody/btSoftRigidDynamicsWorld.h \ - BulletDynamics/Vehicle/btRaycastVehicle.h \ - BulletDynamics/Vehicle/btWheelInfo.h \ - BulletDynamics/Vehicle/btVehicleRaycaster.h \ - BulletDynamics/Dynamics/btActionInterface.h \ - BulletDynamics/Dynamics/btRigidBody.h \ - BulletDynamics/Dynamics/btDynamicsWorld.h \ - BulletDynamics/Dynamics/btSimpleDynamicsWorld.h \ - BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h \ - BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h \ - BulletDynamics/ConstraintSolver/btSolverConstraint.h \ - BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h \ - BulletDynamics/ConstraintSolver/btTypedConstraint.h \ - BulletDynamics/ConstraintSolver/btSliderConstraint.h \ - BulletDynamics/ConstraintSolver/btConstraintSolver.h \ - BulletDynamics/ConstraintSolver/btContactConstraint.h \ - BulletDynamics/ConstraintSolver/btContactSolverInfo.h \ - BulletDynamics/ConstraintSolver/btGearConstraint.h \ - BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h \ - BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h \ - BulletDynamics/ConstraintSolver/btJacobianEntry.h \ - BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h \ - BulletDynamics/ConstraintSolver/btConeTwistConstraint.h \ - BulletDynamics/ConstraintSolver/btHingeConstraint.h \ - BulletDynamics/ConstraintSolver/btHinge2Constraint.h \ - BulletDynamics/ConstraintSolver/btUniversalConstraint.h \ - BulletDynamics/ConstraintSolver/btSolverBody.h \ - BulletDynamics/Character/btCharacterControllerInterface.h \ - BulletDynamics/Character/btKinematicCharacterController.h \ - BulletDynamics/Featherstone/btMultiBody.h \ - BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h \ - BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h \ - BulletDynamics/Featherstone/btMultiBodyLink.h \ - BulletDynamics/Featherstone/btMultiBodyLinkCollider.h \ - BulletDynamics/Featherstone/btMultiBodySolverConstraint.h \ - BulletDynamics/Featherstone/btMultiBodyConstraint.h \ - BulletDynamics/Featherstone/btMultiBodyPoint2Point.h \ - BulletDynamics/MLCPSolvers/btDantzigLCP.h \ - BulletDynamics/MLCPSolvers/btDantzigSolver.h \ - BulletDynamics/MLCPSolvers/btMLCPSolver.h \ - BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h \ - BulletDynamics/MLCPSolvers/btPATHSolver.h \ - BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h \ - BulletCollision/CollisionShapes/btShapeHull.h \ - BulletCollision/CollisionShapes/btConcaveShape.h \ - BulletCollision/CollisionShapes/btCollisionMargin.h \ - BulletCollision/CollisionShapes/btCompoundShape.h \ - BulletCollision/CollisionShapes/btConvexHullShape.h \ - BulletCollision/CollisionShapes/btCylinderShape.h \ - BulletCollision/CollisionShapes/btTriangleMesh.h \ - BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \ - BulletCollision/CollisionShapes/btUniformScalingShape.h \ - BulletCollision/CollisionShapes/btConvexPointCloudShape.h \ - BulletCollision/CollisionShapes/btTetrahedronShape.h \ - BulletCollision/CollisionShapes/btCapsuleShape.h \ - BulletCollision/CollisionShapes/btSphereShape.h \ - BulletCollision/CollisionShapes/btMultiSphereShape.h \ - BulletCollision/CollisionShapes/btConvexInternalShape.h \ - BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btStridingMeshInterface.h \ - BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btEmptyShape.h \ - BulletCollision/CollisionShapes/btOptimizedBvh.h \ - BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btTriangleCallback.h \ - BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \ - BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \ - BulletCollision/CollisionShapes/btTriangleInfoMap.h \ - BulletCollision/CollisionShapes/btTriangleBuffer.h \ - BulletCollision/CollisionShapes/btConvexShape.h \ - BulletCollision/CollisionShapes/btConvex2dShape.h \ - BulletCollision/CollisionShapes/btStaticPlaneShape.h \ - BulletCollision/CollisionShapes/btConeShape.h \ - BulletCollision/CollisionShapes/btCollisionShape.h \ - BulletCollision/CollisionShapes/btTriangleShape.h \ - BulletCollision/CollisionShapes/btBoxShape.h \ - BulletCollision/CollisionShapes/btBox2dShape.h \ - BulletCollision/CollisionShapes/btMinkowskiSumShape.h \ - BulletCollision/CollisionShapes/btTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btMaterial.h \ - BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \ - BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \ - BulletCollision/NarrowPhaseCollision/btConvexCast.h \ - BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \ - BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \ - BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \ - BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \ - BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \ - BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \ - BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \ - BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \ - BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \ - BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \ - BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \ - BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \ - BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \ - BulletCollision/NarrowPhaseCollision/btPointCollector.h \ - BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \ - BulletCollision/BroadphaseCollision/btDbvt.h \ - BulletCollision/BroadphaseCollision/btDispatcher.h \ - BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \ - BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \ - BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \ - BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \ - BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \ - BulletCollision/BroadphaseCollision/btQuantizedBvh.h \ - BulletCollision/BroadphaseCollision/btAxisSweep3.h \ - BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \ - BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \ - BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \ - BulletCollision/CollisionDispatch/btUnionFind.h \ - BulletCollision/CollisionDispatch/btCollisionConfiguration.h \ - BulletCollision/CollisionDispatch/btCollisionDispatcher.h \ - BulletCollision/CollisionDispatch/SphereTriangleDetector.h \ - BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btCollisionWorld.h \ - BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \ - BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \ - BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \ - BulletCollision/CollisionDispatch/btCollisionObject.h \ - BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h \ - BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \ - BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btHashedSimplePairCache.h \ - BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btGhostObject.h \ - BulletCollision/CollisionDispatch/btSimulationIslandManager.h \ - BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btBoxBoxDetector.h \ - BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \ - BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \ - BulletCollision/CollisionDispatch/btManifoldResult.h \ - BulletCollision/Gimpact/gim_memory.h \ - BulletCollision/Gimpact/gim_clip_polygon.h \ - BulletCollision/Gimpact/gim_bitset.h \ - BulletCollision/Gimpact/gim_linear_math.h \ - BulletCollision/Gimpact/btGeometryOperations.h \ - BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h \ - BulletCollision/Gimpact/btGImpactBvh.h \ - BulletCollision/Gimpact/gim_box_set.h \ - BulletCollision/Gimpact/gim_array.h \ - BulletCollision/Gimpact/btGImpactShape.h \ - BulletCollision/Gimpact/btTriangleShapeEx.h \ - BulletCollision/Gimpact/btClipPolygon.h \ - BulletCollision/Gimpact/gim_box_collision.h \ - BulletCollision/Gimpact/gim_tri_collision.h \ - BulletCollision/Gimpact/gim_geometry.h \ - BulletCollision/Gimpact/gim_math.h \ - BulletCollision/Gimpact/btQuantization.h \ - BulletCollision/Gimpact/btGImpactQuantizedBvh.h \ - BulletCollision/Gimpact/gim_geom_types.h \ - BulletCollision/Gimpact/gim_basic_geometry_operations.h \ - BulletCollision/Gimpact/gim_contact.h \ - BulletCollision/Gimpact/gim_hash_table.h \ - BulletCollision/Gimpact/gim_radixsort.h \ - BulletCollision/Gimpact/btGImpactMassUtil.h \ - BulletCollision/Gimpact/btGenericPoolAllocator.h \ - BulletCollision/Gimpact/btBoxCollision.h \ - BulletCollision/Gimpact/btContactProcessing.h \ - LinearMath/btGeometryUtil.h \ - LinearMath/btConvexHull.h \ - LinearMath/btList.h \ - LinearMath/btMatrix3x3.h \ - LinearMath/btVector3.h \ - LinearMath/btPoolAllocator.h \ - LinearMath/btPolarDecomposition.h \ - LinearMath/btScalar.h \ - LinearMath/btDefaultMotionState.h \ - LinearMath/btTransform.h \ - LinearMath/btQuadWord.h \ - LinearMath/btAabbUtil2.h \ - LinearMath/btTransformUtil.h \ - LinearMath/btRandom.h \ - LinearMath/btQuaternion.h \ - LinearMath/btMinMax.h \ - LinearMath/btMotionState.h \ - LinearMath/btIDebugDraw.h \ - LinearMath/btAlignedAllocator.h \ - LinearMath/btStackAlloc.h \ - LinearMath/btAlignedObjectArray.h \ - LinearMath/btHashMap.h \ - LinearMath/btQuickprof.h\ - LinearMath/btSerializer.h diff --git a/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt b/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt deleted file mode 100644 index f351b1ce..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ -#MiniCL provides a small subset of OpenCL - -INCLUDE_DIRECTORIES( - ${BULLET_PHYSICS_SOURCE_DIR}/src - ${VECTOR_MATH_INCLUDE} -) - -SET(MiniCL_SRCS - MiniCL.cpp - MiniCLTaskScheduler.cpp - MiniCLTask/MiniCLTask.cpp -) - -SET(Root_HDRS - MiniCLTaskScheduler.h - cl.h - cl_gl.h - cl_platform.h - cl_MiniCL_Defs.h -) - -SET(MiniCLTask_HDRS - MiniCLTask/MiniCLTask.h -) - -SET(MiniCL_HDRS - ${Root_HDRS} - ${MiniCLTask_HDRS} -) - -ADD_LIBRARY(MiniCL ${MiniCL_SRCS} ${MiniCL_HDRS} ) -SET_TARGET_PROPERTIES(MiniCL PROPERTIES VERSION ${BULLET_VERSION}) -SET_TARGET_PROPERTIES(MiniCL PROPERTIES SOVERSION ${BULLET_VERSION}) - - -IF (BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(MiniCL BulletMultiThreaded BulletDynamics BulletCollision) -ENDIF (BUILD_SHARED_LIBS) - -IF (INSTALL_LIBS) - IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) - #INSTALL of other files requires CMake 2.6 - IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) -# IF(INSTALL_EXTRA_LIBS) - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS MiniCL DESTINATION .) - ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - INSTALL(TARGETS MiniCL - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) - INSTALL(DIRECTORY -${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING -PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE) - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) -# ENDIF (INSTALL_EXTRA_LIBS) - ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5) - - IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - SET_TARGET_PROPERTIES(MiniCL PROPERTIES FRAMEWORK true) - - SET_TARGET_PROPERTIES(MiniCL PROPERTIES PUBLIC_HEADER "${Root_HDRS}") - # Have to list out sub-directories manually: - SET_PROPERTY(SOURCE ${MiniCLTask_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MiniCLTask) - - ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK) - ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) -ENDIF (INSTALL_LIBS) - diff --git a/Code/Physics/Bullet Source/src/MiniCL/MiniCL.cpp b/Code/Physics/Bullet Source/src/MiniCL/MiniCL.cpp deleted file mode 100644 index ba0865aa..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/MiniCL.cpp +++ /dev/null @@ -1,788 +0,0 @@ -/* - Copyright (C) 2010 Sony Computer Entertainment Inc. - All rights reserved. - -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 "MiniCL/cl.h" -#define __PHYSICS_COMMON_H__ 1 -#ifdef _WIN32 -#include "BulletMultiThreaded/Win32ThreadSupport.h" -#endif - -#include "BulletMultiThreaded/PlatformDefinitions.h" -#ifdef USE_PTHREADS -#include "BulletMultiThreaded/PosixThreadSupport.h" -#endif - - -#include "BulletMultiThreaded/SequentialThreadSupport.h" -#include "MiniCLTaskScheduler.h" -#include "MiniCLTask/MiniCLTask.h" -#include "LinearMath/btMinMax.h" -#include -#include - -//#define DEBUG_MINICL_KERNELS 1 - -static const char* spPlatformID = "MiniCL, SCEA"; -static const char* spDriverVersion= "1.0"; - -CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs( - cl_uint num_entries, - cl_platform_id * platforms, - cl_uint * num_platforms ) CL_API_SUFFIX__VERSION_1_0 -{ - if(platforms != NULL) - { - if(num_entries <= 0) - { - return CL_INVALID_VALUE; - } - *((const char**)platforms) = spPlatformID; - } - if(num_platforms != NULL) - { - *num_platforms = 1; - } - return CL_SUCCESS; -} - - -CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo( - cl_platform_id platform, - cl_platform_info param_name, - size_t param_value_size, - void * param_value, - size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 -{ - char* pId = (char*)platform; - if(strcmp(pId, spPlatformID)) - { - return CL_INVALID_PLATFORM; - } - switch(param_name) - { - case CL_PLATFORM_VERSION: - { - if(param_value_size < (strlen(spDriverVersion) + 1)) - { - return CL_INVALID_VALUE; - } - strcpy((char*)param_value, spDriverVersion); - if(param_value_size_ret != NULL) - { - *param_value_size_ret = strlen(spDriverVersion) + 1; - } - break; - } - case CL_PLATFORM_NAME: - case CL_PLATFORM_VENDOR : - if(param_value_size < (strlen(spPlatformID) + 1)) - { - return CL_INVALID_VALUE; - } - strcpy((char*)param_value, spPlatformID); - if(param_value_size_ret != NULL) - { - *param_value_size_ret = strlen(spPlatformID) + 1; - } - break; - default : - return CL_INVALID_VALUE; - } - return CL_SUCCESS; -} - - - - -CL_API_ENTRY cl_int CL_API_CALL clGetDeviceInfo( - cl_device_id device , - cl_device_info param_name , - size_t param_value_size , - void * param_value , - size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 -{ - - switch (param_name) - { - case CL_DEVICE_NAME: - { - char deviceName[] = "MiniCL CPU"; - unsigned int nameLen = (unsigned int)strlen(deviceName)+1; - btAssert(param_value_size>strlen(deviceName)); - if (nameLen < param_value_size) - { - const char* cpuName = "MiniCL CPU"; - sprintf((char*)param_value,"%s",cpuName); - } else - { - printf("error: param_value_size should be at least %d, but it is %zu\n",nameLen,param_value_size); - return CL_INVALID_VALUE; - } - break; - } - case CL_DEVICE_TYPE: - { - if (param_value_size>=sizeof(cl_device_type)) - { - cl_device_type* deviceType = (cl_device_type*)param_value; - *deviceType = CL_DEVICE_TYPE_CPU; - } else - { - printf("error: param_value_size should be at least %zu\n",sizeof(cl_device_type)); - return CL_INVALID_VALUE; - } - break; - } - case CL_DEVICE_MAX_COMPUTE_UNITS: - { - if (param_value_size>=sizeof(cl_uint)) - { - cl_uint* numUnits = (cl_uint*)param_value; - *numUnits= 4; - } else - { - printf("error: param_value_size should be at least %zu\n",sizeof(cl_uint)); - return CL_INVALID_VALUE; - } - - break; - } - case CL_DEVICE_MAX_WORK_ITEM_SIZES: - { - size_t workitem_size[3]; - - if (param_value_size>=sizeof(workitem_size)) - { - size_t* workItemSize = (size_t*)param_value; - workItemSize[0] = 64; - workItemSize[1] = 24; - workItemSize[2] = 16; - } else - { - printf("error: param_value_size should be at least %zu\n",sizeof(cl_uint)); - return CL_INVALID_VALUE; - } - break; - } - case CL_DEVICE_MAX_CLOCK_FREQUENCY: - { - cl_uint* clock_frequency = (cl_uint*)param_value; - *clock_frequency = 3*1024; - break; - } - - case CL_DEVICE_VENDOR : - { - if(param_value_size < (strlen(spPlatformID) + 1)) - { - return CL_INVALID_VALUE; - } - strcpy((char*)param_value, spPlatformID); - if(param_value_size_ret != NULL) - { - *param_value_size_ret = strlen(spPlatformID) + 1; - } - break; - } - case CL_DRIVER_VERSION: - { - if(param_value_size < (strlen(spDriverVersion) + 1)) - { - return CL_INVALID_VALUE; - } - strcpy((char*)param_value, spDriverVersion); - if(param_value_size_ret != NULL) - { - *param_value_size_ret = strlen(spDriverVersion) + 1; - } - - break; - } - case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: - { - cl_uint* maxDimensions = (cl_uint*)param_value; - *maxDimensions = 1; - break; - } - case CL_DEVICE_MAX_WORK_GROUP_SIZE: - { - cl_uint* maxWorkGroupSize = (cl_uint*)param_value; - *maxWorkGroupSize = 128;//1; - break; - } - case CL_DEVICE_ADDRESS_BITS: - { - cl_uint* addressBits = (cl_uint*)param_value; - *addressBits= 32; //@todo: should this be 64 for 64bit builds? - break; - } - case CL_DEVICE_MAX_MEM_ALLOC_SIZE: - { - cl_ulong* maxMemAlloc = (cl_ulong*)param_value; - *maxMemAlloc= 512*1024*1024; //this "should be enough for everyone" ? - break; - } - case CL_DEVICE_GLOBAL_MEM_SIZE: - { - cl_ulong* maxMemAlloc = (cl_ulong*)param_value; - *maxMemAlloc= 1024*1024*1024; //this "should be enough for everyone" ? - break; - } - - case CL_DEVICE_ERROR_CORRECTION_SUPPORT: - { - cl_bool* error_correction_support = (cl_bool*)param_value; - *error_correction_support = CL_FALSE; - break; - } - - case CL_DEVICE_LOCAL_MEM_TYPE: - { - cl_device_local_mem_type* local_mem_type = (cl_device_local_mem_type*)param_value; - *local_mem_type = CL_GLOBAL; - break; - } - case CL_DEVICE_LOCAL_MEM_SIZE: - { - cl_ulong* localmem = (cl_ulong*) param_value; - *localmem = 32*1024; - break; - } - - case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: - { - cl_ulong* localmem = (cl_ulong*) param_value; - *localmem = 64*1024; - break; - } - case CL_DEVICE_QUEUE_PROPERTIES: - { - cl_command_queue_properties* queueProp = (cl_command_queue_properties*) param_value; - memset(queueProp,0,param_value_size); - - break; - } - case CL_DEVICE_IMAGE_SUPPORT: - { - cl_bool* imageSupport = (cl_bool*) param_value; - *imageSupport = CL_FALSE; - break; - } - - case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: - case CL_DEVICE_MAX_READ_IMAGE_ARGS: - { - cl_uint* imageArgs = (cl_uint*) param_value; - *imageArgs = 0; - break; - } - case CL_DEVICE_IMAGE3D_MAX_DEPTH: - case CL_DEVICE_IMAGE3D_MAX_HEIGHT: - case CL_DEVICE_IMAGE2D_MAX_HEIGHT: - case CL_DEVICE_IMAGE3D_MAX_WIDTH: - case CL_DEVICE_IMAGE2D_MAX_WIDTH: - { - size_t* maxSize = (size_t*) param_value; - *maxSize = 0; - break; - } - - case CL_DEVICE_EXTENSIONS: - { - char* extensions = (char*) param_value; - *extensions = 0; - break; - } - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: - { - cl_uint* width = (cl_uint*) param_value; - *width = 1; - break; - } - - default: - { - printf("error: unsupported param_name:%d\n",param_name); - } - } - - - return 0; -} - -CL_API_ENTRY cl_int CL_API_CALL clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0 -{ - return 0; -} - - - -CL_API_ENTRY cl_int CL_API_CALL clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0 -{ - return 0; -} - -CL_API_ENTRY cl_int CL_API_CALL clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0 -{ - return 0; -} - -CL_API_ENTRY cl_int CL_API_CALL clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0 -{ - return 0; -} - - -// Enqueued Commands APIs -CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadBuffer(cl_command_queue command_queue , - cl_mem buffer , - cl_bool /* blocking_read */, - size_t offset , - size_t cb , - void * ptr , - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 -{ - MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; - - ///wait for all work items to be completed - scheduler->flush(); - - memcpy(ptr,(char*)buffer + offset,cb); - return 0; -} - - -CL_API_ENTRY cl_int clGetProgramBuildInfo(cl_program /* program */, - cl_device_id /* device */, - cl_program_build_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 -{ - - return 0; -} - - -// Program Object APIs -CL_API_ENTRY cl_program -clCreateProgramWithSource(cl_context context , - cl_uint /* count */, - const char ** /* strings */, - const size_t * /* lengths */, - cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - *errcode_ret = CL_SUCCESS; - return (cl_program)context; -} - -CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue command_queue , - cl_mem buffer , - cl_bool /* blocking_read */, - size_t offset, - size_t cb , - const void * ptr , - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 -{ - MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; - - ///wait for all work items to be completed - scheduler->flush(); - - memcpy((char*)buffer + offset, ptr,cb); - return 0; -} - -CL_API_ENTRY cl_int CL_API_CALL clFlush(cl_command_queue command_queue) -{ - MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; - ///wait for all work items to be completed - scheduler->flush(); - return 0; -} - - -CL_API_ENTRY cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, - cl_kernel clKernel , - cl_uint work_dim , - const size_t * /* global_work_offset */, - const size_t * global_work_size , - const size_t * /* local_work_size */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0 -{ - - - MiniCLKernel* kernel = (MiniCLKernel*) clKernel; - for (unsigned int ii=0;iim_scheduler->getMaxNumOutstandingTasks(); - int numWorkItems = global_work_size[ii]; - -// //at minimum 64 work items per task -// int numWorkItemsPerTask = btMax(64,numWorkItems / maxTask); - int numWorkItemsPerTask = numWorkItems / maxTask; - if (!numWorkItemsPerTask) numWorkItemsPerTask = 1; - - for (int t=0;tm_scheduler->issueTask(t, endIndex, kernel); - t = endIndex; - } - } -/* - - void* bla = 0; - - scheduler->issueTask(bla,2,3); - scheduler->flush(); - - */ - - return 0; -} - -#define LOCAL_BUF_SIZE 32768 -static int sLocalMemBuf[LOCAL_BUF_SIZE * 4 + 16]; -static int* spLocalBufCurr = NULL; -static int sLocalBufUsed = LOCAL_BUF_SIZE; // so it will be reset at the first call -static void* localBufMalloc(int size) -{ - int size16 = (size + 15) >> 4; // in 16-byte units - if((sLocalBufUsed + size16) > LOCAL_BUF_SIZE) - { // reset - spLocalBufCurr = sLocalMemBuf; - while((size_t)spLocalBufCurr & 0x0F) spLocalBufCurr++; // align to 16 bytes - sLocalBufUsed = 0; - } - void* ret = spLocalBufCurr; - spLocalBufCurr += size16 * 4; - sLocalBufUsed += size; - return ret; -} - - - -CL_API_ENTRY cl_int CL_API_CALL clSetKernelArg(cl_kernel clKernel , - cl_uint arg_index , - size_t arg_size , - const void * arg_value ) CL_API_SUFFIX__VERSION_1_0 -{ - MiniCLKernel* kernel = (MiniCLKernel* ) clKernel; - btAssert(arg_size <= MINICL_MAX_ARGLENGTH); - if (arg_index>MINI_CL_MAX_ARG) - { - printf("error: clSetKernelArg arg_index (%u) exceeds %u\n",arg_index,MINI_CL_MAX_ARG); - } else - { - if (arg_size>MINICL_MAX_ARGLENGTH) - //if (arg_size != MINICL_MAX_ARGLENGTH) - { - printf("error: clSetKernelArg argdata too large: %zu (maximum is %zu)\n",arg_size,MINICL_MAX_ARGLENGTH); - } - else - { - if(arg_value == NULL) - { // this is only for __local memory qualifier - void* ptr = localBufMalloc(arg_size); - kernel->m_argData[arg_index] = ptr; - } - else - { - memcpy(&(kernel->m_argData[arg_index]), arg_value, arg_size); - } - kernel->m_argSizes[arg_index] = arg_size; - if(arg_index >= kernel->m_numArgs) - { - kernel->m_numArgs = arg_index + 1; - kernel->updateLauncher(); - } - } - } - return 0; -} - -// Kernel Object APIs -CL_API_ENTRY cl_kernel CL_API_CALL clCreateKernel(cl_program program , - const char * kernel_name , - cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) program; - int nameLen = strlen(kernel_name); - if(nameLen >= MINI_CL_MAX_KERNEL_NAME) - { - *errcode_ret = CL_INVALID_KERNEL_NAME; - return NULL; - } - - MiniCLKernel* kernel = new MiniCLKernel(); - - strcpy(kernel->m_name, kernel_name); - kernel->m_numArgs = 0; - - //kernel->m_kernelProgramCommandId = scheduler->findProgramCommandIdByName(kernel_name); - //if (kernel->m_kernelProgramCommandId>=0) - //{ - // *errcode_ret = CL_SUCCESS; - //} else - //{ - // *errcode_ret = CL_INVALID_KERNEL_NAME; - //} - kernel->m_scheduler = scheduler; - if(kernel->registerSelf() == NULL) - { - *errcode_ret = CL_INVALID_KERNEL_NAME; - delete kernel; - return NULL; - } - else - { - *errcode_ret = CL_SUCCESS; - } - - return (cl_kernel)kernel; - -} - - -CL_API_ENTRY cl_int CL_API_CALL clBuildProgram(cl_program /* program */, - cl_uint /* num_devices */, - const cl_device_id * /* device_list */, - const char * /* options */, - void (*pfn_notify)(cl_program /* program */, void * /* user_data */), - void * /* user_data */) CL_API_SUFFIX__VERSION_1_0 -{ - return CL_SUCCESS; -} - -CL_API_ENTRY cl_program CL_API_CALL clCreateProgramWithBinary(cl_context context , - cl_uint /* num_devices */, - const cl_device_id * /* device_list */, - const size_t * /* lengths */, - const unsigned char ** /* binaries */, - cl_int * /* binary_status */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0 -{ - return (cl_program)context; -} - - -// Memory Object APIs -CL_API_ENTRY cl_mem CL_API_CALL clCreateBuffer(cl_context /* context */, - cl_mem_flags flags , - size_t size, - void * host_ptr , - cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - cl_mem buf = (cl_mem)malloc(size); - if ((flags&CL_MEM_COPY_HOST_PTR) && host_ptr) - { - memcpy(buf,host_ptr,size); - } - *errcode_ret = 0; - return buf; -} - -// Command Queue APIs -CL_API_ENTRY cl_command_queue CL_API_CALL clCreateCommandQueue(cl_context context , - cl_device_id /* device */, - cl_command_queue_properties /* properties */, - cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - *errcode_ret = 0; - return (cl_command_queue) context; -} - -extern CL_API_ENTRY cl_int CL_API_CALL clGetContextInfo(cl_context /* context */, - cl_context_info param_name , - size_t param_value_size , - void * param_value, - size_t * param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - - switch (param_name) - { - case CL_CONTEXT_DEVICES: - { - if (!param_value_size) - { - *param_value_size_ret = 13; - } else - { - const char* testName = "MiniCL_Test."; - sprintf((char*)param_value,"%s",testName); - } - break; - }; - default: - { - printf("unsupported\n"); - } - } - - return 0; -} - - - -CL_API_ENTRY cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties * /* properties */, - cl_device_type device_type , - void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, - void * /* user_data */, - cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - int maxNumOutstandingTasks = 4; -// int maxNumOutstandingTasks = 2; -// int maxNumOutstandingTasks = 1; - gMiniCLNumOutstandingTasks = maxNumOutstandingTasks; - const int maxNumOfThreadSupports = 8; - static int sUniqueThreadSupportIndex = 0; - static const char* sUniqueThreadSupportName[maxNumOfThreadSupports] = - { - "MiniCL_0", "MiniCL_1", "MiniCL_2", "MiniCL_3", "MiniCL_4", "MiniCL_5", "MiniCL_6", "MiniCL_7" - }; - - btThreadSupportInterface* threadSupport = 0; - - if (device_type==CL_DEVICE_TYPE_DEBUG) - { - SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory); - threadSupport = new SequentialThreadSupport(stc); - } else - { - -#if _WIN32 - btAssert(sUniqueThreadSupportIndex < maxNumOfThreadSupports); - const char* bla = "MiniCL"; - threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( -// bla, - sUniqueThreadSupportName[sUniqueThreadSupportIndex++], - processMiniCLTask, //processCollisionTask, - createMiniCLLocalStoreMemory,//createCollisionLocalStoreMemory, - maxNumOutstandingTasks)); -#else - -#ifdef USE_PTHREADS - PosixThreadSupport::ThreadConstructionInfo constructionInfo("PosixThreads", - processMiniCLTask, - createMiniCLLocalStoreMemory, - maxNumOutstandingTasks); - threadSupport = new PosixThreadSupport(constructionInfo); - -#else - ///todo: add posix thread support for other platforms - SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory); - threadSupport = new SequentialThreadSupport(stc); -#endif //USE_PTHREADS -#endif - - } - - - MiniCLTaskScheduler* scheduler = new MiniCLTaskScheduler(threadSupport,maxNumOutstandingTasks); - - *errcode_ret = 0; - return (cl_context)scheduler; -} - -CL_API_ENTRY cl_int CL_API_CALL -clGetDeviceIDs(cl_platform_id /* platform */, - cl_device_type /* device_type */, - cl_uint /* num_entries */, - cl_device_id * /* devices */, - cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0 -{ - return 0; -} - -CL_API_ENTRY cl_context CL_API_CALL -clCreateContext(const cl_context_properties * properties , - cl_uint num_devices , - const cl_device_id * devices , - void (*pfn_notify)(const char *, const void *, size_t, void *), - void * user_data , - cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 -{ - - return clCreateContextFromType(properties,CL_DEVICE_TYPE_ALL,pfn_notify,user_data,errcode_ret); -} - -CL_API_ENTRY cl_int CL_API_CALL clReleaseContext(cl_context context ) CL_API_SUFFIX__VERSION_1_0 -{ - - MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) context; - - btThreadSupportInterface* threadSupport = scheduler->getThreadSupportInterface(); - delete scheduler; - delete threadSupport; - - return 0; -} -extern CL_API_ENTRY cl_int CL_API_CALL -clFinish(cl_command_queue command_queue ) CL_API_SUFFIX__VERSION_1_0 -{ - MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue; - ///wait for all work items to be completed - scheduler->flush(); - return CL_SUCCESS; -} - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetProgramInfo(cl_program /* program */, - cl_program_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 -{ - return 0; -} - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetKernelWorkGroupInfo(cl_kernel kernel , - cl_device_id /* device */, - cl_kernel_work_group_info wgi/* param_name */, - size_t sz /* param_value_size */, - void * ptr /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0 -{ - if((wgi == CL_KERNEL_WORK_GROUP_SIZE) - &&(sz == sizeof(size_t)) - &&(ptr != NULL)) - { - MiniCLKernel* miniCLKernel = (MiniCLKernel*)kernel; - MiniCLTaskScheduler* scheduler = miniCLKernel->m_scheduler; - *((size_t*)ptr) = scheduler->getMaxNumOutstandingTasks(); - return CL_SUCCESS; - } - else - { - return CL_INVALID_VALUE; - } -} diff --git a/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.cpp b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.cpp deleted file mode 100644 index a56e96a0..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans - -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 "MiniCLTask.h" -#include "BulletMultiThreaded/PlatformDefinitions.h" -#include "BulletMultiThreaded/SpuFakeDma.h" -#include "LinearMath/btMinMax.h" -#include "MiniCLTask.h" -#include "MiniCL/MiniCLTaskScheduler.h" - - -#ifdef __SPU__ -#include -#else -#include -#define spu_printf printf -#endif - -int gMiniCLNumOutstandingTasks = 0; - -struct MiniCLTask_LocalStoreMemory -{ - -}; - - -//-- MAIN METHOD -void processMiniCLTask(void* userPtr, void* lsMemory) -{ - // BT_PROFILE("processSampleTask"); - - MiniCLTask_LocalStoreMemory* localMemory = (MiniCLTask_LocalStoreMemory*)lsMemory; - - MiniCLTaskDesc* taskDescPtr = (MiniCLTaskDesc*)userPtr; - MiniCLTaskDesc& taskDesc = *taskDescPtr; - - for (unsigned int i=taskDesc.m_firstWorkUnit;im_launcher(&taskDesc, i); - } - -// printf("Compute Unit[%d] executed kernel %d work items [%d..%d)\n",taskDesc.m_taskId,taskDesc.m_kernelProgramId,taskDesc.m_firstWorkUnit,taskDesc.m_lastWorkUnit); - -} - - -#if defined(__CELLOS_LV2__) || defined (LIBSPE2) - -ATTRIBUTE_ALIGNED16(MiniCLTask_LocalStoreMemory gLocalStoreMemory); - -void* createMiniCLLocalStoreMemory() -{ - return &gLocalStoreMemory; -} -#else -void* createMiniCLLocalStoreMemory() -{ - return new MiniCLTask_LocalStoreMemory; -}; - -#endif diff --git a/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.h b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.h deleted file mode 100644 index 7e78be08..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/MiniCLTask/MiniCLTask.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans - -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 MINICL__TASK_H -#define MINICL__TASK_H - -#include "BulletMultiThreaded/PlatformDefinitions.h" -#include "LinearMath/btScalar.h" - -#include "LinearMath/btAlignedAllocator.h" - - -#define MINICL_MAX_ARGLENGTH (sizeof(void*)) -#define MINI_CL_MAX_ARG 16 -#define MINI_CL_MAX_KERNEL_NAME 256 - -struct MiniCLKernel; - -ATTRIBUTE_ALIGNED16(struct) MiniCLTaskDesc -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - MiniCLTaskDesc() - { - for (int i=0;i - -#ifdef __SPU__ - - - -void SampleThreadFunc(void* userPtr,void* lsMemory) -{ - //do nothing - printf("hello world\n"); -} - - -void* SamplelsMemoryFunc() -{ - //don't create local store memory, just return 0 - return 0; -} - - -#else - - -#include "BulletMultiThreaded/btThreadSupportInterface.h" - -//# include "SPUAssert.h" -#include - -#include "MiniCL/cl_platform.h" - -extern "C" { - extern char SPU_SAMPLE_ELF_SYMBOL[]; -} - - -MiniCLTaskScheduler::MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks) -:m_threadInterface(threadInterface), -m_maxNumOutstandingTasks(maxNumOutstandingTasks) -{ - - m_taskBusy.resize(m_maxNumOutstandingTasks); - m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks); - - m_kernels.resize(0); - - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - m_taskBusy[i] = false; - } - m_numBusyTasks = 0; - m_currentTask = 0; - - m_initialized = false; - - m_threadInterface->startSPU(); - - -} - -MiniCLTaskScheduler::~MiniCLTaskScheduler() -{ - m_threadInterface->stopSPU(); - -} - - - -void MiniCLTaskScheduler::initialize() -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("MiniCLTaskScheduler::initialize()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - m_taskBusy[i] = false; - } - m_numBusyTasks = 0; - m_currentTask = 0; - m_initialized = true; - -} - - -void MiniCLTaskScheduler::issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel) -{ - -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("MiniCLTaskScheduler::issueTask (m_currentTask= %d\)n", m_currentTask); -#endif //DEBUG_SPU_TASK_SCHEDULING - - m_taskBusy[m_currentTask] = true; - m_numBusyTasks++; - - MiniCLTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask]; - { - // send task description in event message - taskDesc.m_firstWorkUnit = firstWorkUnit; - taskDesc.m_lastWorkUnit = lastWorkUnit; - taskDesc.m_kernel = kernel; - //some bookkeeping to recognize finished tasks - taskDesc.m_taskId = m_currentTask; - -// for (int i=0;im_numArgs; i++) - { - taskDesc.m_argSizes[i] = kernel->m_argSizes[i]; - if (taskDesc.m_argSizes[i]) - { - taskDesc.m_argData[i] = kernel->m_argData[i]; -// memcpy(&taskDesc.m_argData[i],&argData[MINICL_MAX_ARGLENGTH*i],taskDesc.m_argSizes[i]); - } - } - } - - - m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc, m_currentTask); - - // if all tasks busy, wait for spu event to clear the task. - - if (m_numBusyTasks >= m_maxNumOutstandingTasks) - { - unsigned int taskId; - unsigned int outputSize; - - for (int i=0;iwaitForResponse(&taskId, &outputSize); - - //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); - - postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - - // find new task buffer - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - if (!m_taskBusy[i]) - { - m_currentTask = i; - break; - } - } -} - - -///Optional PPU-size post processing for each task -void MiniCLTaskScheduler::postProcess(int taskId, int outputSize) -{ - -} - - -void MiniCLTaskScheduler::flush() -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("\nSpuCollisionTaskProcess::flush()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - - - // all tasks are issued, wait for all tasks to be complete - while(m_numBusyTasks > 0) - { -// Consolidating SPU code - unsigned int taskId; - unsigned int outputSize; - - for (int i=0;iwaitForResponse(&taskId, &outputSize); - } - - //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); - - postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - - -} - - - -typedef void (*MiniCLKernelLauncher0)(int); -typedef void (*MiniCLKernelLauncher1)(void*, int); -typedef void (*MiniCLKernelLauncher2)(void*, void*, int); -typedef void (*MiniCLKernelLauncher3)(void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher4)(void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher5)(void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher6)(void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher7)(void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher8)(void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher9)(void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher10)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher11)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher12)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher13)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher14)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher15)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); -typedef void (*MiniCLKernelLauncher16)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int); - - -static void kernelLauncher0(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher0)(taskDesc->m_kernel->m_launcher))(guid); -} -static void kernelLauncher1(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher1)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - guid); -} -static void kernelLauncher2(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher2)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - guid); -} -static void kernelLauncher3(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher3)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - guid); -} -static void kernelLauncher4(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher4)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - guid); -} -static void kernelLauncher5(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher5)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - guid); -} -static void kernelLauncher6(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher6)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - guid); -} -static void kernelLauncher7(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher7)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - guid); -} -static void kernelLauncher8(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher8)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - guid); -} -static void kernelLauncher9(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher9)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - guid); -} -static void kernelLauncher10(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher10)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - guid); -} -static void kernelLauncher11(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher11)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - taskDesc->m_argData[10], - guid); -} -static void kernelLauncher12(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher12)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - taskDesc->m_argData[10], - taskDesc->m_argData[11], - guid); -} -static void kernelLauncher13(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher13)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - taskDesc->m_argData[10], - taskDesc->m_argData[11], - taskDesc->m_argData[12], - guid); -} -static void kernelLauncher14(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher14)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - taskDesc->m_argData[10], - taskDesc->m_argData[11], - taskDesc->m_argData[12], - taskDesc->m_argData[13], - guid); -} -static void kernelLauncher15(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher15)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - taskDesc->m_argData[10], - taskDesc->m_argData[11], - taskDesc->m_argData[12], - taskDesc->m_argData[13], - taskDesc->m_argData[14], - guid); -} -static void kernelLauncher16(MiniCLTaskDesc* taskDesc, int guid) -{ - ((MiniCLKernelLauncher16)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0], - taskDesc->m_argData[1], - taskDesc->m_argData[2], - taskDesc->m_argData[3], - taskDesc->m_argData[4], - taskDesc->m_argData[5], - taskDesc->m_argData[6], - taskDesc->m_argData[7], - taskDesc->m_argData[8], - taskDesc->m_argData[9], - taskDesc->m_argData[10], - taskDesc->m_argData[11], - taskDesc->m_argData[12], - taskDesc->m_argData[13], - taskDesc->m_argData[14], - taskDesc->m_argData[15], - guid); -} - -static kernelLauncherCB spLauncherList[MINI_CL_MAX_ARG+1] = -{ - kernelLauncher0, - kernelLauncher1, - kernelLauncher2, - kernelLauncher3, - kernelLauncher4, - kernelLauncher5, - kernelLauncher6, - kernelLauncher7, - kernelLauncher8, - kernelLauncher9, - kernelLauncher10, - kernelLauncher11, - kernelLauncher12, - kernelLauncher13, - kernelLauncher14, - kernelLauncher15, - kernelLauncher16 -}; - -void MiniCLKernel::updateLauncher() -{ - m_launcher = spLauncherList[m_numArgs]; -} - -struct MiniCLKernelDescEntry -{ - void* pCode; - const char* pName; -}; -static MiniCLKernelDescEntry spKernelDesc[256]; -static int sNumKernelDesc = 0; - -MiniCLKernelDesc::MiniCLKernelDesc(void* pCode, const char* pName) -{ - for(int i = 0; i < sNumKernelDesc; i++) - { - if(!strcmp(pName, spKernelDesc[i].pName)) - { // already registered - btAssert(spKernelDesc[i].pCode == pCode); - return; - } - } - spKernelDesc[sNumKernelDesc].pCode = pCode; - spKernelDesc[sNumKernelDesc].pName = pName; - sNumKernelDesc++; -} - - -MiniCLKernel* MiniCLKernel::registerSelf() -{ - m_scheduler->registerKernel(this); - for(int i = 0; i < sNumKernelDesc; i++) - { - if(!strcmp(m_name, spKernelDesc[i].pName)) - { - m_pCode = spKernelDesc[i].pCode; - return this; - } - } - return NULL; -} - -#endif - - -#endif //USE_SAMPLE_PROCESS diff --git a/Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.h b/Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.h deleted file mode 100644 index 3061a713..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/MiniCLTaskScheduler.h +++ /dev/null @@ -1,194 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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 MINICL_TASK_SCHEDULER_H -#define MINICL_TASK_SCHEDULER_H - -#include - - -#include "BulletMultiThreaded/PlatformDefinitions.h" - -#include - -#include "LinearMath/btAlignedObjectArray.h" - - -#include "MiniCLTask/MiniCLTask.h" - -//just add your commands here, try to keep them globally unique for debugging purposes -#define CMD_SAMPLE_TASK_COMMAND 10 - -struct MiniCLKernel; - -/// MiniCLTaskScheduler handles SPU processing of collision pairs. -/// When PPU issues a task, it will look for completed task buffers -/// PPU will do postprocessing, dependent on workunit output (not likely) -class MiniCLTaskScheduler -{ - // track task buffers that are being used, and total busy tasks - btAlignedObjectArray m_taskBusy; - btAlignedObjectArray m_spuSampleTaskDesc; - - - btAlignedObjectArray m_kernels; - - - int m_numBusyTasks; - - // the current task and the current entry to insert a new work unit - int m_currentTask; - - bool m_initialized; - - void postProcess(int taskId, int outputSize); - - class btThreadSupportInterface* m_threadInterface; - - int m_maxNumOutstandingTasks; - - - -public: - MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks); - - ~MiniCLTaskScheduler(); - - ///call initialize in the beginning of the frame, before addCollisionPairToTask - void initialize(); - - void issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel); - - ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished - void flush(); - - class btThreadSupportInterface* getThreadSupportInterface() - { - return m_threadInterface; - } - - int findProgramCommandIdByName(const char* programName) const; - - int getMaxNumOutstandingTasks() const - { - return m_maxNumOutstandingTasks; - } - - void registerKernel(MiniCLKernel* kernel) - { - m_kernels.push_back(kernel); - } -}; - -typedef void (*kernelLauncherCB)(MiniCLTaskDesc* taskDesc, int guid); - -struct MiniCLKernel -{ - MiniCLTaskScheduler* m_scheduler; - -// int m_kernelProgramCommandId; - - char m_name[MINI_CL_MAX_KERNEL_NAME]; - unsigned int m_numArgs; - kernelLauncherCB m_launcher; - void* m_pCode; - void updateLauncher(); - MiniCLKernel* registerSelf(); - - void* m_argData[MINI_CL_MAX_ARG]; - int m_argSizes[MINI_CL_MAX_ARG]; -}; - - -#if defined(USE_LIBSPE2) && defined(__SPU__) -////////////////////MAIN///////////////////////////// -#include "../SpuLibspe2Support.h" -#include -#include -#include - -void * SamplelsMemoryFunc(); -void SampleThreadFunc(void* userPtr,void* lsMemory); - -//#define DEBUG_LIBSPE2_MAINLOOP - -int main(unsigned long long speid, addr64 argp, addr64 envp) -{ - printf("SPU is up \n"); - - ATTRIBUTE_ALIGNED128(btSpuStatus status); - ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ; - unsigned int received_message = Spu_Mailbox_Event_Nothing; - bool shutdown = false; - - cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - status.m_status = Spu_Status_Free; - status.m_lsMemory.p = SamplelsMemoryFunc(); - - cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - - while (!shutdown) - { - received_message = spu_read_in_mbox(); - - - - switch(received_message) - { - case Spu_Mailbox_Event_Shutdown: - shutdown = true; - break; - case Spu_Mailbox_Event_Task: - // refresh the status -#ifdef DEBUG_LIBSPE2_MAINLOOP - printf("SPU recieved Task \n"); -#endif //DEBUG_LIBSPE2_MAINLOOP - cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - btAssert(status.m_status==Spu_Status_Occupied); - - cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - SampleThreadFunc((void*)&taskDesc, reinterpret_cast (taskDesc.m_mainMemoryPtr) ); - break; - case Spu_Mailbox_Event_Nothing: - default: - break; - } - - // set to status free and wait for next task - status.m_status = Spu_Status_Free; - cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0); - cellDmaWaitTagStatusAll(DMA_MASK(3)); - - - } - return 0; -} -////////////////////////////////////////////////////// -#endif - - - -#endif // MINICL_TASK_SCHEDULER_H - diff --git a/Code/Physics/Bullet Source/src/MiniCL/cl.h b/Code/Physics/Bullet Source/src/MiniCL/cl.h deleted file mode 100644 index 35282988..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/cl.h +++ /dev/null @@ -1,867 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008-2009 The Khronos Group Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and/or associated documentation files (the - * "Materials"), to deal in the Materials without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Materials, and to - * permit persons to whom the Materials are furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Materials. - * - * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. - ******************************************************************************/ - -#ifndef __OPENCL_CL_H -#define __OPENCL_CL_H - -#ifdef __APPLE__ -#include -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/******************************************************************************/ - -typedef struct _cl_platform_id * cl_platform_id; -typedef struct _cl_device_id * cl_device_id; -typedef struct _cl_context * cl_context; -typedef struct _cl_command_queue * cl_command_queue; -typedef struct _cl_mem * cl_mem; -typedef struct _cl_program * cl_program; -typedef struct _cl_kernel * cl_kernel; -typedef struct _cl_event * cl_event; -typedef struct _cl_sampler * cl_sampler; - -typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */ -typedef cl_ulong cl_bitfield; -typedef cl_bitfield cl_device_type; -typedef cl_uint cl_platform_info; -typedef cl_uint cl_device_info; -typedef cl_bitfield cl_device_address_info; -typedef cl_bitfield cl_device_fp_config; -typedef cl_uint cl_device_mem_cache_type; -typedef cl_uint cl_device_local_mem_type; -typedef cl_bitfield cl_device_exec_capabilities; -typedef cl_bitfield cl_command_queue_properties; - -typedef intptr_t cl_context_properties; -typedef cl_uint cl_context_info; -typedef cl_uint cl_command_queue_info; -typedef cl_uint cl_channel_order; -typedef cl_uint cl_channel_type; -typedef cl_bitfield cl_mem_flags; -typedef cl_uint cl_mem_object_type; -typedef cl_uint cl_mem_info; -typedef cl_uint cl_image_info; -typedef cl_uint cl_addressing_mode; -typedef cl_uint cl_filter_mode; -typedef cl_uint cl_sampler_info; -typedef cl_bitfield cl_map_flags; -typedef cl_uint cl_program_info; -typedef cl_uint cl_program_build_info; -typedef cl_int cl_build_status; -typedef cl_uint cl_kernel_info; -typedef cl_uint cl_kernel_work_group_info; -typedef cl_uint cl_event_info; -typedef cl_uint cl_command_type; -typedef cl_uint cl_profiling_info; - -typedef struct _cl_image_format { - cl_channel_order image_channel_order; - cl_channel_type image_channel_data_type; -} cl_image_format; - -/******************************************************************************/ - -// Error Codes -#define CL_SUCCESS 0 -#define CL_DEVICE_NOT_FOUND -1 -#define CL_DEVICE_NOT_AVAILABLE -2 -#define CL_DEVICE_COMPILER_NOT_AVAILABLE -3 -#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4 -#define CL_OUT_OF_RESOURCES -5 -#define CL_OUT_OF_HOST_MEMORY -6 -#define CL_PROFILING_INFO_NOT_AVAILABLE -7 -#define CL_MEM_COPY_OVERLAP -8 -#define CL_IMAGE_FORMAT_MISMATCH -9 -#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10 -#define CL_BUILD_PROGRAM_FAILURE -11 -#define CL_MAP_FAILURE -12 - -#define CL_INVALID_VALUE -30 -#define CL_INVALID_DEVICE_TYPE -31 -#define CL_INVALID_PLATFORM -32 -#define CL_INVALID_DEVICE -33 -#define CL_INVALID_CONTEXT -34 -#define CL_INVALID_QUEUE_PROPERTIES -35 -#define CL_INVALID_COMMAND_QUEUE -36 -#define CL_INVALID_HOST_PTR -37 -#define CL_INVALID_MEM_OBJECT -38 -#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39 -#define CL_INVALID_IMAGE_SIZE -40 -#define CL_INVALID_SAMPLER -41 -#define CL_INVALID_BINARY -42 -#define CL_INVALID_BUILD_OPTIONS -43 -#define CL_INVALID_PROGRAM -44 -#define CL_INVALID_PROGRAM_EXECUTABLE -45 -#define CL_INVALID_KERNEL_NAME -46 -#define CL_INVALID_KERNEL_DEFINITION -47 -#define CL_INVALID_KERNEL -48 -#define CL_INVALID_ARG_INDEX -49 -#define CL_INVALID_ARG_VALUE -50 -#define CL_INVALID_ARG_SIZE -51 -#define CL_INVALID_KERNEL_ARGS -52 -#define CL_INVALID_WORK_DIMENSION -53 -#define CL_INVALID_WORK_GROUP_SIZE -54 -#define CL_INVALID_WORK_ITEM_SIZE -55 -#define CL_INVALID_GLOBAL_OFFSET -56 -#define CL_INVALID_EVENT_WAIT_LIST -57 -#define CL_INVALID_EVENT -58 -#define CL_INVALID_OPERATION -59 -#define CL_INVALID_GL_OBJECT -60 -#define CL_INVALID_BUFFER_SIZE -61 -#define CL_INVALID_MIP_LEVEL -62 - -// OpenCL Version -#define CL_VERSION_1_0 1 - -// cl_bool -#define CL_FALSE 0 -#define CL_TRUE 1 - -// cl_platform_info -#define CL_PLATFORM_PROFILE 0x0900 -#define CL_PLATFORM_VERSION 0x0901 -#define CL_PLATFORM_NAME 0x0902 -#define CL_PLATFORM_VENDOR 0x0903 -#define CL_PLATFORM_EXTENSIONS 0x0904 - -// cl_device_type - bitfield -#define CL_DEVICE_TYPE_DEFAULT (1 << 0) -#define CL_DEVICE_TYPE_CPU (1 << 1) -#define CL_DEVICE_TYPE_GPU (1 << 2) -#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3) -#define CL_DEVICE_TYPE_DEBUG (1 << 4) -#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF - - -// cl_device_info -#define CL_DEVICE_TYPE 0x1000 -#define CL_DEVICE_VENDOR_ID 0x1001 -#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002 -#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003 -#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004 -#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005 -#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006 -#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007 -#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008 -#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009 -#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A -#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B -#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C -#define CL_DEVICE_ADDRESS_BITS 0x100D -#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E -#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F -#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010 -#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011 -#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012 -#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013 -#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014 -#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015 -#define CL_DEVICE_IMAGE_SUPPORT 0x1016 -#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017 -#define CL_DEVICE_MAX_SAMPLERS 0x1018 -#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019 -#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A -#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B -#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C -#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D -#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E -#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F -#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020 -#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021 -#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022 -#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023 -#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024 -#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025 -#define CL_DEVICE_ENDIAN_LITTLE 0x1026 -#define CL_DEVICE_AVAILABLE 0x1027 -#define CL_DEVICE_COMPILER_AVAILABLE 0x1028 -#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029 -#define CL_DEVICE_QUEUE_PROPERTIES 0x102A -#define CL_DEVICE_NAME 0x102B -#define CL_DEVICE_VENDOR 0x102C -#define CL_DRIVER_VERSION 0x102D -#define CL_DEVICE_PROFILE 0x102E -#define CL_DEVICE_VERSION 0x102F -#define CL_DEVICE_EXTENSIONS 0x1030 -#define CL_DEVICE_PLATFORM 0x1031 - -// cl_device_address_info - bitfield -#define CL_DEVICE_ADDRESS_32_BITS (1 << 0) -#define CL_DEVICE_ADDRESS_64_BITS (1 << 1) - -// cl_device_fp_config - bitfield -#define CL_FP_DENORM (1 << 0) -#define CL_FP_INF_NAN (1 << 1) -#define CL_FP_ROUND_TO_NEAREST (1 << 2) -#define CL_FP_ROUND_TO_ZERO (1 << 3) -#define CL_FP_ROUND_TO_INF (1 << 4) -#define CL_FP_FMA (1 << 5) - -// cl_device_mem_cache_type -#define CL_NONE 0x0 -#define CL_READ_ONLY_CACHE 0x1 -#define CL_READ_WRITE_CACHE 0x2 - -// cl_device_local_mem_type -#define CL_LOCAL 0x1 -#define CL_GLOBAL 0x2 - -// cl_device_exec_capabilities - bitfield -#define CL_EXEC_KERNEL (1 << 0) -#define CL_EXEC_NATIVE_KERNEL (1 << 1) - -// cl_command_queue_properties - bitfield -#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0) -#define CL_QUEUE_PROFILING_ENABLE (1 << 1) - -// cl_context_info -#define CL_CONTEXT_REFERENCE_COUNT 0x1080 -#define CL_CONTEXT_NUM_DEVICES 0x1081 -#define CL_CONTEXT_DEVICES 0x1082 -#define CL_CONTEXT_PROPERTIES 0x1083 -#define CL_CONTEXT_PLATFORM 0x1084 - -// cl_command_queue_info -#define CL_QUEUE_CONTEXT 0x1090 -#define CL_QUEUE_DEVICE 0x1091 -#define CL_QUEUE_REFERENCE_COUNT 0x1092 -#define CL_QUEUE_PROPERTIES 0x1093 - -// cl_mem_flags - bitfield -#define CL_MEM_READ_WRITE (1 << 0) -#define CL_MEM_WRITE_ONLY (1 << 1) -#define CL_MEM_READ_ONLY (1 << 2) -#define CL_MEM_USE_HOST_PTR (1 << 3) -#define CL_MEM_ALLOC_HOST_PTR (1 << 4) -#define CL_MEM_COPY_HOST_PTR (1 << 5) - -// cl_channel_order -#define CL_R 0x10B0 -#define CL_A 0x10B1 -#define CL_RG 0x10B2 -#define CL_RA 0x10B3 -#define CL_RGB 0x10B4 -#define CL_RGBA 0x10B5 -#define CL_BGRA 0x10B6 -#define CL_ARGB 0x10B7 -#define CL_INTENSITY 0x10B8 -#define CL_LUMINANCE 0x10B9 - -// cl_channel_type -#define CL_SNORM_INT8 0x10D0 -#define CL_SNORM_INT16 0x10D1 -#define CL_UNORM_INT8 0x10D2 -#define CL_UNORM_INT16 0x10D3 -#define CL_UNORM_SHORT_565 0x10D4 -#define CL_UNORM_SHORT_555 0x10D5 -#define CL_UNORM_INT_101010 0x10D6 -#define CL_SIGNED_INT8 0x10D7 -#define CL_SIGNED_INT16 0x10D8 -#define CL_SIGNED_INT32 0x10D9 -#define CL_UNSIGNED_INT8 0x10DA -#define CL_UNSIGNED_INT16 0x10DB -#define CL_UNSIGNED_INT32 0x10DC -#define CL_HALF_FLOAT 0x10DD -#define CL_FLOAT 0x10DE - -// cl_mem_object_type -#define CL_MEM_OBJECT_BUFFER 0x10F0 -#define CL_MEM_OBJECT_IMAGE2D 0x10F1 -#define CL_MEM_OBJECT_IMAGE3D 0x10F2 - -// cl_mem_info -#define CL_MEM_TYPE 0x1100 -#define CL_MEM_FLAGS 0x1101 -#define CL_MEM_SIZE 0x1102 -#define CL_MEM_HOST_PTR 0x1103 -#define CL_MEM_MAP_COUNT 0x1104 -#define CL_MEM_REFERENCE_COUNT 0x1105 -#define CL_MEM_CONTEXT 0x1106 - -// cl_image_info -#define CL_IMAGE_FORMAT 0x1110 -#define CL_IMAGE_ELEMENT_SIZE 0x1111 -#define CL_IMAGE_ROW_PITCH 0x1112 -#define CL_IMAGE_SLICE_PITCH 0x1113 -#define CL_IMAGE_WIDTH 0x1114 -#define CL_IMAGE_HEIGHT 0x1115 -#define CL_IMAGE_DEPTH 0x1116 - -// cl_addressing_mode -#define CL_ADDRESS_NONE 0x1130 -#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131 -#define CL_ADDRESS_CLAMP 0x1132 -#define CL_ADDRESS_REPEAT 0x1133 - -// cl_filter_mode -#define CL_FILTER_NEAREST 0x1140 -#define CL_FILTER_LINEAR 0x1141 - -// cl_sampler_info -#define CL_SAMPLER_REFERENCE_COUNT 0x1150 -#define CL_SAMPLER_CONTEXT 0x1151 -#define CL_SAMPLER_NORMALIZED_COORDS 0x1152 -#define CL_SAMPLER_ADDRESSING_MODE 0x1153 -#define CL_SAMPLER_FILTER_MODE 0x1154 - -// cl_map_flags - bitfield -#define CL_MAP_READ (1 << 0) -#define CL_MAP_WRITE (1 << 1) - -// cl_program_info -#define CL_PROGRAM_REFERENCE_COUNT 0x1160 -#define CL_PROGRAM_CONTEXT 0x1161 -#define CL_PROGRAM_NUM_DEVICES 0x1162 -#define CL_PROGRAM_DEVICES 0x1163 -#define CL_PROGRAM_SOURCE 0x1164 -#define CL_PROGRAM_BINARY_SIZES 0x1165 -#define CL_PROGRAM_BINARIES 0x1166 - -// cl_program_build_info -#define CL_PROGRAM_BUILD_STATUS 0x1181 -#define CL_PROGRAM_BUILD_OPTIONS 0x1182 -#define CL_PROGRAM_BUILD_LOG 0x1183 - -// cl_build_status -#define CL_BUILD_SUCCESS 0 -#define CL_BUILD_NONE -1 -#define CL_BUILD_ERROR -2 -#define CL_BUILD_IN_PROGRESS -3 - -// cl_kernel_info -#define CL_KERNEL_FUNCTION_NAME 0x1190 -#define CL_KERNEL_NUM_ARGS 0x1191 -#define CL_KERNEL_REFERENCE_COUNT 0x1192 -#define CL_KERNEL_CONTEXT 0x1193 -#define CL_KERNEL_PROGRAM 0x1194 - -// cl_kernel_work_group_info -#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0 -#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1 -#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2 - -// cl_event_info -#define CL_EVENT_COMMAND_QUEUE 0x11D0 -#define CL_EVENT_COMMAND_TYPE 0x11D1 -#define CL_EVENT_REFERENCE_COUNT 0x11D2 -#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3 - -// cl_command_type -#define CL_COMMAND_NDRANGE_KERNEL 0x11F0 -#define CL_COMMAND_TASK 0x11F1 -#define CL_COMMAND_NATIVE_KERNEL 0x11F2 -#define CL_COMMAND_READ_BUFFER 0x11F3 -#define CL_COMMAND_WRITE_BUFFER 0x11F4 -#define CL_COMMAND_COPY_BUFFER 0x11F5 -#define CL_COMMAND_READ_IMAGE 0x11F6 -#define CL_COMMAND_WRITE_IMAGE 0x11F7 -#define CL_COMMAND_COPY_IMAGE 0x11F8 -#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9 -#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA -#define CL_COMMAND_MAP_BUFFER 0x11FB -#define CL_COMMAND_MAP_IMAGE 0x11FC -#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD -#define CL_COMMAND_MARKER 0x11FE -#define CL_COMMAND_WAIT_FOR_EVENTS 0x11FF -#define CL_COMMAND_BARRIER 0x1200 -#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x1201 -#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1202 - -// command execution status -#define CL_COMPLETE 0x0 -#define CL_RUNNING 0x1 -#define CL_SUBMITTED 0x2 -#define CL_QUEUED 0x3 - -// cl_profiling_info -#define CL_PROFILING_COMMAND_QUEUED 0x1280 -#define CL_PROFILING_COMMAND_SUBMIT 0x1281 -#define CL_PROFILING_COMMAND_START 0x1282 -#define CL_PROFILING_COMMAND_END 0x1283 - -/********************************************************************************************************/ - -// Platform API -extern CL_API_ENTRY cl_int CL_API_CALL -clGetPlatformIDs(cl_uint /* num_entries */, - cl_platform_id * /* platforms */, - cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetPlatformInfo(cl_platform_id /* platform */, - cl_platform_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Device APIs -extern CL_API_ENTRY cl_int CL_API_CALL -clGetDeviceIDs(cl_platform_id /* platform */, - cl_device_type /* device_type */, - cl_uint /* num_entries */, - cl_device_id * /* devices */, - cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetDeviceInfo(cl_device_id /* device */, - cl_device_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Context APIs -extern CL_API_ENTRY cl_context CL_API_CALL -clCreateContext(const cl_context_properties * /* properties */, - cl_uint /* num_devices */, - const cl_device_id * /* devices */, - void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, - void * /* user_data */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_context CL_API_CALL -clCreateContextFromType(const cl_context_properties * /* properties */, - cl_device_type /* device_type */, - void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */, - void * /* user_data */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetContextInfo(cl_context /* context */, - cl_context_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Command Queue APIs -extern CL_API_ENTRY cl_command_queue CL_API_CALL -clCreateCommandQueue(cl_context /* context */, - cl_device_id /* device */, - cl_command_queue_properties /* properties */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetCommandQueueInfo(cl_command_queue /* command_queue */, - cl_command_queue_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clSetCommandQueueProperty(cl_command_queue /* command_queue */, - cl_command_queue_properties /* properties */, - cl_bool /* enable */, - cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0; - -// Memory Object APIs -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateBuffer(cl_context /* context */, - cl_mem_flags /* flags */, - size_t /* size */, - void * /* host_ptr */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateImage2D(cl_context /* context */, - cl_mem_flags /* flags */, - const cl_image_format * /* image_format */, - size_t /* image_width */, - size_t /* image_height */, - size_t /* image_row_pitch */, - void * /* host_ptr */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateImage3D(cl_context /* context */, - cl_mem_flags /* flags */, - const cl_image_format * /* image_format */, - size_t /* image_width */, - size_t /* image_height */, - size_t /* image_depth */, - size_t /* image_row_pitch */, - size_t /* image_slice_pitch */, - void * /* host_ptr */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetSupportedImageFormats(cl_context /* context */, - cl_mem_flags /* flags */, - cl_mem_object_type /* image_type */, - cl_uint /* num_entries */, - cl_image_format * /* image_formats */, - cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetMemObjectInfo(cl_mem /* memobj */, - cl_mem_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetImageInfo(cl_mem /* image */, - cl_image_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Sampler APIs -extern CL_API_ENTRY cl_sampler CL_API_CALL -clCreateSampler(cl_context /* context */, - cl_bool /* normalized_coords */, - cl_addressing_mode /* addressing_mode */, - cl_filter_mode /* filter_mode */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainSampler(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseSampler(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetSamplerInfo(cl_sampler /* sampler */, - cl_sampler_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Program Object APIs -extern CL_API_ENTRY cl_program CL_API_CALL -clCreateProgramWithSource(cl_context /* context */, - cl_uint /* count */, - const char ** /* strings */, - const size_t * /* lengths */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_program CL_API_CALL -clCreateProgramWithBinary(cl_context /* context */, - cl_uint /* num_devices */, - const cl_device_id * /* device_list */, - const size_t * /* lengths */, - const unsigned char ** /* binaries */, - cl_int * /* binary_status */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clBuildProgram(cl_program /* program */, - cl_uint /* num_devices */, - const cl_device_id * /* device_list */, - const char * /* options */, - void (*pfn_notify)(cl_program /* program */, void * /* user_data */), - void * /* user_data */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clUnloadCompiler(void) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetProgramInfo(cl_program /* program */, - cl_program_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetProgramBuildInfo(cl_program /* program */, - cl_device_id /* device */, - cl_program_build_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Kernel Object APIs -extern CL_API_ENTRY cl_kernel CL_API_CALL -clCreateKernel(cl_program /* program */, - const char * /* kernel_name */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clCreateKernelsInProgram(cl_program /* program */, - cl_uint /* num_kernels */, - cl_kernel * /* kernels */, - cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clSetKernelArg(cl_kernel /* kernel */, - cl_uint /* arg_index */, - size_t /* arg_size */, - const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetKernelInfo(cl_kernel /* kernel */, - cl_kernel_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetKernelWorkGroupInfo(cl_kernel /* kernel */, - cl_device_id /* device */, - cl_kernel_work_group_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Event Object APIs -extern CL_API_ENTRY cl_int CL_API_CALL -clWaitForEvents(cl_uint /* num_events */, - const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetEventInfo(cl_event /* event */, - cl_event_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clRetainEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clReleaseEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; - -// Profiling APIs -extern CL_API_ENTRY cl_int CL_API_CALL -clGetEventProfilingInfo(cl_event /* event */, - cl_profiling_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// Flush and Finish APIs -extern CL_API_ENTRY cl_int CL_API_CALL -clFlush(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clFinish(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; - -// Enqueued Commands APIs -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueReadBuffer(cl_command_queue /* command_queue */, - cl_mem /* buffer */, - cl_bool /* blocking_read */, - size_t /* offset */, - size_t /* cb */, - void * /* ptr */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueWriteBuffer(cl_command_queue /* command_queue */, - cl_mem /* buffer */, - cl_bool /* blocking_write */, - size_t /* offset */, - size_t /* cb */, - const void * /* ptr */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueCopyBuffer(cl_command_queue /* command_queue */, - cl_mem /* src_buffer */, - cl_mem /* dst_buffer */, - size_t /* src_offset */, - size_t /* dst_offset */, - size_t /* cb */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueReadImage(cl_command_queue /* command_queue */, - cl_mem /* image */, - cl_bool /* blocking_read */, - const size_t * /* origin[3] */, - const size_t * /* region[3] */, - size_t /* row_pitch */, - size_t /* slice_pitch */, - void * /* ptr */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueWriteImage(cl_command_queue /* command_queue */, - cl_mem /* image */, - cl_bool /* blocking_write */, - const size_t * /* origin[3] */, - const size_t * /* region[3] */, - size_t /* input_row_pitch */, - size_t /* input_slice_pitch */, - const void * /* ptr */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueCopyImage(cl_command_queue /* command_queue */, - cl_mem /* src_image */, - cl_mem /* dst_image */, - const size_t * /* src_origin[3] */, - const size_t * /* dst_origin[3] */, - const size_t * /* region[3] */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueCopyImageToBuffer(cl_command_queue /* command_queue */, - cl_mem /* src_image */, - cl_mem /* dst_buffer */, - const size_t * /* src_origin[3] */, - const size_t * /* region[3] */, - size_t /* dst_offset */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueCopyBufferToImage(cl_command_queue /* command_queue */, - cl_mem /* src_buffer */, - cl_mem /* dst_image */, - size_t /* src_offset */, - const size_t * /* dst_origin[3] */, - const size_t * /* region[3] */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY void * CL_API_CALL -clEnqueueMapBuffer(cl_command_queue /* command_queue */, - cl_mem /* buffer */, - cl_bool /* blocking_map */, - cl_map_flags /* map_flags */, - size_t /* offset */, - size_t /* cb */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY void * CL_API_CALL -clEnqueueMapImage(cl_command_queue /* command_queue */, - cl_mem /* image */, - cl_bool /* blocking_map */, - cl_map_flags /* map_flags */, - const size_t * /* origin[3] */, - const size_t * /* region[3] */, - size_t * /* image_row_pitch */, - size_t * /* image_slice_pitch */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueUnmapMemObject(cl_command_queue /* command_queue */, - cl_mem /* memobj */, - void * /* mapped_ptr */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, - cl_kernel /* kernel */, - cl_uint /* work_dim */, - const size_t * /* global_work_offset */, - const size_t * /* global_work_size */, - const size_t * /* local_work_size */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueTask(cl_command_queue /* command_queue */, - cl_kernel /* kernel */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueNativeKernel(cl_command_queue /* command_queue */, - void (*user_func)(void *), - void * /* args */, - size_t /* cb_args */, - cl_uint /* num_mem_objects */, - const cl_mem * /* mem_list */, - const void ** /* args_mem_loc */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueMarker(cl_command_queue /* command_queue */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueWaitForEvents(cl_command_queue /* command_queue */, - cl_uint /* num_events */, - const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueBarrier(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; - -#ifdef __cplusplus -} -#endif - -#endif // __OPENCL_CL_H - diff --git a/Code/Physics/Bullet Source/src/MiniCL/cl_MiniCL_Defs.h b/Code/Physics/Bullet Source/src/MiniCL/cl_MiniCL_Defs.h deleted file mode 100644 index 0773c857..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/cl_MiniCL_Defs.h +++ /dev/null @@ -1,439 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans - -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 -#include -#include "LinearMath/btScalar.h" - -#include "MiniCL/cl.h" - - -#define __kernel -#define __global -#define __local -#define get_global_id(a) __guid_arg -#define get_local_id(a) ((__guid_arg) % gMiniCLNumOutstandingTasks) -#define get_local_size(a) (gMiniCLNumOutstandingTasks) -#define get_group_id(a) ((__guid_arg) / gMiniCLNumOutstandingTasks) - -//static unsigned int as_uint(float val) { return *((unsigned int*)&val); } - - -#define CLK_LOCAL_MEM_FENCE 0x01 -#define CLK_GLOBAL_MEM_FENCE 0x02 - -static void barrier(unsigned int a) -{ - // TODO : implement -} - -//ATTRIBUTE_ALIGNED16(struct) float8 -struct float8 -{ - float s0; - float s1; - float s2; - float s3; - float s4; - float s5; - float s6; - float s7; - - float8(float scalar) - { - s0=s1=s2=s3=s4=s5=s6=s7=scalar; - } -}; - - -float select( float arg0, float arg1, bool select) -{ - if (select) - return arg0; - return arg1; -} - -#define __constant - - -struct float3 -{ - float x,y,z; - - float3& operator+=(const float3& other) - { - x += other.x; - y += other.y; - z += other.z; - return *this; - } - - float3& operator-=(const float3& other) - { - x -= other.x; - y -= other.y; - z -= other.z; - return *this; - } - -}; - -static float dot(const float3&a ,const float3& b) -{ - float3 tmp; - tmp.x = a.x*b.x; - tmp.y = a.y*b.y; - tmp.z = a.z*b.z; - return tmp.x+tmp.y+tmp.z; -} - -static float3 operator-(const float3& a,const float3& b) -{ - float3 tmp; - tmp.x = a.x - b.x; - tmp.y = a.y - b.y; - tmp.z = a.z - b.z; - return tmp; -} - -static float3 operator*(const float& scalar,const float3& b) -{ - float3 tmp; - tmp.x = scalar * b.x; - tmp.y = scalar * b.y; - tmp.z = scalar * b.z; - return tmp; -} - -static float3 operator*(const float3& a,const float& scalar) -{ - float3 tmp; - tmp.x = a.x * scalar; - tmp.y = a.y * scalar; - tmp.z = a.z * scalar; - return tmp; -} - - -static float3 operator*(const float3& a,const float3& b) -{ - float3 tmp; - tmp.x = a.x * b.x; - tmp.y = a.y * b.y; - tmp.z = a.z * b.z; - return tmp; -} - - -//ATTRIBUTE_ALIGNED16(struct) float4 -struct float4 -{ - union - { - struct { - float x; - float y; - float z; - }; - float3 xyz; - }; - float w; - - float4() {} - - float4(float v0, float v1, float v2, float v3) - { - x=v0; - y=v1; - z=v2; - w=v3; - - } - float4(float3 xyz, float scalarW) - { - x = xyz.x; - y = xyz.y; - z = xyz.z; - w = scalarW; - } - - float4(float v) - { - x = y = z = w = v; - } - float4 operator*(const float4& other) - { - float4 tmp; - tmp.x = x*other.x; - tmp.y = y*other.y; - tmp.z = z*other.z; - tmp.w = w*other.w; - return tmp; - } - - - - float4 operator*(const float& other) - { - float4 tmp; - tmp.x = x*other; - tmp.y = y*other; - tmp.z = z*other; - tmp.w = w*other; - return tmp; - } - - - - float4& operator+=(const float4& other) - { - x += other.x; - y += other.y; - z += other.z; - w += other.w; - return *this; - } - - float4& operator-=(const float4& other) - { - x -= other.x; - y -= other.y; - z -= other.z; - w -= other.w; - return *this; - } - - float4& operator *=(float scalar) - { - x *= scalar; - y *= scalar; - z *= scalar; - w *= scalar; - return (*this); - } - - - - - -}; - -static float4 fabs(const float4& a) -{ - float4 tmp; - tmp.x = a.x < 0.f ? 0.f : a.x; - tmp.y = a.y < 0.f ? 0.f : a.y; - tmp.z = a.z < 0.f ? 0.f : a.z; - tmp.w = a.w < 0.f ? 0.f : a.w; - return tmp; -} -static float4 operator+(const float4& a,const float4& b) -{ - float4 tmp; - tmp.x = a.x + b.x; - tmp.y = a.y + b.y; - tmp.z = a.z + b.z; - tmp.w = a.w + b.w; - return tmp; -} - - -static float8 operator+(const float8& a,const float8& b) -{ - float8 tmp(0); - tmp.s0 = a.s0 + b.s0; - tmp.s1 = a.s1 + b.s1; - tmp.s2 = a.s2 + b.s2; - tmp.s3 = a.s3 + b.s3; - tmp.s4 = a.s4 + b.s4; - tmp.s5 = a.s5 + b.s5; - tmp.s6 = a.s6 + b.s6; - tmp.s7 = a.s7 + b.s7; - return tmp; -} - - -static float4 operator-(const float4& a,const float4& b) -{ - float4 tmp; - tmp.x = a.x - b.x; - tmp.y = a.y - b.y; - tmp.z = a.z - b.z; - tmp.w = a.w - b.w; - return tmp; -} - -static float8 operator-(const float8& a,const float8& b) -{ - float8 tmp(0); - tmp.s0 = a.s0 - b.s0; - tmp.s1 = a.s1 - b.s1; - tmp.s2 = a.s2 - b.s2; - tmp.s3 = a.s3 - b.s3; - tmp.s4 = a.s4 - b.s4; - tmp.s5 = a.s5 - b.s5; - tmp.s6 = a.s6 - b.s6; - tmp.s7 = a.s7 - b.s7; - return tmp; -} - -static float4 operator*(float a,const float4& b) -{ - float4 tmp; - tmp.x = a * b.x; - tmp.y = a * b.y; - tmp.z = a * b.z; - tmp.w = a * b.w; - return tmp; -} - -static float4 operator/(const float4& b,float a) -{ - float4 tmp; - tmp.x = b.x/a; - tmp.y = b.y/a; - tmp.z = b.z/a; - tmp.w = b.w/a; - return tmp; -} - - - - - -static float dot(const float4&a ,const float4& b) -{ - float4 tmp; - tmp.x = a.x*b.x; - tmp.y = a.y*b.y; - tmp.z = a.z*b.z; - tmp.w = a.w*b.w; - return tmp.x+tmp.y+tmp.z+tmp.w; -} - -static float length(const float4&a) -{ - float l = sqrtf(a.x*a.x+a.y*a.y+a.z*a.z); - return l; -} - -static float4 normalize(const float4&a) -{ - float4 tmp; - float l = length(a); - tmp = 1.f/l*a; - return tmp; -} - - - -static float4 cross(const float4&a ,const float4& b) -{ - float4 tmp; - tmp.x = a.y*b.z - a.z*b.y; - tmp.y = -a.x*b.z + a.z*b.x; - tmp.z = a.x*b.y - a.y*b.x; - tmp.w = 0.f; - return tmp; -} - -static float max(float a, float b) -{ - return (a >= b) ? a : b; -} - - -static float min(float a, float b) -{ - return (a <= b) ? a : b; -} - -static float fmax(float a, float b) -{ - return (a >= b) ? a : b; -} - -static float fmin(float a, float b) -{ - return (a <= b) ? a : b; -} - -struct int2 -{ - int x,y; -}; - -struct uint2 -{ - unsigned int x,y; -}; - -//typedef int2 uint2; - -typedef unsigned int uint; - -struct int4 -{ - int x,y,z,w; -}; - -struct uint4 -{ - unsigned int x,y,z,w; - uint4() {} - uint4(uint val) { x = y = z = w = val; } - uint4& operator+=(const uint4& other) - { - x += other.x; - y += other.y; - z += other.z; - w += other.w; - return *this; - } -}; -static uint4 operator+(const uint4& a,const uint4& b) -{ - uint4 tmp; - tmp.x = a.x + b.x; - tmp.y = a.y + b.y; - tmp.z = a.z + b.z; - tmp.w = a.w + b.w; - return tmp; -} -static uint4 operator-(const uint4& a,const uint4& b) -{ - uint4 tmp; - tmp.x = a.x - b.x; - tmp.y = a.y - b.y; - tmp.z = a.z - b.z; - tmp.w = a.w - b.w; - return tmp; -} - -#define native_sqrt sqrtf -#define native_sin sinf -#define native_cos cosf -#define native_powr powf - -#define GUID_ARG ,int __guid_arg -#define GUID_ARG_VAL ,__guid_arg - - -#define as_int(a) (*((int*)&(a))) - -extern "C" int gMiniCLNumOutstandingTasks; -// extern "C" void __kernel_func(); - - diff --git a/Code/Physics/Bullet Source/src/MiniCL/cl_gl.h b/Code/Physics/Bullet Source/src/MiniCL/cl_gl.h deleted file mode 100644 index 0a69d6ec..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/cl_gl.h +++ /dev/null @@ -1,113 +0,0 @@ -/********************************************************************************** - * Copyright (c) 2008-2009 The Khronos Group Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and/or associated documentation files (the - * "Materials"), to deal in the Materials without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Materials, and to - * permit persons to whom the Materials are furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Materials. - * - * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. - **********************************************************************************/ - -#ifndef __OPENCL_CL_GL_H -#define __OPENCL_CL_GL_H - -#ifdef __APPLE__ -#include -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// NOTE: Make sure that appropriate GL header file is included separately - -typedef cl_uint cl_gl_object_type; -typedef cl_uint cl_gl_texture_info; -typedef cl_uint cl_gl_platform_info; - -// cl_gl_object_type -#define CL_GL_OBJECT_BUFFER 0x2000 -#define CL_GL_OBJECT_TEXTURE2D 0x2001 -#define CL_GL_OBJECT_TEXTURE3D 0x2002 -#define CL_GL_OBJECT_RENDERBUFFER 0x2003 - -// cl_gl_texture_info -#define CL_GL_TEXTURE_TARGET 0x2004 -#define CL_GL_MIPMAP_LEVEL 0x2005 - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateFromGLBuffer(cl_context /* context */, - cl_mem_flags /* flags */, - GLuint /* bufobj */, - int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateFromGLTexture2D(cl_context /* context */, - cl_mem_flags /* flags */, - GLenum /* target */, - GLint /* miplevel */, - GLuint /* texture */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateFromGLTexture3D(cl_context /* context */, - cl_mem_flags /* flags */, - GLenum /* target */, - GLint /* miplevel */, - GLuint /* texture */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateFromGLRenderbuffer(cl_context /* context */, - cl_mem_flags /* flags */, - GLuint /* renderbuffer */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetGLObjectInfo(cl_mem /* memobj */, - cl_gl_object_type * /* gl_object_type */, - GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clGetGLTextureInfo(cl_mem /* memobj */, - cl_gl_texture_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueAcquireGLObjects(cl_command_queue /* command_queue */, - cl_uint /* num_objects */, - const cl_mem * /* mem_objects */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */, - cl_uint /* num_objects */, - const cl_mem * /* mem_objects */, - cl_uint /* num_events_in_wait_list */, - const cl_event * /* event_wait_list */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; - -#ifdef __cplusplus -} -#endif - -#endif // __OPENCL_CL_GL_H diff --git a/Code/Physics/Bullet Source/src/MiniCL/cl_platform.h b/Code/Physics/Bullet Source/src/MiniCL/cl_platform.h deleted file mode 100644 index 43219e14..00000000 --- a/Code/Physics/Bullet Source/src/MiniCL/cl_platform.h +++ /dev/null @@ -1,254 +0,0 @@ -/********************************************************************************** - * Copyright (c) 2008-2009 The Khronos Group Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and/or associated documentation files (the - * "Materials"), to deal in the Materials without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Materials, and to - * permit persons to whom the Materials are furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Materials. - * - * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. - **********************************************************************************/ - -#ifndef __CL_PLATFORM_H -#define __CL_PLATFORM_H - -#define CL_PLATFORM_MINI_CL 0x12345 - -struct MiniCLKernelDesc -{ - MiniCLKernelDesc(void* pCode, const char* pName); -}; - -#define MINICL_REGISTER(__kernel_func) static MiniCLKernelDesc __kernel_func##Desc((void*)__kernel_func, #__kernel_func); - - -#ifdef __APPLE__ - /* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */ - #include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define CL_API_ENTRY -#define CL_API_CALL -#ifdef __APPLE__ -#define CL_API_SUFFIX__VERSION_1_0 // AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER -#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import)) -#else -#define CL_API_SUFFIX__VERSION_1_0 -#define CL_EXTENSION_WEAK_LINK -#endif - -#if defined (_WIN32) && ! defined (__MINGW32__) -typedef signed __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef signed __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef signed __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - -typedef int8_t cl_char; -typedef uint8_t cl_uchar; -typedef int16_t cl_short ; -typedef uint16_t cl_ushort ; -typedef int32_t cl_int ; -typedef uint32_t cl_uint ; -typedef int64_t cl_long ; -typedef uint64_t cl_ulong ; - -typedef uint16_t cl_half ; -typedef float cl_float ; -typedef double cl_double ; - - -typedef int8_t cl_char2[2] ; -typedef int8_t cl_char4[4] ; -typedef int8_t cl_char8[8] ; -typedef int8_t cl_char16[16] ; -typedef uint8_t cl_uchar2[2] ; -typedef uint8_t cl_uchar4[4] ; -typedef uint8_t cl_uchar8[8] ; -typedef uint8_t cl_uchar16[16] ; - -typedef int16_t cl_short2[2] ; -typedef int16_t cl_short4[4] ; -typedef int16_t cl_short8[8] ; -typedef int16_t cl_short16[16] ; -typedef uint16_t cl_ushort2[2] ; -typedef uint16_t cl_ushort4[4] ; -typedef uint16_t cl_ushort8[8] ; -typedef uint16_t cl_ushort16[16] ; - -typedef int32_t cl_int2[2] ; -typedef int32_t cl_int4[4] ; -typedef int32_t cl_int8[8] ; -typedef int32_t cl_int16[16] ; -typedef uint32_t cl_uint2[2] ; -typedef uint32_t cl_uint4[4] ; -typedef uint32_t cl_uint8[8] ; -typedef uint32_t cl_uint16[16] ; - -typedef int64_t cl_long2[2] ; -typedef int64_t cl_long4[4] ; -typedef int64_t cl_long8[8] ; -typedef int64_t cl_long16[16] ; -typedef uint64_t cl_ulong2[2] ; -typedef uint64_t cl_ulong4[4] ; -typedef uint64_t cl_ulong8[8] ; -typedef uint64_t cl_ulong16[16] ; - -typedef float cl_float2[2] ; -typedef float cl_float4[4] ; -typedef float cl_float8[8] ; -typedef float cl_float16[16] ; - -typedef double cl_double2[2] ; -typedef double cl_double4[4] ; -typedef double cl_double8[8] ; -typedef double cl_double16[16] ; - - -#else -#include - -/* scalar types */ -typedef int8_t cl_char; -typedef uint8_t cl_uchar; -typedef int16_t cl_short __attribute__((aligned(2))); -typedef uint16_t cl_ushort __attribute__((aligned(2))); -typedef int32_t cl_int __attribute__((aligned(4))); -typedef uint32_t cl_uint __attribute__((aligned(4))); -typedef int64_t cl_long __attribute__((aligned(8))); -typedef uint64_t cl_ulong __attribute__((aligned(8))); - -typedef uint16_t cl_half __attribute__((aligned(2))); -typedef float cl_float __attribute__((aligned(4))); -typedef double cl_double __attribute__((aligned(8))); - - -/* - * Vector types - * - * Note: OpenCL requires that all types be naturally aligned. - * This means that vector types must be naturally aligned. - * For example, a vector of four floats must be aligned to - * a 16 byte boundary (calculated as 4 * the natural 4-byte - * alignment of the float). The alignment qualifiers here - * will only function properly if your compiler supports them - * and if you don't actively work to defeat them. For example, - * in order for a cl_float4 to be 16 byte aligned in a struct, - * the start of the struct must itself be 16-byte aligned. - * - * Maintaining proper alignment is the user's responsibility. - */ -typedef int8_t cl_char2[2] __attribute__((aligned(2))); -typedef int8_t cl_char4[4] __attribute__((aligned(4))); -typedef int8_t cl_char8[8] __attribute__((aligned(8))); -typedef int8_t cl_char16[16] __attribute__((aligned(16))); -typedef uint8_t cl_uchar2[2] __attribute__((aligned(2))); -typedef uint8_t cl_uchar4[4] __attribute__((aligned(4))); -typedef uint8_t cl_uchar8[8] __attribute__((aligned(8))); -typedef uint8_t cl_uchar16[16] __attribute__((aligned(16))); - -typedef int16_t cl_short2[2] __attribute__((aligned(4))); -typedef int16_t cl_short4[4] __attribute__((aligned(8))); -typedef int16_t cl_short8[8] __attribute__((aligned(16))); -typedef int16_t cl_short16[16] __attribute__((aligned(32))); -typedef uint16_t cl_ushort2[2] __attribute__((aligned(4))); -typedef uint16_t cl_ushort4[4] __attribute__((aligned(8))); -typedef uint16_t cl_ushort8[8] __attribute__((aligned(16))); -typedef uint16_t cl_ushort16[16] __attribute__((aligned(32))); - -typedef int32_t cl_int2[2] __attribute__((aligned(8))); -typedef int32_t cl_int4[4] __attribute__((aligned(16))); -typedef int32_t cl_int8[8] __attribute__((aligned(32))); -typedef int32_t cl_int16[16] __attribute__((aligned(64))); -typedef uint32_t cl_uint2[2] __attribute__((aligned(8))); -typedef uint32_t cl_uint4[4] __attribute__((aligned(16))); -typedef uint32_t cl_uint8[8] __attribute__((aligned(32))); -typedef uint32_t cl_uint16[16] __attribute__((aligned(64))); - -typedef int64_t cl_long2[2] __attribute__((aligned(16))); -typedef int64_t cl_long4[4] __attribute__((aligned(32))); -typedef int64_t cl_long8[8] __attribute__((aligned(64))); -typedef int64_t cl_long16[16] __attribute__((aligned(128))); -typedef uint64_t cl_ulong2[2] __attribute__((aligned(16))); -typedef uint64_t cl_ulong4[4] __attribute__((aligned(32))); -typedef uint64_t cl_ulong8[8] __attribute__((aligned(64))); -typedef uint64_t cl_ulong16[16] __attribute__((aligned(128))); - -typedef float cl_float2[2] __attribute__((aligned(8))); -typedef float cl_float4[4] __attribute__((aligned(16))); -typedef float cl_float8[8] __attribute__((aligned(32))); -typedef float cl_float16[16] __attribute__((aligned(64))); - -typedef double cl_double2[2] __attribute__((aligned(16))); -typedef double cl_double4[4] __attribute__((aligned(32))); -typedef double cl_double8[8] __attribute__((aligned(64))); -typedef double cl_double16[16] __attribute__((aligned(128))); -#endif - -#include - -/* and a few goodies to go with them */ -#define CL_CHAR_BIT 8 -#define CL_SCHAR_MAX 127 -#define CL_SCHAR_MIN (-127-1) -#define CL_CHAR_MAX CL_SCHAR_MAX -#define CL_CHAR_MIN CL_SCHAR_MIN -#define CL_UCHAR_MAX 255 -#define CL_SHRT_MAX 32767 -#define CL_SHRT_MIN (-32767-1) -#define CL_USHRT_MAX 65535 -#define CL_INT_MAX 2147483647 -#define CL_INT_MIN (-2147483647-1) -#define CL_UINT_MAX 0xffffffffU -#define CL_LONG_MAX ((cl_long) 0x7FFFFFFFFFFFFFFFLL) -#define CL_LONG_MIN ((cl_long) -0x7FFFFFFFFFFFFFFFLL - 1LL) -#define CL_ULONG_MAX ((cl_ulong) 0xFFFFFFFFFFFFFFFFULL) - -#define CL_FLT_DIG 6 -#define CL_FLT_MANT_DIG 24 -#define CL_FLT_MAX_10_EXP +38 -#define CL_FLT_MAX_EXP +128 -#define CL_FLT_MIN_10_EXP -37 -#define CL_FLT_MIN_EXP -125 -#define CL_FLT_RADIX 2 -#define CL_FLT_MAX 0x1.fffffep127f -#define CL_FLT_MIN 0x1.0p-126f -#define CL_FLT_EPSILON 0x1.0p-23f - -#define CL_DBL_DIG 15 -#define CL_DBL_MANT_DIG 53 -#define CL_DBL_MAX_10_EXP +308 -#define CL_DBL_MAX_EXP +1024 -#define CL_DBL_MIN_10_EXP -307 -#define CL_DBL_MIN_EXP -1021 -#define CL_DBL_RADIX 2 -#define CL_DBL_MAX 0x1.fffffffffffffp1023 -#define CL_DBL_MIN 0x1.0p-1022 -#define CL_DBL_EPSILON 0x1.0p-52 - -/* There are no vector types for half */ - -#ifdef __cplusplus -} -#endif - -#endif // __CL_PLATFORM_H diff --git a/Code/Physics/Bullet Source/src/vectormath/neon/boolInVec.h b/Code/Physics/Bullet Source/src/vectormath/neon/boolInVec.h deleted file mode 100644 index ba16838c..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/neon/boolInVec.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _BOOLINVEC_H -#define _BOOLINVEC_H - -#include -namespace Vectormath { - -class floatInVec; - -//-------------------------------------------------------------------------------------------------- -// boolInVec class -// - -class boolInVec -{ -private: - unsigned int mData; - -public: - // Default constructor; does no initialization - // - inline boolInVec( ) { }; - - // Construct from a value converted from float - // - inline boolInVec(floatInVec vec); - - // Explicit cast from bool - // - explicit inline boolInVec(bool scalar); - - // Explicit cast to bool - // - inline bool getAsBool() const; - -#ifndef _VECTORMATH_NO_SCALAR_CAST - // Implicit cast to bool - // - inline operator bool() const; -#endif - - // Boolean negation operator - // - inline const boolInVec operator ! () const; - - // Assignment operator - // - inline boolInVec& operator = (boolInVec vec); - - // Boolean and assignment operator - // - inline boolInVec& operator &= (boolInVec vec); - - // Boolean exclusive or assignment operator - // - inline boolInVec& operator ^= (boolInVec vec); - - // Boolean or assignment operator - // - inline boolInVec& operator |= (boolInVec vec); - -}; - -// Equal operator -// -inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); - -// Not equal operator -// -inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); - -// And operator -// -inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); - -// Exclusive or operator -// -inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); - -// Or operator -// -inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); - -// Conditionally select between two values -// -inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); - - -} // namespace Vectormath - - -//-------------------------------------------------------------------------------------------------- -// boolInVec implementation -// - -#include "floatInVec.h" - -namespace Vectormath { - -inline -boolInVec::boolInVec(floatInVec vec) -{ - *this = (vec != floatInVec(0.0f)); -} - -inline -boolInVec::boolInVec(bool scalar) -{ - mData = -(int)scalar; -} - -inline -bool -boolInVec::getAsBool() const -{ - return (mData > 0); -} - -#ifndef _VECTORMATH_NO_SCALAR_CAST -inline -boolInVec::operator bool() const -{ - return getAsBool(); -} -#endif - -inline -const boolInVec -boolInVec::operator ! () const -{ - return boolInVec(!mData); -} - -inline -boolInVec& -boolInVec::operator = (boolInVec vec) -{ - mData = vec.mData; - return *this; -} - -inline -boolInVec& -boolInVec::operator &= (boolInVec vec) -{ - *this = *this & vec; - return *this; -} - -inline -boolInVec& -boolInVec::operator ^= (boolInVec vec) -{ - *this = *this ^ vec; - return *this; -} - -inline -boolInVec& -boolInVec::operator |= (boolInVec vec) -{ - *this = *this | vec; - return *this; -} - -inline -const boolInVec -operator == (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() == vec1.getAsBool()); -} - -inline -const boolInVec -operator != (boolInVec vec0, boolInVec vec1) -{ - return !(vec0 == vec1); -} - -inline -const boolInVec -operator & (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() & vec1.getAsBool()); -} - -inline -const boolInVec -operator | (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() | vec1.getAsBool()); -} - -inline -const boolInVec -operator ^ (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); -} - -inline -const boolInVec -select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) -{ - return (select_vec1.getAsBool() == 0) ? vec0 : vec1; -} - -} // namespace Vectormath - -#endif // boolInVec_h - diff --git a/Code/Physics/Bullet Source/src/vectormath/neon/floatInVec.h b/Code/Physics/Bullet Source/src/vectormath/neon/floatInVec.h deleted file mode 100644 index 26147d22..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/neon/floatInVec.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _FLOATINVEC_H -#define _FLOATINVEC_H - -#include -namespace Vectormath { - -class boolInVec; - -//-------------------------------------------------------------------------------------------------- -// floatInVec class -// - -// A class representing a scalar float value contained in a vector register -// This class does not support fastmath -class floatInVec -{ -private: - float mData; - -public: - // Default constructor; does no initialization - // - inline floatInVec( ) { }; - - // Construct from a value converted from bool - // - inline floatInVec(boolInVec vec); - - // Explicit cast from float - // - explicit inline floatInVec(float scalar); - - // Explicit cast to float - // - inline float getAsFloat() const; - -#ifndef _VECTORMATH_NO_SCALAR_CAST - // Implicit cast to float - // - inline operator float() const; -#endif - - // Post increment (add 1.0f) - // - inline const floatInVec operator ++ (int); - - // Post decrement (subtract 1.0f) - // - inline const floatInVec operator -- (int); - - // Pre increment (add 1.0f) - // - inline floatInVec& operator ++ (); - - // Pre decrement (subtract 1.0f) - // - inline floatInVec& operator -- (); - - // Negation operator - // - inline const floatInVec operator - () const; - - // Assignment operator - // - inline floatInVec& operator = (floatInVec vec); - - // Multiplication assignment operator - // - inline floatInVec& operator *= (floatInVec vec); - - // Division assignment operator - // - inline floatInVec& operator /= (floatInVec vec); - - // Addition assignment operator - // - inline floatInVec& operator += (floatInVec vec); - - // Subtraction assignment operator - // - inline floatInVec& operator -= (floatInVec vec); - -}; - -// Multiplication operator -// -inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); - -// Division operator -// -inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); - -// Addition operator -// -inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); - -// Subtraction operator -// -inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); - -// Less than operator -// -inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); - -// Less than or equal operator -// -inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); - -// Greater than operator -// -inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); - -// Greater than or equal operator -// -inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); - -// Equal operator -// -inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); - -// Not equal operator -// -inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); - -// Conditionally select between two values -// -inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); - - -} // namespace Vectormath - - -//-------------------------------------------------------------------------------------------------- -// floatInVec implementation -// - -#include "boolInVec.h" - -namespace Vectormath { - -inline -floatInVec::floatInVec(boolInVec vec) -{ - mData = float(vec.getAsBool()); -} - -inline -floatInVec::floatInVec(float scalar) -{ - mData = scalar; -} - -inline -float -floatInVec::getAsFloat() const -{ - return mData; -} - -#ifndef _VECTORMATH_NO_SCALAR_CAST -inline -floatInVec::operator float() const -{ - return getAsFloat(); -} -#endif - -inline -const floatInVec -floatInVec::operator ++ (int) -{ - float olddata = mData; - operator ++(); - return floatInVec(olddata); -} - -inline -const floatInVec -floatInVec::operator -- (int) -{ - float olddata = mData; - operator --(); - return floatInVec(olddata); -} - -inline -floatInVec& -floatInVec::operator ++ () -{ - *this += floatInVec(1.0f); - return *this; -} - -inline -floatInVec& -floatInVec::operator -- () -{ - *this -= floatInVec(1.0f); - return *this; -} - -inline -const floatInVec -floatInVec::operator - () const -{ - return floatInVec(-mData); -} - -inline -floatInVec& -floatInVec::operator = (floatInVec vec) -{ - mData = vec.mData; - return *this; -} - -inline -floatInVec& -floatInVec::operator *= (floatInVec vec) -{ - *this = *this * vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator /= (floatInVec vec) -{ - *this = *this / vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator += (floatInVec vec) -{ - *this = *this + vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator -= (floatInVec vec) -{ - *this = *this - vec; - return *this; -} - -inline -const floatInVec -operator * (floatInVec vec0, floatInVec vec1) -{ - return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); -} - -inline -const floatInVec -operator / (floatInVec num, floatInVec den) -{ - return floatInVec(num.getAsFloat() / den.getAsFloat()); -} - -inline -const floatInVec -operator + (floatInVec vec0, floatInVec vec1) -{ - return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); -} - -inline -const floatInVec -operator - (floatInVec vec0, floatInVec vec1) -{ - return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); -} - -inline -const boolInVec -operator < (floatInVec vec0, floatInVec vec1) -{ - return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); -} - -inline -const boolInVec -operator <= (floatInVec vec0, floatInVec vec1) -{ - return !(vec0 > vec1); -} - -inline -const boolInVec -operator > (floatInVec vec0, floatInVec vec1) -{ - return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); -} - -inline -const boolInVec -operator >= (floatInVec vec0, floatInVec vec1) -{ - return !(vec0 < vec1); -} - -inline -const boolInVec -operator == (floatInVec vec0, floatInVec vec1) -{ - return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); -} - -inline -const boolInVec -operator != (floatInVec vec0, floatInVec vec1) -{ - return !(vec0 == vec1); -} - -inline -const floatInVec -select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) -{ - return (select_vec1.getAsBool() == 0) ? vec0 : vec1; -} - -} // namespace Vectormath - -#endif // floatInVec_h - diff --git a/Code/Physics/Bullet Source/src/vectormath/neon/mat_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/mat_aos.h deleted file mode 100644 index e61f601c..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/neon/mat_aos.h +++ /dev/null @@ -1,1631 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_MAT_AOS_CPP_H -#define _VECTORMATH_MAT_AOS_CPP_H - -namespace Vectormath { -namespace Aos { - -//----------------------------------------------------------------------------- -// Constants - -#define _VECTORMATH_PI_OVER_2 1.570796327f - -//----------------------------------------------------------------------------- -// Definitions - -inline Matrix3::Matrix3( const Matrix3 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; -} - -inline Matrix3::Matrix3( float scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); -} - -inline Matrix3::Matrix3( const Quat & unitQuat ) -{ - float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; - qx = unitQuat.getX(); - qy = unitQuat.getY(); - qz = unitQuat.getZ(); - qw = unitQuat.getW(); - qx2 = ( qx + qx ); - qy2 = ( qy + qy ); - qz2 = ( qz + qz ); - qxqx2 = ( qx * qx2 ); - qxqy2 = ( qx * qy2 ); - qxqz2 = ( qx * qz2 ); - qxqw2 = ( qw * qx2 ); - qyqy2 = ( qy * qy2 ); - qyqz2 = ( qy * qz2 ); - qyqw2 = ( qw * qy2 ); - qzqz2 = ( qz * qz2 ); - qzqw2 = ( qw * qz2 ); - mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); - mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); - mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); -} - -inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; -} - -inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) -{ - mCol0 = _col0; - return *this; -} - -inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) -{ - mCol1 = _col1; - return *this; -} - -inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) -{ - mCol2 = _col2; - return *this; -} - -inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - return *this; -} - -inline Matrix3 & Matrix3::setElem( int col, int row, float val ) -{ - Vector3 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -inline float Matrix3::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -inline const Vector3 Matrix3::getCol0( ) const -{ - return mCol0; -} - -inline const Vector3 Matrix3::getCol1( ) const -{ - return mCol1; -} - -inline const Vector3 Matrix3::getCol2( ) const -{ - return mCol2; -} - -inline const Vector3 Matrix3::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -inline const Vector3 Matrix3::getRow( int row ) const -{ - return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); -} - -inline Vector3 & Matrix3::operator []( int col ) -{ - return *(&mCol0 + col); -} - -inline const Vector3 Matrix3::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - return *this; -} - -inline const Matrix3 transpose( const Matrix3 & mat ) -{ - return Matrix3( - Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), - Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), - Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) - ); -} - -inline const Matrix3 inverse( const Matrix3 & mat ) -{ - Vector3 tmp0, tmp1, tmp2; - float detinv; - tmp0 = cross( mat.getCol1(), mat.getCol2() ); - tmp1 = cross( mat.getCol2(), mat.getCol0() ); - tmp2 = cross( mat.getCol0(), mat.getCol1() ); - detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); - return Matrix3( - Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), - Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), - Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) - ); -} - -inline float determinant( const Matrix3 & mat ) -{ - return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); -} - -inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const -{ - return Matrix3( - ( mCol0 + mat.mCol0 ), - ( mCol1 + mat.mCol1 ), - ( mCol2 + mat.mCol2 ) - ); -} - -inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const -{ - return Matrix3( - ( mCol0 - mat.mCol0 ), - ( mCol1 - mat.mCol1 ), - ( mCol2 - mat.mCol2 ) - ); -} - -inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) -{ - *this = *this + mat; - return *this; -} - -inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) -{ - *this = *this - mat; - return *this; -} - -inline const Matrix3 Matrix3::operator -( ) const -{ - return Matrix3( - ( -mCol0 ), - ( -mCol1 ), - ( -mCol2 ) - ); -} - -inline const Matrix3 absPerElem( const Matrix3 & mat ) -{ - return Matrix3( - absPerElem( mat.getCol0() ), - absPerElem( mat.getCol1() ), - absPerElem( mat.getCol2() ) - ); -} - -inline const Matrix3 Matrix3::operator *( float scalar ) const -{ - return Matrix3( - ( mCol0 * scalar ), - ( mCol1 * scalar ), - ( mCol2 * scalar ) - ); -} - -inline Matrix3 & Matrix3::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) -{ - return mat * scalar; -} - -inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const -{ - return Vector3( - ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), - ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), - ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) - ); -} - -inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const -{ - return Matrix3( - ( *this * mat.mCol0 ), - ( *this * mat.mCol1 ), - ( *this * mat.mCol2 ) - ); -} - -inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) -{ - *this = *this * mat; - return *this; -} - -inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) -{ - return Matrix3( - mulPerElem( mat0.getCol0(), mat1.getCol0() ), - mulPerElem( mat0.getCol1(), mat1.getCol1() ), - mulPerElem( mat0.getCol2(), mat1.getCol2() ) - ); -} - -inline const Matrix3 Matrix3::identity( ) -{ - return Matrix3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ) - ); -} - -inline const Matrix3 Matrix3::rotationX( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix3( - Vector3::xAxis( ), - Vector3( 0.0f, c, s ), - Vector3( 0.0f, -s, c ) - ); -} - -inline const Matrix3 Matrix3::rotationY( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix3( - Vector3( c, 0.0f, -s ), - Vector3::yAxis( ), - Vector3( s, 0.0f, c ) - ); -} - -inline const Matrix3 Matrix3::rotationZ( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix3( - Vector3( c, s, 0.0f ), - Vector3( -s, c, 0.0f ), - Vector3::zAxis( ) - ); -} - -inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) -{ - float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; - sX = sinf( radiansXYZ.getX() ); - cX = cosf( radiansXYZ.getX() ); - sY = sinf( radiansXYZ.getY() ); - cY = cosf( radiansXYZ.getY() ); - sZ = sinf( radiansXYZ.getZ() ); - cZ = cosf( radiansXYZ.getZ() ); - tmp0 = ( cZ * sY ); - tmp1 = ( sZ * sY ); - return Matrix3( - Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), - Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), - Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) - ); -} - -inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) -{ - float x, y, z, s, c, oneMinusC, xy, yz, zx; - s = sinf( radians ); - c = cosf( radians ); - x = unitVec.getX(); - y = unitVec.getY(); - z = unitVec.getZ(); - xy = ( x * y ); - yz = ( y * z ); - zx = ( z * x ); - oneMinusC = ( 1.0f - c ); - return Matrix3( - Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), - Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), - Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) - ); -} - -inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) -{ - return Matrix3( unitQuat ); -} - -inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) -{ - return Matrix3( - Vector3( scaleVec.getX(), 0.0f, 0.0f ), - Vector3( 0.0f, scaleVec.getY(), 0.0f ), - Vector3( 0.0f, 0.0f, scaleVec.getZ() ) - ); -} - -inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) -{ - return Matrix3( - ( mat.getCol0() * scaleVec.getX( ) ), - ( mat.getCol1() * scaleVec.getY( ) ), - ( mat.getCol2() * scaleVec.getZ( ) ) - ); -} - -inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) -{ - return Matrix3( - mulPerElem( mat.getCol0(), scaleVec ), - mulPerElem( mat.getCol1(), scaleVec ), - mulPerElem( mat.getCol2(), scaleVec ) - ); -} - -inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) -{ - return Matrix3( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Matrix3 & mat ) -{ - print( mat.getRow( 0 ) ); - print( mat.getRow( 1 ) ); - print( mat.getRow( 2 ) ); -} - -inline void print( const Matrix3 & mat, const char * name ) -{ - printf("%s:\n", name); - print( mat ); -} - -#endif - -inline Matrix4::Matrix4( const Matrix4 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - mCol3 = mat.mCol3; -} - -inline Matrix4::Matrix4( float scalar ) -{ - mCol0 = Vector4( scalar ); - mCol1 = Vector4( scalar ); - mCol2 = Vector4( scalar ); - mCol3 = Vector4( scalar ); -} - -inline Matrix4::Matrix4( const Transform3 & mat ) -{ - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( mat.getCol3(), 1.0f ); -} - -inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; - mCol3 = _col3; -} - -inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) -{ - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( translateVec, 1.0f ); -} - -inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) -{ - Matrix3 mat; - mat = Matrix3( unitQuat ); - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( translateVec, 1.0f ); -} - -inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) -{ - mCol0 = _col0; - return *this; -} - -inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) -{ - mCol1 = _col1; - return *this; -} - -inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) -{ - mCol2 = _col2; - return *this; -} - -inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) -{ - mCol3 = _col3; - return *this; -} - -inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - mCol3.setElem( row, vec.getElem( 3 ) ); - return *this; -} - -inline Matrix4 & Matrix4::setElem( int col, int row, float val ) -{ - Vector4 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -inline float Matrix4::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -inline const Vector4 Matrix4::getCol0( ) const -{ - return mCol0; -} - -inline const Vector4 Matrix4::getCol1( ) const -{ - return mCol1; -} - -inline const Vector4 Matrix4::getCol2( ) const -{ - return mCol2; -} - -inline const Vector4 Matrix4::getCol3( ) const -{ - return mCol3; -} - -inline const Vector4 Matrix4::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -inline const Vector4 Matrix4::getRow( int row ) const -{ - return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); -} - -inline Vector4 & Matrix4::operator []( int col ) -{ - return *(&mCol0 + col); -} - -inline const Vector4 Matrix4::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - mCol3 = mat.mCol3; - return *this; -} - -inline const Matrix4 transpose( const Matrix4 & mat ) -{ - return Matrix4( - Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), - Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), - Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), - Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) - ); -} - -inline const Matrix4 inverse( const Matrix4 & mat ) -{ - Vector4 res0, res1, res2, res3; - float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; - mA = mat.getCol0().getX(); - mB = mat.getCol0().getY(); - mC = mat.getCol0().getZ(); - mD = mat.getCol0().getW(); - mE = mat.getCol1().getX(); - mF = mat.getCol1().getY(); - mG = mat.getCol1().getZ(); - mH = mat.getCol1().getW(); - mI = mat.getCol2().getX(); - mJ = mat.getCol2().getY(); - mK = mat.getCol2().getZ(); - mL = mat.getCol2().getW(); - mM = mat.getCol3().getX(); - mN = mat.getCol3().getY(); - mO = mat.getCol3().getZ(); - mP = mat.getCol3().getW(); - tmp0 = ( ( mK * mD ) - ( mC * mL ) ); - tmp1 = ( ( mO * mH ) - ( mG * mP ) ); - tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); - tmp3 = ( ( mF * mO ) - ( mN * mG ) ); - tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); - tmp5 = ( ( mN * mH ) - ( mF * mP ) ); - res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); - res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); - res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); - res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); - detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); - res1.setX( ( mI * tmp1 ) ); - res1.setY( ( mM * tmp0 ) ); - res1.setZ( ( mA * tmp1 ) ); - res1.setW( ( mE * tmp0 ) ); - res3.setX( ( mI * tmp3 ) ); - res3.setY( ( mM * tmp2 ) ); - res3.setZ( ( mA * tmp3 ) ); - res3.setW( ( mE * tmp2 ) ); - res2.setX( ( mI * tmp5 ) ); - res2.setY( ( mM * tmp4 ) ); - res2.setZ( ( mA * tmp5 ) ); - res2.setW( ( mE * tmp4 ) ); - tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); - tmp1 = ( ( mM * mF ) - ( mE * mN ) ); - tmp2 = ( ( mI * mD ) - ( mA * mL ) ); - tmp3 = ( ( mM * mH ) - ( mE * mP ) ); - tmp4 = ( ( mI * mC ) - ( mA * mK ) ); - tmp5 = ( ( mM * mG ) - ( mE * mO ) ); - res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); - res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); - res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); - res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); - res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); - res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); - res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); - res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); - res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); - res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); - res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); - res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); - return Matrix4( - ( res0 * detInv ), - ( res1 * detInv ), - ( res2 * detInv ), - ( res3 * detInv ) - ); -} - -inline const Matrix4 affineInverse( const Matrix4 & mat ) -{ - Transform3 affineMat; - affineMat.setCol0( mat.getCol0().getXYZ( ) ); - affineMat.setCol1( mat.getCol1().getXYZ( ) ); - affineMat.setCol2( mat.getCol2().getXYZ( ) ); - affineMat.setCol3( mat.getCol3().getXYZ( ) ); - return Matrix4( inverse( affineMat ) ); -} - -inline const Matrix4 orthoInverse( const Matrix4 & mat ) -{ - Transform3 affineMat; - affineMat.setCol0( mat.getCol0().getXYZ( ) ); - affineMat.setCol1( mat.getCol1().getXYZ( ) ); - affineMat.setCol2( mat.getCol2().getXYZ( ) ); - affineMat.setCol3( mat.getCol3().getXYZ( ) ); - return Matrix4( orthoInverse( affineMat ) ); -} - -inline float determinant( const Matrix4 & mat ) -{ - float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - mA = mat.getCol0().getX(); - mB = mat.getCol0().getY(); - mC = mat.getCol0().getZ(); - mD = mat.getCol0().getW(); - mE = mat.getCol1().getX(); - mF = mat.getCol1().getY(); - mG = mat.getCol1().getZ(); - mH = mat.getCol1().getW(); - mI = mat.getCol2().getX(); - mJ = mat.getCol2().getY(); - mK = mat.getCol2().getZ(); - mL = mat.getCol2().getW(); - mM = mat.getCol3().getX(); - mN = mat.getCol3().getY(); - mO = mat.getCol3().getZ(); - mP = mat.getCol3().getW(); - tmp0 = ( ( mK * mD ) - ( mC * mL ) ); - tmp1 = ( ( mO * mH ) - ( mG * mP ) ); - tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); - tmp3 = ( ( mF * mO ) - ( mN * mG ) ); - tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); - tmp5 = ( ( mN * mH ) - ( mF * mP ) ); - dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); - dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); - dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); - dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); - return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); -} - -inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const -{ - return Matrix4( - ( mCol0 + mat.mCol0 ), - ( mCol1 + mat.mCol1 ), - ( mCol2 + mat.mCol2 ), - ( mCol3 + mat.mCol3 ) - ); -} - -inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const -{ - return Matrix4( - ( mCol0 - mat.mCol0 ), - ( mCol1 - mat.mCol1 ), - ( mCol2 - mat.mCol2 ), - ( mCol3 - mat.mCol3 ) - ); -} - -inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) -{ - *this = *this + mat; - return *this; -} - -inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) -{ - *this = *this - mat; - return *this; -} - -inline const Matrix4 Matrix4::operator -( ) const -{ - return Matrix4( - ( -mCol0 ), - ( -mCol1 ), - ( -mCol2 ), - ( -mCol3 ) - ); -} - -inline const Matrix4 absPerElem( const Matrix4 & mat ) -{ - return Matrix4( - absPerElem( mat.getCol0() ), - absPerElem( mat.getCol1() ), - absPerElem( mat.getCol2() ), - absPerElem( mat.getCol3() ) - ); -} - -inline const Matrix4 Matrix4::operator *( float scalar ) const -{ - return Matrix4( - ( mCol0 * scalar ), - ( mCol1 * scalar ), - ( mCol2 * scalar ), - ( mCol3 * scalar ) - ); -} - -inline Matrix4 & Matrix4::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) -{ - return mat * scalar; -} - -inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const -{ - return Vector4( - ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), - ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), - ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), - ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) - ); -} - -inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const -{ - return Vector4( - ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), - ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), - ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), - ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) - ); -} - -inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const -{ - return Vector4( - ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), - ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), - ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), - ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) - ); -} - -inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const -{ - return Matrix4( - ( *this * mat.mCol0 ), - ( *this * mat.mCol1 ), - ( *this * mat.mCol2 ), - ( *this * mat.mCol3 ) - ); -} - -inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) -{ - *this = *this * mat; - return *this; -} - -inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const -{ - return Matrix4( - ( *this * tfrm.getCol0() ), - ( *this * tfrm.getCol1() ), - ( *this * tfrm.getCol2() ), - ( *this * Point3( tfrm.getCol3() ) ) - ); -} - -inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) -{ - *this = *this * tfrm; - return *this; -} - -inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) -{ - return Matrix4( - mulPerElem( mat0.getCol0(), mat1.getCol0() ), - mulPerElem( mat0.getCol1(), mat1.getCol1() ), - mulPerElem( mat0.getCol2(), mat1.getCol2() ), - mulPerElem( mat0.getCol3(), mat1.getCol3() ) - ); -} - -inline const Matrix4 Matrix4::identity( ) -{ - return Matrix4( - Vector4::xAxis( ), - Vector4::yAxis( ), - Vector4::zAxis( ), - Vector4::wAxis( ) - ); -} - -inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) -{ - mCol0.setXYZ( mat3.getCol0() ); - mCol1.setXYZ( mat3.getCol1() ); - mCol2.setXYZ( mat3.getCol2() ); - return *this; -} - -inline const Matrix3 Matrix4::getUpper3x3( ) const -{ - return Matrix3( - mCol0.getXYZ( ), - mCol1.getXYZ( ), - mCol2.getXYZ( ) - ); -} - -inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) -{ - mCol3.setXYZ( translateVec ); - return *this; -} - -inline const Vector3 Matrix4::getTranslation( ) const -{ - return mCol3.getXYZ( ); -} - -inline const Matrix4 Matrix4::rotationX( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix4( - Vector4::xAxis( ), - Vector4( 0.0f, c, s, 0.0f ), - Vector4( 0.0f, -s, c, 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotationY( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix4( - Vector4( c, 0.0f, -s, 0.0f ), - Vector4::yAxis( ), - Vector4( s, 0.0f, c, 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotationZ( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix4( - Vector4( c, s, 0.0f, 0.0f ), - Vector4( -s, c, 0.0f, 0.0f ), - Vector4::zAxis( ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) -{ - float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; - sX = sinf( radiansXYZ.getX() ); - cX = cosf( radiansXYZ.getX() ); - sY = sinf( radiansXYZ.getY() ); - cY = cosf( radiansXYZ.getY() ); - sZ = sinf( radiansXYZ.getZ() ); - cZ = cosf( radiansXYZ.getZ() ); - tmp0 = ( cZ * sY ); - tmp1 = ( sZ * sY ); - return Matrix4( - Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), - Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), - Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) -{ - float x, y, z, s, c, oneMinusC, xy, yz, zx; - s = sinf( radians ); - c = cosf( radians ); - x = unitVec.getX(); - y = unitVec.getY(); - z = unitVec.getZ(); - xy = ( x * y ); - yz = ( y * z ); - zx = ( z * x ); - oneMinusC = ( 1.0f - c ); - return Matrix4( - Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), - Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), - Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) -{ - return Matrix4( Transform3::rotation( unitQuat ) ); -} - -inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) -{ - return Matrix4( - Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), - Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) -{ - return Matrix4( - ( mat.getCol0() * scaleVec.getX( ) ), - ( mat.getCol1() * scaleVec.getY( ) ), - ( mat.getCol2() * scaleVec.getZ( ) ), - mat.getCol3() - ); -} - -inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) -{ - Vector4 scale4; - scale4 = Vector4( scaleVec, 1.0f ); - return Matrix4( - mulPerElem( mat.getCol0(), scale4 ), - mulPerElem( mat.getCol1(), scale4 ), - mulPerElem( mat.getCol2(), scale4 ), - mulPerElem( mat.getCol3(), scale4 ) - ); -} - -inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) -{ - return Matrix4( - Vector4::xAxis( ), - Vector4::yAxis( ), - Vector4::zAxis( ), - Vector4( translateVec, 1.0f ) - ); -} - -inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) -{ - Matrix4 m4EyeFrame; - Vector3 v3X, v3Y, v3Z; - v3Y = normalize( upVec ); - v3Z = normalize( ( eyePos - lookAtPos ) ); - v3X = normalize( cross( v3Y, v3Z ) ); - v3Y = cross( v3Z, v3X ); - m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); - return orthoInverse( m4EyeFrame ); -} - -inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) -{ - float f, rangeInv; - f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); - rangeInv = ( 1.0f / ( zNear - zFar ) ); - return Matrix4( - Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, f, 0.0f, 0.0f ), - Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), - Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) - ); -} - -inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) -{ - float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; - sum_rl = ( right + left ); - sum_tb = ( top + bottom ); - sum_nf = ( zNear + zFar ); - inv_rl = ( 1.0f / ( right - left ) ); - inv_tb = ( 1.0f / ( top - bottom ) ); - inv_nf = ( 1.0f / ( zNear - zFar ) ); - n2 = ( zNear + zNear ); - return Matrix4( - Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), - Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), - Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) - ); -} - -inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) -{ - float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; - sum_rl = ( right + left ); - sum_tb = ( top + bottom ); - sum_nf = ( zNear + zFar ); - inv_rl = ( 1.0f / ( right - left ) ); - inv_tb = ( 1.0f / ( top - bottom ) ); - inv_nf = ( 1.0f / ( zNear - zFar ) ); - return Matrix4( - Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), - Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), - Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) - ); -} - -inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) -{ - return Matrix4( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ), - select( mat0.getCol3(), mat1.getCol3(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Matrix4 & mat ) -{ - print( mat.getRow( 0 ) ); - print( mat.getRow( 1 ) ); - print( mat.getRow( 2 ) ); - print( mat.getRow( 3 ) ); -} - -inline void print( const Matrix4 & mat, const char * name ) -{ - printf("%s:\n", name); - print( mat ); -} - -#endif - -inline Transform3::Transform3( const Transform3 & tfrm ) -{ - mCol0 = tfrm.mCol0; - mCol1 = tfrm.mCol1; - mCol2 = tfrm.mCol2; - mCol3 = tfrm.mCol3; -} - -inline Transform3::Transform3( float scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); - mCol3 = Vector3( scalar ); -} - -inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; - mCol3 = _col3; -} - -inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) -{ - this->setUpper3x3( tfrm ); - this->setTranslation( translateVec ); -} - -inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) -{ - this->setUpper3x3( Matrix3( unitQuat ) ); - this->setTranslation( translateVec ); -} - -inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) -{ - mCol0 = _col0; - return *this; -} - -inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) -{ - mCol1 = _col1; - return *this; -} - -inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) -{ - mCol2 = _col2; - return *this; -} - -inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) -{ - mCol3 = _col3; - return *this; -} - -inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - mCol3.setElem( row, vec.getElem( 3 ) ); - return *this; -} - -inline Transform3 & Transform3::setElem( int col, int row, float val ) -{ - Vector3 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -inline float Transform3::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -inline const Vector3 Transform3::getCol0( ) const -{ - return mCol0; -} - -inline const Vector3 Transform3::getCol1( ) const -{ - return mCol1; -} - -inline const Vector3 Transform3::getCol2( ) const -{ - return mCol2; -} - -inline const Vector3 Transform3::getCol3( ) const -{ - return mCol3; -} - -inline const Vector3 Transform3::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -inline const Vector4 Transform3::getRow( int row ) const -{ - return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); -} - -inline Vector3 & Transform3::operator []( int col ) -{ - return *(&mCol0 + col); -} - -inline const Vector3 Transform3::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) -{ - mCol0 = tfrm.mCol0; - mCol1 = tfrm.mCol1; - mCol2 = tfrm.mCol2; - mCol3 = tfrm.mCol3; - return *this; -} - -inline const Transform3 inverse( const Transform3 & tfrm ) -{ - Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; - float detinv; - tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); - tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); - tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); - detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); - inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); - inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); - inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); - return Transform3( - inv0, - inv1, - inv2, - Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) - ); -} - -inline const Transform3 orthoInverse( const Transform3 & tfrm ) -{ - Vector3 inv0, inv1, inv2; - inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); - inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); - inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); - return Transform3( - inv0, - inv1, - inv2, - Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) - ); -} - -inline const Transform3 absPerElem( const Transform3 & tfrm ) -{ - return Transform3( - absPerElem( tfrm.getCol0() ), - absPerElem( tfrm.getCol1() ), - absPerElem( tfrm.getCol2() ), - absPerElem( tfrm.getCol3() ) - ); -} - -inline const Vector3 Transform3::operator *( const Vector3 & vec ) const -{ - return Vector3( - ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), - ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), - ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) - ); -} - -inline const Point3 Transform3::operator *( const Point3 & pnt ) const -{ - return Point3( - ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), - ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), - ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) - ); -} - -inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const -{ - return Transform3( - ( *this * tfrm.mCol0 ), - ( *this * tfrm.mCol1 ), - ( *this * tfrm.mCol2 ), - Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) - ); -} - -inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) -{ - *this = *this * tfrm; - return *this; -} - -inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) -{ - return Transform3( - mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), - mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), - mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), - mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) - ); -} - -inline const Transform3 Transform3::identity( ) -{ - return Transform3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ), - Vector3( 0.0f ) - ); -} - -inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) -{ - mCol0 = tfrm.getCol0(); - mCol1 = tfrm.getCol1(); - mCol2 = tfrm.getCol2(); - return *this; -} - -inline const Matrix3 Transform3::getUpper3x3( ) const -{ - return Matrix3( mCol0, mCol1, mCol2 ); -} - -inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) -{ - mCol3 = translateVec; - return *this; -} - -inline const Vector3 Transform3::getTranslation( ) const -{ - return mCol3; -} - -inline const Transform3 Transform3::rotationX( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Transform3( - Vector3::xAxis( ), - Vector3( 0.0f, c, s ), - Vector3( 0.0f, -s, c ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotationY( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Transform3( - Vector3( c, 0.0f, -s ), - Vector3::yAxis( ), - Vector3( s, 0.0f, c ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotationZ( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Transform3( - Vector3( c, s, 0.0f ), - Vector3( -s, c, 0.0f ), - Vector3::zAxis( ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) -{ - float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; - sX = sinf( radiansXYZ.getX() ); - cX = cosf( radiansXYZ.getX() ); - sY = sinf( radiansXYZ.getY() ); - cY = cosf( radiansXYZ.getY() ); - sZ = sinf( radiansXYZ.getZ() ); - cZ = cosf( radiansXYZ.getZ() ); - tmp0 = ( cZ * sY ); - tmp1 = ( sZ * sY ); - return Transform3( - Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), - Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), - Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) -{ - return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); -} - -inline const Transform3 Transform3::rotation( const Quat & unitQuat ) -{ - return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); -} - -inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) -{ - return Transform3( - Vector3( scaleVec.getX(), 0.0f, 0.0f ), - Vector3( 0.0f, scaleVec.getY(), 0.0f ), - Vector3( 0.0f, 0.0f, scaleVec.getZ() ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) -{ - return Transform3( - ( tfrm.getCol0() * scaleVec.getX( ) ), - ( tfrm.getCol1() * scaleVec.getY( ) ), - ( tfrm.getCol2() * scaleVec.getZ( ) ), - tfrm.getCol3() - ); -} - -inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) -{ - return Transform3( - mulPerElem( tfrm.getCol0(), scaleVec ), - mulPerElem( tfrm.getCol1(), scaleVec ), - mulPerElem( tfrm.getCol2(), scaleVec ), - mulPerElem( tfrm.getCol3(), scaleVec ) - ); -} - -inline const Transform3 Transform3::translation( const Vector3 & translateVec ) -{ - return Transform3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ), - translateVec - ); -} - -inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) -{ - return Transform3( - select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), - select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), - select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), - select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Transform3 & tfrm ) -{ - print( tfrm.getRow( 0 ) ); - print( tfrm.getRow( 1 ) ); - print( tfrm.getRow( 2 ) ); -} - -inline void print( const Transform3 & tfrm, const char * name ) -{ - printf("%s:\n", name); - print( tfrm ); -} - -#endif - -inline Quat::Quat( const Matrix3 & tfrm ) -{ - float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; - int negTrace, ZgtX, ZgtY, YgtX; - int largestXorY, largestYorZ, largestZorX; - - xx = tfrm.getCol0().getX(); - yx = tfrm.getCol0().getY(); - zx = tfrm.getCol0().getZ(); - xy = tfrm.getCol1().getX(); - yy = tfrm.getCol1().getY(); - zy = tfrm.getCol1().getZ(); - xz = tfrm.getCol2().getX(); - yz = tfrm.getCol2().getY(); - zz = tfrm.getCol2().getZ(); - - trace = ( ( xx + yy ) + zz ); - - negTrace = ( trace < 0.0f ); - ZgtX = zz > xx; - ZgtY = zz > yy; - YgtX = yy > xx; - largestXorY = ( !ZgtX || !ZgtY ) && negTrace; - largestYorZ = ( YgtX || ZgtX ) && negTrace; - largestZorX = ( ZgtY || !YgtX ) && negTrace; - - if ( largestXorY ) - { - zz = -zz; - xy = -xy; - } - if ( largestYorZ ) - { - xx = -xx; - yz = -yz; - } - if ( largestZorX ) - { - yy = -yy; - zx = -zx; - } - - radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); - scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); - - tmpx = ( ( zy - yz ) * scale ); - tmpy = ( ( xz - zx ) * scale ); - tmpz = ( ( yx - xy ) * scale ); - tmpw = ( radicand * scale ); - qx = tmpx; - qy = tmpy; - qz = tmpz; - qw = tmpw; - - if ( largestXorY ) - { - qx = tmpw; - qy = tmpz; - qz = tmpy; - qw = tmpx; - } - if ( largestYorZ ) - { - tmpx = qx; - tmpz = qz; - qx = qy; - qy = tmpx; - qz = qw; - qw = tmpz; - } - - mXYZW[0] = qx; - mXYZW[1] = qy; - mXYZW[2] = qz; - mXYZW[3] = qw; -} - -inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) -{ - return Matrix3( - ( tfrm0 * tfrm1.getX( ) ), - ( tfrm0 * tfrm1.getY( ) ), - ( tfrm0 * tfrm1.getZ( ) ) - ); -} - -inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) -{ - return Matrix4( - ( tfrm0 * tfrm1.getX( ) ), - ( tfrm0 * tfrm1.getY( ) ), - ( tfrm0 * tfrm1.getZ( ) ), - ( tfrm0 * tfrm1.getW( ) ) - ); -} - -inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) -{ - return Vector3( - ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), - ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), - ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) - ); -} - -inline const Matrix3 crossMatrix( const Vector3 & vec ) -{ - return Matrix3( - Vector3( 0.0f, vec.getZ(), -vec.getY() ), - Vector3( -vec.getZ(), 0.0f, vec.getX() ), - Vector3( vec.getY(), -vec.getX(), 0.0f ) - ); -} - -inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) -{ - return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); -} - -} // namespace Aos -} // namespace Vectormath - -#endif - diff --git a/Code/Physics/Bullet Source/src/vectormath/neon/quat_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/quat_aos.h deleted file mode 100644 index d0618460..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/neon/quat_aos.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_QUAT_AOS_CPP_H -#define _VECTORMATH_QUAT_AOS_CPP_H - -//----------------------------------------------------------------------------- -// Definitions - -#ifndef _VECTORMATH_INTERNAL_FUNCTIONS -#define _VECTORMATH_INTERNAL_FUNCTIONS - -#endif - -namespace Vectormath { -namespace Aos { - - inline Quat::Quat( const Quat & quat ) - { - vXYZW = quat.vXYZW; - } - - inline Quat::Quat( float _x, float _y, float _z, float _w ) - { - mXYZW[0] = _x; - mXYZW[1] = _y; - mXYZW[2] = _z; - mXYZW[3] = _w; - } - - inline Quat::Quat( float32x4_t fXYZW ) - { - vXYZW = fXYZW; - } - - inline Quat::Quat( const Vector3 & xyz, float _w ) - { - this->setXYZ( xyz ); - this->setW( _w ); - } - - inline Quat::Quat( const Vector4 & vec ) - { - mXYZW[0] = vec.getX(); - mXYZW[1] = vec.getY(); - mXYZW[2] = vec.getZ(); - mXYZW[3] = vec.getW(); - } - - inline Quat::Quat( float scalar ) - { - vXYZW = vdupq_n_f32(scalar); - } - - inline const Quat Quat::identity( ) - { - return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); - } - - inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) - { - return ( quat0 + ( ( quat1 - quat0 ) * t ) ); - } - - inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) - { - Quat start; - float recipSinAngle, scale0, scale1, cosAngle, angle; - cosAngle = dot( unitQuat0, unitQuat1 ); - if ( cosAngle < 0.0f ) { - cosAngle = -cosAngle; - start = ( -unitQuat0 ); - } else { - start = unitQuat0; - } - if ( cosAngle < _VECTORMATH_SLERP_TOL ) { - angle = acosf( cosAngle ); - recipSinAngle = ( 1.0f / sinf( angle ) ); - scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); - scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); - } else { - scale0 = ( 1.0f - t ); - scale1 = t; - } - return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); - } - - inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) - { - Quat tmp0, tmp1; - tmp0 = slerp( t, unitQuat0, unitQuat3 ); - tmp1 = slerp( t, unitQuat1, unitQuat2 ); - return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); - } - - inline void loadXYZW( Quat & quat, const float * fptr ) - { - quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); - } - - inline void storeXYZW( const Quat & quat, float * fptr ) - { - vst1q_f32(fptr, quat.getvXYZW()); - } - - inline Quat & Quat::operator =( const Quat & quat ) - { - vXYZW = quat.getvXYZW(); - return *this; - } - - inline Quat & Quat::setXYZ( const Vector3 & vec ) - { - mXYZW[0] = vec.getX(); - mXYZW[1] = vec.getY(); - mXYZW[2] = vec.getZ(); - return *this; - } - - inline const Vector3 Quat::getXYZ( ) const - { - return Vector3( mXYZW[0], mXYZW[1], mXYZW[2] ); - } - - inline float32x4_t Quat::getvXYZW( ) const - { - return vXYZW; - } - - inline Quat & Quat::setX( float _x ) - { - mXYZW[0] = _x; - return *this; - } - - inline float Quat::getX( ) const - { - return mXYZW[0]; - } - - inline Quat & Quat::setY( float _y ) - { - mXYZW[1] = _y; - return *this; - } - - inline float Quat::getY( ) const - { - return mXYZW[1]; - } - - inline Quat & Quat::setZ( float _z ) - { - mXYZW[2] = _z; - return *this; - } - - inline float Quat::getZ( ) const - { - return mXYZW[2]; - } - - inline Quat & Quat::setW( float _w ) - { - mXYZW[3] = _w; - return *this; - } - - inline float Quat::getW( ) const - { - return mXYZW[3]; - } - - inline Quat & Quat::setElem( int idx, float value ) - { - *(&mXYZW[0] + idx) = value; - return *this; - } - - inline float Quat::getElem( int idx ) const - { - return *(&mXYZW[0] + idx); - } - - inline float & Quat::operator []( int idx ) - { - return *(&mXYZW[0] + idx); - } - - inline float Quat::operator []( int idx ) const - { - return *(&mXYZW[0] + idx); - } - - inline const Quat Quat::operator +( const Quat & quat ) const - { - return Quat( vaddq_f32(vXYZW, quat.vXYZW) ); - } - - inline const Quat Quat::operator -( const Quat & quat ) const - { - return Quat( vsubq_f32(vXYZW, quat.vXYZW) ); - } - - inline const Quat Quat::operator *( float scalar ) const - { - float32x4_t v_scalar = vdupq_n_f32(scalar); - return Quat( vmulq_f32(vXYZW, v_scalar) ); - } - - inline Quat & Quat::operator +=( const Quat & quat ) - { - *this = *this + quat; - return *this; - } - - inline Quat & Quat::operator -=( const Quat & quat ) - { - *this = *this - quat; - return *this; - } - - inline Quat & Quat::operator *=( float scalar ) - { - *this = *this * scalar; - return *this; - } - - inline const Quat Quat::operator /( float scalar ) const - { - return Quat( - ( mXYZW[0] / scalar ), - ( mXYZW[1] / scalar ), - ( mXYZW[2] / scalar ), - ( mXYZW[3] / scalar ) - ); - } - - inline Quat & Quat::operator /=( float scalar ) - { - *this = *this / scalar; - return *this; - } - - inline const Quat Quat::operator -( ) const - { - return Quat( vnegq_f32(vXYZW) ); - } - - inline const Quat operator *( float scalar, const Quat & quat ) - { - return quat * scalar; - } - - inline float dot( const Quat & quat0, const Quat & quat1 ) - { - float result; - result = ( quat0.getX() * quat1.getX() ); - result = ( result + ( quat0.getY() * quat1.getY() ) ); - result = ( result + ( quat0.getZ() * quat1.getZ() ) ); - result = ( result + ( quat0.getW() * quat1.getW() ) ); - return result; - } - - inline float norm( const Quat & quat ) - { - float result; - result = ( quat.getX() * quat.getX() ); - result = ( result + ( quat.getY() * quat.getY() ) ); - result = ( result + ( quat.getZ() * quat.getZ() ) ); - result = ( result + ( quat.getW() * quat.getW() ) ); - return result; - } - - inline float length( const Quat & quat ) - { - return ::sqrtf( norm( quat ) ); - } - - inline const Quat normalize( const Quat & quat ) - { - float lenSqr, lenInv; - lenSqr = norm( quat ); - lenInv = ( 1.0f / sqrtf( lenSqr ) ); - return Quat( - ( quat.getX() * lenInv ), - ( quat.getY() * lenInv ), - ( quat.getZ() * lenInv ), - ( quat.getW() * lenInv ) - ); - } - - inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) - { - float cosHalfAngleX2, recipCosHalfAngleX2; - cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); - recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); - return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); - } - - inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) - { - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( ( unitVec * s ), c ); - } - - inline const Quat Quat::rotationX( float radians ) - { - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( s, 0.0f, 0.0f, c ); - } - - inline const Quat Quat::rotationY( float radians ) - { - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( 0.0f, s, 0.0f, c ); - } - - inline const Quat Quat::rotationZ( float radians ) - { - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( 0.0f, 0.0f, s, c ); - } - - inline const Quat Quat::operator *( const Quat & quat ) const - { - return Quat( - ( ( ( ( mXYZW[3] * quat.mXYZW[0] ) + ( mXYZW[0] * quat.mXYZW[3] ) ) + ( mXYZW[1] * quat.mXYZW[2] ) ) - ( mXYZW[2] * quat.mXYZW[1] ) ), - ( ( ( ( mXYZW[3] * quat.mXYZW[1] ) + ( mXYZW[1] * quat.mXYZW[3] ) ) + ( mXYZW[2] * quat.mXYZW[0] ) ) - ( mXYZW[0] * quat.mXYZW[2] ) ), - ( ( ( ( mXYZW[3] * quat.mXYZW[2] ) + ( mXYZW[2] * quat.mXYZW[3] ) ) + ( mXYZW[0] * quat.mXYZW[1] ) ) - ( mXYZW[1] * quat.mXYZW[0] ) ), - ( ( ( ( mXYZW[3] * quat.mXYZW[3] ) - ( mXYZW[0] * quat.mXYZW[0] ) ) - ( mXYZW[1] * quat.mXYZW[1] ) ) - ( mXYZW[2] * quat.mXYZW[2] ) ) - ); - } - - inline Quat & Quat::operator *=( const Quat & quat ) - { - *this = *this * quat; - return *this; - } - - inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) - { - float tmpX, tmpY, tmpZ, tmpW; - tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); - tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); - tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); - tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); - return Vector3( - ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), - ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), - ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) - ); - } - - inline const Quat conj( const Quat & quat ) - { - return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); - } - - inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) - { - return Quat( - ( select1 )? quat1.getX() : quat0.getX(), - ( select1 )? quat1.getY() : quat0.getY(), - ( select1 )? quat1.getZ() : quat0.getZ(), - ( select1 )? quat1.getW() : quat0.getW() - ); - } - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Quat & quat ) -{ - printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); -} - -inline void print( const Quat & quat, const char * name ) -{ - printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); -} - -#endif - -} // namespace Aos -} // namespace Vectormath - -#endif - diff --git a/Code/Physics/Bullet Source/src/vectormath/neon/vec_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/vec_aos.h deleted file mode 100644 index 7bcf8dbe..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/neon/vec_aos.h +++ /dev/null @@ -1,1427 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_VEC_AOS_CPP_H -#define _VECTORMATH_VEC_AOS_CPP_H - -//----------------------------------------------------------------------------- -// Constants - -#define _VECTORMATH_SLERP_TOL 0.999f - -//----------------------------------------------------------------------------- -// Definitions - -#ifndef _VECTORMATH_INTERNAL_FUNCTIONS -#define _VECTORMATH_INTERNAL_FUNCTIONS - -#endif - -namespace Vectormath { -namespace Aos { - -inline Vector3::Vector3( const Vector3 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; -} - -inline Vector3::Vector3( float _x, float _y, float _z ) -{ - mX = _x; - mY = _y; - mZ = _z; -} - -inline Vector3::Vector3( const Point3 & pnt ) -{ - mX = pnt.getX(); - mY = pnt.getY(); - mZ = pnt.getZ(); -} - -inline Vector3::Vector3( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; -} - -inline const Vector3 Vector3::xAxis( ) -{ - return Vector3( 1.0f, 0.0f, 0.0f ); -} - -inline const Vector3 Vector3::yAxis( ) -{ - return Vector3( 0.0f, 1.0f, 0.0f ); -} - -inline const Vector3 Vector3::zAxis( ) -{ - return Vector3( 0.0f, 0.0f, 1.0f ); -} - -inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) -{ - return ( vec0 + ( ( vec1 - vec0 ) * t ) ); -} - -inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) -{ - float recipSinAngle, scale0, scale1, cosAngle, angle; - cosAngle = dot( unitVec0, unitVec1 ); - if ( cosAngle < _VECTORMATH_SLERP_TOL ) { - angle = acosf( cosAngle ); - recipSinAngle = ( 1.0f / sinf( angle ) ); - scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); - scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); - } else { - scale0 = ( 1.0f - t ); - scale1 = t; - } - return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); -} - -inline void loadXYZ( Vector3 & vec, const float * fptr ) -{ - vec = Vector3( fptr[0], fptr[1], fptr[2] ); -} - -inline void storeXYZ( const Vector3 & vec, float * fptr ) -{ - fptr[0] = vec.getX(); - fptr[1] = vec.getY(); - fptr[2] = vec.getZ(); -} - -inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - unsigned short fp16 = hfptr[i]; - unsigned int sign = fp16 >> 15; - unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); - unsigned int mantissa = fp16 & ((1 << 10) - 1); - - if (exponent == 0) { - // zero - mantissa = 0; - - } else if (exponent == 31) { - // infinity or nan -> infinity - exponent = 255; - mantissa = 0; - - } else { - exponent += 127 - 15; - mantissa <<= 13; - } - - Data32 d; - d.u32 = (sign << 31) | (exponent << 23) | mantissa; - vec[i] = d.f32; - } -} - -inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - Data32 d; - d.f32 = vec[i]; - - unsigned int sign = d.u32 >> 31; - unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); - unsigned int mantissa = d.u32 & ((1 << 23) - 1);; - - if (exponent == 0) { - // zero or denorm -> zero - mantissa = 0; - - } else if (exponent == 255 && mantissa != 0) { - // nan -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent >= 127 - 15 + 31) { - // overflow or infinity -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent <= 127 - 15) { - // underflow -> zero - exponent = 0; - mantissa = 0; - - } else { - exponent -= 127 - 15; - mantissa >>= 13; - } - - hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); - } -} - -inline Vector3 & Vector3::operator =( const Vector3 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; - return *this; -} - -inline Vector3 & Vector3::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Vector3::getX( ) const -{ - return mX; -} - -inline Vector3 & Vector3::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Vector3::getY( ) const -{ - return mY; -} - -inline Vector3 & Vector3::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Vector3::getZ( ) const -{ - return mZ; -} - -inline Vector3 & Vector3::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Vector3::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Vector3::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Vector3::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Vector3 Vector3::operator +( const Vector3 & vec ) const -{ - return Vector3( - ( mX + vec.mX ), - ( mY + vec.mY ), - ( mZ + vec.mZ ) - ); -} - -inline const Vector3 Vector3::operator -( const Vector3 & vec ) const -{ - return Vector3( - ( mX - vec.mX ), - ( mY - vec.mY ), - ( mZ - vec.mZ ) - ); -} - -inline const Point3 Vector3::operator +( const Point3 & pnt ) const -{ - return Point3( - ( mX + pnt.getX() ), - ( mY + pnt.getY() ), - ( mZ + pnt.getZ() ) - ); -} - -inline const Vector3 Vector3::operator *( float scalar ) const -{ - return Vector3( - ( mX * scalar ), - ( mY * scalar ), - ( mZ * scalar ) - ); -} - -inline Vector3 & Vector3::operator +=( const Vector3 & vec ) -{ - *this = *this + vec; - return *this; -} - -inline Vector3 & Vector3::operator -=( const Vector3 & vec ) -{ - *this = *this - vec; - return *this; -} - -inline Vector3 & Vector3::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Vector3 Vector3::operator /( float scalar ) const -{ - return Vector3( - ( mX / scalar ), - ( mY / scalar ), - ( mZ / scalar ) - ); -} - -inline Vector3 & Vector3::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -inline const Vector3 Vector3::operator -( ) const -{ - return Vector3( - -mX, - -mY, - -mZ - ); -} - -inline const Vector3 operator *( float scalar, const Vector3 & vec ) -{ - return vec * scalar; -} - -inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( vec0.getX() * vec1.getX() ), - ( vec0.getY() * vec1.getY() ), - ( vec0.getZ() * vec1.getZ() ) - ); -} - -inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( vec0.getX() / vec1.getX() ), - ( vec0.getY() / vec1.getY() ), - ( vec0.getZ() / vec1.getZ() ) - ); -} - -inline const Vector3 recipPerElem( const Vector3 & vec ) -{ - return Vector3( - ( 1.0f / vec.getX() ), - ( 1.0f / vec.getY() ), - ( 1.0f / vec.getZ() ) - ); -} - -inline const Vector3 sqrtPerElem( const Vector3 & vec ) -{ - return Vector3( - sqrtf( vec.getX() ), - sqrtf( vec.getY() ), - sqrtf( vec.getZ() ) - ); -} - -inline const Vector3 rsqrtPerElem( const Vector3 & vec ) -{ - return Vector3( - ( 1.0f / sqrtf( vec.getX() ) ), - ( 1.0f / sqrtf( vec.getY() ) ), - ( 1.0f / sqrtf( vec.getZ() ) ) - ); -} - -inline const Vector3 absPerElem( const Vector3 & vec ) -{ - return Vector3( - fabsf( vec.getX() ), - fabsf( vec.getY() ), - fabsf( vec.getZ() ) - ); -} - -inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), - ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), - ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) - ); -} - -inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() - ); -} - -inline float maxElem( const Vector3 & vec ) -{ - float result; - result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() > result)? vec.getZ() : result; - return result; -} - -inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() - ); -} - -inline float minElem( const Vector3 & vec ) -{ - float result; - result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() < result)? vec.getZ() : result; - return result; -} - -inline float sum( const Vector3 & vec ) -{ - float result; - result = ( vec.getX() + vec.getY() ); - result = ( result + vec.getZ() ); - return result; -} - -inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) -{ - float result; - result = ( vec0.getX() * vec1.getX() ); - result = ( result + ( vec0.getY() * vec1.getY() ) ); - result = ( result + ( vec0.getZ() * vec1.getZ() ) ); - return result; -} - -inline float lengthSqr( const Vector3 & vec ) -{ - float result; - result = ( vec.getX() * vec.getX() ); - result = ( result + ( vec.getY() * vec.getY() ) ); - result = ( result + ( vec.getZ() * vec.getZ() ) ); - return result; -} - -inline float length( const Vector3 & vec ) -{ - return ::sqrtf( lengthSqr( vec ) ); -} - -inline const Vector3 normalize( const Vector3 & vec ) -{ - float lenSqr, lenInv; - lenSqr = lengthSqr( vec ); - lenInv = ( 1.0f / sqrtf( lenSqr ) ); - return Vector3( - ( vec.getX() * lenInv ), - ( vec.getY() * lenInv ), - ( vec.getZ() * lenInv ) - ); -} - -inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), - ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), - ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) - ); -} - -inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) -{ - return Vector3( - ( select1 )? vec1.getX() : vec0.getX(), - ( select1 )? vec1.getY() : vec0.getY(), - ( select1 )? vec1.getZ() : vec0.getZ() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Vector3 & vec ) -{ - printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); -} - -inline void print( const Vector3 & vec, const char * name ) -{ - printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); -} - -#endif - -inline Vector4::Vector4( const Vector4 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; - mW = vec.mW; -} - -inline Vector4::Vector4( float _x, float _y, float _z, float _w ) -{ - mX = _x; - mY = _y; - mZ = _z; - mW = _w; -} - -inline Vector4::Vector4( const Vector3 & xyz, float _w ) -{ - this->setXYZ( xyz ); - this->setW( _w ); -} - -inline Vector4::Vector4( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); - mW = 0.0f; -} - -inline Vector4::Vector4( const Point3 & pnt ) -{ - mX = pnt.getX(); - mY = pnt.getY(); - mZ = pnt.getZ(); - mW = 1.0f; -} - -inline Vector4::Vector4( const Quat & quat ) -{ - mX = quat.getX(); - mY = quat.getY(); - mZ = quat.getZ(); - mW = quat.getW(); -} - -inline Vector4::Vector4( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; - mW = scalar; -} - -inline const Vector4 Vector4::xAxis( ) -{ - return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); -} - -inline const Vector4 Vector4::yAxis( ) -{ - return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); -} - -inline const Vector4 Vector4::zAxis( ) -{ - return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); -} - -inline const Vector4 Vector4::wAxis( ) -{ - return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); -} - -inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) -{ - return ( vec0 + ( ( vec1 - vec0 ) * t ) ); -} - -inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) -{ - float recipSinAngle, scale0, scale1, cosAngle, angle; - cosAngle = dot( unitVec0, unitVec1 ); - if ( cosAngle < _VECTORMATH_SLERP_TOL ) { - angle = acosf( cosAngle ); - recipSinAngle = ( 1.0f / sinf( angle ) ); - scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); - scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); - } else { - scale0 = ( 1.0f - t ); - scale1 = t; - } - return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); -} - -inline void loadXYZW( Vector4 & vec, const float * fptr ) -{ - vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); -} - -inline void storeXYZW( const Vector4 & vec, float * fptr ) -{ - fptr[0] = vec.getX(); - fptr[1] = vec.getY(); - fptr[2] = vec.getZ(); - fptr[3] = vec.getW(); -} - -inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 4; i++) { - unsigned short fp16 = hfptr[i]; - unsigned int sign = fp16 >> 15; - unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); - unsigned int mantissa = fp16 & ((1 << 10) - 1); - - if (exponent == 0) { - // zero - mantissa = 0; - - } else if (exponent == 31) { - // infinity or nan -> infinity - exponent = 255; - mantissa = 0; - - } else { - exponent += 127 - 15; - mantissa <<= 13; - } - - Data32 d; - d.u32 = (sign << 31) | (exponent << 23) | mantissa; - vec[i] = d.f32; - } -} - -inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 4; i++) { - Data32 d; - d.f32 = vec[i]; - - unsigned int sign = d.u32 >> 31; - unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); - unsigned int mantissa = d.u32 & ((1 << 23) - 1);; - - if (exponent == 0) { - // zero or denorm -> zero - mantissa = 0; - - } else if (exponent == 255 && mantissa != 0) { - // nan -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent >= 127 - 15 + 31) { - // overflow or infinity -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent <= 127 - 15) { - // underflow -> zero - exponent = 0; - mantissa = 0; - - } else { - exponent -= 127 - 15; - mantissa >>= 13; - } - - hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); - } -} - -inline Vector4 & Vector4::operator =( const Vector4 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; - mW = vec.mW; - return *this; -} - -inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); - return *this; -} - -inline const Vector3 Vector4::getXYZ( ) const -{ - return Vector3( mX, mY, mZ ); -} - -inline Vector4 & Vector4::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Vector4::getX( ) const -{ - return mX; -} - -inline Vector4 & Vector4::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Vector4::getY( ) const -{ - return mY; -} - -inline Vector4 & Vector4::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Vector4::getZ( ) const -{ - return mZ; -} - -inline Vector4 & Vector4::setW( float _w ) -{ - mW = _w; - return *this; -} - -inline float Vector4::getW( ) const -{ - return mW; -} - -inline Vector4 & Vector4::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Vector4::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Vector4::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Vector4::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Vector4 Vector4::operator +( const Vector4 & vec ) const -{ - return Vector4( - ( mX + vec.mX ), - ( mY + vec.mY ), - ( mZ + vec.mZ ), - ( mW + vec.mW ) - ); -} - -inline const Vector4 Vector4::operator -( const Vector4 & vec ) const -{ - return Vector4( - ( mX - vec.mX ), - ( mY - vec.mY ), - ( mZ - vec.mZ ), - ( mW - vec.mW ) - ); -} - -inline const Vector4 Vector4::operator *( float scalar ) const -{ - return Vector4( - ( mX * scalar ), - ( mY * scalar ), - ( mZ * scalar ), - ( mW * scalar ) - ); -} - -inline Vector4 & Vector4::operator +=( const Vector4 & vec ) -{ - *this = *this + vec; - return *this; -} - -inline Vector4 & Vector4::operator -=( const Vector4 & vec ) -{ - *this = *this - vec; - return *this; -} - -inline Vector4 & Vector4::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Vector4 Vector4::operator /( float scalar ) const -{ - return Vector4( - ( mX / scalar ), - ( mY / scalar ), - ( mZ / scalar ), - ( mW / scalar ) - ); -} - -inline Vector4 & Vector4::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -inline const Vector4 Vector4::operator -( ) const -{ - return Vector4( - -mX, - -mY, - -mZ, - -mW - ); -} - -inline const Vector4 operator *( float scalar, const Vector4 & vec ) -{ - return vec * scalar; -} - -inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - ( vec0.getX() * vec1.getX() ), - ( vec0.getY() * vec1.getY() ), - ( vec0.getZ() * vec1.getZ() ), - ( vec0.getW() * vec1.getW() ) - ); -} - -inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - ( vec0.getX() / vec1.getX() ), - ( vec0.getY() / vec1.getY() ), - ( vec0.getZ() / vec1.getZ() ), - ( vec0.getW() / vec1.getW() ) - ); -} - -inline const Vector4 recipPerElem( const Vector4 & vec ) -{ - return Vector4( - ( 1.0f / vec.getX() ), - ( 1.0f / vec.getY() ), - ( 1.0f / vec.getZ() ), - ( 1.0f / vec.getW() ) - ); -} - -inline const Vector4 sqrtPerElem( const Vector4 & vec ) -{ - return Vector4( - sqrtf( vec.getX() ), - sqrtf( vec.getY() ), - sqrtf( vec.getZ() ), - sqrtf( vec.getW() ) - ); -} - -inline const Vector4 rsqrtPerElem( const Vector4 & vec ) -{ - return Vector4( - ( 1.0f / sqrtf( vec.getX() ) ), - ( 1.0f / sqrtf( vec.getY() ) ), - ( 1.0f / sqrtf( vec.getZ() ) ), - ( 1.0f / sqrtf( vec.getW() ) ) - ); -} - -inline const Vector4 absPerElem( const Vector4 & vec ) -{ - return Vector4( - fabsf( vec.getX() ), - fabsf( vec.getY() ), - fabsf( vec.getZ() ), - fabsf( vec.getW() ) - ); -} - -inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), - ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), - ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), - ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) - ); -} - -inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), - (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() - ); -} - -inline float maxElem( const Vector4 & vec ) -{ - float result; - result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() > result)? vec.getZ() : result; - result = (vec.getW() > result)? vec.getW() : result; - return result; -} - -inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), - (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() - ); -} - -inline float minElem( const Vector4 & vec ) -{ - float result; - result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() < result)? vec.getZ() : result; - result = (vec.getW() < result)? vec.getW() : result; - return result; -} - -inline float sum( const Vector4 & vec ) -{ - float result; - result = ( vec.getX() + vec.getY() ); - result = ( result + vec.getZ() ); - result = ( result + vec.getW() ); - return result; -} - -inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) -{ - float result; - result = ( vec0.getX() * vec1.getX() ); - result = ( result + ( vec0.getY() * vec1.getY() ) ); - result = ( result + ( vec0.getZ() * vec1.getZ() ) ); - result = ( result + ( vec0.getW() * vec1.getW() ) ); - return result; -} - -inline float lengthSqr( const Vector4 & vec ) -{ - float result; - result = ( vec.getX() * vec.getX() ); - result = ( result + ( vec.getY() * vec.getY() ) ); - result = ( result + ( vec.getZ() * vec.getZ() ) ); - result = ( result + ( vec.getW() * vec.getW() ) ); - return result; -} - -inline float length( const Vector4 & vec ) -{ - return ::sqrtf( lengthSqr( vec ) ); -} - -inline const Vector4 normalize( const Vector4 & vec ) -{ - float lenSqr, lenInv; - lenSqr = lengthSqr( vec ); - lenInv = ( 1.0f / sqrtf( lenSqr ) ); - return Vector4( - ( vec.getX() * lenInv ), - ( vec.getY() * lenInv ), - ( vec.getZ() * lenInv ), - ( vec.getW() * lenInv ) - ); -} - -inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) -{ - return Vector4( - ( select1 )? vec1.getX() : vec0.getX(), - ( select1 )? vec1.getY() : vec0.getY(), - ( select1 )? vec1.getZ() : vec0.getZ(), - ( select1 )? vec1.getW() : vec0.getW() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Vector4 & vec ) -{ - printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); -} - -inline void print( const Vector4 & vec, const char * name ) -{ - printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); -} - -#endif - -inline Point3::Point3( const Point3 & pnt ) -{ - mX = pnt.mX; - mY = pnt.mY; - mZ = pnt.mZ; -} - -inline Point3::Point3( float _x, float _y, float _z ) -{ - mX = _x; - mY = _y; - mZ = _z; -} - -inline Point3::Point3( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); -} - -inline Point3::Point3( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; -} - -inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) -{ - return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); -} - -inline void loadXYZ( Point3 & pnt, const float * fptr ) -{ - pnt = Point3( fptr[0], fptr[1], fptr[2] ); -} - -inline void storeXYZ( const Point3 & pnt, float * fptr ) -{ - fptr[0] = pnt.getX(); - fptr[1] = pnt.getY(); - fptr[2] = pnt.getZ(); -} - -inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - unsigned short fp16 = hfptr[i]; - unsigned int sign = fp16 >> 15; - unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); - unsigned int mantissa = fp16 & ((1 << 10) - 1); - - if (exponent == 0) { - // zero - mantissa = 0; - - } else if (exponent == 31) { - // infinity or nan -> infinity - exponent = 255; - mantissa = 0; - - } else { - exponent += 127 - 15; - mantissa <<= 13; - } - - Data32 d; - d.u32 = (sign << 31) | (exponent << 23) | mantissa; - vec[i] = d.f32; - } -} - -inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - Data32 d; - d.f32 = vec[i]; - - unsigned int sign = d.u32 >> 31; - unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); - unsigned int mantissa = d.u32 & ((1 << 23) - 1);; - - if (exponent == 0) { - // zero or denorm -> zero - mantissa = 0; - - } else if (exponent == 255 && mantissa != 0) { - // nan -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent >= 127 - 15 + 31) { - // overflow or infinity -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent <= 127 - 15) { - // underflow -> zero - exponent = 0; - mantissa = 0; - - } else { - exponent -= 127 - 15; - mantissa >>= 13; - } - - hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); - } -} - -inline Point3 & Point3::operator =( const Point3 & pnt ) -{ - mX = pnt.mX; - mY = pnt.mY; - mZ = pnt.mZ; - return *this; -} - -inline Point3 & Point3::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Point3::getX( ) const -{ - return mX; -} - -inline Point3 & Point3::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Point3::getY( ) const -{ - return mY; -} - -inline Point3 & Point3::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Point3::getZ( ) const -{ - return mZ; -} - -inline Point3 & Point3::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Point3::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Point3::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Point3::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Vector3 Point3::operator -( const Point3 & pnt ) const -{ - return Vector3( - ( mX - pnt.mX ), - ( mY - pnt.mY ), - ( mZ - pnt.mZ ) - ); -} - -inline const Point3 Point3::operator +( const Vector3 & vec ) const -{ - return Point3( - ( mX + vec.getX() ), - ( mY + vec.getY() ), - ( mZ + vec.getZ() ) - ); -} - -inline const Point3 Point3::operator -( const Vector3 & vec ) const -{ - return Point3( - ( mX - vec.getX() ), - ( mY - vec.getY() ), - ( mZ - vec.getZ() ) - ); -} - -inline Point3 & Point3::operator +=( const Vector3 & vec ) -{ - *this = *this + vec; - return *this; -} - -inline Point3 & Point3::operator -=( const Vector3 & vec ) -{ - *this = *this - vec; - return *this; -} - -inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - ( pnt0.getX() * pnt1.getX() ), - ( pnt0.getY() * pnt1.getY() ), - ( pnt0.getZ() * pnt1.getZ() ) - ); -} - -inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - ( pnt0.getX() / pnt1.getX() ), - ( pnt0.getY() / pnt1.getY() ), - ( pnt0.getZ() / pnt1.getZ() ) - ); -} - -inline const Point3 recipPerElem( const Point3 & pnt ) -{ - return Point3( - ( 1.0f / pnt.getX() ), - ( 1.0f / pnt.getY() ), - ( 1.0f / pnt.getZ() ) - ); -} - -inline const Point3 sqrtPerElem( const Point3 & pnt ) -{ - return Point3( - sqrtf( pnt.getX() ), - sqrtf( pnt.getY() ), - sqrtf( pnt.getZ() ) - ); -} - -inline const Point3 rsqrtPerElem( const Point3 & pnt ) -{ - return Point3( - ( 1.0f / sqrtf( pnt.getX() ) ), - ( 1.0f / sqrtf( pnt.getY() ) ), - ( 1.0f / sqrtf( pnt.getZ() ) ) - ); -} - -inline const Point3 absPerElem( const Point3 & pnt ) -{ - return Point3( - fabsf( pnt.getX() ), - fabsf( pnt.getY() ), - fabsf( pnt.getZ() ) - ); -} - -inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), - ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), - ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) - ); -} - -inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), - (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), - (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() - ); -} - -inline float maxElem( const Point3 & pnt ) -{ - float result; - result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); - result = (pnt.getZ() > result)? pnt.getZ() : result; - return result; -} - -inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), - (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), - (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() - ); -} - -inline float minElem( const Point3 & pnt ) -{ - float result; - result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); - result = (pnt.getZ() < result)? pnt.getZ() : result; - return result; -} - -inline float sum( const Point3 & pnt ) -{ - float result; - result = ( pnt.getX() + pnt.getY() ); - result = ( result + pnt.getZ() ); - return result; -} - -inline const Point3 scale( const Point3 & pnt, float scaleVal ) -{ - return mulPerElem( pnt, Point3( scaleVal ) ); -} - -inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) -{ - return mulPerElem( pnt, Point3( scaleVec ) ); -} - -inline float projection( const Point3 & pnt, const Vector3 & unitVec ) -{ - float result; - result = ( pnt.getX() * unitVec.getX() ); - result = ( result + ( pnt.getY() * unitVec.getY() ) ); - result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); - return result; -} - -inline float distSqrFromOrigin( const Point3 & pnt ) -{ - return lengthSqr( Vector3( pnt ) ); -} - -inline float distFromOrigin( const Point3 & pnt ) -{ - return length( Vector3( pnt ) ); -} - -inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return lengthSqr( ( pnt1 - pnt0 ) ); -} - -inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return length( ( pnt1 - pnt0 ) ); -} - -inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) -{ - return Point3( - ( select1 )? pnt1.getX() : pnt0.getX(), - ( select1 )? pnt1.getY() : pnt0.getY(), - ( select1 )? pnt1.getZ() : pnt0.getZ() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Point3 & pnt ) -{ - printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); -} - -inline void print( const Point3 & pnt, const char * name ) -{ - printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); -} - -#endif - -} // namespace Aos -} // namespace Vectormath - -#endif - diff --git a/Code/Physics/Bullet Source/src/vectormath/neon/vectormath_aos.h b/Code/Physics/Bullet Source/src/vectormath/neon/vectormath_aos.h deleted file mode 100644 index 97bdc278..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/neon/vectormath_aos.h +++ /dev/null @@ -1,1890 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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. - -This source version has been altered. - -*/ - -#ifndef _VECTORMATH_AOS_CPP_H -#define _VECTORMATH_AOS_CPP_H - -#include - -#ifdef _VECTORMATH_DEBUG -#include -#endif - -namespace Vectormath { - -namespace Aos { - -//----------------------------------------------------------------------------- -// Forward Declarations -// - -class Vector3; -class Vector4; -class Point3; -class Quat; -class Matrix3; -class Matrix4; -class Transform3; - -// A 3-D vector in array-of-structures format -// -class Vector3 -{ - float mX; - float mY; - float mZ; -#ifndef __GNUC__ - float d; -#endif - -public: - // Default constructor; does no initialization - // - inline Vector3( ) { }; - - // Copy a 3-D vector - // - inline Vector3( const Vector3 & vec ); - - // Construct a 3-D vector from x, y, and z elements - // - inline Vector3( float x, float y, float z ); - - // Copy elements from a 3-D point into a 3-D vector - // - explicit inline Vector3( const Point3 & pnt ); - - // Set all elements of a 3-D vector to the same scalar value - // - explicit inline Vector3( float scalar ); - - // Assign one 3-D vector to another - // - inline Vector3 & operator =( const Vector3 & vec ); - - // Set the x element of a 3-D vector - // - inline Vector3 & setX( float x ); - - // Set the y element of a 3-D vector - // - inline Vector3 & setY( float y ); - - // Set the z element of a 3-D vector - // - inline Vector3 & setZ( float z ); - - // Get the x element of a 3-D vector - // - inline float getX( ) const; - - // Get the y element of a 3-D vector - // - inline float getY( ) const; - - // Get the z element of a 3-D vector - // - inline float getZ( ) const; - - // Set an x, y, or z element of a 3-D vector by index - // - inline Vector3 & setElem( int idx, float value ); - - // Get an x, y, or z element of a 3-D vector by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Add two 3-D vectors - // - inline const Vector3 operator +( const Vector3 & vec ) const; - - // Subtract a 3-D vector from another 3-D vector - // - inline const Vector3 operator -( const Vector3 & vec ) const; - - // Add a 3-D vector to a 3-D point - // - inline const Point3 operator +( const Point3 & pnt ) const; - - // Multiply a 3-D vector by a scalar - // - inline const Vector3 operator *( float scalar ) const; - - // Divide a 3-D vector by a scalar - // - inline const Vector3 operator /( float scalar ) const; - - // Perform compound assignment and addition with a 3-D vector - // - inline Vector3 & operator +=( const Vector3 & vec ); - - // Perform compound assignment and subtraction by a 3-D vector - // - inline Vector3 & operator -=( const Vector3 & vec ); - - // Perform compound assignment and multiplication by a scalar - // - inline Vector3 & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - inline Vector3 & operator /=( float scalar ); - - // Negate all elements of a 3-D vector - // - inline const Vector3 operator -( ) const; - - // Construct x axis - // - static inline const Vector3 xAxis( ); - - // Construct y axis - // - static inline const Vector3 yAxis( ); - - // Construct z axis - // - static inline const Vector3 zAxis( ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply a 3-D vector by a scalar -// -inline const Vector3 operator *( float scalar, const Vector3 & vec ); - -// Multiply two 3-D vectors per element -// -inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Divide two 3-D vectors per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Compute the reciprocal of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -inline const Vector3 recipPerElem( const Vector3 & vec ); - -// Compute the square root of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function sqrtf4. -// -inline const Vector3 sqrtPerElem( const Vector3 & vec ); - -// Compute the reciprocal square root of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function rsqrtf4. -// -inline const Vector3 rsqrtPerElem( const Vector3 & vec ); - -// Compute the absolute value of a 3-D vector per element -// -inline const Vector3 absPerElem( const Vector3 & vec ); - -// Copy sign from one 3-D vector to another, per element -// -inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Maximum of two 3-D vectors per element -// -inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Minimum of two 3-D vectors per element -// -inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Maximum element of a 3-D vector -// -inline float maxElem( const Vector3 & vec ); - -// Minimum element of a 3-D vector -// -inline float minElem( const Vector3 & vec ); - -// Compute the sum of all elements of a 3-D vector -// -inline float sum( const Vector3 & vec ); - -// Compute the dot product of two 3-D vectors -// -inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); - -// Compute the square of the length of a 3-D vector -// -inline float lengthSqr( const Vector3 & vec ); - -// Compute the length of a 3-D vector -// -inline float length( const Vector3 & vec ); - -// Normalize a 3-D vector -// NOTE: -// The result is unpredictable when all elements of vec are at or near zero. -// -inline const Vector3 normalize( const Vector3 & vec ); - -// Compute cross product of two 3-D vectors -// -inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); - -// Outer product of two 3-D vectors -// -inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); - -// Pre-multiply a row vector by a 3x3 matrix -// -inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); - -// Cross-product matrix of a 3-D vector -// -inline const Matrix3 crossMatrix( const Vector3 & vec ); - -// Create cross-product matrix and multiply -// NOTE: -// Faster than separately creating a cross-product matrix and multiplying. -// -inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); - -// Linear interpolation between two 3-D vectors -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); - -// Spherical linear interpolation between two 3-D vectors -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); - -// Conditionally select between two 3-D vectors -// -inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); - -// Load x, y, and z elements from the first three words of a float array. -// -// -inline void loadXYZ( Vector3 & vec, const float * fptr ); - -// Store x, y, and z elements of a 3-D vector in the first three words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZ( const Vector3 & vec, float * fptr ); - -// Load three-half-floats as a 3-D vector -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. -// -inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); - -// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// -inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3-D vector -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector3 & vec ); - -// Print a 3-D vector and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector3 & vec, const char * name ); - -#endif - -// A 4-D vector in array-of-structures format -// -class Vector4 -{ - float mX; - float mY; - float mZ; - float mW; - -public: - // Default constructor; does no initialization - // - inline Vector4( ) { }; - - // Copy a 4-D vector - // - inline Vector4( const Vector4 & vec ); - - // Construct a 4-D vector from x, y, z, and w elements - // - inline Vector4( float x, float y, float z, float w ); - - // Construct a 4-D vector from a 3-D vector and a scalar - // - inline Vector4( const Vector3 & xyz, float w ); - - // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 - // - explicit inline Vector4( const Vector3 & vec ); - - // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 - // - explicit inline Vector4( const Point3 & pnt ); - - // Copy elements from a quaternion into a 4-D vector - // - explicit inline Vector4( const Quat & quat ); - - // Set all elements of a 4-D vector to the same scalar value - // - explicit inline Vector4( float scalar ); - - // Assign one 4-D vector to another - // - inline Vector4 & operator =( const Vector4 & vec ); - - // Set the x, y, and z elements of a 4-D vector - // NOTE: - // This function does not change the w element. - // - inline Vector4 & setXYZ( const Vector3 & vec ); - - // Get the x, y, and z elements of a 4-D vector - // - inline const Vector3 getXYZ( ) const; - - // Set the x element of a 4-D vector - // - inline Vector4 & setX( float x ); - - // Set the y element of a 4-D vector - // - inline Vector4 & setY( float y ); - - // Set the z element of a 4-D vector - // - inline Vector4 & setZ( float z ); - - // Set the w element of a 4-D vector - // - inline Vector4 & setW( float w ); - - // Get the x element of a 4-D vector - // - inline float getX( ) const; - - // Get the y element of a 4-D vector - // - inline float getY( ) const; - - // Get the z element of a 4-D vector - // - inline float getZ( ) const; - - // Get the w element of a 4-D vector - // - inline float getW( ) const; - - // Set an x, y, z, or w element of a 4-D vector by index - // - inline Vector4 & setElem( int idx, float value ); - - // Get an x, y, z, or w element of a 4-D vector by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Add two 4-D vectors - // - inline const Vector4 operator +( const Vector4 & vec ) const; - - // Subtract a 4-D vector from another 4-D vector - // - inline const Vector4 operator -( const Vector4 & vec ) const; - - // Multiply a 4-D vector by a scalar - // - inline const Vector4 operator *( float scalar ) const; - - // Divide a 4-D vector by a scalar - // - inline const Vector4 operator /( float scalar ) const; - - // Perform compound assignment and addition with a 4-D vector - // - inline Vector4 & operator +=( const Vector4 & vec ); - - // Perform compound assignment and subtraction by a 4-D vector - // - inline Vector4 & operator -=( const Vector4 & vec ); - - // Perform compound assignment and multiplication by a scalar - // - inline Vector4 & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - inline Vector4 & operator /=( float scalar ); - - // Negate all elements of a 4-D vector - // - inline const Vector4 operator -( ) const; - - // Construct x axis - // - static inline const Vector4 xAxis( ); - - // Construct y axis - // - static inline const Vector4 yAxis( ); - - // Construct z axis - // - static inline const Vector4 zAxis( ); - - // Construct w axis - // - static inline const Vector4 wAxis( ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply a 4-D vector by a scalar -// -inline const Vector4 operator *( float scalar, const Vector4 & vec ); - -// Multiply two 4-D vectors per element -// -inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Divide two 4-D vectors per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Compute the reciprocal of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -inline const Vector4 recipPerElem( const Vector4 & vec ); - -// Compute the square root of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function sqrtf4. -// -inline const Vector4 sqrtPerElem( const Vector4 & vec ); - -// Compute the reciprocal square root of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function rsqrtf4. -// -inline const Vector4 rsqrtPerElem( const Vector4 & vec ); - -// Compute the absolute value of a 4-D vector per element -// -inline const Vector4 absPerElem( const Vector4 & vec ); - -// Copy sign from one 4-D vector to another, per element -// -inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Maximum of two 4-D vectors per element -// -inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Minimum of two 4-D vectors per element -// -inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Maximum element of a 4-D vector -// -inline float maxElem( const Vector4 & vec ); - -// Minimum element of a 4-D vector -// -inline float minElem( const Vector4 & vec ); - -// Compute the sum of all elements of a 4-D vector -// -inline float sum( const Vector4 & vec ); - -// Compute the dot product of two 4-D vectors -// -inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); - -// Compute the square of the length of a 4-D vector -// -inline float lengthSqr( const Vector4 & vec ); - -// Compute the length of a 4-D vector -// -inline float length( const Vector4 & vec ); - -// Normalize a 4-D vector -// NOTE: -// The result is unpredictable when all elements of vec are at or near zero. -// -inline const Vector4 normalize( const Vector4 & vec ); - -// Outer product of two 4-D vectors -// -inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); - -// Linear interpolation between two 4-D vectors -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); - -// Spherical linear interpolation between two 4-D vectors -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); - -// Conditionally select between two 4-D vectors -// -inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); - -// Load x, y, z, and w elements from the first four words of a float array. -// -// -inline void loadXYZW( Vector4 & vec, const float * fptr ); - -// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZW( const Vector4 & vec, float * fptr ); - -// Load four-half-floats as a 4-D vector -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. -// -inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); - -// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// -inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 4-D vector -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector4 & vec ); - -// Print a 4-D vector and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector4 & vec, const char * name ); - -#endif - -// A 3-D point in array-of-structures format -// -class Point3 -{ - float mX; - float mY; - float mZ; -#ifndef __GNUC__ - float d; -#endif - -public: - // Default constructor; does no initialization - // - inline Point3( ) { }; - - // Copy a 3-D point - // - inline Point3( const Point3 & pnt ); - - // Construct a 3-D point from x, y, and z elements - // - inline Point3( float x, float y, float z ); - - // Copy elements from a 3-D vector into a 3-D point - // - explicit inline Point3( const Vector3 & vec ); - - // Set all elements of a 3-D point to the same scalar value - // - explicit inline Point3( float scalar ); - - // Assign one 3-D point to another - // - inline Point3 & operator =( const Point3 & pnt ); - - // Set the x element of a 3-D point - // - inline Point3 & setX( float x ); - - // Set the y element of a 3-D point - // - inline Point3 & setY( float y ); - - // Set the z element of a 3-D point - // - inline Point3 & setZ( float z ); - - // Get the x element of a 3-D point - // - inline float getX( ) const; - - // Get the y element of a 3-D point - // - inline float getY( ) const; - - // Get the z element of a 3-D point - // - inline float getZ( ) const; - - // Set an x, y, or z element of a 3-D point by index - // - inline Point3 & setElem( int idx, float value ); - - // Get an x, y, or z element of a 3-D point by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Subtract a 3-D point from another 3-D point - // - inline const Vector3 operator -( const Point3 & pnt ) const; - - // Add a 3-D point to a 3-D vector - // - inline const Point3 operator +( const Vector3 & vec ) const; - - // Subtract a 3-D vector from a 3-D point - // - inline const Point3 operator -( const Vector3 & vec ) const; - - // Perform compound assignment and addition with a 3-D vector - // - inline Point3 & operator +=( const Vector3 & vec ); - - // Perform compound assignment and subtraction by a 3-D vector - // - inline Point3 & operator -=( const Vector3 & vec ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply two 3-D points per element -// -inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Divide two 3-D points per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Compute the reciprocal of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -inline const Point3 recipPerElem( const Point3 & pnt ); - -// Compute the square root of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function sqrtf4. -// -inline const Point3 sqrtPerElem( const Point3 & pnt ); - -// Compute the reciprocal square root of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function rsqrtf4. -// -inline const Point3 rsqrtPerElem( const Point3 & pnt ); - -// Compute the absolute value of a 3-D point per element -// -inline const Point3 absPerElem( const Point3 & pnt ); - -// Copy sign from one 3-D point to another, per element -// -inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Maximum of two 3-D points per element -// -inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Minimum of two 3-D points per element -// -inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Maximum element of a 3-D point -// -inline float maxElem( const Point3 & pnt ); - -// Minimum element of a 3-D point -// -inline float minElem( const Point3 & pnt ); - -// Compute the sum of all elements of a 3-D point -// -inline float sum( const Point3 & pnt ); - -// Apply uniform scale to a 3-D point -// -inline const Point3 scale( const Point3 & pnt, float scaleVal ); - -// Apply non-uniform scale to a 3-D point -// -inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); - -// Scalar projection of a 3-D point on a unit-length 3-D vector -// -inline float projection( const Point3 & pnt, const Vector3 & unitVec ); - -// Compute the square of the distance of a 3-D point from the coordinate-system origin -// -inline float distSqrFromOrigin( const Point3 & pnt ); - -// Compute the distance of a 3-D point from the coordinate-system origin -// -inline float distFromOrigin( const Point3 & pnt ); - -// Compute the square of the distance between two 3-D points -// -inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); - -// Compute the distance between two 3-D points -// -inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); - -// Linear interpolation between two 3-D points -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); - -// Conditionally select between two 3-D points -// -inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); - -// Load x, y, and z elements from the first three words of a float array. -// -// -inline void loadXYZ( Point3 & pnt, const float * fptr ); - -// Store x, y, and z elements of a 3-D point in the first three words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZ( const Point3 & pnt, float * fptr ); - -// Load three-half-floats as a 3-D point -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. -// -inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); - -// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// -inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3-D point -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Point3 & pnt ); - -// Print a 3-D point and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Point3 & pnt, const char * name ); - -#endif - -// A quaternion in array-of-structures format -// -class Quat -{ -#if defined( __APPLE__ ) && defined( BT_USE_NEON ) - union{ - float32x4_t vXYZW; - float mXYZW[4]; - }; -#else - float mX; - float mY; - float mZ; - float mW; -#endif - -public: - // Default constructor; does no initialization - // - inline Quat( ) { }; - - // Copy a quaternion - // - inline Quat( const Quat & quat ); - - // Construct a quaternion from x, y, z, and w elements - // - inline Quat( float x, float y, float z, float w ); - - // Construct a quaternion from vector of x, y, z, and w elements - // - inline Quat( float32x4_t fXYZW ); - - // Construct a quaternion from a 3-D vector and a scalar - // - inline Quat( const Vector3 & xyz, float w ); - - // Copy elements from a 4-D vector into a quaternion - // - explicit inline Quat( const Vector4 & vec ); - - // Convert a rotation matrix to a unit-length quaternion - // - explicit inline Quat( const Matrix3 & rotMat ); - - // Set all elements of a quaternion to the same scalar value - // - explicit inline Quat( float scalar ); - - // Assign one quaternion to another - // - inline Quat & operator =( const Quat & quat ); - - // Set the x, y, and z elements of a quaternion - // NOTE: - // This function does not change the w element. - // - inline Quat & setXYZ( const Vector3 & vec ); - - // Get the x, y, and z elements of a quaternion - // - inline const Vector3 getXYZ( ) const; - - // Set the x element of a quaternion - // - inline Quat & setX( float x ); - - // Set the y element of a quaternion - // - inline Quat & setY( float y ); - - // Set the z element of a quaternion - // - inline Quat & setZ( float z ); - - // Set the w element of a quaternion - // - inline Quat & setW( float w ); - -#if defined( __APPLE__ ) && defined( BT_USE_NEON ) - inline float32x4_t getvXYZW( ) const; -#endif - - // Get the x element of a quaternion - // - inline float getX( ) const; - - // Get the y element of a quaternion - // - inline float getY( ) const; - - // Get the z element of a quaternion - // - inline float getZ( ) const; - - // Get the w element of a quaternion - // - inline float getW( ) const; - - // Set an x, y, z, or w element of a quaternion by index - // - inline Quat & setElem( int idx, float value ); - - // Get an x, y, z, or w element of a quaternion by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Add two quaternions - // - inline const Quat operator +( const Quat & quat ) const; - - // Subtract a quaternion from another quaternion - // - inline const Quat operator -( const Quat & quat ) const; - - // Multiply two quaternions - // - inline const Quat operator *( const Quat & quat ) const; - - // Multiply a quaternion by a scalar - // - inline const Quat operator *( float scalar ) const; - - // Divide a quaternion by a scalar - // - inline const Quat operator /( float scalar ) const; - - // Perform compound assignment and addition with a quaternion - // - inline Quat & operator +=( const Quat & quat ); - - // Perform compound assignment and subtraction by a quaternion - // - inline Quat & operator -=( const Quat & quat ); - - // Perform compound assignment and multiplication by a quaternion - // - inline Quat & operator *=( const Quat & quat ); - - // Perform compound assignment and multiplication by a scalar - // - inline Quat & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - inline Quat & operator /=( float scalar ); - - // Negate all elements of a quaternion - // - inline const Quat operator -( ) const; - - // Construct an identity quaternion - // - static inline const Quat identity( ); - - // Construct a quaternion to rotate between two unit-length 3-D vectors - // NOTE: - // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. - // - static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); - - // Construct a quaternion to rotate around a unit-length 3-D vector - // - static inline const Quat rotation( float radians, const Vector3 & unitVec ); - - // Construct a quaternion to rotate around the x axis - // - static inline const Quat rotationX( float radians ); - - // Construct a quaternion to rotate around the y axis - // - static inline const Quat rotationY( float radians ); - - // Construct a quaternion to rotate around the z axis - // - static inline const Quat rotationZ( float radians ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply a quaternion by a scalar -// -inline const Quat operator *( float scalar, const Quat & quat ); - -// Compute the conjugate of a quaternion -// -inline const Quat conj( const Quat & quat ); - -// Use a unit-length quaternion to rotate a 3-D vector -// -inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); - -// Compute the dot product of two quaternions -// -inline float dot( const Quat & quat0, const Quat & quat1 ); - -// Compute the norm of a quaternion -// -inline float norm( const Quat & quat ); - -// Compute the length of a quaternion -// -inline float length( const Quat & quat ); - -// Normalize a quaternion -// NOTE: -// The result is unpredictable when all elements of quat are at or near zero. -// -inline const Quat normalize( const Quat & quat ); - -// Linear interpolation between two quaternions -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); - -// Spherical linear interpolation between two quaternions -// NOTE: -// Interpolates along the shortest path between orientations. -// Does not clamp t between 0 and 1. -// -inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); - -// Spherical quadrangle interpolation -// -inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); - -// Conditionally select between two quaternions -// -inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); - -// Load x, y, z, and w elements from the first four words of a float array. -// -// -inline void loadXYZW( Quat & quat, const float * fptr ); - -// Store x, y, z, and w elements of a quaternion in the first four words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZW( const Quat & quat, float * fptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a quaternion -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Quat & quat ); - -// Print a quaternion and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Quat & quat, const char * name ); - -#endif - -// A 3x3 matrix in array-of-structures format -// -class Matrix3 -{ - Vector3 mCol0; - Vector3 mCol1; - Vector3 mCol2; - -public: - // Default constructor; does no initialization - // - inline Matrix3( ) { }; - - // Copy a 3x3 matrix - // - inline Matrix3( const Matrix3 & mat ); - - // Construct a 3x3 matrix containing the specified columns - // - inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); - - // Construct a 3x3 rotation matrix from a unit-length quaternion - // - explicit inline Matrix3( const Quat & unitQuat ); - - // Set all elements of a 3x3 matrix to the same scalar value - // - explicit inline Matrix3( float scalar ); - - // Assign one 3x3 matrix to another - // - inline Matrix3 & operator =( const Matrix3 & mat ); - - // Set column 0 of a 3x3 matrix - // - inline Matrix3 & setCol0( const Vector3 & col0 ); - - // Set column 1 of a 3x3 matrix - // - inline Matrix3 & setCol1( const Vector3 & col1 ); - - // Set column 2 of a 3x3 matrix - // - inline Matrix3 & setCol2( const Vector3 & col2 ); - - // Get column 0 of a 3x3 matrix - // - inline const Vector3 getCol0( ) const; - - // Get column 1 of a 3x3 matrix - // - inline const Vector3 getCol1( ) const; - - // Get column 2 of a 3x3 matrix - // - inline const Vector3 getCol2( ) const; - - // Set the column of a 3x3 matrix referred to by the specified index - // - inline Matrix3 & setCol( int col, const Vector3 & vec ); - - // Set the row of a 3x3 matrix referred to by the specified index - // - inline Matrix3 & setRow( int row, const Vector3 & vec ); - - // Get the column of a 3x3 matrix referred to by the specified index - // - inline const Vector3 getCol( int col ) const; - - // Get the row of a 3x3 matrix referred to by the specified index - // - inline const Vector3 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - inline Vector3 & operator []( int col ); - - // Subscripting operator to get a column - // - inline const Vector3 operator []( int col ) const; - - // Set the element of a 3x3 matrix referred to by column and row indices - // - inline Matrix3 & setElem( int col, int row, float val ); - - // Get the element of a 3x3 matrix referred to by column and row indices - // - inline float getElem( int col, int row ) const; - - // Add two 3x3 matrices - // - inline const Matrix3 operator +( const Matrix3 & mat ) const; - - // Subtract a 3x3 matrix from another 3x3 matrix - // - inline const Matrix3 operator -( const Matrix3 & mat ) const; - - // Negate all elements of a 3x3 matrix - // - inline const Matrix3 operator -( ) const; - - // Multiply a 3x3 matrix by a scalar - // - inline const Matrix3 operator *( float scalar ) const; - - // Multiply a 3x3 matrix by a 3-D vector - // - inline const Vector3 operator *( const Vector3 & vec ) const; - - // Multiply two 3x3 matrices - // - inline const Matrix3 operator *( const Matrix3 & mat ) const; - - // Perform compound assignment and addition with a 3x3 matrix - // - inline Matrix3 & operator +=( const Matrix3 & mat ); - - // Perform compound assignment and subtraction by a 3x3 matrix - // - inline Matrix3 & operator -=( const Matrix3 & mat ); - - // Perform compound assignment and multiplication by a scalar - // - inline Matrix3 & operator *=( float scalar ); - - // Perform compound assignment and multiplication by a 3x3 matrix - // - inline Matrix3 & operator *=( const Matrix3 & mat ); - - // Construct an identity 3x3 matrix - // - static inline const Matrix3 identity( ); - - // Construct a 3x3 matrix to rotate around the x axis - // - static inline const Matrix3 rotationX( float radians ); - - // Construct a 3x3 matrix to rotate around the y axis - // - static inline const Matrix3 rotationY( float radians ); - - // Construct a 3x3 matrix to rotate around the z axis - // - static inline const Matrix3 rotationZ( float radians ); - - // Construct a 3x3 matrix to rotate around the x, y, and z axes - // - static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); - - // Construct a 3x3 matrix to rotate around a unit-length 3-D vector - // - static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static inline const Matrix3 rotation( const Quat & unitQuat ); - - // Construct a 3x3 matrix to perform scaling - // - static inline const Matrix3 scale( const Vector3 & scaleVec ); - -}; -// Multiply a 3x3 matrix by a scalar -// -inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); - -// Append (post-multiply) a scale transformation to a 3x3 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 3x3 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); - -// Multiply two 3x3 matrices per element -// -inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); - -// Compute the absolute value of a 3x3 matrix per element -// -inline const Matrix3 absPerElem( const Matrix3 & mat ); - -// Transpose of a 3x3 matrix -// -inline const Matrix3 transpose( const Matrix3 & mat ); - -// Compute the inverse of a 3x3 matrix -// NOTE: -// Result is unpredictable when the determinant of mat is equal to or near 0. -// -inline const Matrix3 inverse( const Matrix3 & mat ); - -// Determinant of a 3x3 matrix -// -inline float determinant( const Matrix3 & mat ); - -// Conditionally select between two 3x3 matrices -// -inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3x3 matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix3 & mat ); - -// Print a 3x3 matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix3 & mat, const char * name ); - -#endif - -// A 4x4 matrix in array-of-structures format -// -class Matrix4 -{ - Vector4 mCol0; - Vector4 mCol1; - Vector4 mCol2; - Vector4 mCol3; - -public: - // Default constructor; does no initialization - // - inline Matrix4( ) { }; - - // Copy a 4x4 matrix - // - inline Matrix4( const Matrix4 & mat ); - - // Construct a 4x4 matrix containing the specified columns - // - inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); - - // Construct a 4x4 matrix from a 3x4 transformation matrix - // - explicit inline Matrix4( const Transform3 & mat ); - - // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector - // - inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); - - // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector - // - inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); - - // Set all elements of a 4x4 matrix to the same scalar value - // - explicit inline Matrix4( float scalar ); - - // Assign one 4x4 matrix to another - // - inline Matrix4 & operator =( const Matrix4 & mat ); - - // Set the upper-left 3x3 submatrix - // NOTE: - // This function does not change the bottom row elements. - // - inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); - - // Get the upper-left 3x3 submatrix of a 4x4 matrix - // - inline const Matrix3 getUpper3x3( ) const; - - // Set translation component - // NOTE: - // This function does not change the bottom row elements. - // - inline Matrix4 & setTranslation( const Vector3 & translateVec ); - - // Get the translation component of a 4x4 matrix - // - inline const Vector3 getTranslation( ) const; - - // Set column 0 of a 4x4 matrix - // - inline Matrix4 & setCol0( const Vector4 & col0 ); - - // Set column 1 of a 4x4 matrix - // - inline Matrix4 & setCol1( const Vector4 & col1 ); - - // Set column 2 of a 4x4 matrix - // - inline Matrix4 & setCol2( const Vector4 & col2 ); - - // Set column 3 of a 4x4 matrix - // - inline Matrix4 & setCol3( const Vector4 & col3 ); - - // Get column 0 of a 4x4 matrix - // - inline const Vector4 getCol0( ) const; - - // Get column 1 of a 4x4 matrix - // - inline const Vector4 getCol1( ) const; - - // Get column 2 of a 4x4 matrix - // - inline const Vector4 getCol2( ) const; - - // Get column 3 of a 4x4 matrix - // - inline const Vector4 getCol3( ) const; - - // Set the column of a 4x4 matrix referred to by the specified index - // - inline Matrix4 & setCol( int col, const Vector4 & vec ); - - // Set the row of a 4x4 matrix referred to by the specified index - // - inline Matrix4 & setRow( int row, const Vector4 & vec ); - - // Get the column of a 4x4 matrix referred to by the specified index - // - inline const Vector4 getCol( int col ) const; - - // Get the row of a 4x4 matrix referred to by the specified index - // - inline const Vector4 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - inline Vector4 & operator []( int col ); - - // Subscripting operator to get a column - // - inline const Vector4 operator []( int col ) const; - - // Set the element of a 4x4 matrix referred to by column and row indices - // - inline Matrix4 & setElem( int col, int row, float val ); - - // Get the element of a 4x4 matrix referred to by column and row indices - // - inline float getElem( int col, int row ) const; - - // Add two 4x4 matrices - // - inline const Matrix4 operator +( const Matrix4 & mat ) const; - - // Subtract a 4x4 matrix from another 4x4 matrix - // - inline const Matrix4 operator -( const Matrix4 & mat ) const; - - // Negate all elements of a 4x4 matrix - // - inline const Matrix4 operator -( ) const; - - // Multiply a 4x4 matrix by a scalar - // - inline const Matrix4 operator *( float scalar ) const; - - // Multiply a 4x4 matrix by a 4-D vector - // - inline const Vector4 operator *( const Vector4 & vec ) const; - - // Multiply a 4x4 matrix by a 3-D vector - // - inline const Vector4 operator *( const Vector3 & vec ) const; - - // Multiply a 4x4 matrix by a 3-D point - // - inline const Vector4 operator *( const Point3 & pnt ) const; - - // Multiply two 4x4 matrices - // - inline const Matrix4 operator *( const Matrix4 & mat ) const; - - // Multiply a 4x4 matrix by a 3x4 transformation matrix - // - inline const Matrix4 operator *( const Transform3 & tfrm ) const; - - // Perform compound assignment and addition with a 4x4 matrix - // - inline Matrix4 & operator +=( const Matrix4 & mat ); - - // Perform compound assignment and subtraction by a 4x4 matrix - // - inline Matrix4 & operator -=( const Matrix4 & mat ); - - // Perform compound assignment and multiplication by a scalar - // - inline Matrix4 & operator *=( float scalar ); - - // Perform compound assignment and multiplication by a 4x4 matrix - // - inline Matrix4 & operator *=( const Matrix4 & mat ); - - // Perform compound assignment and multiplication by a 3x4 transformation matrix - // - inline Matrix4 & operator *=( const Transform3 & tfrm ); - - // Construct an identity 4x4 matrix - // - static inline const Matrix4 identity( ); - - // Construct a 4x4 matrix to rotate around the x axis - // - static inline const Matrix4 rotationX( float radians ); - - // Construct a 4x4 matrix to rotate around the y axis - // - static inline const Matrix4 rotationY( float radians ); - - // Construct a 4x4 matrix to rotate around the z axis - // - static inline const Matrix4 rotationZ( float radians ); - - // Construct a 4x4 matrix to rotate around the x, y, and z axes - // - static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); - - // Construct a 4x4 matrix to rotate around a unit-length 3-D vector - // - static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static inline const Matrix4 rotation( const Quat & unitQuat ); - - // Construct a 4x4 matrix to perform scaling - // - static inline const Matrix4 scale( const Vector3 & scaleVec ); - - // Construct a 4x4 matrix to perform translation - // - static inline const Matrix4 translation( const Vector3 & translateVec ); - - // Construct viewing matrix based on eye position, position looked at, and up direction - // - static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); - - // Construct a perspective projection matrix - // - static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); - - // Construct a perspective projection matrix based on frustum - // - static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); - - // Construct an orthographic projection matrix - // - static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); - -}; -// Multiply a 4x4 matrix by a scalar -// -inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); - -// Append (post-multiply) a scale transformation to a 4x4 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 4x4 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); - -// Multiply two 4x4 matrices per element -// -inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); - -// Compute the absolute value of a 4x4 matrix per element -// -inline const Matrix4 absPerElem( const Matrix4 & mat ); - -// Transpose of a 4x4 matrix -// -inline const Matrix4 transpose( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix -// NOTE: -// Result is unpredictable when the determinant of mat is equal to or near 0. -// -inline const Matrix4 inverse( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. -// -inline const Matrix4 affineInverse( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. -// -inline const Matrix4 orthoInverse( const Matrix4 & mat ); - -// Determinant of a 4x4 matrix -// -inline float determinant( const Matrix4 & mat ); - -// Conditionally select between two 4x4 matrices -// -inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 4x4 matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix4 & mat ); - -// Print a 4x4 matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix4 & mat, const char * name ); - -#endif - -// A 3x4 transformation matrix in array-of-structures format -// -class Transform3 -{ - Vector3 mCol0; - Vector3 mCol1; - Vector3 mCol2; - Vector3 mCol3; - -public: - // Default constructor; does no initialization - // - inline Transform3( ) { }; - - // Copy a 3x4 transformation matrix - // - inline Transform3( const Transform3 & tfrm ); - - // Construct a 3x4 transformation matrix containing the specified columns - // - inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); - - // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector - // - inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); - - // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector - // - inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); - - // Set all elements of a 3x4 transformation matrix to the same scalar value - // - explicit inline Transform3( float scalar ); - - // Assign one 3x4 transformation matrix to another - // - inline Transform3 & operator =( const Transform3 & tfrm ); - - // Set the upper-left 3x3 submatrix - // - inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); - - // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix - // - inline const Matrix3 getUpper3x3( ) const; - - // Set translation component - // - inline Transform3 & setTranslation( const Vector3 & translateVec ); - - // Get the translation component of a 3x4 transformation matrix - // - inline const Vector3 getTranslation( ) const; - - // Set column 0 of a 3x4 transformation matrix - // - inline Transform3 & setCol0( const Vector3 & col0 ); - - // Set column 1 of a 3x4 transformation matrix - // - inline Transform3 & setCol1( const Vector3 & col1 ); - - // Set column 2 of a 3x4 transformation matrix - // - inline Transform3 & setCol2( const Vector3 & col2 ); - - // Set column 3 of a 3x4 transformation matrix - // - inline Transform3 & setCol3( const Vector3 & col3 ); - - // Get column 0 of a 3x4 transformation matrix - // - inline const Vector3 getCol0( ) const; - - // Get column 1 of a 3x4 transformation matrix - // - inline const Vector3 getCol1( ) const; - - // Get column 2 of a 3x4 transformation matrix - // - inline const Vector3 getCol2( ) const; - - // Get column 3 of a 3x4 transformation matrix - // - inline const Vector3 getCol3( ) const; - - // Set the column of a 3x4 transformation matrix referred to by the specified index - // - inline Transform3 & setCol( int col, const Vector3 & vec ); - - // Set the row of a 3x4 transformation matrix referred to by the specified index - // - inline Transform3 & setRow( int row, const Vector4 & vec ); - - // Get the column of a 3x4 transformation matrix referred to by the specified index - // - inline const Vector3 getCol( int col ) const; - - // Get the row of a 3x4 transformation matrix referred to by the specified index - // - inline const Vector4 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - inline Vector3 & operator []( int col ); - - // Subscripting operator to get a column - // - inline const Vector3 operator []( int col ) const; - - // Set the element of a 3x4 transformation matrix referred to by column and row indices - // - inline Transform3 & setElem( int col, int row, float val ); - - // Get the element of a 3x4 transformation matrix referred to by column and row indices - // - inline float getElem( int col, int row ) const; - - // Multiply a 3x4 transformation matrix by a 3-D vector - // - inline const Vector3 operator *( const Vector3 & vec ) const; - - // Multiply a 3x4 transformation matrix by a 3-D point - // - inline const Point3 operator *( const Point3 & pnt ) const; - - // Multiply two 3x4 transformation matrices - // - inline const Transform3 operator *( const Transform3 & tfrm ) const; - - // Perform compound assignment and multiplication by a 3x4 transformation matrix - // - inline Transform3 & operator *=( const Transform3 & tfrm ); - - // Construct an identity 3x4 transformation matrix - // - static inline const Transform3 identity( ); - - // Construct a 3x4 transformation matrix to rotate around the x axis - // - static inline const Transform3 rotationX( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the y axis - // - static inline const Transform3 rotationY( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the z axis - // - static inline const Transform3 rotationZ( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes - // - static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); - - // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector - // - static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static inline const Transform3 rotation( const Quat & unitQuat ); - - // Construct a 3x4 transformation matrix to perform scaling - // - static inline const Transform3 scale( const Vector3 & scaleVec ); - - // Construct a 3x4 transformation matrix to perform translation - // - static inline const Transform3 translation( const Vector3 & translateVec ); - -}; -// Append (post-multiply) a scale transformation to a 3x4 transformation matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); - -// Multiply two 3x4 transformation matrices per element -// -inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); - -// Compute the absolute value of a 3x4 transformation matrix per element -// -inline const Transform3 absPerElem( const Transform3 & tfrm ); - -// Inverse of a 3x4 transformation matrix -// NOTE: -// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. -// -inline const Transform3 inverse( const Transform3 & tfrm ); - -// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. -// -inline const Transform3 orthoInverse( const Transform3 & tfrm ); - -// Conditionally select between two 3x4 transformation matrices -// -inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3x4 transformation matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Transform3 & tfrm ); - -// Print a 3x4 transformation matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Transform3 & tfrm, const char * name ); - -#endif - -} // namespace Aos -} // namespace Vectormath - -#include "vec_aos.h" -#include "quat_aos.h" -#include "mat_aos.h" - -#endif - diff --git a/Code/Physics/Bullet Source/src/vectormath/scalar/boolInVec.h b/Code/Physics/Bullet Source/src/vectormath/scalar/boolInVec.h deleted file mode 100644 index c5eeeebd..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/scalar/boolInVec.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _BOOLINVEC_H -#define _BOOLINVEC_H - -#include -namespace Vectormath { - -class floatInVec; - -//-------------------------------------------------------------------------------------------------- -// boolInVec class -// - -class boolInVec -{ -private: - unsigned int mData; - -public: - // Default constructor; does no initialization - // - inline boolInVec( ) { }; - - // Construct from a value converted from float - // - inline boolInVec(floatInVec vec); - - // Explicit cast from bool - // - explicit inline boolInVec(bool scalar); - - // Explicit cast to bool - // - inline bool getAsBool() const; - -#ifndef _VECTORMATH_NO_SCALAR_CAST - // Implicit cast to bool - // - inline operator bool() const; -#endif - - // Boolean negation operator - // - inline const boolInVec operator ! () const; - - // Assignment operator - // - inline boolInVec& operator = (boolInVec vec); - - // Boolean and assignment operator - // - inline boolInVec& operator &= (boolInVec vec); - - // Boolean exclusive or assignment operator - // - inline boolInVec& operator ^= (boolInVec vec); - - // Boolean or assignment operator - // - inline boolInVec& operator |= (boolInVec vec); - -}; - -// Equal operator -// -inline const boolInVec operator == (boolInVec vec0, boolInVec vec1); - -// Not equal operator -// -inline const boolInVec operator != (boolInVec vec0, boolInVec vec1); - -// And operator -// -inline const boolInVec operator & (boolInVec vec0, boolInVec vec1); - -// Exclusive or operator -// -inline const boolInVec operator ^ (boolInVec vec0, boolInVec vec1); - -// Or operator -// -inline const boolInVec operator | (boolInVec vec0, boolInVec vec1); - -// Conditionally select between two values -// -inline const boolInVec select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1); - - -} // namespace Vectormath - - -//-------------------------------------------------------------------------------------------------- -// boolInVec implementation -// - -#include "floatInVec.h" - -namespace Vectormath { - -inline -boolInVec::boolInVec(floatInVec vec) -{ - *this = (vec != floatInVec(0.0f)); -} - -inline -boolInVec::boolInVec(bool scalar) -{ - mData = -(int)scalar; -} - -inline -bool -boolInVec::getAsBool() const -{ - return (mData > 0); -} - -#ifndef _VECTORMATH_NO_SCALAR_CAST -inline -boolInVec::operator bool() const -{ - return getAsBool(); -} -#endif - -inline -const boolInVec -boolInVec::operator ! () const -{ - return boolInVec(!mData); -} - -inline -boolInVec& -boolInVec::operator = (boolInVec vec) -{ - mData = vec.mData; - return *this; -} - -inline -boolInVec& -boolInVec::operator &= (boolInVec vec) -{ - *this = *this & vec; - return *this; -} - -inline -boolInVec& -boolInVec::operator ^= (boolInVec vec) -{ - *this = *this ^ vec; - return *this; -} - -inline -boolInVec& -boolInVec::operator |= (boolInVec vec) -{ - *this = *this | vec; - return *this; -} - -inline -const boolInVec -operator == (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() == vec1.getAsBool()); -} - -inline -const boolInVec -operator != (boolInVec vec0, boolInVec vec1) -{ - return !(vec0 == vec1); -} - -inline -const boolInVec -operator & (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() & vec1.getAsBool()); -} - -inline -const boolInVec -operator | (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() | vec1.getAsBool()); -} - -inline -const boolInVec -operator ^ (boolInVec vec0, boolInVec vec1) -{ - return boolInVec(vec0.getAsBool() ^ vec1.getAsBool()); -} - -inline -const boolInVec -select(boolInVec vec0, boolInVec vec1, boolInVec select_vec1) -{ - return (select_vec1.getAsBool() == 0) ? vec0 : vec1; -} - -} // namespace Vectormath - -#endif // boolInVec_h diff --git a/Code/Physics/Bullet Source/src/vectormath/scalar/floatInVec.h b/Code/Physics/Bullet Source/src/vectormath/scalar/floatInVec.h deleted file mode 100644 index 12d89e43..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/scalar/floatInVec.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _FLOATINVEC_H -#define _FLOATINVEC_H - -#include -namespace Vectormath { - -class boolInVec; - -//-------------------------------------------------------------------------------------------------- -// floatInVec class -// - -// A class representing a scalar float value contained in a vector register -// This class does not support fastmath -class floatInVec -{ -private: - float mData; - -public: - // Default constructor; does no initialization - // - inline floatInVec( ) { }; - - // Construct from a value converted from bool - // - inline floatInVec(boolInVec vec); - - // Explicit cast from float - // - explicit inline floatInVec(float scalar); - - // Explicit cast to float - // - inline float getAsFloat() const; - -#ifndef _VECTORMATH_NO_SCALAR_CAST - // Implicit cast to float - // - inline operator float() const; -#endif - - // Post increment (add 1.0f) - // - inline const floatInVec operator ++ (int); - - // Post decrement (subtract 1.0f) - // - inline const floatInVec operator -- (int); - - // Pre increment (add 1.0f) - // - inline floatInVec& operator ++ (); - - // Pre decrement (subtract 1.0f) - // - inline floatInVec& operator -- (); - - // Negation operator - // - inline const floatInVec operator - () const; - - // Assignment operator - // - inline floatInVec& operator = (floatInVec vec); - - // Multiplication assignment operator - // - inline floatInVec& operator *= (floatInVec vec); - - // Division assignment operator - // - inline floatInVec& operator /= (floatInVec vec); - - // Addition assignment operator - // - inline floatInVec& operator += (floatInVec vec); - - // Subtraction assignment operator - // - inline floatInVec& operator -= (floatInVec vec); - -}; - -// Multiplication operator -// -inline const floatInVec operator * (floatInVec vec0, floatInVec vec1); - -// Division operator -// -inline const floatInVec operator / (floatInVec vec0, floatInVec vec1); - -// Addition operator -// -inline const floatInVec operator + (floatInVec vec0, floatInVec vec1); - -// Subtraction operator -// -inline const floatInVec operator - (floatInVec vec0, floatInVec vec1); - -// Less than operator -// -inline const boolInVec operator < (floatInVec vec0, floatInVec vec1); - -// Less than or equal operator -// -inline const boolInVec operator <= (floatInVec vec0, floatInVec vec1); - -// Greater than operator -// -inline const boolInVec operator > (floatInVec vec0, floatInVec vec1); - -// Greater than or equal operator -// -inline const boolInVec operator >= (floatInVec vec0, floatInVec vec1); - -// Equal operator -// -inline const boolInVec operator == (floatInVec vec0, floatInVec vec1); - -// Not equal operator -// -inline const boolInVec operator != (floatInVec vec0, floatInVec vec1); - -// Conditionally select between two values -// -inline const floatInVec select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1); - - -} // namespace Vectormath - - -//-------------------------------------------------------------------------------------------------- -// floatInVec implementation -// - -#include "boolInVec.h" - -namespace Vectormath { - -inline -floatInVec::floatInVec(boolInVec vec) -{ - mData = float(vec.getAsBool()); -} - -inline -floatInVec::floatInVec(float scalar) -{ - mData = scalar; -} - -inline -float -floatInVec::getAsFloat() const -{ - return mData; -} - -#ifndef _VECTORMATH_NO_SCALAR_CAST -inline -floatInVec::operator float() const -{ - return getAsFloat(); -} -#endif - -inline -const floatInVec -floatInVec::operator ++ (int) -{ - float olddata = mData; - operator ++(); - return floatInVec(olddata); -} - -inline -const floatInVec -floatInVec::operator -- (int) -{ - float olddata = mData; - operator --(); - return floatInVec(olddata); -} - -inline -floatInVec& -floatInVec::operator ++ () -{ - *this += floatInVec(1.0f); - return *this; -} - -inline -floatInVec& -floatInVec::operator -- () -{ - *this -= floatInVec(1.0f); - return *this; -} - -inline -const floatInVec -floatInVec::operator - () const -{ - return floatInVec(-mData); -} - -inline -floatInVec& -floatInVec::operator = (floatInVec vec) -{ - mData = vec.mData; - return *this; -} - -inline -floatInVec& -floatInVec::operator *= (floatInVec vec) -{ - *this = *this * vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator /= (floatInVec vec) -{ - *this = *this / vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator += (floatInVec vec) -{ - *this = *this + vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator -= (floatInVec vec) -{ - *this = *this - vec; - return *this; -} - -inline -const floatInVec -operator * (floatInVec vec0, floatInVec vec1) -{ - return floatInVec(vec0.getAsFloat() * vec1.getAsFloat()); -} - -inline -const floatInVec -operator / (floatInVec num, floatInVec den) -{ - return floatInVec(num.getAsFloat() / den.getAsFloat()); -} - -inline -const floatInVec -operator + (floatInVec vec0, floatInVec vec1) -{ - return floatInVec(vec0.getAsFloat() + vec1.getAsFloat()); -} - -inline -const floatInVec -operator - (floatInVec vec0, floatInVec vec1) -{ - return floatInVec(vec0.getAsFloat() - vec1.getAsFloat()); -} - -inline -const boolInVec -operator < (floatInVec vec0, floatInVec vec1) -{ - return boolInVec(vec0.getAsFloat() < vec1.getAsFloat()); -} - -inline -const boolInVec -operator <= (floatInVec vec0, floatInVec vec1) -{ - return !(vec0 > vec1); -} - -inline -const boolInVec -operator > (floatInVec vec0, floatInVec vec1) -{ - return boolInVec(vec0.getAsFloat() > vec1.getAsFloat()); -} - -inline -const boolInVec -operator >= (floatInVec vec0, floatInVec vec1) -{ - return !(vec0 < vec1); -} - -inline -const boolInVec -operator == (floatInVec vec0, floatInVec vec1) -{ - return boolInVec(vec0.getAsFloat() == vec1.getAsFloat()); -} - -inline -const boolInVec -operator != (floatInVec vec0, floatInVec vec1) -{ - return !(vec0 == vec1); -} - -inline -const floatInVec -select(floatInVec vec0, floatInVec vec1, boolInVec select_vec1) -{ - return (select_vec1.getAsBool() == 0) ? vec0 : vec1; -} - -} // namespace Vectormath - -#endif // floatInVec_h diff --git a/Code/Physics/Bullet Source/src/vectormath/scalar/mat_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/mat_aos.h deleted file mode 100644 index e103243d..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/scalar/mat_aos.h +++ /dev/null @@ -1,1630 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_MAT_AOS_CPP_H -#define _VECTORMATH_MAT_AOS_CPP_H - -namespace Vectormath { -namespace Aos { - -//----------------------------------------------------------------------------- -// Constants - -#define _VECTORMATH_PI_OVER_2 1.570796327f - -//----------------------------------------------------------------------------- -// Definitions - -inline Matrix3::Matrix3( const Matrix3 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; -} - -inline Matrix3::Matrix3( float scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); -} - -inline Matrix3::Matrix3( const Quat & unitQuat ) -{ - float qx, qy, qz, qw, qx2, qy2, qz2, qxqx2, qyqy2, qzqz2, qxqy2, qyqz2, qzqw2, qxqz2, qyqw2, qxqw2; - qx = unitQuat.getX(); - qy = unitQuat.getY(); - qz = unitQuat.getZ(); - qw = unitQuat.getW(); - qx2 = ( qx + qx ); - qy2 = ( qy + qy ); - qz2 = ( qz + qz ); - qxqx2 = ( qx * qx2 ); - qxqy2 = ( qx * qy2 ); - qxqz2 = ( qx * qz2 ); - qxqw2 = ( qw * qx2 ); - qyqy2 = ( qy * qy2 ); - qyqz2 = ( qy * qz2 ); - qyqw2 = ( qw * qy2 ); - qzqz2 = ( qz * qz2 ); - qzqw2 = ( qw * qz2 ); - mCol0 = Vector3( ( ( 1.0f - qyqy2 ) - qzqz2 ), ( qxqy2 + qzqw2 ), ( qxqz2 - qyqw2 ) ); - mCol1 = Vector3( ( qxqy2 - qzqw2 ), ( ( 1.0f - qxqx2 ) - qzqz2 ), ( qyqz2 + qxqw2 ) ); - mCol2 = Vector3( ( qxqz2 + qyqw2 ), ( qyqz2 - qxqw2 ), ( ( 1.0f - qxqx2 ) - qyqy2 ) ); -} - -inline Matrix3::Matrix3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; -} - -inline Matrix3 & Matrix3::setCol0( const Vector3 & _col0 ) -{ - mCol0 = _col0; - return *this; -} - -inline Matrix3 & Matrix3::setCol1( const Vector3 & _col1 ) -{ - mCol1 = _col1; - return *this; -} - -inline Matrix3 & Matrix3::setCol2( const Vector3 & _col2 ) -{ - mCol2 = _col2; - return *this; -} - -inline Matrix3 & Matrix3::setCol( int col, const Vector3 & vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -inline Matrix3 & Matrix3::setRow( int row, const Vector3 & vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - return *this; -} - -inline Matrix3 & Matrix3::setElem( int col, int row, float val ) -{ - Vector3 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -inline float Matrix3::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -inline const Vector3 Matrix3::getCol0( ) const -{ - return mCol0; -} - -inline const Vector3 Matrix3::getCol1( ) const -{ - return mCol1; -} - -inline const Vector3 Matrix3::getCol2( ) const -{ - return mCol2; -} - -inline const Vector3 Matrix3::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -inline const Vector3 Matrix3::getRow( int row ) const -{ - return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); -} - -inline Vector3 & Matrix3::operator []( int col ) -{ - return *(&mCol0 + col); -} - -inline const Vector3 Matrix3::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -inline Matrix3 & Matrix3::operator =( const Matrix3 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - return *this; -} - -inline const Matrix3 transpose( const Matrix3 & mat ) -{ - return Matrix3( - Vector3( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX() ), - Vector3( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY() ), - Vector3( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ() ) - ); -} - -inline const Matrix3 inverse( const Matrix3 & mat ) -{ - Vector3 tmp0, tmp1, tmp2; - float detinv; - tmp0 = cross( mat.getCol1(), mat.getCol2() ); - tmp1 = cross( mat.getCol2(), mat.getCol0() ); - tmp2 = cross( mat.getCol0(), mat.getCol1() ); - detinv = ( 1.0f / dot( mat.getCol2(), tmp2 ) ); - return Matrix3( - Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ), - Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ), - Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ) - ); -} - -inline float determinant( const Matrix3 & mat ) -{ - return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); -} - -inline const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const -{ - return Matrix3( - ( mCol0 + mat.mCol0 ), - ( mCol1 + mat.mCol1 ), - ( mCol2 + mat.mCol2 ) - ); -} - -inline const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const -{ - return Matrix3( - ( mCol0 - mat.mCol0 ), - ( mCol1 - mat.mCol1 ), - ( mCol2 - mat.mCol2 ) - ); -} - -inline Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) -{ - *this = *this + mat; - return *this; -} - -inline Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) -{ - *this = *this - mat; - return *this; -} - -inline const Matrix3 Matrix3::operator -( ) const -{ - return Matrix3( - ( -mCol0 ), - ( -mCol1 ), - ( -mCol2 ) - ); -} - -inline const Matrix3 absPerElem( const Matrix3 & mat ) -{ - return Matrix3( - absPerElem( mat.getCol0() ), - absPerElem( mat.getCol1() ), - absPerElem( mat.getCol2() ) - ); -} - -inline const Matrix3 Matrix3::operator *( float scalar ) const -{ - return Matrix3( - ( mCol0 * scalar ), - ( mCol1 * scalar ), - ( mCol2 * scalar ) - ); -} - -inline Matrix3 & Matrix3::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Matrix3 operator *( float scalar, const Matrix3 & mat ) -{ - return mat * scalar; -} - -inline const Vector3 Matrix3::operator *( const Vector3 & vec ) const -{ - return Vector3( - ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), - ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), - ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) - ); -} - -inline const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const -{ - return Matrix3( - ( *this * mat.mCol0 ), - ( *this * mat.mCol1 ), - ( *this * mat.mCol2 ) - ); -} - -inline Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) -{ - *this = *this * mat; - return *this; -} - -inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) -{ - return Matrix3( - mulPerElem( mat0.getCol0(), mat1.getCol0() ), - mulPerElem( mat0.getCol1(), mat1.getCol1() ), - mulPerElem( mat0.getCol2(), mat1.getCol2() ) - ); -} - -inline const Matrix3 Matrix3::identity( ) -{ - return Matrix3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ) - ); -} - -inline const Matrix3 Matrix3::rotationX( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix3( - Vector3::xAxis( ), - Vector3( 0.0f, c, s ), - Vector3( 0.0f, -s, c ) - ); -} - -inline const Matrix3 Matrix3::rotationY( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix3( - Vector3( c, 0.0f, -s ), - Vector3::yAxis( ), - Vector3( s, 0.0f, c ) - ); -} - -inline const Matrix3 Matrix3::rotationZ( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix3( - Vector3( c, s, 0.0f ), - Vector3( -s, c, 0.0f ), - Vector3::zAxis( ) - ); -} - -inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ ) -{ - float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; - sX = sinf( radiansXYZ.getX() ); - cX = cosf( radiansXYZ.getX() ); - sY = sinf( radiansXYZ.getY() ); - cY = cosf( radiansXYZ.getY() ); - sZ = sinf( radiansXYZ.getZ() ); - cZ = cosf( radiansXYZ.getZ() ); - tmp0 = ( cZ * sY ); - tmp1 = ( sZ * sY ); - return Matrix3( - Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), - Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), - Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ) - ); -} - -inline const Matrix3 Matrix3::rotation( float radians, const Vector3 & unitVec ) -{ - float x, y, z, s, c, oneMinusC, xy, yz, zx; - s = sinf( radians ); - c = cosf( radians ); - x = unitVec.getX(); - y = unitVec.getY(); - z = unitVec.getZ(); - xy = ( x * y ); - yz = ( y * z ); - zx = ( z * x ); - oneMinusC = ( 1.0f - c ); - return Matrix3( - Vector3( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ) ), - Vector3( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ) ), - Vector3( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ) ) - ); -} - -inline const Matrix3 Matrix3::rotation( const Quat & unitQuat ) -{ - return Matrix3( unitQuat ); -} - -inline const Matrix3 Matrix3::scale( const Vector3 & scaleVec ) -{ - return Matrix3( - Vector3( scaleVec.getX(), 0.0f, 0.0f ), - Vector3( 0.0f, scaleVec.getY(), 0.0f ), - Vector3( 0.0f, 0.0f, scaleVec.getZ() ) - ); -} - -inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ) -{ - return Matrix3( - ( mat.getCol0() * scaleVec.getX( ) ), - ( mat.getCol1() * scaleVec.getY( ) ), - ( mat.getCol2() * scaleVec.getZ( ) ) - ); -} - -inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ) -{ - return Matrix3( - mulPerElem( mat.getCol0(), scaleVec ), - mulPerElem( mat.getCol1(), scaleVec ), - mulPerElem( mat.getCol2(), scaleVec ) - ); -} - -inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) -{ - return Matrix3( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Matrix3 & mat ) -{ - print( mat.getRow( 0 ) ); - print( mat.getRow( 1 ) ); - print( mat.getRow( 2 ) ); -} - -inline void print( const Matrix3 & mat, const char * name ) -{ - printf("%s:\n", name); - print( mat ); -} - -#endif - -inline Matrix4::Matrix4( const Matrix4 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - mCol3 = mat.mCol3; -} - -inline Matrix4::Matrix4( float scalar ) -{ - mCol0 = Vector4( scalar ); - mCol1 = Vector4( scalar ); - mCol2 = Vector4( scalar ); - mCol3 = Vector4( scalar ); -} - -inline Matrix4::Matrix4( const Transform3 & mat ) -{ - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( mat.getCol3(), 1.0f ); -} - -inline Matrix4::Matrix4( const Vector4 & _col0, const Vector4 & _col1, const Vector4 & _col2, const Vector4 & _col3 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; - mCol3 = _col3; -} - -inline Matrix4::Matrix4( const Matrix3 & mat, const Vector3 & translateVec ) -{ - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( translateVec, 1.0f ); -} - -inline Matrix4::Matrix4( const Quat & unitQuat, const Vector3 & translateVec ) -{ - Matrix3 mat; - mat = Matrix3( unitQuat ); - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( translateVec, 1.0f ); -} - -inline Matrix4 & Matrix4::setCol0( const Vector4 & _col0 ) -{ - mCol0 = _col0; - return *this; -} - -inline Matrix4 & Matrix4::setCol1( const Vector4 & _col1 ) -{ - mCol1 = _col1; - return *this; -} - -inline Matrix4 & Matrix4::setCol2( const Vector4 & _col2 ) -{ - mCol2 = _col2; - return *this; -} - -inline Matrix4 & Matrix4::setCol3( const Vector4 & _col3 ) -{ - mCol3 = _col3; - return *this; -} - -inline Matrix4 & Matrix4::setCol( int col, const Vector4 & vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -inline Matrix4 & Matrix4::setRow( int row, const Vector4 & vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - mCol3.setElem( row, vec.getElem( 3 ) ); - return *this; -} - -inline Matrix4 & Matrix4::setElem( int col, int row, float val ) -{ - Vector4 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -inline float Matrix4::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -inline const Vector4 Matrix4::getCol0( ) const -{ - return mCol0; -} - -inline const Vector4 Matrix4::getCol1( ) const -{ - return mCol1; -} - -inline const Vector4 Matrix4::getCol2( ) const -{ - return mCol2; -} - -inline const Vector4 Matrix4::getCol3( ) const -{ - return mCol3; -} - -inline const Vector4 Matrix4::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -inline const Vector4 Matrix4::getRow( int row ) const -{ - return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); -} - -inline Vector4 & Matrix4::operator []( int col ) -{ - return *(&mCol0 + col); -} - -inline const Vector4 Matrix4::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -inline Matrix4 & Matrix4::operator =( const Matrix4 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - mCol3 = mat.mCol3; - return *this; -} - -inline const Matrix4 transpose( const Matrix4 & mat ) -{ - return Matrix4( - Vector4( mat.getCol0().getX(), mat.getCol1().getX(), mat.getCol2().getX(), mat.getCol3().getX() ), - Vector4( mat.getCol0().getY(), mat.getCol1().getY(), mat.getCol2().getY(), mat.getCol3().getY() ), - Vector4( mat.getCol0().getZ(), mat.getCol1().getZ(), mat.getCol2().getZ(), mat.getCol3().getZ() ), - Vector4( mat.getCol0().getW(), mat.getCol1().getW(), mat.getCol2().getW(), mat.getCol3().getW() ) - ); -} - -inline const Matrix4 inverse( const Matrix4 & mat ) -{ - Vector4 res0, res1, res2, res3; - float mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, detInv; - mA = mat.getCol0().getX(); - mB = mat.getCol0().getY(); - mC = mat.getCol0().getZ(); - mD = mat.getCol0().getW(); - mE = mat.getCol1().getX(); - mF = mat.getCol1().getY(); - mG = mat.getCol1().getZ(); - mH = mat.getCol1().getW(); - mI = mat.getCol2().getX(); - mJ = mat.getCol2().getY(); - mK = mat.getCol2().getZ(); - mL = mat.getCol2().getW(); - mM = mat.getCol3().getX(); - mN = mat.getCol3().getY(); - mO = mat.getCol3().getZ(); - mP = mat.getCol3().getW(); - tmp0 = ( ( mK * mD ) - ( mC * mL ) ); - tmp1 = ( ( mO * mH ) - ( mG * mP ) ); - tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); - tmp3 = ( ( mF * mO ) - ( mN * mG ) ); - tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); - tmp5 = ( ( mN * mH ) - ( mF * mP ) ); - res0.setX( ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ) ); - res0.setY( ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ) ); - res0.setZ( ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ) ); - res0.setW( ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ) ); - detInv = ( 1.0f / ( ( ( ( mA * res0.getX() ) + ( mE * res0.getY() ) ) + ( mI * res0.getZ() ) ) + ( mM * res0.getW() ) ) ); - res1.setX( ( mI * tmp1 ) ); - res1.setY( ( mM * tmp0 ) ); - res1.setZ( ( mA * tmp1 ) ); - res1.setW( ( mE * tmp0 ) ); - res3.setX( ( mI * tmp3 ) ); - res3.setY( ( mM * tmp2 ) ); - res3.setZ( ( mA * tmp3 ) ); - res3.setW( ( mE * tmp2 ) ); - res2.setX( ( mI * tmp5 ) ); - res2.setY( ( mM * tmp4 ) ); - res2.setZ( ( mA * tmp5 ) ); - res2.setW( ( mE * tmp4 ) ); - tmp0 = ( ( mI * mB ) - ( mA * mJ ) ); - tmp1 = ( ( mM * mF ) - ( mE * mN ) ); - tmp2 = ( ( mI * mD ) - ( mA * mL ) ); - tmp3 = ( ( mM * mH ) - ( mE * mP ) ); - tmp4 = ( ( mI * mC ) - ( mA * mK ) ); - tmp5 = ( ( mM * mG ) - ( mE * mO ) ); - res2.setX( ( ( ( mL * tmp1 ) - ( mJ * tmp3 ) ) + res2.getX() ) ); - res2.setY( ( ( ( mP * tmp0 ) - ( mN * tmp2 ) ) + res2.getY() ) ); - res2.setZ( ( ( ( mB * tmp3 ) - ( mD * tmp1 ) ) - res2.getZ() ) ); - res2.setW( ( ( ( mF * tmp2 ) - ( mH * tmp0 ) ) - res2.getW() ) ); - res3.setX( ( ( ( mJ * tmp5 ) - ( mK * tmp1 ) ) + res3.getX() ) ); - res3.setY( ( ( ( mN * tmp4 ) - ( mO * tmp0 ) ) + res3.getY() ) ); - res3.setZ( ( ( ( mC * tmp1 ) - ( mB * tmp5 ) ) - res3.getZ() ) ); - res3.setW( ( ( ( mG * tmp0 ) - ( mF * tmp4 ) ) - res3.getW() ) ); - res1.setX( ( ( ( mK * tmp3 ) - ( mL * tmp5 ) ) - res1.getX() ) ); - res1.setY( ( ( ( mO * tmp2 ) - ( mP * tmp4 ) ) - res1.getY() ) ); - res1.setZ( ( ( ( mD * tmp5 ) - ( mC * tmp3 ) ) + res1.getZ() ) ); - res1.setW( ( ( ( mH * tmp4 ) - ( mG * tmp2 ) ) + res1.getW() ) ); - return Matrix4( - ( res0 * detInv ), - ( res1 * detInv ), - ( res2 * detInv ), - ( res3 * detInv ) - ); -} - -inline const Matrix4 affineInverse( const Matrix4 & mat ) -{ - Transform3 affineMat; - affineMat.setCol0( mat.getCol0().getXYZ( ) ); - affineMat.setCol1( mat.getCol1().getXYZ( ) ); - affineMat.setCol2( mat.getCol2().getXYZ( ) ); - affineMat.setCol3( mat.getCol3().getXYZ( ) ); - return Matrix4( inverse( affineMat ) ); -} - -inline const Matrix4 orthoInverse( const Matrix4 & mat ) -{ - Transform3 affineMat; - affineMat.setCol0( mat.getCol0().getXYZ( ) ); - affineMat.setCol1( mat.getCol1().getXYZ( ) ); - affineMat.setCol2( mat.getCol2().getXYZ( ) ); - affineMat.setCol3( mat.getCol3().getXYZ( ) ); - return Matrix4( orthoInverse( affineMat ) ); -} - -inline float determinant( const Matrix4 & mat ) -{ - float dx, dy, dz, dw, mA, mB, mC, mD, mE, mF, mG, mH, mI, mJ, mK, mL, mM, mN, mO, mP, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - mA = mat.getCol0().getX(); - mB = mat.getCol0().getY(); - mC = mat.getCol0().getZ(); - mD = mat.getCol0().getW(); - mE = mat.getCol1().getX(); - mF = mat.getCol1().getY(); - mG = mat.getCol1().getZ(); - mH = mat.getCol1().getW(); - mI = mat.getCol2().getX(); - mJ = mat.getCol2().getY(); - mK = mat.getCol2().getZ(); - mL = mat.getCol2().getW(); - mM = mat.getCol3().getX(); - mN = mat.getCol3().getY(); - mO = mat.getCol3().getZ(); - mP = mat.getCol3().getW(); - tmp0 = ( ( mK * mD ) - ( mC * mL ) ); - tmp1 = ( ( mO * mH ) - ( mG * mP ) ); - tmp2 = ( ( mB * mK ) - ( mJ * mC ) ); - tmp3 = ( ( mF * mO ) - ( mN * mG ) ); - tmp4 = ( ( mJ * mD ) - ( mB * mL ) ); - tmp5 = ( ( mN * mH ) - ( mF * mP ) ); - dx = ( ( ( mJ * tmp1 ) - ( mL * tmp3 ) ) - ( mK * tmp5 ) ); - dy = ( ( ( mN * tmp0 ) - ( mP * tmp2 ) ) - ( mO * tmp4 ) ); - dz = ( ( ( mD * tmp3 ) + ( mC * tmp5 ) ) - ( mB * tmp1 ) ); - dw = ( ( ( mH * tmp2 ) + ( mG * tmp4 ) ) - ( mF * tmp0 ) ); - return ( ( ( ( mA * dx ) + ( mE * dy ) ) + ( mI * dz ) ) + ( mM * dw ) ); -} - -inline const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const -{ - return Matrix4( - ( mCol0 + mat.mCol0 ), - ( mCol1 + mat.mCol1 ), - ( mCol2 + mat.mCol2 ), - ( mCol3 + mat.mCol3 ) - ); -} - -inline const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const -{ - return Matrix4( - ( mCol0 - mat.mCol0 ), - ( mCol1 - mat.mCol1 ), - ( mCol2 - mat.mCol2 ), - ( mCol3 - mat.mCol3 ) - ); -} - -inline Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) -{ - *this = *this + mat; - return *this; -} - -inline Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) -{ - *this = *this - mat; - return *this; -} - -inline const Matrix4 Matrix4::operator -( ) const -{ - return Matrix4( - ( -mCol0 ), - ( -mCol1 ), - ( -mCol2 ), - ( -mCol3 ) - ); -} - -inline const Matrix4 absPerElem( const Matrix4 & mat ) -{ - return Matrix4( - absPerElem( mat.getCol0() ), - absPerElem( mat.getCol1() ), - absPerElem( mat.getCol2() ), - absPerElem( mat.getCol3() ) - ); -} - -inline const Matrix4 Matrix4::operator *( float scalar ) const -{ - return Matrix4( - ( mCol0 * scalar ), - ( mCol1 * scalar ), - ( mCol2 * scalar ), - ( mCol3 * scalar ) - ); -} - -inline Matrix4 & Matrix4::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Matrix4 operator *( float scalar, const Matrix4 & mat ) -{ - return mat * scalar; -} - -inline const Vector4 Matrix4::operator *( const Vector4 & vec ) const -{ - return Vector4( - ( ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ) + ( mCol3.getX() * vec.getW() ) ), - ( ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ) + ( mCol3.getY() * vec.getW() ) ), - ( ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) + ( mCol3.getZ() * vec.getW() ) ), - ( ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) + ( mCol3.getW() * vec.getW() ) ) - ); -} - -inline const Vector4 Matrix4::operator *( const Vector3 & vec ) const -{ - return Vector4( - ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), - ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), - ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ), - ( ( ( mCol0.getW() * vec.getX() ) + ( mCol1.getW() * vec.getY() ) ) + ( mCol2.getW() * vec.getZ() ) ) - ); -} - -inline const Vector4 Matrix4::operator *( const Point3 & pnt ) const -{ - return Vector4( - ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), - ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), - ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ), - ( ( ( ( mCol0.getW() * pnt.getX() ) + ( mCol1.getW() * pnt.getY() ) ) + ( mCol2.getW() * pnt.getZ() ) ) + mCol3.getW() ) - ); -} - -inline const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const -{ - return Matrix4( - ( *this * mat.mCol0 ), - ( *this * mat.mCol1 ), - ( *this * mat.mCol2 ), - ( *this * mat.mCol3 ) - ); -} - -inline Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) -{ - *this = *this * mat; - return *this; -} - -inline const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const -{ - return Matrix4( - ( *this * tfrm.getCol0() ), - ( *this * tfrm.getCol1() ), - ( *this * tfrm.getCol2() ), - ( *this * Point3( tfrm.getCol3() ) ) - ); -} - -inline Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) -{ - *this = *this * tfrm; - return *this; -} - -inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) -{ - return Matrix4( - mulPerElem( mat0.getCol0(), mat1.getCol0() ), - mulPerElem( mat0.getCol1(), mat1.getCol1() ), - mulPerElem( mat0.getCol2(), mat1.getCol2() ), - mulPerElem( mat0.getCol3(), mat1.getCol3() ) - ); -} - -inline const Matrix4 Matrix4::identity( ) -{ - return Matrix4( - Vector4::xAxis( ), - Vector4::yAxis( ), - Vector4::zAxis( ), - Vector4::wAxis( ) - ); -} - -inline Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) -{ - mCol0.setXYZ( mat3.getCol0() ); - mCol1.setXYZ( mat3.getCol1() ); - mCol2.setXYZ( mat3.getCol2() ); - return *this; -} - -inline const Matrix3 Matrix4::getUpper3x3( ) const -{ - return Matrix3( - mCol0.getXYZ( ), - mCol1.getXYZ( ), - mCol2.getXYZ( ) - ); -} - -inline Matrix4 & Matrix4::setTranslation( const Vector3 & translateVec ) -{ - mCol3.setXYZ( translateVec ); - return *this; -} - -inline const Vector3 Matrix4::getTranslation( ) const -{ - return mCol3.getXYZ( ); -} - -inline const Matrix4 Matrix4::rotationX( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix4( - Vector4::xAxis( ), - Vector4( 0.0f, c, s, 0.0f ), - Vector4( 0.0f, -s, c, 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotationY( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix4( - Vector4( c, 0.0f, -s, 0.0f ), - Vector4::yAxis( ), - Vector4( s, 0.0f, c, 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotationZ( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Matrix4( - Vector4( c, s, 0.0f, 0.0f ), - Vector4( -s, c, 0.0f, 0.0f ), - Vector4::zAxis( ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotationZYX( const Vector3 & radiansXYZ ) -{ - float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; - sX = sinf( radiansXYZ.getX() ); - cX = cosf( radiansXYZ.getX() ); - sY = sinf( radiansXYZ.getY() ); - cY = cosf( radiansXYZ.getY() ); - sZ = sinf( radiansXYZ.getZ() ); - cZ = cosf( radiansXYZ.getZ() ); - tmp0 = ( cZ * sY ); - tmp1 = ( sZ * sY ); - return Matrix4( - Vector4( ( cZ * cY ), ( sZ * cY ), -sY, 0.0f ), - Vector4( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ), 0.0f ), - Vector4( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ), 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotation( float radians, const Vector3 & unitVec ) -{ - float x, y, z, s, c, oneMinusC, xy, yz, zx; - s = sinf( radians ); - c = cosf( radians ); - x = unitVec.getX(); - y = unitVec.getY(); - z = unitVec.getZ(); - xy = ( x * y ); - yz = ( y * z ); - zx = ( z * x ); - oneMinusC = ( 1.0f - c ); - return Matrix4( - Vector4( ( ( ( x * x ) * oneMinusC ) + c ), ( ( xy * oneMinusC ) + ( z * s ) ), ( ( zx * oneMinusC ) - ( y * s ) ), 0.0f ), - Vector4( ( ( xy * oneMinusC ) - ( z * s ) ), ( ( ( y * y ) * oneMinusC ) + c ), ( ( yz * oneMinusC ) + ( x * s ) ), 0.0f ), - Vector4( ( ( zx * oneMinusC ) + ( y * s ) ), ( ( yz * oneMinusC ) - ( x * s ) ), ( ( ( z * z ) * oneMinusC ) + c ), 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 Matrix4::rotation( const Quat & unitQuat ) -{ - return Matrix4( Transform3::rotation( unitQuat ) ); -} - -inline const Matrix4 Matrix4::scale( const Vector3 & scaleVec ) -{ - return Matrix4( - Vector4( scaleVec.getX(), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, scaleVec.getY(), 0.0f, 0.0f ), - Vector4( 0.0f, 0.0f, scaleVec.getZ(), 0.0f ), - Vector4::wAxis( ) - ); -} - -inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ) -{ - return Matrix4( - ( mat.getCol0() * scaleVec.getX( ) ), - ( mat.getCol1() * scaleVec.getY( ) ), - ( mat.getCol2() * scaleVec.getZ( ) ), - mat.getCol3() - ); -} - -inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ) -{ - Vector4 scale4; - scale4 = Vector4( scaleVec, 1.0f ); - return Matrix4( - mulPerElem( mat.getCol0(), scale4 ), - mulPerElem( mat.getCol1(), scale4 ), - mulPerElem( mat.getCol2(), scale4 ), - mulPerElem( mat.getCol3(), scale4 ) - ); -} - -inline const Matrix4 Matrix4::translation( const Vector3 & translateVec ) -{ - return Matrix4( - Vector4::xAxis( ), - Vector4::yAxis( ), - Vector4::zAxis( ), - Vector4( translateVec, 1.0f ) - ); -} - -inline const Matrix4 Matrix4::lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ) -{ - Matrix4 m4EyeFrame; - Vector3 v3X, v3Y, v3Z; - v3Y = normalize( upVec ); - v3Z = normalize( ( eyePos - lookAtPos ) ); - v3X = normalize( cross( v3Y, v3Z ) ); - v3Y = cross( v3Z, v3X ); - m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); - return orthoInverse( m4EyeFrame ); -} - -inline const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) -{ - float f, rangeInv; - f = tanf( ( (float)( _VECTORMATH_PI_OVER_2 ) - ( 0.5f * fovyRadians ) ) ); - rangeInv = ( 1.0f / ( zNear - zFar ) ); - return Matrix4( - Vector4( ( f / aspect ), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, f, 0.0f, 0.0f ), - Vector4( 0.0f, 0.0f, ( ( zNear + zFar ) * rangeInv ), -1.0f ), - Vector4( 0.0f, 0.0f, ( ( ( zNear * zFar ) * rangeInv ) * 2.0f ), 0.0f ) - ); -} - -inline const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) -{ - float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf, n2; - sum_rl = ( right + left ); - sum_tb = ( top + bottom ); - sum_nf = ( zNear + zFar ); - inv_rl = ( 1.0f / ( right - left ) ); - inv_tb = ( 1.0f / ( top - bottom ) ); - inv_nf = ( 1.0f / ( zNear - zFar ) ); - n2 = ( zNear + zNear ); - return Matrix4( - Vector4( ( n2 * inv_rl ), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, ( n2 * inv_tb ), 0.0f, 0.0f ), - Vector4( ( sum_rl * inv_rl ), ( sum_tb * inv_tb ), ( sum_nf * inv_nf ), -1.0f ), - Vector4( 0.0f, 0.0f, ( ( n2 * inv_nf ) * zFar ), 0.0f ) - ); -} - -inline const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) -{ - float sum_rl, sum_tb, sum_nf, inv_rl, inv_tb, inv_nf; - sum_rl = ( right + left ); - sum_tb = ( top + bottom ); - sum_nf = ( zNear + zFar ); - inv_rl = ( 1.0f / ( right - left ) ); - inv_tb = ( 1.0f / ( top - bottom ) ); - inv_nf = ( 1.0f / ( zNear - zFar ) ); - return Matrix4( - Vector4( ( inv_rl + inv_rl ), 0.0f, 0.0f, 0.0f ), - Vector4( 0.0f, ( inv_tb + inv_tb ), 0.0f, 0.0f ), - Vector4( 0.0f, 0.0f, ( inv_nf + inv_nf ), 0.0f ), - Vector4( ( -sum_rl * inv_rl ), ( -sum_tb * inv_tb ), ( sum_nf * inv_nf ), 1.0f ) - ); -} - -inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) -{ - return Matrix4( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ), - select( mat0.getCol3(), mat1.getCol3(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Matrix4 & mat ) -{ - print( mat.getRow( 0 ) ); - print( mat.getRow( 1 ) ); - print( mat.getRow( 2 ) ); - print( mat.getRow( 3 ) ); -} - -inline void print( const Matrix4 & mat, const char * name ) -{ - printf("%s:\n", name); - print( mat ); -} - -#endif - -inline Transform3::Transform3( const Transform3 & tfrm ) -{ - mCol0 = tfrm.mCol0; - mCol1 = tfrm.mCol1; - mCol2 = tfrm.mCol2; - mCol3 = tfrm.mCol3; -} - -inline Transform3::Transform3( float scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); - mCol3 = Vector3( scalar ); -} - -inline Transform3::Transform3( const Vector3 & _col0, const Vector3 & _col1, const Vector3 & _col2, const Vector3 & _col3 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; - mCol3 = _col3; -} - -inline Transform3::Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ) -{ - this->setUpper3x3( tfrm ); - this->setTranslation( translateVec ); -} - -inline Transform3::Transform3( const Quat & unitQuat, const Vector3 & translateVec ) -{ - this->setUpper3x3( Matrix3( unitQuat ) ); - this->setTranslation( translateVec ); -} - -inline Transform3 & Transform3::setCol0( const Vector3 & _col0 ) -{ - mCol0 = _col0; - return *this; -} - -inline Transform3 & Transform3::setCol1( const Vector3 & _col1 ) -{ - mCol1 = _col1; - return *this; -} - -inline Transform3 & Transform3::setCol2( const Vector3 & _col2 ) -{ - mCol2 = _col2; - return *this; -} - -inline Transform3 & Transform3::setCol3( const Vector3 & _col3 ) -{ - mCol3 = _col3; - return *this; -} - -inline Transform3 & Transform3::setCol( int col, const Vector3 & vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -inline Transform3 & Transform3::setRow( int row, const Vector4 & vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - mCol3.setElem( row, vec.getElem( 3 ) ); - return *this; -} - -inline Transform3 & Transform3::setElem( int col, int row, float val ) -{ - Vector3 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -inline float Transform3::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -inline const Vector3 Transform3::getCol0( ) const -{ - return mCol0; -} - -inline const Vector3 Transform3::getCol1( ) const -{ - return mCol1; -} - -inline const Vector3 Transform3::getCol2( ) const -{ - return mCol2; -} - -inline const Vector3 Transform3::getCol3( ) const -{ - return mCol3; -} - -inline const Vector3 Transform3::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -inline const Vector4 Transform3::getRow( int row ) const -{ - return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); -} - -inline Vector3 & Transform3::operator []( int col ) -{ - return *(&mCol0 + col); -} - -inline const Vector3 Transform3::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -inline Transform3 & Transform3::operator =( const Transform3 & tfrm ) -{ - mCol0 = tfrm.mCol0; - mCol1 = tfrm.mCol1; - mCol2 = tfrm.mCol2; - mCol3 = tfrm.mCol3; - return *this; -} - -inline const Transform3 inverse( const Transform3 & tfrm ) -{ - Vector3 tmp0, tmp1, tmp2, inv0, inv1, inv2; - float detinv; - tmp0 = cross( tfrm.getCol1(), tfrm.getCol2() ); - tmp1 = cross( tfrm.getCol2(), tfrm.getCol0() ); - tmp2 = cross( tfrm.getCol0(), tfrm.getCol1() ); - detinv = ( 1.0f / dot( tfrm.getCol2(), tmp2 ) ); - inv0 = Vector3( ( tmp0.getX() * detinv ), ( tmp1.getX() * detinv ), ( tmp2.getX() * detinv ) ); - inv1 = Vector3( ( tmp0.getY() * detinv ), ( tmp1.getY() * detinv ), ( tmp2.getY() * detinv ) ); - inv2 = Vector3( ( tmp0.getZ() * detinv ), ( tmp1.getZ() * detinv ), ( tmp2.getZ() * detinv ) ); - return Transform3( - inv0, - inv1, - inv2, - Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) - ); -} - -inline const Transform3 orthoInverse( const Transform3 & tfrm ) -{ - Vector3 inv0, inv1, inv2; - inv0 = Vector3( tfrm.getCol0().getX(), tfrm.getCol1().getX(), tfrm.getCol2().getX() ); - inv1 = Vector3( tfrm.getCol0().getY(), tfrm.getCol1().getY(), tfrm.getCol2().getY() ); - inv2 = Vector3( tfrm.getCol0().getZ(), tfrm.getCol1().getZ(), tfrm.getCol2().getZ() ); - return Transform3( - inv0, - inv1, - inv2, - Vector3( ( -( ( inv0 * tfrm.getCol3().getX() ) + ( ( inv1 * tfrm.getCol3().getY() ) + ( inv2 * tfrm.getCol3().getZ() ) ) ) ) ) - ); -} - -inline const Transform3 absPerElem( const Transform3 & tfrm ) -{ - return Transform3( - absPerElem( tfrm.getCol0() ), - absPerElem( tfrm.getCol1() ), - absPerElem( tfrm.getCol2() ), - absPerElem( tfrm.getCol3() ) - ); -} - -inline const Vector3 Transform3::operator *( const Vector3 & vec ) const -{ - return Vector3( - ( ( ( mCol0.getX() * vec.getX() ) + ( mCol1.getX() * vec.getY() ) ) + ( mCol2.getX() * vec.getZ() ) ), - ( ( ( mCol0.getY() * vec.getX() ) + ( mCol1.getY() * vec.getY() ) ) + ( mCol2.getY() * vec.getZ() ) ), - ( ( ( mCol0.getZ() * vec.getX() ) + ( mCol1.getZ() * vec.getY() ) ) + ( mCol2.getZ() * vec.getZ() ) ) - ); -} - -inline const Point3 Transform3::operator *( const Point3 & pnt ) const -{ - return Point3( - ( ( ( ( mCol0.getX() * pnt.getX() ) + ( mCol1.getX() * pnt.getY() ) ) + ( mCol2.getX() * pnt.getZ() ) ) + mCol3.getX() ), - ( ( ( ( mCol0.getY() * pnt.getX() ) + ( mCol1.getY() * pnt.getY() ) ) + ( mCol2.getY() * pnt.getZ() ) ) + mCol3.getY() ), - ( ( ( ( mCol0.getZ() * pnt.getX() ) + ( mCol1.getZ() * pnt.getY() ) ) + ( mCol2.getZ() * pnt.getZ() ) ) + mCol3.getZ() ) - ); -} - -inline const Transform3 Transform3::operator *( const Transform3 & tfrm ) const -{ - return Transform3( - ( *this * tfrm.mCol0 ), - ( *this * tfrm.mCol1 ), - ( *this * tfrm.mCol2 ), - Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) - ); -} - -inline Transform3 & Transform3::operator *=( const Transform3 & tfrm ) -{ - *this = *this * tfrm; - return *this; -} - -inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) -{ - return Transform3( - mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), - mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), - mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), - mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) - ); -} - -inline const Transform3 Transform3::identity( ) -{ - return Transform3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ), - Vector3( 0.0f ) - ); -} - -inline Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) -{ - mCol0 = tfrm.getCol0(); - mCol1 = tfrm.getCol1(); - mCol2 = tfrm.getCol2(); - return *this; -} - -inline const Matrix3 Transform3::getUpper3x3( ) const -{ - return Matrix3( mCol0, mCol1, mCol2 ); -} - -inline Transform3 & Transform3::setTranslation( const Vector3 & translateVec ) -{ - mCol3 = translateVec; - return *this; -} - -inline const Vector3 Transform3::getTranslation( ) const -{ - return mCol3; -} - -inline const Transform3 Transform3::rotationX( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Transform3( - Vector3::xAxis( ), - Vector3( 0.0f, c, s ), - Vector3( 0.0f, -s, c ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotationY( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Transform3( - Vector3( c, 0.0f, -s ), - Vector3::yAxis( ), - Vector3( s, 0.0f, c ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotationZ( float radians ) -{ - float s, c; - s = sinf( radians ); - c = cosf( radians ); - return Transform3( - Vector3( c, s, 0.0f ), - Vector3( -s, c, 0.0f ), - Vector3::zAxis( ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotationZYX( const Vector3 & radiansXYZ ) -{ - float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1; - sX = sinf( radiansXYZ.getX() ); - cX = cosf( radiansXYZ.getX() ); - sY = sinf( radiansXYZ.getY() ); - cY = cosf( radiansXYZ.getY() ); - sZ = sinf( radiansXYZ.getZ() ); - cZ = cosf( radiansXYZ.getZ() ); - tmp0 = ( cZ * sY ); - tmp1 = ( sZ * sY ); - return Transform3( - Vector3( ( cZ * cY ), ( sZ * cY ), -sY ), - Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ), - Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 Transform3::rotation( float radians, const Vector3 & unitVec ) -{ - return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); -} - -inline const Transform3 Transform3::rotation( const Quat & unitQuat ) -{ - return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); -} - -inline const Transform3 Transform3::scale( const Vector3 & scaleVec ) -{ - return Transform3( - Vector3( scaleVec.getX(), 0.0f, 0.0f ), - Vector3( 0.0f, scaleVec.getY(), 0.0f ), - Vector3( 0.0f, 0.0f, scaleVec.getZ() ), - Vector3( 0.0f ) - ); -} - -inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ) -{ - return Transform3( - ( tfrm.getCol0() * scaleVec.getX( ) ), - ( tfrm.getCol1() * scaleVec.getY( ) ), - ( tfrm.getCol2() * scaleVec.getZ( ) ), - tfrm.getCol3() - ); -} - -inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ) -{ - return Transform3( - mulPerElem( tfrm.getCol0(), scaleVec ), - mulPerElem( tfrm.getCol1(), scaleVec ), - mulPerElem( tfrm.getCol2(), scaleVec ), - mulPerElem( tfrm.getCol3(), scaleVec ) - ); -} - -inline const Transform3 Transform3::translation( const Vector3 & translateVec ) -{ - return Transform3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ), - translateVec - ); -} - -inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) -{ - return Transform3( - select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), - select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), - select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), - select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Transform3 & tfrm ) -{ - print( tfrm.getRow( 0 ) ); - print( tfrm.getRow( 1 ) ); - print( tfrm.getRow( 2 ) ); -} - -inline void print( const Transform3 & tfrm, const char * name ) -{ - printf("%s:\n", name); - print( tfrm ); -} - -#endif - -inline Quat::Quat( const Matrix3 & tfrm ) -{ - float trace, radicand, scale, xx, yx, zx, xy, yy, zy, xz, yz, zz, tmpx, tmpy, tmpz, tmpw, qx, qy, qz, qw; - int negTrace, ZgtX, ZgtY, YgtX; - int largestXorY, largestYorZ, largestZorX; - - xx = tfrm.getCol0().getX(); - yx = tfrm.getCol0().getY(); - zx = tfrm.getCol0().getZ(); - xy = tfrm.getCol1().getX(); - yy = tfrm.getCol1().getY(); - zy = tfrm.getCol1().getZ(); - xz = tfrm.getCol2().getX(); - yz = tfrm.getCol2().getY(); - zz = tfrm.getCol2().getZ(); - - trace = ( ( xx + yy ) + zz ); - - negTrace = ( trace < 0.0f ); - ZgtX = zz > xx; - ZgtY = zz > yy; - YgtX = yy > xx; - largestXorY = ( !ZgtX || !ZgtY ) && negTrace; - largestYorZ = ( YgtX || ZgtX ) && negTrace; - largestZorX = ( ZgtY || !YgtX ) && negTrace; - - if ( largestXorY ) - { - zz = -zz; - xy = -xy; - } - if ( largestYorZ ) - { - xx = -xx; - yz = -yz; - } - if ( largestZorX ) - { - yy = -yy; - zx = -zx; - } - - radicand = ( ( ( xx + yy ) + zz ) + 1.0f ); - scale = ( 0.5f * ( 1.0f / sqrtf( radicand ) ) ); - - tmpx = ( ( zy - yz ) * scale ); - tmpy = ( ( xz - zx ) * scale ); - tmpz = ( ( yx - xy ) * scale ); - tmpw = ( radicand * scale ); - qx = tmpx; - qy = tmpy; - qz = tmpz; - qw = tmpw; - - if ( largestXorY ) - { - qx = tmpw; - qy = tmpz; - qz = tmpy; - qw = tmpx; - } - if ( largestYorZ ) - { - tmpx = qx; - tmpz = qz; - qx = qy; - qy = tmpx; - qz = qw; - qw = tmpz; - } - - mX = qx; - mY = qy; - mZ = qz; - mW = qw; -} - -inline const Matrix3 outer( const Vector3 & tfrm0, const Vector3 & tfrm1 ) -{ - return Matrix3( - ( tfrm0 * tfrm1.getX( ) ), - ( tfrm0 * tfrm1.getY( ) ), - ( tfrm0 * tfrm1.getZ( ) ) - ); -} - -inline const Matrix4 outer( const Vector4 & tfrm0, const Vector4 & tfrm1 ) -{ - return Matrix4( - ( tfrm0 * tfrm1.getX( ) ), - ( tfrm0 * tfrm1.getY( ) ), - ( tfrm0 * tfrm1.getZ( ) ), - ( tfrm0 * tfrm1.getW( ) ) - ); -} - -inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ) -{ - return Vector3( - ( ( ( vec.getX() * mat.getCol0().getX() ) + ( vec.getY() * mat.getCol0().getY() ) ) + ( vec.getZ() * mat.getCol0().getZ() ) ), - ( ( ( vec.getX() * mat.getCol1().getX() ) + ( vec.getY() * mat.getCol1().getY() ) ) + ( vec.getZ() * mat.getCol1().getZ() ) ), - ( ( ( vec.getX() * mat.getCol2().getX() ) + ( vec.getY() * mat.getCol2().getY() ) ) + ( vec.getZ() * mat.getCol2().getZ() ) ) - ); -} - -inline const Matrix3 crossMatrix( const Vector3 & vec ) -{ - return Matrix3( - Vector3( 0.0f, vec.getZ(), -vec.getY() ), - Vector3( -vec.getZ(), 0.0f, vec.getX() ), - Vector3( vec.getY(), -vec.getX(), 0.0f ) - ); -} - -inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ) -{ - return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); -} - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/scalar/quat_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/quat_aos.h deleted file mode 100644 index 764e0170..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/scalar/quat_aos.h +++ /dev/null @@ -1,433 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_QUAT_AOS_CPP_H -#define _VECTORMATH_QUAT_AOS_CPP_H - -//----------------------------------------------------------------------------- -// Definitions - -#ifndef _VECTORMATH_INTERNAL_FUNCTIONS -#define _VECTORMATH_INTERNAL_FUNCTIONS - -#endif - -namespace Vectormath { -namespace Aos { - -inline Quat::Quat( const Quat & quat ) -{ - mX = quat.mX; - mY = quat.mY; - mZ = quat.mZ; - mW = quat.mW; -} - -inline Quat::Quat( float _x, float _y, float _z, float _w ) -{ - mX = _x; - mY = _y; - mZ = _z; - mW = _w; -} - -inline Quat::Quat( const Vector3 & xyz, float _w ) -{ - this->setXYZ( xyz ); - this->setW( _w ); -} - -inline Quat::Quat( const Vector4 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); - mW = vec.getW(); -} - -inline Quat::Quat( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; - mW = scalar; -} - -inline const Quat Quat::identity( ) -{ - return Quat( 0.0f, 0.0f, 0.0f, 1.0f ); -} - -inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ) -{ - return ( quat0 + ( ( quat1 - quat0 ) * t ) ); -} - -inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ) -{ - Quat start; - float recipSinAngle, scale0, scale1, cosAngle, angle; - cosAngle = dot( unitQuat0, unitQuat1 ); - if ( cosAngle < 0.0f ) { - cosAngle = -cosAngle; - start = ( -unitQuat0 ); - } else { - start = unitQuat0; - } - if ( cosAngle < _VECTORMATH_SLERP_TOL ) { - angle = acosf( cosAngle ); - recipSinAngle = ( 1.0f / sinf( angle ) ); - scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); - scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); - } else { - scale0 = ( 1.0f - t ); - scale1 = t; - } - return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); -} - -inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ) -{ - Quat tmp0, tmp1; - tmp0 = slerp( t, unitQuat0, unitQuat3 ); - tmp1 = slerp( t, unitQuat1, unitQuat2 ); - return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); -} - -inline void loadXYZW( Quat & quat, const float * fptr ) -{ - quat = Quat( fptr[0], fptr[1], fptr[2], fptr[3] ); -} - -inline void storeXYZW( const Quat & quat, float * fptr ) -{ - fptr[0] = quat.getX(); - fptr[1] = quat.getY(); - fptr[2] = quat.getZ(); - fptr[3] = quat.getW(); -} - -inline Quat & Quat::operator =( const Quat & quat ) -{ - mX = quat.mX; - mY = quat.mY; - mZ = quat.mZ; - mW = quat.mW; - return *this; -} - -inline Quat & Quat::setXYZ( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); - return *this; -} - -inline const Vector3 Quat::getXYZ( ) const -{ - return Vector3( mX, mY, mZ ); -} - -inline Quat & Quat::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Quat::getX( ) const -{ - return mX; -} - -inline Quat & Quat::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Quat::getY( ) const -{ - return mY; -} - -inline Quat & Quat::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Quat::getZ( ) const -{ - return mZ; -} - -inline Quat & Quat::setW( float _w ) -{ - mW = _w; - return *this; -} - -inline float Quat::getW( ) const -{ - return mW; -} - -inline Quat & Quat::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Quat::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Quat::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Quat::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Quat Quat::operator +( const Quat & quat ) const -{ - return Quat( - ( mX + quat.mX ), - ( mY + quat.mY ), - ( mZ + quat.mZ ), - ( mW + quat.mW ) - ); -} - -inline const Quat Quat::operator -( const Quat & quat ) const -{ - return Quat( - ( mX - quat.mX ), - ( mY - quat.mY ), - ( mZ - quat.mZ ), - ( mW - quat.mW ) - ); -} - -inline const Quat Quat::operator *( float scalar ) const -{ - return Quat( - ( mX * scalar ), - ( mY * scalar ), - ( mZ * scalar ), - ( mW * scalar ) - ); -} - -inline Quat & Quat::operator +=( const Quat & quat ) -{ - *this = *this + quat; - return *this; -} - -inline Quat & Quat::operator -=( const Quat & quat ) -{ - *this = *this - quat; - return *this; -} - -inline Quat & Quat::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Quat Quat::operator /( float scalar ) const -{ - return Quat( - ( mX / scalar ), - ( mY / scalar ), - ( mZ / scalar ), - ( mW / scalar ) - ); -} - -inline Quat & Quat::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -inline const Quat Quat::operator -( ) const -{ - return Quat( - -mX, - -mY, - -mZ, - -mW - ); -} - -inline const Quat operator *( float scalar, const Quat & quat ) -{ - return quat * scalar; -} - -inline float dot( const Quat & quat0, const Quat & quat1 ) -{ - float result; - result = ( quat0.getX() * quat1.getX() ); - result = ( result + ( quat0.getY() * quat1.getY() ) ); - result = ( result + ( quat0.getZ() * quat1.getZ() ) ); - result = ( result + ( quat0.getW() * quat1.getW() ) ); - return result; -} - -inline float norm( const Quat & quat ) -{ - float result; - result = ( quat.getX() * quat.getX() ); - result = ( result + ( quat.getY() * quat.getY() ) ); - result = ( result + ( quat.getZ() * quat.getZ() ) ); - result = ( result + ( quat.getW() * quat.getW() ) ); - return result; -} - -inline float length( const Quat & quat ) -{ - return ::sqrtf( norm( quat ) ); -} - -inline const Quat normalize( const Quat & quat ) -{ - float lenSqr, lenInv; - lenSqr = norm( quat ); - lenInv = ( 1.0f / sqrtf( lenSqr ) ); - return Quat( - ( quat.getX() * lenInv ), - ( quat.getY() * lenInv ), - ( quat.getZ() * lenInv ), - ( quat.getW() * lenInv ) - ); -} - -inline const Quat Quat::rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ) -{ - float cosHalfAngleX2, recipCosHalfAngleX2; - cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); - recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); - return Quat( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); -} - -inline const Quat Quat::rotation( float radians, const Vector3 & unitVec ) -{ - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( ( unitVec * s ), c ); -} - -inline const Quat Quat::rotationX( float radians ) -{ - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( s, 0.0f, 0.0f, c ); -} - -inline const Quat Quat::rotationY( float radians ) -{ - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( 0.0f, s, 0.0f, c ); -} - -inline const Quat Quat::rotationZ( float radians ) -{ - float s, c, angle; - angle = ( radians * 0.5f ); - s = sinf( angle ); - c = cosf( angle ); - return Quat( 0.0f, 0.0f, s, c ); -} - -inline const Quat Quat::operator *( const Quat & quat ) const -{ - return Quat( - ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), - ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), - ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), - ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) - ); -} - -inline Quat & Quat::operator *=( const Quat & quat ) -{ - *this = *this * quat; - return *this; -} - -inline const Vector3 rotate( const Quat & quat, const Vector3 & vec ) -{ - float tmpX, tmpY, tmpZ, tmpW; - tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); - tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); - tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); - tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); - return Vector3( - ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), - ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), - ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) - ); -} - -inline const Quat conj( const Quat & quat ) -{ - return Quat( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); -} - -inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ) -{ - return Quat( - ( select1 )? quat1.getX() : quat0.getX(), - ( select1 )? quat1.getY() : quat0.getY(), - ( select1 )? quat1.getZ() : quat0.getZ(), - ( select1 )? quat1.getW() : quat0.getW() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Quat & quat ) -{ - printf( "( %f %f %f %f )\n", quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); -} - -inline void print( const Quat & quat, const char * name ) -{ - printf( "%s: ( %f %f %f %f )\n", name, quat.getX(), quat.getY(), quat.getZ(), quat.getW() ); -} - -#endif - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/scalar/vec_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/vec_aos.h deleted file mode 100644 index 46d4d6b3..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/scalar/vec_aos.h +++ /dev/null @@ -1,1426 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_VEC_AOS_CPP_H -#define _VECTORMATH_VEC_AOS_CPP_H - -//----------------------------------------------------------------------------- -// Constants - -#define _VECTORMATH_SLERP_TOL 0.999f - -//----------------------------------------------------------------------------- -// Definitions - -#ifndef _VECTORMATH_INTERNAL_FUNCTIONS -#define _VECTORMATH_INTERNAL_FUNCTIONS - -#endif - -namespace Vectormath { -namespace Aos { - -inline Vector3::Vector3( const Vector3 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; -} - -inline Vector3::Vector3( float _x, float _y, float _z ) -{ - mX = _x; - mY = _y; - mZ = _z; -} - -inline Vector3::Vector3( const Point3 & pnt ) -{ - mX = pnt.getX(); - mY = pnt.getY(); - mZ = pnt.getZ(); -} - -inline Vector3::Vector3( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; -} - -inline const Vector3 Vector3::xAxis( ) -{ - return Vector3( 1.0f, 0.0f, 0.0f ); -} - -inline const Vector3 Vector3::yAxis( ) -{ - return Vector3( 0.0f, 1.0f, 0.0f ); -} - -inline const Vector3 Vector3::zAxis( ) -{ - return Vector3( 0.0f, 0.0f, 1.0f ); -} - -inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ) -{ - return ( vec0 + ( ( vec1 - vec0 ) * t ) ); -} - -inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ) -{ - float recipSinAngle, scale0, scale1, cosAngle, angle; - cosAngle = dot( unitVec0, unitVec1 ); - if ( cosAngle < _VECTORMATH_SLERP_TOL ) { - angle = acosf( cosAngle ); - recipSinAngle = ( 1.0f / sinf( angle ) ); - scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); - scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); - } else { - scale0 = ( 1.0f - t ); - scale1 = t; - } - return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); -} - -inline void loadXYZ( Vector3 & vec, const float * fptr ) -{ - vec = Vector3( fptr[0], fptr[1], fptr[2] ); -} - -inline void storeXYZ( const Vector3 & vec, float * fptr ) -{ - fptr[0] = vec.getX(); - fptr[1] = vec.getY(); - fptr[2] = vec.getZ(); -} - -inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - unsigned short fp16 = hfptr[i]; - unsigned int sign = fp16 >> 15; - unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); - unsigned int mantissa = fp16 & ((1 << 10) - 1); - - if (exponent == 0) { - // zero - mantissa = 0; - - } else if (exponent == 31) { - // infinity or nan -> infinity - exponent = 255; - mantissa = 0; - - } else { - exponent += 127 - 15; - mantissa <<= 13; - } - - Data32 d; - d.u32 = (sign << 31) | (exponent << 23) | mantissa; - vec[i] = d.f32; - } -} - -inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - Data32 d; - d.f32 = vec[i]; - - unsigned int sign = d.u32 >> 31; - unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); - unsigned int mantissa = d.u32 & ((1 << 23) - 1);; - - if (exponent == 0) { - // zero or denorm -> zero - mantissa = 0; - - } else if (exponent == 255 && mantissa != 0) { - // nan -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent >= 127 - 15 + 31) { - // overflow or infinity -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent <= 127 - 15) { - // underflow -> zero - exponent = 0; - mantissa = 0; - - } else { - exponent -= 127 - 15; - mantissa >>= 13; - } - - hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); - } -} - -inline Vector3 & Vector3::operator =( const Vector3 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; - return *this; -} - -inline Vector3 & Vector3::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Vector3::getX( ) const -{ - return mX; -} - -inline Vector3 & Vector3::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Vector3::getY( ) const -{ - return mY; -} - -inline Vector3 & Vector3::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Vector3::getZ( ) const -{ - return mZ; -} - -inline Vector3 & Vector3::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Vector3::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Vector3::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Vector3::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Vector3 Vector3::operator +( const Vector3 & vec ) const -{ - return Vector3( - ( mX + vec.mX ), - ( mY + vec.mY ), - ( mZ + vec.mZ ) - ); -} - -inline const Vector3 Vector3::operator -( const Vector3 & vec ) const -{ - return Vector3( - ( mX - vec.mX ), - ( mY - vec.mY ), - ( mZ - vec.mZ ) - ); -} - -inline const Point3 Vector3::operator +( const Point3 & pnt ) const -{ - return Point3( - ( mX + pnt.getX() ), - ( mY + pnt.getY() ), - ( mZ + pnt.getZ() ) - ); -} - -inline const Vector3 Vector3::operator *( float scalar ) const -{ - return Vector3( - ( mX * scalar ), - ( mY * scalar ), - ( mZ * scalar ) - ); -} - -inline Vector3 & Vector3::operator +=( const Vector3 & vec ) -{ - *this = *this + vec; - return *this; -} - -inline Vector3 & Vector3::operator -=( const Vector3 & vec ) -{ - *this = *this - vec; - return *this; -} - -inline Vector3 & Vector3::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Vector3 Vector3::operator /( float scalar ) const -{ - return Vector3( - ( mX / scalar ), - ( mY / scalar ), - ( mZ / scalar ) - ); -} - -inline Vector3 & Vector3::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -inline const Vector3 Vector3::operator -( ) const -{ - return Vector3( - -mX, - -mY, - -mZ - ); -} - -inline const Vector3 operator *( float scalar, const Vector3 & vec ) -{ - return vec * scalar; -} - -inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( vec0.getX() * vec1.getX() ), - ( vec0.getY() * vec1.getY() ), - ( vec0.getZ() * vec1.getZ() ) - ); -} - -inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( vec0.getX() / vec1.getX() ), - ( vec0.getY() / vec1.getY() ), - ( vec0.getZ() / vec1.getZ() ) - ); -} - -inline const Vector3 recipPerElem( const Vector3 & vec ) -{ - return Vector3( - ( 1.0f / vec.getX() ), - ( 1.0f / vec.getY() ), - ( 1.0f / vec.getZ() ) - ); -} - -inline const Vector3 sqrtPerElem( const Vector3 & vec ) -{ - return Vector3( - sqrtf( vec.getX() ), - sqrtf( vec.getY() ), - sqrtf( vec.getZ() ) - ); -} - -inline const Vector3 rsqrtPerElem( const Vector3 & vec ) -{ - return Vector3( - ( 1.0f / sqrtf( vec.getX() ) ), - ( 1.0f / sqrtf( vec.getY() ) ), - ( 1.0f / sqrtf( vec.getZ() ) ) - ); -} - -inline const Vector3 absPerElem( const Vector3 & vec ) -{ - return Vector3( - fabsf( vec.getX() ), - fabsf( vec.getY() ), - fabsf( vec.getZ() ) - ); -} - -inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), - ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), - ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ) - ); -} - -inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ() - ); -} - -inline float maxElem( const Vector3 & vec ) -{ - float result; - result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() > result)? vec.getZ() : result; - return result; -} - -inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ() - ); -} - -inline float minElem( const Vector3 & vec ) -{ - float result; - result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() < result)? vec.getZ() : result; - return result; -} - -inline float sum( const Vector3 & vec ) -{ - float result; - result = ( vec.getX() + vec.getY() ); - result = ( result + vec.getZ() ); - return result; -} - -inline float dot( const Vector3 & vec0, const Vector3 & vec1 ) -{ - float result; - result = ( vec0.getX() * vec1.getX() ); - result = ( result + ( vec0.getY() * vec1.getY() ) ); - result = ( result + ( vec0.getZ() * vec1.getZ() ) ); - return result; -} - -inline float lengthSqr( const Vector3 & vec ) -{ - float result; - result = ( vec.getX() * vec.getX() ); - result = ( result + ( vec.getY() * vec.getY() ) ); - result = ( result + ( vec.getZ() * vec.getZ() ) ); - return result; -} - -inline float length( const Vector3 & vec ) -{ - return ::sqrtf( lengthSqr( vec ) ); -} - -inline const Vector3 normalize( const Vector3 & vec ) -{ - float lenSqr, lenInv; - lenSqr = lengthSqr( vec ); - lenInv = ( 1.0f / sqrtf( lenSqr ) ); - return Vector3( - ( vec.getX() * lenInv ), - ( vec.getY() * lenInv ), - ( vec.getZ() * lenInv ) - ); -} - -inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ) -{ - return Vector3( - ( ( vec0.getY() * vec1.getZ() ) - ( vec0.getZ() * vec1.getY() ) ), - ( ( vec0.getZ() * vec1.getX() ) - ( vec0.getX() * vec1.getZ() ) ), - ( ( vec0.getX() * vec1.getY() ) - ( vec0.getY() * vec1.getX() ) ) - ); -} - -inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ) -{ - return Vector3( - ( select1 )? vec1.getX() : vec0.getX(), - ( select1 )? vec1.getY() : vec0.getY(), - ( select1 )? vec1.getZ() : vec0.getZ() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Vector3 & vec ) -{ - printf( "( %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ() ); -} - -inline void print( const Vector3 & vec, const char * name ) -{ - printf( "%s: ( %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ() ); -} - -#endif - -inline Vector4::Vector4( const Vector4 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; - mW = vec.mW; -} - -inline Vector4::Vector4( float _x, float _y, float _z, float _w ) -{ - mX = _x; - mY = _y; - mZ = _z; - mW = _w; -} - -inline Vector4::Vector4( const Vector3 & xyz, float _w ) -{ - this->setXYZ( xyz ); - this->setW( _w ); -} - -inline Vector4::Vector4( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); - mW = 0.0f; -} - -inline Vector4::Vector4( const Point3 & pnt ) -{ - mX = pnt.getX(); - mY = pnt.getY(); - mZ = pnt.getZ(); - mW = 1.0f; -} - -inline Vector4::Vector4( const Quat & quat ) -{ - mX = quat.getX(); - mY = quat.getY(); - mZ = quat.getZ(); - mW = quat.getW(); -} - -inline Vector4::Vector4( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; - mW = scalar; -} - -inline const Vector4 Vector4::xAxis( ) -{ - return Vector4( 1.0f, 0.0f, 0.0f, 0.0f ); -} - -inline const Vector4 Vector4::yAxis( ) -{ - return Vector4( 0.0f, 1.0f, 0.0f, 0.0f ); -} - -inline const Vector4 Vector4::zAxis( ) -{ - return Vector4( 0.0f, 0.0f, 1.0f, 0.0f ); -} - -inline const Vector4 Vector4::wAxis( ) -{ - return Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); -} - -inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ) -{ - return ( vec0 + ( ( vec1 - vec0 ) * t ) ); -} - -inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ) -{ - float recipSinAngle, scale0, scale1, cosAngle, angle; - cosAngle = dot( unitVec0, unitVec1 ); - if ( cosAngle < _VECTORMATH_SLERP_TOL ) { - angle = acosf( cosAngle ); - recipSinAngle = ( 1.0f / sinf( angle ) ); - scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); - scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); - } else { - scale0 = ( 1.0f - t ); - scale1 = t; - } - return ( ( unitVec0 * scale0 ) + ( unitVec1 * scale1 ) ); -} - -inline void loadXYZW( Vector4 & vec, const float * fptr ) -{ - vec = Vector4( fptr[0], fptr[1], fptr[2], fptr[3] ); -} - -inline void storeXYZW( const Vector4 & vec, float * fptr ) -{ - fptr[0] = vec.getX(); - fptr[1] = vec.getY(); - fptr[2] = vec.getZ(); - fptr[3] = vec.getW(); -} - -inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 4; i++) { - unsigned short fp16 = hfptr[i]; - unsigned int sign = fp16 >> 15; - unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); - unsigned int mantissa = fp16 & ((1 << 10) - 1); - - if (exponent == 0) { - // zero - mantissa = 0; - - } else if (exponent == 31) { - // infinity or nan -> infinity - exponent = 255; - mantissa = 0; - - } else { - exponent += 127 - 15; - mantissa <<= 13; - } - - Data32 d; - d.u32 = (sign << 31) | (exponent << 23) | mantissa; - vec[i] = d.f32; - } -} - -inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 4; i++) { - Data32 d; - d.f32 = vec[i]; - - unsigned int sign = d.u32 >> 31; - unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); - unsigned int mantissa = d.u32 & ((1 << 23) - 1);; - - if (exponent == 0) { - // zero or denorm -> zero - mantissa = 0; - - } else if (exponent == 255 && mantissa != 0) { - // nan -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent >= 127 - 15 + 31) { - // overflow or infinity -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent <= 127 - 15) { - // underflow -> zero - exponent = 0; - mantissa = 0; - - } else { - exponent -= 127 - 15; - mantissa >>= 13; - } - - hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); - } -} - -inline Vector4 & Vector4::operator =( const Vector4 & vec ) -{ - mX = vec.mX; - mY = vec.mY; - mZ = vec.mZ; - mW = vec.mW; - return *this; -} - -inline Vector4 & Vector4::setXYZ( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); - return *this; -} - -inline const Vector3 Vector4::getXYZ( ) const -{ - return Vector3( mX, mY, mZ ); -} - -inline Vector4 & Vector4::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Vector4::getX( ) const -{ - return mX; -} - -inline Vector4 & Vector4::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Vector4::getY( ) const -{ - return mY; -} - -inline Vector4 & Vector4::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Vector4::getZ( ) const -{ - return mZ; -} - -inline Vector4 & Vector4::setW( float _w ) -{ - mW = _w; - return *this; -} - -inline float Vector4::getW( ) const -{ - return mW; -} - -inline Vector4 & Vector4::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Vector4::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Vector4::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Vector4::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Vector4 Vector4::operator +( const Vector4 & vec ) const -{ - return Vector4( - ( mX + vec.mX ), - ( mY + vec.mY ), - ( mZ + vec.mZ ), - ( mW + vec.mW ) - ); -} - -inline const Vector4 Vector4::operator -( const Vector4 & vec ) const -{ - return Vector4( - ( mX - vec.mX ), - ( mY - vec.mY ), - ( mZ - vec.mZ ), - ( mW - vec.mW ) - ); -} - -inline const Vector4 Vector4::operator *( float scalar ) const -{ - return Vector4( - ( mX * scalar ), - ( mY * scalar ), - ( mZ * scalar ), - ( mW * scalar ) - ); -} - -inline Vector4 & Vector4::operator +=( const Vector4 & vec ) -{ - *this = *this + vec; - return *this; -} - -inline Vector4 & Vector4::operator -=( const Vector4 & vec ) -{ - *this = *this - vec; - return *this; -} - -inline Vector4 & Vector4::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -inline const Vector4 Vector4::operator /( float scalar ) const -{ - return Vector4( - ( mX / scalar ), - ( mY / scalar ), - ( mZ / scalar ), - ( mW / scalar ) - ); -} - -inline Vector4 & Vector4::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -inline const Vector4 Vector4::operator -( ) const -{ - return Vector4( - -mX, - -mY, - -mZ, - -mW - ); -} - -inline const Vector4 operator *( float scalar, const Vector4 & vec ) -{ - return vec * scalar; -} - -inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - ( vec0.getX() * vec1.getX() ), - ( vec0.getY() * vec1.getY() ), - ( vec0.getZ() * vec1.getZ() ), - ( vec0.getW() * vec1.getW() ) - ); -} - -inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - ( vec0.getX() / vec1.getX() ), - ( vec0.getY() / vec1.getY() ), - ( vec0.getZ() / vec1.getZ() ), - ( vec0.getW() / vec1.getW() ) - ); -} - -inline const Vector4 recipPerElem( const Vector4 & vec ) -{ - return Vector4( - ( 1.0f / vec.getX() ), - ( 1.0f / vec.getY() ), - ( 1.0f / vec.getZ() ), - ( 1.0f / vec.getW() ) - ); -} - -inline const Vector4 sqrtPerElem( const Vector4 & vec ) -{ - return Vector4( - sqrtf( vec.getX() ), - sqrtf( vec.getY() ), - sqrtf( vec.getZ() ), - sqrtf( vec.getW() ) - ); -} - -inline const Vector4 rsqrtPerElem( const Vector4 & vec ) -{ - return Vector4( - ( 1.0f / sqrtf( vec.getX() ) ), - ( 1.0f / sqrtf( vec.getY() ) ), - ( 1.0f / sqrtf( vec.getZ() ) ), - ( 1.0f / sqrtf( vec.getW() ) ) - ); -} - -inline const Vector4 absPerElem( const Vector4 & vec ) -{ - return Vector4( - fabsf( vec.getX() ), - fabsf( vec.getY() ), - fabsf( vec.getZ() ), - fabsf( vec.getW() ) - ); -} - -inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - ( vec1.getX() < 0.0f )? -fabsf( vec0.getX() ) : fabsf( vec0.getX() ), - ( vec1.getY() < 0.0f )? -fabsf( vec0.getY() ) : fabsf( vec0.getY() ), - ( vec1.getZ() < 0.0f )? -fabsf( vec0.getZ() ) : fabsf( vec0.getZ() ), - ( vec1.getW() < 0.0f )? -fabsf( vec0.getW() ) : fabsf( vec0.getW() ) - ); -} - -inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - (vec0.getX() > vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() > vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() > vec1.getZ())? vec0.getZ() : vec1.getZ(), - (vec0.getW() > vec1.getW())? vec0.getW() : vec1.getW() - ); -} - -inline float maxElem( const Vector4 & vec ) -{ - float result; - result = (vec.getX() > vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() > result)? vec.getZ() : result; - result = (vec.getW() > result)? vec.getW() : result; - return result; -} - -inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ) -{ - return Vector4( - (vec0.getX() < vec1.getX())? vec0.getX() : vec1.getX(), - (vec0.getY() < vec1.getY())? vec0.getY() : vec1.getY(), - (vec0.getZ() < vec1.getZ())? vec0.getZ() : vec1.getZ(), - (vec0.getW() < vec1.getW())? vec0.getW() : vec1.getW() - ); -} - -inline float minElem( const Vector4 & vec ) -{ - float result; - result = (vec.getX() < vec.getY())? vec.getX() : vec.getY(); - result = (vec.getZ() < result)? vec.getZ() : result; - result = (vec.getW() < result)? vec.getW() : result; - return result; -} - -inline float sum( const Vector4 & vec ) -{ - float result; - result = ( vec.getX() + vec.getY() ); - result = ( result + vec.getZ() ); - result = ( result + vec.getW() ); - return result; -} - -inline float dot( const Vector4 & vec0, const Vector4 & vec1 ) -{ - float result; - result = ( vec0.getX() * vec1.getX() ); - result = ( result + ( vec0.getY() * vec1.getY() ) ); - result = ( result + ( vec0.getZ() * vec1.getZ() ) ); - result = ( result + ( vec0.getW() * vec1.getW() ) ); - return result; -} - -inline float lengthSqr( const Vector4 & vec ) -{ - float result; - result = ( vec.getX() * vec.getX() ); - result = ( result + ( vec.getY() * vec.getY() ) ); - result = ( result + ( vec.getZ() * vec.getZ() ) ); - result = ( result + ( vec.getW() * vec.getW() ) ); - return result; -} - -inline float length( const Vector4 & vec ) -{ - return ::sqrtf( lengthSqr( vec ) ); -} - -inline const Vector4 normalize( const Vector4 & vec ) -{ - float lenSqr, lenInv; - lenSqr = lengthSqr( vec ); - lenInv = ( 1.0f / sqrtf( lenSqr ) ); - return Vector4( - ( vec.getX() * lenInv ), - ( vec.getY() * lenInv ), - ( vec.getZ() * lenInv ), - ( vec.getW() * lenInv ) - ); -} - -inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ) -{ - return Vector4( - ( select1 )? vec1.getX() : vec0.getX(), - ( select1 )? vec1.getY() : vec0.getY(), - ( select1 )? vec1.getZ() : vec0.getZ(), - ( select1 )? vec1.getW() : vec0.getW() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Vector4 & vec ) -{ - printf( "( %f %f %f %f )\n", vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); -} - -inline void print( const Vector4 & vec, const char * name ) -{ - printf( "%s: ( %f %f %f %f )\n", name, vec.getX(), vec.getY(), vec.getZ(), vec.getW() ); -} - -#endif - -inline Point3::Point3( const Point3 & pnt ) -{ - mX = pnt.mX; - mY = pnt.mY; - mZ = pnt.mZ; -} - -inline Point3::Point3( float _x, float _y, float _z ) -{ - mX = _x; - mY = _y; - mZ = _z; -} - -inline Point3::Point3( const Vector3 & vec ) -{ - mX = vec.getX(); - mY = vec.getY(); - mZ = vec.getZ(); -} - -inline Point3::Point3( float scalar ) -{ - mX = scalar; - mY = scalar; - mZ = scalar; -} - -inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ) -{ - return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); -} - -inline void loadXYZ( Point3 & pnt, const float * fptr ) -{ - pnt = Point3( fptr[0], fptr[1], fptr[2] ); -} - -inline void storeXYZ( const Point3 & pnt, float * fptr ) -{ - fptr[0] = pnt.getX(); - fptr[1] = pnt.getY(); - fptr[2] = pnt.getZ(); -} - -inline void loadHalfFloats( Point3 & vec, const unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - unsigned short fp16 = hfptr[i]; - unsigned int sign = fp16 >> 15; - unsigned int exponent = (fp16 >> 10) & ((1 << 5) - 1); - unsigned int mantissa = fp16 & ((1 << 10) - 1); - - if (exponent == 0) { - // zero - mantissa = 0; - - } else if (exponent == 31) { - // infinity or nan -> infinity - exponent = 255; - mantissa = 0; - - } else { - exponent += 127 - 15; - mantissa <<= 13; - } - - Data32 d; - d.u32 = (sign << 31) | (exponent << 23) | mantissa; - vec[i] = d.f32; - } -} - -inline void storeHalfFloats( const Point3 & vec, unsigned short * hfptr ) -{ - union Data32 { - unsigned int u32; - float f32; - }; - - for (int i = 0; i < 3; i++) { - Data32 d; - d.f32 = vec[i]; - - unsigned int sign = d.u32 >> 31; - unsigned int exponent = (d.u32 >> 23) & ((1 << 8) - 1); - unsigned int mantissa = d.u32 & ((1 << 23) - 1);; - - if (exponent == 0) { - // zero or denorm -> zero - mantissa = 0; - - } else if (exponent == 255 && mantissa != 0) { - // nan -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent >= 127 - 15 + 31) { - // overflow or infinity -> infinity - exponent = 31; - mantissa = 0; - - } else if (exponent <= 127 - 15) { - // underflow -> zero - exponent = 0; - mantissa = 0; - - } else { - exponent -= 127 - 15; - mantissa >>= 13; - } - - hfptr[i] = (unsigned short)((sign << 15) | (exponent << 10) | mantissa); - } -} - -inline Point3 & Point3::operator =( const Point3 & pnt ) -{ - mX = pnt.mX; - mY = pnt.mY; - mZ = pnt.mZ; - return *this; -} - -inline Point3 & Point3::setX( float _x ) -{ - mX = _x; - return *this; -} - -inline float Point3::getX( ) const -{ - return mX; -} - -inline Point3 & Point3::setY( float _y ) -{ - mY = _y; - return *this; -} - -inline float Point3::getY( ) const -{ - return mY; -} - -inline Point3 & Point3::setZ( float _z ) -{ - mZ = _z; - return *this; -} - -inline float Point3::getZ( ) const -{ - return mZ; -} - -inline Point3 & Point3::setElem( int idx, float value ) -{ - *(&mX + idx) = value; - return *this; -} - -inline float Point3::getElem( int idx ) const -{ - return *(&mX + idx); -} - -inline float & Point3::operator []( int idx ) -{ - return *(&mX + idx); -} - -inline float Point3::operator []( int idx ) const -{ - return *(&mX + idx); -} - -inline const Vector3 Point3::operator -( const Point3 & pnt ) const -{ - return Vector3( - ( mX - pnt.mX ), - ( mY - pnt.mY ), - ( mZ - pnt.mZ ) - ); -} - -inline const Point3 Point3::operator +( const Vector3 & vec ) const -{ - return Point3( - ( mX + vec.getX() ), - ( mY + vec.getY() ), - ( mZ + vec.getZ() ) - ); -} - -inline const Point3 Point3::operator -( const Vector3 & vec ) const -{ - return Point3( - ( mX - vec.getX() ), - ( mY - vec.getY() ), - ( mZ - vec.getZ() ) - ); -} - -inline Point3 & Point3::operator +=( const Vector3 & vec ) -{ - *this = *this + vec; - return *this; -} - -inline Point3 & Point3::operator -=( const Vector3 & vec ) -{ - *this = *this - vec; - return *this; -} - -inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - ( pnt0.getX() * pnt1.getX() ), - ( pnt0.getY() * pnt1.getY() ), - ( pnt0.getZ() * pnt1.getZ() ) - ); -} - -inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - ( pnt0.getX() / pnt1.getX() ), - ( pnt0.getY() / pnt1.getY() ), - ( pnt0.getZ() / pnt1.getZ() ) - ); -} - -inline const Point3 recipPerElem( const Point3 & pnt ) -{ - return Point3( - ( 1.0f / pnt.getX() ), - ( 1.0f / pnt.getY() ), - ( 1.0f / pnt.getZ() ) - ); -} - -inline const Point3 sqrtPerElem( const Point3 & pnt ) -{ - return Point3( - sqrtf( pnt.getX() ), - sqrtf( pnt.getY() ), - sqrtf( pnt.getZ() ) - ); -} - -inline const Point3 rsqrtPerElem( const Point3 & pnt ) -{ - return Point3( - ( 1.0f / sqrtf( pnt.getX() ) ), - ( 1.0f / sqrtf( pnt.getY() ) ), - ( 1.0f / sqrtf( pnt.getZ() ) ) - ); -} - -inline const Point3 absPerElem( const Point3 & pnt ) -{ - return Point3( - fabsf( pnt.getX() ), - fabsf( pnt.getY() ), - fabsf( pnt.getZ() ) - ); -} - -inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - ( pnt1.getX() < 0.0f )? -fabsf( pnt0.getX() ) : fabsf( pnt0.getX() ), - ( pnt1.getY() < 0.0f )? -fabsf( pnt0.getY() ) : fabsf( pnt0.getY() ), - ( pnt1.getZ() < 0.0f )? -fabsf( pnt0.getZ() ) : fabsf( pnt0.getZ() ) - ); -} - -inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - (pnt0.getX() > pnt1.getX())? pnt0.getX() : pnt1.getX(), - (pnt0.getY() > pnt1.getY())? pnt0.getY() : pnt1.getY(), - (pnt0.getZ() > pnt1.getZ())? pnt0.getZ() : pnt1.getZ() - ); -} - -inline float maxElem( const Point3 & pnt ) -{ - float result; - result = (pnt.getX() > pnt.getY())? pnt.getX() : pnt.getY(); - result = (pnt.getZ() > result)? pnt.getZ() : result; - return result; -} - -inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return Point3( - (pnt0.getX() < pnt1.getX())? pnt0.getX() : pnt1.getX(), - (pnt0.getY() < pnt1.getY())? pnt0.getY() : pnt1.getY(), - (pnt0.getZ() < pnt1.getZ())? pnt0.getZ() : pnt1.getZ() - ); -} - -inline float minElem( const Point3 & pnt ) -{ - float result; - result = (pnt.getX() < pnt.getY())? pnt.getX() : pnt.getY(); - result = (pnt.getZ() < result)? pnt.getZ() : result; - return result; -} - -inline float sum( const Point3 & pnt ) -{ - float result; - result = ( pnt.getX() + pnt.getY() ); - result = ( result + pnt.getZ() ); - return result; -} - -inline const Point3 scale( const Point3 & pnt, float scaleVal ) -{ - return mulPerElem( pnt, Point3( scaleVal ) ); -} - -inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ) -{ - return mulPerElem( pnt, Point3( scaleVec ) ); -} - -inline float projection( const Point3 & pnt, const Vector3 & unitVec ) -{ - float result; - result = ( pnt.getX() * unitVec.getX() ); - result = ( result + ( pnt.getY() * unitVec.getY() ) ); - result = ( result + ( pnt.getZ() * unitVec.getZ() ) ); - return result; -} - -inline float distSqrFromOrigin( const Point3 & pnt ) -{ - return lengthSqr( Vector3( pnt ) ); -} - -inline float distFromOrigin( const Point3 & pnt ) -{ - return length( Vector3( pnt ) ); -} - -inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return lengthSqr( ( pnt1 - pnt0 ) ); -} - -inline float dist( const Point3 & pnt0, const Point3 & pnt1 ) -{ - return length( ( pnt1 - pnt0 ) ); -} - -inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ) -{ - return Point3( - ( select1 )? pnt1.getX() : pnt0.getX(), - ( select1 )? pnt1.getY() : pnt0.getY(), - ( select1 )? pnt1.getZ() : pnt0.getZ() - ); -} - -#ifdef _VECTORMATH_DEBUG - -inline void print( const Point3 & pnt ) -{ - printf( "( %f %f %f )\n", pnt.getX(), pnt.getY(), pnt.getZ() ); -} - -inline void print( const Point3 & pnt, const char * name ) -{ - printf( "%s: ( %f %f %f )\n", name, pnt.getX(), pnt.getY(), pnt.getZ() ); -} - -#endif - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/scalar/vectormath_aos.h b/Code/Physics/Bullet Source/src/vectormath/scalar/vectormath_aos.h deleted file mode 100644 index d00456df..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/scalar/vectormath_aos.h +++ /dev/null @@ -1,1872 +0,0 @@ -/* - Copyright (C) 2009 Sony Computer Entertainment Inc. - All rights reserved. - -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 _VECTORMATH_AOS_CPP_H -#define _VECTORMATH_AOS_CPP_H - -#include - -#ifdef _VECTORMATH_DEBUG -#include -#endif - -namespace Vectormath { - -namespace Aos { - -//----------------------------------------------------------------------------- -// Forward Declarations -// - -class Vector3; -class Vector4; -class Point3; -class Quat; -class Matrix3; -class Matrix4; -class Transform3; - -// A 3-D vector in array-of-structures format -// -class Vector3 -{ - float mX; - float mY; - float mZ; -#ifndef __GNUC__ - float d; -#endif - -public: - // Default constructor; does no initialization - // - inline Vector3( ) { }; - - // Copy a 3-D vector - // - inline Vector3( const Vector3 & vec ); - - // Construct a 3-D vector from x, y, and z elements - // - inline Vector3( float x, float y, float z ); - - // Copy elements from a 3-D point into a 3-D vector - // - explicit inline Vector3( const Point3 & pnt ); - - // Set all elements of a 3-D vector to the same scalar value - // - explicit inline Vector3( float scalar ); - - // Assign one 3-D vector to another - // - inline Vector3 & operator =( const Vector3 & vec ); - - // Set the x element of a 3-D vector - // - inline Vector3 & setX( float x ); - - // Set the y element of a 3-D vector - // - inline Vector3 & setY( float y ); - - // Set the z element of a 3-D vector - // - inline Vector3 & setZ( float z ); - - // Get the x element of a 3-D vector - // - inline float getX( ) const; - - // Get the y element of a 3-D vector - // - inline float getY( ) const; - - // Get the z element of a 3-D vector - // - inline float getZ( ) const; - - // Set an x, y, or z element of a 3-D vector by index - // - inline Vector3 & setElem( int idx, float value ); - - // Get an x, y, or z element of a 3-D vector by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Add two 3-D vectors - // - inline const Vector3 operator +( const Vector3 & vec ) const; - - // Subtract a 3-D vector from another 3-D vector - // - inline const Vector3 operator -( const Vector3 & vec ) const; - - // Add a 3-D vector to a 3-D point - // - inline const Point3 operator +( const Point3 & pnt ) const; - - // Multiply a 3-D vector by a scalar - // - inline const Vector3 operator *( float scalar ) const; - - // Divide a 3-D vector by a scalar - // - inline const Vector3 operator /( float scalar ) const; - - // Perform compound assignment and addition with a 3-D vector - // - inline Vector3 & operator +=( const Vector3 & vec ); - - // Perform compound assignment and subtraction by a 3-D vector - // - inline Vector3 & operator -=( const Vector3 & vec ); - - // Perform compound assignment and multiplication by a scalar - // - inline Vector3 & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - inline Vector3 & operator /=( float scalar ); - - // Negate all elements of a 3-D vector - // - inline const Vector3 operator -( ) const; - - // Construct x axis - // - static inline const Vector3 xAxis( ); - - // Construct y axis - // - static inline const Vector3 yAxis( ); - - // Construct z axis - // - static inline const Vector3 zAxis( ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply a 3-D vector by a scalar -// -inline const Vector3 operator *( float scalar, const Vector3 & vec ); - -// Multiply two 3-D vectors per element -// -inline const Vector3 mulPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Divide two 3-D vectors per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -inline const Vector3 divPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Compute the reciprocal of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -inline const Vector3 recipPerElem( const Vector3 & vec ); - -// Compute the square root of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function sqrtf4. -// -inline const Vector3 sqrtPerElem( const Vector3 & vec ); - -// Compute the reciprocal square root of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function rsqrtf4. -// -inline const Vector3 rsqrtPerElem( const Vector3 & vec ); - -// Compute the absolute value of a 3-D vector per element -// -inline const Vector3 absPerElem( const Vector3 & vec ); - -// Copy sign from one 3-D vector to another, per element -// -inline const Vector3 copySignPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Maximum of two 3-D vectors per element -// -inline const Vector3 maxPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Minimum of two 3-D vectors per element -// -inline const Vector3 minPerElem( const Vector3 & vec0, const Vector3 & vec1 ); - -// Maximum element of a 3-D vector -// -inline float maxElem( const Vector3 & vec ); - -// Minimum element of a 3-D vector -// -inline float minElem( const Vector3 & vec ); - -// Compute the sum of all elements of a 3-D vector -// -inline float sum( const Vector3 & vec ); - -// Compute the dot product of two 3-D vectors -// -inline float dot( const Vector3 & vec0, const Vector3 & vec1 ); - -// Compute the square of the length of a 3-D vector -// -inline float lengthSqr( const Vector3 & vec ); - -// Compute the length of a 3-D vector -// -inline float length( const Vector3 & vec ); - -// Normalize a 3-D vector -// NOTE: -// The result is unpredictable when all elements of vec are at or near zero. -// -inline const Vector3 normalize( const Vector3 & vec ); - -// Compute cross product of two 3-D vectors -// -inline const Vector3 cross( const Vector3 & vec0, const Vector3 & vec1 ); - -// Outer product of two 3-D vectors -// -inline const Matrix3 outer( const Vector3 & vec0, const Vector3 & vec1 ); - -// Pre-multiply a row vector by a 3x3 matrix -// -inline const Vector3 rowMul( const Vector3 & vec, const Matrix3 & mat ); - -// Cross-product matrix of a 3-D vector -// -inline const Matrix3 crossMatrix( const Vector3 & vec ); - -// Create cross-product matrix and multiply -// NOTE: -// Faster than separately creating a cross-product matrix and multiplying. -// -inline const Matrix3 crossMatrixMul( const Vector3 & vec, const Matrix3 & mat ); - -// Linear interpolation between two 3-D vectors -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Vector3 lerp( float t, const Vector3 & vec0, const Vector3 & vec1 ); - -// Spherical linear interpolation between two 3-D vectors -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -inline const Vector3 slerp( float t, const Vector3 & unitVec0, const Vector3 & unitVec1 ); - -// Conditionally select between two 3-D vectors -// -inline const Vector3 select( const Vector3 & vec0, const Vector3 & vec1, bool select1 ); - -// Load x, y, and z elements from the first three words of a float array. -// -// -inline void loadXYZ( Vector3 & vec, const float * fptr ); - -// Store x, y, and z elements of a 3-D vector in the first three words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZ( const Vector3 & vec, float * fptr ); - -// Load three-half-floats as a 3-D vector -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. -// -inline void loadHalfFloats( Vector3 & vec, const unsigned short * hfptr ); - -// Store a 3-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// -inline void storeHalfFloats( const Vector3 & vec, unsigned short * hfptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3-D vector -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector3 & vec ); - -// Print a 3-D vector and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector3 & vec, const char * name ); - -#endif - -// A 4-D vector in array-of-structures format -// -class Vector4 -{ - float mX; - float mY; - float mZ; - float mW; - -public: - // Default constructor; does no initialization - // - inline Vector4( ) { }; - - // Copy a 4-D vector - // - inline Vector4( const Vector4 & vec ); - - // Construct a 4-D vector from x, y, z, and w elements - // - inline Vector4( float x, float y, float z, float w ); - - // Construct a 4-D vector from a 3-D vector and a scalar - // - inline Vector4( const Vector3 & xyz, float w ); - - // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 - // - explicit inline Vector4( const Vector3 & vec ); - - // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 - // - explicit inline Vector4( const Point3 & pnt ); - - // Copy elements from a quaternion into a 4-D vector - // - explicit inline Vector4( const Quat & quat ); - - // Set all elements of a 4-D vector to the same scalar value - // - explicit inline Vector4( float scalar ); - - // Assign one 4-D vector to another - // - inline Vector4 & operator =( const Vector4 & vec ); - - // Set the x, y, and z elements of a 4-D vector - // NOTE: - // This function does not change the w element. - // - inline Vector4 & setXYZ( const Vector3 & vec ); - - // Get the x, y, and z elements of a 4-D vector - // - inline const Vector3 getXYZ( ) const; - - // Set the x element of a 4-D vector - // - inline Vector4 & setX( float x ); - - // Set the y element of a 4-D vector - // - inline Vector4 & setY( float y ); - - // Set the z element of a 4-D vector - // - inline Vector4 & setZ( float z ); - - // Set the w element of a 4-D vector - // - inline Vector4 & setW( float w ); - - // Get the x element of a 4-D vector - // - inline float getX( ) const; - - // Get the y element of a 4-D vector - // - inline float getY( ) const; - - // Get the z element of a 4-D vector - // - inline float getZ( ) const; - - // Get the w element of a 4-D vector - // - inline float getW( ) const; - - // Set an x, y, z, or w element of a 4-D vector by index - // - inline Vector4 & setElem( int idx, float value ); - - // Get an x, y, z, or w element of a 4-D vector by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Add two 4-D vectors - // - inline const Vector4 operator +( const Vector4 & vec ) const; - - // Subtract a 4-D vector from another 4-D vector - // - inline const Vector4 operator -( const Vector4 & vec ) const; - - // Multiply a 4-D vector by a scalar - // - inline const Vector4 operator *( float scalar ) const; - - // Divide a 4-D vector by a scalar - // - inline const Vector4 operator /( float scalar ) const; - - // Perform compound assignment and addition with a 4-D vector - // - inline Vector4 & operator +=( const Vector4 & vec ); - - // Perform compound assignment and subtraction by a 4-D vector - // - inline Vector4 & operator -=( const Vector4 & vec ); - - // Perform compound assignment and multiplication by a scalar - // - inline Vector4 & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - inline Vector4 & operator /=( float scalar ); - - // Negate all elements of a 4-D vector - // - inline const Vector4 operator -( ) const; - - // Construct x axis - // - static inline const Vector4 xAxis( ); - - // Construct y axis - // - static inline const Vector4 yAxis( ); - - // Construct z axis - // - static inline const Vector4 zAxis( ); - - // Construct w axis - // - static inline const Vector4 wAxis( ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply a 4-D vector by a scalar -// -inline const Vector4 operator *( float scalar, const Vector4 & vec ); - -// Multiply two 4-D vectors per element -// -inline const Vector4 mulPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Divide two 4-D vectors per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -inline const Vector4 divPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Compute the reciprocal of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -inline const Vector4 recipPerElem( const Vector4 & vec ); - -// Compute the square root of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function sqrtf4. -// -inline const Vector4 sqrtPerElem( const Vector4 & vec ); - -// Compute the reciprocal square root of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function rsqrtf4. -// -inline const Vector4 rsqrtPerElem( const Vector4 & vec ); - -// Compute the absolute value of a 4-D vector per element -// -inline const Vector4 absPerElem( const Vector4 & vec ); - -// Copy sign from one 4-D vector to another, per element -// -inline const Vector4 copySignPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Maximum of two 4-D vectors per element -// -inline const Vector4 maxPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Minimum of two 4-D vectors per element -// -inline const Vector4 minPerElem( const Vector4 & vec0, const Vector4 & vec1 ); - -// Maximum element of a 4-D vector -// -inline float maxElem( const Vector4 & vec ); - -// Minimum element of a 4-D vector -// -inline float minElem( const Vector4 & vec ); - -// Compute the sum of all elements of a 4-D vector -// -inline float sum( const Vector4 & vec ); - -// Compute the dot product of two 4-D vectors -// -inline float dot( const Vector4 & vec0, const Vector4 & vec1 ); - -// Compute the square of the length of a 4-D vector -// -inline float lengthSqr( const Vector4 & vec ); - -// Compute the length of a 4-D vector -// -inline float length( const Vector4 & vec ); - -// Normalize a 4-D vector -// NOTE: -// The result is unpredictable when all elements of vec are at or near zero. -// -inline const Vector4 normalize( const Vector4 & vec ); - -// Outer product of two 4-D vectors -// -inline const Matrix4 outer( const Vector4 & vec0, const Vector4 & vec1 ); - -// Linear interpolation between two 4-D vectors -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Vector4 lerp( float t, const Vector4 & vec0, const Vector4 & vec1 ); - -// Spherical linear interpolation between two 4-D vectors -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -inline const Vector4 slerp( float t, const Vector4 & unitVec0, const Vector4 & unitVec1 ); - -// Conditionally select between two 4-D vectors -// -inline const Vector4 select( const Vector4 & vec0, const Vector4 & vec1, bool select1 ); - -// Load x, y, z, and w elements from the first four words of a float array. -// -// -inline void loadXYZW( Vector4 & vec, const float * fptr ); - -// Store x, y, z, and w elements of a 4-D vector in the first four words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZW( const Vector4 & vec, float * fptr ); - -// Load four-half-floats as a 4-D vector -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. -// -inline void loadHalfFloats( Vector4 & vec, const unsigned short * hfptr ); - -// Store a 4-D vector as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// -inline void storeHalfFloats( const Vector4 & vec, unsigned short * hfptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 4-D vector -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector4 & vec ); - -// Print a 4-D vector and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Vector4 & vec, const char * name ); - -#endif - -// A 3-D point in array-of-structures format -// -class Point3 -{ - float mX; - float mY; - float mZ; -#ifndef __GNUC__ - float d; -#endif - -public: - // Default constructor; does no initialization - // - inline Point3( ) { }; - - // Copy a 3-D point - // - inline Point3( const Point3 & pnt ); - - // Construct a 3-D point from x, y, and z elements - // - inline Point3( float x, float y, float z ); - - // Copy elements from a 3-D vector into a 3-D point - // - explicit inline Point3( const Vector3 & vec ); - - // Set all elements of a 3-D point to the same scalar value - // - explicit inline Point3( float scalar ); - - // Assign one 3-D point to another - // - inline Point3 & operator =( const Point3 & pnt ); - - // Set the x element of a 3-D point - // - inline Point3 & setX( float x ); - - // Set the y element of a 3-D point - // - inline Point3 & setY( float y ); - - // Set the z element of a 3-D point - // - inline Point3 & setZ( float z ); - - // Get the x element of a 3-D point - // - inline float getX( ) const; - - // Get the y element of a 3-D point - // - inline float getY( ) const; - - // Get the z element of a 3-D point - // - inline float getZ( ) const; - - // Set an x, y, or z element of a 3-D point by index - // - inline Point3 & setElem( int idx, float value ); - - // Get an x, y, or z element of a 3-D point by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Subtract a 3-D point from another 3-D point - // - inline const Vector3 operator -( const Point3 & pnt ) const; - - // Add a 3-D point to a 3-D vector - // - inline const Point3 operator +( const Vector3 & vec ) const; - - // Subtract a 3-D vector from a 3-D point - // - inline const Point3 operator -( const Vector3 & vec ) const; - - // Perform compound assignment and addition with a 3-D vector - // - inline Point3 & operator +=( const Vector3 & vec ); - - // Perform compound assignment and subtraction by a 3-D vector - // - inline Point3 & operator -=( const Vector3 & vec ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply two 3-D points per element -// -inline const Point3 mulPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Divide two 3-D points per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -inline const Point3 divPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Compute the reciprocal of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -inline const Point3 recipPerElem( const Point3 & pnt ); - -// Compute the square root of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function sqrtf4. -// -inline const Point3 sqrtPerElem( const Point3 & pnt ); - -// Compute the reciprocal square root of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function rsqrtf4. -// -inline const Point3 rsqrtPerElem( const Point3 & pnt ); - -// Compute the absolute value of a 3-D point per element -// -inline const Point3 absPerElem( const Point3 & pnt ); - -// Copy sign from one 3-D point to another, per element -// -inline const Point3 copySignPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Maximum of two 3-D points per element -// -inline const Point3 maxPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Minimum of two 3-D points per element -// -inline const Point3 minPerElem( const Point3 & pnt0, const Point3 & pnt1 ); - -// Maximum element of a 3-D point -// -inline float maxElem( const Point3 & pnt ); - -// Minimum element of a 3-D point -// -inline float minElem( const Point3 & pnt ); - -// Compute the sum of all elements of a 3-D point -// -inline float sum( const Point3 & pnt ); - -// Apply uniform scale to a 3-D point -// -inline const Point3 scale( const Point3 & pnt, float scaleVal ); - -// Apply non-uniform scale to a 3-D point -// -inline const Point3 scale( const Point3 & pnt, const Vector3 & scaleVec ); - -// Scalar projection of a 3-D point on a unit-length 3-D vector -// -inline float projection( const Point3 & pnt, const Vector3 & unitVec ); - -// Compute the square of the distance of a 3-D point from the coordinate-system origin -// -inline float distSqrFromOrigin( const Point3 & pnt ); - -// Compute the distance of a 3-D point from the coordinate-system origin -// -inline float distFromOrigin( const Point3 & pnt ); - -// Compute the square of the distance between two 3-D points -// -inline float distSqr( const Point3 & pnt0, const Point3 & pnt1 ); - -// Compute the distance between two 3-D points -// -inline float dist( const Point3 & pnt0, const Point3 & pnt1 ); - -// Linear interpolation between two 3-D points -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Point3 lerp( float t, const Point3 & pnt0, const Point3 & pnt1 ); - -// Conditionally select between two 3-D points -// -inline const Point3 select( const Point3 & pnt0, const Point3 & pnt1, bool select1 ); - -// Load x, y, and z elements from the first three words of a float array. -// -// -inline void loadXYZ( Point3 & pnt, const float * fptr ); - -// Store x, y, and z elements of a 3-D point in the first three words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZ( const Point3 & pnt, float * fptr ); - -// Load three-half-floats as a 3-D point -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. -// -inline void loadHalfFloats( Point3 & pnt, const unsigned short * hfptr ); - -// Store a 3-D point as half-floats. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// NOTE: -// This transformation does not support either denormalized numbers or NaNs. Memory area of previous 16 bytes and next 32 bytes from hfptr might be accessed. -// -inline void storeHalfFloats( const Point3 & pnt, unsigned short * hfptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3-D point -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Point3 & pnt ); - -// Print a 3-D point and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Point3 & pnt, const char * name ); - -#endif - -// A quaternion in array-of-structures format -// -class Quat -{ - float mX; - float mY; - float mZ; - float mW; - -public: - // Default constructor; does no initialization - // - inline Quat( ) { }; - - // Copy a quaternion - // - inline Quat( const Quat & quat ); - - // Construct a quaternion from x, y, z, and w elements - // - inline Quat( float x, float y, float z, float w ); - - // Construct a quaternion from a 3-D vector and a scalar - // - inline Quat( const Vector3 & xyz, float w ); - - // Copy elements from a 4-D vector into a quaternion - // - explicit inline Quat( const Vector4 & vec ); - - // Convert a rotation matrix to a unit-length quaternion - // - explicit inline Quat( const Matrix3 & rotMat ); - - // Set all elements of a quaternion to the same scalar value - // - explicit inline Quat( float scalar ); - - // Assign one quaternion to another - // - inline Quat & operator =( const Quat & quat ); - - // Set the x, y, and z elements of a quaternion - // NOTE: - // This function does not change the w element. - // - inline Quat & setXYZ( const Vector3 & vec ); - - // Get the x, y, and z elements of a quaternion - // - inline const Vector3 getXYZ( ) const; - - // Set the x element of a quaternion - // - inline Quat & setX( float x ); - - // Set the y element of a quaternion - // - inline Quat & setY( float y ); - - // Set the z element of a quaternion - // - inline Quat & setZ( float z ); - - // Set the w element of a quaternion - // - inline Quat & setW( float w ); - - // Get the x element of a quaternion - // - inline float getX( ) const; - - // Get the y element of a quaternion - // - inline float getY( ) const; - - // Get the z element of a quaternion - // - inline float getZ( ) const; - - // Get the w element of a quaternion - // - inline float getW( ) const; - - // Set an x, y, z, or w element of a quaternion by index - // - inline Quat & setElem( int idx, float value ); - - // Get an x, y, z, or w element of a quaternion by index - // - inline float getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - inline float & operator []( int idx ); - - // Subscripting operator to get an element - // - inline float operator []( int idx ) const; - - // Add two quaternions - // - inline const Quat operator +( const Quat & quat ) const; - - // Subtract a quaternion from another quaternion - // - inline const Quat operator -( const Quat & quat ) const; - - // Multiply two quaternions - // - inline const Quat operator *( const Quat & quat ) const; - - // Multiply a quaternion by a scalar - // - inline const Quat operator *( float scalar ) const; - - // Divide a quaternion by a scalar - // - inline const Quat operator /( float scalar ) const; - - // Perform compound assignment and addition with a quaternion - // - inline Quat & operator +=( const Quat & quat ); - - // Perform compound assignment and subtraction by a quaternion - // - inline Quat & operator -=( const Quat & quat ); - - // Perform compound assignment and multiplication by a quaternion - // - inline Quat & operator *=( const Quat & quat ); - - // Perform compound assignment and multiplication by a scalar - // - inline Quat & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - inline Quat & operator /=( float scalar ); - - // Negate all elements of a quaternion - // - inline const Quat operator -( ) const; - - // Construct an identity quaternion - // - static inline const Quat identity( ); - - // Construct a quaternion to rotate between two unit-length 3-D vectors - // NOTE: - // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. - // - static inline const Quat rotation( const Vector3 & unitVec0, const Vector3 & unitVec1 ); - - // Construct a quaternion to rotate around a unit-length 3-D vector - // - static inline const Quat rotation( float radians, const Vector3 & unitVec ); - - // Construct a quaternion to rotate around the x axis - // - static inline const Quat rotationX( float radians ); - - // Construct a quaternion to rotate around the y axis - // - static inline const Quat rotationY( float radians ); - - // Construct a quaternion to rotate around the z axis - // - static inline const Quat rotationZ( float radians ); - -} -#ifdef __GNUC__ -__attribute__ ((aligned(16))) -#endif -; - -// Multiply a quaternion by a scalar -// -inline const Quat operator *( float scalar, const Quat & quat ); - -// Compute the conjugate of a quaternion -// -inline const Quat conj( const Quat & quat ); - -// Use a unit-length quaternion to rotate a 3-D vector -// -inline const Vector3 rotate( const Quat & unitQuat, const Vector3 & vec ); - -// Compute the dot product of two quaternions -// -inline float dot( const Quat & quat0, const Quat & quat1 ); - -// Compute the norm of a quaternion -// -inline float norm( const Quat & quat ); - -// Compute the length of a quaternion -// -inline float length( const Quat & quat ); - -// Normalize a quaternion -// NOTE: -// The result is unpredictable when all elements of quat are at or near zero. -// -inline const Quat normalize( const Quat & quat ); - -// Linear interpolation between two quaternions -// NOTE: -// Does not clamp t between 0 and 1. -// -inline const Quat lerp( float t, const Quat & quat0, const Quat & quat1 ); - -// Spherical linear interpolation between two quaternions -// NOTE: -// Interpolates along the shortest path between orientations. -// Does not clamp t between 0 and 1. -// -inline const Quat slerp( float t, const Quat & unitQuat0, const Quat & unitQuat1 ); - -// Spherical quadrangle interpolation -// -inline const Quat squad( float t, const Quat & unitQuat0, const Quat & unitQuat1, const Quat & unitQuat2, const Quat & unitQuat3 ); - -// Conditionally select between two quaternions -// -inline const Quat select( const Quat & quat0, const Quat & quat1, bool select1 ); - -// Load x, y, z, and w elements from the first four words of a float array. -// -// -inline void loadXYZW( Quat & quat, const float * fptr ); - -// Store x, y, z, and w elements of a quaternion in the first four words of a float array. -// Memory area of previous 16 bytes and next 32 bytes from fptr might be accessed -// -inline void storeXYZW( const Quat & quat, float * fptr ); - -#ifdef _VECTORMATH_DEBUG - -// Print a quaternion -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Quat & quat ); - -// Print a quaternion and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Quat & quat, const char * name ); - -#endif - -// A 3x3 matrix in array-of-structures format -// -class Matrix3 -{ - Vector3 mCol0; - Vector3 mCol1; - Vector3 mCol2; - -public: - // Default constructor; does no initialization - // - inline Matrix3( ) { }; - - // Copy a 3x3 matrix - // - inline Matrix3( const Matrix3 & mat ); - - // Construct a 3x3 matrix containing the specified columns - // - inline Matrix3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2 ); - - // Construct a 3x3 rotation matrix from a unit-length quaternion - // - explicit inline Matrix3( const Quat & unitQuat ); - - // Set all elements of a 3x3 matrix to the same scalar value - // - explicit inline Matrix3( float scalar ); - - // Assign one 3x3 matrix to another - // - inline Matrix3 & operator =( const Matrix3 & mat ); - - // Set column 0 of a 3x3 matrix - // - inline Matrix3 & setCol0( const Vector3 & col0 ); - - // Set column 1 of a 3x3 matrix - // - inline Matrix3 & setCol1( const Vector3 & col1 ); - - // Set column 2 of a 3x3 matrix - // - inline Matrix3 & setCol2( const Vector3 & col2 ); - - // Get column 0 of a 3x3 matrix - // - inline const Vector3 getCol0( ) const; - - // Get column 1 of a 3x3 matrix - // - inline const Vector3 getCol1( ) const; - - // Get column 2 of a 3x3 matrix - // - inline const Vector3 getCol2( ) const; - - // Set the column of a 3x3 matrix referred to by the specified index - // - inline Matrix3 & setCol( int col, const Vector3 & vec ); - - // Set the row of a 3x3 matrix referred to by the specified index - // - inline Matrix3 & setRow( int row, const Vector3 & vec ); - - // Get the column of a 3x3 matrix referred to by the specified index - // - inline const Vector3 getCol( int col ) const; - - // Get the row of a 3x3 matrix referred to by the specified index - // - inline const Vector3 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - inline Vector3 & operator []( int col ); - - // Subscripting operator to get a column - // - inline const Vector3 operator []( int col ) const; - - // Set the element of a 3x3 matrix referred to by column and row indices - // - inline Matrix3 & setElem( int col, int row, float val ); - - // Get the element of a 3x3 matrix referred to by column and row indices - // - inline float getElem( int col, int row ) const; - - // Add two 3x3 matrices - // - inline const Matrix3 operator +( const Matrix3 & mat ) const; - - // Subtract a 3x3 matrix from another 3x3 matrix - // - inline const Matrix3 operator -( const Matrix3 & mat ) const; - - // Negate all elements of a 3x3 matrix - // - inline const Matrix3 operator -( ) const; - - // Multiply a 3x3 matrix by a scalar - // - inline const Matrix3 operator *( float scalar ) const; - - // Multiply a 3x3 matrix by a 3-D vector - // - inline const Vector3 operator *( const Vector3 & vec ) const; - - // Multiply two 3x3 matrices - // - inline const Matrix3 operator *( const Matrix3 & mat ) const; - - // Perform compound assignment and addition with a 3x3 matrix - // - inline Matrix3 & operator +=( const Matrix3 & mat ); - - // Perform compound assignment and subtraction by a 3x3 matrix - // - inline Matrix3 & operator -=( const Matrix3 & mat ); - - // Perform compound assignment and multiplication by a scalar - // - inline Matrix3 & operator *=( float scalar ); - - // Perform compound assignment and multiplication by a 3x3 matrix - // - inline Matrix3 & operator *=( const Matrix3 & mat ); - - // Construct an identity 3x3 matrix - // - static inline const Matrix3 identity( ); - - // Construct a 3x3 matrix to rotate around the x axis - // - static inline const Matrix3 rotationX( float radians ); - - // Construct a 3x3 matrix to rotate around the y axis - // - static inline const Matrix3 rotationY( float radians ); - - // Construct a 3x3 matrix to rotate around the z axis - // - static inline const Matrix3 rotationZ( float radians ); - - // Construct a 3x3 matrix to rotate around the x, y, and z axes - // - static inline const Matrix3 rotationZYX( const Vector3 & radiansXYZ ); - - // Construct a 3x3 matrix to rotate around a unit-length 3-D vector - // - static inline const Matrix3 rotation( float radians, const Vector3 & unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static inline const Matrix3 rotation( const Quat & unitQuat ); - - // Construct a 3x3 matrix to perform scaling - // - static inline const Matrix3 scale( const Vector3 & scaleVec ); - -}; -// Multiply a 3x3 matrix by a scalar -// -inline const Matrix3 operator *( float scalar, const Matrix3 & mat ); - -// Append (post-multiply) a scale transformation to a 3x3 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix3 appendScale( const Matrix3 & mat, const Vector3 & scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 3x3 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix3 prependScale( const Vector3 & scaleVec, const Matrix3 & mat ); - -// Multiply two 3x3 matrices per element -// -inline const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); - -// Compute the absolute value of a 3x3 matrix per element -// -inline const Matrix3 absPerElem( const Matrix3 & mat ); - -// Transpose of a 3x3 matrix -// -inline const Matrix3 transpose( const Matrix3 & mat ); - -// Compute the inverse of a 3x3 matrix -// NOTE: -// Result is unpredictable when the determinant of mat is equal to or near 0. -// -inline const Matrix3 inverse( const Matrix3 & mat ); - -// Determinant of a 3x3 matrix -// -inline float determinant( const Matrix3 & mat ); - -// Conditionally select between two 3x3 matrices -// -inline const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3x3 matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix3 & mat ); - -// Print a 3x3 matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix3 & mat, const char * name ); - -#endif - -// A 4x4 matrix in array-of-structures format -// -class Matrix4 -{ - Vector4 mCol0; - Vector4 mCol1; - Vector4 mCol2; - Vector4 mCol3; - -public: - // Default constructor; does no initialization - // - inline Matrix4( ) { }; - - // Copy a 4x4 matrix - // - inline Matrix4( const Matrix4 & mat ); - - // Construct a 4x4 matrix containing the specified columns - // - inline Matrix4( const Vector4 & col0, const Vector4 & col1, const Vector4 & col2, const Vector4 & col3 ); - - // Construct a 4x4 matrix from a 3x4 transformation matrix - // - explicit inline Matrix4( const Transform3 & mat ); - - // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector - // - inline Matrix4( const Matrix3 & mat, const Vector3 & translateVec ); - - // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector - // - inline Matrix4( const Quat & unitQuat, const Vector3 & translateVec ); - - // Set all elements of a 4x4 matrix to the same scalar value - // - explicit inline Matrix4( float scalar ); - - // Assign one 4x4 matrix to another - // - inline Matrix4 & operator =( const Matrix4 & mat ); - - // Set the upper-left 3x3 submatrix - // NOTE: - // This function does not change the bottom row elements. - // - inline Matrix4 & setUpper3x3( const Matrix3 & mat3 ); - - // Get the upper-left 3x3 submatrix of a 4x4 matrix - // - inline const Matrix3 getUpper3x3( ) const; - - // Set translation component - // NOTE: - // This function does not change the bottom row elements. - // - inline Matrix4 & setTranslation( const Vector3 & translateVec ); - - // Get the translation component of a 4x4 matrix - // - inline const Vector3 getTranslation( ) const; - - // Set column 0 of a 4x4 matrix - // - inline Matrix4 & setCol0( const Vector4 & col0 ); - - // Set column 1 of a 4x4 matrix - // - inline Matrix4 & setCol1( const Vector4 & col1 ); - - // Set column 2 of a 4x4 matrix - // - inline Matrix4 & setCol2( const Vector4 & col2 ); - - // Set column 3 of a 4x4 matrix - // - inline Matrix4 & setCol3( const Vector4 & col3 ); - - // Get column 0 of a 4x4 matrix - // - inline const Vector4 getCol0( ) const; - - // Get column 1 of a 4x4 matrix - // - inline const Vector4 getCol1( ) const; - - // Get column 2 of a 4x4 matrix - // - inline const Vector4 getCol2( ) const; - - // Get column 3 of a 4x4 matrix - // - inline const Vector4 getCol3( ) const; - - // Set the column of a 4x4 matrix referred to by the specified index - // - inline Matrix4 & setCol( int col, const Vector4 & vec ); - - // Set the row of a 4x4 matrix referred to by the specified index - // - inline Matrix4 & setRow( int row, const Vector4 & vec ); - - // Get the column of a 4x4 matrix referred to by the specified index - // - inline const Vector4 getCol( int col ) const; - - // Get the row of a 4x4 matrix referred to by the specified index - // - inline const Vector4 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - inline Vector4 & operator []( int col ); - - // Subscripting operator to get a column - // - inline const Vector4 operator []( int col ) const; - - // Set the element of a 4x4 matrix referred to by column and row indices - // - inline Matrix4 & setElem( int col, int row, float val ); - - // Get the element of a 4x4 matrix referred to by column and row indices - // - inline float getElem( int col, int row ) const; - - // Add two 4x4 matrices - // - inline const Matrix4 operator +( const Matrix4 & mat ) const; - - // Subtract a 4x4 matrix from another 4x4 matrix - // - inline const Matrix4 operator -( const Matrix4 & mat ) const; - - // Negate all elements of a 4x4 matrix - // - inline const Matrix4 operator -( ) const; - - // Multiply a 4x4 matrix by a scalar - // - inline const Matrix4 operator *( float scalar ) const; - - // Multiply a 4x4 matrix by a 4-D vector - // - inline const Vector4 operator *( const Vector4 & vec ) const; - - // Multiply a 4x4 matrix by a 3-D vector - // - inline const Vector4 operator *( const Vector3 & vec ) const; - - // Multiply a 4x4 matrix by a 3-D point - // - inline const Vector4 operator *( const Point3 & pnt ) const; - - // Multiply two 4x4 matrices - // - inline const Matrix4 operator *( const Matrix4 & mat ) const; - - // Multiply a 4x4 matrix by a 3x4 transformation matrix - // - inline const Matrix4 operator *( const Transform3 & tfrm ) const; - - // Perform compound assignment and addition with a 4x4 matrix - // - inline Matrix4 & operator +=( const Matrix4 & mat ); - - // Perform compound assignment and subtraction by a 4x4 matrix - // - inline Matrix4 & operator -=( const Matrix4 & mat ); - - // Perform compound assignment and multiplication by a scalar - // - inline Matrix4 & operator *=( float scalar ); - - // Perform compound assignment and multiplication by a 4x4 matrix - // - inline Matrix4 & operator *=( const Matrix4 & mat ); - - // Perform compound assignment and multiplication by a 3x4 transformation matrix - // - inline Matrix4 & operator *=( const Transform3 & tfrm ); - - // Construct an identity 4x4 matrix - // - static inline const Matrix4 identity( ); - - // Construct a 4x4 matrix to rotate around the x axis - // - static inline const Matrix4 rotationX( float radians ); - - // Construct a 4x4 matrix to rotate around the y axis - // - static inline const Matrix4 rotationY( float radians ); - - // Construct a 4x4 matrix to rotate around the z axis - // - static inline const Matrix4 rotationZ( float radians ); - - // Construct a 4x4 matrix to rotate around the x, y, and z axes - // - static inline const Matrix4 rotationZYX( const Vector3 & radiansXYZ ); - - // Construct a 4x4 matrix to rotate around a unit-length 3-D vector - // - static inline const Matrix4 rotation( float radians, const Vector3 & unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static inline const Matrix4 rotation( const Quat & unitQuat ); - - // Construct a 4x4 matrix to perform scaling - // - static inline const Matrix4 scale( const Vector3 & scaleVec ); - - // Construct a 4x4 matrix to perform translation - // - static inline const Matrix4 translation( const Vector3 & translateVec ); - - // Construct viewing matrix based on eye position, position looked at, and up direction - // - static inline const Matrix4 lookAt( const Point3 & eyePos, const Point3 & lookAtPos, const Vector3 & upVec ); - - // Construct a perspective projection matrix - // - static inline const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); - - // Construct a perspective projection matrix based on frustum - // - static inline const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); - - // Construct an orthographic projection matrix - // - static inline const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); - -}; -// Multiply a 4x4 matrix by a scalar -// -inline const Matrix4 operator *( float scalar, const Matrix4 & mat ); - -// Append (post-multiply) a scale transformation to a 4x4 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix4 appendScale( const Matrix4 & mat, const Vector3 & scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 4x4 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Matrix4 prependScale( const Vector3 & scaleVec, const Matrix4 & mat ); - -// Multiply two 4x4 matrices per element -// -inline const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); - -// Compute the absolute value of a 4x4 matrix per element -// -inline const Matrix4 absPerElem( const Matrix4 & mat ); - -// Transpose of a 4x4 matrix -// -inline const Matrix4 transpose( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix -// NOTE: -// Result is unpredictable when the determinant of mat is equal to or near 0. -// -inline const Matrix4 inverse( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. -// -inline const Matrix4 affineInverse( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. -// -inline const Matrix4 orthoInverse( const Matrix4 & mat ); - -// Determinant of a 4x4 matrix -// -inline float determinant( const Matrix4 & mat ); - -// Conditionally select between two 4x4 matrices -// -inline const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 4x4 matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix4 & mat ); - -// Print a 4x4 matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Matrix4 & mat, const char * name ); - -#endif - -// A 3x4 transformation matrix in array-of-structures format -// -class Transform3 -{ - Vector3 mCol0; - Vector3 mCol1; - Vector3 mCol2; - Vector3 mCol3; - -public: - // Default constructor; does no initialization - // - inline Transform3( ) { }; - - // Copy a 3x4 transformation matrix - // - inline Transform3( const Transform3 & tfrm ); - - // Construct a 3x4 transformation matrix containing the specified columns - // - inline Transform3( const Vector3 & col0, const Vector3 & col1, const Vector3 & col2, const Vector3 & col3 ); - - // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector - // - inline Transform3( const Matrix3 & tfrm, const Vector3 & translateVec ); - - // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector - // - inline Transform3( const Quat & unitQuat, const Vector3 & translateVec ); - - // Set all elements of a 3x4 transformation matrix to the same scalar value - // - explicit inline Transform3( float scalar ); - - // Assign one 3x4 transformation matrix to another - // - inline Transform3 & operator =( const Transform3 & tfrm ); - - // Set the upper-left 3x3 submatrix - // - inline Transform3 & setUpper3x3( const Matrix3 & mat3 ); - - // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix - // - inline const Matrix3 getUpper3x3( ) const; - - // Set translation component - // - inline Transform3 & setTranslation( const Vector3 & translateVec ); - - // Get the translation component of a 3x4 transformation matrix - // - inline const Vector3 getTranslation( ) const; - - // Set column 0 of a 3x4 transformation matrix - // - inline Transform3 & setCol0( const Vector3 & col0 ); - - // Set column 1 of a 3x4 transformation matrix - // - inline Transform3 & setCol1( const Vector3 & col1 ); - - // Set column 2 of a 3x4 transformation matrix - // - inline Transform3 & setCol2( const Vector3 & col2 ); - - // Set column 3 of a 3x4 transformation matrix - // - inline Transform3 & setCol3( const Vector3 & col3 ); - - // Get column 0 of a 3x4 transformation matrix - // - inline const Vector3 getCol0( ) const; - - // Get column 1 of a 3x4 transformation matrix - // - inline const Vector3 getCol1( ) const; - - // Get column 2 of a 3x4 transformation matrix - // - inline const Vector3 getCol2( ) const; - - // Get column 3 of a 3x4 transformation matrix - // - inline const Vector3 getCol3( ) const; - - // Set the column of a 3x4 transformation matrix referred to by the specified index - // - inline Transform3 & setCol( int col, const Vector3 & vec ); - - // Set the row of a 3x4 transformation matrix referred to by the specified index - // - inline Transform3 & setRow( int row, const Vector4 & vec ); - - // Get the column of a 3x4 transformation matrix referred to by the specified index - // - inline const Vector3 getCol( int col ) const; - - // Get the row of a 3x4 transformation matrix referred to by the specified index - // - inline const Vector4 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - inline Vector3 & operator []( int col ); - - // Subscripting operator to get a column - // - inline const Vector3 operator []( int col ) const; - - // Set the element of a 3x4 transformation matrix referred to by column and row indices - // - inline Transform3 & setElem( int col, int row, float val ); - - // Get the element of a 3x4 transformation matrix referred to by column and row indices - // - inline float getElem( int col, int row ) const; - - // Multiply a 3x4 transformation matrix by a 3-D vector - // - inline const Vector3 operator *( const Vector3 & vec ) const; - - // Multiply a 3x4 transformation matrix by a 3-D point - // - inline const Point3 operator *( const Point3 & pnt ) const; - - // Multiply two 3x4 transformation matrices - // - inline const Transform3 operator *( const Transform3 & tfrm ) const; - - // Perform compound assignment and multiplication by a 3x4 transformation matrix - // - inline Transform3 & operator *=( const Transform3 & tfrm ); - - // Construct an identity 3x4 transformation matrix - // - static inline const Transform3 identity( ); - - // Construct a 3x4 transformation matrix to rotate around the x axis - // - static inline const Transform3 rotationX( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the y axis - // - static inline const Transform3 rotationY( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the z axis - // - static inline const Transform3 rotationZ( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes - // - static inline const Transform3 rotationZYX( const Vector3 & radiansXYZ ); - - // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector - // - static inline const Transform3 rotation( float radians, const Vector3 & unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static inline const Transform3 rotation( const Quat & unitQuat ); - - // Construct a 3x4 transformation matrix to perform scaling - // - static inline const Transform3 scale( const Vector3 & scaleVec ); - - // Construct a 3x4 transformation matrix to perform translation - // - static inline const Transform3 translation( const Vector3 & translateVec ); - -}; -// Append (post-multiply) a scale transformation to a 3x4 transformation matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Transform3 appendScale( const Transform3 & tfrm, const Vector3 & scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -inline const Transform3 prependScale( const Vector3 & scaleVec, const Transform3 & tfrm ); - -// Multiply two 3x4 transformation matrices per element -// -inline const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); - -// Compute the absolute value of a 3x4 transformation matrix per element -// -inline const Transform3 absPerElem( const Transform3 & tfrm ); - -// Inverse of a 3x4 transformation matrix -// NOTE: -// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. -// -inline const Transform3 inverse( const Transform3 & tfrm ); - -// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. -// -inline const Transform3 orthoInverse( const Transform3 & tfrm ); - -// Conditionally select between two 3x4 transformation matrices -// -inline const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3x4 transformation matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Transform3 & tfrm ); - -// Print a 3x4 transformation matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -inline void print( const Transform3 & tfrm, const char * name ); - -#endif - -} // namespace Aos -} // namespace Vectormath - -#include "vec_aos.h" -#include "quat_aos.h" -#include "mat_aos.h" - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/boolInVec.h b/Code/Physics/Bullet Source/src/vectormath/sse/boolInVec.h deleted file mode 100644 index d21d25cb..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/boolInVec.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _BOOLINVEC_H -#define _BOOLINVEC_H - -#include - -namespace Vectormath { - -class floatInVec; - -//-------------------------------------------------------------------------------------------------- -// boolInVec class -// - -class boolInVec -{ - private: - __m128 mData; - - inline boolInVec(__m128 vec); - public: - inline boolInVec() {} - - // matches standard type conversions - // - inline boolInVec(const floatInVec &vec); - - // explicit cast from bool - // - explicit inline boolInVec(bool scalar); - -#ifdef _VECTORMATH_NO_SCALAR_CAST - // explicit cast to bool - // - inline bool getAsBool() const; -#else - // implicit cast to bool - // - inline operator bool() const; -#endif - - // get vector data - // bool value is splatted across all word slots of vector as 0 (false) or -1 (true) - // - inline __m128 get128() const; - - // operators - // - inline const boolInVec operator ! () const; - inline boolInVec& operator = (const boolInVec &vec); - inline boolInVec& operator &= (const boolInVec &vec); - inline boolInVec& operator ^= (const boolInVec &vec); - inline boolInVec& operator |= (const boolInVec &vec); - - // friend functions - // - friend inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); - friend inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); - friend inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); - friend inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); - friend inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); - friend inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); - friend inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); - friend inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); - friend inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); - friend inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); - friend inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); - friend inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); -}; - -//-------------------------------------------------------------------------------------------------- -// boolInVec functions -// - -// operators -// -inline const boolInVec operator == (const boolInVec &vec0, const boolInVec &vec1); -inline const boolInVec operator != (const boolInVec &vec0, const boolInVec &vec1); -inline const boolInVec operator & (const boolInVec &vec0, const boolInVec &vec1); -inline const boolInVec operator ^ (const boolInVec &vec0, const boolInVec &vec1); -inline const boolInVec operator | (const boolInVec &vec0, const boolInVec &vec1); - -// select between vec0 and vec1 using boolInVec. -// false selects vec0, true selects vec1 -// -inline const boolInVec select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1); - -} // namespace Vectormath - -//-------------------------------------------------------------------------------------------------- -// boolInVec implementation -// - -#include "floatInVec.h" - -namespace Vectormath { - -inline -boolInVec::boolInVec(__m128 vec) -{ - mData = vec; -} - -inline -boolInVec::boolInVec(const floatInVec &vec) -{ - *this = (vec != floatInVec(0.0f)); -} - -inline -boolInVec::boolInVec(bool scalar) -{ - unsigned int mask = -(int)scalar; - mData = _mm_set1_ps(*(float *)&mask); // TODO: Union -} - -#ifdef _VECTORMATH_NO_SCALAR_CAST -inline -bool -boolInVec::getAsBool() const -#else -inline -boolInVec::operator bool() const -#endif -{ - return *(bool *)&mData; -} - -inline -__m128 -boolInVec::get128() const -{ - return mData; -} - -inline -const boolInVec -boolInVec::operator ! () const -{ - return boolInVec(_mm_andnot_ps(mData, _mm_cmpneq_ps(_mm_setzero_ps(),_mm_setzero_ps()))); -} - -inline -boolInVec& -boolInVec::operator = (const boolInVec &vec) -{ - mData = vec.mData; - return *this; -} - -inline -boolInVec& -boolInVec::operator &= (const boolInVec &vec) -{ - *this = *this & vec; - return *this; -} - -inline -boolInVec& -boolInVec::operator ^= (const boolInVec &vec) -{ - *this = *this ^ vec; - return *this; -} - -inline -boolInVec& -boolInVec::operator |= (const boolInVec &vec) -{ - *this = *this | vec; - return *this; -} - -inline -const boolInVec -operator == (const boolInVec &vec0, const boolInVec &vec1) -{ - return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator != (const boolInVec &vec0, const boolInVec &vec1) -{ - return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator & (const boolInVec &vec0, const boolInVec &vec1) -{ - return boolInVec(_mm_and_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator | (const boolInVec &vec0, const boolInVec &vec1) -{ - return boolInVec(_mm_or_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator ^ (const boolInVec &vec0, const boolInVec &vec1) -{ - return boolInVec(_mm_xor_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -select(const boolInVec &vec0, const boolInVec &vec1, const boolInVec &select_vec1) -{ - return boolInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); -} - -} // namespace Vectormath - -#endif // boolInVec_h diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/floatInVec.h b/Code/Physics/Bullet Source/src/vectormath/sse/floatInVec.h deleted file mode 100644 index e8ac5959..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/floatInVec.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _FLOATINVEC_H -#define _FLOATINVEC_H - -#include -#include - -namespace Vectormath { - -class boolInVec; - -//-------------------------------------------------------------------------------------------------- -// floatInVec class -// - -class floatInVec -{ - private: - __m128 mData; - - public: - inline floatInVec(__m128 vec); - - inline floatInVec() {} - - // matches standard type conversions - // - inline floatInVec(const boolInVec &vec); - - // construct from a slot of __m128 - // - inline floatInVec(__m128 vec, int slot); - - // explicit cast from float - // - explicit inline floatInVec(float scalar); - -#ifdef _VECTORMATH_NO_SCALAR_CAST - // explicit cast to float - // - inline float getAsFloat() const; -#else - // implicit cast to float - // - inline operator float() const; -#endif - - // get vector data - // float value is splatted across all word slots of vector - // - inline __m128 get128() const; - - // operators - // - inline const floatInVec operator ++ (int); - inline const floatInVec operator -- (int); - inline floatInVec& operator ++ (); - inline floatInVec& operator -- (); - inline const floatInVec operator - () const; - inline floatInVec& operator = (const floatInVec &vec); - inline floatInVec& operator *= (const floatInVec &vec); - inline floatInVec& operator /= (const floatInVec &vec); - inline floatInVec& operator += (const floatInVec &vec); - inline floatInVec& operator -= (const floatInVec &vec); - - // friend functions - // - friend inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); - friend inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); - friend inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); - friend inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); - friend inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, boolInVec select_vec1); -}; - -//-------------------------------------------------------------------------------------------------- -// floatInVec functions -// - -// operators -// -inline const floatInVec operator * (const floatInVec &vec0, const floatInVec &vec1); -inline const floatInVec operator / (const floatInVec &vec0, const floatInVec &vec1); -inline const floatInVec operator + (const floatInVec &vec0, const floatInVec &vec1); -inline const floatInVec operator - (const floatInVec &vec0, const floatInVec &vec1); -inline const boolInVec operator < (const floatInVec &vec0, const floatInVec &vec1); -inline const boolInVec operator <= (const floatInVec &vec0, const floatInVec &vec1); -inline const boolInVec operator > (const floatInVec &vec0, const floatInVec &vec1); -inline const boolInVec operator >= (const floatInVec &vec0, const floatInVec &vec1); -inline const boolInVec operator == (const floatInVec &vec0, const floatInVec &vec1); -inline const boolInVec operator != (const floatInVec &vec0, const floatInVec &vec1); - -// select between vec0 and vec1 using boolInVec. -// false selects vec0, true selects vec1 -// -inline const floatInVec select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1); - -} // namespace Vectormath - -//-------------------------------------------------------------------------------------------------- -// floatInVec implementation -// - -#include "boolInVec.h" - -namespace Vectormath { - -inline -floatInVec::floatInVec(__m128 vec) -{ - mData = vec; -} - -inline -floatInVec::floatInVec(const boolInVec &vec) -{ - mData = vec_sel(_mm_setzero_ps(), _mm_set1_ps(1.0f), vec.get128()); -} - -inline -floatInVec::floatInVec(__m128 vec, int slot) -{ - SSEFloat v; - v.m128 = vec; - mData = _mm_set1_ps(v.f[slot]); -} - -inline -floatInVec::floatInVec(float scalar) -{ - mData = _mm_set1_ps(scalar); -} - -#ifdef _VECTORMATH_NO_SCALAR_CAST -inline -float -floatInVec::getAsFloat() const -#else -inline -floatInVec::operator float() const -#endif -{ - return *((float *)&mData); -} - -inline -__m128 -floatInVec::get128() const -{ - return mData; -} - -inline -const floatInVec -floatInVec::operator ++ (int) -{ - __m128 olddata = mData; - operator ++(); - return floatInVec(olddata); -} - -inline -const floatInVec -floatInVec::operator -- (int) -{ - __m128 olddata = mData; - operator --(); - return floatInVec(olddata); -} - -inline -floatInVec& -floatInVec::operator ++ () -{ - *this += floatInVec(_mm_set1_ps(1.0f)); - return *this; -} - -inline -floatInVec& -floatInVec::operator -- () -{ - *this -= floatInVec(_mm_set1_ps(1.0f)); - return *this; -} - -inline -const floatInVec -floatInVec::operator - () const -{ - return floatInVec(_mm_sub_ps(_mm_setzero_ps(), mData)); -} - -inline -floatInVec& -floatInVec::operator = (const floatInVec &vec) -{ - mData = vec.mData; - return *this; -} - -inline -floatInVec& -floatInVec::operator *= (const floatInVec &vec) -{ - *this = *this * vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator /= (const floatInVec &vec) -{ - *this = *this / vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator += (const floatInVec &vec) -{ - *this = *this + vec; - return *this; -} - -inline -floatInVec& -floatInVec::operator -= (const floatInVec &vec) -{ - *this = *this - vec; - return *this; -} - -inline -const floatInVec -operator * (const floatInVec &vec0, const floatInVec &vec1) -{ - return floatInVec(_mm_mul_ps(vec0.get128(), vec1.get128())); -} - -inline -const floatInVec -operator / (const floatInVec &num, const floatInVec &den) -{ - return floatInVec(_mm_div_ps(num.get128(), den.get128())); -} - -inline -const floatInVec -operator + (const floatInVec &vec0, const floatInVec &vec1) -{ - return floatInVec(_mm_add_ps(vec0.get128(), vec1.get128())); -} - -inline -const floatInVec -operator - (const floatInVec &vec0, const floatInVec &vec1) -{ - return floatInVec(_mm_sub_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator < (const floatInVec &vec0, const floatInVec &vec1) -{ - return boolInVec(_mm_cmpgt_ps(vec1.get128(), vec0.get128())); -} - -inline -const boolInVec -operator <= (const floatInVec &vec0, const floatInVec &vec1) -{ - return boolInVec(_mm_cmpge_ps(vec1.get128(), vec0.get128())); -} - -inline -const boolInVec -operator > (const floatInVec &vec0, const floatInVec &vec1) -{ - return boolInVec(_mm_cmpgt_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator >= (const floatInVec &vec0, const floatInVec &vec1) -{ - return boolInVec(_mm_cmpge_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator == (const floatInVec &vec0, const floatInVec &vec1) -{ - return boolInVec(_mm_cmpeq_ps(vec0.get128(), vec1.get128())); -} - -inline -const boolInVec -operator != (const floatInVec &vec0, const floatInVec &vec1) -{ - return boolInVec(_mm_cmpneq_ps(vec0.get128(), vec1.get128())); -} - -inline -const floatInVec -select(const floatInVec &vec0, const floatInVec &vec1, const boolInVec &select_vec1) -{ - return floatInVec(vec_sel(vec0.get128(), vec1.get128(), select_vec1.get128())); -} - -} // namespace Vectormath - -#endif // floatInVec_h diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/mat_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/mat_aos.h deleted file mode 100644 index a2c66cc5..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/mat_aos.h +++ /dev/null @@ -1,2190 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _VECTORMATH_MAT_AOS_CPP_H -#define _VECTORMATH_MAT_AOS_CPP_H - -namespace Vectormath { -namespace Aos { - -//----------------------------------------------------------------------------- -// Constants -// for shuffles, words are labeled [x,y,z,w] [a,b,c,d] - -#define _VECTORMATH_PERM_ZBWX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_XCYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_C, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_XYAB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B }) -#define _VECTORMATH_PERM_ZWCD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W, _VECTORMATH_PERM_C, _VECTORMATH_PERM_D }) -#define _VECTORMATH_PERM_XZBX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_B, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_CXXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_YAXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_XAZC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_C }) -#define _VECTORMATH_PERM_YXWZ ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W, _VECTORMATH_PERM_Z }) -#define _VECTORMATH_PERM_YBWD ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_B, _VECTORMATH_PERM_W, _VECTORMATH_PERM_D }) -#define _VECTORMATH_PERM_XYCX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_YCXY ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y }) -#define _VECTORMATH_PERM_CXYC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_C, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_C }) -#define _VECTORMATH_PERM_ZAYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_BZXX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PERM_XZYA ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A }) -#define _VECTORMATH_PERM_ZXXB ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_B }) -#define _VECTORMATH_PERM_YXXC ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X, _VECTORMATH_PERM_X, _VECTORMATH_PERM_C }) -#define _VECTORMATH_PERM_BBYX ((vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_B, _VECTORMATH_PERM_B, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_X }) -#define _VECTORMATH_PI_OVER_2 1.570796327f - -//----------------------------------------------------------------------------- -// Definitions - -VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Matrix3 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; -} - -VECTORMATH_FORCE_INLINE Matrix3::Matrix3( float scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); -} - -VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const floatInVec &scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); -} - -VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Quat &unitQuat ) -{ - __m128 xyzw_2, wwww, yzxw, zxyw, yzxw_2, zxyw_2; - __m128 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - VM_ATTRIBUTE_ALIGN16 unsigned int sx[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int sz[4] = {0, 0, 0xffffffff, 0}; - __m128 select_x = _mm_load_ps((float *)sx); - __m128 select_z = _mm_load_ps((float *)sz); - - xyzw_2 = _mm_add_ps( unitQuat.get128(), unitQuat.get128() ); - wwww = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,3,3,3) ); - yzxw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,0,2,1) ); - zxyw = _mm_shuffle_ps( unitQuat.get128(), unitQuat.get128(), _MM_SHUFFLE(3,1,0,2) ); - yzxw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,0,2,1) ); - zxyw_2 = _mm_shuffle_ps( xyzw_2, xyzw_2, _MM_SHUFFLE(3,1,0,2) ); - - tmp0 = _mm_mul_ps( yzxw_2, wwww ); // tmp0 = 2yw, 2zw, 2xw, 2w2 - tmp1 = _mm_sub_ps( _mm_set1_ps(1.0f), _mm_mul_ps(yzxw, yzxw_2) ); // tmp1 = 1 - 2y2, 1 - 2z2, 1 - 2x2, 1 - 2w2 - tmp2 = _mm_mul_ps( yzxw, xyzw_2 ); // tmp2 = 2xy, 2yz, 2xz, 2w2 - tmp0 = _mm_add_ps( _mm_mul_ps(zxyw, xyzw_2), tmp0 ); // tmp0 = 2yw + 2zx, 2zw + 2xy, 2xw + 2yz, 2w2 + 2w2 - tmp1 = _mm_sub_ps( tmp1, _mm_mul_ps(zxyw, zxyw_2) ); // tmp1 = 1 - 2y2 - 2z2, 1 - 2z2 - 2x2, 1 - 2x2 - 2y2, 1 - 2w2 - 2w2 - tmp2 = _mm_sub_ps( tmp2, _mm_mul_ps(zxyw_2, wwww) ); // tmp2 = 2xy - 2zw, 2yz - 2xw, 2xz - 2yw, 2w2 -2w2 - - tmp3 = vec_sel( tmp0, tmp1, select_x ); - tmp4 = vec_sel( tmp1, tmp2, select_x ); - tmp5 = vec_sel( tmp2, tmp0, select_x ); - mCol0 = Vector3( vec_sel( tmp3, tmp2, select_z ) ); - mCol1 = Vector3( vec_sel( tmp4, tmp0, select_z ) ); - mCol2 = Vector3( vec_sel( tmp5, tmp1, select_z ) ); -} - -VECTORMATH_FORCE_INLINE Matrix3::Matrix3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol0( const Vector3 &_col0 ) -{ - mCol0 = _col0; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol1( const Vector3 &_col1 ) -{ - mCol1 = _col1; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol2( const Vector3 &_col2 ) -{ - mCol2 = _col2; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setCol( int col, const Vector3 &vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setRow( int row, const Vector3 &vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, float val ) -{ - (*this)[col].setElem(row, val); - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::setElem( int col, int row, const floatInVec &val ) -{ - Vector3 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Matrix3::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol0( ) const -{ - return mCol0; -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol1( ) const -{ - return mCol1; -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol2( ) const -{ - return mCol2; -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::getRow( int row ) const -{ - return Vector3( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ) ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Matrix3::operator []( int col ) -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator =( const Matrix3 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ) -{ - __m128 tmp0, tmp1, res0, res1, res2; - tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); - tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); - res0 = vec_mergeh( tmp0, mat.getCol1().get128() ); - //res1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - res1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); - res1 = vec_sel(res1, mat.getCol1().get128(), select_y); - //res2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); - res2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); - res2 = vec_sel(res2, vec_splat(mat.getCol1().get128(), 2), select_y); - return Matrix3( - Vector3( res0 ), - Vector3( res1 ), - Vector3( res2 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ) -{ - __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet, inv0, inv1, inv2; - tmp2 = _vmathVfCross( mat.getCol0().get128(), mat.getCol1().get128() ); - tmp0 = _vmathVfCross( mat.getCol1().get128(), mat.getCol2().get128() ); - tmp1 = _vmathVfCross( mat.getCol2().get128(), mat.getCol0().get128() ); - dot = _vmathVfDot3( tmp2, mat.getCol2().get128() ); - dot = vec_splat( dot, 0 ); - invdet = recipf4( dot ); - tmp3 = vec_mergeh( tmp0, tmp2 ); - tmp4 = vec_mergel( tmp0, tmp2 ); - inv0 = vec_mergeh( tmp3, tmp1 ); - //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); - inv1 = vec_sel(inv1, tmp1, select_y); - //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); - inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); - inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); - inv0 = vec_mul( inv0, invdet ); - inv1 = vec_mul( inv1, invdet ); - inv2 = vec_mul( inv2, invdet ); - return Matrix3( - Vector3( inv0 ), - Vector3( inv1 ), - Vector3( inv2 ) - ); -} - -VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ) -{ - return dot( mat.getCol2(), cross( mat.getCol0(), mat.getCol1() ) ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator +( const Matrix3 & mat ) const -{ - return Matrix3( - ( mCol0 + mat.mCol0 ), - ( mCol1 + mat.mCol1 ), - ( mCol2 + mat.mCol2 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( const Matrix3 & mat ) const -{ - return Matrix3( - ( mCol0 - mat.mCol0 ), - ( mCol1 - mat.mCol1 ), - ( mCol2 - mat.mCol2 ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator +=( const Matrix3 & mat ) -{ - *this = *this + mat; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator -=( const Matrix3 & mat ) -{ - *this = *this - mat; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator -( ) const -{ - return Matrix3( - ( -mCol0 ), - ( -mCol1 ), - ( -mCol2 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ) -{ - return Matrix3( - absPerElem( mat.getCol0() ), - absPerElem( mat.getCol1() ), - absPerElem( mat.getCol2() ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( float scalar ) const -{ - return *this * floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const floatInVec &scalar ) const -{ - return Matrix3( - ( mCol0 * scalar ), - ( mCol1 * scalar ), - ( mCol2 * scalar ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( float scalar ) -{ - return *this *= floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const floatInVec &scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ) -{ - return floatInVec(scalar) * mat; -} - -VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ) -{ - return mat * scalar; -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix3::operator *( const Vector3 &vec ) const -{ - __m128 res; - __m128 xxxx, yyyy, zzzz; - xxxx = vec_splat( vec.get128(), 0 ); - yyyy = vec_splat( vec.get128(), 1 ); - zzzz = vec_splat( vec.get128(), 2 ); - res = vec_mul( mCol0.get128(), xxxx ); - res = vec_madd( mCol1.get128(), yyyy, res ); - res = vec_madd( mCol2.get128(), zzzz, res ); - return Vector3( res ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::operator *( const Matrix3 & mat ) const -{ - return Matrix3( - ( *this * mat.mCol0 ), - ( *this * mat.mCol1 ), - ( *this * mat.mCol2 ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix3 & Matrix3::operator *=( const Matrix3 & mat ) -{ - *this = *this * mat; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ) -{ - return Matrix3( - mulPerElem( mat0.getCol0(), mat1.getCol0() ), - mulPerElem( mat0.getCol1(), mat1.getCol1() ), - mulPerElem( mat0.getCol2(), mat1.getCol2() ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::identity( ) -{ - return Matrix3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( float radians ) -{ - return rotationX( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationX( const floatInVec &radians ) -{ - __m128 s, c, res1, res2; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res1 = vec_sel( zero, c, select_y ); - res1 = vec_sel( res1, s, select_z ); - res2 = vec_sel( zero, negatef4(s), select_y ); - res2 = vec_sel( res2, c, select_z ); - return Matrix3( - Vector3::xAxis( ), - Vector3( res1 ), - Vector3( res2 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( float radians ) -{ - return rotationY( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationY( const floatInVec &radians ) -{ - __m128 s, c, res0, res2; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res0 = vec_sel( zero, c, select_x ); - res0 = vec_sel( res0, negatef4(s), select_z ); - res2 = vec_sel( zero, s, select_x ); - res2 = vec_sel( res2, c, select_z ); - return Matrix3( - Vector3( res0 ), - Vector3::yAxis( ), - Vector3( res2 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( float radians ) -{ - return rotationZ( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZ( const floatInVec &radians ) -{ - __m128 s, c, res0, res1; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res0 = vec_sel( zero, c, select_x ); - res0 = vec_sel( res0, s, select_y ); - res1 = vec_sel( zero, negatef4(s), select_x ); - res1 = vec_sel( res1, c, select_y ); - return Matrix3( - Vector3( res0 ), - Vector3( res1 ), - Vector3::zAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotationZYX( const Vector3 &radiansXYZ ) -{ - __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; - angles = Vector4( radiansXYZ, 0.0f ).get128(); - sincosf4( angles, &s, &c ); - negS = negatef4( s ); - Z0 = vec_mergel( c, s ); - Z1 = vec_mergel( negS, c ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; - Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); - Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); - Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); - X0 = vec_splat( s, 0 ); - X1 = vec_splat( c, 0 ); - tmp = vec_mul( Z0, Y1 ); - return Matrix3( - Vector3( vec_mul( Z0, Y0 ) ), - Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), - Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( float radians, const Vector3 &unitVec ) -{ - return rotation( floatInVec(radians), unitVec ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const floatInVec &radians, const Vector3 &unitVec ) -{ - __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; - axis = unitVec.get128(); - sincosf4( radians.get128(), &s, &c ); - xxxx = vec_splat( axis, 0 ); - yyyy = vec_splat( axis, 1 ); - zzzz = vec_splat( axis, 2 ); - oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); - axisS = vec_mul( axis, s ); - negAxisS = negatef4( axisS ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); - tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); - tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); - //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); - tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); - //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); - tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); - tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); - tmp0 = vec_sel( tmp0, c, select_x ); - tmp1 = vec_sel( tmp1, c, select_y ); - tmp2 = vec_sel( tmp2, c, select_z ); - return Matrix3( - Vector3( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), - Vector3( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), - Vector3( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::rotation( const Quat &unitQuat ) -{ - return Matrix3( unitQuat ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix3::scale( const Vector3 &scaleVec ) -{ - __m128 zero = _mm_setzero_ps(); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - return Matrix3( - Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), - Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), - Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ) -{ - return Matrix3( - ( mat.getCol0() * scaleVec.getX( ) ), - ( mat.getCol1() * scaleVec.getY( ) ), - ( mat.getCol2() * scaleVec.getZ( ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ) -{ - return Matrix3( - mulPerElem( mat.getCol0(), scaleVec ), - mulPerElem( mat.getCol1(), scaleVec ), - mulPerElem( mat.getCol2(), scaleVec ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ) -{ - return Matrix3( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ) -{ - return Matrix3( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ) -{ - print( mat.getRow( 0 ) ); - print( mat.getRow( 1 ) ); - print( mat.getRow( 2 ) ); -} - -VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ) -{ - printf("%s:\n", name); - print( mat ); -} - -#endif - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix4 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - mCol3 = mat.mCol3; -} - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( float scalar ) -{ - mCol0 = Vector4( scalar ); - mCol1 = Vector4( scalar ); - mCol2 = Vector4( scalar ); - mCol3 = Vector4( scalar ); -} - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const floatInVec &scalar ) -{ - mCol0 = Vector4( scalar ); - mCol1 = Vector4( scalar ); - mCol2 = Vector4( scalar ); - mCol3 = Vector4( scalar ); -} - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Transform3 & mat ) -{ - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( mat.getCol3(), 1.0f ); -} - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Vector4 &_col0, const Vector4 &_col1, const Vector4 &_col2, const Vector4 &_col3 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; - mCol3 = _col3; -} - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Matrix3 & mat, const Vector3 &translateVec ) -{ - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( translateVec, 1.0f ); -} - -VECTORMATH_FORCE_INLINE Matrix4::Matrix4( const Quat &unitQuat, const Vector3 &translateVec ) -{ - Matrix3 mat; - mat = Matrix3( unitQuat ); - mCol0 = Vector4( mat.getCol0(), 0.0f ); - mCol1 = Vector4( mat.getCol1(), 0.0f ); - mCol2 = Vector4( mat.getCol2(), 0.0f ); - mCol3 = Vector4( translateVec, 1.0f ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol0( const Vector4 &_col0 ) -{ - mCol0 = _col0; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol1( const Vector4 &_col1 ) -{ - mCol1 = _col1; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol2( const Vector4 &_col2 ) -{ - mCol2 = _col2; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol3( const Vector4 &_col3 ) -{ - mCol3 = _col3; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setCol( int col, const Vector4 &vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setRow( int row, const Vector4 &vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - mCol3.setElem( row, vec.getElem( 3 ) ); - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, float val ) -{ - (*this)[col].setElem(row, val); - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setElem( int col, int row, const floatInVec &val ) -{ - Vector4 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Matrix4::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol0( ) const -{ - return mCol0; -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol1( ) const -{ - return mCol1; -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol2( ) const -{ - return mCol2; -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol3( ) const -{ - return mCol3; -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::getRow( int row ) const -{ - return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Matrix4::operator []( int col ) -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator =( const Matrix4 & mat ) -{ - mCol0 = mat.mCol0; - mCol1 = mat.mCol1; - mCol2 = mat.mCol2; - mCol3 = mat.mCol3; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ) -{ - __m128 tmp0, tmp1, tmp2, tmp3, res0, res1, res2, res3; - tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); - tmp1 = vec_mergeh( mat.getCol1().get128(), mat.getCol3().get128() ); - tmp2 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); - tmp3 = vec_mergel( mat.getCol1().get128(), mat.getCol3().get128() ); - res0 = vec_mergeh( tmp0, tmp1 ); - res1 = vec_mergel( tmp0, tmp1 ); - res2 = vec_mergeh( tmp2, tmp3 ); - res3 = vec_mergel( tmp2, tmp3 ); - return Matrix4( - Vector4( res0 ), - Vector4( res1 ), - Vector4( res2 ), - Vector4( res3 ) - ); -} - -// TODO: Tidy -static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathPNPN[4] = {0x00000000, 0x80000000, 0x00000000, 0x80000000}; -static VM_ATTRIBUTE_ALIGN16 const unsigned int _vmathNPNP[4] = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; -static VM_ATTRIBUTE_ALIGN16 const float _vmathZERONE[4] = {1.0f, 0.0f, 0.0f, 1.0f}; - -VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ) -{ - __m128 Va,Vb,Vc; - __m128 r1,r2,r3,tt,tt2; - __m128 sum,Det,RDet; - __m128 trns0,trns1,trns2,trns3; - - __m128 _L1 = mat.getCol0().get128(); - __m128 _L2 = mat.getCol1().get128(); - __m128 _L3 = mat.getCol2().get128(); - __m128 _L4 = mat.getCol3().get128(); - // Calculating the minterms for the first line. - - // _mm_ror_ps is just a macro using _mm_shuffle_ps(). - tt = _L4; tt2 = _mm_ror_ps(_L3,1); - Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3'dot V4 - Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3'dot V4" - Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ - - r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" - r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ - r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' - - tt = _L2; - Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); - Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); - Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); - - // Calculating the determinant. - Det = _mm_mul_ps(sum,_L1); - Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); - - const __m128 Sign_PNPN = _mm_load_ps((float *)_vmathPNPN); - const __m128 Sign_NPNP = _mm_load_ps((float *)_vmathNPNP); - - __m128 mtL1 = _mm_xor_ps(sum,Sign_PNPN); - - // Calculating the minterms of the second line (using previous results). - tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); - __m128 mtL2 = _mm_xor_ps(sum,Sign_NPNP); - - // Testing the determinant. - Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); - - // Calculating the minterms of the third line. - tt = _mm_ror_ps(_L1,1); - Va = _mm_mul_ps(tt,Vb); // V1' dot V2" - Vb = _mm_mul_ps(tt,Vc); // V1' dot V2^ - Vc = _mm_mul_ps(tt,_L2); // V1' dot V2 - - r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V1" dot V2^ - V1^ dot V2" - r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V1^ dot V2' - V1' dot V2^ - r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V1' dot V2" - V1" dot V2' - - tt = _mm_ror_ps(_L4,1); sum = _mm_mul_ps(tt,r1); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); - __m128 mtL3 = _mm_xor_ps(sum,Sign_PNPN); - - // Dividing is FASTER than rcp_nr! (Because rcp_nr causes many register-memory RWs). - RDet = _mm_div_ss(_mm_load_ss((float *)&_vmathZERONE), Det); // TODO: just 1.0f? - RDet = _mm_shuffle_ps(RDet,RDet,0x00); - - // Devide the first 12 minterms with the determinant. - mtL1 = _mm_mul_ps(mtL1, RDet); - mtL2 = _mm_mul_ps(mtL2, RDet); - mtL3 = _mm_mul_ps(mtL3, RDet); - - // Calculate the minterms of the forth line and devide by the determinant. - tt = _mm_ror_ps(_L3,1); sum = _mm_mul_ps(tt,r1); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); - __m128 mtL4 = _mm_xor_ps(sum,Sign_NPNP); - mtL4 = _mm_mul_ps(mtL4, RDet); - - // Now we just have to transpose the minterms matrix. - trns0 = _mm_unpacklo_ps(mtL1,mtL2); - trns1 = _mm_unpacklo_ps(mtL3,mtL4); - trns2 = _mm_unpackhi_ps(mtL1,mtL2); - trns3 = _mm_unpackhi_ps(mtL3,mtL4); - _L1 = _mm_movelh_ps(trns0,trns1); - _L2 = _mm_movehl_ps(trns1,trns0); - _L3 = _mm_movelh_ps(trns2,trns3); - _L4 = _mm_movehl_ps(trns3,trns2); - - return Matrix4( - Vector4( _L1 ), - Vector4( _L2 ), - Vector4( _L3 ), - Vector4( _L4 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ) -{ - Transform3 affineMat; - affineMat.setCol0( mat.getCol0().getXYZ( ) ); - affineMat.setCol1( mat.getCol1().getXYZ( ) ); - affineMat.setCol2( mat.getCol2().getXYZ( ) ); - affineMat.setCol3( mat.getCol3().getXYZ( ) ); - return Matrix4( inverse( affineMat ) ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ) -{ - Transform3 affineMat; - affineMat.setCol0( mat.getCol0().getXYZ( ) ); - affineMat.setCol1( mat.getCol1().getXYZ( ) ); - affineMat.setCol2( mat.getCol2().getXYZ( ) ); - affineMat.setCol3( mat.getCol3().getXYZ( ) ); - return Matrix4( orthoInverse( affineMat ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ) -{ - __m128 Va,Vb,Vc; - __m128 r1,r2,r3,tt,tt2; - __m128 sum,Det; - - __m128 _L1 = mat.getCol0().get128(); - __m128 _L2 = mat.getCol1().get128(); - __m128 _L3 = mat.getCol2().get128(); - __m128 _L4 = mat.getCol3().get128(); - // Calculating the minterms for the first line. - - // _mm_ror_ps is just a macro using _mm_shuffle_ps(). - tt = _L4; tt2 = _mm_ror_ps(_L3,1); - Vc = _mm_mul_ps(tt2,_mm_ror_ps(tt,0)); // V3' dot V4 - Va = _mm_mul_ps(tt2,_mm_ror_ps(tt,2)); // V3' dot V4" - Vb = _mm_mul_ps(tt2,_mm_ror_ps(tt,3)); // V3' dot V4^ - - r1 = _mm_sub_ps(_mm_ror_ps(Va,1),_mm_ror_ps(Vc,2)); // V3" dot V4^ - V3^ dot V4" - r2 = _mm_sub_ps(_mm_ror_ps(Vb,2),_mm_ror_ps(Vb,0)); // V3^ dot V4' - V3' dot V4^ - r3 = _mm_sub_ps(_mm_ror_ps(Va,0),_mm_ror_ps(Vc,1)); // V3' dot V4" - V3" dot V4' - - tt = _L2; - Va = _mm_ror_ps(tt,1); sum = _mm_mul_ps(Va,r1); - Vb = _mm_ror_ps(tt,2); sum = _mm_add_ps(sum,_mm_mul_ps(Vb,r2)); - Vc = _mm_ror_ps(tt,3); sum = _mm_add_ps(sum,_mm_mul_ps(Vc,r3)); - - // Calculating the determinant. - Det = _mm_mul_ps(sum,_L1); - Det = _mm_add_ps(Det,_mm_movehl_ps(Det,Det)); - - // Calculating the minterms of the second line (using previous results). - tt = _mm_ror_ps(_L1,1); sum = _mm_mul_ps(tt,r1); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r2)); - tt = _mm_ror_ps(tt,1); sum = _mm_add_ps(sum,_mm_mul_ps(tt,r3)); - - // Testing the determinant. - Det = _mm_sub_ss(Det,_mm_shuffle_ps(Det,Det,1)); - return floatInVec(Det, 0); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator +( const Matrix4 & mat ) const -{ - return Matrix4( - ( mCol0 + mat.mCol0 ), - ( mCol1 + mat.mCol1 ), - ( mCol2 + mat.mCol2 ), - ( mCol3 + mat.mCol3 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( const Matrix4 & mat ) const -{ - return Matrix4( - ( mCol0 - mat.mCol0 ), - ( mCol1 - mat.mCol1 ), - ( mCol2 - mat.mCol2 ), - ( mCol3 - mat.mCol3 ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator +=( const Matrix4 & mat ) -{ - *this = *this + mat; - return *this; -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator -=( const Matrix4 & mat ) -{ - *this = *this - mat; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator -( ) const -{ - return Matrix4( - ( -mCol0 ), - ( -mCol1 ), - ( -mCol2 ), - ( -mCol3 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ) -{ - return Matrix4( - absPerElem( mat.getCol0() ), - absPerElem( mat.getCol1() ), - absPerElem( mat.getCol2() ), - absPerElem( mat.getCol3() ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( float scalar ) const -{ - return *this * floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const floatInVec &scalar ) const -{ - return Matrix4( - ( mCol0 * scalar ), - ( mCol1 * scalar ), - ( mCol2 * scalar ), - ( mCol3 * scalar ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( float scalar ) -{ - return *this *= floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const floatInVec &scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ) -{ - return floatInVec(scalar) * mat; -} - -VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ) -{ - return mat * scalar; -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector4 &vec ) const -{ - return Vector4( - _mm_add_ps( - _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), - _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2))), _mm_mul_ps(mCol3.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(3,3,3,3))))) - ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Vector3 &vec ) const -{ - return Vector4( - _mm_add_ps( - _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(1,1,1,1)))), - _mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(vec.get128(), vec.get128(), _MM_SHUFFLE(2,2,2,2)))) - ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Matrix4::operator *( const Point3 &pnt ) const -{ - return Vector4( - _mm_add_ps( - _mm_add_ps(_mm_mul_ps(mCol0.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(0,0,0,0))), _mm_mul_ps(mCol1.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(1,1,1,1)))), - _mm_add_ps(_mm_mul_ps(mCol2.get128(), _mm_shuffle_ps(pnt.get128(), pnt.get128(), _MM_SHUFFLE(2,2,2,2))), mCol3.get128())) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Matrix4 & mat ) const -{ - return Matrix4( - ( *this * mat.mCol0 ), - ( *this * mat.mCol1 ), - ( *this * mat.mCol2 ), - ( *this * mat.mCol3 ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Matrix4 & mat ) -{ - *this = *this * mat; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::operator *( const Transform3 & tfrm ) const -{ - return Matrix4( - ( *this * tfrm.getCol0() ), - ( *this * tfrm.getCol1() ), - ( *this * tfrm.getCol2() ), - ( *this * Point3( tfrm.getCol3() ) ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::operator *=( const Transform3 & tfrm ) -{ - *this = *this * tfrm; - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ) -{ - return Matrix4( - mulPerElem( mat0.getCol0(), mat1.getCol0() ), - mulPerElem( mat0.getCol1(), mat1.getCol1() ), - mulPerElem( mat0.getCol2(), mat1.getCol2() ), - mulPerElem( mat0.getCol3(), mat1.getCol3() ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::identity( ) -{ - return Matrix4( - Vector4::xAxis( ), - Vector4::yAxis( ), - Vector4::zAxis( ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setUpper3x3( const Matrix3 & mat3 ) -{ - mCol0.setXYZ( mat3.getCol0() ); - mCol1.setXYZ( mat3.getCol1() ); - mCol2.setXYZ( mat3.getCol2() ); - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix3 Matrix4::getUpper3x3( ) const -{ - return Matrix3( - mCol0.getXYZ( ), - mCol1.getXYZ( ), - mCol2.getXYZ( ) - ); -} - -VECTORMATH_FORCE_INLINE Matrix4 & Matrix4::setTranslation( const Vector3 &translateVec ) -{ - mCol3.setXYZ( translateVec ); - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 Matrix4::getTranslation( ) const -{ - return mCol3.getXYZ( ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( float radians ) -{ - return rotationX( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationX( const floatInVec &radians ) -{ - __m128 s, c, res1, res2; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res1 = vec_sel( zero, c, select_y ); - res1 = vec_sel( res1, s, select_z ); - res2 = vec_sel( zero, negatef4(s), select_y ); - res2 = vec_sel( res2, c, select_z ); - return Matrix4( - Vector4::xAxis( ), - Vector4( res1 ), - Vector4( res2 ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( float radians ) -{ - return rotationY( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationY( const floatInVec &radians ) -{ - __m128 s, c, res0, res2; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res0 = vec_sel( zero, c, select_x ); - res0 = vec_sel( res0, negatef4(s), select_z ); - res2 = vec_sel( zero, s, select_x ); - res2 = vec_sel( res2, c, select_z ); - return Matrix4( - Vector4( res0 ), - Vector4::yAxis( ), - Vector4( res2 ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( float radians ) -{ - return rotationZ( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZ( const floatInVec &radians ) -{ - __m128 s, c, res0, res1; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res0 = vec_sel( zero, c, select_x ); - res0 = vec_sel( res0, s, select_y ); - res1 = vec_sel( zero, negatef4(s), select_x ); - res1 = vec_sel( res1, c, select_y ); - return Matrix4( - Vector4( res0 ), - Vector4( res1 ), - Vector4::zAxis( ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotationZYX( const Vector3 &radiansXYZ ) -{ - __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; - angles = Vector4( radiansXYZ, 0.0f ).get128(); - sincosf4( angles, &s, &c ); - negS = negatef4( s ); - Z0 = vec_mergel( c, s ); - Z1 = vec_mergel( negS, c ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; - Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); - Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); - Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); - X0 = vec_splat( s, 0 ); - X1 = vec_splat( c, 0 ); - tmp = vec_mul( Z0, Y1 ); - return Matrix4( - Vector4( vec_mul( Z0, Y0 ) ), - Vector4( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), - Vector4( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( float radians, const Vector3 &unitVec ) -{ - return rotation( floatInVec(radians), unitVec ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const floatInVec &radians, const Vector3 &unitVec ) -{ - __m128 axis, s, c, oneMinusC, axisS, negAxisS, xxxx, yyyy, zzzz, tmp0, tmp1, tmp2; - axis = unitVec.get128(); - sincosf4( radians.get128(), &s, &c ); - xxxx = vec_splat( axis, 0 ); - yyyy = vec_splat( axis, 1 ); - zzzz = vec_splat( axis, 2 ); - oneMinusC = vec_sub( _mm_set1_ps(1.0f), c ); - axisS = vec_mul( axis, s ); - negAxisS = negatef4( axisS ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - //tmp0 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_XZBX ); - tmp0 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,2,0) ); - tmp0 = vec_sel(tmp0, vec_splat(negAxisS, 1), select_z); - //tmp1 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_CXXX ); - tmp1 = vec_sel( vec_splat(axisS, 0), vec_splat(negAxisS, 2), select_x ); - //tmp2 = vec_perm( axisS, negAxisS, _VECTORMATH_PERM_YAXX ); - tmp2 = _mm_shuffle_ps( axisS, axisS, _MM_SHUFFLE(0,0,0,1) ); - tmp2 = vec_sel(tmp2, vec_splat(negAxisS, 0), select_y); - tmp0 = vec_sel( tmp0, c, select_x ); - tmp1 = vec_sel( tmp1, c, select_y ); - tmp2 = vec_sel( tmp2, c, select_z ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; - axis = vec_and( axis, _mm_load_ps( (float *)select_xyz ) ); - tmp0 = vec_and( tmp0, _mm_load_ps( (float *)select_xyz ) ); - tmp1 = vec_and( tmp1, _mm_load_ps( (float *)select_xyz ) ); - tmp2 = vec_and( tmp2, _mm_load_ps( (float *)select_xyz ) ); - return Matrix4( - Vector4( vec_madd( vec_mul( axis, xxxx ), oneMinusC, tmp0 ) ), - Vector4( vec_madd( vec_mul( axis, yyyy ), oneMinusC, tmp1 ) ), - Vector4( vec_madd( vec_mul( axis, zzzz ), oneMinusC, tmp2 ) ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::rotation( const Quat &unitQuat ) -{ - return Matrix4( Transform3::rotation( unitQuat ) ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::scale( const Vector3 &scaleVec ) -{ - __m128 zero = _mm_setzero_ps(); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - return Matrix4( - Vector4( vec_sel( zero, scaleVec.get128(), select_x ) ), - Vector4( vec_sel( zero, scaleVec.get128(), select_y ) ), - Vector4( vec_sel( zero, scaleVec.get128(), select_z ) ), - Vector4::wAxis( ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ) -{ - return Matrix4( - ( mat.getCol0() * scaleVec.getX( ) ), - ( mat.getCol1() * scaleVec.getY( ) ), - ( mat.getCol2() * scaleVec.getZ( ) ), - mat.getCol3() - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ) -{ - Vector4 scale4; - scale4 = Vector4( scaleVec, 1.0f ); - return Matrix4( - mulPerElem( mat.getCol0(), scale4 ), - mulPerElem( mat.getCol1(), scale4 ), - mulPerElem( mat.getCol2(), scale4 ), - mulPerElem( mat.getCol3(), scale4 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::translation( const Vector3 &translateVec ) -{ - return Matrix4( - Vector4::xAxis( ), - Vector4::yAxis( ), - Vector4::zAxis( ), - Vector4( translateVec, 1.0f ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ) -{ - Matrix4 m4EyeFrame; - Vector3 v3X, v3Y, v3Z; - v3Y = normalize( upVec ); - v3Z = normalize( ( eyePos - lookAtPos ) ); - v3X = normalize( cross( v3Y, v3Z ) ); - v3Y = cross( v3Z, v3X ); - m4EyeFrame = Matrix4( Vector4( v3X ), Vector4( v3Y ), Vector4( v3Z ), Vector4( eyePos ) ); - return orthoInverse( m4EyeFrame ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::perspective( float fovyRadians, float aspect, float zNear, float zFar ) -{ - float f, rangeInv; - __m128 zero, col0, col1, col2, col3; - union { __m128 v; float s[4]; } tmp; - f = tanf( _VECTORMATH_PI_OVER_2 - fovyRadians * 0.5f ); - rangeInv = 1.0f / ( zNear - zFar ); - zero = _mm_setzero_ps(); - tmp.v = zero; - tmp.s[0] = f / aspect; - col0 = tmp.v; - tmp.v = zero; - tmp.s[1] = f; - col1 = tmp.v; - tmp.v = zero; - tmp.s[2] = ( zNear + zFar ) * rangeInv; - tmp.s[3] = -1.0f; - col2 = tmp.v; - tmp.v = zero; - tmp.s[2] = zNear * zFar * rangeInv * 2.0f; - col3 = tmp.v; - return Matrix4( - Vector4( col0 ), - Vector4( col1 ), - Vector4( col2 ), - Vector4( col3 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::frustum( float left, float right, float bottom, float top, float zNear, float zFar ) -{ - /* function implementation based on code from STIDC SDK: */ - /* -------------------------------------------------------------- */ - /* PLEASE DO NOT MODIFY THIS SECTION */ - /* This prolog section is automatically generated. */ - /* */ - /* (C)Copyright */ - /* Sony Computer Entertainment, Inc., */ - /* Toshiba Corporation, */ - /* International Business Machines Corporation, */ - /* 2001,2002. */ - /* S/T/I Confidential Information */ - /* -------------------------------------------------------------- */ - __m128 lbf, rtn; - __m128 diff, sum, inv_diff; - __m128 diagonal, column, near2; - __m128 zero = _mm_setzero_ps(); - union { __m128 v; float s[4]; } l, f, r, n, b, t; // TODO: Union? - l.s[0] = left; - f.s[0] = zFar; - r.s[0] = right; - n.s[0] = zNear; - b.s[0] = bottom; - t.s[0] = top; - lbf = vec_mergeh( l.v, f.v ); - rtn = vec_mergeh( r.v, n.v ); - lbf = vec_mergeh( lbf, b.v ); - rtn = vec_mergeh( rtn, t.v ); - diff = vec_sub( rtn, lbf ); - sum = vec_add( rtn, lbf ); - inv_diff = recipf4( diff ); - near2 = vec_splat( n.v, 0 ); - near2 = vec_add( near2, near2 ); - diagonal = vec_mul( near2, inv_diff ); - column = vec_mul( sum, inv_diff ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; - return Matrix4( - Vector4( vec_sel( zero, diagonal, select_x ) ), - Vector4( vec_sel( zero, diagonal, select_y ) ), - Vector4( vec_sel( column, _mm_set1_ps(-1.0f), select_w ) ), - Vector4( vec_sel( zero, vec_mul( diagonal, vec_splat( f.v, 0 ) ), select_z ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 Matrix4::orthographic( float left, float right, float bottom, float top, float zNear, float zFar ) -{ - /* function implementation based on code from STIDC SDK: */ - /* -------------------------------------------------------------- */ - /* PLEASE DO NOT MODIFY THIS SECTION */ - /* This prolog section is automatically generated. */ - /* */ - /* (C)Copyright */ - /* Sony Computer Entertainment, Inc., */ - /* Toshiba Corporation, */ - /* International Business Machines Corporation, */ - /* 2001,2002. */ - /* S/T/I Confidential Information */ - /* -------------------------------------------------------------- */ - __m128 lbf, rtn; - __m128 diff, sum, inv_diff, neg_inv_diff; - __m128 diagonal, column; - __m128 zero = _mm_setzero_ps(); - union { __m128 v; float s[4]; } l, f, r, n, b, t; - l.s[0] = left; - f.s[0] = zFar; - r.s[0] = right; - n.s[0] = zNear; - b.s[0] = bottom; - t.s[0] = top; - lbf = vec_mergeh( l.v, f.v ); - rtn = vec_mergeh( r.v, n.v ); - lbf = vec_mergeh( lbf, b.v ); - rtn = vec_mergeh( rtn, t.v ); - diff = vec_sub( rtn, lbf ); - sum = vec_add( rtn, lbf ); - inv_diff = recipf4( diff ); - neg_inv_diff = negatef4( inv_diff ); - diagonal = vec_add( inv_diff, inv_diff ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; - column = vec_mul( sum, vec_sel( neg_inv_diff, inv_diff, select_z ) ); // TODO: no madds with zero - return Matrix4( - Vector4( vec_sel( zero, diagonal, select_x ) ), - Vector4( vec_sel( zero, diagonal, select_y ) ), - Vector4( vec_sel( zero, diagonal, select_z ) ), - Vector4( vec_sel( column, _mm_set1_ps(1.0f), select_w ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ) -{ - return Matrix4( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ), - select( mat0.getCol3(), mat1.getCol3(), select1 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ) -{ - return Matrix4( - select( mat0.getCol0(), mat1.getCol0(), select1 ), - select( mat0.getCol1(), mat1.getCol1(), select1 ), - select( mat0.getCol2(), mat1.getCol2(), select1 ), - select( mat0.getCol3(), mat1.getCol3(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ) -{ - print( mat.getRow( 0 ) ); - print( mat.getRow( 1 ) ); - print( mat.getRow( 2 ) ); - print( mat.getRow( 3 ) ); -} - -VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ) -{ - printf("%s:\n", name); - print( mat ); -} - -#endif - -VECTORMATH_FORCE_INLINE Transform3::Transform3( const Transform3 & tfrm ) -{ - mCol0 = tfrm.mCol0; - mCol1 = tfrm.mCol1; - mCol2 = tfrm.mCol2; - mCol3 = tfrm.mCol3; -} - -VECTORMATH_FORCE_INLINE Transform3::Transform3( float scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); - mCol3 = Vector3( scalar ); -} - -VECTORMATH_FORCE_INLINE Transform3::Transform3( const floatInVec &scalar ) -{ - mCol0 = Vector3( scalar ); - mCol1 = Vector3( scalar ); - mCol2 = Vector3( scalar ); - mCol3 = Vector3( scalar ); -} - -VECTORMATH_FORCE_INLINE Transform3::Transform3( const Vector3 &_col0, const Vector3 &_col1, const Vector3 &_col2, const Vector3 &_col3 ) -{ - mCol0 = _col0; - mCol1 = _col1; - mCol2 = _col2; - mCol3 = _col3; -} - -VECTORMATH_FORCE_INLINE Transform3::Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ) -{ - this->setUpper3x3( tfrm ); - this->setTranslation( translateVec ); -} - -VECTORMATH_FORCE_INLINE Transform3::Transform3( const Quat &unitQuat, const Vector3 &translateVec ) -{ - this->setUpper3x3( Matrix3( unitQuat ) ); - this->setTranslation( translateVec ); -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol0( const Vector3 &_col0 ) -{ - mCol0 = _col0; - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol1( const Vector3 &_col1 ) -{ - mCol1 = _col1; - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol2( const Vector3 &_col2 ) -{ - mCol2 = _col2; - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol3( const Vector3 &_col3 ) -{ - mCol3 = _col3; - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setCol( int col, const Vector3 &vec ) -{ - *(&mCol0 + col) = vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setRow( int row, const Vector4 &vec ) -{ - mCol0.setElem( row, vec.getElem( 0 ) ); - mCol1.setElem( row, vec.getElem( 1 ) ); - mCol2.setElem( row, vec.getElem( 2 ) ); - mCol3.setElem( row, vec.getElem( 3 ) ); - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, float val ) -{ - (*this)[col].setElem(row, val); - return *this; -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setElem( int col, int row, const floatInVec &val ) -{ - Vector3 tmpV3_0; - tmpV3_0 = this->getCol( col ); - tmpV3_0.setElem( row, val ); - this->setCol( col, tmpV3_0 ); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Transform3::getElem( int col, int row ) const -{ - return this->getCol( col ).getElem( row ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol0( ) const -{ - return mCol0; -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol1( ) const -{ - return mCol1; -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol2( ) const -{ - return mCol2; -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol3( ) const -{ - return mCol3; -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::getCol( int col ) const -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE const Vector4 Transform3::getRow( int row ) const -{ - return Vector4( mCol0.getElem( row ), mCol1.getElem( row ), mCol2.getElem( row ), mCol3.getElem( row ) ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Transform3::operator []( int col ) -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator []( int col ) const -{ - return *(&mCol0 + col); -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator =( const Transform3 & tfrm ) -{ - mCol0 = tfrm.mCol0; - mCol1 = tfrm.mCol1; - mCol2 = tfrm.mCol2; - mCol3 = tfrm.mCol3; - return *this; -} - -VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ) -{ - __m128 inv0, inv1, inv2, inv3; - __m128 tmp0, tmp1, tmp2, tmp3, tmp4, dot, invdet; - __m128 xxxx, yyyy, zzzz; - tmp2 = _vmathVfCross( tfrm.getCol0().get128(), tfrm.getCol1().get128() ); - tmp0 = _vmathVfCross( tfrm.getCol1().get128(), tfrm.getCol2().get128() ); - tmp1 = _vmathVfCross( tfrm.getCol2().get128(), tfrm.getCol0().get128() ); - inv3 = negatef4( tfrm.getCol3().get128() ); - dot = _vmathVfDot3( tmp2, tfrm.getCol2().get128() ); - dot = vec_splat( dot, 0 ); - invdet = recipf4( dot ); - tmp3 = vec_mergeh( tmp0, tmp2 ); - tmp4 = vec_mergel( tmp0, tmp2 ); - inv0 = vec_mergeh( tmp3, tmp1 ); - xxxx = vec_splat( inv3, 0 ); - //inv1 = vec_perm( tmp3, tmp1, _VECTORMATH_PERM_ZBWX ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - inv1 = _mm_shuffle_ps( tmp3, tmp3, _MM_SHUFFLE(0,3,2,2)); - inv1 = vec_sel(inv1, tmp1, select_y); - //inv2 = vec_perm( tmp4, tmp1, _VECTORMATH_PERM_XCYX ); - inv2 = _mm_shuffle_ps( tmp4, tmp4, _MM_SHUFFLE(0,1,1,0)); - inv2 = vec_sel(inv2, vec_splat(tmp1, 2), select_y); - yyyy = vec_splat( inv3, 1 ); - zzzz = vec_splat( inv3, 2 ); - inv3 = vec_mul( inv0, xxxx ); - inv3 = vec_madd( inv1, yyyy, inv3 ); - inv3 = vec_madd( inv2, zzzz, inv3 ); - inv0 = vec_mul( inv0, invdet ); - inv1 = vec_mul( inv1, invdet ); - inv2 = vec_mul( inv2, invdet ); - inv3 = vec_mul( inv3, invdet ); - return Transform3( - Vector3( inv0 ), - Vector3( inv1 ), - Vector3( inv2 ), - Vector3( inv3 ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ) -{ - __m128 inv0, inv1, inv2, inv3; - __m128 tmp0, tmp1; - __m128 xxxx, yyyy, zzzz; - tmp0 = vec_mergeh( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); - tmp1 = vec_mergel( tfrm.getCol0().get128(), tfrm.getCol2().get128() ); - inv3 = negatef4( tfrm.getCol3().get128() ); - inv0 = vec_mergeh( tmp0, tfrm.getCol1().get128() ); - xxxx = vec_splat( inv3, 0 ); - //inv1 = vec_perm( tmp0, tfrm.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - inv1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); - inv1 = vec_sel(inv1, tfrm.getCol1().get128(), select_y); - //inv2 = vec_perm( tmp1, tfrm.getCol1().get128(), _VECTORMATH_PERM_XCYX ); - inv2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); - inv2 = vec_sel(inv2, vec_splat(tfrm.getCol1().get128(), 2), select_y); - yyyy = vec_splat( inv3, 1 ); - zzzz = vec_splat( inv3, 2 ); - inv3 = vec_mul( inv0, xxxx ); - inv3 = vec_madd( inv1, yyyy, inv3 ); - inv3 = vec_madd( inv2, zzzz, inv3 ); - return Transform3( - Vector3( inv0 ), - Vector3( inv1 ), - Vector3( inv2 ), - Vector3( inv3 ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ) -{ - return Transform3( - absPerElem( tfrm.getCol0() ), - absPerElem( tfrm.getCol1() ), - absPerElem( tfrm.getCol2() ), - absPerElem( tfrm.getCol3() ) - ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::operator *( const Vector3 &vec ) const -{ - __m128 res; - __m128 xxxx, yyyy, zzzz; - xxxx = vec_splat( vec.get128(), 0 ); - yyyy = vec_splat( vec.get128(), 1 ); - zzzz = vec_splat( vec.get128(), 2 ); - res = vec_mul( mCol0.get128(), xxxx ); - res = vec_madd( mCol1.get128(), yyyy, res ); - res = vec_madd( mCol2.get128(), zzzz, res ); - return Vector3( res ); -} - -VECTORMATH_FORCE_INLINE const Point3 Transform3::operator *( const Point3 &pnt ) const -{ - __m128 tmp0, tmp1, res; - __m128 xxxx, yyyy, zzzz; - xxxx = vec_splat( pnt.get128(), 0 ); - yyyy = vec_splat( pnt.get128(), 1 ); - zzzz = vec_splat( pnt.get128(), 2 ); - tmp0 = vec_mul( mCol0.get128(), xxxx ); - tmp1 = vec_mul( mCol1.get128(), yyyy ); - tmp0 = vec_madd( mCol2.get128(), zzzz, tmp0 ); - tmp1 = vec_add( mCol3.get128(), tmp1 ); - res = vec_add( tmp0, tmp1 ); - return Point3( res ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::operator *( const Transform3 & tfrm ) const -{ - return Transform3( - ( *this * tfrm.mCol0 ), - ( *this * tfrm.mCol1 ), - ( *this * tfrm.mCol2 ), - Vector3( ( *this * Point3( tfrm.mCol3 ) ) ) - ); -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::operator *=( const Transform3 & tfrm ) -{ - *this = *this * tfrm; - return *this; -} - -VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ) -{ - return Transform3( - mulPerElem( tfrm0.getCol0(), tfrm1.getCol0() ), - mulPerElem( tfrm0.getCol1(), tfrm1.getCol1() ), - mulPerElem( tfrm0.getCol2(), tfrm1.getCol2() ), - mulPerElem( tfrm0.getCol3(), tfrm1.getCol3() ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::identity( ) -{ - return Transform3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ), - Vector3( 0.0f ) - ); -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setUpper3x3( const Matrix3 & tfrm ) -{ - mCol0 = tfrm.getCol0(); - mCol1 = tfrm.getCol1(); - mCol2 = tfrm.getCol2(); - return *this; -} - -VECTORMATH_FORCE_INLINE const Matrix3 Transform3::getUpper3x3( ) const -{ - return Matrix3( mCol0, mCol1, mCol2 ); -} - -VECTORMATH_FORCE_INLINE Transform3 & Transform3::setTranslation( const Vector3 &translateVec ) -{ - mCol3 = translateVec; - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 Transform3::getTranslation( ) const -{ - return mCol3; -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( float radians ) -{ - return rotationX( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationX( const floatInVec &radians ) -{ - __m128 s, c, res1, res2; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res1 = vec_sel( zero, c, select_y ); - res1 = vec_sel( res1, s, select_z ); - res2 = vec_sel( zero, negatef4(s), select_y ); - res2 = vec_sel( res2, c, select_z ); - return Transform3( - Vector3::xAxis( ), - Vector3( res1 ), - Vector3( res2 ), - Vector3( _mm_setzero_ps() ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( float radians ) -{ - return rotationY( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationY( const floatInVec &radians ) -{ - __m128 s, c, res0, res2; - __m128 zero; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res0 = vec_sel( zero, c, select_x ); - res0 = vec_sel( res0, negatef4(s), select_z ); - res2 = vec_sel( zero, s, select_x ); - res2 = vec_sel( res2, c, select_z ); - return Transform3( - Vector3( res0 ), - Vector3::yAxis( ), - Vector3( res2 ), - Vector3( 0.0f ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( float radians ) -{ - return rotationZ( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZ( const floatInVec &radians ) -{ - __m128 s, c, res0, res1; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - __m128 zero = _mm_setzero_ps(); - sincosf4( radians.get128(), &s, &c ); - res0 = vec_sel( zero, c, select_x ); - res0 = vec_sel( res0, s, select_y ); - res1 = vec_sel( zero, negatef4(s), select_x ); - res1 = vec_sel( res1, c, select_y ); - return Transform3( - Vector3( res0 ), - Vector3( res1 ), - Vector3::zAxis( ), - Vector3( 0.0f ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotationZYX( const Vector3 &radiansXYZ ) -{ - __m128 angles, s, negS, c, X0, X1, Y0, Y1, Z0, Z1, tmp; - angles = Vector4( radiansXYZ, 0.0f ).get128(); - sincosf4( angles, &s, &c ); - negS = negatef4( s ); - Z0 = vec_mergel( c, s ); - Z1 = vec_mergel( negS, c ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_xyz[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0}; - Z1 = vec_and( Z1, _mm_load_ps( (float *)select_xyz ) ); - Y0 = _mm_shuffle_ps( c, negS, _MM_SHUFFLE(0,1,1,1) ); - Y1 = _mm_shuffle_ps( s, c, _MM_SHUFFLE(0,1,1,1) ); - X0 = vec_splat( s, 0 ); - X1 = vec_splat( c, 0 ); - tmp = vec_mul( Z0, Y1 ); - return Transform3( - Vector3( vec_mul( Z0, Y0 ) ), - Vector3( vec_madd( Z1, X1, vec_mul( tmp, X0 ) ) ), - Vector3( vec_nmsub( Z1, X0, vec_mul( tmp, X1 ) ) ), - Vector3( 0.0f ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( float radians, const Vector3 &unitVec ) -{ - return rotation( floatInVec(radians), unitVec ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const floatInVec &radians, const Vector3 &unitVec ) -{ - return Transform3( Matrix3::rotation( radians, unitVec ), Vector3( 0.0f ) ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::rotation( const Quat &unitQuat ) -{ - return Transform3( Matrix3( unitQuat ), Vector3( 0.0f ) ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::scale( const Vector3 &scaleVec ) -{ - __m128 zero = _mm_setzero_ps(); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - return Transform3( - Vector3( vec_sel( zero, scaleVec.get128(), select_x ) ), - Vector3( vec_sel( zero, scaleVec.get128(), select_y ) ), - Vector3( vec_sel( zero, scaleVec.get128(), select_z ) ), - Vector3( 0.0f ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ) -{ - return Transform3( - ( tfrm.getCol0() * scaleVec.getX( ) ), - ( tfrm.getCol1() * scaleVec.getY( ) ), - ( tfrm.getCol2() * scaleVec.getZ( ) ), - tfrm.getCol3() - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ) -{ - return Transform3( - mulPerElem( tfrm.getCol0(), scaleVec ), - mulPerElem( tfrm.getCol1(), scaleVec ), - mulPerElem( tfrm.getCol2(), scaleVec ), - mulPerElem( tfrm.getCol3(), scaleVec ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 Transform3::translation( const Vector3 &translateVec ) -{ - return Transform3( - Vector3::xAxis( ), - Vector3::yAxis( ), - Vector3::zAxis( ), - translateVec - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ) -{ - return Transform3( - select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), - select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), - select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), - select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) - ); -} - -VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ) -{ - return Transform3( - select( tfrm0.getCol0(), tfrm1.getCol0(), select1 ), - select( tfrm0.getCol1(), tfrm1.getCol1(), select1 ), - select( tfrm0.getCol2(), tfrm1.getCol2(), select1 ), - select( tfrm0.getCol3(), tfrm1.getCol3(), select1 ) - ); -} - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ) -{ - print( tfrm.getRow( 0 ) ); - print( tfrm.getRow( 1 ) ); - print( tfrm.getRow( 2 ) ); -} - -VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ) -{ - printf("%s:\n", name); - print( tfrm ); -} - -#endif - -VECTORMATH_FORCE_INLINE Quat::Quat( const Matrix3 & tfrm ) -{ - __m128 res; - __m128 col0, col1, col2; - __m128 xx_yy, xx_yy_zz_xx, yy_zz_xx_yy, zz_xx_yy_zz, diagSum, diagDiff; - __m128 zy_xz_yx, yz_zx_xy, sum, diff; - __m128 radicand, invSqrt, scale; - __m128 res0, res1, res2, res3; - __m128 xx, yy, zz; - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_w[4] = {0, 0, 0, 0xffffffff}; - - col0 = tfrm.getCol0().get128(); - col1 = tfrm.getCol1().get128(); - col2 = tfrm.getCol2().get128(); - - /* four cases: */ - /* trace > 0 */ - /* else */ - /* xx largest diagonal element */ - /* yy largest diagonal element */ - /* zz largest diagonal element */ - - /* compute quaternion for each case */ - - xx_yy = vec_sel( col0, col1, select_y ); - //xx_yy_zz_xx = vec_perm( xx_yy, col2, _VECTORMATH_PERM_XYCX ); - //yy_zz_xx_yy = vec_perm( xx_yy, col2, _VECTORMATH_PERM_YCXY ); - //zz_xx_yy_zz = vec_perm( xx_yy, col2, _VECTORMATH_PERM_CXYC ); - xx_yy_zz_xx = _mm_shuffle_ps( xx_yy, xx_yy, _MM_SHUFFLE(0,0,1,0) ); - xx_yy_zz_xx = vec_sel( xx_yy_zz_xx, col2, select_z ); // TODO: Ck - yy_zz_xx_yy = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(1,0,2,1) ); - zz_xx_yy_zz = _mm_shuffle_ps( xx_yy_zz_xx, xx_yy_zz_xx, _MM_SHUFFLE(2,1,0,2) ); - - diagSum = vec_add( vec_add( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); - diagDiff = vec_sub( vec_sub( xx_yy_zz_xx, yy_zz_xx_yy ), zz_xx_yy_zz ); - radicand = vec_add( vec_sel( diagDiff, diagSum, select_w ), _mm_set1_ps(1.0f) ); - // invSqrt = rsqrtf4( radicand ); - invSqrt = newtonrapson_rsqrt4( radicand ); - - - - zy_xz_yx = vec_sel( col0, col1, select_z ); // zy_xz_yx = 00 01 12 03 - //zy_xz_yx = vec_perm( zy_xz_yx, col2, _VECTORMATH_PERM_ZAYX ); - zy_xz_yx = _mm_shuffle_ps( zy_xz_yx, zy_xz_yx, _MM_SHUFFLE(0,1,2,2) ); // zy_xz_yx = 12 12 01 00 - zy_xz_yx = vec_sel( zy_xz_yx, vec_splat(col2, 0), select_y ); // zy_xz_yx = 12 20 01 00 - yz_zx_xy = vec_sel( col0, col1, select_x ); // yz_zx_xy = 10 01 02 03 - //yz_zx_xy = vec_perm( yz_zx_xy, col2, _VECTORMATH_PERM_BZXX ); - yz_zx_xy = _mm_shuffle_ps( yz_zx_xy, yz_zx_xy, _MM_SHUFFLE(0,0,2,0) ); // yz_zx_xy = 10 02 10 10 - yz_zx_xy = vec_sel( yz_zx_xy, vec_splat(col2, 1), select_x ); // yz_zx_xy = 21 02 10 10 - - sum = vec_add( zy_xz_yx, yz_zx_xy ); - diff = vec_sub( zy_xz_yx, yz_zx_xy ); - - scale = vec_mul( invSqrt, _mm_set1_ps(0.5f) ); - - //res0 = vec_perm( sum, diff, _VECTORMATH_PERM_XZYA ); - res0 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,1,2,0) ); - res0 = vec_sel( res0, vec_splat(diff, 0), select_w ); // TODO: Ck - //res1 = vec_perm( sum, diff, _VECTORMATH_PERM_ZXXB ); - res1 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,2) ); - res1 = vec_sel( res1, vec_splat(diff, 1), select_w ); // TODO: Ck - //res2 = vec_perm( sum, diff, _VECTORMATH_PERM_YXXC ); - res2 = _mm_shuffle_ps( sum, sum, _MM_SHUFFLE(0,0,0,1) ); - res2 = vec_sel( res2, vec_splat(diff, 2), select_w ); // TODO: Ck - res3 = diff; - res0 = vec_sel( res0, radicand, select_x ); - res1 = vec_sel( res1, radicand, select_y ); - res2 = vec_sel( res2, radicand, select_z ); - res3 = vec_sel( res3, radicand, select_w ); - res0 = vec_mul( res0, vec_splat( scale, 0 ) ); - res1 = vec_mul( res1, vec_splat( scale, 1 ) ); - res2 = vec_mul( res2, vec_splat( scale, 2 ) ); - res3 = vec_mul( res3, vec_splat( scale, 3 ) ); - - /* determine case and select answer */ - - xx = vec_splat( col0, 0 ); - yy = vec_splat( col1, 1 ); - zz = vec_splat( col2, 2 ); - res = vec_sel( res0, res1, vec_cmpgt( yy, xx ) ); - res = vec_sel( res, res2, vec_and( vec_cmpgt( zz, xx ), vec_cmpgt( zz, yy ) ) ); - res = vec_sel( res, res3, vec_cmpgt( vec_splat( diagSum, 0 ), _mm_setzero_ps() ) ); - mVec128 = res; -} - -VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &tfrm0, const Vector3 &tfrm1 ) -{ - return Matrix3( - ( tfrm0 * tfrm1.getX( ) ), - ( tfrm0 * tfrm1.getY( ) ), - ( tfrm0 * tfrm1.getZ( ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &tfrm0, const Vector4 &tfrm1 ) -{ - return Matrix4( - ( tfrm0 * tfrm1.getX( ) ), - ( tfrm0 * tfrm1.getY( ) ), - ( tfrm0 * tfrm1.getZ( ) ), - ( tfrm0 * tfrm1.getW( ) ) - ); -} - -VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ) -{ - __m128 tmp0, tmp1, mcol0, mcol1, mcol2, res; - __m128 xxxx, yyyy, zzzz; - tmp0 = vec_mergeh( mat.getCol0().get128(), mat.getCol2().get128() ); - tmp1 = vec_mergel( mat.getCol0().get128(), mat.getCol2().get128() ); - xxxx = vec_splat( vec.get128(), 0 ); - mcol0 = vec_mergeh( tmp0, mat.getCol1().get128() ); - //mcol1 = vec_perm( tmp0, mat.getCol1().get128(), _VECTORMATH_PERM_ZBWX ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - mcol1 = _mm_shuffle_ps( tmp0, tmp0, _MM_SHUFFLE(0,3,2,2)); - mcol1 = vec_sel(mcol1, mat.getCol1().get128(), select_y); - //mcol2 = vec_perm( tmp1, mat.getCol1().get128(), _VECTORMATH_PERM_XCYX ); - mcol2 = _mm_shuffle_ps( tmp1, tmp1, _MM_SHUFFLE(0,1,1,0)); - mcol2 = vec_sel(mcol2, vec_splat(mat.getCol1().get128(), 2), select_y); - yyyy = vec_splat( vec.get128(), 1 ); - res = vec_mul( mcol0, xxxx ); - zzzz = vec_splat( vec.get128(), 2 ); - res = vec_madd( mcol1, yyyy, res ); - res = vec_madd( mcol2, zzzz, res ); - return Vector3( res ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ) -{ - __m128 neg, res0, res1, res2; - neg = negatef4( vec.get128() ); - VM_ATTRIBUTE_ALIGN16 unsigned int select_x[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_y[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int select_z[4] = {0, 0, 0xffffffff, 0}; - //res0 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_XZBX ); - res0 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,2,2,0) ); - res0 = vec_sel(res0, vec_splat(neg, 1), select_z); - //res1 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_CXXX ); - res1 = vec_sel(vec_splat(vec.get128(), 0), vec_splat(neg, 2), select_x); - //res2 = vec_perm( vec.get128(), neg, _VECTORMATH_PERM_YAXX ); - res2 = _mm_shuffle_ps( vec.get128(), vec.get128(), _MM_SHUFFLE(0,0,1,1) ); - res2 = vec_sel(res2, vec_splat(neg, 0), select_y); - VM_ATTRIBUTE_ALIGN16 unsigned int filter_x[4] = {0, 0xffffffff, 0xffffffff, 0xffffffff}; - VM_ATTRIBUTE_ALIGN16 unsigned int filter_y[4] = {0xffffffff, 0, 0xffffffff, 0xffffffff}; - VM_ATTRIBUTE_ALIGN16 unsigned int filter_z[4] = {0xffffffff, 0xffffffff, 0, 0xffffffff}; - res0 = vec_and( res0, _mm_load_ps((float *)filter_x ) ); - res1 = vec_and( res1, _mm_load_ps((float *)filter_y ) ); - res2 = vec_and( res2, _mm_load_ps((float *)filter_z ) ); // TODO: Use selects? - return Matrix3( - Vector3( res0 ), - Vector3( res1 ), - Vector3( res2 ) - ); -} - -VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ) -{ - return Matrix3( cross( vec, mat.getCol0() ), cross( vec, mat.getCol1() ), cross( vec, mat.getCol2() ) ); -} - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/quat_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/quat_aos.h deleted file mode 100644 index 7eac59fe..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/quat_aos.h +++ /dev/null @@ -1,579 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _VECTORMATH_QUAT_AOS_CPP_H -#define _VECTORMATH_QUAT_AOS_CPP_H - -//----------------------------------------------------------------------------- -// Definitions - -#ifndef _VECTORMATH_INTERNAL_FUNCTIONS -#define _VECTORMATH_INTERNAL_FUNCTIONS - -#endif - -namespace Vectormath { -namespace Aos { - -VECTORMATH_FORCE_INLINE void Quat::set128(vec_float4 vec) -{ - mVec128 = vec; -} - -VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) -{ - mVec128 = _mm_unpacklo_ps( - _mm_unpacklo_ps( _x.get128(), _z.get128() ), - _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, float _w ) -{ - mVec128 = xyz.get128(); - _vmathVfSetElement(mVec128, _w, 3); -} - - - -VECTORMATH_FORCE_INLINE Quat::Quat(const Quat& quat) -{ - mVec128 = quat.get128(); -} - -VECTORMATH_FORCE_INLINE Quat::Quat( float _x, float _y, float _z, float _w ) -{ - mVec128 = _mm_setr_ps(_x, _y, _z, _w); -} - - - - - -VECTORMATH_FORCE_INLINE Quat::Quat( const Vector3 &xyz, const floatInVec &_w ) -{ - mVec128 = xyz.get128(); - mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); -} - -VECTORMATH_FORCE_INLINE Quat::Quat( const Vector4 &vec ) -{ - mVec128 = vec.get128(); -} - -VECTORMATH_FORCE_INLINE Quat::Quat( float scalar ) -{ - mVec128 = floatInVec(scalar).get128(); -} - -VECTORMATH_FORCE_INLINE Quat::Quat( const floatInVec &scalar ) -{ - mVec128 = scalar.get128(); -} - -VECTORMATH_FORCE_INLINE Quat::Quat( __m128 vf4 ) -{ - mVec128 = vf4; -} - -VECTORMATH_FORCE_INLINE const Quat Quat::identity( ) -{ - return Quat( _VECTORMATH_UNIT_0001 ); -} - -VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ) -{ - return lerp( floatInVec(t), quat0, quat1 ); -} - -VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ) -{ - return ( quat0 + ( ( quat1 - quat0 ) * t ) ); -} - -VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ) -{ - return slerp( floatInVec(t), unitQuat0, unitQuat1 ); -} - -VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ) -{ - Quat start; - vec_float4 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; - __m128 selectMask; - cosAngle = _vmathVfDot4( unitQuat0.get128(), unitQuat1.get128() ); - selectMask = (__m128)vec_cmpgt( _mm_setzero_ps(), cosAngle ); - cosAngle = vec_sel( cosAngle, negatef4( cosAngle ), selectMask ); - start = Quat( vec_sel( unitQuat0.get128(), negatef4( unitQuat0.get128() ), selectMask ) ); - selectMask = (__m128)vec_cmpgt( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); - angle = acosf4( cosAngle ); - tttt = t.get128(); - oneMinusT = vec_sub( _mm_set1_ps(1.0f), tttt ); - angles = vec_mergeh( _mm_set1_ps(1.0f), tttt ); - angles = vec_mergeh( angles, oneMinusT ); - angles = vec_madd( angles, angle, _mm_setzero_ps() ); - sines = sinf4( angles ); - scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); - scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); - scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); - return Quat( vec_madd( start.get128(), scale0, vec_mul( unitQuat1.get128(), scale1 ) ) ); -} - -VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) -{ - return squad( floatInVec(t), unitQuat0, unitQuat1, unitQuat2, unitQuat3 ); -} - -VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ) -{ - return slerp( ( ( floatInVec(2.0f) * t ) * ( floatInVec(1.0f) - t ) ), slerp( t, unitQuat0, unitQuat3 ), slerp( t, unitQuat1, unitQuat2 ) ); -} - -VECTORMATH_FORCE_INLINE __m128 Quat::get128( ) const -{ - return mVec128; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator =( const Quat &quat ) -{ - mVec128 = quat.mVec128; - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setXYZ( const Vector3 &vec ) -{ - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; - mVec128 = vec_sel( vec.get128(), mVec128, sw ); - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 Quat::getXYZ( ) const -{ - return Vector3( mVec128 ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setX( float _x ) -{ - _vmathVfSetElement(mVec128, _x, 0); - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setX( const floatInVec &_x ) -{ - mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Quat::getX( ) const -{ - return floatInVec( mVec128, 0 ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setY( float _y ) -{ - _vmathVfSetElement(mVec128, _y, 1); - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setY( const floatInVec &_y ) -{ - mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Quat::getY( ) const -{ - return floatInVec( mVec128, 1 ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setZ( float _z ) -{ - _vmathVfSetElement(mVec128, _z, 2); - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setZ( const floatInVec &_z ) -{ - mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Quat::getZ( ) const -{ - return floatInVec( mVec128, 2 ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setW( float _w ) -{ - _vmathVfSetElement(mVec128, _w, 3); - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setW( const floatInVec &_w ) -{ - mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Quat::getW( ) const -{ - return floatInVec( mVec128, 3 ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, float value ) -{ - _vmathVfSetElement(mVec128, value, idx); - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::setElem( int idx, const floatInVec &value ) -{ - mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Quat::getElem( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE VecIdx Quat::operator []( int idx ) -{ - return VecIdx( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const floatInVec Quat::operator []( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator +( const Quat &quat ) const -{ - return Quat( _mm_add_ps( mVec128, quat.mVec128 ) ); -} - - -VECTORMATH_FORCE_INLINE const Quat Quat::operator -( const Quat &quat ) const -{ - return Quat( _mm_sub_ps( mVec128, quat.mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator *( float scalar ) const -{ - return *this * floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const floatInVec &scalar ) const -{ - return Quat( _mm_mul_ps( mVec128, scalar.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator +=( const Quat &quat ) -{ - *this = *this + quat; - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator -=( const Quat &quat ) -{ - *this = *this - quat; - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const floatInVec &scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator /( float scalar ) const -{ - return *this / floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator /( const floatInVec &scalar ) const -{ - return Quat( _mm_div_ps( mVec128, scalar.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator /=( const floatInVec &scalar ) -{ - *this = *this / scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator -( ) const -{ - return Quat(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ) -{ - return floatInVec(scalar) * quat; -} - -VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ) -{ - return quat * scalar; -} - -VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ) -{ - return floatInVec( _vmathVfDot4( quat0.get128(), quat1.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ) -{ - return floatInVec( _vmathVfDot4( quat.get128(), quat.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ) -{ - return floatInVec( _mm_sqrt_ps(_vmathVfDot4( quat.get128(), quat.get128() )), 0 ); -} - -VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ) -{ - vec_float4 dot =_vmathVfDot4( quat.get128(), quat.get128()); - return Quat( _mm_mul_ps( quat.get128(), newtonrapson_rsqrt4( dot ) ) ); -} - - -VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ) -{ - Vector3 crossVec; - __m128 cosAngle, cosAngleX2Plus2, recipCosHalfAngleX2, cosHalfAngleX2, res; - cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); - cosAngleX2Plus2 = vec_madd( cosAngle, _mm_set1_ps(2.0f), _mm_set1_ps(2.0f) ); - recipCosHalfAngleX2 = _mm_rsqrt_ps( cosAngleX2Plus2 ); - cosHalfAngleX2 = vec_mul( recipCosHalfAngleX2, cosAngleX2Plus2 ); - crossVec = cross( unitVec0, unitVec1 ); - res = vec_mul( crossVec.get128(), recipCosHalfAngleX2 ); - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; - res = vec_sel( res, vec_mul( cosHalfAngleX2, _mm_set1_ps(0.5f) ), sw ); - return Quat( res ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotation( float radians, const Vector3 &unitVec ) -{ - return rotation( floatInVec(radians), unitVec ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotation( const floatInVec &radians, const Vector3 &unitVec ) -{ - __m128 s, c, angle, res; - angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); - sincosf4( angle, &s, &c ); - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; - res = vec_sel( vec_mul( unitVec.get128(), s ), c, sw ); - return Quat( res ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( float radians ) -{ - return rotationX( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotationX( const floatInVec &radians ) -{ - __m128 s, c, angle, res; - angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); - sincosf4( angle, &s, &c ); - VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0xffffffff, 0, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; - res = vec_sel( _mm_setzero_ps(), s, xsw ); - res = vec_sel( res, c, wsw ); - return Quat( res ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( float radians ) -{ - return rotationY( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotationY( const floatInVec &radians ) -{ - __m128 s, c, angle, res; - angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); - sincosf4( angle, &s, &c ); - VM_ATTRIBUTE_ALIGN16 unsigned int ysw[4] = {0, 0xffffffff, 0, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; - res = vec_sel( _mm_setzero_ps(), s, ysw ); - res = vec_sel( res, c, wsw ); - return Quat( res ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( float radians ) -{ - return rotationZ( floatInVec(radians) ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::rotationZ( const floatInVec &radians ) -{ - __m128 s, c, angle, res; - angle = vec_mul( radians.get128(), _mm_set1_ps(0.5f) ); - sincosf4( angle, &s, &c ); - VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0, 0, 0xffffffff, 0}; - VM_ATTRIBUTE_ALIGN16 unsigned int wsw[4] = {0, 0, 0, 0xffffffff}; - res = vec_sel( _mm_setzero_ps(), s, zsw ); - res = vec_sel( res, c, wsw ); - return Quat( res ); -} - -VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const Quat &quat ) const -{ - __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3; - __m128 product, l_wxyz, r_wxyz, xy, qw; - ldata = mVec128; - rdata = quat.mVec128; - tmp0 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,0,2,1) ); - tmp1 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,1,0,2) ); - tmp2 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,1,0,2) ); - tmp3 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,0,2,1) ); - qv = vec_mul( vec_splat( ldata, 3 ), rdata ); - qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv ); - qv = vec_madd( tmp0, tmp1, qv ); - qv = vec_nmsub( tmp2, tmp3, qv ); - product = vec_mul( ldata, rdata ); - l_wxyz = vec_sld( ldata, ldata, 12 ); - r_wxyz = vec_sld( rdata, rdata, 12 ); - qw = vec_nmsub( l_wxyz, r_wxyz, product ); - xy = vec_madd( l_wxyz, r_wxyz, product ); - qw = vec_sub( qw, vec_sld( xy, xy, 8 ) ); - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; - return Quat( vec_sel( qv, qw, sw ) ); -} - -VECTORMATH_FORCE_INLINE Quat & Quat::operator *=( const Quat &quat ) -{ - *this = *this * quat; - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &quat, const Vector3 &vec ) -{ __m128 qdata, vdata, product, tmp0, tmp1, tmp2, tmp3, wwww, qv, qw, res; - qdata = quat.get128(); - vdata = vec.get128(); - tmp0 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,0,2,1) ); - tmp1 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,1,0,2) ); - tmp2 = _mm_shuffle_ps( qdata, qdata, _MM_SHUFFLE(3,1,0,2) ); - tmp3 = _mm_shuffle_ps( vdata, vdata, _MM_SHUFFLE(3,0,2,1) ); - wwww = vec_splat( qdata, 3 ); - qv = vec_mul( wwww, vdata ); - qv = vec_madd( tmp0, tmp1, qv ); - qv = vec_nmsub( tmp2, tmp3, qv ); - product = vec_mul( qdata, vdata ); - qw = vec_madd( vec_sld( qdata, qdata, 4 ), vec_sld( vdata, vdata, 4 ), product ); - qw = vec_add( vec_sld( product, product, 8 ), qw ); - tmp1 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,1,0,2) ); - tmp3 = _mm_shuffle_ps( qv, qv, _MM_SHUFFLE(3,0,2,1) ); - res = vec_mul( vec_splat( qw, 0 ), qdata ); - res = vec_madd( wwww, qv, res ); - res = vec_madd( tmp0, tmp1, res ); - res = vec_nmsub( tmp2, tmp3, res ); - return Vector3( res ); -} - -VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ) -{ - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0x80000000,0x80000000,0x80000000,0}; - return Quat( vec_xor( quat.get128(), _mm_load_ps((float *)sw) ) ); -} - -VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ) -{ - return select( quat0, quat1, boolInVec(select1) ); -} - -//VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ) -//{ -// return Quat( vec_sel( quat0.get128(), quat1.get128(), select1.get128() ) ); -//} - -VECTORMATH_FORCE_INLINE void loadXYZW(Quat& quat, const float* fptr) -{ -#ifdef USE_SSE3_LDDQU - quat = Quat( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); -#else - SSEFloat fl; - fl.f[0] = fptr[0]; - fl.f[1] = fptr[1]; - fl.f[2] = fptr[2]; - fl.f[3] = fptr[3]; - quat = Quat( fl.m128); -#endif - - -} - -VECTORMATH_FORCE_INLINE void storeXYZW(const Quat& quat, float* fptr) -{ - fptr[0] = quat.getX(); - fptr[1] = quat.getY(); - fptr[2] = quat.getZ(); - fptr[3] = quat.getW(); -// _mm_storeu_ps((float*)quat.get128(),fptr); -} - - - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Quat &quat ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = quat.get128(); - printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); -} - -VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = quat.get128(); - printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); -} - -#endif - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/vec_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/vec_aos.h deleted file mode 100644 index 35aeeaf1..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/vec_aos.h +++ /dev/null @@ -1,1455 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _VECTORMATH_VEC_AOS_CPP_H -#define _VECTORMATH_VEC_AOS_CPP_H - -//----------------------------------------------------------------------------- -// Constants -// for permutes words are labeled [x,y,z,w] [a,b,c,d] - -#define _VECTORMATH_PERM_X 0x00010203 -#define _VECTORMATH_PERM_Y 0x04050607 -#define _VECTORMATH_PERM_Z 0x08090a0b -#define _VECTORMATH_PERM_W 0x0c0d0e0f -#define _VECTORMATH_PERM_A 0x10111213 -#define _VECTORMATH_PERM_B 0x14151617 -#define _VECTORMATH_PERM_C 0x18191a1b -#define _VECTORMATH_PERM_D 0x1c1d1e1f -#define _VECTORMATH_PERM_XYZA (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A } -#define _VECTORMATH_PERM_ZXYW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_W } -#define _VECTORMATH_PERM_YZXW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_X, _VECTORMATH_PERM_W } -#define _VECTORMATH_PERM_YZAB (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Y, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B } -#define _VECTORMATH_PERM_ZABC (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_Z, _VECTORMATH_PERM_A, _VECTORMATH_PERM_B, _VECTORMATH_PERM_C } -#define _VECTORMATH_PERM_XYAW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_Y, _VECTORMATH_PERM_A, _VECTORMATH_PERM_W } -#define _VECTORMATH_PERM_XAZW (vec_uchar16)(vec_uint4){ _VECTORMATH_PERM_X, _VECTORMATH_PERM_A, _VECTORMATH_PERM_Z, _VECTORMATH_PERM_W } -#define _VECTORMATH_MASK_0xF000 (vec_uint4){ 0xffffffff, 0, 0, 0 } -#define _VECTORMATH_MASK_0x0F00 (vec_uint4){ 0, 0xffffffff, 0, 0 } -#define _VECTORMATH_MASK_0x00F0 (vec_uint4){ 0, 0, 0xffffffff, 0 } -#define _VECTORMATH_MASK_0x000F (vec_uint4){ 0, 0, 0, 0xffffffff } -#define _VECTORMATH_UNIT_1000 _mm_setr_ps(1.0f,0.0f,0.0f,0.0f) // (__m128){ 1.0f, 0.0f, 0.0f, 0.0f } -#define _VECTORMATH_UNIT_0100 _mm_setr_ps(0.0f,1.0f,0.0f,0.0f) // (__m128){ 0.0f, 1.0f, 0.0f, 0.0f } -#define _VECTORMATH_UNIT_0010 _mm_setr_ps(0.0f,0.0f,1.0f,0.0f) // (__m128){ 0.0f, 0.0f, 1.0f, 0.0f } -#define _VECTORMATH_UNIT_0001 _mm_setr_ps(0.0f,0.0f,0.0f,1.0f) // (__m128){ 0.0f, 0.0f, 0.0f, 1.0f } -#define _VECTORMATH_SLERP_TOL 0.999f -//_VECTORMATH_SLERP_TOLF - -//----------------------------------------------------------------------------- -// Definitions - -#ifndef _VECTORMATH_INTERNAL_FUNCTIONS -#define _VECTORMATH_INTERNAL_FUNCTIONS - -#define _vmath_shufps(a, b, immx, immy, immz, immw) _mm_shuffle_ps(a, b, _MM_SHUFFLE(immw, immz, immy, immx)) -static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot3( __m128 vec0, __m128 vec1 ) -{ - __m128 result = _mm_mul_ps( vec0, vec1); - return _mm_add_ps( vec_splat( result, 0 ), _mm_add_ps( vec_splat( result, 1 ), vec_splat( result, 2 ) ) ); -} - -static VECTORMATH_FORCE_INLINE __m128 _vmathVfDot4( __m128 vec0, __m128 vec1 ) -{ - __m128 result = _mm_mul_ps(vec0, vec1); - return _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(0,0,0,0)), - _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(1,1,1,1)), - _mm_add_ps(_mm_shuffle_ps(result, result, _MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(result, result, _MM_SHUFFLE(3,3,3,3))))); -} - -static VECTORMATH_FORCE_INLINE __m128 _vmathVfCross( __m128 vec0, __m128 vec1 ) -{ - __m128 tmp0, tmp1, tmp2, tmp3, result; - tmp0 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,0,2,1) ); - tmp1 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,1,0,2) ); - tmp2 = _mm_shuffle_ps( vec0, vec0, _MM_SHUFFLE(3,1,0,2) ); - tmp3 = _mm_shuffle_ps( vec1, vec1, _MM_SHUFFLE(3,0,2,1) ); - result = vec_mul( tmp0, tmp1 ); - result = vec_nmsub( tmp2, tmp3, result ); - return result; -} -/* -static VECTORMATH_FORCE_INLINE vec_uint4 _vmathVfToHalfFloatsUnpacked(__m128 v) -{ -#if 0 - vec_int4 bexp; - vec_uint4 mant, sign, hfloat; - vec_uint4 notZero, isInf; - const vec_uint4 hfloatInf = (vec_uint4)(0x00007c00u); - const vec_uint4 mergeMant = (vec_uint4)(0x000003ffu); - const vec_uint4 mergeSign = (vec_uint4)(0x00008000u); - - sign = vec_sr((vec_uint4)v, (vec_uint4)16); - mant = vec_sr((vec_uint4)v, (vec_uint4)13); - bexp = vec_and(vec_sr((vec_int4)v, (vec_uint4)23), (vec_int4)0xff); - - notZero = (vec_uint4)vec_cmpgt(bexp, (vec_int4)112); - isInf = (vec_uint4)vec_cmpgt(bexp, (vec_int4)142); - - bexp = _mm_add_ps(bexp, (vec_int4)-112); - bexp = vec_sl(bexp, (vec_uint4)10); - - hfloat = vec_sel((vec_uint4)bexp, mant, mergeMant); - hfloat = vec_sel((vec_uint4)(0), hfloat, notZero); - hfloat = vec_sel(hfloat, hfloatInf, isInf); - hfloat = vec_sel(hfloat, sign, mergeSign); - - return hfloat; -#else - assert(0); - return _mm_setzero_ps(); -#endif -} - -static VECTORMATH_FORCE_INLINE vec_ushort8 _vmath2VfToHalfFloats(__m128 u, __m128 v) -{ -#if 0 - vec_uint4 hfloat_u, hfloat_v; - const vec_uchar16 pack = (vec_uchar16){2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31}; - hfloat_u = _vmathVfToHalfFloatsUnpacked(u); - hfloat_v = _vmathVfToHalfFloatsUnpacked(v); - return (vec_ushort8)vec_perm(hfloat_u, hfloat_v, pack); -#else - assert(0); - return _mm_setzero_si128(); -#endif -} -*/ - -static VECTORMATH_FORCE_INLINE __m128 _vmathVfInsert(__m128 dst, __m128 src, int slot) -{ - SSEFloat s; - s.m128 = src; - SSEFloat d; - d.m128 = dst; - d.f[slot] = s.f[slot]; - return d.m128; -} - -#define _vmathVfSetElement(vec, scalar, slot) ((float *)&(vec))[slot] = scalar - -static VECTORMATH_FORCE_INLINE __m128 _vmathVfSplatScalar(float scalar) -{ - return _mm_set1_ps(scalar); -} - -#endif - -namespace Vectormath { -namespace Aos { - - -#ifdef _VECTORMATH_NO_SCALAR_CAST -VECTORMATH_FORCE_INLINE VecIdx::operator floatInVec() const -{ - return floatInVec(ref, i); -} - -VECTORMATH_FORCE_INLINE float VecIdx::getAsFloat() const -#else -VECTORMATH_FORCE_INLINE VecIdx::operator float() const -#endif -{ - return ((float *)&ref)[i]; -} - -VECTORMATH_FORCE_INLINE float VecIdx::operator =( float scalar ) -{ - _vmathVfSetElement(ref, scalar, i); - return scalar; -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const floatInVec &scalar ) -{ - ref = _vmathVfInsert(ref, scalar.get128(), i); - return scalar; -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator =( const VecIdx& scalar ) -{ - return *this = floatInVec(scalar.ref, scalar.i); -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( float scalar ) -{ - return *this *= floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator *=( const floatInVec &scalar ) -{ - return *this = floatInVec(ref, i) * scalar; -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator /=( float scalar ) -{ - return *this /= floatInVec(scalar); -} - -inline floatInVec VecIdx::operator /=( const floatInVec &scalar ) -{ - return *this = floatInVec(ref, i) / scalar; -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( float scalar ) -{ - return *this += floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator +=( const floatInVec &scalar ) -{ - return *this = floatInVec(ref, i) + scalar; -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( float scalar ) -{ - return *this -= floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE floatInVec VecIdx::operator -=( const floatInVec &scalar ) -{ - return *this = floatInVec(ref, i) - scalar; -} - -VECTORMATH_FORCE_INLINE Vector3::Vector3(const Vector3& vec) -{ - set128(vec.get128()); -} - -VECTORMATH_FORCE_INLINE void Vector3::set128(vec_float4 vec) -{ - mVec128 = vec; -} - - -VECTORMATH_FORCE_INLINE Vector3::Vector3( float _x, float _y, float _z ) -{ - mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); -} - -VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) -{ - __m128 xz = _mm_unpacklo_ps( _x.get128(), _z.get128() ); - mVec128 = _mm_unpacklo_ps( xz, _y.get128() ); -} - -VECTORMATH_FORCE_INLINE Vector3::Vector3( const Point3 &pnt ) -{ - mVec128 = pnt.get128(); -} - -VECTORMATH_FORCE_INLINE Vector3::Vector3( float scalar ) -{ - mVec128 = floatInVec(scalar).get128(); -} - -VECTORMATH_FORCE_INLINE Vector3::Vector3( const floatInVec &scalar ) -{ - mVec128 = scalar.get128(); -} - -VECTORMATH_FORCE_INLINE Vector3::Vector3( __m128 vf4 ) -{ - mVec128 = vf4; -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::xAxis( ) -{ - return Vector3( _VECTORMATH_UNIT_1000 ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::yAxis( ) -{ - return Vector3( _VECTORMATH_UNIT_0100 ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::zAxis( ) -{ - return Vector3( _VECTORMATH_UNIT_0010 ); -} - -VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ) -{ - return lerp( floatInVec(t), vec0, vec1 ); -} - -VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ) -{ - return ( vec0 + ( ( vec1 - vec0 ) * t ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) -{ - return slerp( floatInVec(t), unitVec0, unitVec1 ); -} - -VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ) -{ - __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; - cosAngle = _vmathVfDot3( unitVec0.get128(), unitVec1.get128() ); - __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); - angle = acosf4( cosAngle ); - tttt = t.get128(); - oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); - angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t - angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t - angles = _mm_mul_ps( angles, angle ); - sines = sinf4( angles ); - scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); - scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); - scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); - return Vector3( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); -} - -VECTORMATH_FORCE_INLINE __m128 Vector3::get128( ) const -{ - return mVec128; -} - -VECTORMATH_FORCE_INLINE void loadXYZ(Point3& vec, const float* fptr) -{ -#ifdef USE_SSE3_LDDQU - vec = Point3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); -#else - SSEFloat fl; - fl.f[0] = fptr[0]; - fl.f[1] = fptr[1]; - fl.f[2] = fptr[2]; - fl.f[3] = fptr[3]; - vec = Point3( fl.m128); -#endif //USE_SSE3_LDDQU - -} - - - -VECTORMATH_FORCE_INLINE void loadXYZ(Vector3& vec, const float* fptr) -{ -#ifdef USE_SSE3_LDDQU - vec = Vector3( SSEFloat(_mm_lddqu_si128((const __m128i*)((float*)(fptr)))).m128 ); -#else - SSEFloat fl; - fl.f[0] = fptr[0]; - fl.f[1] = fptr[1]; - fl.f[2] = fptr[2]; - fl.f[3] = fptr[3]; - vec = Vector3( fl.m128); -#endif //USE_SSE3_LDDQU - -} - -VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ) -{ - __m128 dstVec = *quad; - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize - dstVec = vec_sel(vec.get128(), dstVec, sw); - *quad = dstVec; -} - -VECTORMATH_FORCE_INLINE void storeXYZ(const Point3& vec, float* fptr) -{ - fptr[0] = vec.getX(); - fptr[1] = vec.getY(); - fptr[2] = vec.getZ(); -} - -VECTORMATH_FORCE_INLINE void storeXYZ(const Vector3& vec, float* fptr) -{ - fptr[0] = vec.getX(); - fptr[1] = vec.getY(); - fptr[2] = vec.getZ(); -} - - -VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ) -{ - const float *quads = (float *)threeQuads; - vec0 = Vector3( _mm_load_ps(quads) ); - vec1 = Vector3( _mm_loadu_ps(quads + 3) ); - vec2 = Vector3( _mm_loadu_ps(quads + 6) ); - vec3 = Vector3( _mm_loadu_ps(quads + 9) ); -} - -VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ) -{ - __m128 xxxx = _mm_shuffle_ps( vec1.get128(), vec1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); - __m128 zzzz = _mm_shuffle_ps( vec2.get128(), vec2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); - VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; - VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; - threeQuads[0] = vec_sel( vec0.get128(), xxxx, xsw ); - threeQuads[1] = _mm_shuffle_ps( vec1.get128(), vec2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); - threeQuads[2] = vec_sel( _mm_shuffle_ps( vec3.get128(), vec3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); -} -/* -VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ) -{ - assert(0); -#if 0 - __m128 xyz0[3]; - __m128 xyz1[3]; - storeXYZArray( vec0, vec1, vec2, vec3, xyz0 ); - storeXYZArray( vec4, vec5, vec6, vec7, xyz1 ); - threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); - threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); - threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); -#endif -} -*/ -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator =( const Vector3 &vec ) -{ - mVec128 = vec.mVec128; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( float _x ) -{ - _vmathVfSetElement(mVec128, _x, 0); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setX( const floatInVec &_x ) -{ - mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector3::getX( ) const -{ - return floatInVec( mVec128, 0 ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( float _y ) -{ - _vmathVfSetElement(mVec128, _y, 1); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setY( const floatInVec &_y ) -{ - mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector3::getY( ) const -{ - return floatInVec( mVec128, 1 ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( float _z ) -{ - _vmathVfSetElement(mVec128, _z, 2); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setZ( const floatInVec &_z ) -{ - mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector3::getZ( ) const -{ - return floatInVec( mVec128, 2 ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, float value ) -{ - _vmathVfSetElement(mVec128, value, idx); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::setElem( int idx, const floatInVec &value ) -{ - mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector3::getElem( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE VecIdx Vector3::operator []( int idx ) -{ - return VecIdx( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector3::operator []( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator +( const Vector3 &vec ) const -{ - return Vector3( _mm_add_ps( mVec128, vec.mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( const Vector3 &vec ) const -{ - return Vector3( _mm_sub_ps( mVec128, vec.mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 Vector3::operator +( const Point3 &pnt ) const -{ - return Point3( _mm_add_ps( mVec128, pnt.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( float scalar ) const -{ - return *this * floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator *( const floatInVec &scalar ) const -{ - return Vector3( _mm_mul_ps( mVec128, scalar.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator +=( const Vector3 &vec ) -{ - *this = *this + vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator -=( const Vector3 &vec ) -{ - *this = *this - vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator *=( const floatInVec &scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( float scalar ) const -{ - return *this / floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator /( const floatInVec &scalar ) const -{ - return Vector3( _mm_div_ps( mVec128, scalar.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector3 & Vector3::operator /=( const floatInVec &scalar ) -{ - *this = *this / scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector3::operator -( ) const -{ - //return Vector3(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); - - VM_ATTRIBUTE_ALIGN16 static const int array[] = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; - __m128 NEG_MASK = SSEFloat(*(const vec_float4*)array).vf; - return Vector3(_mm_xor_ps(get128(),NEG_MASK)); -} - -VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ) -{ - return floatInVec(scalar) * vec; -} - -VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ) -{ - return vec * scalar; -} - -VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ) -{ - return Vector3( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ) -{ - return Vector3( _mm_div_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ) -{ - return Vector3( _mm_rcp_ps( vec.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ) -{ - return Vector3( fabsf4( vec.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ) -{ - __m128 vmask = toM128(0x7fffffff); - return Vector3( _mm_or_ps( - _mm_and_ps ( vmask, vec0.get128() ), // Value - _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs -} - -VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ) -{ - return Vector3( _mm_max_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ) -{ - return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ) -{ - return Vector3( _mm_min_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ) -{ - return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ) -{ - return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), vec_splat( vec.get128(), 2 ) ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ) -{ - return floatInVec( _vmathVfDot3( vec0.get128(), vec1.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ) -{ - return floatInVec( _vmathVfDot3( vec.get128(), vec.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ) -{ - return floatInVec( _mm_sqrt_ps(_vmathVfDot3( vec.get128(), vec.get128() )), 0 ); -} - - -VECTORMATH_FORCE_INLINE const Vector3 normalizeApprox( const Vector3 &vec ) -{ - return Vector3( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ) -{ - return Vector3( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot3( vec.get128(), vec.get128() ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ) -{ - return Vector3( _vmathVfCross( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ) -{ - return select( vec0, vec1, boolInVec(select1) ); -} - - -VECTORMATH_FORCE_INLINE const Vector4 select(const Vector4& vec0, const Vector4& vec1, const boolInVec& select1) -{ - return Vector4(vec_sel(vec0.get128(), vec1.get128(), select1.get128())); -} - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = vec.get128(); - printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); -} - -VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = vec.get128(); - printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); -} - -#endif - -VECTORMATH_FORCE_INLINE Vector4::Vector4( float _x, float _y, float _z, float _w ) -{ - mVec128 = _mm_setr_ps(_x, _y, _z, _w); - } - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z, const floatInVec &_w ) -{ - mVec128 = _mm_unpacklo_ps( - _mm_unpacklo_ps( _x.get128(), _z.get128() ), - _mm_unpacklo_ps( _y.get128(), _w.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, float _w ) -{ - mVec128 = xyz.get128(); - _vmathVfSetElement(mVec128, _w, 3); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &xyz, const floatInVec &_w ) -{ - mVec128 = xyz.get128(); - mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const Vector3 &vec ) -{ - mVec128 = vec.get128(); - mVec128 = _vmathVfInsert(mVec128, _mm_setzero_ps(), 3); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const Point3 &pnt ) -{ - mVec128 = pnt.get128(); - mVec128 = _vmathVfInsert(mVec128, _mm_set1_ps(1.0f), 3); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const Quat &quat ) -{ - mVec128 = quat.get128(); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( float scalar ) -{ - mVec128 = floatInVec(scalar).get128(); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( const floatInVec &scalar ) -{ - mVec128 = scalar.get128(); -} - -VECTORMATH_FORCE_INLINE Vector4::Vector4( __m128 vf4 ) -{ - mVec128 = vf4; -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::xAxis( ) -{ - return Vector4( _VECTORMATH_UNIT_1000 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::yAxis( ) -{ - return Vector4( _VECTORMATH_UNIT_0100 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::zAxis( ) -{ - return Vector4( _VECTORMATH_UNIT_0010 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::wAxis( ) -{ - return Vector4( _VECTORMATH_UNIT_0001 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ) -{ - return lerp( floatInVec(t), vec0, vec1 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ) -{ - return ( vec0 + ( ( vec1 - vec0 ) * t ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) -{ - return slerp( floatInVec(t), unitVec0, unitVec1 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ) -{ - __m128 scales, scale0, scale1, cosAngle, angle, tttt, oneMinusT, angles, sines; - cosAngle = _vmathVfDot4( unitVec0.get128(), unitVec1.get128() ); - __m128 selectMask = _mm_cmpgt_ps( _mm_set1_ps(_VECTORMATH_SLERP_TOL), cosAngle ); - angle = acosf4( cosAngle ); - tttt = t.get128(); - oneMinusT = _mm_sub_ps( _mm_set1_ps(1.0f), tttt ); - angles = _mm_unpacklo_ps( _mm_set1_ps(1.0f), tttt ); // angles = 1, t, 1, t - angles = _mm_unpacklo_ps( angles, oneMinusT ); // angles = 1, 1-t, t, 1-t - angles = _mm_mul_ps( angles, angle ); - sines = sinf4( angles ); - scales = _mm_div_ps( sines, vec_splat( sines, 0 ) ); - scale0 = vec_sel( oneMinusT, vec_splat( scales, 1 ), selectMask ); - scale1 = vec_sel( tttt, vec_splat( scales, 2 ), selectMask ); - return Vector4( vec_madd( unitVec0.get128(), scale0, _mm_mul_ps( unitVec1.get128(), scale1 ) ) ); -} - -VECTORMATH_FORCE_INLINE __m128 Vector4::get128( ) const -{ - return mVec128; -} -/* -VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ) -{ - twoQuads[0] = _vmath2VfToHalfFloats(vec0.get128(), vec1.get128()); - twoQuads[1] = _vmath2VfToHalfFloats(vec2.get128(), vec3.get128()); -} -*/ -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator =( const Vector4 &vec ) -{ - mVec128 = vec.mVec128; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setXYZ( const Vector3 &vec ) -{ - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; - mVec128 = vec_sel( vec.get128(), mVec128, sw ); - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector3 Vector4::getXYZ( ) const -{ - return Vector3( mVec128 ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( float _x ) -{ - _vmathVfSetElement(mVec128, _x, 0); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setX( const floatInVec &_x ) -{ - mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector4::getX( ) const -{ - return floatInVec( mVec128, 0 ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( float _y ) -{ - _vmathVfSetElement(mVec128, _y, 1); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setY( const floatInVec &_y ) -{ - mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector4::getY( ) const -{ - return floatInVec( mVec128, 1 ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( float _z ) -{ - _vmathVfSetElement(mVec128, _z, 2); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setZ( const floatInVec &_z ) -{ - mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector4::getZ( ) const -{ - return floatInVec( mVec128, 2 ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( float _w ) -{ - _vmathVfSetElement(mVec128, _w, 3); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setW( const floatInVec &_w ) -{ - mVec128 = _vmathVfInsert(mVec128, _w.get128(), 3); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector4::getW( ) const -{ - return floatInVec( mVec128, 3 ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, float value ) -{ - _vmathVfSetElement(mVec128, value, idx); - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::setElem( int idx, const floatInVec &value ) -{ - mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector4::getElem( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE VecIdx Vector4::operator []( int idx ) -{ - return VecIdx( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const floatInVec Vector4::operator []( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator +( const Vector4 &vec ) const -{ - return Vector4( _mm_add_ps( mVec128, vec.mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( const Vector4 &vec ) const -{ - return Vector4( _mm_sub_ps( mVec128, vec.mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( float scalar ) const -{ - return *this * floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator *( const floatInVec &scalar ) const -{ - return Vector4( _mm_mul_ps( mVec128, scalar.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator +=( const Vector4 &vec ) -{ - *this = *this + vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator -=( const Vector4 &vec ) -{ - *this = *this - vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( float scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator *=( const floatInVec &scalar ) -{ - *this = *this * scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( float scalar ) const -{ - return *this / floatInVec(scalar); -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator /( const floatInVec &scalar ) const -{ - return Vector4( _mm_div_ps( mVec128, scalar.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( float scalar ) -{ - *this = *this / scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE Vector4 & Vector4::operator /=( const floatInVec &scalar ) -{ - *this = *this / scalar; - return *this; -} - -VECTORMATH_FORCE_INLINE const Vector4 Vector4::operator -( ) const -{ - return Vector4(_mm_sub_ps( _mm_setzero_ps(), mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ) -{ - return floatInVec(scalar) * vec; -} - -VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ) -{ - return vec * scalar; -} - -VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ) -{ - return Vector4( _mm_mul_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ) -{ - return Vector4( _mm_div_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ) -{ - return Vector4( _mm_rcp_ps( vec.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ) -{ - return Vector4( fabsf4( vec.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ) -{ - __m128 vmask = toM128(0x7fffffff); - return Vector4( _mm_or_ps( - _mm_and_ps ( vmask, vec0.get128() ), // Value - _mm_andnot_ps( vmask, vec1.get128() ) ) ); // Signs -} - -VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ) -{ - return Vector4( _mm_max_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ) -{ - return floatInVec( _mm_max_ps( - _mm_max_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), - _mm_max_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ) -{ - return Vector4( _mm_min_ps( vec0.get128(), vec1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ) -{ - return floatInVec( _mm_min_ps( - _mm_min_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), - _mm_min_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ) -{ - return floatInVec( _mm_add_ps( - _mm_add_ps( vec_splat( vec.get128(), 0 ), vec_splat( vec.get128(), 1 ) ), - _mm_add_ps( vec_splat( vec.get128(), 2 ), vec_splat( vec.get128(), 3 ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ) -{ - return floatInVec( _vmathVfDot4( vec0.get128(), vec1.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ) -{ - return floatInVec( _vmathVfDot4( vec.get128(), vec.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ) -{ - return floatInVec( _mm_sqrt_ps(_vmathVfDot4( vec.get128(), vec.get128() )), 0 ); -} - -VECTORMATH_FORCE_INLINE const Vector4 normalizeApprox( const Vector4 &vec ) -{ - return Vector4( _mm_mul_ps( vec.get128(), _mm_rsqrt_ps( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ) -{ - return Vector4( _mm_mul_ps( vec.get128(), newtonrapson_rsqrt4( _vmathVfDot4( vec.get128(), vec.get128() ) ) ) ); -} - -VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ) -{ - return select( vec0, vec1, boolInVec(select1) ); -} - - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = vec.get128(); - printf( "( %f %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); -} - -VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = vec.get128(); - printf( "%s: ( %f %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2], tmp.s[3] ); -} - -#endif - -VECTORMATH_FORCE_INLINE Point3::Point3( float _x, float _y, float _z ) -{ - mVec128 = _mm_setr_ps(_x, _y, _z, 0.0f); -} - -VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &_x, const floatInVec &_y, const floatInVec &_z ) -{ - mVec128 = _mm_unpacklo_ps( _mm_unpacklo_ps( _x.get128(), _z.get128() ), _y.get128() ); -} - -VECTORMATH_FORCE_INLINE Point3::Point3( const Vector3 &vec ) -{ - mVec128 = vec.get128(); -} - -VECTORMATH_FORCE_INLINE Point3::Point3( float scalar ) -{ - mVec128 = floatInVec(scalar).get128(); -} - -VECTORMATH_FORCE_INLINE Point3::Point3( const floatInVec &scalar ) -{ - mVec128 = scalar.get128(); -} - -VECTORMATH_FORCE_INLINE Point3::Point3( __m128 vf4 ) -{ - mVec128 = vf4; -} - -VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ) -{ - return lerp( floatInVec(t), pnt0, pnt1 ); -} - -VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ) -{ - return ( pnt0 + ( ( pnt1 - pnt0 ) * t ) ); -} - -VECTORMATH_FORCE_INLINE __m128 Point3::get128( ) const -{ - return mVec128; -} - -VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ) -{ - __m128 dstVec = *quad; - VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff}; // TODO: Centralize - dstVec = vec_sel(pnt.get128(), dstVec, sw); - *quad = dstVec; -} - -VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ) -{ - const float *quads = (float *)threeQuads; - pnt0 = Point3( _mm_load_ps(quads) ); - pnt1 = Point3( _mm_loadu_ps(quads + 3) ); - pnt2 = Point3( _mm_loadu_ps(quads + 6) ); - pnt3 = Point3( _mm_loadu_ps(quads + 9) ); -} - -VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ) -{ - __m128 xxxx = _mm_shuffle_ps( pnt1.get128(), pnt1.get128(), _MM_SHUFFLE(0, 0, 0, 0) ); - __m128 zzzz = _mm_shuffle_ps( pnt2.get128(), pnt2.get128(), _MM_SHUFFLE(2, 2, 2, 2) ); - VM_ATTRIBUTE_ALIGN16 unsigned int xsw[4] = {0, 0, 0, 0xffffffff}; - VM_ATTRIBUTE_ALIGN16 unsigned int zsw[4] = {0xffffffff, 0, 0, 0}; - threeQuads[0] = vec_sel( pnt0.get128(), xxxx, xsw ); - threeQuads[1] = _mm_shuffle_ps( pnt1.get128(), pnt2.get128(), _MM_SHUFFLE(1, 0, 2, 1) ); - threeQuads[2] = vec_sel( _mm_shuffle_ps( pnt3.get128(), pnt3.get128(), _MM_SHUFFLE(2, 1, 0, 3) ), zzzz, zsw ); -} -/* -VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ) -{ -#if 0 - __m128 xyz0[3]; - __m128 xyz1[3]; - storeXYZArray( pnt0, pnt1, pnt2, pnt3, xyz0 ); - storeXYZArray( pnt4, pnt5, pnt6, pnt7, xyz1 ); - threeQuads[0] = _vmath2VfToHalfFloats(xyz0[0], xyz0[1]); - threeQuads[1] = _vmath2VfToHalfFloats(xyz0[2], xyz1[0]); - threeQuads[2] = _vmath2VfToHalfFloats(xyz1[1], xyz1[2]); -#else - assert(0); -#endif -} -*/ -VECTORMATH_FORCE_INLINE Point3 & Point3::operator =( const Point3 &pnt ) -{ - mVec128 = pnt.mVec128; - return *this; -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setX( float _x ) -{ - _vmathVfSetElement(mVec128, _x, 0); - return *this; -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setX( const floatInVec &_x ) -{ - mVec128 = _vmathVfInsert(mVec128, _x.get128(), 0); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Point3::getX( ) const -{ - return floatInVec( mVec128, 0 ); -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setY( float _y ) -{ - _vmathVfSetElement(mVec128, _y, 1); - return *this; -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setY( const floatInVec &_y ) -{ - mVec128 = _vmathVfInsert(mVec128, _y.get128(), 1); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Point3::getY( ) const -{ - return floatInVec( mVec128, 1 ); -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( float _z ) -{ - _vmathVfSetElement(mVec128, _z, 2); - return *this; -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setZ( const floatInVec &_z ) -{ - mVec128 = _vmathVfInsert(mVec128, _z.get128(), 2); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Point3::getZ( ) const -{ - return floatInVec( mVec128, 2 ); -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, float value ) -{ - _vmathVfSetElement(mVec128, value, idx); - return *this; -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::setElem( int idx, const floatInVec &value ) -{ - mVec128 = _vmathVfInsert(mVec128, value.get128(), idx); - return *this; -} - -VECTORMATH_FORCE_INLINE const floatInVec Point3::getElem( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE VecIdx Point3::operator []( int idx ) -{ - return VecIdx( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const floatInVec Point3::operator []( int idx ) const -{ - return floatInVec( mVec128, idx ); -} - -VECTORMATH_FORCE_INLINE const Vector3 Point3::operator -( const Point3 &pnt ) const -{ - return Vector3( _mm_sub_ps( mVec128, pnt.mVec128 ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 Point3::operator +( const Vector3 &vec ) const -{ - return Point3( _mm_add_ps( mVec128, vec.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 Point3::operator -( const Vector3 &vec ) const -{ - return Point3( _mm_sub_ps( mVec128, vec.get128() ) ); -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::operator +=( const Vector3 &vec ) -{ - *this = *this + vec; - return *this; -} - -VECTORMATH_FORCE_INLINE Point3 & Point3::operator -=( const Vector3 &vec ) -{ - *this = *this - vec; - return *this; -} - -VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ) -{ - return Point3( _mm_mul_ps( pnt0.get128(), pnt1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ) -{ - return Point3( _mm_div_ps( pnt0.get128(), pnt1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ) -{ - return Point3( _mm_rcp_ps( pnt.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ) -{ - return Point3( fabsf4( pnt.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ) -{ - __m128 vmask = toM128(0x7fffffff); - return Point3( _mm_or_ps( - _mm_and_ps ( vmask, pnt0.get128() ), // Value - _mm_andnot_ps( vmask, pnt1.get128() ) ) ); // Signs -} - -VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ) -{ - return Point3( _mm_max_ps( pnt0.get128(), pnt1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ) -{ - return floatInVec( _mm_max_ps( _mm_max_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ) -{ - return Point3( _mm_min_ps( pnt0.get128(), pnt1.get128() ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ) -{ - return floatInVec( _mm_min_ps( _mm_min_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ) -{ - return floatInVec( _mm_add_ps( _mm_add_ps( vec_splat( pnt.get128(), 0 ), vec_splat( pnt.get128(), 1 ) ), vec_splat( pnt.get128(), 2 ) ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ) -{ - return scale( pnt, floatInVec( scaleVal ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ) -{ - return mulPerElem( pnt, Point3( scaleVal ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ) -{ - return mulPerElem( pnt, Point3( scaleVec ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ) -{ - return floatInVec( _vmathVfDot3( pnt.get128(), unitVec.get128() ), 0 ); -} - -VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ) -{ - return lengthSqr( Vector3( pnt ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ) -{ - return length( Vector3( pnt ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ) -{ - return lengthSqr( ( pnt1 - pnt0 ) ); -} - -VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ) -{ - return length( ( pnt1 - pnt0 ) ); -} - -VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ) -{ - return select( pnt0, pnt1, boolInVec(select1) ); -} - -VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ) -{ - return Point3( vec_sel( pnt0.get128(), pnt1.get128(), select1.get128() ) ); -} - - - -#ifdef _VECTORMATH_DEBUG - -VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = pnt.get128(); - printf( "( %f %f %f )\n", tmp.s[0], tmp.s[1], tmp.s[2] ); -} - -VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ) -{ - union { __m128 v; float s[4]; } tmp; - tmp.v = pnt.get128(); - printf( "%s: ( %f %f %f )\n", name, tmp.s[0], tmp.s[1], tmp.s[2] ); -} - -#endif - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/vecidx_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/vecidx_aos.h deleted file mode 100644 index 8ba4b1d7..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/vecidx_aos.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _VECTORMATH_VECIDX_AOS_H -#define _VECTORMATH_VECIDX_AOS_H - - -#include "floatInVec.h" - -namespace Vectormath { -namespace Aos { - -//----------------------------------------------------------------------------- -// VecIdx -// Used in setting elements of Vector3, Vector4, Point3, or Quat with the -// subscripting operator. -// - -VM_ATTRIBUTE_ALIGNED_CLASS16 (class) VecIdx -{ -private: - __m128 &ref; - int i; -public: - inline VecIdx( __m128& vec, int idx ): ref(vec) { i = idx; } - - // implicitly casts to float unless _VECTORMATH_NO_SCALAR_CAST defined - // in which case, implicitly casts to floatInVec, and one must call - // getAsFloat to convert to float. - // -#ifdef _VECTORMATH_NO_SCALAR_CAST - inline operator floatInVec() const; - inline float getAsFloat() const; -#else - inline operator float() const; -#endif - - inline float operator =( float scalar ); - inline floatInVec operator =( const floatInVec &scalar ); - inline floatInVec operator =( const VecIdx& scalar ); - inline floatInVec operator *=( float scalar ); - inline floatInVec operator *=( const floatInVec &scalar ); - inline floatInVec operator /=( float scalar ); - inline floatInVec operator /=( const floatInVec &scalar ); - inline floatInVec operator +=( float scalar ); - inline floatInVec operator +=( const floatInVec &scalar ); - inline floatInVec operator -=( float scalar ); - inline floatInVec operator -=( const floatInVec &scalar ); -}; - -} // namespace Aos -} // namespace Vectormath - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/sse/vectormath_aos.h b/Code/Physics/Bullet Source/src/vectormath/sse/vectormath_aos.h deleted file mode 100644 index be5ae8c6..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/sse/vectormath_aos.h +++ /dev/null @@ -1,2547 +0,0 @@ -/* - Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. - All rights reserved. - - Redistribution and use in source and binary forms, - with or without modification, are permitted provided that the - following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Sony Computer Entertainment Inc nor the names - of its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _VECTORMATH_AOS_CPP_SSE_H -#define _VECTORMATH_AOS_CPP_SSE_H - -#include -#include -#include -#include - -#define Vector3Ref Vector3& -#define QuatRef Quat& -#define Matrix3Ref Matrix3& - -#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) - #define USE_SSE3_LDDQU - - #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) __declspec(align(16)) a - #define VM_ATTRIBUTE_ALIGN16 __declspec(align(16)) - #define VECTORMATH_FORCE_INLINE __forceinline -#else - #define VM_ATTRIBUTE_ALIGNED_CLASS16(a) a __attribute__ ((aligned (16))) - #define VM_ATTRIBUTE_ALIGN16 __attribute__ ((aligned (16))) - #define VECTORMATH_FORCE_INLINE inline __attribute__ ((always_inline)) - #ifdef __SSE3__ - #define USE_SSE3_LDDQU - #endif //__SSE3__ -#endif//_WIN32 - - -#ifdef USE_SSE3_LDDQU -#include //_mm_lddqu_si128 -#endif //USE_SSE3_LDDQU - - -// TODO: Tidy -typedef __m128 vec_float4; -typedef __m128 vec_uint4; -typedef __m128 vec_int4; -typedef __m128i vec_uchar16; -typedef __m128i vec_ushort8; - -#define vec_splat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) - -#define _mm_ror_ps(vec,i) \ - (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec)) -#define _mm_rol_ps(vec,i) \ - (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(7-i)%4,(unsigned char)(6-i)%4,(unsigned char)(5-i)%4,(unsigned char)(4-i)%4))) : (vec)) - -#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4)) - -#define _mm_abs_ps(vec) _mm_andnot_ps(_MASKSIGN_,vec) -#define _mm_neg_ps(vec) _mm_xor_ps(_MASKSIGN_,vec) - -#define vec_madd(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b) ) - -union SSEFloat -{ - __m128i vi; - __m128 m128; - __m128 vf; - unsigned int ui[4]; - unsigned short s[8]; - float f[4]; - SSEFloat(__m128 v) : m128(v) {} - SSEFloat(__m128i v) : vi(v) {} - SSEFloat() {}//uninitialized -}; - -static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, __m128 mask) -{ - return _mm_or_ps(_mm_and_ps(mask, b), _mm_andnot_ps(mask, a)); -} -static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, const unsigned int *_mask) -{ - return vec_sel(a, b, _mm_load_ps((float *)_mask)); -} -static VECTORMATH_FORCE_INLINE __m128 vec_sel(__m128 a, __m128 b, unsigned int _mask) -{ - return vec_sel(a, b, _mm_set1_ps(*(float *)&_mask)); -} - -static VECTORMATH_FORCE_INLINE __m128 toM128(unsigned int x) -{ - return _mm_set1_ps( *(float *)&x ); -} - -static VECTORMATH_FORCE_INLINE __m128 fabsf4(__m128 x) -{ - return _mm_and_ps( x, toM128( 0x7fffffff ) ); -} -/* -union SSE64 -{ - __m128 m128; - struct - { - __m64 m01; - __m64 m23; - } m64; -}; - -static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) -{ - assert(a == 0); // Only 2^0 supported - (void)a; - SSE64 sse64; - sse64.m64.m01 = _mm_cvttps_pi32(x); - sse64.m64.m23 = _mm_cvttps_pi32(_mm_ror_ps(x,2)); - _mm_empty(); - return sse64.m128; -} - -static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) -{ - assert(a == 0); // Only 2^0 supported - (void)a; - SSE64 sse64; - sse64.m128 = x; - __m128 result =_mm_movelh_ps( - _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m01), - _mm_cvt_pi2ps(_mm_setzero_ps(), sse64.m64.m23)); - _mm_empty(); - return result; -} -*/ -static VECTORMATH_FORCE_INLINE __m128 vec_cts(__m128 x, int a) -{ - assert(a == 0); // Only 2^0 supported - (void)a; - __m128i result = _mm_cvtps_epi32(x); - return (__m128 &)result; -} - -static VECTORMATH_FORCE_INLINE __m128 vec_ctf(__m128 x, int a) -{ - assert(a == 0); // Only 2^0 supported - (void)a; - return _mm_cvtepi32_ps((__m128i &)x); -} - -#define vec_nmsub(a,b,c) _mm_sub_ps( c, _mm_mul_ps( a, b ) ) -#define vec_sub(a,b) _mm_sub_ps( a, b ) -#define vec_add(a,b) _mm_add_ps( a, b ) -#define vec_mul(a,b) _mm_mul_ps( a, b ) -#define vec_xor(a,b) _mm_xor_ps( a, b ) -#define vec_and(a,b) _mm_and_ps( a, b ) -#define vec_cmpeq(a,b) _mm_cmpeq_ps( a, b ) -#define vec_cmpgt(a,b) _mm_cmpgt_ps( a, b ) - -#define vec_mergeh(a,b) _mm_unpacklo_ps( a, b ) -#define vec_mergel(a,b) _mm_unpackhi_ps( a, b ) - -#define vec_andc(a,b) _mm_andnot_ps( b, a ) - -#define sqrtf4(x) _mm_sqrt_ps( x ) -#define rsqrtf4(x) _mm_rsqrt_ps( x ) -#define recipf4(x) _mm_rcp_ps( x ) -#define negatef4(x) _mm_sub_ps( _mm_setzero_ps(), x ) - -static VECTORMATH_FORCE_INLINE __m128 newtonrapson_rsqrt4( const __m128 v ) -{ -#define _half4 _mm_setr_ps(.5f,.5f,.5f,.5f) -#define _three _mm_setr_ps(3.f,3.f,3.f,3.f) -const __m128 approx = _mm_rsqrt_ps( v ); -const __m128 muls = _mm_mul_ps(_mm_mul_ps(v, approx), approx); -return _mm_mul_ps(_mm_mul_ps(_half4, approx), _mm_sub_ps(_three, muls) ); -} - -static VECTORMATH_FORCE_INLINE __m128 acosf4(__m128 x) -{ - __m128 xabs = fabsf4(x); - __m128 select = _mm_cmplt_ps( x, _mm_setzero_ps() ); - __m128 t1 = sqrtf4(vec_sub(_mm_set1_ps(1.0f), xabs)); - - /* Instruction counts can be reduced if the polynomial was - * computed entirely from nested (dependent) fma's. However, - * to reduce the number of pipeline stalls, the polygon is evaluated - * in two halves (hi amd lo). - */ - __m128 xabs2 = _mm_mul_ps(xabs, xabs); - __m128 xabs4 = _mm_mul_ps(xabs2, xabs2); - __m128 hi = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0012624911f), - xabs, _mm_set1_ps(0.0066700901f)), - xabs, _mm_set1_ps(-0.0170881256f)), - xabs, _mm_set1_ps( 0.0308918810f)); - __m128 lo = vec_madd(vec_madd(vec_madd(_mm_set1_ps(-0.0501743046f), - xabs, _mm_set1_ps(0.0889789874f)), - xabs, _mm_set1_ps(-0.2145988016f)), - xabs, _mm_set1_ps( 1.5707963050f)); - - __m128 result = vec_madd(hi, xabs4, lo); - - // Adjust the result if x is negactive. - return vec_sel( - vec_mul(t1, result), // Positive - vec_nmsub(t1, result, _mm_set1_ps(3.1415926535898f)), // Negative - select); -} - -static VECTORMATH_FORCE_INLINE __m128 sinf4(vec_float4 x) -{ - -// -// Common constants used to evaluate sinf4/cosf4/tanf4 -// -#define _SINCOS_CC0 -0.0013602249f -#define _SINCOS_CC1 0.0416566950f -#define _SINCOS_CC2 -0.4999990225f -#define _SINCOS_SC0 -0.0001950727f -#define _SINCOS_SC1 0.0083320758f -#define _SINCOS_SC2 -0.1666665247f - -#define _SINCOS_KC1 1.57079625129f -#define _SINCOS_KC2 7.54978995489e-8f - - vec_float4 xl,xl2,xl3,res; - - // Range reduction using : xl = angle * TwoOverPi; - // - xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); - - // Find the quadrant the angle falls in - // using: q = (int) (ceil(abs(xl))*sign(xl)) - // - vec_int4 q = vec_cts(xl,0); - - // Compute an offset based on the quadrant that the angle falls in - // - vec_int4 offset = _mm_and_ps(q,toM128(0x3)); - - // Remainder in range [-pi/4..pi/4] - // - vec_float4 qf = vec_ctf(q,0); - xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); - - // Compute x^2 and x^3 - // - xl2 = vec_mul(xl,xl); - xl3 = vec_mul(xl2,xl); - - // Compute both the sin and cos of the angles - // using a polynomial expression: - // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and - // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) - // - - vec_float4 cx = - vec_madd( - vec_madd( - vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); - vec_float4 sx = - vec_madd( - vec_madd( - vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); - - // Use the cosine when the offset is odd and the sin - // when the offset is even - // - res = vec_sel(cx,sx,vec_cmpeq(vec_and(offset, - toM128(0x1)), - _mm_setzero_ps())); - - // Flip the sign of the result when (offset mod 4) = 1 or 2 - // - return vec_sel( - vec_xor(toM128(0x80000000U), res), // Negative - res, // Positive - vec_cmpeq(vec_and(offset,toM128(0x2)),_mm_setzero_ps())); -} - -static VECTORMATH_FORCE_INLINE void sincosf4(vec_float4 x, vec_float4* s, vec_float4* c) -{ - vec_float4 xl,xl2,xl3; - vec_int4 offsetSin, offsetCos; - - // Range reduction using : xl = angle * TwoOverPi; - // - xl = vec_mul(x, _mm_set1_ps(0.63661977236f)); - - // Find the quadrant the angle falls in - // using: q = (int) (ceil(abs(xl))*sign(xl)) - // - //vec_int4 q = vec_cts(vec_add(xl,vec_sel(_mm_set1_ps(0.5f),xl,(0x80000000))),0); - vec_int4 q = vec_cts(xl,0); - - // Compute the offset based on the quadrant that the angle falls in. - // Add 1 to the offset for the cosine. - // - offsetSin = vec_and(q,toM128((int)0x3)); - __m128i temp = _mm_add_epi32(_mm_set1_epi32(1),(__m128i &)offsetSin); - offsetCos = (__m128 &)temp; - - // Remainder in range [-pi/4..pi/4] - // - vec_float4 qf = vec_ctf(q,0); - xl = vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC2),vec_nmsub(qf,_mm_set1_ps(_SINCOS_KC1),x)); - - // Compute x^2 and x^3 - // - xl2 = vec_mul(xl,xl); - xl3 = vec_mul(xl2,xl); - - // Compute both the sin and cos of the angles - // using a polynomial expression: - // cx = 1.0f + xl2 * ((C0 * xl2 + C1) * xl2 + C2), and - // sx = xl + xl3 * ((S0 * xl2 + S1) * xl2 + S2) - // - vec_float4 cx = - vec_madd( - vec_madd( - vec_madd(_mm_set1_ps(_SINCOS_CC0),xl2,_mm_set1_ps(_SINCOS_CC1)),xl2,_mm_set1_ps(_SINCOS_CC2)),xl2,_mm_set1_ps(1.0f)); - vec_float4 sx = - vec_madd( - vec_madd( - vec_madd(_mm_set1_ps(_SINCOS_SC0),xl2,_mm_set1_ps(_SINCOS_SC1)),xl2,_mm_set1_ps(_SINCOS_SC2)),xl3,xl); - - // Use the cosine when the offset is odd and the sin - // when the offset is even - // - vec_uint4 sinMask = (vec_uint4)vec_cmpeq(vec_and(offsetSin,toM128(0x1)),_mm_setzero_ps()); - vec_uint4 cosMask = (vec_uint4)vec_cmpeq(vec_and(offsetCos,toM128(0x1)),_mm_setzero_ps()); - *s = vec_sel(cx,sx,sinMask); - *c = vec_sel(cx,sx,cosMask); - - // Flip the sign of the result when (offset mod 4) = 1 or 2 - // - sinMask = vec_cmpeq(vec_and(offsetSin,toM128(0x2)),_mm_setzero_ps()); - cosMask = vec_cmpeq(vec_and(offsetCos,toM128(0x2)),_mm_setzero_ps()); - - *s = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*s),*s,sinMask); - *c = vec_sel((vec_float4)vec_xor(toM128(0x80000000),(vec_uint4)*c),*c,cosMask); -} - -#include "vecidx_aos.h" -#include "floatInVec.h" -#include "boolInVec.h" - -#ifdef _VECTORMATH_DEBUG -#include -#endif -namespace Vectormath { - -namespace Aos { - -//----------------------------------------------------------------------------- -// Forward Declarations -// - -class Vector3; -class Vector4; -class Point3; -class Quat; -class Matrix3; -class Matrix4; -class Transform3; - -// A 3-D vector in array-of-structures format -// -class Vector3 -{ - __m128 mVec128; - - VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); - - VECTORMATH_FORCE_INLINE vec_float4& get128Ref(); - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Vector3( ) { }; - - // Default copy constructor - // - VECTORMATH_FORCE_INLINE Vector3(const Vector3& vec); - - // Construct a 3-D vector from x, y, and z elements - // - VECTORMATH_FORCE_INLINE Vector3( float x, float y, float z ); - - // Construct a 3-D vector from x, y, and z elements (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); - - // Copy elements from a 3-D point into a 3-D vector - // - explicit VECTORMATH_FORCE_INLINE Vector3( const Point3 &pnt ); - - // Set all elements of a 3-D vector to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Vector3( float scalar ); - - // Set all elements of a 3-D vector to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Vector3( const floatInVec &scalar ); - - // Set vector float data in a 3-D vector - // - explicit VECTORMATH_FORCE_INLINE Vector3( __m128 vf4 ); - - // Get vector float data from a 3-D vector - // - VECTORMATH_FORCE_INLINE __m128 get128( ) const; - - // Assign one 3-D vector to another - // - VECTORMATH_FORCE_INLINE Vector3 & operator =( const Vector3 &vec ); - - // Set the x element of a 3-D vector - // - VECTORMATH_FORCE_INLINE Vector3 & setX( float x ); - - // Set the y element of a 3-D vector - // - VECTORMATH_FORCE_INLINE Vector3 & setY( float y ); - - // Set the z element of a 3-D vector - // - VECTORMATH_FORCE_INLINE Vector3 & setZ( float z ); - - // Set the x element of a 3-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3 & setX( const floatInVec &x ); - - // Set the y element of a 3-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3 & setY( const floatInVec &y ); - - // Set the z element of a 3-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3 & setZ( const floatInVec &z ); - - // Get the x element of a 3-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; - - // Get the y element of a 3-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; - - // Get the z element of a 3-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; - - // Set an x, y, or z element of a 3-D vector by index - // - VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, float value ); - - // Set an x, y, or z element of a 3-D vector by index (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3 & setElem( int idx, const floatInVec &value ); - - // Get an x, y, or z element of a 3-D vector by index - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); - - // Subscripting operator to get an element - // - VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; - - // Add two 3-D vectors - // - VECTORMATH_FORCE_INLINE const Vector3 operator +( const Vector3 &vec ) const; - - // Subtract a 3-D vector from another 3-D vector - // - VECTORMATH_FORCE_INLINE const Vector3 operator -( const Vector3 &vec ) const; - - // Add a 3-D vector to a 3-D point - // - VECTORMATH_FORCE_INLINE const Point3 operator +( const Point3 &pnt ) const; - - // Multiply a 3-D vector by a scalar - // - VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar ) const; - - // Divide a 3-D vector by a scalar - // - VECTORMATH_FORCE_INLINE const Vector3 operator /( float scalar ) const; - - // Multiply a 3-D vector by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar ) const; - - // Divide a 3-D vector by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Vector3 operator /( const floatInVec &scalar ) const; - - // Perform compound assignment and addition with a 3-D vector - // - VECTORMATH_FORCE_INLINE Vector3 & operator +=( const Vector3 &vec ); - - // Perform compound assignment and subtraction by a 3-D vector - // - VECTORMATH_FORCE_INLINE Vector3 & operator -=( const Vector3 &vec ); - - // Perform compound assignment and multiplication by a scalar - // - VECTORMATH_FORCE_INLINE Vector3 & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - VECTORMATH_FORCE_INLINE Vector3 & operator /=( float scalar ); - - // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3 & operator *=( const floatInVec &scalar ); - - // Perform compound assignment and division by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector3 & operator /=( const floatInVec &scalar ); - - // Negate all elements of a 3-D vector - // - VECTORMATH_FORCE_INLINE const Vector3 operator -( ) const; - - // Construct x axis - // - static VECTORMATH_FORCE_INLINE const Vector3 xAxis( ); - - // Construct y axis - // - static VECTORMATH_FORCE_INLINE const Vector3 yAxis( ); - - // Construct z axis - // - static VECTORMATH_FORCE_INLINE const Vector3 zAxis( ); - -}; - -// Multiply a 3-D vector by a scalar -// -VECTORMATH_FORCE_INLINE const Vector3 operator *( float scalar, const Vector3 &vec ); - -// Multiply a 3-D vector by a scalar (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Vector3 operator *( const floatInVec &scalar, const Vector3 &vec ); - -// Multiply two 3-D vectors per element -// -VECTORMATH_FORCE_INLINE const Vector3 mulPerElem( const Vector3 &vec0, const Vector3 &vec1 ); - -// Divide two 3-D vectors per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -VECTORMATH_FORCE_INLINE const Vector3 divPerElem( const Vector3 &vec0, const Vector3 &vec1 ); - -// Compute the reciprocal of a 3-D vector per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -VECTORMATH_FORCE_INLINE const Vector3 recipPerElem( const Vector3 &vec ); - -// Compute the absolute value of a 3-D vector per element -// -VECTORMATH_FORCE_INLINE const Vector3 absPerElem( const Vector3 &vec ); - -// Copy sign from one 3-D vector to another, per element -// -VECTORMATH_FORCE_INLINE const Vector3 copySignPerElem( const Vector3 &vec0, const Vector3 &vec1 ); - -// Maximum of two 3-D vectors per element -// -VECTORMATH_FORCE_INLINE const Vector3 maxPerElem( const Vector3 &vec0, const Vector3 &vec1 ); - -// Minimum of two 3-D vectors per element -// -VECTORMATH_FORCE_INLINE const Vector3 minPerElem( const Vector3 &vec0, const Vector3 &vec1 ); - -// Maximum element of a 3-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector3 &vec ); - -// Minimum element of a 3-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector3 &vec ); - -// Compute the sum of all elements of a 3-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector3 &vec ); - -// Compute the dot product of two 3-D vectors -// -VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector3 &vec0, const Vector3 &vec1 ); - -// Compute the square of the length of a 3-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector3 &vec ); - -// Compute the length of a 3-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec length( const Vector3 &vec ); - -// Normalize a 3-D vector -// NOTE: -// The result is unpredictable when all elements of vec are at or near zero. -// -VECTORMATH_FORCE_INLINE const Vector3 normalize( const Vector3 &vec ); - -// Compute cross product of two 3-D vectors -// -VECTORMATH_FORCE_INLINE const Vector3 cross( const Vector3 &vec0, const Vector3 &vec1 ); - -// Outer product of two 3-D vectors -// -VECTORMATH_FORCE_INLINE const Matrix3 outer( const Vector3 &vec0, const Vector3 &vec1 ); - -// Pre-multiply a row vector by a 3x3 matrix -// NOTE: -// Slower than column post-multiply. -// -VECTORMATH_FORCE_INLINE const Vector3 rowMul( const Vector3 &vec, const Matrix3 & mat ); - -// Cross-product matrix of a 3-D vector -// -VECTORMATH_FORCE_INLINE const Matrix3 crossMatrix( const Vector3 &vec ); - -// Create cross-product matrix and multiply -// NOTE: -// Faster than separately creating a cross-product matrix and multiplying. -// -VECTORMATH_FORCE_INLINE const Matrix3 crossMatrixMul( const Vector3 &vec, const Matrix3 & mat ); - -// Linear interpolation between two 3-D vectors -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector3 lerp( float t, const Vector3 &vec0, const Vector3 &vec1 ); - -// Linear interpolation between two 3-D vectors (scalar data contained in vector data type) -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector3 lerp( const floatInVec &t, const Vector3 &vec0, const Vector3 &vec1 ); - -// Spherical linear interpolation between two 3-D vectors -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector3 slerp( float t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); - -// Spherical linear interpolation between two 3-D vectors (scalar data contained in vector data type) -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector3 slerp( const floatInVec &t, const Vector3 &unitVec0, const Vector3 &unitVec1 ); - -// Conditionally select between two 3-D vectors -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, bool select1 ); - -// Conditionally select between two 3-D vectors (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Vector3 select( const Vector3 &vec0, const Vector3 &vec1, const boolInVec &select1 ); - -// Store x, y, and z elements of 3-D vector in first three words of a quadword, preserving fourth word -// -VECTORMATH_FORCE_INLINE void storeXYZ( const Vector3 &vec, __m128 * quad ); - -// Load four three-float 3-D vectors, stored in three quadwords -// -VECTORMATH_FORCE_INLINE void loadXYZArray( Vector3 & vec0, Vector3 & vec1, Vector3 & vec2, Vector3 & vec3, const __m128 * threeQuads ); - -// Store four 3-D vectors in three quadwords -// -VECTORMATH_FORCE_INLINE void storeXYZArray( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, __m128 * threeQuads ); - -// Store eight 3-D vectors as half-floats -// -VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector3 &vec0, const Vector3 &vec1, const Vector3 &vec2, const Vector3 &vec3, const Vector3 &vec4, const Vector3 &vec5, const Vector3 &vec6, const Vector3 &vec7, vec_ushort8 * threeQuads ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3-D vector -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Vector3 &vec ); - -// Print a 3-D vector and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Vector3 &vec, const char * name ); - -#endif - -// A 4-D vector in array-of-structures format -// -class Vector4 -{ - __m128 mVec128; - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Vector4( ) { }; - - // Construct a 4-D vector from x, y, z, and w elements - // - VECTORMATH_FORCE_INLINE Vector4( float x, float y, float z, float w ); - - // Construct a 4-D vector from x, y, z, and w elements (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); - - // Construct a 4-D vector from a 3-D vector and a scalar - // - VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, float w ); - - // Construct a 4-D vector from a 3-D vector and a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4( const Vector3 &xyz, const floatInVec &w ); - - // Copy x, y, and z from a 3-D vector into a 4-D vector, and set w to 0 - // - explicit VECTORMATH_FORCE_INLINE Vector4( const Vector3 &vec ); - - // Copy x, y, and z from a 3-D point into a 4-D vector, and set w to 1 - // - explicit VECTORMATH_FORCE_INLINE Vector4( const Point3 &pnt ); - - // Copy elements from a quaternion into a 4-D vector - // - explicit VECTORMATH_FORCE_INLINE Vector4( const Quat &quat ); - - // Set all elements of a 4-D vector to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Vector4( float scalar ); - - // Set all elements of a 4-D vector to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Vector4( const floatInVec &scalar ); - - // Set vector float data in a 4-D vector - // - explicit VECTORMATH_FORCE_INLINE Vector4( __m128 vf4 ); - - // Get vector float data from a 4-D vector - // - VECTORMATH_FORCE_INLINE __m128 get128( ) const; - - // Assign one 4-D vector to another - // - VECTORMATH_FORCE_INLINE Vector4 & operator =( const Vector4 &vec ); - - // Set the x, y, and z elements of a 4-D vector - // NOTE: - // This function does not change the w element. - // - VECTORMATH_FORCE_INLINE Vector4 & setXYZ( const Vector3 &vec ); - - // Get the x, y, and z elements of a 4-D vector - // - VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; - - // Set the x element of a 4-D vector - // - VECTORMATH_FORCE_INLINE Vector4 & setX( float x ); - - // Set the y element of a 4-D vector - // - VECTORMATH_FORCE_INLINE Vector4 & setY( float y ); - - // Set the z element of a 4-D vector - // - VECTORMATH_FORCE_INLINE Vector4 & setZ( float z ); - - // Set the w element of a 4-D vector - // - VECTORMATH_FORCE_INLINE Vector4 & setW( float w ); - - // Set the x element of a 4-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & setX( const floatInVec &x ); - - // Set the y element of a 4-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & setY( const floatInVec &y ); - - // Set the z element of a 4-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & setZ( const floatInVec &z ); - - // Set the w element of a 4-D vector (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & setW( const floatInVec &w ); - - // Get the x element of a 4-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; - - // Get the y element of a 4-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; - - // Get the z element of a 4-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; - - // Get the w element of a 4-D vector - // - VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; - - // Set an x, y, z, or w element of a 4-D vector by index - // - VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, float value ); - - // Set an x, y, z, or w element of a 4-D vector by index (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & setElem( int idx, const floatInVec &value ); - - // Get an x, y, z, or w element of a 4-D vector by index - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); - - // Subscripting operator to get an element - // - VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; - - // Add two 4-D vectors - // - VECTORMATH_FORCE_INLINE const Vector4 operator +( const Vector4 &vec ) const; - - // Subtract a 4-D vector from another 4-D vector - // - VECTORMATH_FORCE_INLINE const Vector4 operator -( const Vector4 &vec ) const; - - // Multiply a 4-D vector by a scalar - // - VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar ) const; - - // Divide a 4-D vector by a scalar - // - VECTORMATH_FORCE_INLINE const Vector4 operator /( float scalar ) const; - - // Multiply a 4-D vector by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar ) const; - - // Divide a 4-D vector by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Vector4 operator /( const floatInVec &scalar ) const; - - // Perform compound assignment and addition with a 4-D vector - // - VECTORMATH_FORCE_INLINE Vector4 & operator +=( const Vector4 &vec ); - - // Perform compound assignment and subtraction by a 4-D vector - // - VECTORMATH_FORCE_INLINE Vector4 & operator -=( const Vector4 &vec ); - - // Perform compound assignment and multiplication by a scalar - // - VECTORMATH_FORCE_INLINE Vector4 & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - VECTORMATH_FORCE_INLINE Vector4 & operator /=( float scalar ); - - // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & operator *=( const floatInVec &scalar ); - - // Perform compound assignment and division by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Vector4 & operator /=( const floatInVec &scalar ); - - // Negate all elements of a 4-D vector - // - VECTORMATH_FORCE_INLINE const Vector4 operator -( ) const; - - // Construct x axis - // - static VECTORMATH_FORCE_INLINE const Vector4 xAxis( ); - - // Construct y axis - // - static VECTORMATH_FORCE_INLINE const Vector4 yAxis( ); - - // Construct z axis - // - static VECTORMATH_FORCE_INLINE const Vector4 zAxis( ); - - // Construct w axis - // - static VECTORMATH_FORCE_INLINE const Vector4 wAxis( ); - -}; - -// Multiply a 4-D vector by a scalar -// -VECTORMATH_FORCE_INLINE const Vector4 operator *( float scalar, const Vector4 &vec ); - -// Multiply a 4-D vector by a scalar (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Vector4 operator *( const floatInVec &scalar, const Vector4 &vec ); - -// Multiply two 4-D vectors per element -// -VECTORMATH_FORCE_INLINE const Vector4 mulPerElem( const Vector4 &vec0, const Vector4 &vec1 ); - -// Divide two 4-D vectors per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -VECTORMATH_FORCE_INLINE const Vector4 divPerElem( const Vector4 &vec0, const Vector4 &vec1 ); - -// Compute the reciprocal of a 4-D vector per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -VECTORMATH_FORCE_INLINE const Vector4 recipPerElem( const Vector4 &vec ); - -// Compute the absolute value of a 4-D vector per element -// -VECTORMATH_FORCE_INLINE const Vector4 absPerElem( const Vector4 &vec ); - -// Copy sign from one 4-D vector to another, per element -// -VECTORMATH_FORCE_INLINE const Vector4 copySignPerElem( const Vector4 &vec0, const Vector4 &vec1 ); - -// Maximum of two 4-D vectors per element -// -VECTORMATH_FORCE_INLINE const Vector4 maxPerElem( const Vector4 &vec0, const Vector4 &vec1 ); - -// Minimum of two 4-D vectors per element -// -VECTORMATH_FORCE_INLINE const Vector4 minPerElem( const Vector4 &vec0, const Vector4 &vec1 ); - -// Maximum element of a 4-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Vector4 &vec ); - -// Minimum element of a 4-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec minElem( const Vector4 &vec ); - -// Compute the sum of all elements of a 4-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec sum( const Vector4 &vec ); - -// Compute the dot product of two 4-D vectors -// -VECTORMATH_FORCE_INLINE const floatInVec dot( const Vector4 &vec0, const Vector4 &vec1 ); - -// Compute the square of the length of a 4-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec lengthSqr( const Vector4 &vec ); - -// Compute the length of a 4-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec length( const Vector4 &vec ); - -// Normalize a 4-D vector -// NOTE: -// The result is unpredictable when all elements of vec are at or near zero. -// -VECTORMATH_FORCE_INLINE const Vector4 normalize( const Vector4 &vec ); - -// Outer product of two 4-D vectors -// -VECTORMATH_FORCE_INLINE const Matrix4 outer( const Vector4 &vec0, const Vector4 &vec1 ); - -// Linear interpolation between two 4-D vectors -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector4 lerp( float t, const Vector4 &vec0, const Vector4 &vec1 ); - -// Linear interpolation between two 4-D vectors (scalar data contained in vector data type) -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector4 lerp( const floatInVec &t, const Vector4 &vec0, const Vector4 &vec1 ); - -// Spherical linear interpolation between two 4-D vectors -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector4 slerp( float t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); - -// Spherical linear interpolation between two 4-D vectors (scalar data contained in vector data type) -// NOTE: -// The result is unpredictable if the vectors point in opposite directions. -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Vector4 slerp( const floatInVec &t, const Vector4 &unitVec0, const Vector4 &unitVec1 ); - -// Conditionally select between two 4-D vectors -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, bool select1 ); - -// Conditionally select between two 4-D vectors (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Vector4 select( const Vector4 &vec0, const Vector4 &vec1, const boolInVec &select1 ); - -// Store four 4-D vectors as half-floats -// -VECTORMATH_FORCE_INLINE void storeHalfFloats( const Vector4 &vec0, const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3, vec_ushort8 * twoQuads ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 4-D vector -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Vector4 &vec ); - -// Print a 4-D vector and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Vector4 &vec, const char * name ); - -#endif - -// A 3-D point in array-of-structures format -// -class Point3 -{ - __m128 mVec128; - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Point3( ) { }; - - // Construct a 3-D point from x, y, and z elements - // - VECTORMATH_FORCE_INLINE Point3( float x, float y, float z ); - - // Construct a 3-D point from x, y, and z elements (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Point3( const floatInVec &x, const floatInVec &y, const floatInVec &z ); - - // Copy elements from a 3-D vector into a 3-D point - // - explicit VECTORMATH_FORCE_INLINE Point3( const Vector3 &vec ); - - // Set all elements of a 3-D point to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Point3( float scalar ); - - // Set all elements of a 3-D point to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Point3( const floatInVec &scalar ); - - // Set vector float data in a 3-D point - // - explicit VECTORMATH_FORCE_INLINE Point3( __m128 vf4 ); - - // Get vector float data from a 3-D point - // - VECTORMATH_FORCE_INLINE __m128 get128( ) const; - - // Assign one 3-D point to another - // - VECTORMATH_FORCE_INLINE Point3 & operator =( const Point3 &pnt ); - - // Set the x element of a 3-D point - // - VECTORMATH_FORCE_INLINE Point3 & setX( float x ); - - // Set the y element of a 3-D point - // - VECTORMATH_FORCE_INLINE Point3 & setY( float y ); - - // Set the z element of a 3-D point - // - VECTORMATH_FORCE_INLINE Point3 & setZ( float z ); - - // Set the x element of a 3-D point (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Point3 & setX( const floatInVec &x ); - - // Set the y element of a 3-D point (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Point3 & setY( const floatInVec &y ); - - // Set the z element of a 3-D point (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Point3 & setZ( const floatInVec &z ); - - // Get the x element of a 3-D point - // - VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; - - // Get the y element of a 3-D point - // - VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; - - // Get the z element of a 3-D point - // - VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; - - // Set an x, y, or z element of a 3-D point by index - // - VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, float value ); - - // Set an x, y, or z element of a 3-D point by index (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Point3 & setElem( int idx, const floatInVec &value ); - - // Get an x, y, or z element of a 3-D point by index - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); - - // Subscripting operator to get an element - // - VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; - - // Subtract a 3-D point from another 3-D point - // - VECTORMATH_FORCE_INLINE const Vector3 operator -( const Point3 &pnt ) const; - - // Add a 3-D point to a 3-D vector - // - VECTORMATH_FORCE_INLINE const Point3 operator +( const Vector3 &vec ) const; - - // Subtract a 3-D vector from a 3-D point - // - VECTORMATH_FORCE_INLINE const Point3 operator -( const Vector3 &vec ) const; - - // Perform compound assignment and addition with a 3-D vector - // - VECTORMATH_FORCE_INLINE Point3 & operator +=( const Vector3 &vec ); - - // Perform compound assignment and subtraction by a 3-D vector - // - VECTORMATH_FORCE_INLINE Point3 & operator -=( const Vector3 &vec ); - -}; - -// Multiply two 3-D points per element -// -VECTORMATH_FORCE_INLINE const Point3 mulPerElem( const Point3 &pnt0, const Point3 &pnt1 ); - -// Divide two 3-D points per element -// NOTE: -// Floating-point behavior matches standard library function divf4. -// -VECTORMATH_FORCE_INLINE const Point3 divPerElem( const Point3 &pnt0, const Point3 &pnt1 ); - -// Compute the reciprocal of a 3-D point per element -// NOTE: -// Floating-point behavior matches standard library function recipf4. -// -VECTORMATH_FORCE_INLINE const Point3 recipPerElem( const Point3 &pnt ); - -// Compute the absolute value of a 3-D point per element -// -VECTORMATH_FORCE_INLINE const Point3 absPerElem( const Point3 &pnt ); - -// Copy sign from one 3-D point to another, per element -// -VECTORMATH_FORCE_INLINE const Point3 copySignPerElem( const Point3 &pnt0, const Point3 &pnt1 ); - -// Maximum of two 3-D points per element -// -VECTORMATH_FORCE_INLINE const Point3 maxPerElem( const Point3 &pnt0, const Point3 &pnt1 ); - -// Minimum of two 3-D points per element -// -VECTORMATH_FORCE_INLINE const Point3 minPerElem( const Point3 &pnt0, const Point3 &pnt1 ); - -// Maximum element of a 3-D point -// -VECTORMATH_FORCE_INLINE const floatInVec maxElem( const Point3 &pnt ); - -// Minimum element of a 3-D point -// -VECTORMATH_FORCE_INLINE const floatInVec minElem( const Point3 &pnt ); - -// Compute the sum of all elements of a 3-D point -// -VECTORMATH_FORCE_INLINE const floatInVec sum( const Point3 &pnt ); - -// Apply uniform scale to a 3-D point -// -VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, float scaleVal ); - -// Apply uniform scale to a 3-D point (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const floatInVec &scaleVal ); - -// Apply non-uniform scale to a 3-D point -// -VECTORMATH_FORCE_INLINE const Point3 scale( const Point3 &pnt, const Vector3 &scaleVec ); - -// Scalar projection of a 3-D point on a unit-length 3-D vector -// -VECTORMATH_FORCE_INLINE const floatInVec projection( const Point3 &pnt, const Vector3 &unitVec ); - -// Compute the square of the distance of a 3-D point from the coordinate-system origin -// -VECTORMATH_FORCE_INLINE const floatInVec distSqrFromOrigin( const Point3 &pnt ); - -// Compute the distance of a 3-D point from the coordinate-system origin -// -VECTORMATH_FORCE_INLINE const floatInVec distFromOrigin( const Point3 &pnt ); - -// Compute the square of the distance between two 3-D points -// -VECTORMATH_FORCE_INLINE const floatInVec distSqr( const Point3 &pnt0, const Point3 &pnt1 ); - -// Compute the distance between two 3-D points -// -VECTORMATH_FORCE_INLINE const floatInVec dist( const Point3 &pnt0, const Point3 &pnt1 ); - -// Linear interpolation between two 3-D points -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Point3 lerp( float t, const Point3 &pnt0, const Point3 &pnt1 ); - -// Linear interpolation between two 3-D points (scalar data contained in vector data type) -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Point3 lerp( const floatInVec &t, const Point3 &pnt0, const Point3 &pnt1 ); - -// Conditionally select between two 3-D points -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, bool select1 ); - -// Conditionally select between two 3-D points (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Point3 select( const Point3 &pnt0, const Point3 &pnt1, const boolInVec &select1 ); - -// Store x, y, and z elements of 3-D point in first three words of a quadword, preserving fourth word -// -VECTORMATH_FORCE_INLINE void storeXYZ( const Point3 &pnt, __m128 * quad ); - -// Load four three-float 3-D points, stored in three quadwords -// -VECTORMATH_FORCE_INLINE void loadXYZArray( Point3 & pnt0, Point3 & pnt1, Point3 & pnt2, Point3 & pnt3, const __m128 * threeQuads ); - -// Store four 3-D points in three quadwords -// -VECTORMATH_FORCE_INLINE void storeXYZArray( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, __m128 * threeQuads ); - -// Store eight 3-D points as half-floats -// -VECTORMATH_FORCE_INLINE void storeHalfFloats( const Point3 &pnt0, const Point3 &pnt1, const Point3 &pnt2, const Point3 &pnt3, const Point3 &pnt4, const Point3 &pnt5, const Point3 &pnt6, const Point3 &pnt7, vec_ushort8 * threeQuads ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3-D point -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Point3 &pnt ); - -// Print a 3-D point and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Point3 &pnt, const char * name ); - -#endif - -// A quaternion in array-of-structures format -// -class Quat -{ - __m128 mVec128; - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Quat( ) { }; - - VECTORMATH_FORCE_INLINE Quat(const Quat& quat); - - // Construct a quaternion from x, y, z, and w elements - // - VECTORMATH_FORCE_INLINE Quat( float x, float y, float z, float w ); - - // Construct a quaternion from x, y, z, and w elements (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat( const floatInVec &x, const floatInVec &y, const floatInVec &z, const floatInVec &w ); - - // Construct a quaternion from a 3-D vector and a scalar - // - VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, float w ); - - // Construct a quaternion from a 3-D vector and a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat( const Vector3 &xyz, const floatInVec &w ); - - // Copy elements from a 4-D vector into a quaternion - // - explicit VECTORMATH_FORCE_INLINE Quat( const Vector4 &vec ); - - // Convert a rotation matrix to a unit-length quaternion - // - explicit VECTORMATH_FORCE_INLINE Quat( const Matrix3 & rotMat ); - - // Set all elements of a quaternion to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Quat( float scalar ); - - // Set all elements of a quaternion to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Quat( const floatInVec &scalar ); - - // Set vector float data in a quaternion - // - explicit VECTORMATH_FORCE_INLINE Quat( __m128 vf4 ); - - // Get vector float data from a quaternion - // - VECTORMATH_FORCE_INLINE __m128 get128( ) const; - - // Set a quaterion from vector float data - // - VECTORMATH_FORCE_INLINE void set128(vec_float4 vec); - - // Assign one quaternion to another - // - VECTORMATH_FORCE_INLINE Quat & operator =( const Quat &quat ); - - // Set the x, y, and z elements of a quaternion - // NOTE: - // This function does not change the w element. - // - VECTORMATH_FORCE_INLINE Quat & setXYZ( const Vector3 &vec ); - - // Get the x, y, and z elements of a quaternion - // - VECTORMATH_FORCE_INLINE const Vector3 getXYZ( ) const; - - // Set the x element of a quaternion - // - VECTORMATH_FORCE_INLINE Quat & setX( float x ); - - // Set the y element of a quaternion - // - VECTORMATH_FORCE_INLINE Quat & setY( float y ); - - // Set the z element of a quaternion - // - VECTORMATH_FORCE_INLINE Quat & setZ( float z ); - - // Set the w element of a quaternion - // - VECTORMATH_FORCE_INLINE Quat & setW( float w ); - - // Set the x element of a quaternion (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & setX( const floatInVec &x ); - - // Set the y element of a quaternion (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & setY( const floatInVec &y ); - - // Set the z element of a quaternion (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & setZ( const floatInVec &z ); - - // Set the w element of a quaternion (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & setW( const floatInVec &w ); - - // Get the x element of a quaternion - // - VECTORMATH_FORCE_INLINE const floatInVec getX( ) const; - - // Get the y element of a quaternion - // - VECTORMATH_FORCE_INLINE const floatInVec getY( ) const; - - // Get the z element of a quaternion - // - VECTORMATH_FORCE_INLINE const floatInVec getZ( ) const; - - // Get the w element of a quaternion - // - VECTORMATH_FORCE_INLINE const floatInVec getW( ) const; - - // Set an x, y, z, or w element of a quaternion by index - // - VECTORMATH_FORCE_INLINE Quat & setElem( int idx, float value ); - - // Set an x, y, z, or w element of a quaternion by index (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & setElem( int idx, const floatInVec &value ); - - // Get an x, y, z, or w element of a quaternion by index - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int idx ) const; - - // Subscripting operator to set or get an element - // - VECTORMATH_FORCE_INLINE VecIdx operator []( int idx ); - - // Subscripting operator to get an element - // - VECTORMATH_FORCE_INLINE const floatInVec operator []( int idx ) const; - - // Add two quaternions - // - VECTORMATH_FORCE_INLINE const Quat operator +( const Quat &quat ) const; - - // Subtract a quaternion from another quaternion - // - VECTORMATH_FORCE_INLINE const Quat operator -( const Quat &quat ) const; - - // Multiply two quaternions - // - VECTORMATH_FORCE_INLINE const Quat operator *( const Quat &quat ) const; - - // Multiply a quaternion by a scalar - // - VECTORMATH_FORCE_INLINE const Quat operator *( float scalar ) const; - - // Divide a quaternion by a scalar - // - VECTORMATH_FORCE_INLINE const Quat operator /( float scalar ) const; - - // Multiply a quaternion by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar ) const; - - // Divide a quaternion by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Quat operator /( const floatInVec &scalar ) const; - - // Perform compound assignment and addition with a quaternion - // - VECTORMATH_FORCE_INLINE Quat & operator +=( const Quat &quat ); - - // Perform compound assignment and subtraction by a quaternion - // - VECTORMATH_FORCE_INLINE Quat & operator -=( const Quat &quat ); - - // Perform compound assignment and multiplication by a quaternion - // - VECTORMATH_FORCE_INLINE Quat & operator *=( const Quat &quat ); - - // Perform compound assignment and multiplication by a scalar - // - VECTORMATH_FORCE_INLINE Quat & operator *=( float scalar ); - - // Perform compound assignment and division by a scalar - // - VECTORMATH_FORCE_INLINE Quat & operator /=( float scalar ); - - // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & operator *=( const floatInVec &scalar ); - - // Perform compound assignment and division by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Quat & operator /=( const floatInVec &scalar ); - - // Negate all elements of a quaternion - // - VECTORMATH_FORCE_INLINE const Quat operator -( ) const; - - // Construct an identity quaternion - // - static VECTORMATH_FORCE_INLINE const Quat identity( ); - - // Construct a quaternion to rotate between two unit-length 3-D vectors - // NOTE: - // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. - // - static VECTORMATH_FORCE_INLINE const Quat rotation( const Vector3 &unitVec0, const Vector3 &unitVec1 ); - - // Construct a quaternion to rotate around a unit-length 3-D vector - // - static VECTORMATH_FORCE_INLINE const Quat rotation( float radians, const Vector3 &unitVec ); - - // Construct a quaternion to rotate around a unit-length 3-D vector (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Quat rotation( const floatInVec &radians, const Vector3 &unitVec ); - - // Construct a quaternion to rotate around the x axis - // - static VECTORMATH_FORCE_INLINE const Quat rotationX( float radians ); - - // Construct a quaternion to rotate around the y axis - // - static VECTORMATH_FORCE_INLINE const Quat rotationY( float radians ); - - // Construct a quaternion to rotate around the z axis - // - static VECTORMATH_FORCE_INLINE const Quat rotationZ( float radians ); - - // Construct a quaternion to rotate around the x axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Quat rotationX( const floatInVec &radians ); - - // Construct a quaternion to rotate around the y axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Quat rotationY( const floatInVec &radians ); - - // Construct a quaternion to rotate around the z axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Quat rotationZ( const floatInVec &radians ); - -}; - -// Multiply a quaternion by a scalar -// -VECTORMATH_FORCE_INLINE const Quat operator *( float scalar, const Quat &quat ); - -// Multiply a quaternion by a scalar (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Quat operator *( const floatInVec &scalar, const Quat &quat ); - -// Compute the conjugate of a quaternion -// -VECTORMATH_FORCE_INLINE const Quat conj( const Quat &quat ); - -// Use a unit-length quaternion to rotate a 3-D vector -// -VECTORMATH_FORCE_INLINE const Vector3 rotate( const Quat &unitQuat, const Vector3 &vec ); - -// Compute the dot product of two quaternions -// -VECTORMATH_FORCE_INLINE const floatInVec dot( const Quat &quat0, const Quat &quat1 ); - -// Compute the norm of a quaternion -// -VECTORMATH_FORCE_INLINE const floatInVec norm( const Quat &quat ); - -// Compute the length of a quaternion -// -VECTORMATH_FORCE_INLINE const floatInVec length( const Quat &quat ); - -// Normalize a quaternion -// NOTE: -// The result is unpredictable when all elements of quat are at or near zero. -// -VECTORMATH_FORCE_INLINE const Quat normalize( const Quat &quat ); - -// Linear interpolation between two quaternions -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Quat lerp( float t, const Quat &quat0, const Quat &quat1 ); - -// Linear interpolation between two quaternions (scalar data contained in vector data type) -// NOTE: -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Quat lerp( const floatInVec &t, const Quat &quat0, const Quat &quat1 ); - -// Spherical linear interpolation between two quaternions -// NOTE: -// Interpolates along the shortest path between orientations. -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Quat slerp( float t, const Quat &unitQuat0, const Quat &unitQuat1 ); - -// Spherical linear interpolation between two quaternions (scalar data contained in vector data type) -// NOTE: -// Interpolates along the shortest path between orientations. -// Does not clamp t between 0 and 1. -// -VECTORMATH_FORCE_INLINE const Quat slerp( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1 ); - -// Spherical quadrangle interpolation -// -VECTORMATH_FORCE_INLINE const Quat squad( float t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); - -// Spherical quadrangle interpolation (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Quat squad( const floatInVec &t, const Quat &unitQuat0, const Quat &unitQuat1, const Quat &unitQuat2, const Quat &unitQuat3 ); - -// Conditionally select between two quaternions -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, bool select1 ); - -// Conditionally select between two quaternions (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Quat select( const Quat &quat0, const Quat &quat1, const boolInVec &select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a quaternion -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Quat &quat ); - -// Print a quaternion and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Quat &quat, const char * name ); - -#endif - -// A 3x3 matrix in array-of-structures format -// -class Matrix3 -{ - Vector3 mCol0; - Vector3 mCol1; - Vector3 mCol2; - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Matrix3( ) { }; - - // Copy a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3( const Matrix3 & mat ); - - // Construct a 3x3 matrix containing the specified columns - // - VECTORMATH_FORCE_INLINE Matrix3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2 ); - - // Construct a 3x3 rotation matrix from a unit-length quaternion - // - explicit VECTORMATH_FORCE_INLINE Matrix3( const Quat &unitQuat ); - - // Set all elements of a 3x3 matrix to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Matrix3( float scalar ); - - // Set all elements of a 3x3 matrix to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Matrix3( const floatInVec &scalar ); - - // Assign one 3x3 matrix to another - // - VECTORMATH_FORCE_INLINE Matrix3 & operator =( const Matrix3 & mat ); - - // Set column 0 of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3 & setCol0( const Vector3 &col0 ); - - // Set column 1 of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3 & setCol1( const Vector3 &col1 ); - - // Set column 2 of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3 & setCol2( const Vector3 &col2 ); - - // Get column 0 of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; - - // Get column 1 of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; - - // Get column 2 of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; - - // Set the column of a 3x3 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE Matrix3 & setCol( int col, const Vector3 &vec ); - - // Set the row of a 3x3 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE Matrix3 & setRow( int row, const Vector3 &vec ); - - // Get the column of a 3x3 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; - - // Get the row of a 3x3 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE const Vector3 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); - - // Subscripting operator to get a column - // - VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; - - // Set the element of a 3x3 matrix referred to by column and row indices - // - VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, float val ); - - // Set the element of a 3x3 matrix referred to by column and row indices (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Matrix3 & setElem( int col, int row, const floatInVec &val ); - - // Get the element of a 3x3 matrix referred to by column and row indices - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; - - // Add two 3x3 matrices - // - VECTORMATH_FORCE_INLINE const Matrix3 operator +( const Matrix3 & mat ) const; - - // Subtract a 3x3 matrix from another 3x3 matrix - // - VECTORMATH_FORCE_INLINE const Matrix3 operator -( const Matrix3 & mat ) const; - - // Negate all elements of a 3x3 matrix - // - VECTORMATH_FORCE_INLINE const Matrix3 operator -( ) const; - - // Multiply a 3x3 matrix by a scalar - // - VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar ) const; - - // Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar ) const; - - // Multiply a 3x3 matrix by a 3-D vector - // - VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; - - // Multiply two 3x3 matrices - // - VECTORMATH_FORCE_INLINE const Matrix3 operator *( const Matrix3 & mat ) const; - - // Perform compound assignment and addition with a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3 & operator +=( const Matrix3 & mat ); - - // Perform compound assignment and subtraction by a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3 & operator -=( const Matrix3 & mat ); - - // Perform compound assignment and multiplication by a scalar - // - VECTORMATH_FORCE_INLINE Matrix3 & operator *=( float scalar ); - - // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const floatInVec &scalar ); - - // Perform compound assignment and multiplication by a 3x3 matrix - // - VECTORMATH_FORCE_INLINE Matrix3 & operator *=( const Matrix3 & mat ); - - // Construct an identity 3x3 matrix - // - static VECTORMATH_FORCE_INLINE const Matrix3 identity( ); - - // Construct a 3x3 matrix to rotate around the x axis - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( float radians ); - - // Construct a 3x3 matrix to rotate around the y axis - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( float radians ); - - // Construct a 3x3 matrix to rotate around the z axis - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( float radians ); - - // Construct a 3x3 matrix to rotate around the x axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationX( const floatInVec &radians ); - - // Construct a 3x3 matrix to rotate around the y axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationY( const floatInVec &radians ); - - // Construct a 3x3 matrix to rotate around the z axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationZ( const floatInVec &radians ); - - // Construct a 3x3 matrix to rotate around the x, y, and z axes - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotationZYX( const Vector3 &radiansXYZ ); - - // Construct a 3x3 matrix to rotate around a unit-length 3-D vector - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotation( float radians, const Vector3 &unitVec ); - - // Construct a 3x3 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const floatInVec &radians, const Vector3 &unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static VECTORMATH_FORCE_INLINE const Matrix3 rotation( const Quat &unitQuat ); - - // Construct a 3x3 matrix to perform scaling - // - static VECTORMATH_FORCE_INLINE const Matrix3 scale( const Vector3 &scaleVec ); - -}; -// Multiply a 3x3 matrix by a scalar -// -VECTORMATH_FORCE_INLINE const Matrix3 operator *( float scalar, const Matrix3 & mat ); - -// Multiply a 3x3 matrix by a scalar (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Matrix3 operator *( const floatInVec &scalar, const Matrix3 & mat ); - -// Append (post-multiply) a scale transformation to a 3x3 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -VECTORMATH_FORCE_INLINE const Matrix3 appendScale( const Matrix3 & mat, const Vector3 &scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 3x3 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -VECTORMATH_FORCE_INLINE const Matrix3 prependScale( const Vector3 &scaleVec, const Matrix3 & mat ); - -// Multiply two 3x3 matrices per element -// -VECTORMATH_FORCE_INLINE const Matrix3 mulPerElem( const Matrix3 & mat0, const Matrix3 & mat1 ); - -// Compute the absolute value of a 3x3 matrix per element -// -VECTORMATH_FORCE_INLINE const Matrix3 absPerElem( const Matrix3 & mat ); - -// Transpose of a 3x3 matrix -// -VECTORMATH_FORCE_INLINE const Matrix3 transpose( const Matrix3 & mat ); - -// Compute the inverse of a 3x3 matrix -// NOTE: -// Result is unpredictable when the determinant of mat is equal to or near 0. -// -VECTORMATH_FORCE_INLINE const Matrix3 inverse( const Matrix3 & mat ); - -// Determinant of a 3x3 matrix -// -VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix3 & mat ); - -// Conditionally select between two 3x3 matrices -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, bool select1 ); - -// Conditionally select between two 3x3 matrices (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Matrix3 select( const Matrix3 & mat0, const Matrix3 & mat1, const boolInVec &select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3x3 matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat ); - -// Print a 3x3 matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Matrix3 & mat, const char * name ); - -#endif - -// A 4x4 matrix in array-of-structures format -// -class Matrix4 -{ - Vector4 mCol0; - Vector4 mCol1; - Vector4 mCol2; - Vector4 mCol3; - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Matrix4( ) { }; - - // Copy a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4( const Matrix4 & mat ); - - // Construct a 4x4 matrix containing the specified columns - // - VECTORMATH_FORCE_INLINE Matrix4( const Vector4 &col0, const Vector4 &col1, const Vector4 &col2, const Vector4 &col3 ); - - // Construct a 4x4 matrix from a 3x4 transformation matrix - // - explicit VECTORMATH_FORCE_INLINE Matrix4( const Transform3 & mat ); - - // Construct a 4x4 matrix from a 3x3 matrix and a 3-D vector - // - VECTORMATH_FORCE_INLINE Matrix4( const Matrix3 & mat, const Vector3 &translateVec ); - - // Construct a 4x4 matrix from a unit-length quaternion and a 3-D vector - // - VECTORMATH_FORCE_INLINE Matrix4( const Quat &unitQuat, const Vector3 &translateVec ); - - // Set all elements of a 4x4 matrix to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Matrix4( float scalar ); - - // Set all elements of a 4x4 matrix to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Matrix4( const floatInVec &scalar ); - - // Assign one 4x4 matrix to another - // - VECTORMATH_FORCE_INLINE Matrix4 & operator =( const Matrix4 & mat ); - - // Set the upper-left 3x3 submatrix - // NOTE: - // This function does not change the bottom row elements. - // - VECTORMATH_FORCE_INLINE Matrix4 & setUpper3x3( const Matrix3 & mat3 ); - - // Get the upper-left 3x3 submatrix of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; - - // Set translation component - // NOTE: - // This function does not change the bottom row elements. - // - VECTORMATH_FORCE_INLINE Matrix4 & setTranslation( const Vector3 &translateVec ); - - // Get the translation component of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; - - // Set column 0 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & setCol0( const Vector4 &col0 ); - - // Set column 1 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & setCol1( const Vector4 &col1 ); - - // Set column 2 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & setCol2( const Vector4 &col2 ); - - // Set column 3 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & setCol3( const Vector4 &col3 ); - - // Get column 0 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Vector4 getCol0( ) const; - - // Get column 1 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Vector4 getCol1( ) const; - - // Get column 2 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Vector4 getCol2( ) const; - - // Get column 3 of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Vector4 getCol3( ) const; - - // Set the column of a 4x4 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE Matrix4 & setCol( int col, const Vector4 &vec ); - - // Set the row of a 4x4 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE Matrix4 & setRow( int row, const Vector4 &vec ); - - // Get the column of a 4x4 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE const Vector4 getCol( int col ) const; - - // Get the row of a 4x4 matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - VECTORMATH_FORCE_INLINE Vector4 & operator []( int col ); - - // Subscripting operator to get a column - // - VECTORMATH_FORCE_INLINE const Vector4 operator []( int col ) const; - - // Set the element of a 4x4 matrix referred to by column and row indices - // - VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, float val ); - - // Set the element of a 4x4 matrix referred to by column and row indices (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Matrix4 & setElem( int col, int row, const floatInVec &val ); - - // Get the element of a 4x4 matrix referred to by column and row indices - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; - - // Add two 4x4 matrices - // - VECTORMATH_FORCE_INLINE const Matrix4 operator +( const Matrix4 & mat ) const; - - // Subtract a 4x4 matrix from another 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Matrix4 operator -( const Matrix4 & mat ) const; - - // Negate all elements of a 4x4 matrix - // - VECTORMATH_FORCE_INLINE const Matrix4 operator -( ) const; - - // Multiply a 4x4 matrix by a scalar - // - VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar ) const; - - // Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar ) const; - - // Multiply a 4x4 matrix by a 4-D vector - // - VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector4 &vec ) const; - - // Multiply a 4x4 matrix by a 3-D vector - // - VECTORMATH_FORCE_INLINE const Vector4 operator *( const Vector3 &vec ) const; - - // Multiply a 4x4 matrix by a 3-D point - // - VECTORMATH_FORCE_INLINE const Vector4 operator *( const Point3 &pnt ) const; - - // Multiply two 4x4 matrices - // - VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Matrix4 & mat ) const; - - // Multiply a 4x4 matrix by a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Matrix4 operator *( const Transform3 & tfrm ) const; - - // Perform compound assignment and addition with a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & operator +=( const Matrix4 & mat ); - - // Perform compound assignment and subtraction by a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & operator -=( const Matrix4 & mat ); - - // Perform compound assignment and multiplication by a scalar - // - VECTORMATH_FORCE_INLINE Matrix4 & operator *=( float scalar ); - - // Perform compound assignment and multiplication by a scalar (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const floatInVec &scalar ); - - // Perform compound assignment and multiplication by a 4x4 matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Matrix4 & mat ); - - // Perform compound assignment and multiplication by a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Matrix4 & operator *=( const Transform3 & tfrm ); - - // Construct an identity 4x4 matrix - // - static VECTORMATH_FORCE_INLINE const Matrix4 identity( ); - - // Construct a 4x4 matrix to rotate around the x axis - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( float radians ); - - // Construct a 4x4 matrix to rotate around the y axis - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( float radians ); - - // Construct a 4x4 matrix to rotate around the z axis - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( float radians ); - - // Construct a 4x4 matrix to rotate around the x axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationX( const floatInVec &radians ); - - // Construct a 4x4 matrix to rotate around the y axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationY( const floatInVec &radians ); - - // Construct a 4x4 matrix to rotate around the z axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationZ( const floatInVec &radians ); - - // Construct a 4x4 matrix to rotate around the x, y, and z axes - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotationZYX( const Vector3 &radiansXYZ ); - - // Construct a 4x4 matrix to rotate around a unit-length 3-D vector - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotation( float radians, const Vector3 &unitVec ); - - // Construct a 4x4 matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const floatInVec &radians, const Vector3 &unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static VECTORMATH_FORCE_INLINE const Matrix4 rotation( const Quat &unitQuat ); - - // Construct a 4x4 matrix to perform scaling - // - static VECTORMATH_FORCE_INLINE const Matrix4 scale( const Vector3 &scaleVec ); - - // Construct a 4x4 matrix to perform translation - // - static VECTORMATH_FORCE_INLINE const Matrix4 translation( const Vector3 &translateVec ); - - // Construct viewing matrix based on eye, position looked at, and up direction - // - static VECTORMATH_FORCE_INLINE const Matrix4 lookAt( const Point3 &eyePos, const Point3 &lookAtPos, const Vector3 &upVec ); - - // Construct a perspective projection matrix - // - static VECTORMATH_FORCE_INLINE const Matrix4 perspective( float fovyRadians, float aspect, float zNear, float zFar ); - - // Construct a perspective projection matrix based on frustum - // - static VECTORMATH_FORCE_INLINE const Matrix4 frustum( float left, float right, float bottom, float top, float zNear, float zFar ); - - // Construct an orthographic projection matrix - // - static VECTORMATH_FORCE_INLINE const Matrix4 orthographic( float left, float right, float bottom, float top, float zNear, float zFar ); - -}; -// Multiply a 4x4 matrix by a scalar -// -VECTORMATH_FORCE_INLINE const Matrix4 operator *( float scalar, const Matrix4 & mat ); - -// Multiply a 4x4 matrix by a scalar (scalar data contained in vector data type) -// -VECTORMATH_FORCE_INLINE const Matrix4 operator *( const floatInVec &scalar, const Matrix4 & mat ); - -// Append (post-multiply) a scale transformation to a 4x4 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -VECTORMATH_FORCE_INLINE const Matrix4 appendScale( const Matrix4 & mat, const Vector3 &scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 4x4 matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -VECTORMATH_FORCE_INLINE const Matrix4 prependScale( const Vector3 &scaleVec, const Matrix4 & mat ); - -// Multiply two 4x4 matrices per element -// -VECTORMATH_FORCE_INLINE const Matrix4 mulPerElem( const Matrix4 & mat0, const Matrix4 & mat1 ); - -// Compute the absolute value of a 4x4 matrix per element -// -VECTORMATH_FORCE_INLINE const Matrix4 absPerElem( const Matrix4 & mat ); - -// Transpose of a 4x4 matrix -// -VECTORMATH_FORCE_INLINE const Matrix4 transpose( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix -// NOTE: -// Result is unpredictable when the determinant of mat is equal to or near 0. -// -VECTORMATH_FORCE_INLINE const Matrix4 inverse( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. The result is unpredictable when the determinant of mat is equal to or near 0. -// -VECTORMATH_FORCE_INLINE const Matrix4 affineInverse( const Matrix4 & mat ); - -// Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 4x4 matrix meets the given restrictions. -// -VECTORMATH_FORCE_INLINE const Matrix4 orthoInverse( const Matrix4 & mat ); - -// Determinant of a 4x4 matrix -// -VECTORMATH_FORCE_INLINE const floatInVec determinant( const Matrix4 & mat ); - -// Conditionally select between two 4x4 matrices -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, bool select1 ); - -// Conditionally select between two 4x4 matrices (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Matrix4 select( const Matrix4 & mat0, const Matrix4 & mat1, const boolInVec &select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 4x4 matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat ); - -// Print a 4x4 matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Matrix4 & mat, const char * name ); - -#endif - -// A 3x4 transformation matrix in array-of-structures format -// -class Transform3 -{ - Vector3 mCol0; - Vector3 mCol1; - Vector3 mCol2; - Vector3 mCol3; - -public: - // Default constructor; does no initialization - // - VECTORMATH_FORCE_INLINE Transform3( ) { }; - - // Copy a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Transform3( const Transform3 & tfrm ); - - // Construct a 3x4 transformation matrix containing the specified columns - // - VECTORMATH_FORCE_INLINE Transform3( const Vector3 &col0, const Vector3 &col1, const Vector3 &col2, const Vector3 &col3 ); - - // Construct a 3x4 transformation matrix from a 3x3 matrix and a 3-D vector - // - VECTORMATH_FORCE_INLINE Transform3( const Matrix3 & tfrm, const Vector3 &translateVec ); - - // Construct a 3x4 transformation matrix from a unit-length quaternion and a 3-D vector - // - VECTORMATH_FORCE_INLINE Transform3( const Quat &unitQuat, const Vector3 &translateVec ); - - // Set all elements of a 3x4 transformation matrix to the same scalar value - // - explicit VECTORMATH_FORCE_INLINE Transform3( float scalar ); - - // Set all elements of a 3x4 transformation matrix to the same scalar value (scalar data contained in vector data type) - // - explicit VECTORMATH_FORCE_INLINE Transform3( const floatInVec &scalar ); - - // Assign one 3x4 transformation matrix to another - // - VECTORMATH_FORCE_INLINE Transform3 & operator =( const Transform3 & tfrm ); - - // Set the upper-left 3x3 submatrix - // - VECTORMATH_FORCE_INLINE Transform3 & setUpper3x3( const Matrix3 & mat3 ); - - // Get the upper-left 3x3 submatrix of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Matrix3 getUpper3x3( ) const; - - // Set translation component - // - VECTORMATH_FORCE_INLINE Transform3 & setTranslation( const Vector3 &translateVec ); - - // Get the translation component of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getTranslation( ) const; - - // Set column 0 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Transform3 & setCol0( const Vector3 &col0 ); - - // Set column 1 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Transform3 & setCol1( const Vector3 &col1 ); - - // Set column 2 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Transform3 & setCol2( const Vector3 &col2 ); - - // Set column 3 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Transform3 & setCol3( const Vector3 &col3 ); - - // Get column 0 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol0( ) const; - - // Get column 1 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol1( ) const; - - // Get column 2 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol2( ) const; - - // Get column 3 of a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE const Vector3 getCol3( ) const; - - // Set the column of a 3x4 transformation matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE Transform3 & setCol( int col, const Vector3 &vec ); - - // Set the row of a 3x4 transformation matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE Transform3 & setRow( int row, const Vector4 &vec ); - - // Get the column of a 3x4 transformation matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE const Vector3 getCol( int col ) const; - - // Get the row of a 3x4 transformation matrix referred to by the specified index - // - VECTORMATH_FORCE_INLINE const Vector4 getRow( int row ) const; - - // Subscripting operator to set or get a column - // - VECTORMATH_FORCE_INLINE Vector3 & operator []( int col ); - - // Subscripting operator to get a column - // - VECTORMATH_FORCE_INLINE const Vector3 operator []( int col ) const; - - // Set the element of a 3x4 transformation matrix referred to by column and row indices - // - VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, float val ); - - // Set the element of a 3x4 transformation matrix referred to by column and row indices (scalar data contained in vector data type) - // - VECTORMATH_FORCE_INLINE Transform3 & setElem( int col, int row, const floatInVec &val ); - - // Get the element of a 3x4 transformation matrix referred to by column and row indices - // - VECTORMATH_FORCE_INLINE const floatInVec getElem( int col, int row ) const; - - // Multiply a 3x4 transformation matrix by a 3-D vector - // - VECTORMATH_FORCE_INLINE const Vector3 operator *( const Vector3 &vec ) const; - - // Multiply a 3x4 transformation matrix by a 3-D point - // - VECTORMATH_FORCE_INLINE const Point3 operator *( const Point3 &pnt ) const; - - // Multiply two 3x4 transformation matrices - // - VECTORMATH_FORCE_INLINE const Transform3 operator *( const Transform3 & tfrm ) const; - - // Perform compound assignment and multiplication by a 3x4 transformation matrix - // - VECTORMATH_FORCE_INLINE Transform3 & operator *=( const Transform3 & tfrm ); - - // Construct an identity 3x4 transformation matrix - // - static VECTORMATH_FORCE_INLINE const Transform3 identity( ); - - // Construct a 3x4 transformation matrix to rotate around the x axis - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationX( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the y axis - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationY( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the z axis - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( float radians ); - - // Construct a 3x4 transformation matrix to rotate around the x axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationX( const floatInVec &radians ); - - // Construct a 3x4 transformation matrix to rotate around the y axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationY( const floatInVec &radians ); - - // Construct a 3x4 transformation matrix to rotate around the z axis (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationZ( const floatInVec &radians ); - - // Construct a 3x4 transformation matrix to rotate around the x, y, and z axes - // - static VECTORMATH_FORCE_INLINE const Transform3 rotationZYX( const Vector3 &radiansXYZ ); - - // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector - // - static VECTORMATH_FORCE_INLINE const Transform3 rotation( float radians, const Vector3 &unitVec ); - - // Construct a 3x4 transformation matrix to rotate around a unit-length 3-D vector (scalar data contained in vector data type) - // - static VECTORMATH_FORCE_INLINE const Transform3 rotation( const floatInVec &radians, const Vector3 &unitVec ); - - // Construct a rotation matrix from a unit-length quaternion - // - static VECTORMATH_FORCE_INLINE const Transform3 rotation( const Quat &unitQuat ); - - // Construct a 3x4 transformation matrix to perform scaling - // - static VECTORMATH_FORCE_INLINE const Transform3 scale( const Vector3 &scaleVec ); - - // Construct a 3x4 transformation matrix to perform translation - // - static VECTORMATH_FORCE_INLINE const Transform3 translation( const Vector3 &translateVec ); - -}; -// Append (post-multiply) a scale transformation to a 3x4 transformation matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -VECTORMATH_FORCE_INLINE const Transform3 appendScale( const Transform3 & tfrm, const Vector3 &scaleVec ); - -// Prepend (pre-multiply) a scale transformation to a 3x4 transformation matrix -// NOTE: -// Faster than creating and multiplying a scale transformation matrix. -// -VECTORMATH_FORCE_INLINE const Transform3 prependScale( const Vector3 &scaleVec, const Transform3 & tfrm ); - -// Multiply two 3x4 transformation matrices per element -// -VECTORMATH_FORCE_INLINE const Transform3 mulPerElem( const Transform3 & tfrm0, const Transform3 & tfrm1 ); - -// Compute the absolute value of a 3x4 transformation matrix per element -// -VECTORMATH_FORCE_INLINE const Transform3 absPerElem( const Transform3 & tfrm ); - -// Inverse of a 3x4 transformation matrix -// NOTE: -// Result is unpredictable when the determinant of the left 3x3 submatrix is equal to or near 0. -// -VECTORMATH_FORCE_INLINE const Transform3 inverse( const Transform3 & tfrm ); - -// Compute the inverse of a 3x4 transformation matrix, expected to have an orthogonal upper-left 3x3 submatrix -// NOTE: -// This can be used to achieve better performance than a general inverse when the specified 3x4 transformation matrix meets the given restrictions. -// -VECTORMATH_FORCE_INLINE const Transform3 orthoInverse( const Transform3 & tfrm ); - -// Conditionally select between two 3x4 transformation matrices -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// However, the transfer of select1 to a VMX register may use more processing time than a branch. -// Use the boolInVec version for better performance. -// -VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, bool select1 ); - -// Conditionally select between two 3x4 transformation matrices (scalar data contained in vector data type) -// NOTE: -// This function uses a conditional select instruction to avoid a branch. -// -VECTORMATH_FORCE_INLINE const Transform3 select( const Transform3 & tfrm0, const Transform3 & tfrm1, const boolInVec &select1 ); - -#ifdef _VECTORMATH_DEBUG - -// Print a 3x4 transformation matrix -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm ); - -// Print a 3x4 transformation matrix and an associated string identifier -// NOTE: -// Function is only defined when _VECTORMATH_DEBUG is defined. -// -VECTORMATH_FORCE_INLINE void print( const Transform3 & tfrm, const char * name ); - -#endif - -} // namespace Aos -} // namespace Vectormath - -#include "vec_aos.h" -#include "quat_aos.h" -#include "mat_aos.h" - -#endif diff --git a/Code/Physics/Bullet Source/src/vectormath/vmInclude.h b/Code/Physics/Bullet Source/src/vectormath/vmInclude.h deleted file mode 100644 index 656514e4..00000000 --- a/Code/Physics/Bullet Source/src/vectormath/vmInclude.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef __VM_INCLUDE_H -#define __VM_INCLUDE_H - -#include "LinearMath/btScalar.h" - -#if defined (USE_SYSTEM_VECTORMATH) || defined (__CELLOS_LV2__) - #include -#else //(USE_SYSTEM_VECTORMATH) - #if defined (BT_USE_SSE) - #include "sse/vectormath_aos.h" - #else //all other platforms - #if defined (BT_USE_NEON) - #include "neon/vectormath_aos.h" - #else - #include "scalar/vectormath_aos.h" - #endif - #endif //(BT_USE_SSE) && defined (_WIN32) -#endif //(USE_SYSTEM_VECTORMATH) - - - -typedef Vectormath::Aos::Vector3 vmVector3; -typedef Vectormath::Aos::Quat vmQuat; -typedef Vectormath::Aos::Matrix3 vmMatrix3; -typedef Vectormath::Aos::Transform3 vmTransform3; -typedef Vectormath::Aos::Point3 vmPoint3; - -#endif //__VM_INCLUDE_H - - diff --git a/Code/Physics/Bullet Source/test1.oec b/Code/Physics/Bullet Source/test1.oec deleted file mode 100644 index 7fac1d15..00000000 --- a/Code/Physics/Bullet Source/test1.oec +++ /dev/null @@ -1,227 +0,0 @@ -# OctaveEngine Casual (Jul 14 2008) -version 2 -p 22000 1 ff 7fff66ff 13 79 0 0 13 79 0 0 0 -p 22000 1 ff 7fff66ff 12.25 77.5 0 0 12.25 77.5 0 0 0 -p 22000 1 ff 7fff66ff 12.25 78.25 0 0 12.25 78.25 0 0 0 -p 22000 1 ff 7fff66ff 13 77.5 0 0 13 77.5 0 0 0 -p 22000 1 ff 7fff66ff 13 78.25 0 0 13 78.25 0 0 0 -p 22000 1 ff 7fff66ff 13.75 77.5 0 0 13.75 77.5 0 0 0 -p 22000 1 ff 7fff66ff 13.75 78.25 0 0 13.75 78.25 0 0 0 -p 22000 2 ff 7fff66ff 14.75 73.625 0 0 14.75 73.625 0 0 0 -p 22000 2 ff 7fff66ff 15.5 73.625 0 0 15.5 73.625 0 0 0 -p 22000 2 ff 7fff66ff 16.25 73.625 0 0 16.25 73.625 0 0 0 -p 22000 2 ff 7fff66ff 17 73.625 0 0 17 73.625 0 0 0 -p 22000 2 ff 7fff66ff 17.75 73.625 0 0 17.75 73.625 0 0 0 -p 22000 2 ff 7fff66ff 18.5 73.625 0 0 18.5 73.625 0 0 0 -p 22000 3 ff 7fff66ff 26 79 0 0 26 79 0 0 0 -p 22000 3 ff 7fff66ff 26.2372 78.2885 0 0 26.2372 78.2885 0 0 0 -p 22000 3 ff 7fff66ff 26.9705 78.1313 0 0 26.9705 78.1313 0 0 0 -p 22000 3 ff 7fff66ff 27.2344 78.8334 0 0 27.2344 78.8334 0 0 0 -p 22000 3 ff 7fff66ff 27.0215 79.5525 0 0 27.0215 79.5525 0 0 0 -p 22000 3 ff 7fff66ff 26.5164 80.107 0 0 26.5164 80.107 0 0 0 -p 22000 4 ff 7fff66ff 42 73.875 0 0 42 73.875 0 0 0 -p 22000 4 ff 7fff66ff 42.5857 73.4065 0 0 42.5857 73.4065 0 0 0 -p 22000 4 ff 7fff66ff 41.8884 73.1303 0 0 41.8884 73.1303 0 0 0 -p 22000 4 ff 7fff66ff 41.3003 72.6648 0 0 41.3003 72.6648 0 0 0 -p 22000 4 ff 7fff66ff 40.6805 73.0872 0 0 40.6805 73.0872 0 0 0 -p 22000 5 ff 7fff66ff 57.125 74 0 0 57.125 74 0 0 0 -p 22000 5 ff 7fff66ff 57.7958 73.6646 0 0 57.7958 73.6646 0 0 0 -p 22000 5 ff 7fff66ff 58.1111 74.3451 0 0 58.1111 74.3451 0 0 0 -p 22000 5 ff 7fff66ff 57.5445 74.8364 0 0 57.5445 74.8364 0 0 0 -p 822000 12 ff 99cc7fff 41.875 70 0 0 41.875 70 0 0 0 -p 822000 12 ff 99cc7fff 41.125 70 0 0 41.125 70 0 0 0 -p 822000 12 ff 99cc7fff 40.3852 70.1233 0 0 40.3852 70.1233 0 0 0 -p 822000 12 ff 99cc7fff 39.6352 70.125 0 0 39.6352 70.125 0 0 0 -p 822000 12 ff 99cc7fff 38.8926 70.2299 0 0 38.8926 70.2299 0 0 0 -p 822000 12 ff 99cc7fff 38.1428 70.2495 0 0 38.1428 70.2495 0 0 0 -p 822000 12 ff 99cc7fff 37.3928 70.25 0 0 37.3928 70.25 0 0 0 -p 22000 15 ff 7fff66ff 62.25 57.625 0 0 62.25 57.625 0 0 0 -p 22000 15 ff 7fff66ff 62.9615 57.3878 0 0 62.9615 57.3878 0 0 0 -p 22000 15 ff 7fff66ff 62.8866 58.1341 0 0 62.8866 58.1341 0 0 0 -p 22000 15 ff 7fff66ff 62.2927 58.5921 0 0 62.2927 58.5921 0 0 0 -p 22000 14 ff 7fff66ff 46.875 59 0 0 46.875 59 0 0 0 -p 22000 14 ff 7fff66ff 47.3435 58.4143 0 0 47.3435 58.4143 0 0 0 -p 22000 14 ff 7fff66ff 48.0775 58.26 0 0 48.0775 58.26 0 0 0 -p 22000 14 ff 7fff66ff 48.4494 58.9113 0 0 48.4494 58.9113 0 0 0 -p 22000 14 ff 7fff66ff 48.2759 59.641 0 0 48.2759 59.641 0 0 0 -p 22000 17 ff 7fff66ff 32.625 58.625 0 0 32.625 58.625 0 0 0 -p 22000 17 ff 7fff66ff 33.2958 58.2896 0 0 33.2958 58.2896 0 0 0 -p 22000 17 ff 7fff66ff 34.045 58.2538 0 0 34.045 58.2538 0 0 0 -p 22000 17 ff 7fff66ff 34.3483 58.9397 0 0 34.3483 58.9397 0 0 0 -p 22000 16 ff 7fff66ff 23 50 0 0 23 50 0 0 0 -p 22000 16 ff 7fff66ff 23.6512 49.6279 0 0 23.6512 49.6279 0 0 0 -p 22000 16 ff 7fff66ff 24.3928 49.5162 0 0 24.3928 49.5162 0 0 0 -p 22000 16 ff 7fff66ff 24.1695 50.2321 0 0 24.1695 50.2321 0 0 0 -p 22000 18 ff 7fff66ff 18.375 59.25 0 0 18.375 59.25 0 0 0 -p 22000 18 ff 7fff66ff 18.9053 58.7197 0 0 18.9053 58.7197 0 0 0 -p 22000 18 ff 7fff66ff 19.4651 59.2189 0 0 19.4651 59.2189 0 0 0 -p 22000 18 ff 7fff66ff 19.3792 59.9639 0 0 19.3792 59.9639 0 0 0 -p 22000 7 ff 7fff66ff 44.125 51.75 0 0 44.125 51.75 0 0 0 -p 22000 7 ff 7fff66ff 44.0017 51.0102 0 0 44.0017 51.0102 0 0 0 -p 22000 7 ff 7fff66ff 44.743 51.1239 0 0 44.743 51.1239 0 0 0 -p 22000 7 ff 7fff66ff 45.0428 51.8114 0 0 45.0428 51.8114 0 0 0 -p 22000 8 ff 7fff66ff 59.125 49.375 0 0 59.125 49.375 0 0 0 -p 22000 8 ff 7fff66ff 59.125 48.625 0 0 59.125 48.625 0 0 0 -p 22000 8 ff 7fff66ff 59.7958 48.2896 0 0 59.7958 48.2896 0 0 0 -p 22000 8 ff 7fff66ff 59.9739 49.0181 0 0 59.9739 49.0181 0 0 0 -p 22000 9 ff 7fff66ff 42.5 41.625 0 0 42.5 41.625 0 0 0 -p 22000 9 ff 7fff66ff 43.0303 41.0947 0 0 43.0303 41.0947 0 0 0 -p 22000 9 ff 7fff66ff 43.7798 41.1216 0 0 43.7798 41.1216 0 0 0 -p 22000 9 ff 7fff66ff 44.3525 41.6059 0 0 44.3525 41.6059 0 0 0 -p 22000 9 ff 7fff66ff 43.9569 42.2431 0 0 43.9569 42.2431 0 0 0 -p 22000 a ff 7fff66ff 70.375 63.125 0 0 70.375 63.125 0 0 0 -p 22000 a ff 7fff66ff 70.375 62.375 0 0 70.375 62.375 0 0 0 -p 22000 a ff 7fff66ff 71.1148 62.4983 0 0 71.1148 62.4983 0 0 0 -p 22000 a ff 7fff66ff 71.2476 63.2365 0 0 71.2476 63.2365 0 0 0 -p 22000 b ff 7fff66ff 15.5 40.375 0 0 15.5 40.375 0 0 0 -p 22000 b ff 7fff66ff 16.124 39.959 0 0 16.124 39.959 0 0 0 -p 22000 b ff 7fff66ff 16.8729 39.9999 0 0 16.8729 39.9999 0 0 0 -p 22000 b ff 7fff66ff 17.2098 40.67 0 0 17.2098 40.67 0 0 0 -p 22000 c ff 7fff66ff 29.375 37.875 0 0 29.375 37.875 0 0 0 -p 22000 c ff 7fff66ff 29.791 37.251 0 0 29.791 37.251 0 0 0 -p 22000 c ff 7fff66ff 30.5326 37.139 0 0 30.5326 37.139 0 0 0 -p 22000 c ff 7fff66ff 30.6126 37.8847 0 0 30.6126 37.8847 0 0 0 -p 22000 d ff 7fff66ff 69.75 49 0 0 69.75 49 0 0 0 -p 22000 d ff 7fff66ff 69.8733 48.2602 0 0 69.8733 48.2602 0 0 0 -p 22000 d ff 7fff66ff 69.875 47.5102 0 0 69.875 47.5102 0 0 0 -p 22000 d ff 7fff66ff 69.875 46.7602 0 0 69.875 46.7602 0 0 0 -p 22000 d ff 7fff66ff 69.875 46.0102 0 0 69.875 46.0102 0 0 0 -p 22000 e ff 7fff66ff 61.625 38 0 0 61.625 38 0 0 0 -p 22000 e ff 7fff66ff 61.625 37.25 0 0 61.625 37.25 0 0 0 -p 22000 e ff 7fff66ff 61.625 36.5 0 0 61.625 36.5 0 0 0 -p 22000 e ff 7fff66ff 61.625 35.75 0 0 61.625 35.75 0 0 0 -p 22000 e ff 7fff66ff 61.625 35 0 0 61.625 35 0 0 0 -p 22000 11 ff 7fff66ff 7.25 54 0 0 7.25 54 0 0 0 -p 22000 11 ff 7fff66ff 7.25 53.25 0 0 7.25 53.25 0 0 0 -p 22000 11 ff 7fff66ff 7.25 52.5 0 0 7.25 52.5 0 0 0 -p 22000 11 ff 7fff66ff 7.25 51.75 0 0 7.25 51.75 0 0 0 -p 402000 0 ff b26666ff 55.75 70.75 0 0 55.75 70.75 0 0 0 -p 402000 0 ff b26666ff 55.75 70 0 0 55.75 70 0 0 0 -p 402000 0 ff b26666ff 56.5 70 0 0 56.5 70 0 0 0 -p 402000 0 ff b26666ff 56.5 70.75 0 0 56.5 70.75 0 0 0 -p 402000 0 ff b26666ff 57.25 70.75 0 0 57.25 70.75 0 0 0 -p 402000 0 ff b26666ff 57.25 70 0 0 57.25 70 0 0 0 -p 402000 0 ff b26666ff 58 70 0 0 58 70 0 0 0 -p 402000 0 ff b26666ff 58 70.75 0 0 58 70.75 0 0 0 -p 402000 0 ff b26666ff 58.75 70 0 0 58.75 70 0 0 0 -p 402000 0 ff b26666ff 58.75 70.75 0 0 58.75 70.75 0 0 0 -p 402000 0 ff b26666ff 59.5 70.75 0 0 59.5 70.75 0 0 0 -p 402000 0 ff b26666ff 59.5 70 0 0 59.5 70 0 0 0 -p 402000 0 ff b26666ff 60.25 70 0 0 60.25 70 0 0 0 -p 402000 0 ff b26666ff 60.25 70.75 0 0 60.25 70.75 0 0 0 -p 402000 0 ff b26666ff 61 70 0 0 61 70 0 0 0 -p 402000 0 ff b26666ff 61 70.75 0 0 61 70.75 0 0 0 -p 402000 0 ff b26666ff 43 35.5 0 0 43 35.5 0 0 0 -p 402000 0 ff b26666ff 43 34 0 0 43 34 0 0 0 -p 402000 0 ff b26666ff 43 34.75 0 0 43 34.75 0 0 0 -p 402000 0 ff b26666ff 43.75 35.5 0 0 43.75 35.5 0 0 0 -p 402000 0 ff b26666ff 43.75 34 0 0 43.75 34 0 0 0 -p 402000 0 ff b26666ff 43.75 34.75 0 0 43.75 34.75 0 0 0 -p 402000 0 ff b26666ff 44.5 34.75 0 0 44.5 34.75 0 0 0 -p 402000 0 ff b26666ff 44.5 34 0 0 44.5 34 0 0 0 -p 402000 0 ff b26666ff 45.25 34 0 0 45.25 34 0 0 0 -p 402000 0 ff b26666ff 45.25 34.75 0 0 45.25 34.75 0 0 0 -p 402000 0 ff b26666ff 46 34 0 0 46 34 0 0 0 -p 402000 0 ff b26666ff 46 34.75 0 0 46 34.75 0 0 0 -@ time 7.52012 -@ timeStep 1504 -@ scale 8 -@ timeStepsPerFrame 8 -@ framesPerSecond 25 -@ pauseFlag 1 -@ randSeed 0 -@ gravityFlag 1 -@ gravityAcceleration 0.001 -@ gravityAmplification 1 -@ gravityAngle 0 -@ boundsFlag 1 -@ boundsThickness 0.25 -@ boundsLeft 0 -@ boundsRight 94.75 -@ boundsBottom 0 -@ boundsTop 89.25 -@ boundsRadius 1 -@ standardDistance 0.75 -@ standardDensity 1.0025 -@ maxSpeed 0.5 -@ pressureCoefficient 0.05 -@ repulsionCoefficient 0.05 -@ dampingFlag 1 -@ dampingCoefficient 0.05 -@ staticPressureFlag 0 -@ staticPressureCoefficient 0.5 -@ staticPressureIteration 1 -@ staticMaxPressure 0.5 -@ springCoefficient 0.05 -@ springIteration 5 -@ elasticCoefficient 0.5 -@ elasticIteration 5 -@ mochiElasticityCoefficient 0.1 -@ mochiSpringCoefficient 0.1 -@ mochiIteration 3 -@ viscosityCoefficient 0.4 -@ viscosityIteration 5 -@ surfaceTensionCoefficient 0.1 -@ surfacePressureCoefficient 0.05 -@ surfaceTensionIteration 5 -@ powderSpringCoefficient 0.5 -@ powderDampingCoefficient 0.3 -@ powderFrictionCoefficient 0.05 -@ powderLightProbability 0.5 -@ powderExtinguishProbability 0.05 -@ powderExplosionCoefficient 1 -@ brittlenessCoefficient 0.5 -@ jetCoefficient 0.5 -@ fuelLightProbability 0.01 -@ fuelExtinguishProbability 0.0005 -@ upCoefficient 10 -@ downCoefficient 10 -@ yukiSpringCoefficient 0.02 -@ yukiMeltingProbability 0.0001 -@ resistanceFlag 0 -@ resistanceCoefficient 0.02 -@ fireFlag 1 -@ fireProbability 0.005 -@ fireLife 1000 -@ fireBuoyancyCoefficient 10 -@ splashFlag 0 -@ splashProbability 0.05 -@ splashExpansion 1e-005 -@ splashMinLife 50 -@ bubbleFlag 0 -@ bubbleProbability 0.05 -@ bubbleLife 10000 -@ bubbleBuoyancyCoefficient 20 -@ pouringFlag 0 -@ pouringRainFlag 0 -@ pouringLocation 10 -@ pouringThickness 2 -@ pouringVelocity 0.1 -@ pouringTimer 0 -@ pouringMaterial 113 -@ pouringLayer -1 -@ clearFlag 1 -@ clearColorRed 0.2 -@ clearColorBlue 0.2 -@ clearColorGreen 0.2 -@ clearColorAlpha 1 -@ mouseRadius 1 -@ mouseDelay 10 -@ mouseForce 1 -@ lineWidth 1 -@ usersCharge 0 -@ usersMaxCharge 15 -@ usersSpeedX 0.05 -@ usersSpeedY 0.15 -@ usersForceX 0.05 -@ usersForceY 0.5 -@ usersX 0 -@ usersY 0 -@ viewWidth 0 -@ viewHeight 0 -@ scrollFlag 0 -@ scrollX 0 -@ scrollY 0 -@ scrollAngle 0 -@ colorFlag 1 -@ renderMode 2 diff --git a/Code/Physics/BulletConfig.cmake b/Code/Physics/BulletConfig.cmake deleted file mode 100644 index 2f728869..00000000 --- a/Code/Physics/BulletConfig.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# -*- cmake -*- -# -# BulletConfig.cmake(.in) -# - -# Use the following variables to compile and link against Bullet: -# BULLET_FOUND - True if Bullet was found on your system -# BULLET_USE_FILE - The file making Bullet usable -# BULLET_DEFINITIONS - Definitions needed to build with Bullet -# BULLET_INCLUDE_DIR - Directory where Bullet-C-Api.h can be found -# BULLET_INCLUDE_DIRS - List of directories of Bullet and it's dependencies -# BULLET_LIBRARIES - List of libraries to link against Bullet library -# BULLET_LIBRARY_DIRS - List of directories containing Bullet' libraries -# BULLET_ROOT_DIR - The base directory of Bullet -# BULLET_VERSION_STRING - A human-readable string containing the version - -set ( BULLET_FOUND 1 ) -set ( BULLET_USE_FILE "C:/Program Files (x86)/BULLET_PHYSICS/lib/cmake/bullet/UseBullet.cmake" ) -set ( BULLET_DEFINITIONS "" ) -set ( BULLET_INCLUDE_DIR "" ) -set ( BULLET_INCLUDE_DIRS "" ) -set ( BULLET_LIBRARIES "LinearMath;BulletCollisions;BulletDynamics;BulletSoftBody" ) -set ( BULLET_LIBRARY_DIRS "" ) -set ( BULLET_ROOT_DIR "C:/Program Files (x86)/BULLET_PHYSICS" ) -set ( BULLET_VERSION_STRING "2.82" ) diff --git a/Code/Physics/CMakeCache.txt b/Code/Physics/CMakeCache.txt deleted file mode 100644 index 7cd2cea1..00000000 --- a/Code/Physics/CMakeCache.txt +++ /dev/null @@ -1,471 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: c:/DV1477/Git Repository/Danbias/Code/Physics -# It was generated by CMake: C:/Program Files (x86)/CMake 2.8/bin/cmake.exe -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Path to a file. -AMD_OPENCL_BASE_DIR:PATH=AMD_OPENCL_BASE_DIR-NOTFOUND - -//Build OpenCL demos for AMD (GPU or CPU) -BUILD_AMD_OPENCL_DEMOS:BOOL=OFF - -//Build original Bullet CPU demos -BUILD_CPU_DEMOS:BOOL=ON - -//Set when you want to build the demos -BUILD_DEMOS:BOOL=ON - -//Set when you want to build the extras -BUILD_EXTRAS:BOOL=OFF - -//Build OpenCL demos for Intel (CPU) -BUILD_INTEL_OPENCL_DEMOS:BOOL=OFF - -//Build OpenCL demos for MiniCL (Generic CPU) -BUILD_MINICL_OPENCL_DEMOS:BOOL=ON - -//Use BulletMultiThreading -BUILD_MULTITHREADING:BOOL=ON - -//Build OpenCL demos for NVidia (GPU) -BUILD_NVIDIA_OPENCL_DEMOS:BOOL=OFF - -//Build Unit Tests -BUILD_UNIT_TESTS:BOOL=OFF - -//Value Computed by CMake -BULLET_PHYSICS_BINARY_DIR:STATIC=C:/DV1477/Git Repository/Danbias/Code/Physics - -//Value Computed by CMake -BULLET_PHYSICS_SOURCE_DIR:STATIC=C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source - -//Dependencies for target -BulletCollision_LIB_DEPENDS:STATIC= - -//Dependencies for target -BulletDynamics_LIB_DEPENDS:STATIC= - -//Dependencies for target -BulletMultiThreaded_LIB_DEPENDS:STATIC= - -//Dependencies for target -BulletSoftBodySolvers_DX11_LIB_DEPENDS:STATIC= - -//Dependencies for target -BulletSoftBodySolvers_OpenCL_Mini_LIB_DEPENDS:STATIC= - -//Dependencies for target -BulletSoftBody_LIB_DEPENDS:STATIC= - -//For backwards compatibility, what version of CMake commands and -// syntax should this version of CMake try to support. -CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4 - -//Semicolon separated list of supported configuration types, only -// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything -// else will be ignored. -CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 /GR /EHsc - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 - -//Flags used by the compiler during release minsize builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG - -//Libraries linked by defalut with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 - -//Flags used by the compiler during release minsize builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /D NDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /D NDEBUG - -//Libraries linked by defalut with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib - -//Adds a postfix for debug-built libraries. -CMAKE_DEBUG_POSTFIX:STRING=_Debug - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING=' /machine:X86 ' - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/BULLET_PHYSICS - -//Path to a program. -CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe - -//make program -CMAKE_MAKE_PROGRAM:FILEPATH=C:/PROGRA~2/MICROS~3.0/Common7/IDE/devenv.com - -//Adds a postfix for MinsizeRelease-built libraries. -CMAKE_MINSIZEREL_POSTFIX:STRING=_MinsizeRel - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING=' /machine:X86 ' - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=BULLET_PHYSICS - -//RC compiler -CMAKE_RC_COMPILER:FILEPATH=rc - -//Flags for Fortran compiler. -CMAKE_RC_FLAGS:STRING=' ' - -//Adds a postfix for ReleaseWithDebug-built libraries. -CMAKE_RELWITHDEBINFO_POSTFIX:STRING=_RelWithDebugInfo - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING=' /machine:X86 ' - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=OFF - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=OFF - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If true, cmake will use relative paths in makefiles and projects. -CMAKE_USE_RELATIVE_PATHS:BOOL=OFF - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=OFF - -//Path to a file. -DIRECTX_SDK_BASE_DIR:PATH=C:/Program Files (x86)/Microsoft DirectX SDK (June 2010) - -//Microsoft directX SDK include path -DX11_INCLUDE_PATH:STRING=C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/Include - -//Single output directory for building all executables. -EXECUTABLE_OUTPUT_PATH:PATH= - -//Path to a file. -GLUT_INCLUDE_DIR:PATH=GLUT_INCLUDE_DIR-NOTFOUND - -//Path to a library. -GLUT_glut_LIBRARY:FILEPATH=GLUT_glut_LIBRARY-NOTFOUND - -//Set when you want extra libraries installed -INSTALL_EXTRA_LIBS:BOOL=OFF - -//Set when you want to install libraries -INSTALL_LIBS:BOOL=OFF - -//Path to a file. -INTEL_OPENCL_BASE_DIR:PATH=INTEL_OPENCL_BASE_DIR-NOTFOUND - -//Add MSVC postfix for executable names (_Debug) -INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES:BOOL=OFF - -//Create MSVC projectfiles that can be distributed -INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES:BOOL=OFF - -//Create MSVC projectfiles with relative paths -INTERNAL_CREATE_MSVC_RELATIVE_PATH_PROJECTFILES:BOOL=OFF - -//Internal update serialization structures -INTERNAL_UPDATE_SERIALIZATION_STRUCTURES:BOOL=OFF - -//Single output directory for building all libraries. -LIBRARY_OUTPUT_PATH:PATH=C:/DV1477/Git Repository/Danbias/Code/Physics/lib - -//Dependencies for target -LinearMath_LIB_DEPENDS:STATIC= - -//Dependencies for target -MiniCL_LIB_DEPENDS:STATIC= - -//Path to a file. -NVIDIA_OPENCL_BASE_DIR:PATH=NVIDIA_OPENCL_BASE_DIR-NOTFOUND - -//OpenGL library for win32 -OPENGL_gl_LIBRARY:STRING=opengl32 - -//GLU library for win32 -OPENGL_glu_LIBRARY:STRING=glu32 - -//Use custom vectormath library -USE_CUSTOM_VECTOR_MATH:BOOL=OFF - -//Use double precision -USE_DOUBLE_PRECISION:BOOL=OFF - -//Use DirectX 11 -USE_DX11:BOOL=ON - -//Use Glut -USE_GLUT:BOOL=ON - -//Use Graphical Benchmark -USE_GRAPHICAL_BENCHMARK:BOOL=ON - -//Use MSVC /fp:fast option -USE_MSVC_FAST_FLOATINGPOINT:BOOL=ON - -//Use MSVC Incremental Linking -USE_MSVC_INCREMENTAL_LINKING:BOOL=OFF - -//Use MSVC Runtime Library DLL (/MD or /MDd) -USE_MSVC_RUNTIME_LIBRARY_DLL:BOOL=OFF - -//Use MSVC /arch:sse option -USE_MSVC_SSE:BOOL=ON - -//Use Multithreaded Benchmark -USE_MULTITHREADED_BENCHMARK:BOOL=OFF - - -######################## -# INTERNAL cache entries -######################## - -//Stored GUID -ALL_BUILD_GUID_CMAKE:INTERNAL=14E546AD-2393-41B9-BAA2-134241286A4E -//Stored GUID -BulletCollision_GUID_CMAKE:INTERNAL=C933A737-D7BA-4136-95AF-D12310BD6BA8 -//Stored GUID -BulletDynamics_GUID_CMAKE:INTERNAL=74EDC06C-85E5-47BC-B42D-F55CE6E9928B -//Stored GUID -BulletMultiThreaded_GUID_CMAKE:INTERNAL=83B388D3-BE71-476A-AA6A-CC7082E3866D -//Stored GUID -BulletSoftBodySolvers_DX11_GUID_CMAKE:INTERNAL=2CF89262-94E6-4A9F-A29A-1BE6D73DDA85 -//Stored GUID -BulletSoftBodySolvers_OpenCL_Mini_GUID_CMAKE:INTERNAL=80FC7669-D649-4212-8B6F-C0167CE9CB59 -//Stored GUID -BulletSoftBody_GUID_CMAKE:INTERNAL=14DC504E-697F-4178-8E05-87173957FE59 -//ADVANCED property for variable: CMAKE_BUILD_TOOL -CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 -//What is the target build tool cmake is generating for. -CMAKE_BUILD_TOOL:INTERNAL=C:/PROGRA~2/MICROS~3.0/Common7/IDE/devenv.com -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=c:/DV1477/Git Repository/Danbias/Code/Physics -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/cmake.exe -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/cpack.exe -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/ctest.exe -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=C:/Program Files (x86)/CMake 2.8/bin/cmake-gui.exe -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Visual Studio 11 -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Start directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=12 -//ADVANCED property for variable: CMAKE_RC_COMPILER -CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1 -CMAKE_RC_COMPILER_WORKS:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS -CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=C:/Program Files (x86)/CMake 2.8/share/cmake-2.8 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Suppress Warnings that are meant for the author of the CMakeLists.txt -// files. -CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=FALSE -//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS -CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Details about finding OpenGL -FIND_PACKAGE_MESSAGE_DETAILS_OpenGL:INTERNAL=[opengl32][v()] -//ADVANCED property for variable: GLUT_INCLUDE_DIR -GLUT_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: GLUT_glut_LIBRARY -GLUT_glut_LIBRARY-ADVANCED:INTERNAL=1 -//Stored GUID -INSTALL_GUID_CMAKE:INTERNAL=71641E56-5E9E-462B-844F-A9F8A6D82120 -//Stored GUID -LinearMath_GUID_CMAKE:INTERNAL=D4985405-3286-4026-BD61-E9E53DC5027E -//Stored GUID -MiniCL_GUID_CMAKE:INTERNAL=FA9E3157-5228-4CA4-8327-BD0AF11BD390 -//ADVANCED property for variable: OPENGL_gl_LIBRARY -OPENGL_gl_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENGL_glu_LIBRARY -OPENGL_glu_LIBRARY-ADVANCED:INTERNAL=1 -//Stored GUID -SG_Filter_CMake Rules_GUID_CMAKE:INTERNAL=25AA48BF-9AB1-4661-81E4-21DC63B45029 -//Stored GUID -SG_Filter_Header Files_GUID_CMAKE:INTERNAL=DC4D0118-25E6-4CAA-B131-BCA655977BFA -//Stored GUID -SG_Filter_Object Files_GUID_CMAKE:INTERNAL=F83DE1D7-C15C-47D0-A697-3C273FD0E918 -//Stored GUID -SG_Filter_Resources_GUID_CMAKE:INTERNAL=7CEBDF2C-7E7D-42BC-911B-92C65E0725AB -//Stored GUID -SG_Filter_Source Files_GUID_CMAKE:INTERNAL=9B00025E-DDC2-40FD-8DE1-C35F1698B109 -//Stored GUID -ZERO_CHECK_GUID_CMAKE:INTERNAL=53399ED8-C4B0-4F84-9CA8-623049125822 - diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake deleted file mode 100644 index 69bac982..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake +++ /dev/null @@ -1,56 +0,0 @@ -set(CMAKE_C_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/cl.exe") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "MSVC") -set(CMAKE_C_COMPILER_VERSION "17.0.61030.0") -set(CMAKE_C_PLATFORM_ID "Windows") -set(MSVC_C_ARCHITECTURE_ID X86) -set(CMAKE_AR "") -set(CMAKE_RANLIB "") -set(CMAKE_LINKER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe") -set(CMAKE_COMPILER_IS_GNUCC ) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) -set(CMAKE_COMPILER_IS_MINGW ) -set(CMAKE_COMPILER_IS_CYGWIN ) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "4") -set(CMAKE_C_COMPILER_ABI "") -set(CMAKE_C_LIBRARY_ARCHITECTURE "") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - - - - -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") - - - diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake deleted file mode 100644 index 5cddd9ef..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake +++ /dev/null @@ -1,57 +0,0 @@ -set(CMAKE_CXX_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/cl.exe") -set(CMAKE_CXX_COMPILER_ARG1 "") -set(CMAKE_CXX_COMPILER_ID "MSVC") -set(CMAKE_CXX_COMPILER_VERSION "17.0.61030.0") -set(CMAKE_CXX_PLATFORM_ID "Windows") -set(MSVC_CXX_ARCHITECTURE_ID X86) -set(CMAKE_AR "") -set(CMAKE_RANLIB "") -set(CMAKE_LINKER "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin/link.exe") -set(CMAKE_COMPILER_IS_GNUCXX ) -set(CMAKE_CXX_COMPILER_LOADED 1) -set(CMAKE_CXX_COMPILER_WORKS TRUE) -set(CMAKE_CXX_ABI_COMPILED TRUE) -set(CMAKE_COMPILER_IS_MINGW ) -set(CMAKE_COMPILER_IS_CYGWIN ) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() - -set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") - -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() -set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) -set(CMAKE_CXX_LINKER_PREFERENCE 30) -set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) - -# Save compiler ABI information. -set(CMAKE_CXX_SIZEOF_DATA_PTR "4") -set(CMAKE_CXX_COMPILER_ABI "") -set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") - -if(CMAKE_CXX_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_CXX_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") -endif() - -if(CMAKE_CXX_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "") -endif() - - - - -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") -set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") - - - diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin b/Code/Physics/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin deleted file mode 100644 index 9880b1d79591c82985cd662cb2487c63b47a24d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30208 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 diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake deleted file mode 100644 index f71ace0e..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake +++ /dev/null @@ -1,6 +0,0 @@ -set(CMAKE_RC_COMPILER "rc") -set(CMAKE_RC_COMPILER_ARG1 "") -set(CMAKE_RC_COMPILER_LOADED 1) -set(CMAKE_RC_SOURCE_FILE_EXTENSIONS rc) -set(CMAKE_RC_OUTPUT_EXTENSION .res) -set(CMAKE_RC_COMPILER_ENV_VAR "RC") diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake b/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake deleted file mode 100644 index c10783ee..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Windows-6.1") -set(CMAKE_HOST_SYSTEM_NAME "Windows") -set(CMAKE_HOST_SYSTEM_VERSION "6.1") -set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64") - - - -set(CMAKE_SYSTEM "Windows-6.1") -set(CMAKE_SYSTEM_NAME "Windows") -set(CMAKE_SYSTEM_VERSION "6.1") -set(CMAKE_SYSTEM_PROCESSOR "AMD64") - -set(CMAKE_CROSSCOMPILING "FALSE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c deleted file mode 100644 index cba81d4a..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c +++ /dev/null @@ -1,389 +0,0 @@ -#ifdef __cplusplus -# error "A C++ compiler has been selected for C." -#endif - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__18CXX) -# define ID_VOID_MAIN -#endif - -#if defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" - /* __INTEL_COMPILER = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_C = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) -# if defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" -# else -# if __IBMC__ >= 800 -# define COMPILER_ID "XL" -# else -# define COMPILER_ID "VisualAge" -# endif - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -/* Analog VisualDSP++ >= 4.5.6 */ -#elif defined(__VISUALDSPVERSION__) -# define COMPILER_ID "ADSP" - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) - -/* Analog VisualDSP++ < 4.5.6 */ -#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" - -/* IAR Systems compiler for embedded systems. - http://www.iar.com */ -#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" - -/* sdcc, the small devices C compiler for embedded systems, - http://sdcc.sourceforge.net */ -#elif defined(SDCC) -# define COMPILER_ID "SDCC" - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) - -#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) -# define COMPILER_ID "MIPSpro" -# if defined(_SGI_COMPILER_VERSION) - /* _SGI_COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) -# else - /* _COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) -# endif - -/* This compiler is either not known or is too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__sgi) -# define COMPILER_ID "MIPSpro" - -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" - -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) -# define PLATFORM_ID "IRIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#else /* unknown platform */ -# define PLATFORM_ID "" - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM) -# define ARCHITECTURE_ID "ARM" - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID "" -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number components. */ -#ifdef COMPILER_VERSION_MAJOR -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif - (void)argv; - return require; -} -#endif diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj deleted file mode 100644 index cec63969..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.vcxproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Debug - Win32 - - - - {CAE07175-D007-4FC3-BFE8-47B392814159} - CompilerIdC - Win32Proj - - - - Application - v110 - MultiByte - - - - <_ProjectFileVersion>10.0.30319.1 - .\ - $(Configuration)\ - false - - - - Disabled - %(PreprocessorDefinitions) - false - EnableFastChecks - MultiThreadedDebugDLL - - - TurnOffAllWarnings - - - - - false - Console - - - for %%i in (cl.exe) do %40echo CMAKE_C_COMPILER=%%~$PATH:i - - - - - - - diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CMakeCCompilerId.obj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CMakeCCompilerId.obj deleted file mode 100644 index 85a99d188a255624c75ba9a1daeb3d8125b46465..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1497 zcmZ`(OKTHR6h70jX%%f#e9(o9F;q~HF^Q$AQA(OeOC;0QJX&q0#%VHXN1IHTOlvC? zy3-OA`~!k61@|sQL>F$vzu?N96x_K8)N}5=(CKtINdfj_QR4A<~T*w11c?E@%b zBg3U32Eos&(@VUC_^#j(j|_P+)it+Wo-+Rc{RiY-po!2q3XEhv9z|#K!Hyo zCoXuj)tDdWBVN9jmqE_LF`l9**ORH4=|U!-NynoBEw`A+=97V5bUu@uo7PgffI|ED zgY7*w8>A8JAQ9D*i=pvIM4z=>C2Kb9rsdksj-E8?tCrE!6L!Va7uI*0Rv8n`cx=vC z8)j1vtCMOdtcH{VsH;aWB8sa0Q7ycuYpWa+t?`Dj@zSESRfbnwQ8;Z|*@R$Q{`75hn(5AhnqDX$mr zO-^v^Bo_H#6#Wp3#?kv()U!Zo%XFHST`vZig(4~sfVBiWATEFjpOSQkF zVTZH98**}LaQM@pthM*GcI!Mt3W)T{srG)V-8#b%4UrMK(B3b!Tf~3PQC5SbUn^hF zA~J~02ba-Pl@B85hgqbdKg}X^%+8_ri5P&^^+AljoN8672S4EOkY0JLY8oyc=9L6{ z9O+gXy+&Cgt@T>B%18{dL^|uWZiUgKl_k;`MZxXeFC8wuNHQAfgR$IfD10--^uns3 zTY!Ei`JR(ouhm1J1CxA=X=!&~%9%p|PJ~MIXY;^hEoC%l|hz#Aj?k7|t zWz!mO_oiNAhgPZ?R-K2?4~kgb+a>9q@8^!-aHRWBK=&j|G%I~^ZoCHIzQ`E|zeeZ3 zFn}Zft7?cU#(`&;m8^QzE_u=ssd(Qa^YkN9k_?ne*?gjuu3K*0XqqC;t#7(0u==sl Mqa*Pmk9D-?e@N^GGynhq diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate deleted file mode 100644 index c6df3dc3..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.lastbuildstate +++ /dev/null @@ -1,2 +0,0 @@ -#v4.0:v110:false -Debug|Win32|C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\| diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log deleted file mode 100644 index 51517d68..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/Debug/CompilerIdC.log +++ /dev/null @@ -1,17 +0,0 @@ -Build started 2014-02-10 09:29:19. - 1>Project "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\CompilerIdC.vcxproj" on node 2 (Build target(s)). - 1>ClCompile: - C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\CL.exe /c /nologo /W0 /WX- /Od /Oy- /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc110.pdb" /Gd /TC /analyze- /errorReport:prompt CMakeCCompilerId.c - CMakeCCompilerId.c - Link: - C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:".\CompilerIdC.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdC.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdC.lib" /MACHINE:X86 /SAFESEH Debug\CMakeCCompilerId.obj - CompilerIdC.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\.\CompilerIdC.exe - PostBuildEvent: - for %%i in (cl.exe) do @echo CMAKE_C_COMPILER=%%~$PATH:i - :VCEnd - CMAKE_C_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe - 1>Done Building Project "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\CompilerIdC.vcxproj" (Build target(s)). - -Build succeeded. - -Time Elapsed 00:00:00.23 diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp deleted file mode 100644 index e8220b26..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* This source file must have a .cpp extension so that all C++ compilers - recognize the extension without flags. Borland does not know .cxx for - example. */ -#ifndef __cplusplus -# error "A C compiler has been selected for C++." -#endif - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__COMO__) -# define COMPILER_ID "Comeau" - /* __COMO_VERSION__ = VRR */ -# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) -# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) - -#elif defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" - /* __INTEL_COMPILER = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) - -#elif defined(__SUNPRO_CC) -# define COMPILER_ID "SunPro" -# if __SUNPRO_CC >= 0x5100 - /* __SUNPRO_CC = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# endif - -#elif defined(__HP_aCC) -# define COMPILER_ID "HP" - /* __HP_aCC = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) - -#elif defined(__DECCXX) -# define COMPILER_ID "Compaq" - /* __DECCXX_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) - -#elif defined(__IBMCPP__) -# if defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" -# else -# if __IBMCPP__ >= 800 -# define COMPILER_ID "XL" -# else -# define COMPILER_ID "VisualAge" -# endif - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -/* Analog VisualDSP++ >= 4.5.6 */ -#elif defined(__VISUALDSPVERSION__) -# define COMPILER_ID "ADSP" - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) - -/* Analog VisualDSP++ < 4.5.6 */ -#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" - -/* IAR Systems compiler for embedded systems. - http://www.iar.com */ -#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" - -#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) -# define COMPILER_ID "MIPSpro" -# if defined(_SGI_COMPILER_VERSION) - /* _SGI_COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) -# else - /* _COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) -# endif - -/* This compiler is either not known or is too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__sgi) -# define COMPILER_ID "MIPSpro" - -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" - -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) -# define PLATFORM_ID "IRIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#else /* unknown platform */ -# define PLATFORM_ID "" - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM) -# define ARCHITECTURE_ID "ARM" - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID "" -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number components. */ -#ifdef COMPILER_VERSION_MAJOR -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -/*--------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif - (void)argv; - return require; -} diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj deleted file mode 100644 index 9d0069d6..00000000 --- a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.vcxproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Debug - Win32 - - - - {CAE07175-D007-4FC3-BFE8-47B392814159} - CompilerIdCXX - Win32Proj - - - - Application - v110 - MultiByte - - - - <_ProjectFileVersion>10.0.30319.1 - .\ - $(Configuration)\ - false - - - - Disabled - %(PreprocessorDefinitions) - false - EnableFastChecks - MultiThreadedDebugDLL - - - TurnOffAllWarnings - - - - - false - Console - - - for %%i in (cl.exe) do %40echo CMAKE_CXX_COMPILER=%%~$PATH:i - - - - - - - diff --git a/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj b/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj deleted file mode 100644 index e9dc019ebab86370e9c0f0ebc72403358ab001d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1495 zcmZ`(OHUI~6h6a1!6zl^Lc?Oxpkg#*TONgKwDd)qv{3s%V%yZAozhX-X=VlxSGsUP z8W-%{_!ImA8WI<7OpO1)jXOi)&P5HLbMH)5<869FcH zi(EILqdBV$K(*eG!7En z8Y197l#M~+F5*d>Lp&1XMPy5TVeydZH0qDYJ41<3$ViZVDjQa9DwTP{KvcsxZsO!^ zn@2~DcrhRG3WK~k@8un%KYq4A*?i)l`)A5z1Od{`-Xusb$ zKHxAxm_P%ua5=sfm<@%>%bF$S)Q)aymTv5o<4Su&Q_ONqudC&3bI;Uj7-W>^YEs)$ z&2ms)kOM(Eh=f)L5hGQPt*@8k^a(f*!;?8#-*^ULxIZEI07ilKZX7}1X0)22n|i~N zrgOKX)sCgLw3k|YQ*tuUSx?J31U&2&FEVcowU>FRmE>x;W*@9X?^1yQth%Ebrlz+` zekOsC%pJde9dcPR~GMbZ!a(f^`7nikq*i?EXG&2P5#-bTfpw=RJJ$&OY_onj8!MWL47BCL;uA!zo zpCHq&XbAYK5M*5_zyplvE&1-8vk1*T$KAjq#1p86iCw%p{v8cUwWVln?!pMRGrb6~ zeK_bKRUV=y#NG1rokW37PA|@dX8~|BGY(&6{{Tjj_`g+e>@17}?=X6(wHtcXsr*P} zCL4`Mp~_IZProject "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\CompilerIdCXX.vcxproj" on node 2 (Build target(s)). - 1>ClCompile: - C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\CL.exe /c /nologo /W0 /WX- /Od /Oy- /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc110.pdb" /Gd /TP /analyze- /errorReport:prompt CMakeCXXCompilerId.cpp - CMakeCXXCompilerId.cpp - Link: - C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:".\CompilerIdCXX.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdCXX.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdCXX.lib" /MACHINE:X86 /SAFESEH Debug\CMakeCXXCompilerId.obj - CompilerIdCXX.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\.\CompilerIdCXX.exe - PostBuildEvent: - for %%i in (cl.exe) do @echo CMAKE_CXX_COMPILER=%%~$PATH:i - :VCEnd - CMAKE_CXX_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe - 1>Done Building Project "C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\CompilerIdCXX.vcxproj" (Build target(s)). - -Build succeeded. - -Time Elapsed 00:00:00.20 diff --git a/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule b/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule b/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule b/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule b/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/CMakeOutput.log b/Code/Physics/CMakeFiles/CMakeOutput.log deleted file mode 100644 index 50893944..00000000 --- a/Code/Physics/CMakeFiles/CMakeOutput.log +++ /dev/null @@ -1,119 +0,0 @@ -The system is: Windows - 6.1 - AMD64 -Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. -Compiler: -Build flags: -Id flags: - -The output was: -0 - -Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. -Copyright (C) Microsoft Corp. All rights reserved. -1>------ Build started: Project: CompilerIdC, Configuration: Debug Win32 ------ -1> CMakeCCompilerId.c -1> CompilerIdC.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdC\.\CompilerIdC.exe -1> CMAKE_C_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe -========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== - - -Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CompilerIdC.exe" - -Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CompilerIdC.vcxproj" - -The C compiler identification is MSVC, found in "C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdC/CompilerIdC.exe" - -Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. -Compiler: -Build flags: -Id flags: - -The output was: -0 - -Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. -Copyright (C) Microsoft Corp. All rights reserved. -1>------ Build started: Project: CompilerIdCXX, Configuration: Debug Win32 ------ -1> CMakeCXXCompilerId.cpp -1> CompilerIdCXX.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CompilerIdCXX\.\CompilerIdCXX.exe -1> CMAKE_CXX_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe -========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== - - -Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.exe" - -Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.vcxproj" - -The CXX compiler identification is MSVC, found in "C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CompilerIdCXX/CompilerIdCXX.exe" - -Determining if the C compiler works passed with the following output: -Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp - -Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec1419522888 - -Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. -Copyright (C) Microsoft Corp. All rights reserved. -1>------ Build started: Project: cmTryCompileExec1419522888, Configuration: Debug Win32 ------ -1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 -1> Copyright (C) Microsoft Corporation. All rights reserved. -1> -1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"cmTryCompileExec1419522888.dir\Debug\\" /Fd"cmTryCompileExec1419522888.dir\Debug\vc110.pdb" /Gd /TC /analyze- /errorReport:prompt testCCompiler.c -1> -1> testCCompiler.c -1> cmTryCompileExec1419522888.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec1419522888.exe -========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== - - -Detecting C compiler ABI info compiled with the following output: -Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp - -Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec3902347442 - -Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. -Copyright (C) Microsoft Corp. All rights reserved. -1>------ Build started: Project: cmTryCompileExec3902347442, Configuration: Debug Win32 ------ -1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 -1> Copyright (C) Microsoft Corporation. All rights reserved. -1> -1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"cmTryCompileExec3902347442.dir\Debug\\" /Fd"cmTryCompileExec3902347442.dir\Debug\vc110.pdb" /Gd /TC /analyze- /errorReport:prompt "C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCCompilerABI.c" -1> -1> CMakeCCompilerABI.c -1> cmTryCompileExec3902347442.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec3902347442.exe -========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== - - -Determining if the CXX compiler works passed with the following output: -Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp - -Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec3540497414 - -Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. -Copyright (C) Microsoft Corp. All rights reserved. -1>------ Build started: Project: cmTryCompileExec3540497414, Configuration: Debug Win32 ------ -1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 -1> Copyright (C) Microsoft Corporation. All rights reserved. -1> -1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"cmTryCompileExec3540497414.dir\Debug\\" /Fd"cmTryCompileExec3540497414.dir\Debug\vc110.pdb" /Gd /TP /analyze- /errorReport:prompt testCXXCompiler.cxx -1> -1> testCXXCompiler.cxx -1> cmTryCompileExec3540497414.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec3540497414.exe -========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== - - -Detecting CXX compiler ABI info compiled with the following output: -Change Dir: C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/CMakeTmp - -Run Build Command:C:\PROGRA~2\MICROS~3.0\Common7\IDE\devenv.com CMAKE_TRY_COMPILE.sln /build Debug /project cmTryCompileExec3700395636 - -Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.61030.0. -Copyright (C) Microsoft Corp. All rights reserved. -1>------ Build started: Project: cmTryCompileExec3700395636, Configuration: Debug Win32 ------ -1> Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86 -1> Copyright (C) Microsoft Corporation. All rights reserved. -1> -1> cl /c /Zi /W3 /WX- /Od /Ob0 /Oy- /D WIN32 /D _WINDOWS /D _DEBUG /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"cmTryCompileExec3700395636.dir\Debug\\" /Fd"cmTryCompileExec3700395636.dir\Debug\vc110.pdb" /Gd /TP /analyze- /errorReport:prompt "C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXCompilerABI.cpp" -1> -1> CMakeCXXCompilerABI.cpp -1> cmTryCompileExec3700395636.vcxproj -> C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\CMakeTmp\Debug\cmTryCompileExec3700395636.exe -========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== - - diff --git a/Code/Physics/CMakeFiles/TargetDirectories.txt b/Code/Physics/CMakeFiles/TargetDirectories.txt deleted file mode 100644 index 7e769539..00000000 --- a/Code/Physics/CMakeFiles/TargetDirectories.txt +++ /dev/null @@ -1,10 +0,0 @@ -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ALL_BUILD.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletCollision/CMakeFiles/BulletCollision.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletDynamics/CMakeFiles/BulletDynamics.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/CMakeFiles/BulletMultiThreaded.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletSoftBody/CMakeFiles/BulletSoftBody.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/BulletSoftBodySolvers_DX11.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/BulletSoftBodySolvers_OpenCL_Mini.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/LinearMath/CMakeFiles/LinearMath.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/src/MiniCL/CMakeFiles/MiniCL.dir -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ZERO_CHECK.dir diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ALL_BUILD.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule b/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule b/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule b/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule b/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule b/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/cmake.check_cache b/Code/Physics/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd731..00000000 --- a/Code/Physics/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule b/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule b/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule b/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule deleted file mode 100644 index 2d3998c9..00000000 --- a/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule +++ /dev/null @@ -1 +0,0 @@ -# generated from CMake diff --git a/Code/Physics/CMakeFiles/generate.stamp b/Code/Physics/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/CMakeFiles/generate.stamp.depend b/Code/Physics/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 34f1c5a8..00000000 --- a/Code/Physics/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,33 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/CMakeLists.txt -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeSystem.cmake -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeGenericSystem.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/WindowsPaths.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCInformation.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC-C.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC.cmake -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/2.8.12.2/CMakeRCCompiler.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeRCInformation.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCXXInformation.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC-CXX.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/Platform/Windows-MSVC.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindOpenGL.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageMessage.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeParseArguments.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindGLU.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindOpenGL.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageMessage.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeParseArguments.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindGLUT.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageMessage.cmake -C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeParseArguments.cmake -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/BulletConfig.cmake.in diff --git a/Code/Physics/CMakeFiles/generate.stamp.list b/Code/Physics/CMakeFiles/generate.stamp.list deleted file mode 100644 index 8f20741d..00000000 --- a/Code/Physics/CMakeFiles/generate.stamp.list +++ /dev/null @@ -1,12 +0,0 @@ -C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp -C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp diff --git a/Code/Physics/INSTALL.vcxproj b/Code/Physics/INSTALL.vcxproj deleted file mode 100644 index 79dfd7c3..00000000 --- a/Code/Physics/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/ZERO_CHECK.vcxproj b/Code/Physics/ZERO_CHECK.vcxproj deleted file mode 100644 index db94fe03..00000000 --- a/Code/Physics/ZERO_CHECK.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {53399ED8-C4B0-4F84-9CA8-623049125822} - Win32Proj - Win32 - ZERO_CHECK - - - - Utility - false - MultiByte - v110 - - - Utility - false - MultiByte - v110 - - - Utility - false - MultiByte - v110 - - - Utility - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Checking Build System - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - Checking Build System - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - Checking Build System - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - Checking Build System - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file "$(SolutionPath)" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/generate.stamp.rule;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\BulletConfig.cmake.in;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeCXXCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeRCCompiler.cmake;C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\2.8.12.2\CMakeSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCXXInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeGenericSystem.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeParseArguments.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeRCInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLU.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindGLUT.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindOpenGL.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindPackageMessage.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-MSVC.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows.cmake;C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\WindowsPaths.cmake;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp;C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - - - - - - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK - false - - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK - false - - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK - false - - setlocal -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/a6d6ba8aee0513ad68b7d519ca138700/ZERO_CHECK.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\CMakeFiles\ZERO_CHECK - false - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Physics/cmake_install.cmake b/Code/Physics/cmake_install.cmake deleted file mode 100644 index f3cbeaca..00000000 --- a/Code/Physics/cmake_install.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") - FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/bullet" TYPE FILE FILES - "C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/UseBullet.cmake" - "C:/DV1477/Git Repository/Danbias/Code/Physics/BulletConfig.cmake" - ) -ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") - -IF(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/cmake_install.cmake") - -ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) - -IF(CMAKE_INSTALL_COMPONENT) - SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -ELSE(CMAKE_INSTALL_COMPONENT) - SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -ENDIF(CMAKE_INSTALL_COMPONENT) - -FILE(WRITE "C:/DV1477/Git Repository/Danbias/Code/Physics/${CMAKE_INSTALL_MANIFEST}" "") -FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES}) - FILE(APPEND "C:/DV1477/Git Repository/Danbias/Code/Physics/${CMAKE_INSTALL_MANIFEST}" "${file}\n") -ENDFOREACH(file) diff --git a/Code/Physics/src/BulletCollision/BulletCollision.vcxproj b/Code/Physics/src/BulletCollision/BulletCollision.vcxproj deleted file mode 100644 index 7359cac7..00000000 --- a/Code/Physics/src/BulletCollision/BulletCollision.vcxproj +++ /dev/null @@ -1,485 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {C933A737-D7BA-4136-95AF-D12310BD6BA8} - Win32Proj - Win32 - BulletCollision - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - BulletCollision.dir\Debug\ - BulletCollision_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - BulletCollision.dir\Release\ - BulletCollision - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - BulletCollision.dir\MinSizeRel\ - BulletCollision_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - BulletCollision.dir\RelWithDebInfo\ - BulletCollision_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDLL - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletCollision\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp b/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 242b5658..00000000 --- a/Code/Physics/src/BulletCollision/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision/CMakeLists.txt diff --git a/Code/Physics/src/BulletCollision/INSTALL.vcxproj b/Code/Physics/src/BulletCollision/INSTALL.vcxproj deleted file mode 100644 index 1ae267df..00000000 --- a/Code/Physics/src/BulletCollision/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ab6c74a2bcfefb343f549b8dfd875e4d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletCollision\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletCollision/cmake_install.cmake b/Code/Physics/src/BulletCollision/cmake_install.cmake deleted file mode 100644 index 9ec4b209..00000000 --- a/Code/Physics/src/BulletCollision/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletCollision - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj b/Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj deleted file mode 100644 index 0718896d..00000000 --- a/Code/Physics/src/BulletDynamics/BulletDynamics.vcxproj +++ /dev/null @@ -1,343 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {74EDC06C-85E5-47BC-B42D-F55CE6E9928B} - Win32Proj - Win32 - BulletDynamics - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - BulletDynamics.dir\Debug\ - BulletDynamics_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - BulletDynamics.dir\Release\ - BulletDynamics - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - BulletDynamics.dir\MinSizeRel\ - BulletDynamics_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - BulletDynamics.dir\RelWithDebInfo\ - BulletDynamics_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDLL - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletDynamics\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp b/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 49695f70..00000000 --- a/Code/Physics/src/BulletDynamics/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics/CMakeLists.txt diff --git a/Code/Physics/src/BulletDynamics/INSTALL.vcxproj b/Code/Physics/src/BulletDynamics/INSTALL.vcxproj deleted file mode 100644 index c2d4ef71..00000000 --- a/Code/Physics/src/BulletDynamics/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/c8ee57e7d33c4bc180f3bd9135125ff5/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletDynamics\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletDynamics/cmake_install.cmake b/Code/Physics/src/BulletDynamics/cmake_install.cmake deleted file mode 100644 index 5d4eca19..00000000 --- a/Code/Physics/src/BulletDynamics/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletDynamics - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj b/Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj deleted file mode 100644 index be239532..00000000 --- a/Code/Physics/src/BulletMultiThreaded/BulletMultiThreaded.vcxproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {83B388D3-BE71-476A-AA6A-CC7082E3866D} - Win32Proj - Win32 - BulletMultiThreaded - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - BulletMultiThreaded.dir\Debug\ - BulletMultiThreaded_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - BulletMultiThreaded.dir\Release\ - BulletMultiThreaded - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - BulletMultiThreaded.dir\MinSizeRel\ - BulletMultiThreaded_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - BulletMultiThreaded.dir\RelWithDebInfo\ - BulletMultiThreaded_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebug - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 53399ED8-C4B0-4F84-9CA8-623049125822 - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 4b035201..00000000 --- a/Code/Physics/src/BulletMultiThreaded/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend deleted file mode 100644 index c42cec08..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj deleted file mode 100644 index 7290b1bc..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/BulletSoftBodySolvers_DX11.vcxproj +++ /dev/null @@ -1,293 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {2CF89262-94E6-4A9F-A29A-1BE6D73DDA85} - Win32Proj - Win32 - BulletSoftBodySolvers_DX11 - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - BulletSoftBodySolvers_DX11.dir\Debug\ - BulletSoftBodySolvers_DX11_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - BulletSoftBodySolvers_DX11.dir\Release\ - BulletSoftBodySolvers_DX11 - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - BulletSoftBodySolvers_DX11.dir\MinSizeRel\ - BulletSoftBodySolvers_DX11_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - BulletSoftBodySolvers_DX11.dir\RelWithDebInfo\ - BulletSoftBodySolvers_DX11_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebug - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 53399ED8-C4B0-4F84-9CA8-623049125822 - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 4f8d772e..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj deleted file mode 100644 index ed127c88..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\..\Shared;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/d6522d1ca3b18a1cefd93c49bb585a10/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\DX11\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake deleted file mode 100644 index 474a3928..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11 - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj deleted file mode 100644 index 23e3ae3c..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/7480449d728cc0d853bd4d008829b250/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 90fb95f5..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj deleted file mode 100644 index 478d15e4..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ac95861cd32cea3cf78f1d8d437ff9c4/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj deleted file mode 100644 index afe67dd0..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/BulletSoftBodySolvers_OpenCL_Mini.vcxproj +++ /dev/null @@ -1,284 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {80FC7669-D649-4212-8B6F-C0167CE9CB59} - Win32Proj - Win32 - BulletSoftBodySolvers_OpenCL_Mini - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - BulletSoftBodySolvers_OpenCL_Mini.dir\Debug\ - BulletSoftBodySolvers_OpenCL_Mini_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - BulletSoftBodySolvers_OpenCL_Mini.dir\Release\ - BulletSoftBodySolvers_OpenCL_Mini - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - BulletSoftBodySolvers_OpenCL_Mini.dir\MinSizeRel\ - BulletSoftBodySolvers_OpenCL_Mini_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - BulletSoftBodySolvers_OpenCL_Mini.dir\RelWithDebInfo\ - BulletSoftBodySolvers_OpenCL_Mini_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebug - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;USE_MINICL;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - 53399ED8-C4B0-4F84-9CA8-623049125822 - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 89f3173a..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/CMakeLists.txt diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj deleted file mode 100644 index adfaafeb..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/765171c08dc783fac2d12295ec042bb1/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\GpuSoftBodySolvers\OpenCL\MiniCL\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake deleted file mode 100644 index 54342e1e..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake deleted file mode 100644 index deb5133d..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -IF(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/MiniCL/cmake_install.cmake") - -ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) - diff --git a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake deleted file mode 100644 index 90f58c37..00000000 --- a/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake +++ /dev/null @@ -1,36 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded/GpuSoftBodySolvers - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -IF(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/OpenCL/cmake_install.cmake") - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/DX11/cmake_install.cmake") - -ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) - diff --git a/Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj b/Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj deleted file mode 100644 index 6f114658..00000000 --- a/Code/Physics/src/BulletMultiThreaded/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/330478308f2d4034b022501b4d79274e/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletMultiThreaded\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake b/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake deleted file mode 100644 index 1556c814..00000000 --- a/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletMultiThreaded - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -IF(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/GpuSoftBodySolvers/cmake_install.cmake") - -ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) - diff --git a/Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj b/Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj deleted file mode 100644 index ead70727..00000000 --- a/Code/Physics/src/BulletSoftBody/BulletSoftBody.vcxproj +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {14DC504E-697F-4178-8E05-87173957FE59} - Win32Proj - Win32 - BulletSoftBody - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - BulletSoftBody.dir\Debug\ - BulletSoftBody_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - BulletSoftBody.dir\Release\ - BulletSoftBody - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - BulletSoftBody.dir\MinSizeRel\ - BulletSoftBody_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - BulletSoftBody.dir\RelWithDebInfo\ - BulletSoftBody_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebug - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\BulletSoftBody\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - 53399ED8-C4B0-4F84-9CA8-623049125822 - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp b/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend b/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 42b8971d..00000000 --- a/Code/Physics/src/BulletSoftBody/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody/CMakeLists.txt diff --git a/Code/Physics/src/BulletSoftBody/INSTALL.vcxproj b/Code/Physics/src/BulletSoftBody/INSTALL.vcxproj deleted file mode 100644 index 39d05026..00000000 --- a/Code/Physics/src/BulletSoftBody/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/ca084c0a5c507973a7b07d4c0abb2b7d/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\BulletSoftBody\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/BulletSoftBody/cmake_install.cmake b/Code/Physics/src/BulletSoftBody/cmake_install.cmake deleted file mode 100644 index 4f658151..00000000 --- a/Code/Physics/src/BulletSoftBody/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/BulletSoftBody - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/CMakeFiles/generate.stamp b/Code/Physics/src/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/CMakeFiles/generate.stamp.depend b/Code/Physics/src/CMakeFiles/generate.stamp.depend deleted file mode 100644 index 5c345586..00000000 --- a/Code/Physics/src/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/CMakeLists.txt diff --git a/Code/Physics/src/INSTALL.vcxproj b/Code/Physics/src/INSTALL.vcxproj deleted file mode 100644 index 3a27b8a1..00000000 --- a/Code/Physics/src/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/5d041ccf992a74c6e506ea6e800c9974/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp b/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend b/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend deleted file mode 100644 index e22cf59b..00000000 --- a/Code/Physics/src/LinearMath/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt diff --git a/Code/Physics/src/LinearMath/INSTALL.vcxproj b/Code/Physics/src/LinearMath/INSTALL.vcxproj deleted file mode 100644 index a21294ef..00000000 --- a/Code/Physics/src/LinearMath/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e7e919ab85ba2f15a0972f20ad0a5317/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/LinearMath/LinearMath.vcxproj b/Code/Physics/src/LinearMath/LinearMath.vcxproj deleted file mode 100644 index 305ab63f..00000000 --- a/Code/Physics/src/LinearMath/LinearMath.vcxproj +++ /dev/null @@ -1,300 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {D4985405-3286-4026-BD61-E9E53DC5027E} - Win32Proj - Win32 - LinearMath - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - LinearMath.dir\Debug\ - LinearMath_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - LinearMath.dir\Release\ - LinearMath - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - LinearMath.dir\MinSizeRel\ - LinearMath_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - LinearMath.dir\RelWithDebInfo\ - LinearMath_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDLL - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\LinearMath\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\LinearMath\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/LinearMath/cmake_install.cmake b/Code/Physics/src/LinearMath/cmake_install.cmake deleted file mode 100644 index 19b348f5..00000000 --- a/Code/Physics/src/LinearMath/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/LinearMath - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp b/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp deleted file mode 100644 index 9b5f49fa..00000000 --- a/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp +++ /dev/null @@ -1 +0,0 @@ -# CMake generation timestamp file for this directory. diff --git a/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend b/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend deleted file mode 100644 index aed156a6..00000000 --- a/Code/Physics/src/MiniCL/CMakeFiles/generate.stamp.depend +++ /dev/null @@ -1,2 +0,0 @@ -# CMake generation dependency list for this directory. -C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt diff --git a/Code/Physics/src/MiniCL/INSTALL.vcxproj b/Code/Physics/src/MiniCL/INSTALL.vcxproj deleted file mode 100644 index d88be3fa..00000000 --- a/Code/Physics/src/MiniCL/INSTALL.vcxproj +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {71641E56-5E9E-462B-844F-A9F8A6D82120} - Win32Proj - Win32 - INSTALL - - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - $(Platform)\$(Configuration)\$(ProjectName)\ - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - - - - - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force - false - - setlocal -cd . -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/CMakeFiles/e6392351cabae74903e183e9beca42d8/INSTALL_force.rule;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\INSTALL_force - false - - - - - 14E546AD-2393-41B9-BAA2-134241286A4E - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/MiniCL/MiniCL.vcxproj b/Code/Physics/src/MiniCL/MiniCL.vcxproj deleted file mode 100644 index 11346872..00000000 --- a/Code/Physics/src/MiniCL/MiniCL.vcxproj +++ /dev/null @@ -1,277 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - MinSizeRel - Win32 - - - RelWithDebInfo - Win32 - - - - {FA9E3157-5228-4CA4-8327-BD0AF11BD390} - Win32Proj - Win32 - MiniCL - - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - StaticLibrary - false - MultiByte - v110 - - - - - - - - - <_ProjectFileVersion>10.0.20506.1 - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Debug\ - MiniCL.dir\Debug\ - MiniCL_Debug - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\Release\ - MiniCL.dir\Release\ - MiniCL - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\MinSizeRel\ - MiniCL.dir\MinSizeRel\ - MiniCL_MinsizeRel - .lib - C:\DV1477\Git Repository\Danbias\Code\Physics\lib\RelWithDebInfo\ - MiniCL.dir\RelWithDebInfo\ - MiniCL_RelWithDebugInfo - .lib - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Debug/ - EnableFastChecks - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - Disabled - Disabled - NotUsing - MultiThreadedDebug - true - Level3 - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;_DEBUG;_DEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - Release/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - AnySuitable - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - MinSizeRel/ - CompileAsCpp - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MinSpace - NotUsing - MultiThreaded - true - Level3 - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - RelWithDebInfo/ - CompileAsCpp - ProgramDatabase - StreamingSIMDExtensions - Sync - Fast - OnlyExplicitInline - MaxSpeed - NotUsing - MultiThreaded - true - Level3 - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions) - $(IntDir) - - - WIN32;NDEBUG;USE_GRAPHICAL_BENCHMARK;_IRR_STATIC_LIB_;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions) - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - - - C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\Glut;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src;%(AdditionalIncludeDirectories) - $(IntDir) - %(Filename).h - %(Filename).tlb - %(Filename)_i.c - %(Filename)_p.c - - - - - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp - false - Building Custom Rule C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt - setlocal -"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" "-HC:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source" "-BC:/DV1477/Git Repository/Danbias/Code/Physics" --check-stamp-file "C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp" -if %errorlevel% neq 0 goto :cmEnd -:cmEnd -endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone -:cmErrorLevel -exit /b %1 -:cmDone -if %errorlevel% neq 0 goto :VCEnd - C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL/CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;C:\DV1477\Git Repository\Danbias\Code\Physics\Bullet Source\src\MiniCL\CMakeLists.txt;%(AdditionalInputs) - C:\DV1477\Git Repository\Danbias\Code\Physics\src\MiniCL\CMakeFiles\generate.stamp - false - - - - - - - - - - - - - - - - 53399ED8-C4B0-4F84-9CA8-623049125822 - - - - - - \ No newline at end of file diff --git a/Code/Physics/src/MiniCL/cmake_install.cmake b/Code/Physics/src/MiniCL/cmake_install.cmake deleted file mode 100644 index 2159470a..00000000 --- a/Code/Physics/src/MiniCL/cmake_install.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src/MiniCL - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - diff --git a/Code/Physics/src/cmake_install.cmake b/Code/Physics/src/cmake_install.cmake deleted file mode 100644 index a17a786d..00000000 --- a/Code/Physics/src/cmake_install.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# Install script for directory: C:/DV1477/Git Repository/Danbias/Code/Physics/Bullet Source/src - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/BULLET_PHYSICS") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -IF(NOT CMAKE_INSTALL_LOCAL_ONLY) - # Include the install script for each subdirectory. - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletSoftBody/cmake_install.cmake") - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletCollision/cmake_install.cmake") - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletDynamics/cmake_install.cmake") - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/LinearMath/cmake_install.cmake") - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/MiniCL/cmake_install.cmake") - INCLUDE("C:/DV1477/Git Repository/Danbias/Code/Physics/src/BulletMultiThreaded/cmake_install.cmake") - -ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY) - diff --git a/Code/suoFE00.tmp b/Code/suoFE00.tmp new file mode 100644 index 0000000000000000000000000000000000000000..ef7e46377ca585b054655603440c38a7a4866a76 GIT binary patch literal 1536 zcmca`Uhu)fjZzO8(10BSGsD0CoD6J8;*3Bx2!nwD15p0|e-Il+gV;c!Q80u;;4jdv zp!gdFBQpeo81jLzgh7G9l_3vE7co?VvN6#>jDZy;&l95&xx64oJs~y7F-J%(E#!x? F{Q$8g^JxG8 literal 0 HcmV?d00001 From 8c31c16e4d4c752baaccd464cc73250ac3b5eb3b Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 11:21:57 +0100 Subject: [PATCH 20/35] Commented away --- Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp | 4 ++-- Code/GamePhysics/Implementation/SimpleRigidBody.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 4c07cc24..a71c58e3 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -129,8 +129,8 @@ void API_Impl::UpdateWorld() ICustomBody* bodyA = (ICustomBody*)obA->getUserPointer(); ICustomBody* bodyB = (ICustomBody*)obB->getUserPointer(); - dynamic_cast(bodyA)->CallSubsciptMessage(bodyA, bodyB, 0.0f); - dynamic_cast(bodyB)->CallSubsciptMessage(bodyB, bodyA, 0.0f); + //dynamic_cast(bodyA)->CallSubsciptMessage(bodyA, bodyB, 0.0f); + //dynamic_cast(bodyB)->CallSubsciptMessage(bodyB, bodyA, 0.0f); int numContacts = contactManifold->getNumContacts(); for (int j=0;jafterCollision(bodyA, bodyB, kineticEnergyLoss); } btDefaultMotionState* SimpleRigidBody::GetMotionState() const From c191c96ea887c7cd792fc2db48e63c623d082a79 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 11:24:38 +0100 Subject: [PATCH 21/35] Added bullet physics .lib --- .../lib/Debug/BulletCollision_Debug.lib | Bin 0 -> 7605304 bytes .../lib/Debug/BulletDynamics_Debug.lib | Bin 0 -> 3733436 bytes Code/Physics/lib/Debug/LinearMath_Debug.lib | Bin 0 -> 666352 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Code/Physics/lib/Debug/BulletCollision_Debug.lib create mode 100644 Code/Physics/lib/Debug/BulletDynamics_Debug.lib create mode 100644 Code/Physics/lib/Debug/LinearMath_Debug.lib diff --git a/Code/Physics/lib/Debug/BulletCollision_Debug.lib b/Code/Physics/lib/Debug/BulletCollision_Debug.lib new file mode 100644 index 0000000000000000000000000000000000000000..e47dbff6dd8ab663fa8b2b36a579f62d9c11299e GIT binary patch literal 7605304 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%0D$wdFnC*A};K{1a-+{IIs@m7$A8 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 z

    4Tm`ku8u~*kLovCxzi749E-$kQhTfK@Y$I#V02GPlxw&kPf2#~?@94lTDvz>@p z`QE(Dd~Z=cIyZ9?k_G8HTdG_p9TOQ%Jto3Xz>#j&!4Uv8I&=9pnWd8pKcfnFM!u1Y z&V$Wa>pWNPuc?PD68(zYIeY23->cM=5qJahC=aLD+|IN8&xNk&(Ov>!mNxVVsvC_bHK+7f$ZYs^k7x7=_-d+fb5p0d+}cr>?kJymC|@Fx z&b)q=lo2>q>ytGSf;TPFFtf(7s9eKJ^4o5F2?e;P(Q>klhxXd-?byvh5hT~S?Rx2!LygXXj+*lmfy}SfW(!mJ8@fnsU4Y-(m ztO0!xFdIxbZyNGpS|baHHWJ5fU~&)PnVcb^&fptUOL`Z2)GQ6=zGA z^V~lZgStYeOI`}u~mgLvvNm|u9_H( zc*+CKP2nK+?O9q?=x?kJ`omS@n`#49W%WzL!J2Rtzl&PX(tzFb#y2%I1jD#vj6E0M zMHTmG_(XN|T0gw0dOo&l8RvF+_!N_A*L}|?zS1uZ)`XhEO?45^(DGwE)0!i}g~4Uq zp>I4^n+I`w0G#dhW)?5=q`Pvo7tZMG`CN=}e$0DeOpsqCSOxVb#B{+^XH)W!CEhOM8xthI>&lg z4Bax}dbpP29*7+I!t8x3OL)gMzQG?3=Z8Z6rFi_F;$Fb$veH5*qOeZL3`Fj45=85x zumjVo=VL+tl%^W)>4cq4QruI}W*Ttb5a1QTCpUh=BI^|Q`^c7Q!VBE>xk6wE*1Vo*G+DGbRA~_J6}6}W1?3NkqM!|`BbXJfozT$akK~G?;5HvV z$q!qw#OhEj8fcNtQD%TsRcKQg}hQ8irDocKWc(r zWJyG^nty3!j7A=e$V}E2YY}KigDxtYD!{najX7yS#=^m60c4DISLFl^!pIEm*glMQ zH1#G&fVksmD-oXxGbVyXYo(PYluRiS`5%M+!8BKI%6~7&8b*Wq7LLjl_B_Ih#VRtG z!E7NDH%*jn#YauVf?!GdR8caE#W+{Z6J^GBFDlPRCi%HAir6Zl866!jk7=$O`<;I0 z?+-p|^UfDv@L%9co+{scO>>>M_LJ0~uUOHp-SMC29-r5MG1h8z*%MJRu81B?wA$9k@OG%P9@>&zS^1&0nnlFVB21r^J63_7@WLs^c%~_3snj$>>|S<%F$cFTj)Ye+v4=FU~se z?@wRXZxh$)24JQzk26=xNe{Uq`9&N?l^5t!+CH1Y5KO2 zSHH^-{jp)BxmwS?en;`R%2y;EE<~Y}*_(pH@Nt>-+tS?)Ylwhdo1Q z&FSBIKJ2ze(6#Y>i{?x^`{$FAzy9Uw^rxG!46Fy`RIb{3Q>ndQM%o zX}^IfL!asK=$gp)_>?c|&-)xR<74m5p{9A5UG&sp@DTP4Z5=b}n5u=wAY*Yb+~RNW zgd;7r!6r{u*6_@##WhvI#+rr}jCR5iP>0v=;O zw4}KnSLYgI_*5OK5np+$K@ZRcY2pK_0Y5h9i_~NIg=ub+ur~4+UFuT64Nu z@L~)znnGPJR_^;OmED(`LA&m|l$ubaHc%JdcR^u)Lsu67KFf<++FCqb*?09&vGJ%N z6lknjYG}GI)?e)J8ne}L;L`=!3q_WM8oRmx76uy^`dhm|>fZN0HOpkS1!@k=*yremV!DQX=U}M9+cJtW56nb@mPLbM%VD-MsX}~>iqzih5z(Uj^ z^v|kl?n{en?K)9bNwtf`oWnfKIfSBf4z+5|p@wq~&1%lUeqFWHu|>vBWf!!WSjn|Z zaNh;F8I_ryj6ij>=OlQ+W)IJEJ;!-Y7X;8rkSAezG6u0Hd44scCnGyYr7}zi#;8Wj z-Eeq=FLSyZGvpT=IV03V<6bBX_0;;QP^uO&Xnb*sv8md<2w}B5a1W>uzVv|**H8D< zUQr?Jl#BDTF-7^^4ZD)Z-SS?+vzxyiQSr{LVqH82S9?)+4q7FIDIfEx@|lVd;GyZ0Yjpnc><qYN|ECWvaH31@7Q~R;Er=npyVI}RWLz2tcemo>-08v;v1a1@Fdc3X zg=s#L`#+ySd6}lA7BP8tI z+pW; zKH&tx!RO@%y7;`jcB)IuR2`Pn^YTr{vId!)!}IdWF?a}ui^;qii8~XXH_r3&JiY5t zA|=lLy!-_l&i=goXEc!4fP1M`3cCuP@w{B^Da4pY9M_zU{ul#MI`$U^PEh1u5xfX6 zPbwUHB&X-#X=oE0fZ5h2`PlZIo~!eUI^jlvp0?$9=$zUny}Z@SOCkhkjQ8^Yg_L z$NFNFhpAo-0X^8RX{&J18TN~@OEuyiQ5XTlpHsRXqv)zLE#d~djObQelNtum6wg^cY*1CwZtWAM}vX+x5CBK zZyv-9y++f1hl38q=vclPh`1J*XRZ~nxcc=)^gk6wBAw;2Ji1?pF***qc>0OOA=hIs zO&oOb^kaGC05jwU0gEdy1JN^pS*mdH%Hwt5I)Isdqm&n~{!zarz+A3y@$_Rqc>^$i zxJk;3mtVGz4}eL!Ihw9hds~m_LBP0fk+^vBnBN>=PEojc`F#So1;7ls6#=+-`DM}O zD~tf*&q+V-xb_KfU)?5A@$_SR>vuc)1RQkn^y?0JX8?1~A0#fGyu%Uwpu$L`vwo~E zZvyx19eb9yRbdjzV|_m0PHfAJgD#PNhukGG`oEL?)*&(%xU{<^DxN&f#?HQW6OISbWGPNzwd$mAuxY>hN$@V zqkf+Pv+7v^i<@8ScMCA*|3%{B<+l*gj{&n&;gWFfq~Chb`>oNm9XROX$>Z?)*yr#? z9UOG=^1B^zUjXyL^8yxE9-B|f3lgLMJL$*q+LOS&u{N4>fY z<`IQU#<^2|soz#$)_; >=E#eu(QO4!U^#^BTnE10%L@ML1r5DK7_=VJa>q1eZ zzzqIa;u6WL1g1&h;>lz2F9)XLlf?3N!p0IanR8&PVxpo-dn(Y_oaZvEssV- zAO02Q25`{DlgIw~8DL)gI*N1B?^ZC;hg7z6O|kzmd3j<=cSh&lE-? zo#ipPN#AN(_IHWpO-6JrF!w7Q+qsi|J3xN}m=~!iTs-~yBJL-J5kUMo$z%QN^$+yV zIOr0|>;1jN=>PHL4FT?73L8&eKL|PUpSmRJJIUjC=p^9W>=@t@$s4aQ66u^@$~zUf z5!)mxkvzY`B$CG@mjW03VbAieSC~D?dl5hXL;<-dhNzI z8wXvy^57!x{+dg>xEmCJ^YCzZp9~){(*BC=Yo{hloEtbN{oX?K4q#qp2Li|T;v}yM z(bw+p(tb>pxOn+}0{k`j8qHxG;K8NhaFR#+ode9n2PBsFJopFU<2V~}&@o*ndBupH z-p8d~%L#vlbIR{f#Px8yv=KPyU?xX->p>q6%#Z^mE?#+1-V9*QQn*C&E(2zfdN>(R zUMA$-4$R*aE?)mf{k8$~4hQ;hiR2|=HGd9Q^uxuI$ND!Nm|+JemNyPKA28P|Ts(Qa z{5=WGjr`aTTs-}95cihC2q6BP%9r;?-LTT?-&}147f;?$6u?k?7OU(qi8}~bM|p_u zjf-%%fr;fE3;tYSPFJ{i3YJ4wnt37*`_r1dGNnW=> zF73d%cnTJTKmr7jKoSsqF2-2nx{6im+xjl8TCt@qSgS#( zqQ#09Ehx3|(FzqSDk}D)^8fwLnLB&;-rY^0(eL~J|KB8c=iD=A&di)S^L|{`2Y(0M z!AGa(R|Wq=L9@irkvbVa2Kh8--Z>^czeVt$-#x>51P@KB`kq~gk3jQhPRPNeN-z2C zbzFvXA0C=?{5}B9+T+{i*QrN_b32~4`27VmFP)H{-*aH{U!Zxqr_!aWPg#DupP1p~ z6{Y8wjRDM=pc#0I(v5(>Wck7Jam{HN&Rla{dMf#`Kfl<}02Gsq-)gx09(1wO)5nke zo-;JcEqVONZzJd)?%y`QHw{f&{5}WWZ_Nggbm{%r-9%y-rb=(<%navsJT&R}Wu2uo zhF#M9V0sS+-DX3ZieFdIeXqEE{7wbkPD7iHU$2t(@hb=2{-x>D%l7gd&|GThQq|8b zpo@ZL$bh!_T?v{e3|%^YD?qbgVB7qD37Yo}T{?bWf#x@5ZS&g7eix(hyA++fMm#j^ZzSWF2mAw|d7=$Ew!eP>&0h_j%Ei6! z0FK6xU%}uE=MX$J>B2o7H0QKI$8f7bGvCl9hMRcL!egL$&d^!;d3MY(KAfld6KMWv z=orgX_bhA&P0qQR4nr5XKY{Vt7c>X9LC5;waL}A#=xqGtUWvqX3%_cvcFCG2BZwF{j8LDzgmyTl4R3y>` z(m}nt5Hu6oprf2?Ky#&`v+4E4kK=_~K(i{5UrVz4Mg9nycM|E6#%~j7K5m1Ka{dZ5 z`<1t?FUNr9^mfpl51Pq-I$wGV5$>g+x!usE%Z~>@^Hd^TAiXRfzXi=ILucjeE5A(d zdeCeO(8c$&f<*RF(frUzU`#z-%h&XcG3-OC*7cS(hY4VT}3FnDL5OL^*lni;GM2hHlSo7r1~KSHLE@=j=k~a&NHyi#EU2 zpm8xKW|y5`qaSvG?|vc5YYg0IUw$M-LZkN!B~Nv~e*B`YUrxCBW8ZuV-ZgFpV1}S6 z6Em6p3bx>o&H+v*ffxT5VeAURH9@YA|4UyBoPvT)Oj=JKoNAa>Q;!R23JP+NoKG=< z7Ix%TgAzefC>~@fdZGmdEY%0WbJ&?xi-WMdsY-4Yz;tq^70&x0;&c$qzVOrf&CZ=4 z7c#&aUQUdY4+RDInDNd{y@{JT{bI;DJAuL9(72c(Lm`L@ckJBB3yltN<~Gb5JhNg( z<;?1ex>{bFgbVHt1Vu#>3al6w6tp1k)ay)K)lfO({Fx)>)J>_JTwMw!K-8>roHMQi zno%W@yx+?eH!~F!tVL3;lbFn6B+e6_hlYNPfkPzD3FVf)8YGnUaJ#h|c}5q5)TY88bK>=hIg z!I!$JFC(atyr;rB90U;`fh1I%d5wi+!amMv1-Bp-G*2JF+q_OIcuHUG`v~?VV3r&A zBROJ%IiZx3?B_!ZxazY>aQegYx*b`1FkUwrJn}xmvW#wCq#E|guxG(O1@`B#Ple6Z zl)kX{hTqd*V-^?JoH>z`V4n_~Dsm?55wOpKJppzJ>{+l8naBdz17R};gyT-aPX8VY+3>~h$PV4n~BCD;|P{|b8;>~CO?hTQ`xM;apjdVM0| z&DsUoD`qx;eE<>nDW2_kF7nlF6M-WQ!f|ew&{CW**_I2bh1X7inK{q+}s}($@o%ePWZsPbF{- zOR<_{{hL8(y8a*O-=y!NCF%XJf5NInJ33S9YA-2~rk@fsou69Pgxd3oQgP}VESM@U)+zJZb#ygY=FfP8*JDHtBf$t06#e%P^o-wp$CfL_b z9$GzfYQr>%<`Vcb?v+(FbLu5RYi)#ZRfmmGm1Q*vw+L3@-q7LVrBwPi%Pb>YiP5xgF3oV@ns$%SF1D&BPDX{JEs$#??K30sgECUr|sRYAA z_8QDw5$iO|FfkP+Xp9O9CR$f;E}1!X4lZ=G9ZZoOzR8f#Lk(e!)?G_jH!v7!#ef@O zv|kFTPla&MEc?EnkG{d z>08EoiI6=$JuXKz6ADc*tM`1!JZBK7qIJKFNZxB z_DirYg?$j>Fdz1jun|V2C+sU=Uj_S0*iEpng1r!S1poKLZiLNy4u1gqY1lWwUIY6k z*zdz$2%GmE-U9nDWd3cid&0gQHt##U1NMB_NK51v*muGHIqbV(zYhC8*dM~aANE(U zAB255GT>p@QP_{dehBu@V7I`23^qT3`~>VAv^`J3E`aIldj;%uuwQ`v1?<(Z4@QQ+1iKXW%dn@yUIY75*nfo0b@JC> z9|rqRuzSK@2YU$YH(~R>!u7Cc!`=Y<0oZTBehv29u>S=6FR(v@{SNG-pfK;k?gRTh z*!+m_2e2z){|)wSus?*o81`n^zlHq|*dN0F2=;z^;ghwn`@sGL_6XRY!p7qqgf;Ws zx-4lU=m_dX!sn2 zHLmiCk^v(FA-Qqw>L39l2M?G~F|_2oGEZDx7Ki$SDLZeVCiid?$YG!;uQ-1c@FEir z6PKjW8FBvEBTLU8I5t4yhI6Dd_`K02Lk9<$v~g{7+MAkBz^if zL3p!}qnkdr8gnyftY%iu&7A5&YFJNuHAP{sq|_q5Br>iK2%P@ z%bqOI*f5%13K*Nxy4uPrxfYe5*67%4w0TAJ=HpabYS8# zbWc)rN7U9eRMb^h)!;h;)lwmweD&Unemp#XBU;h+r;0Fjnp5y`JBe|Nx@Vy2mE%s_K`PF?MsS@r0L<`n!{+LuxFD21gp4O42Wu};y>yX4tCZS^!0Zb6dL zV@oLetnmipJRLgXOA7VURY-aleNL8c1<23X`?<|;)&HgFmv{W&!D-iB^aut=a~;fq zXZ(0w-#1U1abUrd`#(Rmd|LIFj`OwP&uty{<+I0*U4CTd10_HHcmoDe(=$jPywmld#*>zs3sZ$0O;j~4B<_s?#|I7#rqyY4?1eDJROp%^ z{ibkU{<+)xY{l9M#$5Rs$G>{Z8>0`OIQ5Qyg&JR&yy+>&Sta=3-S~QkeDH4k5g2PF zyBq(fg1_g~hW-Ei>ie&bp76uVJ1uEgiR)A_w#v`AV@lE2PrP&Yv)vbOy!XMmOJ-wR zrr;lbYttc5-9NCf^soUdYp;C^Rb4K|T=^LfzBBotu><~c)aql$d~m_+hlk@BvfzVv z>~9u)@Q(eHL*x^@WB*FQ2k+Sbz2Jj)?C*_nUw%gLj{Px$58ko=kl=%N?0+oy>|5)v zzNzZSZeO1{Z_>)y@2+s1@pLe)YGrU!9EOO@e>r%h6Mx{6YOS z_q_e)UhAIOh8eHHdy{_cS@+)d(kEqS{NmOp-v8yqM~}gHU+^pY-BNJU=5vRgv%Fx* zi~s!FP^`1*xt7D-_%sVP z{>;LZL=`@P#_y7JKKYw^uU*^#5s=z!1@ zYWe^D;K;6g=jwkyIMU7!j`%BWTPw%=`Z7!D>GF1H>l6%6`}IV9G7KT2z2`NflaS z733tl(AqpdV@iRp8;-4Yv<^2rNJbW>zm-jP7 zy$ba+MDpn(`QbN;Y~1jzoj!&7c_HBX$oGbT>uYe|O2}>~r+oW?^mP;0@d-)bxGNuo zva(MqsuA2eue6^KCUdSqMX(zX%ae0Lsd_D_x>&dv58B_){afd$-R>){BC9V zDXvUxUYy!-%zIgNvfO+1E=m^nj+IZZqNIWBmVo-YtZWjJR|UJpyjMra+SG#aG|QO_ zEInWwmSxH&DoV5YUB!d(=Q7=P5wn7u>H56mnVs@dQe)v&ujr=T$)C1@|Wd zg`9T)T_m{o3>0!c1~fr%pBgCS>;N=TaJTE$&Aa_n^f+YH`n4T#Lm$j+L&15x+fg^_fDs&JF{Gob_10qHC_R(Lf<52a3XP zS?}qLG*GU?O{v6%ob493!{WMQHH!LykCg$c7JlOl6ms4GG*@sN3>0$4VBLvljPOx2 z1Hr;t5xL|#Sq2I@g8?bOas!2&dO*{J?otCmYJjMXxz2S43OTm`nl89S1`0X%1G-pn z4;v`tJPBxq;C^YKkn=1c>U6I2yn#Z_D}ZJS?ll92oQ;5L1=nhzkn<5B?$^zAJ~2?p z`4^zsg8RlmA!jeFb=3)OZv%y#E`aI<*VRBF=NLc@f;-+oA?Fl8Qw7)0Kq03L&=kQ9 zHc-g98|zvs(;piM@w2#3EbeBkXDQvS1`0Vpwz!8Zj_Y1Z_e+a=&f->D+^ZJ%CyV>5 z#l3HFpIF@I7MFuf0UAc0fkMvp`|9<2xz3FSLS6!bF!4NWp#NE4mK+h?*tjL9@q?|6 ztFlH#FV1S7(Jd>wW%|x(h_h4m0Dmh+EZEW?OW>m~7#928Qk=wGj%)p#WouwQe{8If zob>zVvMm*{vTaol(MNOnrfAuw#(DWp=WE}?dlc`3vo_HwI%-q2G^c`?VOhgL6&;jM zTt;+T^xXVtMUS1YpT12fhi&NEP2BUWdtOrad?6Q>gYyi`Q1UgDyy3C(h@f9A+rcQr zVm#a+nCO6<3h(QXykW6eAx;^H>vZfykB-P69&4h93J)7l>~vo@^AxP4C$D)CkAzC3 z!_6_CDUHgnaBFVjsni4n50^$q1MbTJ_irAuAa2syi@}k=+ zVof~VP!Wwuq6>^&+JEO-lY@x4#(>9u5rcS4n}~r=N<FP!Z`9>;;2^ty~lP1iS8ifL9%PYEV*ais%x@LUFnn+O*9g-g{ z;7@6uP0#S?D;2T*sX`LymFi^G%xAXH0Ho6 z4Bm}h(8RN9ZbH__$Xa8!;odQzlo+p%k!XDr5gYF1!7nC_v5z$sLn;#hTol_coJCZ3BchD1CKjyKR7;lcZUz3=^6yvJgsLLhWRAjBaMRwxq43r##} zh!9#_43pkfl2g#M49FLoc*;>TCZ0h{fQ!W@x}I!9Nz5=dfz%}Aw*+!S>^7jUk1?p| zq6mJQ7csnO)3t<~RuPU}PdK)k@S+hiLb!b1dCY=k zMqkE=uUX=&m2gu7;ieA=$L0}^Z6dtr3c`!F;MZ-WW7H0b=Z1Sn0#E*GYu@8sYV6J@ zuCD9$LQ^9o=peoDrl5pP_+lw$0B?X?o?xG=8( zGkCJvGSBzkfcMxUQXvQFh#VviU5{b}AaO_YI&6b*kd}$!MILmCUe7S2Bf6l!bc28u zdA7sk4U@+QcT*zuh)Pn4&|z~e5>JWvL>i-nKJR?dY83Yv11C*a(YrBC`d(n(72o+p zN!?szL0zf<>9F}5)Rb<@kOkyPPqR~bqQmBw)RSnu@l<#03r(|9d7{JS+u&*Q2N;{g z)*)DFG^8i5_!o)RN(`vbCsRb8P(@Tf}}GDql;~#Ht%r_ChIQ z!ju(t6GLOw0Sh`oU*ZOo?T$eO8lN`$*X+~38AyyPG1k7*eD76wk2R4B9O;PqggErj zw!%uHfAREJw55d7qw0!uu?d30=A)!UJJ~Ljb_pej7s_^I*dC&Y#-!Y>XFC5nwhr-W zda2<`B$t`87O$u$u1TmTnp%KuZju@(wu*2}YM@1{2``cwsA-MRum+08mI#g1D~py2 zjnpem%Y;VimDn>v!+PbT;b;vPEd?}u`c9jo(j1$l7n&x6*gkjg{Fy2QZfQM>|(b&ET0xZ)SR_YL$~j{!~-w%z$}6;4O>@!!lbe5YG8}V3t^mM`B#qcP&%m0dQH<_8ulL#g$Bf^W}*w zdO4Hvt=_q~&%j(H;JD}Pu^5Zv?WN|u#L@Q>oTbu<(QIDArShomqf5DV^VgeSNFQq6fB(90s1r555;ui{>`(0hQ6lyEcA0aWM+K+3t?LgN8(8a&&%63|-V ze4B-y2Bf+0nuXrBuAD?xzk8!+uh1bDI>AC`0OGY+*-kYeUN;qXE(4@-zQ)r1&_WMd z=w(2>m?|uj((2mzA6>sXP%7r_aOAp8=^heF3OI=yeEmRFCDt@N}QokuCipqC1t|;CFDo*}*dcBc|q7vqV zR$>a?sPiEf>JEtOXxYvgfK-K;H2-aJWxx^d8vl)EkHBG;@0KX~fd)vz@8pRaF}NkF z?PH%wPI4we$rV!GSh-<1PGKZ|f86_p=KeUn_%CpK8RK~eDl^C&9M$y1q-7s~C&ET4 zlcpVOX9mKWn1Mnv8_I@1mp60>UC2N0hABEYNhU@AHh$%P0Pm3uPA2I?;p$D3U(z?j z{X(Cl>4%a&7|*a>m9(CD?bpwoedV>I-tfWF7_UtKROpo{C3G}Wq!J>e5+c+dY5Zun zr7;H~7pIZN{3A`|&Fy5k|6u^`fa=%JJ(AA1cIwfUCwSAWH{!Arp{XXMsV3x4^)yCf zdggS_*XlG~w7mPU=%{YPqh*B^(ekc^WAWvfVR}x zqOwm*TRaFj_Wi=nC_t$T^8~mui@V{W@v9j7vS<2)N2n?MpjFdN;~~TwJ0TxIt#yJbkp@RCGPINUWO{by&AL#NY^m!i}9eIv@%1b5h=v`5ZFUuu>ftGP5Q zT7t!Z9L!f^q$va|-UC6-GSaSSbuzJT5Ngheo}1M?C@Xp{ruB28!}FRe@`T{E*37aT z3E{POGqIkK-&_!_$l`KCMNaduoM>@gb4gxc&Oa-u>OF=4Q!CuB;7Wz#L*rMtCgA)E zM?X}!NAMJPyu$HrODf!b(7@UT+%RGCURsA@IJk!KVCL_Ehb;n49WuKRb^~l?{v6oz zV9$m9AnZ$FvrhaR8Li4dNR@$5h__IQYcB7d5~v+DhHrs~Yx&Y!_tpW&0+%`?dcoDr z1b~5zs0YrU5%j~1U`={P$7h7SK&=q`UBfUbbjS*|nHuz;M5v!yp%PM|5(@EZFh_CA z3?xELT+bi&V%b(MS3N+kC;i^LZof5JzI7APn2eznE!%1u?((gTEAqt&B#kQyUC`6# zDk+MN+WJCiA9p4Po;@q1jjQtGD|0I`LUWqXN@PomtwTsAneAnmw*xzmh%0qV2UizZ zXc8dpvBdzT&gw;QWi{X$mbnv<`3(D0JTvh0@?LZ5xnuRLBL5{P#l^!)%8JKah|Zkn zs(0U=>#4n&`_h{c<{)3g!g!)#E6R5eiA^rjJ}_EpUWFP6*1Xe)lm@$YGP9bOQ|(a-eDnLy{z87$*5BFb(6b6;zV~ zu@iVRplsaQmVErMjNUG8K>%1p&e_muL)Q#Jp~cX39=QF&DRF3MwopG!N*~ zVyT%dzrX`ASu+U`@opyhtNkb7*59WN^uyX_9G;`Rwau_Ol~q_zuc9Kja65Y$!;|$g zCM5PUCM5PUCM5PUCR_@gVAnvJha%XnVSE=uW$p?c-9d=GGd2|!WEi1miE#ZwhrSA)f~WBdeF1QOq0|wB5syeCG(TpbCdMQclwvod#EmHdR&d6x{sdIQpSz*`+zgCt6{guP@aPwya{kWCGY2QXR6qpKPHu7b{gobIA4N^z2 z#^joYij0toj8LFZrx+;9oEKF*ERA7m!EnOP6$-#W(VqjHUoiAT!5oC==x;+Xp5kAK zFkHiM{W^A%(Xqc9nv3?*35-{ZQCv;knrz5^z$-ej9{!fqiLbRq%;h6}ZDeUX&gf4tnce z#$zF#PI$WFp(%y%*&!TYGGPxms@4+HOdzDgKElmmI5 z0r@0{Z>#|L9h=Eg9Z1is5GdC$KFkRyoULjxi7l;Pmdyb|ngfJF(hXPKI`~tZuc~$H z63(s{Z30zbYo$~x9BGE7%cMiJ<3N~N=X*0W@-oIR@p|C>5~m+Zyc?dII$r0Kj=UMB zU#dNfRJj(WdQC{BN=W+@ieojSxJ0RTz?j1`*v@kMzlla2jCfd@RXl`LJcL5d z5>P2_sezJ+=S4W7#%Ob$=X;={X1d0&nG50YeV=C152Jb@o^yA1o#(3EU+AGW7UFRY zrz*>EdS{w zdmG#*_#{g|lq`jM2Rn3PQ052NYk>f9^~k+4s9(RU(zv#>Vz8gKqPDV*I>btikV=hE zn~L^h5M@iU{Z(LFiuNdio$V8cSJ8&-s-i(IZLjdQQ$Sk_6K3q%qkyLv1w7u0l8}m$ zkS^IOZVS?`IG+OACEKK$h)$xMn9Y_CUz0)DISRPcI_VC)KqSUr+9SXY@nwQL@ZvPy z@0lZFpp)lJznJ%=4>XsOi6;7R?G*1H(cDYJKjJIhryJpN3!9d1LMmKB zI3WyQid$u%fbJ%h>As+5UGSfl?yJCOuuqcS(tYWXAP@sdCeA2}AQMsTl%sEAnI)MU zX;ealR6>OO(vYRNi(4FbElyVZQY^;FV%>^&?Q)>3_N7}6eC<7VHIR#aDHa3MPAA@p zq_8sOL*rLmbUp%eV)Vnx^j172-jRY`9`4t#c2+fRg0HPRqn#4AE5+_e&9`vJn!(#q zVjLFZ$;RV$lrD$zGG14}?g#ry*i&FbWg={DuZGPyNAS-q+y>>>EF`2^NJys{6}Q^Z z`Li`)`F?i?(+uK29ZV<7An#!MEN}Jh8OrTy2DLSmW(F1Gag95W-UA5sR%y8w{HR|8rq8W3p}8BBU8ZNHa!p%oxS_tM;4~tywG#Shq+%h0ba4bUGh_ z`x(9}hJF}zcFhK~q4VD#-%h1pjD|+4XLoSi0PZz19Huyn@VJKIQ{OZ3bTh~wLtKp0 z1F#vd2aWi?fLf_u6H@UJ(#l(Lt3a=~MDe-fI2B;hX>?b7CKiDzV=f#@QizXTFMbkD zjd#rD>SLkYT3L8pJ4I-RUNRmCOd>F@EqIW6lr%Nxc2X@{XT?NF#Y9Nw(iHa$yeO{2 z#e`Z41>qd4ON^YWWfar1?GY2sq1HFFTUZTXnX)^OOjJXRsNS%mBBY`s6mlpa#kCkn zYRbkf-Q>(?bJ@n`vexFZ51Pw1;S_yy+1BQ=ZOvudo6B}g?-VU}Pqdfo;`@g2$+6p$ z(r%lck%Yt6q}VMb-eqwQ0aCw9EN(d<4fh3$dliuS-Dq)t1EhY#2%Vdo!p`CNP2D5rH||(bu|B6^ z$Kq(%S$IC>JDwAL>Q6tU`5x>GY{AHIs|KwT$TVoUdC}cf#;(I9z3i?sdF?H=D*X8? zR)*=XSbv`7L>P~M!)9D?5MA1(PH2O)VkM--fRIj*DUK6libIXjxTSdX1+gnzq+@3e zLAx3k#r_dhdrW*~f8Kd4brDC}%FGGxfHTO-w|w4t+-jvW2Ude@NVmyD_kk*3Qhpzh z4uN8)fGG$;ekNM2Y1p*l;F=q)jcMpMdg#`tpB zx5kauwl_N6BkIs|T|wJJ?;t2}fqY3N$qXl?b^MxL5y!bOd%iam7?2b}Lgw{>Kz z5IfC(72H4zO#;*^xEU6@0nodG<6MhEzW}6M*d!?KH4D9MUB3pTVPt}Xa%N4U(D8uO zbub|1H^RD3vrwIN<#*LJw7USQ-(?nh-nx>%^81H%-Dx2nm{Qkc0BKx!d`dZ=Z=tc) z^#_2sl8eJ+fKu0k_rbLoX?E+u%g_zMr>4@@gY?4=-A%CjrK$(X)HOLS;CSmnF1XH) z*Mst!vL0lZTy^wzFwa2q&v;bxz&WG^JOFpq>QjVnwxDvYq(sBjM2->A?JX*l3`i2;f6H7YJT z(WWrnl`3v1u9r9R;JVdZZBqOV3d3u`!!X^pYCxtF;rl??j7J%4reUKMBq0?fA)Sj> z+)_hl`c-)^mTlwy#uv-BtF?ocblbU^3-@~Pc8aVFG$@_en(T;g{R+5kcYFIu{B85r zC7ybuaaEqD7U66RR}{id6j17nhZ<1yZh)2w1P zl80uaT|6lAcw%@hc)S^R5;BT$=ntFmIMZYtl~qdsApj-=!NBoi)L6gaH%uw61eVahS3j& zH384)RMpn5W|;Kel9x1ww-}E%!>(hOjd<9M$IndHEd$k;W*8yOFhZJPierW;E^UV8 zSHy=S?oBMrx%^@AL59U63-gD^hYl9szPvmNG137-4?ueM@eGS&Bdxem7B|k~>H%p^ zM*x)|tzju{{`G_F;kv6iO+S?KWq3yIeokxNx%Io$`GP=TW9EkGq>!EX{9+jUH@b`)AHK8-10O>x+&Mg%)))@0o@k}O1-yGGgz>%g2 z&x`HJTF@E8taYnG=H&sYh7b&+1&=o?k3!Zl+#awQc2AR)y!1n}l8|O4p^)=1s1&!@ zK<*G?m&@pw_LNaWl)j7_qExy3-&96d1vB#a@2ZS`ia|BY=)Yj!4||6hWUsdwOGq=8 zkd{%!v5YDXWfUjhWGomh^W0B(kru{S`3`&PcoRH1C{8jR?P>UA1CHKW(E}75x`btI zHFe!M5OgdoZdJwxFxTK%fNJsh3lRN~2KzXimxFRYQRGghL9<)KI)>MR$6J`rMd4u_ zM#5%1Mw`O)7b|l@Dsw{GcT^nvj*3gwcPunZAIaA}nlaaklb+~2au}g~kP40*ToCiX z2IK;Qz1@{}>DsItkb~t--ou*1MO8CK7-k`k0(9I^1L)6^ll6e8E6GOz*TJ3t4czeyM%OES#hfkoxj%@pDE#)Iy=MSL8H;j z%7{057!V2>%Hmirnq>L5AH?fkr3K{te;iAqkm0Sz@d7~-EkUN;-tiQY!z|=OC*uC9`zP4U!!Cl5?i;M z905w*t=!Jp!bSDRo_&+G;@5yfE(9ab2?j`G@$N;>f{6H=6B; zYZtun{Zl-*;PIDa`r*i)jX=d{rLs38Ru(YGxtA+e6->wq`6NhLB+p#(#5`-Wz!t^*aeI~&SZ|vOQOZ)#-(WLdAHrtVykfJ4kY)`b zEtra1W$65Esw-u7L|Zc&cn5JtM+rHl*&Ja;lVq=0oFe z{T>0%f2$S!ux8>2bEtRkT-$q|-8+{0^_!?)qb{tfo>7gj&Q1kT-%vM)pBO%-jsC4W zr}L*m&t4tGg~C1t^@)}PLMm)R9Uxe4Lf6x!9U<7;5Ly2ge6L{VF$cv!tJ7@3?*KUl zw%{LXg-A$+NT>sZsHYb?N;{h%pbB4G?iJ!?J|Wt>uR1_#$?n41-wKY93XV_*2u`=y zca-4nh2W;85nTDM7V8cW=+?quaqeLSN=OAtr~?Gb9r_(toY{jLl}4a1b7D#iinH&e zLWfj_3FjEJF6?cEM@WT7r~`z@ZTuZ4yk-byWE$bk^%mpA(+M3SyQ4~jn%560)P{tR z3XhNoZ!{*58aHJ$m*vkp825FT=j+$|%3;ky*#N68YhevWr#y3@O)TiG zaXSFoDROTt$pjh~5}>))!^m?$KVd?>yfcao@;+1E!+`(1AKjtU(-0>;UAE6p z+s+Un6)T~T^H<}V>%4EEfS$??pT$L;Pb|xy%K^p7@yto5z?D^1Y~L#<>sg$3c7CkReh*p0?lY%=+%No;4xT9=-a#KZeu#WlEiMsv z9e9R>8CZ;`s(Mz#G|3{4ODpiWhH2n!PlXp3 z>xmXR3y?OtQvoTzTL4k3!_H6f%PFz2^Gp0LK-%ze3qX49KIe#wCA|#&8gXST8wFx& zt`#T?vGVufC>@p!SDsIyTY4IrYtnv-=Ulj#``Q=!VdF@9pm#`YH-L?5sF~5P-{i^} zljqF9($Bz}DN{=3)zp{FoI0agDp&^T8V04tzawmKCy$M@Yj)}NKx`e$flsq_tgdoq z{gm3eON!9>OW0H9I`oo-M2evaKVhd5@kI+-ARYGKC`zKA4;+=d7^DX{Gpc8bN9tq@ zvOB;LjpSZ7s_YwzqJHYMHv5v-<8cjTn2+3H-|-5A#7wtzJ}!qnN%0YGS-lePq>14F z2e7Y!eLHOEY=q;4YhmwzeI4u&_<}}GAtAg7YFD}Eq_=9`>dyV*BdDWV<4fH`!pZAUTV0ng#VNZMd_hh& zTe@8GWBj;n*;3h!85?!KWr!Pr7gk6G%RLbI{#4Q$I!T=-3+^i+3Ncg*su|5vz^?k^ z!$c??qISLDln45-ECDGr5IF9t(yEO62*SKx+FS$7i53br%(J{^2L|_bDcu`@u7qp0 z^A;ejG`0Y`N^si&T`drY91(?p^H&x7!F3k!ZkLa@S|01ftBO*%`!DgO9}d82_v!*b z4Epw|stSCQsdjQr!+fbF7@BKbF*yzw{dcJ<@DcBN&9Fa8GqbE154NG!Tv9!vp?a3H zpQ#Ly-A3<9BRC_7dW*+BF+ z$l1s!%C!zQVD9pb%!dt)h};5uE^I7~+6%{zgnupKgtUkg3d!zh=6 z93b?*^Gr&3L)J~}^A=+MNL_HYAq6o$)taZo>o3{vTVK`tNO{~i?DR%d6*}KS*!W>^ z6k_Vp7<&gfc&H3C{pGM$xM4fK-WNpsZ$??6P;@aDO8bMrBZUtpr7vssq(+v;JdTc9W{5Qa68s37< zaCSnPs#1hhr3i)Odnbz9YUqp#4!8NRmtfz*pl1!j<~AYhLa?#UA97De>jA4m-6hfd-s4cXS3!O*#pY*s#zTd z19>%h`x)MgEK{9tYr(rWXJ185GOn9pGrk|0oaMGJ%~?X4vxGu2>Q~%G&?`<>$n%o# z3`O=nOKDyFCHAJ7;|%3HHe~f$pCkAce<$9S=}~a%y*_7s*>-V#?eF5KAHIi9h`;q^ z+hniQ#jj_2_c_hU*^pJRJ}>*76^T1RpU=Ydh}%^^8<2M2Cj-(hJu@-23OoQ;DmxQF z!#&)G;muWn%YZx8rvmhI7@mcAdKBPC3<|t=8x*ualz_}#;|9VeF0KSuqYG*G=(Bo| z}F)CW-}qpWK{UPsC-@P&eF`+hO+Gm zn^IOD2mDJ2DD0dB=xD?>n-|rlDGZ$Y^|nu}4-W*60%Lu6H6H(|75X8~8FcfG6}^RF zYIQ?=Xy^?Ao{aHkMM8<-iJ@W;ncfq#qOb8oi{bls4c(6dz&LSIw;${WVKaUYnS$|8 znHV+oc}vh3xcilcVfvM3j*(8Tl@1}54k0~^ zptxo5uek40I+dyQW|yRspg8T64jL;dQXJZ=?hsPx5K`$Vj?z(F66qB0uI{j|KG)Y= zdUa>kK_C!=%4S4EWkb#6iW!wNt4B<$oK-D_OJ1==Ti;MQQ~NS)YtjfT^V@r*0;>WH zpT^s4_JyRV&!@qrI-|Z8$(?B>M@S_{Nb6|DtpdH`l1Og1OWl>=>YwKDO0Kqjk~


    T8k~`T*4tH}Hog<`@Bczg393`hXNUm|q(9t~9ymUEQ z4tFwc>;r&xF)3RnZtn@cgXYb}m`#B{py?PKv-iEWrSq0f5mxZ1Lq_KY*kjDNMKpOjZEc7KH<&uqbDa0?{D|C*9>Mhi0A%3C$eZ(>B{2fpk zIAuE@0n!=#uK^VU7k0QGP3JJefX)`WLO|yT1RyXLITpyFz|)Q9Zgl*Q#^8?cpW+#d zQ2mEO=;vs-(H`RMJb7;K#aLu`Eqe>Kx{-omxF*L1oWdsk4BrkY5pRC*P0*)*<>VL# zeRdwy9gts+=4m!2>v9XWnK5BQUFGCznN6d*7UiS!K~>$~$+Xem0|~uKBSt>!jZcmy zxhE=4$V!+q+At(s3&IA#)8%cAdAnHNR$C^dTxZ;PJ!>`|`?a_h@-l`pT@0AxucZcu z5V|E3ulT}%9Bsnsk;sFf!Gdt)cd-8mn{)lp=14AL2tAIR0~;kE(g+)i!V$(C zXE-CLBNbRhiVTJQ7VPn`H^N>88*4=oOz!eCX^}0kTVbC79m70Xqz3kTupfc_0qj=T ze}~N(3@)5&Czg$@Lb{|#?beT;5(>#Bk;)JAR}w}@ z7NZq+p2cAYm$>F~ua==pwWL_YZp_-{jI>!(9E+(e9F~;|KUUUiC!+NLt-XLHSWBYc z%~P~lNh`$Jvd94WplqILBoyW)#q!;%Fh5)83_&XK<$6F`nlZ|Dm@C<`3|uY{OXC-K zy5VunH2{k6(2eE*^oo1pjqfbEzrf=!x%AT$5A8`-^#ijA2_=_dxW*03advs_jjLQN z=Dtf^SRQq`e6}eP98?y&0m5cn7vfDugmD?+e&2^kYS6NS-Y6NXf){dwk`e z#nglCqGi`?!HT+DpvEs_uMaai9Vj@~TpHQ|;GnL@16nQohTvCS zFSV}M0OAJNuyYrFwYQ1MXVYhW9FX=!mjU_^Pgtl~S`VPz8Rk5Qur=Z+B+Fr4@L$CK!s|)`?EM z-T5hE;{Ut`{hSCtv}Yd)K#aHD(T!r*fnPlpCorn*^sUT`v>FezTs7H^CMbP((&x&p z9yth4w~bAnQzuc9T^;N;aM361V5`Sm?CRkD52~Xgv8#hfGN6o#@p$%%90qh3puUFK zaAMn4-gtu9P*T^mRTPCj2q>z&qO2b(JgH|{C)skw*enBz0UzK@(FK*1n@nW#jpHuY zFpu*2071>C>4Dmw`G;A%$RyaO!k!Krb#-J8Y)-~q4;$qzau@8gU@wMU3OgVAFc9{> zu+M>ABl_V)o`H>?P=pKcLt$@%T@L$m*yqFUgg8{drnHX$tgQ?oZDk0B9B#CrCg)1) zO-R?vsMEP}w>+T`uX+&e&gJC}0)?D60a4F$Wj7R|kn=a-SVnT4%?8r;o@FW5*$x~b zY;8a+H7+cJ8kgj)TjQ3A>}}q^oVo7lZBEaa-f6lMzqVz=__cWLgg<+e%ZBl56yZg! zj+L!NO}z%qz-sI`j(1skN2J+6quZ8sPRwoSbmD6rg3UlUmUeylx((x3Nyxyv90c3q zaz|?-^I)7XDSL*IX4DgCmq|qZe3vHWu!L!3ED|_8E?oV57boTLaIAb4(%*tM_8G`x z8Q`UWmjHeo@M6FZ+m1qXKu)Sw2i^7*QyG(MWy>9RuY{?VvdbmxOtcVY?#S&kXH7eTijmor>>mR&`FDvEsl+cx^h6Sjl!*fKEo51 z0nZ?)Ww!GO-nFu4@fs{RHb3VIl&m`Ep5%#$gxsig+w6My`#=~v{O{Xj!W?)(+f}w_!1^ZUm*{~mhy%%gY+#%Skrv3$3 zt0_WSO%Vz?tQ46Cxiat|q*WJlNUJVFT6Hlewdx`ia>C%C{JIz@-CkK#H3^$#$3B3d z?fiVKtOY|`GtFAQ9iJ~naj`pFbFj0u1!ZWV?Z{yxE%wF6FCa})knAL(9SM7i6gzW8 zi~tNYLhkF($-!b^zD9b&a-!}nfhtLcG>0*L18EC{p`3Fbplt4LHoCnKP_ei^4Cs7u zT>_{=pk!LU46d{AxZ1}ptKREPpMjfS%ju^t9@0hbwoZ|8fnyKKFs%|K!Ox<;A#?>{9Go{3M^e{+F5k*MzEbM`>pMyOQb_;B3 zFB^T;UP7w9ghI}vaHVW>Wg>@A$oUm;lzgt-ph8G*Lt?d5&C9EQ0n-$t9@SLGZh%1T!Z zYnglld-Zq#a5}JHD}gCBXfO3R19H%f+5aUt>al8c6wolZW=jrfZGA6rs?kdT4HsAH z}}SKBn-qgjEI_! zR%`cGOLIy?YVCN%?zt$R@plc=u@DcV$keyVFAH3xh z5gX9Wq9cWXN)TG|3--FhHJ$+&NagDe58^(>!;JE88={|m@EnZi1k`zIkmKH6S2(&d zwP9NCb}m8NO;>KcQ{=LR&G7u&4vR58%s7<5W;}2_KyuAgfu4z>3$i-Ed{;e zc14=n2P20+bhkVLi%bTO}mY7*Fja@j?z?|Pnu@jFwC=GFi}VMg-_-~SZ=PxLIfa6Bei^)j&#~u z3wM8uOFz_ojRQu!*5@>SgK z$d@_Oaq^vkxcE0Dd*%DHd=Q8U>Tf%Ro1ng&{33tX5N^Ta)!iH;Ta0x?wjm?iwN|!- zRJMddauh{zOTbHUkSz|81h&4qgGp?0<>3JLHF2-&_rQfY6n2gS^szvF0HxMrjsQNwGIycYfb6rKs+2Ho$ehUd23z0jH2c;9U^&yfG=abv-GtX^~ASK1$3EV`gOS+ z@?|_Gz-C-3jl4N|p}I^+r{D?{Hu+&#K?9w(pyNR&? zYqAtOXYFcr8)UL3jd56r$E(N~-b<5q2W-aePT1^Ra5h;5OGpJvNV~?0TW#pf9`59m zL+-8&D06&;;G#0T6qNBoolRhZDH)xX*+%Tvq}VMo~5AG?LvRzG$Vu^atZ z;jrG16%N?ElNev&u-1=cs?Ut`L!`z3#Gm56?eu7yt6%QL17 zpQpo=6<@KvW?UII`{-g1UB{{GQp<-N6ZkBl6K1`}l;OK`1!a#LK4X;6V&ghaT_5Hv zqB4ei*b@2NujA@xFxXy(0SS+kE&=>F;KhI+mO;2%V@+sWH8Ekg&0$EIHomO1bb~&N z`(LH{8V;ycplN`xMvuykgAJ_G1G>#ZKeJE^Aoa@`P=&Tw2ptT=kJAmxxhEjy%=LDi z*uu382Esl81MLT0{}OLu=TJbYE7k6Born z4!+HsFRxo%+Io5Yz`R~MPhMA<*UK)G*R8H!CEnz^>MKV*uzCD$BnL|a$4(h z(pPuC$$Wiv=fUQ=7ve~xF%i67Lzynd%U*a!8szJ!%P8kR!9E)H8?ZT`%0=UG8SFgR z&%oXr_BXKifsHP{gZcdk^9BPTsSCdXPU}KKS{D)u@nR20ad#Llpp8z2PvW*xPX1<(Yo{{5t0HhZm3W>X>bD z5_K#^r=M}~w>Ox8k@n^%uo*YxnaH>^aYNpg+lDMRu{Y`tP*S@CZ zZa^TjD(e~sR~2C)Ot11Hu4ZOc^}Hg-ZOyxDWaO9e|19sZ zGTivU58I8(86Mx0Y!!4ObSJZg^Na(6GE}dj$vikl{RSDOf7#I$w#qxUWjgaw4uuTxeb|Q(`8Xu9qn>3!A)NCYmBm zPBCz#dD-r5inS+!Zn3e(&X%l9t_{lj1;|kFd?ghV});*=SsIomK;xac=610Rk2JR(H6!A$xs}xN4PduLnpVz$F1fBUSr` z@#c~MAIY|)mjUQH`pJl>LPISy8j!BRbDmONxh+#y?W2HFw+4&gN+D5cX#7_NTn?On zW|@9C%)1uPP;VvR8Qe7Bs(^XYsJp5NVjD{0uqLo4KFuL@hRqroCBU{|HOOejXF6=g z>0*=dJ8Z@i(u^mh+dUQ60(!-v5pUe`KQZIY_6kHap7DxH%y`9pR~cWPCgb%Uq;Egt zFEJTE(`0Vv3Wn)#G~US6Uc@%o zTtfd6Hft z4rg!iDKvJwwBNv~+jZgydTg#tN)LbKoatR1S6cWhU+enAm-bTn!_@K^%qJIk&p(?1 zXuBi0#tkT41Ub9xi=d_&2}>72PK8SZx9z?J^@w&G62#26KZ1I;pp6J(!d@e&=dgDx zi=Sza1hEw0kKi)bUpfimkcUQa%kE3i992%QgIJC5M{r4dB8a65jo_x;kKp5OKd~C|v|^3r29E>n~jd7rGH#@4cQcR<;FeT$`}Q^?});w-NAq z@3nmsFg%;(S@X(~%_Z9YavZALtK%*47~s^k%DP@`aSJVUk9B>>;<$ZF{k~ycIcn9G z{cG#W1Hl?DRy>SrFF@+|4C^}3x=y#QbFJ%@fV5X|mvw#Ax;|lD8M<#hecZb8{s#5?oW*Ul&?f8piN*0G zl!jXfNc|pTape{oYh5P-QfXXiU7M{dw=bycudM3|>$=*y{?kJLvaT8E(x@~J1*BY# z1EjI)WnD*G*Gbm3#=72YUGKK84+7FuK4)G3U|nCgu3uT#OiVCoxFJC5w+N8Ns=sv| zU~v;IG{d^qTihKMdf2)?W^o?_`V5*9c6Iyp$clSTq|PXRsauiiMDhg^-FxaTJT!{w>wgM7To?*sf|Yrj`Ou->he}Rh`ueMzc5l;1*DcxLMk;vDmBGXYKj|)0dzGUEUG)$ zzqu0*)+S7I#2&XE1m~27u^PZppyFf>bi!)$^FJv&F$6a)KkYzt!XH%tH#np4L+kAJ*qY&58POh9$S=YU&XVJ08hLD0pvsmIo2^=60N20%lP%xhKncrB-!z^W2fqaDa zb*uHkEwtG(s8-&TvqDtD zbDicEFMbJ1f?Sw_$1L5?6X<%LRWe$>w{AWaUR+EcGB}SjbCr^eo=WiUEKPg`fva!D zfL)`Zv;USDy6aAx%%2u+l=JTr_}W-D)XbbyJEtC(6EnWGGiKD(<3hsXV)%f;XgMBf zFc3q&EeYHNy;4wArg#$EbS6uJMvX~GjG8brKMd+6;mahfNeC2480FtQTU@LjQ^xz% z1QtU4x}X^EH>_j2cx!wZ@5K0!S+aDl7p|m#+wvzZ<3GH*e$I@B;znc%a^gLj@yzlhM!b1`Nc@2iQ>Y&%cvGQvKy3bz zz}ERV@fG1F6P3n_qDqVv5Y{mEDpJNiQKXg#0O`K8sr))2eARy6N7Rdp)q6_a*^$6Q zh<6H#x)V>Jnf9XaeGy-)tZ;I*JP(2UxQ(`c&2|oV?0&dYd^ycT~Y!b>AX}Zl5 z8kUL7jG6f5@MOW%**yiVGzy|?LYgxCGK_zn*aP#3OshBTjBRE{KC+jg((EaaH$FTi zl9_QReyIiTjQjKEARjivnHj73i-%^f03XJ*Ek0E6%#0=c#Y2-D;6rg_W=y~@)3xA@ zm+|XQ7bgNTGiG?wwReCIb09P0SNz3Ox^g}=z|V)p5qaw2(>cJ0a}Ajpy$qkPE_xJV z@blSMXx8D^m2*LW53&b*nCHxu6K?r@PLK~fahVy@5FbjDX1_QeqZ|7Jo0)MWekq>| z51sja4-GIh2jI!fm?SW6^nIY;reIh+LYkRT=t=tl@vw|fmU<0~h!G3Ujs^K}3OqAo z8-CricM0&}>6Xk4#+>H9*WX9U^vm#jaLLTrh+mh_!2v#;hRDn~4ZrkVdE4QS1o?0h zG&6%2Hn@Dc2KZ3hGc!&wd`29)4wK|aj!%#5x0b@?0-;L}ZLhT@le?rwf{S&+|BLgVGr zEx_k!q3O+EJl&7EYDSO`Q=OUN)%l|Xe7Xw_C$5kk&iu#+IAY6~dF!ZSg{GS)zq$wb zaNky2`g6R{c;$RtfKLyhp{6lD8^62-nd6TSwIWf@Jpz1K9cN}x+VtIW$9+Eu@;Omx z*6UiL1#5%Mj4ThIz5zb{ zgoZT(P05r4cLd|ZeF%y9-Y>wXztFgR_T73Hs&aq2&JY@}9`+CLVTUL)BR!w9gk~dt zUHP0D;8QF#$0F@)IZnNN|JlL#lnBiS_;vXd2l$i<&3#D95rFzlI}j@1PuG9|pV9!I zfkJa6e(8JVrI}v_`IHGwD}LSh3=Hr&TWD^@FZq>0G>LW?YY7WVq9F-l5}ye1-^3D}LShoEzZ7nmIEg zVrbU>y9FHwznsg3h82{{XJ~-Wc|yaQfxesnn)mx4AC{U#eLgS1r$T6+G<-fReKJYk zZ33xuW>zpk7|2l$K;n(GYB#NU1WT#(OLq1oo)GbX_2LZNvIzckM; zf3`Wu=lgI;?6+JP-~+V-%?)G%v!-Q#u=MNCc(^3?X~zZlTqHEuNFbw#7dBpk?zW!~ zP~gM*c~3wz7X|oC1U556N+O`}W5=U{^z*3{8gGANVt~&ip^=&s(CSBTK&QaZXR^?= z@)r-yqyV2PU^6q)^QjgZZ@XL-;4`Hie5MLb3xDy@ObPIr25ejLsSz5s7cQS^0Y1~) z!RKP3S>@p~J-}y1JNU4+%*^oenGxVKQ)t)|U@o=Z@jf~-{`{&H8gIVO4DgvHG!6Kr zIpBzA7YF&wh6~2;p89ZBfKQ#!u%<#s!-;(O-n&6Q^+Mx~PhEfyW1{^rre^19-y9U= zGe>Az@axta4FNuLg@*mQ)O;=#nil-JeC7uD%oCdQeC7+yS`VLj0X{70nHjup^bkOw zk390LV7e|BnlK`~Hz1nJ0(`CjHZx;C@FC5^oA=on(LT`I|mC!We zmoCR#(fmS?&(%WH6?|OzTovFG5gKYEX(k-}dsL!+JzO9(-Z6e8z~>sFc>upzc%H1D zH8RMDvCYibf?qd2*97=nD>N)+G$;4?I~2+vpC-6uW^BT*%jenvAGSD|8PcNwR2S~^ zQjpINgl4;k&vgMl*9*=5_@zlc?nYCDu)O+neSi;JoVLba(Ey(t0(@>1nlAXInbdDQ z1m>4d3@(ZNgc}2VZW5aGd~Oc#xhcSBVFI5g-ntpe>yOVZLgTGB76$nIFo93uhgSXKlQ>@OM>yaS7^q0(sfUO&wWC(48I{f(pI5gb)xByyOXyyiCH&SECRrhFEH;T8k}OtN5te7T+&GtXOFUYb#jWqN1Wui;9+C zY5l+N%!M&aS!{>h+<< zoA7Jv`CWt_#yWbUuh(H}6{crXgr47bLC>oZdVU|FXR}Ao{ku|gBFpuM2tAu4^!%|4 zdQgR7<@#fUo-M*N5WhSgzTzb~<8V7~MU2VlrXM(BCVl<-8v z@u;`b#UAQ~?+UY#e07RnA|Y;K^&)OS@nG|zVbKUS))~m?saDV%ibpnjD&#Llk7lv9 zIeIkomLTLWRzmX2T2-5J87?$Dc7|FEaxEEf%s0q#1z1f6S*4LP48l>9$6$l7fAW}N zkPj7L%`yn@BJfyZkaUgQW03PTvc@1&H1d0c@Xj=kKN@7QMqW1vpB&^d(jdRq$b|;k zq>-l$!dJ@kXf;TRG9}*hXt#vZHBxMlF&Zf`NV!JF803156c}W+My48s&k*t$V34;o zvdJKyX=JlOe4Mo5*kX{AHS#-y+^d>6xgkvB4mNHL}Ve<2AC;AoDfy ztU-RRk>?GvNh9kF@~K9yGl-v4D;yUYWTZyM8Dx$|0tWfMMou-z&oq)@kUweUWP|)m zBO?sbCrPC~%^)K*GQl8a8oALRH*4f3gFK^=s%1o>3a9HppczshYTc=-Ik++sY6waPg?v zJ2leN==l$jR{ zL-H6zq}CY(g!Me^LzkF{x`?-iG%qxJE#C%;JC9_-G3bk>zg842b{@!C7{57aDI1Oe zHOGw%C-*$@Et=u2=n}X55hbz zGzd{ zIsMh6x(;$T5T>pWcUoACLt1Cy7v{6}yz}q-)Q(o1SpAPyQo=*P8U=)hLWVRMw_*JQ zXnY(kz#}(s%UowRP@|>D)5CI0?Es>@jj{<&aeK=km5leNIBJIeF((a{kS9hhF8d;j+?aMCuIuGKar?>{#Kz4~~AvsE|C~wEhXivBtH%P8sc_b%B;5k5}pwk>W){ zWDd);6nVT-{}L(N8ncc%fF*NVzD-M!$16pDhkZ?g<3|o#>Ni@7Jdko(<5M8^z(F3b)IK0i+wfXrpq3(! zSLzFol($7)sHMmQDVH_A6scVN(i*>8>PO|+HoRI(k;j|XzeUQnhPS8uR!fn`E45#w zqW6>!wG?^0QvWAX(QEm*;}D61Jl=AB1tdO>gCNV5x#OH6&T8cd0w7v%7w0Up2 zuGUiI@k$*Ksp#ceqov5>mHLlJ*=^oiUw_t8HOFysg>J~7J#$Djn!{z#mbDalY-=d4ULL7mXAbXer({_HEkz!$6la9-aV$HJ z$M&r~$&o77QsnVU;gftWsVi>?KHx~r(o*E{O8GoeQ|o&SbEF!z6nVT-_>zz-t(gU* zu6LwbwG?^0QYjv(3(l^7+>u(LrO4xz!dHr1X}z)fjXFnawU#1}SBmp&$AIxR&Wuaw^-)wp5BR!3@!mLiW=D%B%3b@ix-6@$wMLD~4qTc?7Qt)k8WGu4Q;+vCjKZ_~xPKHt zd{Gf%ah~7M>^_}bQ|~^_!>uIed{n0SnnprHQJYj`|!qN1Y3EDQsY2?{KV4qp`=9yQvXr##qR zlz8FM!D6M`{?LR+S6**Wmw?p6;O5AKpe%MXil`&BZ zPCZ0$*iAAgT&XUO9iQioXUoIeG)$iw$DF%bk2f9FVkt--;Dus$(Wx2+ zjUh1_{(vv`2$yKF-x?p5f_4$Ch8nzDqp6vd4Ta>9U$(2hl&b4of=DH9UF5uN0uE}@`^YKA% zLk)w&mCL!wt0aX+A1S1>jJE5I3v0V2-gv2CSDhd=RfD4ny2yyuIJ&I4rWq!WNZ3(Z~+DQm`r&WuZ;u@M5CEJ`~J1!KlF zRlyFZx2X+H4fPE*lQCc%MuyK4{UbJ~7F5gp9;`<4>M# zM3)gV^P;_D$L=YeC}SauS%IqL@;%EyAhVb*G^;J4M)Q5R^1#5p|_4vBRvI-iulVYJxLldN7x{Z`cGv%Xl&Fg$r zIS2*RR7|yvSf)2kMK_5~_`+LA7g*sLq`;+%8aW7=R}5(@Od1^=#}C*o-XL~s>{n$*ECtCs=D&7BU3+_ha~3e>4zkTajM5P=Z;Ih@#*Hf~>ISa^OGKn-7aRS{ZE3pM zXuRk-Q`~%qQX}v$x*22#q%`9T_)?~Vrm_WrKxl$EMjAg_x*kh+$^f%^zeVf}Rv2=` zUAVtVjBHV=KXnd>g*&W`ZIp)3ub9*H--xQmdNd zD%$^`mLdxHze&?w%-EG3p1Dpqv67x22xX4DI8a!8@#w;d`FR2L3f)n|Dn@0G8miu+ zJ8CFiqdRJt^B&z%LjzdY4xMXXgQ(f~@X;zeM-la zU?swRg<->)5wD)bAOaJVWPAA)I5ZlVl@}P5nHLD=VZd@Hp+r==2eDd-$wn+jPp)Dy zxii^0PgtHiXGRfXSrz$?@t(NCA zIY*Q8p(92JWS?i}C=PR8HX=J~=oFtgdwUtG(&z zzH-6#3_FgMs`A2KMQUUR^1b;>8_L&M5pYy(6qD*pYIw|J}SefhG@1kK0@854v zx2#~pKK>pA z&j*^1yIIns=qrG}ufTKRsgzQ?N2BTE`^g)@bH?e4uRnrl`uNOXBDNa#JxlTNF{o(z zzCyawz*B;KSvc zy@mXJ0iM^eLxo3Q{6))OB@$XZ9IxmeA#C!Ld$jW20)11?17EJg7fs)C=$nGdd*=eh zcO-&n`rZLvaiL`uu;4gS@fS_s8^AvS&xQa99P#*zrmr9H9Rd8fj%fO}A^wX1_TuL$ z##r_{4bk6#=hV@P55dk#Fg zmnyzR2%^>RiUfSUaVGp=x#DAYkJetW0p2>H5^spaACFl1D@1wk1kXoRiZ53Eu0h{8 zt{VOF=ZbG413Za&7K7*;dJjRpAQ0d?TZ44BbbP{nsW zc-kWP+#4Yk-w!m87S;M9`F_+zzT3LU_tP%&{k)5Ozvv?0eO=^xu#0?;bdm43UEt$* z@k9h)aR5_?a|(iE@}?A)7LFgCdvej_sreXWW^e2b#H#}0 z=tZsk+!+N^G{uB*AJ~LWAM`La!g`W?ptZAAdOVs$d zO&3`P@~uADeX z#PAb0c6?E&v}AnVgt3Le++4|YWfcoh#*H?iIb}_ip%&axl~0<9F|{bu(nni7UWJvL zdH`R5=npq>q?IC8*0G(Rrdp|~`yu#9fY0W)%&BR{K%AP&l05+^&1z_w0~;IzECtw; zf>o%6^N@7RqY<_D>u4%U8ib!B><8xlC{+t+bvXMVj|;;+nI9LBVl=^CuP-jxPx6nEpDZ2V%yQOq@_^B$84K(IaqYv8=X=*DImsmZo_XEwENn z>YtCo3-O%&EO@b0Qfh}_&i(_;zmig)g9>xAQP|cackVWT$GMVHF9I9xL*sg-vaVbf zC-Hfaq}1awV4|vu>}phTQfe-kLZP~>p(F5Z#iY~|nY-G`n)#s?)LK$%tt7>Ju$2?b zufSI~tmA>+kK_u*PcF@ykgtmz$}R|vnKB{YIt9_JLw9aM`FVx;QwsA+$4{I9I)7Xc zFPVmJo$1jNr-k@eT9P+m@|cMwMVjYC@X+j4V(!rR38lf3$-#WlQhI4|5S=h7wZ=A3 zfA4$NR>YGzyP1*!NO^095H$U4W;B^ z8=CG|+De&NPjreak7hWQmKX zo}3l$|N6WSrVT&({cC=mJ-+Ndyh=mx8E5@4<;(N7X7nrAbKc(ErI_mR^(p?iW0wE> zmusizrd;`t-p_7+!sbznA;l8A6n!dd1XiVuYLJRfB)z_Z!oAdiE zykqzoM}2bJ( z5xnod=Ko$&d&TuvgqA0s-tkF2UJQ>s`Qx$&9W^p_)=SA7|8QmU)sOvsGwdw*!s~y! zf84IuPT2q3!8ckLB^KfmOYpb;_QZ_WOC~*Xf60Y`#G0zpFx~D&J=>0Z;=P*k$5!mL zW;DLN@~ZuKlvnU0=D&O4lG|P$(et95x8|Jo@He!s|l$ELx(Osab?qj z7hune1^?N=a{~VI{~mqhj~cAp*6HZ_KN9@+e?B(&%MZSKGr8&7>BlZyf_nL@;8uRW z;Pi{G`}%^!5C3~x+A|Hf96N&gOPB9GW!IWN`=|eL__Na|w*u$OK>Tq--ucDerR#FW zytBCE&9ATK)v$Cv*LV;<%d{acHYQK+G@O6?wN{*KG2KEW8O!#5be3MoYv&z z?QpbIG__P#RqGl%97WA#wTE9O%&4*PqN%FBVv*7JopqIp+M32tV?*tt*$wrFpY{1= z-DAgU&e#q=JE+$MO}bd$nFYNUm=%qUhwY6$J*9=4{Hw7ANSWiXis4a=uG3VrFneKk zcPqwR6(5i6cC~di^>t+n55G|~FHn!U4XLTG?cS;?tF4(`UsZ{x>u_ZV6Lf=NI~(OV z=7f09tQ#B`HkcvP-C*37%G#Rp!`D-bm6w)oC|6Y-nhn}{H~2Q(f$J_+UQONCrLQ!P znsr0d^EeA=u3UgibLh<|%}mdzDsN1`06|S-I?r>`&rH8u0N@1FNwYc`f!GVu(=%{y zQZb(`@g7a3SyZ~vQJUpex)6d{Zlzi2N~vT-ewZSX$dM$nGKXiTM@i*S^6Saop$M8> zoHz7v^I&W?90gP5G1`X@9no#-huYRM+D&>MGjvxisfLi9Z5zlWo1Hzp`wC^-$I))5 z=PA@7)~(LFt;$i}eK|Lc*C-!uSHG;E<8l+L*M+II8F*bB=;`?DWevcp1gT_epr(A* zRiJQz4eUBi`K)E2xDt|Vb!f^bD;l+etpY~MXC+~ELh0jeW>P+@7!)o>A$iK=fy9xk-x&S;u8+@|y!EbkDRF2Qt6cF99|gnCWyQaeI}mW8 znU$3}q!C*#KKnGzYW<#tzsc=yFW!^1c<0{58xy9q&rMiXn~~7I=lVTdLBC{D$8$Td zVEq*D6h65b$L9}TdKWTjWxup6cwkx4{*DeVXzwD_o}W_OesR*I?Qz=&W;~6>Cu{4w z?fFR^g?|4eIbHuQcwFamUpMFNQ}$2V-UD(^irkKNXfBQOm&ob*9hT>O?mBbsO1`B1 z55*n*m=Vd%wCSPtq667~P+5C_X8U`WZAh{@#>?s#xtMRM2+*#jc-)S+zK_2|D~Mm* ze8dv*M*PkY>W}zk^(R_?!f&NuJMfED5%6(=jZFvZFR&LIR-!efeb3@O{;8LU^_B(q zE(`8k7Thn!JJ4Q~q_Vg71sL0!`whyKBFIy6{tA|sF5H%q1itMv_q$owe`r{rCM!%U ztp07m{ldM^&As(QkKV2CD7D*y`-FF|@QR+fug7l>?%kH*4_&@^qyPLpO3V8*VY+lA zGZlYn7EPq6iw#9XDU3IB6?K!Lerc!|Kvm-}O-vttx9AnbumL3DPmUD4#tvsJBJXZI zj=z~)_nSO{zvBksM~=AYOZU0CY6YU9Y4GVI%{uW}HkETBRQ2^U3-)2MVx_nC zz>0RV+&p?9z}0r#0rCSN%M*jK2FnN71VOf~rO?vYfH{%t?oOty6(RG@ZiPiibI0sV z%W7p=&O*rYoQ;sWX5p`wHBD2=(in;PEG*wiY_fGgQ$9AiNiPQvu)AijyD|7ppT~>7 znbbZdt)xBZFGfoMom8?5?AGFqY3TJ%HNSW&z;gVhS=soFT~XZ8!%DF&bv!&Aot#}! zZ-AZ{R#B884+>>fITfXDeB>97FAfz?EWC8=#0l92v8#p&L>{b~$eK6?bwletE;S+7 z@VJ&ojWpvM$H}S8JD2_S<-Ll+!Wi#d^hJCc;_dvaA~rG8-ZMsY)cJDv^}WN<%YH7zZhZiQgD8^^%TjH$BxGT-y77-p3#G_c^C0 z5NrMsF9-SRLu+?05JcMPUk;Eb&Be3F=Gh}WMSI}4;c(BNa-h$WI}oRIULra{7o~mP zXGW3#^FEia|GZCXa33HYHA5T*!ClgPY%fIxyFTx8X#zY|3Zr*QwDu^XA6hO=fKGqW z&d>Wy+teN$*q*fhorL(J0pKs%5ut7e;Dn@TNx$vrhSy`#Z;Ni7^fpJ;`gfe9sj6t3 zBt2zdyU$7bjR^iXVkW)CNqXzMOnHkt<;{+!t?w{a$}9LPq`7vTdW0#SG z-0n zFCJCHotK6tc;iIz$ZFd}qhgm|+Lk_z_{m^L1RCw+>D?W&6c2Ux#j-mn5!?(}eOJ}oJJN!Q1 zXFq!iRb{~$#CzR<%rN(h^Gg$9+eM2L@W+sn$);OM{JwD=F{C)@bPGvRTi;bFwFmdZ z$6+EYS%>2b?s+-53r4YaAJJa4Yw`NHWktK%r|dd^iobb!dvMqK9SM=;-q|r_Kjt)P z#gn!NcjDRs!5##VmlATGvup9kaqHhrh@X;TPk1oi_=6aOkmBwicLevtmT8k9xz|x3 z7c00pp%kV}i+9E8o4$^fj|5B3bE|;bP+s;!q;J&i$z{e&|gP6l1+#+?0iR8SnPK`gB*ZaB^~Mg0n`B8 zZCQOqRfta>V(dsZ4%6F8(h##(d%)_NCf*;$#u?5}_h_`Cwo)*+3w;==a0JD1Bv^NW zl}0|rge2K=;T3cDqXqT<0BZT(W z0)&?#WLw20V(XU(FGu(d!ZL)+BielHAcU0&Meo6VPzv7oIJz3tPP0D9|j9>PRWa|@6`Q*z3 zO5aALrSyHEsbuS8gYiqkif@3XVqSm^5NFk1RSRbwP|*p z)gqHhI*RQ4?@|Nf01k}1oPn`@iXY83#WY(ErMqM(y3{H1ZKrw8AOpwyr`89SauTr@%S^k8upY5F9+o1h_4It0hBoraSUeZ^)ny@jq^V7%?xm&#nM_tYx?hhR9c+BCGgDe!u$R2fo<}PoxliTrUAFKoVE_ydIW?HG_--$u9+;RguOLRf)s)X-4z9sp zvb94~K5I89w(Vr=Uz);Tj1-hUPCJ!8@vqZxm*LtqPxS|9)LRVb@-GKC&cTQBdODG#*=A37gPUyE-Q=7;1mfTJxPlfGKou`QUgedZeaoi+NB zsi_J{Xuz6(no1=Imee@gD?{QBHy>0Ez5&^91NOrKC*5{laO#`8*eOv
    A1meXP|@mFANbQ9M^% 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

    xFK|n7 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 E9rmKUm+NcnPtz83I<3 z=+ulwWNuT&Fj0W8NX0kGkY-J!TxiTFMioOX#*X!_2UCjI#VSC5%aGxqzR~jMLF5#M52DjL|`*2E(86V!V|v=X3D z>Y5U2_S?3K7Li9qR9F?^wcEqNhN7d~bkE~pm5q4geE!^YPcmrr^*ezjI#-T^^BX}5 z)$@O_{t@CO#3FbCR*?u@#IFt4&u0LI>KrvmD_8vzQb)Rmw`*a-;3pkAJ-B2S!B9|| zgpwLuvKyd&KFa}YwaL=r*mMs|Thh6b0(9w{?KjOQX=7IM#)p`bP4~QwpPS~(|Ih#N z<;NRmPwV*XsLtpB^eZxCFx(A)IUE-$o7bXE)AUNWUg0EEJmMZ>Jf!5(_p5@rDIE9P1#)b6reX9IlRdlRX+2I_C=A` zs$!4T*PYGZ{f0yWOKR6;b%Z*YzWRmRp!!YTN-=D^ZHnq7R-l*w+jYLlUO?N1<_Hfbo)^>30<2gmV*KAYfs20 zx-^75Ex}DiVQ9=QL_ph$Cm5zQ^h_G)=~NCDL~B+Tj+l1^*g zn+e)`HHEX11H4dHd$(O8@Paj-TvCJ(K2R*MHG`{2D4Os`-c38;^RR$rgxLL(qbL7>RypfqT6x ztV50HctYA%&FDR&3*O8p%(^NbUlL}OuvF^1AV$O=T+$i96K>%&$NMWZpYPFp(R~yb zVkB!bOjkr8O*-wW3M&!b6nUv>MfLUUu1mgUybWx@Xu|F=shu~Y7uXON%>UsBBY#{PYV@p-b!d>=I@aE%hMuy}OOUNE12fgF^MC+%X)S}Q528ek0 z0`D0n)P&ZXZHLp&@R);p8sMS8c?w3yE^YZm3wV^-?@_uj#xB#G#T?=1wHP%hR}juL z_FzgFXA5{S;##O&xljRIOqS*vGWqUe=H2bXlN~O0`|vmw5ynoogU>@$m6yT#$qB=3 zhsPRJMV>8 zBJl00DCN3W(01?_MhNjgxMV8veEtvSL)n|Arl2915E|1EY8RY8fez3Pq@$*X@*9F_ zb*o5nYEJCoZ(vn=Dd1O%~mv$wJ@XHd)qBM3ZHy z+b&@Ao+iuR3UCxxqSsb{vm81~dx7oKEtr2L9C?x#lmTRS7J3a2t*f}dhe?nNT*X^C^=QBtMaU*8;Ozx!Hm>F{8%|HV} zM=Ie)9=0C|k%YD;kBlm(8!P>IBVO1NXt>)>qw@9`58+Ot>SfD$tCwv#{!G1`;Ve!v z`m`2;?CMhrwTl_FtCtzEtBYAIt{Y}3taGy?b!|3=^s)D~6yIaj24VXL!C!6-zMxkx>34!TG(ApHRUgGFbXZ-75Y>tvH>vV$35LrE^^`gKNl={)8A# zfJ2DoawAlajGTs12omAQZLbTKiEZc^C3<6iA4Y&n=ANR&jxC^s2(d$dvB{OKp!loT z!32-j?Z>phkx`q=L~R{1l;hx=(iNq?37;JFQ)A0VRC|053N$?YHwqE%p*^lI zSSJNx6g{*=F#m1n60|1ha|Oq2fXWW$Z(KN{^MV4lYO0kpLWSL}R^Bwe!PQ$>-!iI2q`QXE?S3pN}AnFKV zxJ`U?wdf2W^;=}on-+0ziN5^_=(plG3+*=7re`>30qNT@7L@|sDQ{<6R13s?8cEK4 zpiYvHdx5ySBg0t^#GM^U&Wk|Y3zFol1L6*lB)CK5Pp`Bt;U!a?XHrS%EK(`3(3jALpXf^)# z7LI=o#N9U;P73qN+v#f2NkGGKCpp>puY4H*qY-D}bBEoz56s5|atQ8W-pOJM}i zAri+pz7DApu1rXBRseA~MUvA#;L7tsK$@1rfixed0Ckd(`vIj3 z8V96lsQ}WvRRcXEZ|}5k9|F?wUa+)`6xZ)DK$`l#K$O)CCm)DA6Ox?aK$`jsfK>h} zfVh_-$(akpT@p#owLp}{Bxf-YcSIyPcLQ-BM3VD0kk-}q82(l%Nd?ln$}j6EEz{C^ z0e#PU=oA2bBdNLoNb^w(q&dIaqQ`(1iMv%mHwyaLzWv&wgE1DXez{-gpAttepjXAm zT%a|AZU8z^&>Eo6#N7s!Od=T0Ey{gc++D?sbT?|PsCg0=#w-%e0!hvUpe>SuGN5z`Wg5^%Da)IzyZe9&#obGm#xD~o?NcC4%l@5om4A}c z14z?y5sL4v9i;9ufgTrkX902VUxrfzq<$-a)bDRBx(O&5 zoXl{RS@e>9`=LeKfi#Yju&Phvm;kiD_?>IfbwHZmn}IaHcUs!RmbMW{)50A?2T4kI z0kN&laE?2~ecKmE-{u49+lfHhMqN&K;^Q_;`-7#u3#2y94$>s0?GANOI#57pnHKc` zQeN@X+1w?O?rl<9XG=QZ9G^*rg*r1^}sqodcxtUI3(NSqP-z-3g>p z@-UD}$%{bh<24|am(4&bFP{M&E^#zj^pka$3d3K091V1Yxa$pcq@Zy?+`*dRTxHP> z*4^)cG*v5rRKnf@QXXso;@*fPXA_Xh)mK0&SBXdHZi*x)4T$?WlAJC;+{KaPbOYkv zjU=ZR5O-`OIk`aGr-5DNK-`^?U|`<-tWj%C$-$<=Slfw$7rP?b}Czlxxoc(dy1{-T_kneF3C$`aO__mw=^a8ry*u zWdUg@eSp;O*+AUsfcyfPdI@CeB@p*Upk4xThXv{-5cgHUx&c}!=uIH*RzN=rNO_f- z2@Zjl;hYVmB{&i&AgR9yNI7|#MRS4FuKP8Ra%};S%HJ(OYN6a~(d$4O^5+))59k1i zw?kLm%aG)x0%_ik1=76r0pjk5Bxf)X_f;f0g+Sa*k>rd6S}bTP5O+=_VUmwy5ZfGF z+G`dV8l9C~KQJ}4kSo`FY9~E3yvd*ybgk|Rc1F05;pBcgu50-5K|a^G0mpEtb8IFh zoB%P9lVuT+Ead!LGl|ksUE`Z0c9FhEBfRE(7p#kP&($-{xJN(5bbHap8+06y7D%>5 zrvW`HEbj+&C{Tto5J-))QP$lBKr6)EcFvbHG@i;{s}6~6}nso#TvRAf)E z?s{6(2WYMMI1@;HL@vzWqSvkCX{tNl;LgJBUN8adYC6*Xo+%&E6xx^g&CHK;&V~&a zzUT+0wL@Y**eQA?;G^DpYH*(W#e@DhER^3G?$+V93lbc~(HX2~PVzG|jLgr`e{Krkze41hCIx&n$HJwSg+$6iB5YNL zPo*^&6mWbjbeBQ7Pv0u8HLUC`nGA;WwKeh@$Ek(s?9}29 zO|>%*PfGACWL71ZNZC(>-Gt_Cipa9k_JaLO5ty?7AwjKU|8J3~(q`Dd1%|F(vDxp6 zcDypM?^{?9r=H*~2vr_?TNJ+sf3zrwv?z$QCMc}|nNymtDD2`!RmkX3IzNc!MgUPl zP5~g@z5GIcJ6=rmahZN7bQ^63DPo{L1D?chLgAJ6lBX8RUL-HP8Ku6__YTaSy>!++N&5mMx87nM0m&xJ7wJq&y>v;u)8e zCWq34vX2O;C^1-=sO>xk=a}_xaA)Cmuaf~t=grH{k}E;$<6{Z^kR?Lv)Z88EDg#op#0R}K$n}z4g!ecCdH3*W`dWWo40`G z=O+EQ0=B9xxtVUbS%V15XOx!B&4F!}l1`3TQjgeNW}5t5?g?%(ou}c+)~Gk0N8x!o zo(%IoWL&vSq+BLadrD~=jXU9T?S(SaLqT!wM3rIr?!b|NBIGFb;1A~v? z;<*6Z&!+oyhR_L~l0yS0#Pr1Y!k#)w8kkOm7+lDJ7{USppcJ{Qmq`up*2NAz&nk0N zX4C=a7SVase%g6P(U?id;Xo_E{0uQ`sb4dk8KC_rs1~R_{AM^01F63J$RaLOh_6HQ z@HP!@5s+LTLkpY&foFQY#GTj<$EP{_(HiGfTwFGFYRQb!in6M#v(CznZgO&Si}Lbw z3kQz18dX}KVfIH1lx1p1lwcZ1e>#O zg3T6LSOWn#$JcmJeog`XSUe|%+tX;l&}Jmk6p;pn(&t{uE^xBZEetsQ(i_n&qebfKu`7IqwHbPSkkq_o!Ddao= z%x)vE1yF;yorQQ(FD=6J2|RDW^EEs{tNjfCEJcrLIFk zt~L+mS7KdrRcq5fW8xy1N1*ZkOn6aIn8hi zfesQh2522n61t0V#!d=$yA6^E#l^u5iZ>8@0n^bApKI!=HprDt7i1W)|wd|a5VnOB{tgVk;C%NJ^P&e;z8$~ zJ34RBXsu{|Y71?*54w2`eC5aE;^ zxKi5N21VIt;o*ZfB=jiGcLG@(KsJ;KXs0lS4-~(N%f?&s*1i1vj@8AYAM%^5E|27Q zqzdcTZ!|xI-U4C^OW-@OI6R&})xoA+`AMYwBx)`1enc3p<=s6<-&CKhdU-c>54}#8eeJy!} zf9d(F!#wh&M1_B~hew_a*`4je& z|DuRc{MzLWqxpze#E*CdS%ZJ+`A>&yS2z)glJKWJoC(L8|1=o`;nD5g;t4X>{*_?< z^3a&&2)NzX9mnNogz|yYp{+gcAX0SqcxcSy9(TY#ckg~eXOCb%gvS}MICBNs8}qWz zm}Tnp0>%s+?bJlRG&E+Z$0=~MQ;q-b(3rbDE`i}Pe|IqkTS_Cgv}dBF)>Q;2S%mR0 zhdYz8*3+U17F}f#I(Wt%yMyXujYWUAh@C-wn~Cm?qJBWST5`0dO}1#BMfX_roJH?h zw8bK>G}n+1he56=&!UTgG`3lmcAZ7+@T!j&EZShv=N9ou9d&mYxTA<`$rW8_Q5BHJ z7P2&M{!@1=EZShv=N9b``$*k!-HM{#7LBxMu0>0LG`2rk+A9`uMV5xbo`NE-{7`hV zMQ2&W)w}wZE5;PvZP7{~jqR_N#&zTBj&`)7!_XU1)Wf24EE;do9E)zY=sAo23Z${^ zuqXq4E~WLiXtG5&S@fbs{|1WRC)$O#rI64x+`Ljz5xQX55A2dY=oc>@Q^>_47jqcddpN_K(co$0?DT{h|E9AJiVxFmLLj>Dg{*X3sq`N<^8 z&z>^g%}L!{-1=2SbVScf$1e`)EWqtvOlvZ3_TgA}dF@93l=HC(2~KSxYEC;mFN1Vr zSw`*kkj4G*vuk9!`O2k40uiPY3ZW0BY z$IaUmXSqR9+_aO91-oC*OJt+Kr81nE{TKzEBux1Rzp`+<*RcQy-(G%ZVT3Pg{+oWt ztgg8K%<&1iF#jDrt>~RpZ2o-6_LhLI^Ekh%WG24tOtodp zCgM#Cx!%#`x;s60FCv{;QdKsi2Fg{HSq9ux%kcECK%qW+4US}wYc)Q=tI;}#;T?tk zONb>tYgLY?HVX$2WEO@BaA?mM9zu`-%+o8~b3xT0_v`;xvoI;*jy+QpbnJO3 zP1#UiQeu1MO3fx1ubK73vsGyS(^u3V4%9^QVRi^C4oXo`w_hLF&_^8w{ zko2lTVP^tD154r0!gDTu&&KlsJm=s^?eL=&1|k&(BApIV+S|t6o`u0*6l-GXfD;g0 z{DR2ATelDZqY9!LG=D+R4-4WL+-J6ZLD*^8OoZ=VjFU`9MX^oS>4vGhEmMh&gJ^3eHqqJYf&4-{Gj+!FfGJc@rAviw>nr8#f>BqC38 zjsl9cpnodpesck%!`UK?u%I#21^*5vP15snTcj6`hijd+?g4ZndRo}`0u)~q(V{`{ z!k1rZ*WuNIxK%vx051T(A-ftIDUB*ObpLbB!_)7C*6tR>QV#eo+CzUQC03 zo_Zui19Q~QXd@ywA!FJ~6R8d%3WyLWZ5`YzZBOPePBNWW3)kdURAF=i@fy5QTlgy} z_R~O%&-gPGi0VUe=a#6O>H6T@5CrW zxRz>9(_2rOj;RnXZ#@O$WqBdq)po~w*4tD(SAZ*82t-;4MA|wk?QP@E-#Y5arN%lg zNJiB_2eaS-5Y^z(2WA z3v9Pe%E0#VTDC*x3)fb5O&9hSqf8fXO<+2BWK%mlX%X`p2OgNPwgiZ@1c-F+htf6}cTv^A?TT}((6kP*I^(p8GMpn2ijEq#ZmcktmB?0w9M8gi zgPTR}zG)kd$Fvd|r=P3c4Oat}t3=9GBDE5gMk`Tiez|tfs16SnZWG0g0HTJfjs%T# z_wviv?0#TG4ER-JaQ0?))`%gq)e-4g(9D`G?V(A`p zgjF-f`>Uy9V0V==W|@S|_tU_g44RfsgS@4o$vTwej0Mthmv4dMw;-(a&S zCjCN?bG>G|&!l&YUz%?#FJ%qArh?J3Cf3d zCx`<0HXZbx(0*f(&hOAiigY4~@J&6WLj86(2w#2&Qg@3CYH@dh)1&_G#KTBN{O*K) zIxgNp{JsVQm4WJsiOZ0UL0?GNy+DgE)9wLOC3XU}PTOY?g+$T`mXkUW3)UDlmU;3svAxtr8@7winat?^G;?fMD*FTc|})ZbxQSxe}>zB~qbK+D^Dv zTI{0<>vqiKa>T_eX|H*fBYHY~`7e5ZaCHdEN4kPs?h*dMVJV~FQ&mSr%-OSUxN;AiJabsz*SC(R8EPs^Q$!SPHB;*5qo8hG~t-V zOWxFOQxRY?RkHV`C#l!T@$FnP**WpQ}dp({*@LYiBC3pt$Bp)c`T8u}fsFwyd^>zgNl`AKBLqHx(r>j=3`pR~Yut zNK^I@DSL?Ud1km$8k>8iMM}9xb471driTm}xr^T%9*=;3E)(g88DMwd1`bciW#zS3 zSYCUzP+s45<<&AV(}cHSA@`VR=9wVY;?TGkAww|e`n zF*xmR9mgRLvDs}Mw2jA#xfD7IBZ44+Ep3zgokTlP+Q30h$9}z-b~!?#dIx&!u6^P%*u!m ze`ncAr0gULI2++hX`2mdxe(_fgw_f%2M7J@MzTP2)x~vT4%@{cc2Q8Ab0Dq>uit7R zV#T+ z3GdHucB=EY=q7llItL(}@a9Y1kU0@F7Jh~-Raz+sde3a;ybCCPJMbXhqWQ8HtB!Zn zq$_gU(>vzj9W}{`t}S*(w6E8bf1sopk6AsPz4qE;@4e>iy;o_H*jc#&cY#mMkiQ(w z;po%ca3zRl9JF^dQRLoRJSbap#T(SIySK#{5lfzjr0K{CrAbFthyu=K2<#rA%`!;W zdU9R1uJt6sre(anOK4atDk$I_4avAuXvY~8aIOVnY$-DCLKJY`08Qilvq5{ik=fn4 z9DU|r2c+swk$ak~S_6&&(pr%Nq%~zAkj@RC4fHnBhw~VLV$BV^#%Xk`uc6W)j$f~` z@HSjn(LJeHO%naM3UgZXvJ!Jg>@_i{E!3P5TVkm=sbf@e5~<=OifUGDD;?8FItW4O zCRny>%D7{J;xmqwr8&mki}&TeN=83q+)=no_P{vr0GH8)*u;C(%XwE?k+2UJy?iVnoZ9-C{(TI8=0+wspN2Kf{ zQX5=p4e+ltpA8;Yz@{LC)(RMHqUQRTzYbSrYc#sm)SaXg2DjmAV+tIP2vvb2QjQTt z30z$6us_pU?#x6=&S<9k&GB-_E)7Gy^R5j;I$~Vj4I>fj!I*m<(W<#8(%ciZJomlf zy0y7~04bT?OzwAjl}}-1#pPUkQ&NF%*32%On^!V%;-C_ItZ2p*ncEN{*^{Fd*2L3c zSNIeZm927&NI6E-a*k1*wU%SF_=}q1*cV=oMK4Se9z~N|$Q9puCCU-4Fy#u7a)qen zTxknAx(X>dyBV(B7r_;;ai9$GQd-ChJFQ9!oSc|sIYFeHAZj@$=(@G?QHzv}XoeFn z#N`CnvO%x7s@F^xwvZckZqVfh?R1q3BIO2=a3hqT8vA_ZWTc*#`(%sV9>3vHCO&Db z^zh}5Zs`UMqhmjJFsgSKgEY|jj zyZC%8X)klMufZj)9p0YiV-x)_NxWrhflm*cO3QF+Tv-b_B}{QSMfO=vxkTX=S=CMA z(SJ+>S=A0tcC2{i8dl}u$xsfnEFw}C5$SxI($*PwMwpTd8$ocwUAXaU$eB-&)eMJr za{PXXTN@C8Tz-MO5>&rpp&xRwBkrYc030BXG==;1vm)3c-X3VAki4B)V|GyZO+ZGM zi4HdYkT<=$8qQq}k1AY5$~huE&Qoct;YDc>E-w4rXPm>#QPiRrFXt9{ITxXH+JtdY zN1ijfT8togIR_aOnJcoKBT~*0Dd&_%&M7U@cy^azxx0U4e^H$6Kkia2cLS2_FKTWB z(!2k3_aAY4QJn2ZX4W_MIkvw=vXK+H@rau1tplyUPgT$l`#`tg&f_ekTo7=(AuU`) zXST3`uzSaF@tlk&S_L^;@Yi@U z&9(TWD)|YuR4W9L7Auje5~Zy(?xI@hh}F1zxg?rVw022!9TMm-pz}Z@BhKRO?WB5^ zhq}tAr3JL71<@>^T-@%(G;p~nb$TyD90JBOT^M$&{S}@l&{`JWFg%&o;druO_z4m% z7$PkgA}tuDv0#+O`i4Vrck?5)I7_VV>SX8YBSO2TJ^>d~aXUY8I1uVT`HWqSL_GXQ zK;Qi2tLXAc5aYN+rQ&w#byCvX~^hwLV5+CdnwTHYdFi=o};( zUt|GF6L$qb>h63XbysN-97nCixEwUndGjiPHt&dE{QV{FKjQY=bM(W;hgrJPTR&sW z8|vBot}t9YKB~I95j&2zzi4M<-No58h-(Ifu5UULDA#KkvF2~=*|fjI7E-RE^1<|S z2G=Vp%N?hdc|al7_P`TGR67pOr|@LHp2m}+G8gGnQ6W-MAqqIJo3|;>TLuN3zggOc zmbTNnVupehF+;J5m_3dsi|-G3Qp{en zVn(E5Mig*9GH+9ye;5>SI6b27zOXc|$yQpjLE5DJ0-EdHz0h2b?Q=0hO^(`F27FLf`(YTZ5;tCztB|0kBbV%2aM9LN=0tawbx^qG~jX6V;EWPQip zh}c`l|9?Ysy=g^^NJWe&;CuisD2+NyX`fjdb(qrFB~o|PVM>eanYOs zvnzAM=3HjjrLb)-enVL77{u^)$|fGIrsf)vvWY0*tbl8!y=c%rU=w2V^f=Ay4^JmOPiuX z*cp?$BPO+R8kRyug|HTbAA49?0;y&{)b&7>+^R4?*MKD-U8eJym_R1ekfE^ z-P){hw`~m!N~x?F{2+_d0ToEki(nPa-~lsElAsH$yAq)Ngf_#{<^ZYRYb~uFNd4Yv zX%7Oa-{qFJ5=i~Bi=y$ekypQ)Ep021`prO9;$b!!4i{p@AFbr~471>i3W*oB#Bq2c z@uDRz!}C<1mY^TH;Wre{4=Y($HKxLF;M)%y9IAq zaNfc@9KVrQDZENN{e?$AbTc3Ky0GqwEIc}mfo_`IuA6T{V!FbS+T)l3swf z z$#l#!RWunQswGXNB~7Fytu&Uj(&BB!E96$Zp3)Fw65qYR(I-voiHXnrOwTy|hjEQvTgwi&^z0y<-V`wA3 z9$v}(y!#2yu$U$4n1^F09vGpI#f@xDk9K4gvpB-6O01CL)p_(>y(;>*NQze6-vPz1 zxPQW1a+No){wHvrGF<4Ff#z4y^wS0RQrxen;h$V~`uSwBx!nNyj(pL}+rCOw4Y#lI zGj99JIQ?om9cr2BI1`TM~a&rHhS z{XFx8$t=w4^Ie+fU6ZHy_%7gi7q9dp3-4rv-Ma(F-Z70}5Nom0es1gQ)@Q#?o`ewn zMSBZq)Q9tNztNJSg*$VxXx%!>vOFZ79%dZ=qC6Hw$9TKr$+%B3McHJFl1Ph^DBvuE zE2TYRklW(^>^gcuOX{d`)O;N^j^dT_|4VgrZFE7N^h?#zFVXd59sM59rFiZ(UBPc{ z!4he~5@{V(8tbUi;x(|Drgs>-Ysjzg;A{f4u(Y*weyot@l?!1V8^}IZXoTB`8@B8zA$DXkpn8{{AZmZqjVLlmEX+~YdD&BX0i%XY^(*rE|O zimwIs4;#@B-CT{kI354wirvh1J3-1e(>RKJcsGN`Xj@rtGf+9%w)zcarorE|7NaR; zx+dVsw3XmV#ZMDNH87EuE|Jc5Ds7!{XR2*C+DaQ&20(RfC6u2%XLL7u_i6)e8s8K? za};)yOWh^smvZ^QZrfGfG=8Uq@Ja(mqC7$D2(L@n?FpkXdV_YO z;}?I!x^il9`$d<2sM!y}v&bvDF-AO3)R}um;a+Z3s559^_$9~PFbnO{3U{(YI{~iP z_HljV$@ppYGobErcPo=Gef2HlcavGFO z<%BXv**92~LxMewYfv(OHZtM5=mm#gyqYL>0s9^qIK

    wuss(H7Sa%c53i86E{4` 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

    0AB3=p)kH$VD|f$&|XQsVNUfiexs_JH|V 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

    Io2g3nQxd*H*8MEAnK1U{@$ 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 z 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

    &Msd(MpWONOGL! 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

    (D@(ku? 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%0Ac3g?ZXbUT~uqt57n^SyZi=v*CIRLxaqSGOW4S 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

    Z&ncT|QEI=Z#sx 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≫oJO!PP%F8qW@$s}FP!8V=`^%Gnr> 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 z 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

    -}5`lH;V2PpUK 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

  • UO%`bxEd+4Lv_lTrpIl^|arRlJ|#TJbtH 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 z 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
    6Q}%>0-P()N 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�%r)E%6?E zwhnC*zVSBv9viRR9UqYs$HNQbV{+mn2D$sYzE0{GP0u9_o1#NoG~Vwo-pKUR;eBTB znZ>kCzn}jr8e00;x7!*k+a4?15i5HuR@M|N+Ziis)>oF017EC2l(kKNkg@naWrcW; z0wgDI9Ns`4w7G0I@8T6V)A!`%3*^>IWxKQR6QPm#*zjWDmxlN8W*5#LCHEUP<>6WJ z%9e3{!gfUK(Xe#8S9f5%e7gjUm2KU1z~-{8!oLhj-r-p9h>gvQmlYt{@$zN~9N!{d z&nLGme|gd25bJTX7;g`20S}Kff_*h!Ss1I_886?N8mn=6qr^HPLoD+YNGo36q*2RT zW5fGeMv!E@{4Kpv*%}+s4+6sO9eW_4czN6O7+Qy(cOi1BB$-ni3O&s!{U6G&u@j+N zyq7*xjO6hkbljK$`gAH3q)+*@#t(+h`qfHqjFW&3n{psdhHY4{8E2DhIi;k#Fqv+n zVdLX(HMHb4>}&<6%J`g|*xWujL6sYSeam^MV<%oPHu2m;*qH9=Ly%S}VSoSbh32)O z41RTMj*o`C}D=S<5KLb`V9MBAKYU z3uSZpS>8N!c;7`Rp*u|eHV+-quP)DOUZVV2p}Qi{oHP_qY%bf*RMI+Z7wfP+UjBpx zA6&M*XJRAn#Vfa?SSgWaqUW+Tq?T<*p;IdO#md*l+Y*(}j*FMArLkBWA5q|}!RE5Z z>_Z-thdgG}G`Q@sr6b~%kBzg0xSEXRjdjPz%O0yplE=o+jq2+eA8KUKt~HyNuS4eX z8HrUy<7Rs{=6lCN%Z=t(nw4CvY>gFKtn8sU3hU@%Sdr%Vh`b6g9~&QEi1z_C2h=9O zok&or(hAC+>B`uLyZ7GRFeG*Ph!cq%2FX!Hxk~ux&31a4tfOvxJ zh4Eks)id!kw1DHQ7;2pFuIdE$+l))N3g10yMuK~9CKB8jQ75gt!NZsqu*0WNG^3y?NyZI zxWw|+@XW2T@l|}2c#n8O{ED1CuNgC*NN}r6^Sa!LQ(u=mZ<^QTW}EuDX@mxSGle;} zoUyG<$AcXUAI&{0jp#~qDw4doTWCDN|4`UQ78D;tFi$3`EwP+R!Uw`bXx#!a*#agW{UphAxj^_i%J?G30KnII}lm7c{z6@HR`{LxM4$9On@)w zU(nY@d zdCDbdb`AWQ>do&jj=%dA)Y0r)(me}1gy98o+z`3gVA`irgBu|q8-{s7y?Fnh%KPqB%=Yo4mR5} z_8Z$&X0YFH{snEUoMcro`o*O=OnV;h0#+f&!K)FUkyB$n1c zT?}B_P6<;zCdwNnVTrQF3ecoR9sA~A-t656?I*c|iq-)6*|4dX4V$Q3X{*SBMA=FN z%(JEhNe>i~DRC(d8xvzZ4Bd$1zKd3;xiO=~+_$mVgn|BCN+sf6jr6cPqs!$`d-wVl zHe)7Uka%u1SUi0qewf$2pX~g-l7^*hC;b3PX;@kS#J%{?Sf+|>E^E04Ucz)Dpg@eA zC|{@Im{sq)i7o^(4mPZOt=x^5#24qVZL?i|#!6y~bI_Y>_)}J_65XIy$XM^h^Wqgb zvGPr^$}QSE+5%&`$%(V)lW27IT*e)Ik^Mu=qw-A> zQqB3Yf8nL#<-W#j&t+qU)EY}nhn$!`7}d(wbsWr^)5yT_30Zx{C4X;{--+_o$(M{T zXIz&8eN*&k5>xlea(xpXVOiekXUVu}SWXVH6c(9Mxzf*)anrDzv{#lXsa)Y_$+)R3 z-@6r(Lq^3C6a0MRWm_tq7NNe3M*61ss7N2gGwoAqN?gK2ds5XUwyJ_`%32#5voMN) z{22QT*{pvDt@=&z^9uW*(p-!nzEnvRw9*-cZ<9(G8$=}mC9)qqok&FS0RPP(DCx9yjH`~R(R zD%iYR$h4%?zt?YChgVG6?~U<2C`978Yrm~qxie;-p)bI`a%O|g&x5oK;iGbx&^3ZC z1Z}CHIS#D=+Ag#;4*eLYL1>MR_Ddj6FXno=C~{Z9$mDWsac_i#!{*`MaY7r#yF!}| zbcP^ox$Tt-;t9St2zmzSDM9OjRtnk%gi%&-<_6=#K+E;s2GaD=q-l(Q0BMW^5C$`N z2zMZm#`p}7#wZ5T7$*YVi7V<2cC=BBHXBG|a0>TrT)Eyo_^)sIBOraZ4L}SLm8n^c zu?xS?6xv7lf3=_jNMfX*V}LZ=7$8nB=E_k4%9-1hYx=$gq;K>?Ak1hX95*f3H`)NC zTz(3qFRqu?ou0;x3mICKh-zS}UMS0wf41E~(p z0lG$L^+2ja-*D(jAbr|apjRc_+d%BZMZIRA`GVRVEgMtR>x7mM^t7Nu9qnYGUkL3i zpq~mlALtH27djLJdR}O^0{vLf8i&3QG)HKh8lNlZH6Tu;M7<^;eWO+&%(Fp$9|EcT z@WZ@O0g%ez2q2ZqNkG(|s5iu+GKVT0x&la_aXXMoZLLF_fMy7nHyzsP(1$Ku7ADwN zNw}Us`j(#qnkBSj9qlAX8xEvTI}hj^5^fHV%HT>DZViy;+mC=WEn6Jo#J27rB*r;F*9lq#q_V%oh5NQcn}C$xHlS-I#=AhOYkvmfRCccSH=x(#Zaxgt z>wb1>*96T<;VhE(*x?N`c-JbRN*31Wf{>oyhg31GNZR0K_T&T<;nnPVDD; zD}XqipX=QY)GBB-5U1{Qy~lt!VGqjy#A*6mZxc|PptUfAm=6Z+Ng&nYMj(C5pF6}Y z7gV2*0#XT;0I5tzICLqH#;tK^Es*Lxmm4VJ(t>-Df~fZ!AX?3+EG@WO&Q_!a{ z?0cUeE*apIZLaqjAeC-EAWrS(dV_#CL7eN20^+oAu2%uX$>3b?3Ls9v=6d%6sTF+< z=rMgR&;x@03iJa(+|uDeK?kAt`h7ut9U2A1sbZWO1f+4fXyI|8T>+$Au64Ap0o^Zm zzva+QAbmzVkUrxy7;&YY3#7E09PK_w;}#DZ?tMo)9_CzWrvqu+T1We;qum9hX?erl zeb3!J3Pw%23-TmBbv}RaYWrjh@aD*ChGRo@NBn*LZNyx^)|A?)a95T_lAp{1^}rA_!7_&^8Q1C zekFHD0*w@OK9IHprT}S-=|D$GjA|f_aXFCM8+OtZtpw5-cRTbgpra-3LqHn$F(A#o zMj(yxBG9oC?iC;n$AN?7xB(~bFe}E_`~X)UT-I?Eh;-|&#qt2?ve4d#{}iqp0w-B8 z4#PkjyeU|Hp$;eYrrG%`yfu?<+B{@Pmx9YS`Tlg;r+Qv-ee!6LGmhaVm^jMUovu@y z3@EE1>d}P69}2#@QJz;1TjjBdcYrs^pnPw#K@qRr(b$V-xQMsk#QPvv&hJ3H*I|i= zy7b~rZf?a*r!ojNHBcu-dDh9@73Jklltd~@qKLN>uc9;>38n2fQGOdN7j_`Zl~h-8 z=|#y+hW%S^W)NmDSSQ8#Wt6M#Y34&toJ1;4qKHQ!Dy_w!kY<+e7ITc5a`nr0rwk2l zWXpjn9p$Pg?SU>uF>!ZZd$H~*9E*@mUx z=iRT`oe15@O!*@cl*|-40z!JtNTxWZo5y;sLWfO~wX44gd_AQ(4M^ff?kWCBI7@kzYC#_26%<+ZkWS0DH z!2Zh;4o7H~5NVbWsUcDti-ppSjHCn)y!MxzrD+UUYL@tIQ|3%b z3DwDLISzIH{wgVKvum~xX|@olK~owHn$iNU zKyLMljVR>upvvB{u~BXQZ0O~svuEewNu>9}MHjSZ2ci5=3KSH^p*=ebSAV}fb1Mlo zU(7!JtVz<}>7?{~9&MywgcEV{@K7EJie0Jk%|1qe^vE=x!zi0+z>@2cX)hwsG`nU} z6NG(q^+X>YG=(p|&DoQ3J}G%q2z9u?yKc;M;oaMis^?Fiu~^$xa-3Q*=+;plcS271 za}BFL#x6eLa+^qVn+OY85nO2#3<_0WWxF@aGbAhXVq$jA4 z*{JpXTcWEPWIn&Dlgcp2Hq1VU4718G%^VMJ*NtLx)a2>&_NHC5iH5Lh$V6Ba`w^#X zd92F8V{+WP)%&+ zY`1pT-zaU=!eUXB~YY^_3DB^0k8W8*i}1z`Lwq+BINq!J?v7PnbU#O&NZfPOx=%8iu4}XN)hRS(C0j`uE$Wz;>9>rK#Q3CTp~YlL+@TC zKiSFT-6a~BMM!>XV3r;Esey~l&#N>r-Lkct6@o|=f(Rczq2MU3)S$g9$@pJNM+{YEfDhedPwx;Z| zJbA*lx3jqlI99}IXVe5(JB(Vtv>-OTAXtX6pr9w12UYL8pk-D#c3fDxdC>(GZaHW{ zg<~9+Vm94M_rJoiZl}WC2Mw&Ln*|f?J9o1bH>_hinE9WAe~KY4L}nKQqdu3+Uj%`G6b_?W4equ9_%t_!~op2nE)8dh+5Es z8NoQrh+}b`zW*~K?QjyGNui^lxK__;MyMA!p%ST3iSX$jLMv^ZK|!HHgrPR>=Hb)> zR#q6u+mI*n`2Yl33F~Y%Bq2czD)2p^WvYhy;odZVLnhgCqsdJE>ZHy5A%r6~)3#Wl zg`PAahhx}K?WQA*P__OWg7n2@9p9%AGQ*$LAEX}z`BHm|jhs3Aqn3hlktD~-37RI4MpNZ?1DE^5< z`@kI(z!An2xDXa=fO?gb@(_F#H~AGT}1Z)J!1KOdwJV zqBL3%r3G4K{uTsVWypkrc#l|?d^mv*KJsG2r9K!Nw(@zt96*{n$bs{4mpPEBXxxH( zL6gEb%mKdXC4Q6QguYKXz{5?M9NP9vJ^m`duNzS*PD>VtVvww3dYBV_b91`MftfA` zh%^U?BHmWSQrdQdLdC$g-$eS&d|Xi1WtfmgYyY*0(;0CVcuJf`?dJWj^J$GZpBa>D zKOKk{B_uR>q+42$ByDRFN@0>Rr!gC( zzxOO;eeV6eXHia;vHS&IB`DWI4RS@HgLS}VxJyN+F3|<+fO|n35@p?ck z#KF{N6n5mFF& zs{z@=^e%^gH2fRkp924@@Xvz30zS?*@M7>OhccIqM4F96T1P0Y$%G3P4ykavHFH)2 zmO)V;3L2A6bMnCc6}8juzTj;gpGWcGZJqUIyN_wO%7}-pWYuya6%SFwTZ>Rid%~b} z;z=Ej>!^Xklsl-3M6D6O;QVJ$f9Yk7DCPrbYY>0j$_3a6ER%KTDh`KJWy zWDW$Tq4p&QxQa$|fJk$INN1sx)&f~54LN}Mru0i_@(_y7`m``;po!IaA3kP`asK1k zPHy-qVHqYDm-}kO%c{X<%seo?7$1s=NEkNk*w#A4^dA=C_LM1{!Ks?-y4KmScvCLG zfYA)C#blt}Zz-789Y_GvK&wGF6qbR%(c!6Qx@_m7)Jcj+B}Iholn_d3n+y_5kzP!w zG{t2SQv>dv8W0oXFiE_m(L~=Trs*?y)_f-=B|@>1qWEYAQ;2EXP)q|wg*V27)Rh`h z4Tn!ITqvf>M5H1j!X7u~ZoZ7BDJ``)%P{AhMvQ~%IH!!HW*F#{flz##V24`Qb0oE+ zq1J8h*pXHaq-GdsHGPX54_Xsi?{ODsr1PQ+)}PF_VC#c%Sm)e^Yq-;U)SqtXeaH~2 z>Zf)(q)i;bm>gC3dA9Ud}AA3&7i%FEir>i z^+EFAjx4c!onq)`LGa9=v*B|=(rEb1yfN@O5_S%JW(=2|Yk4Emj3LsDQ5rKwX)JHP zuPFK9+){o5{{x1=m2LwCozogzmUj(9{xEY$6e_Mc$V=qh8u;uoMzym%%3Zh%TsU?lGq-OsJ?i<(=Tpeeo}iG%+GjnkO9EzF8YwzdM}wDrlwnXd6_hra6Y`1vptgNxXWr+cxGhGTFM zCalEqx39NRYRL5X4s7fC)n_f#gYSimtv?w)vaNnH{2#&RyFLM*>hm+FK18ZML=o>z zb2s1nKZ7E&Vp+re+0k;)u!atCVG^jQQDm#G_NmrTeeT=KHF(~5w(b0A}8iyD(E|pE=e!P|pD#qnB-BU6B zqU7VWWKTgf6FN|_E4tP%?6UoG-M^1XwK{9P_{EM^enhHTMA)1a5>ndh21UHzIoi99 z*6wJ#9qr>)Emuiy>xT8xk8(av)p{CYnAm}8opA^Ph|6TXQhKx9s2p9-wj0W&3zthx z3hAY@T%A=felVo!MWpIQ6!Er!v(nx$2)oHT+V35WN~Pgw!!&Mcp9kxP);Hy_LxS1t z^!<(_z{KCK3HCecasTu{mN5>Sj~ucaQG|cu()T;kG+S(h)Mkt8c=&UsTAC%SFiMiK zq`enhgL4Ne1g7aO_)OQ`rh@p26El&DnMixpO523+O8dmcH*$Z8Zw-o$47PVqeBUzS zyWfcK0VBT2PJBcvJ|Y#L(kMQqrHaqa&8hyS9dozZ2M*$b+IJ18XJ^p9&*I+mg&Gfo z6>jn@X%&j)08V>ce5mRlw;SZ_9@q`Bna|-`Kml)FygMzmJuS6uHa18MacE6T zZAnXQ<|cn34m;CQo6=I>N?@I1qP%@wY(@bc8IC`PR?g)eA?qp=55CA3M7Rs}RwX!9NIN+6B9%+V4+8W+aGJmWzijSD+& zXsop~?n{owCV<9$%h70=HEtC8!R38X?`WXRol0)-&_Wj_ag= z`ZEs0d=CBvN$X*oStp2^lWEwomuOd0a#&~H0JoY_exB_4I)Q$J%V!1+?&CRLJ=5_K ze5Pd&e7?tYytmeCL|P1pbP7sooPtssEQaok!-cMSZdV&RGh zGugYn=d>6&JX~|SgCff31#R8cv~i$c2cPM<-q^ZncvH=3BF$+c&1t1ErF9mGbvlN$CHJJ-~q zBlD(UfFX5v!90)os#`j+k5?_ZbRiHeanzdu#1(8&STg&`d%8TV$K48CdAR6K?B#ib zP*xe1b=EDof)f?>pbf$`7gt||SBEBBnsIQoxqO0kQ<=xG zfZs%;w`2Y0us;je~YY|QjHm$5{eu|(QXQQA6$S6T;V zI$6I;<=XRtPazhU6PE2xZpK!?dxgGx?Y`{ey@>B#rrb--yf5M@%b>!!oVPKErC4cQ zt$l5IW*d~Y&Svd2;9%C?1{%XG$F;dLS&MMSvG%oPlzDkrrlt~~5zNZZBkTCwe(?G1 z{w6EOyR0PAtR#wf4_7GCHXQizuWYw$GVIq(u^h2GO9F|QKe<7V2e#RJLUKR*T>cq7g)oxt)&x^6>MHvh!&NB zvhS(gJ5I`CGS@6;`u-d|_+;PMB<@kjU&Fg&j>s%R z_$gCr$?a+-a6O zEl;yDNG#eKzdG;l5992T(EhgAR9^Sa#(12#ttj@z247mU*y|6>Ptv1Yo8|onC>N`; z?XGmU1MLyoY9J3*JpI=%YjBfYCCZ8J2q?`7sHvDW@8fy_SMZYz#yJ5O{Uaf0btpQ? zPw$5eIcs6fyz+7>4CHSeUt1k3rUShKr#ql_{IjR&4r-M(uNua%NXB{$VKEfAsEA^k z3N<*)qmW#evD7@39@EWL_xN+msIdJ(J>Th@@KG|o`{2)nk3Hk-uYkWAK4tVx$W)6c zk?ImrgtJs4=X~!zgCZW5K1eR))2<4_p`t*{t$dkFAd1K&g!1FU1?87s53g^bb>?p8 z+==_?4WptCLbf zrq)^JtTMV-O4uP|^a&^fQ8dqN2TgxpDusr5QUkdi<}Fwx1j=!U5FkYtN|cg@3YCAOf`MwRf}so*$OxtjNA+*c(MszjLSMck5b1A$}>q{;i**b zby6i#sS@dkrP7{2c%_9TlSwS7{JSg`#-Uhf%zI@NOZEKyB^Ev}D3-4pvE1XtLZo6L zQn4tFVo_QqD?1D^fKC$vPjOfNk^uZ?n z4NKc}-E0gDX5k92o8^x8vb6T5j6pC`jD!4|8C?!~Xc0KLtW6f$-kdpJWji(pG4b4y zcZ17XCEl%>v8ohC1^fNm z5bbFGm{^Hc9AKjn{k)eqgN)Og@PAyw9_i$Q?)B8HM55TSZF46i@eCbsV`A`9JL5(C z=R5ZYhe%00CfN62oa4lxP5z(_>@%Reeu2$zoSIU(b6oHoIXS{((Wl;PfcgaaP6hi4 zeGA+DF^4ZLn}Fby;cT49#gu|~Qph~uj4CiT2j@b0?iDfl&fu#-(BMY8@vK~ z&|Z^6JXNwyL-rCK46f#R-DE}KO z-MqTwjZ*k}%r(g#Y?{~3W2K^gouR6Mk*g(}7J%KbvZ=h8Y<3xvemdKBVHUfy7g+#scf%NQv=|G&+ih4CJ z+|@4JS6#SAT(}T6Eq0u(}G3;MFdp<PY&u}v5+Ul%ol!Nj1VfrSlbxguz@%GIQ46f>E)32c=B%E4 z%29%?Rf~$)4&u}|ZgQ(gnO`4(jVOzX>T%~e>8`m0^GKeWO6GxjvaiUNPva9X)K*^;xZHo~3to;!aQqCBl_8ojxthwFKhMb|X|1pvE_;DpTBS zByd+*T3||<{V43V!0(?1erIPX!G`BXqI5SOLt8$$=vY&5?e8s-mieAq1y;C@HcBx`EBmsXMS7$uLpi#KqCeBHOPzcmjr(Q!2Es~{5dSa?(u4q zMu`ZU#5Ch^-tC5dJ^F#PS2w^v5B_ramGEzbe+hha#p)5pLw~FOA@~XSKZK8dRQ+4< zSHk}j{9EC3@h4ej@xe@V^3|Gcwe&@4{^RhQ;r{?Whd_P=pEbdc z;q#=Ir{Et8|7rMr;r|5w6!_1=kHLQq{`cWO5C3`i>*4Q&zY+dl;BSK84*w@MZ7jgqwG~KIgp-)%QGnA@%%BR^>Va6j>cAt z#^sr08g7uIjdHZnjyA#3COO)4N1Nqnb&j^!(Uv*d3P-!$(e8A#ha7El|&9 zqiu1tw;Zj>(KvKvzY=|^Y!9aMwW}L%wZ{fxsyMgjN#2#mx&@QCrGwwN<@G!%_sYDR z%J!@%`_C>MU;iKPrt<%+C`YfYTYM__tf>5md_MASD*I?fS$FxA?^#j4n|yYAH&yOl zQMm^xO#RerBPvI4G|EiWJJO+(92)G>ZJ<4~AqK9kF`;$wH)99kFWh$!MSD7oi!jrvx`@ zu9&fKZq)**Z*)Mm0#xhx9+S|!+;5fp>$!)9E}jWKpk;3Xn)eo9rv%V_Jkq{H)7}ESwYLB}60*j&4WFpA z;&YW23|=+^?*!(Vx^DsR@PE28rD0Rw-O*UlY1|JSEgx#3aSsF1XK>z1MXdoHz0cv7Ez%2cFSx9Qao8VR0DoMvNT+OBQgvx<&D=$1zZpKj zI{P4W15u{!vKIH{n{Di|Kw8J=1y^%7V$~qifDV5>)3FUci`FH0XDwPpTC|9C5=F`*eE#cdQYse5BiC!~peDzhjp--NTo8tQg>^{h*#2LH}S1se~ zte;Fk`GwB3v2}|^ikmz;+tcqdN5f~D$H1r1>zvSuROm#yYoyYeOt|10A?~1$4_tdx zG$R1d!b@Ehl!vY)zRCczsP}oG?Sd#&mWe*NtYh^^x|Kz6R__P6cX1#C7>5H^N8#Fp z3{#iPfZ>!fm#}0wYDo_glf0-hy3Qnooj)tiIL1u<*(F@eiuqC$D9p2Pdsa10E6I>C zOmlr8V z;m;VFBz5UCCRr}Jl^tiH77u-No6L^$aXXnEe?vn2rKBsFvCw4(k!A*w?xLo&7VuYE zn#@?=l>M=1#&?i_$_`4&S%+v=U}oBxDSs*Pf7{=!>~M#_r7s|ByG~ZdeqVnZVX6yAOJcp*knvbCM zdI0x=d&V#hOZ^vcZGc?VCG#cqz^e>f6Lrye{qbm1S~AolEFh&OCG?m^RwHORyCqkb z!8$SBv*1VJSHtfEe>Qx+%N+Q$URxkHwO&M;KSa9mqtaMwC@rGzd(Ut9ELd<*PVsPDAQWt>s!tPYp%h30%QG8 zk4JFR8NVOU8~9=jUl`c$H(TwxOfwKw%gymNA{fkGx&;m$#@p1*crRv*hg8uf^Aoq_ z&*E*ch6&%E7N9fS=)T~uNXRX8lAG+pm4d|h!f}a_g%yc&v0|ZoE$y$z00R6>*O4hc zufZZ|tR3M(L&u{cv5I%m0bgkwGzE!734_GXHA@<{2*X6>N-T&d#2q9~@67I@LG{VA zvr>Lx?G4$ORLOE9q*4=?SjG7z%Px`FieD~C@$tQ|U^@~YofA7Jhbv&tk@J#9AYF`w z#TiTlA~)ifOLY9)-sw+S>csksjUs+XkJEIvFs$@pzDNnh3&)4sFieldGZxqJV8dzn zhZB!bil$uZvCA@dq*4Tru9`cuOaj(QS5ucgoB_6@rJ#>?=whG~P(pLPX+S!;J`YIS zEmr{PAY#2ktAM^JG427<7!Lz!jK_h_k!P%P2-65&iNtsvNMrmTkjD4}(Dib6570P? z%i;Su}3F4|$etZ)3h5~7f3xM=vtT{j$V=2&V3AYT0{r{*3lVHA_eh7$DFH!G@ z4mCQo6-Ynx`V)|*r5K_08GJgID&)%8%WJ~rLj2b$|5-roa<>lu|0xJoj337##@F!w z--7PM|J{Nf!vBv1(S!zjw{PMOjSqXnbosD#LwpnXxws$P5twm?AT0fd4wGp32XpJb z*yaeV*j=)=F3*Dh-bDRpF%!yUaI6+n=~QSYwY+*hPUX}Y_28|l#Ten$&jLyjGwRK& zT6h`4a|WJuf%%qvVHMV*eg-rOa=EZKW63aGjxVKoIK2M)(Wiqk^e_6#k3w-+})U{KKIXo8g}ZALEnt3*o;4e+B%X z!oLUptMIqO=j31n&-pq0Qux1s&o=zsz*_ARX|+of;q<7Ki+ni|?w>+i3mQvEz8w8U z6p;^6SXT0xRw*?RK1E7RJ|`gsMPw6FmY;mtXN^evaV&-TUMs>8MZA9lvE1f+v@k>w z?;!lw^c`$a#5>Z_j&U?Db<%JrI~r}M(l{jhJDfaVmh(+P(9NM z`z>0r6;e{IAX2R$ig?=*N@+U`+P~8LD!2ywX?|%gWgAjlrharvKdp;0e0P9fhAgKg z=4tf0B0<(ADnTNZAdya}D-C7SQ(9_2Y~S=T2Cl(gm0yBoUF}tMQHCelUe$ik!yh^+ z5~&o4B65nO(zfD#l@^eq{h%C!K=wP=fS)oLBnN}N3g&t+*k(bW2lJN&eG%v-K^%G4 z#!$M3z?ry9x^=;UqMLE!!a%=^aaatYecmOUa1fVC!84f)tY}-bI3>)pGdQeNVjrP8jXn3_CuCkBbjmp zSY9cJS++zFv+N2%`<7+Pz~{>yWZ9Knv`JmaC^vA#jG{d%#bw>TWYe{fi)Is%W)qQa z3!tp=03@1(NLPoi< zr2Su_)8J5k13rx6o>!IaLn{lG zp2>OB^1?*)`f;;!nkgX6@*yI>k*fPFDxM(%#XekeePwV+UuAk$Y6v$7;VHh@v8@t`Gs#&0o zDn32z(l)B>NgZ_vUt3p&uQBac@TAO`KV9Yr$?#?vaPB&Q_sW-zvlu}4*wyKfLHKPQ z--ni#@7&K2&xIxBJC?&A2>;9Q`M%@fQ&ulRwyF$*OC899x4 z#cXbjr+bq6^x=4D&zzT`54+m%9GZw89H%R5 zgAGcWitl7rh3oJ#nN@*p+KyBKyH9|CPkAio%g4NMl_7t@$_|15U8Ca}(CPoL4nsX4dWgZ4ZR&!+ue zP^ZV!vuKv!vW{sCuI;!GB&Pc!_)Pm(;L}WRa(O_cc|fGIqe`QkmG;T!!QFUva3z61 z4{k`)s`ckV(s*`L@@`>=l{{^vm3(;RKv!g6>ts))vM18nHl;P;{gw8~%l=+G`+^Si z|9)r5l1){=?EMYZZc5*+@Swy5+M5H5NO52KOD{a4)CKk|r&7wGx7Cel`pG9}3F?6X} zp=_#ZxIBw<7rK`JY#=4R>&W3d_Z&;r8HD@?%tL2ACbB0Jy?^fDwJV$At zWX@pBJGAoIpEGxK-FkH;Z=C7sUfzVelHDmc-*LG^q`5;B@t7w{!Kuaz~^&OQcIhmG+hir>#HxttURg;m4xhoJP;?F317FMR{-L^w?3Ly8^Fo(tGRQ z_WbvLyIx{$Yf5hJ>*D=(eFyvd&c*ZiOkQ-s{e7dx*L$BnJsHhL6O zF)r))ys21A2J3+$tZtzZ3)h6HScp_CMEaeW(w;yRrNQis^=)g6DU13-FwP_#R;bBb z4hx4vX`=$V#5ferXK&txXaz3?PTiP>4=Z?}|J&99zWGk5y98MTY%)+Hsx z?KwIrrP$G7Dfw+5pS=KY4netA@*+ry>A3npE#)zsnm#6YD%Njlopg4)-U7J&GkB^ z6fZ4J8Nb<(gO!7NG;mZtn8`eX!#t;it(1d<%j|OoOE2S44~lVJMRAKmO<*?@m(6!X zEoH|t`PoUmy!kkzm;Pp2HFwiVUpp`@Yf+T_dO8IXX8NYWFNR+QpQU@1lQ@w|oJjkY zO519}g-dse#50TgSTM*eZVs$qe{{fDG7evdt1_=?RK_mJxY1 ze5P}@5&1Wq$ca?sM7n@QY1{7?KiK%Du|hQCzKX{uC9jOi;_O+Bu1nXBhm#5N_!RYl$J(fIo&m;>6U!>jp;pI zl~`BGeX77hm3BIb^)(WE%1Mk!B}SwYQyL|vv@{Yc?XJYG1=lfw((0GkHT)qit#KT+ zWPa7W>SfBVK+$mHS}8bRy$$YANjFuWMV+u^g~US%YAhm#zU zN{&d6yHMIDgjZTXa>?o^#Tag6L-gxl5|t0lGn+yvyyt)0V9m1>_k*U8acBxzyDjNh zxaTjLm#lm`+rkdWR@BfhTs}W2+=)iG7ro-rJ1UjwOqyRxC;4?P+?cLhFdZ9jjGJ*qb!~Oc z{7$w+_GZ%f{GdsD1d^hDeH%XYYmJc{zu!{*B2vi_X(?42OR3UAlG}$<3ewp#zvM1R zt6$ohlk#~%%|f%e=**gh^ExTJEya5)nF|8LgV;(>B=;rwlpMY$l2+Xqia8Q5+hQH5oxPVX>8RgEmdN6JT)8D zXoe4w*h%TAsGSQyn*l?uBXK~ci-$fYE zLzRgiVQDcWQqd4ac)po@=9=%VH7MAR716A3@;*k7k+%A8E8Z^#)*bVMMI>b zQ5r>~v@}|?t*Haa^hV6CDh=aMX=tr}oJlel?H|eTSwW>a)kx+XCmAA@43SDkX_So8 zQYC{`LobyU@_@e~-TF)HvKi%@e=v94kM>aR9u7y$B{iBmXxu;=heb7W0DyDG~eD--RgntzL zi{Kv*|10pB{>ktuw3l245NQSw=}?H$wwrLlQv0!HKm#5cT>94MnZ zRQSiJ?feEw>nI`>Jdsx4N@Mk{wDji_HMA_?MxZO7rd_ief!+_Sn~&h5n?zY7#=-T3 zdHE8j1Y3Hnwp)7SRq#H}=5ZTeRB*!&w`obb^9W(%Qct1J@q8z-HR7A~5+(qydj1vi zm5FXJQ3}cwyk8W#iggZxs(_{mx*TYxAPyPr0Lt}P>|PVvN}$&TJp}Zo+@&f0wIEur z4{-ItW!*Y}1-PtbdkHquf294hxEDOnkZ}g#qW}3`_$LlF)r}Xk?4lc6tDP|Nx6VEX zR&!sDGqC3f_)h5MVTP2dZW%zCQYkrfz_eP&G*3kjnCa+eh|j^UGR*VvN5Ovq{$luz z@M&-7KzgcyM5=*A5$_S)rEK%PM-7T_pK+0VzU$Fs}5)efFUQ&$5osZ%2ZWAxlw!Uic>t#U?n4(P>%RZD3Q!FsSl=A@jLS&?3K(D-g-s8p z=K>?-m3Vg*GLZ_INS8e*jV3{9P}j7JCXKZ9a4+bvYy&I%!6GVjxE)_9CBIGF$X3B> z5&D@x+XYd$L0fe;XnDA-qtIclBqONdw2i|8LT4O?8H{Vq!T2W*LT9CSe$8}@xnT^1 z+W^h4nk%a9e}WC4+QyrP{5=yoeG#p1x%!;x+{$~N@*Dc zY`b2ZxVw6)`X1>wjvi3!X+aGROoCEU7LymrC znSD;d*zjkVM`FG3-oL%%!mANE4UOyu#fIZ+F8}g5-TP9%o@e8~9g@+|2`R^JaQ3CfFMZYO^ zT#`|6?m~gjg0qSli25a0`q{%Es$B1M&{P%20CBn{ijAaoWmJ^Y`sM_)I~?L`bJ#K} zt*Ivk{lL+l1F8|)D=x-1clZAsZKtEP0%?qY17$82Jk^IS4C}6jsXGdV!WN5f)@L@`naix^x{wQ$DFg)?ernfb4Z8q_s93FdzypQO%T92=(jX&xgMe{sQ=X?}hOB7Egn}78fEdE<_P-XC-&@dD@L2EkYWO zMM%SCsOPLH9$J>S^dkS3!D6%9-Ad((@Ln=$NGMS+jlkFw%2IiIjGHIy=I0$FuzuOs z8rhH|oAhr*`gJ4KErNz3t-1@%SwQ@TA14Po8b)m73k4n^ZFi(mrDfgn_g}JpWs(9e!aZ5YfXf% zX`^c(bX^mwU$s*gmfk3_l&pVHoje3h01EmRu6e^T22o}J_tUuq{G z6-0e}ToCo~+k&W%N~1o0M`+Z??+V&CecS{-!6vI;A4eR50OC+Lr?r!T(a)}Fq#FS3 zx<>ND?xaQr>utWn$88^f1o^8z5~)5CMZDkP=}LRoApIUsY1BszC;HgS>}u4E!`6d) z8~OTJWqCu(+HrDwc^*!D$96}RZ4Dc;V%)%}jW_T`<*s?Q!XI3gcWnVex*8sPB5`-4 zPvdlK^qcS$oDw~>Ja6ex=}RGKYa+TLWuK&$hNUfD-NEs)7MyVwFN)#36r`@1qY%y1 zhh0ywQCyi98;cHDuVh;m-*mF>(Yk(uL#%IDJ4C&&1C1EENaBXF}=F@~EnPW;bep&X*ro0d!P;PJ^l6 z|K*2m?k<)e%H`uMKkLDt<%hjQmLJOBmY*NE@TLO5>TLN}J?p zlN}A^C-8|G>X*^nH5eT^npz}73_3haH1%vF+R;X|V~l9mInffSXo+-(BBeFq<&+i_Z6O9Z3&x^B zH!gUvWxT96?)AdGsNP$jJef0I)))8s;9jxb+xE6Sv@_*fgbjV<>$fi>IZ;gPVfRNt z7dwQpvkvO8%W;1XQiN7$M;?d%l0Ywrx@bP;6Pct0{;Z~KZVc!CF+-Y%I9bB z`2rUsSG0{rq$)%d@dlyBP}(qqg2qlJ)#fyES88a{n?2s_o#mTn!%hfE(zYfERG6g9 zY0L)6caBR=77KX+wsJ#m<85+1=6|pYx|y z>-jEf#kF7((uygmS}`S6E2jAJ4#n6xrj5%6bKws&RE%6m-rWHIXwVwqGhgxPfaKwF z_$#!e?684)!;oGD(qNps5sz zREk9UDU8y#f}hfY)zZG`BibOL<&=IY*7@5`Y4tH>Ib|25=XTQFXX#zzq(`LEBhocd zO51|>RNDTO9$IXnb&-DQ-Q}-S(@HNeGS~(Axy@&_!5RAcuPge;ezWQykxGzA*FP%l zRlKXxAi;)~%#+cfwh;!>bdvYY+#PvxS6fHe3#b`PJRfm0o7E9BZ+^w@u!QcYsVQkab9m3s-Eok^`Hg5cery3O>(=!`B z(}bmfV!o&1{War>G~oTP^BD~W6XER>2HZ|jwmYVTO`=m0yyn~F_&n-XxjK?l8 zlJWCR#@CpPuW}hrq!~}78Lu>Eywd(>GhWMYYQ`%qHRF}`NoD-`9c27fpHPXv++_Sh zlkv4C<1cj?Pox=7q#3U?X1vl;D@(E6$=+*)&z6goR>GW@J=?!k!p9uLRvuVrk=mcu zePuN3*`rf5)S+{M)FMoFXr4n$fwV%o*`aSav<7Gr#1@sc*qJMj7Z8pn-J11a@9T2h z3$7<+9JaN;k86A;RpM!R3u?^jcgr0Sd@gMTlA*Q0X9g>cH?prA*{o8R_;JNRymV@>`S3W|)wASVYptaf~gZGO>8`1l;r*J0I~*3Vah z$UncJQonTMBI&om{A%A$2Ck&1;VB5NL%_8536EwyCXQGkz8EYGCv$9ML# z|E`N=xDg9Wn2Lo+#X_WFQ5wafv@~Mbr;i-dDGP^^Siaao{z+P?sFB`RW#MyzA2^OQ zQlTwUsSv4Dh*T;{qg0gUlM2p;#&V(m>)l5zE|!(OdGYQyvHWvWPI7)(b~PCSZc(o< zcx1Lt?62}I?VGZw<(uE{!{?aEiGiZVI1FPaOF^G9 z$x~AlEMnwO>x!;3(ywksmRg>ncqf$_kxGq7Pl{IBLx`fZ-{8*MxOU%1BwYM z0J=#K6(%ldcr6wQ))kK&GI`X*0jHdH+T^pV>x#$CK%G{NZB&;`9#u8}((0<($s_Rr z#pH@vOKPj9)lMF4MV{+}nX_L>Zo{z)t(5;$v5*FWJbE3++>bWQP zpEcz3i;DaDkEiX=&)xeTUp(ye;v~6hu^}HH@%|eLx-fl$K>jZ!=%Vxq0(t)>NHfuW zk#v$nqpE8cRMkymPNvR!n(Ul6#Wx$2Oi%y*lkpc;jlgrDNoLpyM50#T-Ev#RG#AH&W4O3paFWq zfs&QFft6odKJnZckea>${~PIBfPI!ed7Y`5OFd3LcmG=3xz(4=pE2EcXoD%I^HUV` z6ME(_j-86)p^6dL|IFbNeP2Gh5?xvGh4BE29J%r{G>*orG%__@NL;cHToqHj2ST3z)ORdv{UENpAjzMD-N-)&(ELrJl|4c{yI zHoWl$;&F~p-7o#W&IGOAf0fdr^{<{j^DnXBfVuN>l z)d0u0&(7LFnBw|RpK0vs8xZp?ppq zG@ul(>EnFrpn*-Pl+#WbP>{DdPY04Ph4|27?Trry ztB}h+K7}DZ2TPcf_#fA%yB@)+vfz7R4GH-4_3=44#3$MbK9pW|7FW#L_lk!2pv#Le z9jE6r62>p*!$N#$@3OPb!+*N$5l{Uq{9YWM%FbHgOHZ#5pTi~06f%M9*Y{Uvh52w& zHan})$LH`6ANK#UvrguJTx(CfXMUIuht0CH)|xQzFgQ&~`Ss^W-pyiqSR$`~1M6c# z`E`_pnd?i>ks&_C66VMJk88xnC4<6zj+QWf{V5LdIYz<^Fns=T$s=3Be2$ec+wtG# z`!OLteIyL!L-)fYUP~kA&*KiPjqknsg!p_x!h9M3sm1>~{rT^O({r4JX~ln=o-c&> z^p!BwAM&{;_KS64KF3QKKcBuKJ{;*z=6m1cuALj^bE1Ut%jbj;pMDaC<7aq%Z%O^m zJHmXvC}H~eJv0h}e9pw3>@2SAwtUVA@hO!s9hcML62@QNOGA7{NSGz~ zPZ?cU{B;=hV0uPMm{CX%+Xr+bLVQMnnw@3&%zN!y_lNnENf@@nET2&!J}_H8K0~MO znh@r5wuIsOM9b%_5TDU0d^k6&tV2{xHl3O+BQi3IA<+#)bGGn-S(V{3oB`bDJLy^Qn|D zP55v5ObGFrC}CFMKlQo);v*-A`CK4jn(*K9nHb_TNy5~dFk3%rJUGnfLJ7kP#qyaH z;&YLN`9A*hz5Y1j`|pMMd_}_e<$O_y4_?E_htIn4>BBdK`CKevw&TA|&*Tsv&VgiS z+4Q`z<@+Cn`LK1Ao#ju@B_TdjCCrWZ&u2}2?w>D&`BX`mHWLP(H#NlPQVH`2Z^Hfg zi79)+e5T<}YCHVW5TEH1=5+qYwdIkUjt}#hAz@fAGYsAI5TBW#W@oXcV}3Q=`7SDI zBEOwyD1G~!Z&{enJlx67+KT^7Gu_+}A2hoWrsMWcjfC;@nIGb_ zK*F#~JO=2ad*>&@>48bYv#voH*3fhdLVOm2nw^Et38v#b?|W}^L?f7AwGw6$b0zMi*6&w@_$-z% zC*eO+@z#@V*M#}7wnZDs_g;%be6C926FaG9bePZ862{*jyeh;8kH@oYdd@9;@18K9 zr4pvMFFn_U_*^St*h=Jky_Ek^8hyS_!ua3o+7O?53DYs3>m`i;z3M}JZs-J`1_|ST zuNy*qmPwe;;XmJN&*1;0X-6%WFpcb5key#3f8S{@eGuDa7Y%o!|o#03F-yv6ne60m9O60G1R!NxAzW2I4#OE6lhN)ugIq^TDVhr-RL&C7#YvuEe5T83G3^jzY zSMQkek1(IRBn;~>%jeDzpSvXtb(wr7zxq!Ytzdd!N+2J9fAH=QpL;vO=bIA7-*37% z#OJEY>@8`9q4**o`0IPHKPfhao;_rXWl&GJ#89 zU;G$%va?$7-@exqAwEw^7|Z9PQ(ymCSUyjM_&gcnvrfX4;6J5%`bUc))S#T7mN5SM zVqJ*OGZN;DhR?`BFQ5lYHnuZKSm z@qt+JtRwKBF8w&tHr&b1V#=+2wubn;CSfd}?=%;k5|+>FAwI8#_-vOjz44#!@!2n; zatM~wH*hC4J=;Tkekoy2BNMncPF;L@n9r|pCw1KTmmxkoBuvMA-jp!@_QsA7pI>)^ z&u=7*zrFhF5Fcu3b{4H-1lO!7#V7R=5p$12=Qzmc zcescX5#gN>3LVeP(!R9 zz7yiJQ^J(uKiz}>Dg8>A&+l<3b$nxIh|eD+3~S5-aDDc&Z+;Z!^G6B8@n@T!KZN-3 zt+TVZmnb^8-onGOpi05_dQZYsAPk>H*Bs*WCs4DqP^ruK&sT50;G{60T@t3w$LCKW zKCHF(#^=uxhVz~_JuM+Vf9V9DzlQkyCB%nTE<1~*l`?GV_eL!IUhhkoCZy-nKy*|s@k*jwW-3 z8_f5Ag!p_I;?thO=g|)@K_Lk8`KN^O+n@FjpMOc1%ke)4SJBHiEe`Yfw}e>?`B;7a zSBMX5+w83A_>W*-^(}i~NP_7>Q9&60xXtbmpZ`dhUieR!zFyvgJ19B6^!z8phj)|h z)%1M0L?(4S!IK$0|9XHPo#4Y#oSj7tvGVB=;=@sby`|?<5{5Zz`Q(K7V?R=O77V%W3*{OHT>2#mDEM5FggI$@WkBc1ux+Php79!4jt9cFQ3l zJ_m>Ruy>!GRf05AD#u>%?69zWusJ)zH2U5vDttijsK<0Oy<*|ud7m>BPbgFPMT-W( ze})mtOeICLY%I?1TgQ~h-ofH8lURgjxiB_Xb%=74p$u`c?lzQRjCPLZykqu`@ZahEy@58I%7+)*Agl&y}!Q@`k5bCf1S+3qO+GL(a|YQzf(+#E0 zQKlG5L6(*34Th5IDBm@dJV)7XC=o~b$WSIa&d29^;wl_vw4t2fC{qljucO>s-yhVP}Vxi7feIyEk`-qP$oIbWrp%YM|sdtHaW^xLrIpDXr8`T9~Y*- zp&aBW(+uS*M|sLn?sb%0)3mz6QHC4JHykBqC_5bGc|%#_DD8$)?xR-J%W6WN>CBwv!klX;D;?!}L-~WFylN;nIm)LBBspG-qnu$VNvT$a zD7PBQODPM;BzKbX5GX5=?j+^-o@g7V zP#y$@Zo1?AD?{O1RA+q+&oD+y1IqvWLjCcoi*>f4G&#yVL)qdew;PI=W#3|(p^S22 z`mlQgx4}`qY$)p-C2lCsILb?g( =4doR_ISxHax`mE1(NJ!5l-mtuzN0*AD03ZU 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
    Tk3LD@O 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%0DXh5sGuChOE6;O4>o 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�bht@7FkEf(% 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

    p>kd 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

    jL{>I`q>0qfcv3Bc}_ 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%0D$4l{Y4n^zMO#D}uJIW! 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[k6FtNSsr9MS0D@R6px3?-6A1RA7#ILE`Wd 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∨Qg^0yp)S`Y4v?$ZUy1NqYivF)@_DqtEO$>2tI(M`5Dh=Tz(h>%wqgf(4vfI z8fxo%@OR>o(AJPmE<+jq$8w_`|7^#^D~yRm%0!}=Y{ga@y*8y~cKmMe)j|_CoG7dg zTQMC_=eU!_f5G2C{Q2LF0Hjj~_>1cNZ=i(wgU-80fmC=0J87x! zMJ|VKsVO1q{5W3)Tv@j=809{=j&$@oh==v9$Mu7_K7i{`TtANM#kj&4*5XZqAb~6S zaE6JINX1B`eL-n0E?!n&5VjxI2JMB&GRo@XKx5UZ;J@x(R*Qaxt_C zN4yPeVIA&t>^a@oL!|5>iUsQsOKDFzl*Jxrzq7ZuZAT8JQf7WTLB*xA`d?I8A4S0Q zh_W&bYfqy$hXzT0P*%6aJ-nkzHo4{xziq=toM+wDg$X?FH+C>^|_FZjj0v_&10E=?vz+fy&~^L&1(bSo2b{n8pqx*8?H#Z_6seQE zkL*C}3itWWm~x*;xlg1U(3D2=qO{I(|JTT&tD`Sn#Tz@|{)}T0L4LVMUvnBeV0~9M zn{|cjd@oSBPNZBXQkPI^Eoht4!1ZLjIQMIMh021!U+KdjBk^nAz!jU@gR>%BWL(Cf zQ@b)f*I9_;_W5#N*)4N!6GcRDjvv>v-|g1smLhyQzjt}_%mp@)?1ip3{c7yF$v2T? z`7IdDScieGgc0yhcn>GLmi4;8`71RbDyN8)Q$(?#39*#6#Ub%m4x3XCA(t^7aO%`> zZ;w2t?kelJ)=BS-tXov0o0X_vW%%xw?XkA!S8U;7N}6VDvhUw8s{B>0p4nkVZ~7U2+=fXUgx#vvl*5RvZHQrdPGPxL5v zcaz7Nh{mG$i*~m<(9VglhiOof{57Q4bc`pn=Pa00GpCb1PCA$GaqNa(ZLAySoQSaw zEnrP}B31#`uwJ7aiyBd+Qh)7q*m9`D>l?Ej`JQi_Q6@BU!X3=S#>1RiPXVLz~ zI@LzB$@jP0j8#O+Dk7alDUGuzrDcwqvN>~p6LxRv?o9b&d!Fr?vO$!e|8W~cW&dYK z8$@@$;`fJg`)8i*p&dR4`YfsqDS2qTxWmz4hlx z*s7cFBQ+@H7WBm7{XXbQ{3&`3?=KJC`-S8RN8^R{=cTC%8uwM@FS^-i4?XgeWQn5s6Bz#g(G^2Ch`8pP5P#sY(&4 zN-2#hr8K%SN~20CjVh(IcBAD}sqV2-h4Y$PP!tSXuTjN^VW_@^_LT-58>+=9Aitr4 z9}#q9sD6O(t0RVrY1ql<`lQ zVQAQ=&pvDm);SI9$c9nFybW7t8b+iVMx+|1G-{aAs9{Q@hAE92rZj4p((-9oH`%cH zP34De!1keW2Qy$@^R%7@LncKGSlH9L>EP;R&k+towd|QfcNnj(cwB!p)gn^WB8mn7 z4h|`eW=v_nF&dRjY5R>vB~w~H)#@hW^?zHn<{eqp`bT$Ktz4?rk<|)&Uah8DM5LB2_J-SnvyGFSK7e6bpW9v{#Kr)zWxW zElvBsShfD^h^rR7*C{m-k_tYg6^`5ghZI`x0Y62z}et%y{u zh*YhVMzvBJ)k2m+b7D@K-)H*eh5^SjwxDKhIumn!J*UNWj$5Ph8dfPlubmsRb6Qt zkwj_T&ZfJO^(7s!>93t()Ab8)SyIz!X4N1|(Ko-^U#1+9|0$v-M#e0L(=l8Em~#P=rRt%-PBBHo^e?@z=J+|)B!S-h7;<29BN z0lTivP2Ha}Zu?C=a^%pKliHe-y7wlm%x2YLPflt}PU`Ly4$n$e?#El@?Kp6t4Y(CJ zdiX%0G!K@&Zp*;*qpF__M&sED^(>s51&ub^x{MmNYg%RG&=Y6>H1K;}V;Z1|u1ZJB3<0CMCL>HgB-#o;Q=#tyBWKcr7 z=(xl(Z%2FZ&&H*17U-Kn|HPGbc?VavgP)VoafwK~0g=9FsI>Jio{UR})D4pQ$pUl+ zyv2gUB&PPjkrUy5;v-c12t64g)H!^F%p5}f#7D@?A=G7jgv=a5y~jt$%puf~e1yy# zLVe0d$jl+sy?lhs9B`z^0rarUvqe&sd(qqWfZl?hw;QM09JHrlO(i%FGAqU7S+Cub zfzB0Lx>s?V;5kD3gvI+bkfu%dpzmASoffYdNYhf=v8l|-N0%^HJjWz;E z)7}Q8J#9Hq{+{*_LObedTwaa#G^SxsyBAk}PFsJS?rHQ_*de5Ap^F#w<6y7wu)&^wM4iyHd+~zz#_-TL`XeFC)@kMx-y-DD5c}r!*OCDz3UZbx)J*JaQ-A zc)Ol#^MeaIRUdRJT6}gJcSJ{4FrrnqzSVcyHjP)gS50@$csPy5;_c}m9uBIRhErVn z;lKem+~loRO9$Dsyw!J#uh#Ak;_VK_YwjQ(&ZyC9?LTO>UhE(noNi;)+R;J09ie#J zJBWwFZ?szN2d$Q~m^p<5hFi6^bWq%uP`suN;^9;styWuf%nw3GIl5gOsywJsAY za*Cnzfi4l+SVOab#tChKp$CC3722bQz5}HB(KFRh+8sr|vQSzZEu$BDmgdayTG2;< zH1tv+&2N&0@~a~nZ?T201ky4-2c&7&8`^B4EkK&zA1stde`tz#_4J{q0cjaSfHdbT z4NbMsj{{vPJoq$FejE622(3Vyy|+;UXa5B3ceRkAI5cPK5v7W`d^_3LD<`n z(*V=nhTP`$HdrRxjeq8C;7Ami{eA*h*5wiBbWcMhwSz=z2Z_|%P#V1rrHLIJN;|lH z!_lBd>>yo=zE^W64-6pu2X6pDkHg%VS^U3g?mBD64q^?>UL3^Sb=Ev}t2I2B*%=x! zJKE(q$m{nd>G-H)aVd~?zDYppfP4%{yWw3x>Zp7cNIUZvjYfsjoHqk$+7=+q?+-v) zMxhx39?7TiP6N_1h5%{2D}gk>sX$sT9Um=snZ^4wke1PC@qPrP`E3KzGTsJKgV7sZ zDZjxu8lgi`TW>JFir0R_24e}rqD~Xj&|v%%Wt@}GU@%kv%QP6r1pUNmqJ=mf^B>;R zZQ`*8$K!xjS;2@pPAoHOFdCe}cm-G1Wsfr$*P6i~QiDOH2199-pVDA3@ZL!ktN{*p zE}SSMU)`2sOj4a9UHcQ(j>lS+$~sDZW}fUC?3o#T!yuOj$~4GYzUCqCc1s=+57gxw zxzPH050pOV61nrNbo+s$jAVIS-e8%23W@!=wY(pT>w9sHI}fx1M76v`%19#hK$Z3s z;ww!oZ!xwdwsWWJ*7$zC$i7!uPTSeCf#cB5mvP)waw#Wo1(>-_EjWf|_<%o-O5$MO ze6C3Q{j!`y!tVQAk=nz4NysOGOHv%N4eZrtpfRPvSAg;h^;-y~K)p~OKbG&qr+2v0 zVnllg(+t30BmNFhAo7a{)n~{s@0Il@egIl}TuFH?BjXs^Oc0_7Lp zr`Txshl{Mf&=>XoP_7=yG>lV^zjrz#Jj8RqaE}yeS&!8InbWkfyr|&LhM-sn2%whr zxX=lXR!Dm!kqVATd!*9XBbC;H;F9r@s`P52TWY|%Bh6rXjnL@(A>N7Ul|Q3*PFkm+ zMmp0U3{;N#mhvS*M;mLjYNJgv8V4YibS+SRNv}ZYp-P%*$mKinHzD6Z7Vf5q=YC;H zXU_gr?l~pR@}jfv9?RSs8$U0qk|t6~6RD(?MoBA8Bt7t|t2@8g>_nJs z`?1*M*QgA-`s_lSt)`W}5L3Q_Lb1|WI^#0f^jeUW!w;AhEQIMfwMt__4&|IdJysC768h>uQ6 zDhYNheXn#SYWfYKf@8rKGtw!vu68|_7-{l#bpjKvMisl$P zR6o~uE6zOG4JnN`@OM4_qLY-cpZl-Qh!%OcA4Th@@f7Xx{_WG~Y%`Z{dkRFyx(&va zzAe1FT51q{T<7r+sVIqJ!D<&;6s&Q`KUF+}9?z7ndpuJLy6o||S{%N|EAt`1%Ccw8O2;_Ko;qCV@zgtO zy2z|4ky=wC9T=6yfl+CP>G4eIjK||5b?ouDNcqOh{~?d(AKAmA3iiLj<9P$C+4Oku zMF8=54!G6r5hhq76)ceoR%sNh(jZvBrxr^-a8Y_A2=mbE@P|d$ROJEtq~TtM=*oA- zNdj_quYQGMFk*0NsZ@^X$UlV`i+FTBJe%l_;Gel8xt86ShH=itUytm?m@}nAG1Kf{ zcrm8a%Wf<$y6lFhEw!w}WL#N~t6XOqWjrTRo)hU}jMBImqqGpuao&Spvc^j|c)lRc zCD%wpWJsc*N7~8cr?|w=M6@uO(MrVMVn+v45d=BVxbfnVYt3dh3k?$gO7;52-P@m)Z zTrItwWf{VvMu=%RZa#_YNu4x8EW`f_J&=_tf1FH~5t98afh_Z@5enzQIVRXYgs4yx%CLApUe7P?fl&v5MON(k=i06eRE1_TaaF9^mjw2QAI{Sej76F>tLSe z!@V2oHCgDJ^m}CL8(|cmQqaeT!(9!#z(U^n3Y}Pu4GS`*;CN@%#C?G)jNt3?zd-n9 zw1Ir_@{FEd#^u-Od45dO7k_x`Eck7DerQJ)r(YI!()5`lz7+)Xk0n$;xY)~E-op(& zLzWjc#xbq?v3!gj8HXi)DbS;%;Jnsegz&Yva*p*4Tp!2vTez~m>u{xGd#1^kNaahU z@>Lq;t27yF3L)X}jvo1vDp-!~lxN7C^7C(R8G9#BtE)xj<|1*fbM2VG&p_q1j{USZ z(1g8A09)cWU8&4Y0#Uy-I27os;A9_s7sH=XHx@|yDklIsL!ARe$GkLHWT6xQANCEz zpa1buJG&Oc`1=KVa(~?M{tf&+g1@L|!8HBxHxGXwI+$m1rgmkP;eWoYOyOsF7COD* z!F0YG^Psvso(Ag_^)&8-N5OhR5Vd@$fZc<&tn>Z2QuIpAw3mU zY0XB1MqGvEgu1;w67iDT-C>0UJ(JhSJx>-a>Q~Bp6psUaaX(z{ zK@yq>knA5|>?cz86X~%IN_*ACi@w!+Q;ED5-Lpy$K( znFuArynaTf_l*b}A9*c}X*jR_0RFyqEdG;U`YrcS3l=QAo~#`y@2(CWaxRWYDHInb&9Rk*U= zSL4cznh;4xI3g7Sk$$;AX?t9}oI=n8?efZj1HH;&5Kw+OoQ2Si-<`Bons5%jC-@6C#xfQ7mXhETy$M zlv5@+MJca9Xb`)jV{rJL7!gRgV|?ad0`Z4z9hNX|?pPQCk9UNK=1sW6E2 zqbf?HSd>N=Fnx4`vr+{|To~NB8$I(ZER4?{L>TF_gAPj?%Q}|E+ofS?bj4b|ZNeZ@ zVGyY>lty7F?SDuZt5Jcf4tmC#V-Z1qxrPk$pASnCmvuaB+!^i{T@l1i69kb8f=EBP zqBIW8O3M@k4}PvG!6w?!0onU{p52r=gck(wM|uuGrLuICf9T)?3Jx9o<1addKLXn2 z5qU5ThmKS6$BpdzOUonIC(sUY1h<2iIlG~IQG>rF^X~Lt6p;x{g%<vrf^IN^it4 z&3ewo6}^ZqckMu2Z^D&zpN}ht@t>MJh*Ta#>b5G4ZmZG`UmhHMx+;&yP><>kRJ{*4DZ&b#1k_)wWu-)rv}8s#fdLLTfEmw6s!-Ew$9&*8ls?nLBUp zz3;ueK(HOSne)DT=FH5QGwZ!~X4{J6R#$B^ZwXw1N0^oP43TRqAiG^Czp=(yxt))Q zw}0@HGd5Ii-_X01;|-o5xnb5;eP~;`b?*}{;#cWQ4w5y~!gl_^J0F!>jf|qop3hZs zz{sRjZCUwLY*p2kKvK4>s98M)A4YP)uG`g`6tGN@q-fGoNm*UF1>aA8df`*7wvrrd za|F4eoNPu2Jhz5d6#L-vmFo_0o*U%Lj9u6IMnFnC6khDD1a*{9zpxm;qkU1Z;h-`P zkN8PHCw&}(&~bQF0-wXBk8n{=JY>!cL!Oi1m$^-hoEcWpRJR-p8jBV+EFYO{XiZE_ z>Z%4~i8^;xqiTSeLl>JdQ7zUna1K&yqGkz%>}Qsi;*heit)aDkQA2&Q+2d;P*3Uls zjBo>nZ9R&%n_n$$3lS&}qgr)6kzOvU!7|4a<)0tZ zE?oM@*W;e}NuhN6$Gr9u_y@peya&Rc03VwKwJ(R?8~%ClzXX2`{3GGt2LEXIOu}*S ze*?cS{BB753GfHQFN06rRr(S`|qZcnqZ&zpz#e(hYXJ#U@*9n#I_R zZm7(6s*b-(`3!8tJ4}pgKTw&C%eM`8?2Ta7xMqPqHe_53LmoDhzvRlHIE=kVG_^$5 zBK_OCI_5tYhyz~cE(MpQ_~d=>GWb*87)3!wMa^}NJ_V$ zRqR#dSFx_Nze^!CJYRIRcvZ(*bmohl)S%r9f9Ey0)oPHGYLJwkBc#|%$g5&qslm%2 zH9Wg>HF!;j8Vt%)5tI9jsuTY>VmF5ETo?WWP8PMcxa4fMlxNe9K^pLSQe(9Qi4F6Eve;hs^o&OX*)A=NPc2zGyCu-oNw1`M)SEblG z!x!nQcBF`&kV5zpL_Q`Ii|EHfv4|cOYUhgRtB^A@OA#&UuSmlxBA(2EumDJ>>a+E*#Y zzDlt!D5lRKT>Gj|gkmv$Din+9UqbC%F{K+qxHam64vQ%`2S+4Xgn69-^%T)x|x z+7v_Qti?o1i;0vLlVU6;#k!!F^tch$rZ;Ud{n{4O8(mOL7eaRUMJ%_N&hKDI5g6%p zqKxd4`!498eh0m1F_F?@BBjNo7>h|U6w}Hr>0Upr%75w)-SYflA2+{se{)N+;tk!d zTHo_(tf1?i4YRgyhFnj!9S$%TWB(0hUcYdA=snazdDBYY6z`AFN^!kYsTxah?KAV} zaV78KD#S$>e&_T)U_(L;C&O@H-;8UlUGK%hhI3p=ZPVODt&A2a-FGm1CwKeH7V^dZ-HbcXF|Er`jQH=B;-XuRuU47<4e*(V-@s=) zjbKs}Af+ZiO5gQTY^&juk>$!Qh2|kk>gWW02N}mG@F~W2d5VFJ%C?_8rRR#_t1Gda zbK#oe3n!k_P0AcEOX7LU$`#wZ)&seW!eg_yfonsz3pX5u$1ba?wtle3bCrzL`{2Qq z>k6Hx6FsGcYDM~rvHqH^j4#4nmM`;2#~A|NP4QS7AK`ieSNOCGh9M92bJITfBd&wR ztENS|aOE45A549>$nC;ap;P27tqCj{`tP)|n3Iil@|q9s^DX!i^-~%|0MX-&C|C0Noo0$!lz7-q!`!u6+;tn z&S&!}y6z7CtzNmM*jPj0Pz|{`;AhqNfTiv(GNMrN3=1c2xX-z!Y@vnB!c!}Ki8Bv- z;mzL&?v$Nu!pm$7zjDPUuk}lKlvV!%8CFl(nm4v5zJJ*ytT@txCc`^;s|P9Bj9^$Q z{Op6T!Jz6^?a3R{SFS4wm{NCui=eCS^0x9LLNRYkko{us8c^p7^$e)YjmgWnTY}3q zv|(O1NL5376@IO^yWeEg)FkK6Pc+swB%4cz*TQ(>!%OG1M$a*hPYJzd5{Da8Q8{h& z=<4z`_h!H>oJiUlm)1Ad&24MM=(@FQBPuPE3iLYi6<&R#E{5Uy0j`TW9JWN(F#W1j zg5bWREvqYQ-wjqdwCF9AYcD`t59U)jyOx=IwYmy5!B#8x`5T_Qg)0^Fl&(@SpH-+t zQ{b~wG0%Rbx)*k{hiHQK)x(S99;pJ46=Shr_ZX^x58FJ3=;86y1yThbw;a~6=NSqO zvgO-q`2uxkb>$}ersp%OCzs~0spz?S?B)T_OC@;}5qf{(pM7vGMKs0UQK0rfa`csi zt3Y*^^^qQe?TXqy87ao=!K~`%lx3*r=moYcc%dxkN`7+(mAqB*#dQ^}u|ROSEfq77Wd9_>tBwQe5x~ka4UESpW!83;hm`5AwjkU3E?wLrG5qZ zs0xjIn0FdGM@3h3T&dkDYpxZV`N^e1GrxX?-UJ)b3Qb$m3QelO zyAfP%g57GU0{JS8A$oYFsHmh0Jbo#uVdohNud$fBJ-oLpU#fcKTATM~ykf(pptLsA z)~`dVx_f;=?b_Nbr`w@67iOu=7~*$XZC)n%%2ben`8E109oFcSSgx$@Se3SqdUCJQCuFYD;Vzo_ z>1>VO4m;5rO?%QBO{&1V8Pb*u_6sgP=-ZI0P>t^7Y-|eVS!wF4&c;r_+)XO#r>iS^<~_wX;0jk2t*-92>WprytMgZ# zk-s|Lb5(iI@Eq-?baS-hq#j-c4Q3uX-+;TE<+!~n=PJmi3^AXAAAZ4rVaRhiuIo6E z5tn|B7Fcre4VMu{ojXsn57u%w);l28_CI_%EbBatc}Qok%om507@f+Hl6mxdpx4D- zrvV|Q^E6WW29{!c14}VkswteBZleAuwYy-gZdHVR6y&RL*-uk)h;ZPfeNroi5} zo6O97O5S@EMst*a%V*9K2*jfsCABe{keF?O_#8f0jETifZAc6bBT1dahGiz{i!kHF z3X;2iknimV9rYF4ECiL=HhB~pO(h=}-5Id8FTyf?+vEzB1CgP(RQ7#_q2A=F<7n^+%=2*xn_DVoy*6lI4%RKw} z4nMuU2KT~!7Q^uAE$hhrY3hCITTADg*ScgUznQULy>dZ@MIT2R7qvEf_CbcLbEav2 zNaxc%eWE)9KGS*@eCqrut8-GSb5i;!P_gxf@4un*Zz1kEA$xXpeqEYzLQ3amt%5J+ z1|P=iM`WEYhv@?`TAp98A9u4H%F!lvNjW@X%Yl@Z11bH2Pq8hCP%*Tl&gYc;U~E_0 zK4%frvXsNMxs-$dbae-{UlGYtSApOk*@t=J~$K(WtX|D4ZF z&Z7StI?}&C|J^~|+YgKV7Kl^ZF4FzGR`;Y-_oVb=FvT_^|B8M7y1xl=hhK|y+n}2| z(0yvAvV+RMFl_jogrtxM;*ZuW~JNzo3tNZ)1_PKV5 zvxADapAGv~&jGbn{Lbk8HLG`0s&`WQ5s_kVA@7QX_5SI~Wj(#tQoP!>_m9pfyyUgk zz4eJzYUiyfpFUT?{+%EGq@FH3b371s>cw6;sLVs5F}UjwgFr^U9p)pQ@PZt}a42*# zu3OU-i~Fsr{~}wbd*IO9Y%GG&xO~Sna0qzj7XIwUO->M7i!xjap4Zdh|lok;weHUM`SD^>Ry0nNmX4u&xx*SOh?;_&Xs5KoIkw5y{k>UxwwYDpY zhp+c(@sQHuA*JsaD)tg|pjej{4~G>yTRf|fwD8c_EuOD+SUjl#+K!Y@;B7UeWmgmt zU+vQ(BBez{N^6i}tU-!(X%TS*va>~WDUud`DDM{0jr)K>T*oV>o$iA|Z>sHz;`y~L z9#UF7q_hSp#u}s;iU%*OrQ0qs?W;<=eef6VcBs1=hd+iJ0;&1tq5`>Q#X$}SZy(`$ z5ZBmH_rfsb>5uE?4m6({sI{~ zAz}$JjlLrtUYEw_k208>4ZjTcYvD6Lb?_;kUvOxJA*Cfks=(W7?)LDu8Oppr_BoZv zI>dT*mJ+$F!{#dU2L@d0&%KoF;OxIvN{`u6BBiB7N}nDm#-|60eV+B^$0((6r{dO| zmAREtU|80fvaw^b9V(mXJ9s-%hxo0A)*(__I;0A`PoW*fJd}=NpJ(a(2=Rxv5_3yu zb;qR>7?E|RWbAP4zgRNw+ma!rB}1yf+YZer#xhdu^DLQ15No)ncT48#4ofC980$>Y z*pb+d6-`(4JD=E+A*CflN=rsDmW*PbXURN-Si?`R+>*JzgOPw;OOr8jXNtuRz;>uu zx}sG0@rAZzq_k8>704JsG1eT#q*O8-RF7B6or6F&BMd(<-O#Py`h3Cl#18u%!4%x; zzdnC`rJkQ6r*v$Xp^8+*}DUGIY9DP_qfa7A^7DF7|+GM!J**^!yJO^YFvk7 z=~*3y>Z!VlwV@{6VuHeb=SPBPz<5j6-zlLtLbu zC<1oHUNXmo6v=J~qUD|A%k~8!E;ctYr=z`g{10Q|2vIXlpTO&Qt3+hzAIcw%3&SI% zU)}EJ+m<5`v6?9J1O+pJDj0U>vR!+%bWj z+zcH$FWFj=Xh}|3n4Fi$@niRqcp@xKi~r?d3FP~ZaUOunEt4ya(OzoHgp`&EDLpk$ zu}2YBv0$0t*~`kcg*&=kO*5p1&jevAsU2F*aoM#~Z8nGUm5&gPbL)FRH&KgaoMG*( zG}>8dwL?m^LrS%y7`3BVP&?=B9Bu*}d475h*PrQd&lev5XW8mJ#&7@~K5Knh7)!&+LZ) z`td&d+ssV>KiF_BFx&*-SzF||42EGw4#ahAW`&M#TgZ2Jv{`oJKrrJnTRHo&5}yq| z;|v@5BBQ`|t3Xn!KvJqe#i&5VLJDLPP_m;<0AJc08EPPzO1}x{n^`+&HZ?cYO>Sa4 zInfNjI;*3o*)eWj$htg?&QT>+oX(rTl%ORUyNsn$s8m`ky>;8!fDHUC}AJbZ4M zVY4rOI_+jCY*-6$Km5KU!}x|(6dJD9L1A^$wM@&giv9(|EZe2X;(iI_`;KwVMt0pk zWv)@pNUIuBsv1%SJb%Yi>_J0?A0+#)pYB4{?2}P7(|4I_<{Q;iTGfzJ)sRxvC`Q#N zmd0v+xiO1odLv|KjfP=pG_?DDGiqi=muQA@g^lJMqnS}wGo(~Aq*ODCQ8S7KHG_f3 zv++U>2%jtO2_C*A{al4;0=J%vbCB<4s%e99FPqZ7jQim)lNp9e!>G$!xexw`OaBbV zf09t&Sg#XBH!?pcT5D&bXdff^qdAVKeaE=NuX;>{5}BT9@Y!|otygwjGvFT$|19`S z>rD7m&@)!qq*U3YwDD4Gt>FvT&|RwRs}bp0p&r3icAMKHM8DDFLIb84RHvV5$>7-QYq*UpOQR#|(j!JJw zq~XuV0!r_oLv85~+twY`wo3#2ZybQ5&(^gD8r>tJk zZB;{QH@+V+o9Cq8{uqa2^10aG@8>z`=fuw0?Ho_myf)*Gw_(<+__-VYanxg=mlSZJ z=hsxeilb>?!ZEeaPh4XTJ6}_|(cK?Xwogqb}z~GRc~yV zwN7FN?#C?XT37AYH^!jd zy?a1)2UYAn4ysVF=Rp+-g+Gxks9(X|*}!>^ZXssGeesLGKf?7(Tth>{H-_m8oIdx_ zSBJ5(vr|)j9A$HU=q9(G&enV{BX|5@Y}$@bLT*r}IJWcLQdVtWGR z){BK!2w**cIAr$12cz8hr>N)+i?q0_+;02Kyexw@yCdK*lc3$YdF{+6Hno*K{=31y z2EU=<_Iu!e0sc)0R{)=5@N*DeM(hANQV9#}#>cy_Inl|EKr zN%r7ArBbE^UNK@&c{qbWC>cIx_%7Kz!9msHaTc+?&)gk?PK*LgBlilO zd)xdYvh`SvZUxT0t!8Z_57SgsuUZ3(HW^=7n{jB5X(%^ZtuWf0Vzo(1wMnW#-WF8sA%s&bG9t>NO>M_Z5O&A4xe%el zyWF|j+*Ak#aqeT!&Z*Kq`c%`D8CF=EC1^LG6tC38hA*^5n|Vf?*nLcFv!B%_Db*$^ z)uv+9reYy&8oNBhIcp@i0M9WX%b{4l;66$yY9q6LnU8GNiqBvoeG|jbQutZS5!tPE zM~pS1U&a@<)=@^kr@?1BMjQQ3MV_^PAf@^xrTSHj`c-U4^vjazI{h{vE#Vg^T>ZXR z2nKOc`^{0g0rTaYiSm6%I&8amhf-`8<0a8;fzfS$t6Ng4TT;5%sMv#$r&xO3M(vf{ z#mGuFD`l<9W~EpT^-c_ppcsZ$%69uucSdUWF=%XRUbrJVj6MQkTwyKlWwf|Ae5L_A zHAo9Ez-p0{YLS#`Q88*!F=#RE+uwHjvYmTIq4B^u)mX(X(cF*YKpNcgKv+7 znhJ`G{>5Gms7j&cgW_|fVt&+UW>)8e>WSj*?yUr+^O_q#?J3yZp!O09eH~xqzuF=Y0rk57Sp+4&nU2UE| zC#Zve3VvgT+CCBf0{F||FNDwN&qg@4KvHUfqzYsNP5t)pz79T81>QG6QTsi-y9`y} zeGe2%sfTPzNlM=kRe7J{uFC76wK%ylf5i;$|KPV5_<{u6CE4$Q-SrLAz@&jNe|fe7 z&yDaHwrcw-ZhZSGcSWtp$DX*UkB2euXZ!ODRR1)Mi$P^>v997>Tu_O)aEtX5py4lC7=|qcZT~V3nZ%)gP4j5Pe-720Y)LjR z$+h{ikD`jq4lJ#RqGm)>TVreB5WN|IOEr3bZ`?R?!WlFV(K8!)vflcRY3FmS0{Alx zi1X>B<>UExlvW0x&#n5y9}6EFa<@YWvSTzo=t8QyP{40Q7GD^9;iW^+$0!nQZd@(`-0IX zHw(3MHu)6fgujb%ZSuU1ZPIyo);W8$&(At)BPq2t-18Jd5jNK4cJ=ex&Klc>MJmMi+JNdX1g%?Bh&$8k0*~C}Lmp z5q~>Ob8dY@!^lKy0-w^P&H|}zYo0_#_Ym?gA;NwdDW^uML&!Nbav7=1`V=D%Q{Zfi z=Zly*l#W>2l}G+kADl()37^b#XeZlC;KMT8kA=SxK4($yz#j+yJ@{;G-iKceAEhm` zsz1YL{C|Oe5&XZx{|Wr9@SlMH5BQ>Y_&xFaWt6ej4pLe>NELXWnY%qaJT(x$0@&}WL4$XI}no>KG~#ds~9ji zFr7cSa?6SmsZ*O-r#4HS+Pu1QGjE_y{pnIjK=qIyPPI}%>cl2it4&g^HsOpDR;$UY zr);W!Z6kwLZq2LiIdMK|ks$}_yk!qcdCO}pLIp!beaob3J*(Jyu;V?|^{b|A^bbe5 z8KRib(fClrIVGi!vlNjJOTgkKYDjnQ1WVjhCKeZZTKi;fku!b_c@@*1$Z3>&hedq4%~%qc2ol;aeY@`|*FsGQ@*655x& zOJl-;3)<)$j=YCAJ)%A;aG%Y3U57)r@Hr})PFXIdQhmo(PMv>}3ST_v1;{^1#m;oI zHARC_vja_$e|}23rif{uqLH#G+8k(M+@^>RBRN2TBjct3qg~Ev7Y6-99i?lCs5dr5 zRq!{$XY_1{8sW1cS_J=n_-*h}KcwMdL&VtG5Pb_i8=`-~XG8RV@c#jyW$`h5Hbg&! zP3z|ItQop_JgEZjPTXw~?3;!vkW*b4qK7vGGDsD8D?n-33k_A^ePr(T@cv=>4%$sa z^zaTgRDl<_*hq_^l`tnGp>-II%3t|bHFC$b_59RPFdHLB!R!Z?rBXwW0i}mWu%3Sn zdFU?7wHXhO*tLyhI}*|9MshqF$px>KnHJJLUuH*|$2)Ru9+!x+g3Y6@Jg|9Gip?Wu zuf^UYpmemtzEn@2!IQ2m&EtW%%bJ{zi!R(eJ`HT9+i*GORb+3pLdU?wP16{HXJBXO z%x6n=Nes3*WVH?-sLlLWAdmmSwV>nXFu1bfkHn}z-=VyW%hVLwMV4$$;mMf2c70Pg z4@v7>Q%L>n%BJw|ND-StG=tI^AU|(sMKzLeJ44 zRp8Yl^%{1ep)m6XrF?%dRDstWjh$izhAQxmvsjtM&=m6UsLr*6oR79i^*jnx>PW1c zkn9eQ#QGm?2cLSUo8Jx=`aJ=LvpXw1cSyFrM6#Y6t`PjNmY|Qv*aassULU2j7UGRu(-yKOXj@3Cz`F&>J5R9N4W;u_hUnpO zeoCsqYXqfXn+;Xqy<_h7@ZPt4J8pzMliw%W}XJ_5DdKjbLWtdHwIaM>52=7OWM3sBTay1`BfaFoDKFF?HvIUMY~ z0-y6f>fRshyp3|!1t?Ow07a@mmYo#a1Ldd~tF>Zf7UQy$V$&=pOSb7h!@=r|^xfF! z%KcadKZ+{1`8WL!V73wEf{p|UpjdHDgKiF^TPXo6PC?!+L^p=f%|zb{qatB_7!?U` zgi(?3Y8VyXm%^yrCH(<(PHwU6`XtGHRY zkv|_bcW3I|hxk+EP+~yNgS>_Bi>6h+#em=8Pso|3a_%*EXX@R%`4dT*RvD3V`x?CF zwx;TFy!!SiK2mrH^n;+k1NvUjcZ0rtqTdYGtXwzSS&8c=JA+M;mWFfnm!&lx21<7* zn+S@pSry9zv@t@R4{WSZU$@k^EwvVuhUG+5sV$bmYuH8}KkQJ+cumIaeKsDHenNDe zrQWvGzUYAFNxWRO$h_{?2X|*9Mr1`?ZLi=VTW3Jxsi6gVhT*tpfB5AXbEw0Dyz_Za zOHyBn<11@?YjU>F2H%ehEo*yftF$4IlxC|m?m_hu)}rDFxO};^W^DNQvrZ0U_rKj) zwp@O4ElhY@CflQ&*l2l|Ke!bGA!)N7f~EE&BoXe@seE|UbIJ(!+_EFET!#@)K zoA8Ig?}1mH&V`THL)ssQkB27h|AD_3{5Z;MANVXAd>ABaW%D6d+e}j0W|AuKz7B51 zZZMSjbf~v~a9wKI9Vf=)jk{HqpYo{rK%-c>eeb@zBYy82AFmsE?m?@!ozpO%KR@Hr z7MH(H)?EN!T3y)_H4|;abYVXOHMv`dVSk=Y!`^}0$5_{SvJhtskT*G=S^#- zY(-_?g37)bm3@<~?AUs+w^P~kWxYq=?;eb7{6s4IC{W)NiceLJgc7@ZQ$cA3V`sWf z?k)y(H0~CAt1QL_ppRg8f*LH;qo4)}^$SoZ3bhT?=|b_DO6ID|F9Lg$0~g%`sJf-7 zT&!Ln;aZ0)ycZe6lmg$5>kzl)Dt8?qFedC$y*h~)xD~V+|J&ezQ zxn9f1XElk&c@4=>750ZGaWL_)v6G6%f};Bwg7|N7-He=e;V)JvkG9Tdo)Ha_6N>Qe@EipgO zRc2hwJl~#9LME5=9?`so2Y>Xd;t=ui=V?k2L6li*%Z74pZdXwRm_S# zu9_7oH7imD^4vi&?BFRqbNJ&ue}^axK2}f3->}<;-Z6h?B!POSpkHDr2&TdmvS6)j zq&lToAbh<1bfL%c;CdnR@4Ffh#Hn7oup!(JEc`Vu!!YyHaUJ9u0@@6-#}rzO&e*|U z5xsQvt{v0_?Vv_WiwR}n)o4fR+d<9JRN=X81JgPi3U}Lv??D37{{Z|$;XeqU1^a#Y zEW{tcXWo7YpH|4WR|}Dp79uHa8x-4W_;x`dqWhEHk)30VCD~J+-)aAou1xEY7UE1h zUARnd26j?t2*)tg$=SI6MIDR75YB#I)X5?}A3{1`r1r6*TZT+q2`Y(Oh8OOpWq1*M zmf=eHEW?Z8vkWhR&%9g;pL$^PsAWh>%aD}5;i%X~!xt_?u0q7SW!gK6O%Jv0yRf#u zj2q#-qZo$TruAOD5B`YD{sxP@e8Q2l8<`(8IC36~?*T;jes5Wp;*$jrPS%lm+Y(#{ zOJ{nnhtD+K0H0dpTRo~ZQmQplx<`~^YYku5YVB%B4Q~SFYHbzA!Q#?uE!!qgozUc) zSTpGoO+H~YNlG<#2cvG7=8XYB7%NDaS->S{8Pns^4!|sgj@j02cgQQe@q*Qx~ zQG1GYrS{q(HM~)htGz@Ay@&0p{Y3}mT zs!r!ugUUP$yB2rZ&H6oh_&kF1a4)tbA|xr1+K7S@W5@R!Ld8>Rcsk0m%( z;NCb=NjUG$2QO#pOHzYrcj&;lITONvJ9MbW0E_842R_rZzznz+fJv(iDJ^(XI&@HM zE%^oepDlPT+F-#e7A$zhKCglwou%OQoU&bC@C!}BH=2TPG6mmY3!an~JSi=B#aQr) z{m&M>*56>kD;6wx#XhfsACslv&;6Wg{9;q^&8Fa6Ou;X-1y4!~o|G26Vk~&Yf}Lcl zUET~1ui9zL9l%*bQ;yW)*e(g-uWI8B^5EiIH`%ydi=N9rN}X(}(?MyAFw;_4c{JDx zP}+@LWvOpi>RwQ~OWVVsGIt(N;x3zXzgZ8@I~U{LFsF;aPmf_Z&%?@xH$IaoH76Qd z7B!ij*nH^-;5c^;&vqcrgABLRV4UGj>T*zL3B{)oXAAWsP$vuZA*i@ed;YKm|5plUYEu&kA4Ci+J|{J<{N_kp-qF0e=MiTKHGOuY>;<{3QIh;m?Q9H1k;l zt#>)}qeC82YQ3bi0aR?Q;md5jFM(s~nQNXHh$n`RA^pAq-vJU|xvausl-ZPJ_14v= z>kBqmBJ7SQWO$HPbjdV?%g!;mLyl^2tPx4oYu1qcj5XI1vsEE`1mil4V04EZBf+ue z5=uf6$c`isLlV|%jmxTqI9RhMa#)8PL%^}-5=uf6$c`isLlSP6B>2AUg^0fBDYP1T z=f|{1?3|eQw1xZ)6NO8&AY8wEN0<~5CeC3f%3)gYnu^*e@w)LT5{S=XVvh+?Yi1+a zn&fLqPRzPj&)H~t2E43FmR(Pu@oU#cge{~U!mV}a+Z~$n%ajFA+nSq}_UE5|{8J{? zT)$U36)f5bjs~S2=xmFjN}0}*i!aK@DyYN86f?dJ29 zT57PR##m~mr7+SmLjo*&o6i%j0`+B-OLy-YP`cI89ia3*=?6irkh_nAI$x;gL0ur! z8=%^S+6d}Gq3|ctnEwNJ*&MNPqx+;69|q}R%xugDGf$z$oMDFI9{s7Q#(YV#7OgoR zCQJ?tFDTu2`99&5T#|=IbExdy+6zo9OC zDxz^W7qL@WD4h%|fo>%$HqL&Bb-_aYg=?b=m8Is^Zbw9YRYRX{N7Neg+NsNB@SlMH zW%zOMw8MV}{>AW@AlxPJFNc3AeCB3%6sC4Wq_iU)~wzMyh~cYKdj`@cwS70_H$c)q{Bu zD*U*>*)ulNla?<*9AdC8JmQ^?I|D-I$S@r79*Apy6r4IdGe|wFTq^S>SFq0(Tqy}0 zhVwV@l%)7P#xon0AGw1eslzKdQXG8UON)b)76+*UDFns7gCL3pCr185;4CM;?5tXf z)2l@nkamGuT8&yxvuYuwY9Xa+QH*L)tjpEH7bN;;v6jF29i8Vs1f)LDY~ ze8(ayfvLFGGTcm~*{!IxkW#gfQne^XwJ4TGEl+LqcA>TGm)=@*)oB-43nnO1iTHw# zs)dxQg_NpAF{(weE>}xO*7EnX){?7MI&UrI##%TqQMHg#wUAP^C`Pp?mPRc*b(mDT z7MJhdu*Kz5ieBlBMOUhJ(pVTzxW!#&jAe|~3MthJDb@q}BJ5ynvypz-C~bL99ba%M%*uc_Tu<2zdwRM3s?BW+A?6|ISkiNQ`)O-YMI+X=k32x z6i3L+C)QH_Xk2c4jD7m0;W^A|jg)GQl%80t*xd-L*p6uJ;4aV_-*q`Q)SJ0ldnBbb zp7XmyY738f(rFD-B+(krE>>G3rCKAUT2qW#Q*1}Hc1Ra!ts`4|E~T}W`oD%xO0 z`qnikYg@6YG#u+!UhEl?0oS)KIj3!2=_G<|@A6`!m+GldDK^71nF!mWyjVl(rlI;a z<4I6Le;|Y4S<5Klo{j%~qEe-kPU|;dz>p#QB|M%YCzahEL{2Ol#HT>Y<8$9)d5G+b z>v7BD#?IC@FUGJb=eOjC8HhZ)d3{q!mJ-Q}<(vCIz5Wi9W&(8vWf^K)+ysg-DB{M> z#lpOp$vS8{KlTgsCq`isyQ4A2n+kPZ*&ZkZKh*su6nT*5*5op_(RBO}EiZOv0gwlt{jfz^J1JW(B1ahyRZhv?%D=>oV?g} z{PlaY9zwZt_7tA%aySpoiv(JAeDu*N4yci-79(b5rQ=;4c9M8M4>mg(isF&K0 zdNC@euke&Q`Z+!#M`~7V4mjzKzGLX-sGKs~$qTe&Cq(3kW@3kn6l`C3;ixrHIsHY> zHvIMV(=Q@tfbe8*R|g6Y$LGGB0TDST3eQRS%hFDK{m^@&>7nNGVs5=SF(PNM@KD>7 zGwI+5e-)Jj(}bM0{ELfja6}GMk{6S|poabBmRqB8_^>TlzfOwCIazpU)lAPX7q1@~ zl`~9u*5j|QpOYhUI1tN=&BI@qhqt_a)Adm~rwWg2Kc__Gux54C&c}tvP0#R%oN|o| zf0?hfH{ABEXnHDy$8G1!BXUOMAO|W#n%#DOL_|(y4su2bkK4{yM&z89gPhUA=t{ELh3tcaXhK=WeD@t0*kz2s{LM)Sp$zPuP`M;!gr&5Fq3NFya@?!z-M z=nm^=w(z)eY9ewH!t-VPWqMkF^4|BNa^?sRU)=H2lZeQv4anK|__Gd(%BhRUsg1}< z3XiX!TSv@ljLMlSJVTuHBqMUz!l(3e=dZ4X$gqCqN94?l$f*y=8P@YB_ebTN6OmIN zk+UENISs-y(8JRVICREE5}au!D9Gzkw!<84QJow<`!3x($a{H2`b_4{K8Ov>$dE)pI$Ul&H?tQ4MW@Ry;>8#dn)m2{NOvWT2j z!sF}bj};I6DJtiRh@4dsIje<-`eB+cee9s8qjIhko;M5+Ja2VG&KlwI^L6~Y#cArr zRl?(z*P4i&uLzHyuQ#86;NQ{oTpf|~m57|L3eQOX#nm|N_^(Ihd`);Z;;&y`UyaD2 zX7Xa+$6vaqANwg3PfK#`5Te23jx(=`$hlT{eu$uZfvP=s)hAIo*9i|AT$`S2BXTe; zL0mUM4%?ptzqijJQ8_mV&vr-7^$|HY3ePw3m+mhQ)qEC}a}(}hT@-DUub&$ua&8tL zwp4rIdiJe_7=VQJbBpkB{7fFYn8^;JdjfJ6E;wdHR1Qm1*L!{a+!K-WtsLasD?F|}e=8#AKH(XJztqpO zJ^o!3P0zO@a_)=B!LSKw&MxOW!sF`s{)n9K<{;;L!sF`syAe5Tc{)nZgAq9oMC7o= z=t#~FB67YTk@G|083P;Z4(f@9ThZZ%?fD_$c>_FO07du1h@6Lk=Ec~zGxTRC{pY}_ zoF56#TKx6x=i!K)M}#N4oJS*a9*M|#EC)G17M@q}*H6!55jj5*o&)fg?xt%d4Tv%MIR^KuSyei4!LazxH6Imls+z*A1A-+3h>=a<5>5`S5yM}2t} z3MX7%uL+OauKqG2=XK$^2!9!Rw+E|WEMYls2oLAozWux&k@KeTP)p?L_0^|mMdkcT zc=#Dk4^VV(rsSAsn!g6Bw~@GhCp>;!zqw;@o5O>9 zbZ_Izi`{^~jA7XBSE1Vs$Mt*R;hKzJ7H_BG!acf;xbk8Lfrp_N9)HngQ8|AQ9!yHD zoQ)AV?+DK^_)9r6U;5YbsGN6&$F|Sav=CMR?q{Zc9YYhr%-ke_38Hx9pGMHYs;5 z^H&wKM0keaFWtJLbM}sw*Z<*8UaXH(-#>}S;fN(KmR-)j zg~x3-K8?uvPY!ZE6P|%idj1oU!x2J9>EUZMy4LNtW1c*PaG&||+xL#-;C+gaoZTXF z*gAD2ho7tlpOJNo$muRTcR&N|FCIuPnj9@JZhoH^bKBMK5jm{IsrRf-JnsG0s2uLH z8+>+?ACXfaJlV(U*sL0I)*`*Wo(m#!*c#-;W*VLefB3&NeK$`A&5Lm);LGV5k%JAe z!E*q3=;rQsOJy`){2(|eXRnAH*5XupK7R87G@{{ljE6-8*U$0Y}dI`^$s2sTTYu)<`4@acFo_j^) zu$Rn>`Eu^tTr@D69=?#97jxwt5RtBhHCT~JCJ^dnb$|7?5=OAZ*@Nfp<>!*K24tv|YSSfg@pY-pF zoEVWaFd}D=@C<_t=IiXY;>Shv#Z3l+?dqV29L@yuV&8@g+Qt_?JSQHNbCU3o)3=`? z5jjJJ=PJm^$936NXPyw1bF%Q%;qM;cp&J^J!%XIMnesX53QE<6p6 zoKqum;yK7EkI0Ef4e_TN9CL*JZoX77|eka=ZuH^j zYg{BQZfBBOyZG+kKCN|lOk5L$XET1WEIxRC10;sysurF%@YgSk38}b@93BjVc>#j% z3#9#)#mk~{CJN6s{Po+GGa_;(2@gk`SlIBcdvWNCQ8|-^hg$M&Y*Iwd6yaG687$MH z7p_Q?o~gpK41fLfOo_-jQ+R41gRb(1A2dbNGfjBdD*AHHjL4ZTJav!(!mIzvXINYb z>v@Louy^+5OpnMpOL+V-?ak-k_3x-0_L9M|-&qkkvvQDgw(u~)etKp_QjBHuJfi$#8FkTWgv2ZIc-Dg38FPO!+nrddDPBF7r!M2n0u$VnDy zHpnC!*F6Tg#`3H)$h8)E&mi4xsBYaoamQKYFoTp?WVk^FS)|q=H(SXo4RVa-xyK-b zEzi>iIm;sN8st2S0^+^7O67G^%hxZkSQ_WTCOw585VioAPX(>fkFCMq^FsH&9lgf2C28m*#=o) zk;@G7OPii=8f3Xeo-@cAi@a};%Pg{cfhX<~i}W+dQj1g@q{9ZMnC1DOpwOCf&%QU>j( zkXTR6`#v`I!+^{V@Qeg+NlCJ#TfHnt5&;W(G)fPIkW2`=&skgKP-$nSwX7(o65F4r4f3W%er1r7nBPY2g>s<#kL5Yt zAopA33WNO3BF`J-ix&B}K`JfMA7w>X6Z7Lb#~`(q=Z6MKSmaZKykL}h#UH47@6Eb=Xb9Bf1V$snIvp0WcGHQZKnn8}VlCLmGH;X)Fknh`2pBQAjMfzj? zf$mU?Bn)!8MXokTGUk`g(*{{+c|J490*eeQp*1e zbMT>_xFX9l(I9tO3EBWXn6}iVED-7~yi@aoz-&&;jC=FE_^GkV*L3XpqN`pLL zLp^Dbk1g_vK@PFVaeY+s7>k^3kXkGG8iUkZo?jW{WsCGYTIGzhp{5w*Da&(}LE@I@ zIfE>=2sVH;&d=%o5u|?vDUTr45u_%7l#UyJA|v`bt|2k3p?N?C61l}i1`xT|MI_Xt z2+=1HYORY%sFy5487+u?1pET81ab9kS!VYHT17cAqfqaSzx?hF^5dD-xbgk^!GAT6 z7G+Y{uME_B7a0P;+hh^`y3gcP<0A4N5Del>>_iSdR(Hlu@yr53^GG2#0%3Mj$eTc} z3n1HpBm&5x$H|%7PN=a!&JFOi0J+>E$mwAG@Rs#(ayp1eyNihCuXGU!^-#}nsK;GI zLOpL0O1%ZKKLua&MLqY&ueBKerSweAKkp){XBRmMEZ#WfiYil+=b#{>|j`HKOB`6{*ues~uk_TR%#rSMrG ze+(dd_SKa&tDk|){MUy$u@9u`Z*h?UOwXTBad-wWJ--hiOwa29gjMC$05TBB%K?P? z`FQ}LaXcMBn4X^m5T^P20fb7t&qW3@&9?;*ruo_c!Zfc5AWZWm0fcEjKY%dJivtML zJU@U?a<|hRjSXb%JzbX}ps!se@ZwL~7j0GLtf`pVWdf7m@bxhyX$z z_I8o}M21Xp;_A(hxxE zB_A%&tw2TxczzG0&?0V{S4*1Fb$Q5=x8)E2{FZ*_f*;;t&__Oe;UVCy5Doc=E9c6H z9DSFDp*9#f!b8A2QS^#^!K8FtIcp+v^jjE)`WiwpJ;Fo4d(X&G#FcYZM2^01!%!!o z3@Jx=2zYCxRDHyi^OcAk{a%Kl-Z657hk!R&tPIaVBKf*HB1hlJVW>3-#q1#p?0qB6zTiqqFzp*8-t#x$}45O@(SRp~yoUKpSQd z(m^@bh@7){1Mcky4|>H9gT2s9DDnhDeO*GK*%3GJ+n4`26>1M@+c3f~p;~K8$5hQA z@Na*9xsHPm%kLQOZJghwPUG6;XD?3Dq;)#3G4vPp~$gAz2M z$P>)_4S`T!u0FNOj|tCKO(^mNL){n%b;tG}3x~%0T@#8t!B95^LY;E_+#jXldcuSv zPcYQYflx~xes4`G)XOFmd4i#Ckx;Z+y7rfTb7v~l?@TE21Vh~#i0kU|x0a+r{lkPJ zPcYPNfl%ES|5i9O=G}*?Po7|?Zv;X;)^z{;R9yR+P~-`Qx;+r;AH|8gQ=yJ9p~w>q zbw?o7)Iqamr$U`*LXjsJ>P`v8cA4(ay%IO2LRFejnwYbvWJjTtv# zy#I6Zn5xPNQzm=Emn0h6lJViCHIuM4aMRrQl$!DN4e^%Nx_Ep_zy297<>)`A!mF9n zIzG`@m1tQ&a!ljg`o{X!M6FdAq*Ry=!(+E^laPsvU#$H#a64cwb^=WOG^#%c$mL(&b>n$S}OW zJx@IzpCkeOJ7vzDGs-LD)5snM%PXqNkTKku9%L^spIR0#ufQMP#qr&7_kKlX74G$u zdkx9Pd9CyNhwn2wy_N1xV^j0Oba-uZQ%g(e#_)2)WTRUax{Dkzs^#h7bJN4aE8N_a zqj*I~5U!}KR@p7d)~RB`!9dee%7d+xBbm;9QJrdbWVV~9?Z8bbuMAR=ri`~)W?G)Z zPfs7M9~x%jA4e9C(|A%L2ZnA14P{=kbsALe1g@wwC4^hkGvAt#;TDTKoivtrI-CWb z4quu9cgofYR$i%vs|6U*hF_HeA)q7FB{u{sbbS+Qyj%ScCV*!T1-%E1N(vWgp4ily zXr*k)tt$`-PZMPLv6Ei9aZ|< zRyF`8Ib0F zDm1G>Ftpz`J7;-QixH-2elrrig{)376~&idfz)X&9UUtDn(_Ta3H?kYDNaTJvu#^c z-CWyo)L(oiOD5R4Q;J#870}B6J#Wzogo=8gW=leIgW3K@i07U+JWR@(F#wH4aeyBfpfrg2R;2`4B0NJz|a5)H`i zzg|pZYc{<;**5t9G`@f_&OI3dORKH2cg+V!u z43|u~mp9I9!wEuFO$$+{+Bgjg)|sFp7^t=Z#}bWdYOYPTlsCdKn-{kw!*-AIw5%|h zrrP?}`bWq7p?jJiBT#7Iat#Gud4^%Qmp0Aj6-Q zriLZSF&G?RA`q0$0Ktk|c1F2GH@wU-URi5Ov^F)zr!Ma$i!y45sIi1-*NY&24p<{qSR zg|So8jJeb$TUwi&I+qZ(xzZ4&(@KZg;Of;h37%f9IS4RgTc?~m3gnNPhxgloKs+I? zGrB#)j3bAacP29S2hp+>MRiV4d1ZMTBN0K;F?T8}#!Q-%omK*^Bwdcg_7jT|=ahw34UKv0LFfmc)@>K=-)^@37`(kKGTR&3rqMU}|&Ly3>IOQz8Ks zq->@tWMk=?)wJ9geMmPY-Ddi7N*fO5XFB%GT@VIhevc!(+3bkgV+O{uJZbkM^3g0nQJ?o6Un#+^Q()UMRLo+C3e+3v{b)5{BuR7K}mMq{p!RILc0 z9W>Yh-dyWSG*E8UCK4|98WahdeWVp+@33B_XU|r}LLoY;Z4vh11S5ML3Y*@wl>OguFthGDypqB`5Gr4K9ZntQ904VxP@l_G7~ z+3Ge=$s=k;a2b3O*7_GrO*FT}hXAf=N!GSCV^OL`*2wW*X48WDWPBiA znzSJ*TNat0W3b-J=dI@Fr1@=lMPg|qe%6dwwro^$VqtQ0qOlH-Lk0j#&Y!P8O68SC zyVRt16MjgpkKAi&+8USEH`dK1V^~65LrK8PeZr zF=>i$2eMSk0(P|0rO$OD>gr1AqDLp?+1Hbz&nC1VL5Gm$7T+}w)#ol1A5MEVy@cm4 z{<>xePm|=XkQz>Db~S|3#KlVU(AnwL(2aFcyE%#tr?rFp2fJoRt$`b965BO$!>R31 zvw>testw?2lG{asO?ug(*Eh~>%DqRorQMpC(~#^`xa52%x^&%6M0N%yS5PjUMObc* zVM5V#woOkH>kf!;6OqkS)3kebmX+pS%Cby3cClnon0l=O=t)D3^aY#c#;0Vjfe$wnN&Ba9cDj} zCf{H?Olwz(9X`BfM7*Z#w2JuHk=3I|RgEu?m$%?ugx29Fju<{*c>j@8`wbjCczFMc zwg$}C@THsjC-slx;kO@jTt#(d)tJ-pg;K6T=Z&myVY5Fni8s^gm*{6S@c}jC%YCt< z#>GdCA9dR3>T%<87po~6RUIEWp>o2Q2^C{=4yyBEe*!FD4D&l7R-*Zy&EL*rRu923NW%9if2A^%G1(8x-4OoS$N#0i@+Ddm4$NZ5x&B-e2dcYwI-LfGD6?s1N6nns%N_= z(echaTqj_|hU>U#102&)QV71f#}D1^xZ;J-Unt)FfPZXw z$VZn>-g@9Yus6uNW`B@O@*V)+e%K9U9WFX#E3Lduz}JK4@iKB{PTw`S_aS&LH2Z)s z-gN1E1NaZYa~XEgpv#uN$G|gxfbwNa-Sx?;w=hzrnM=*#jbzye*J-EO_=e`z~aX*8sjT&W;ZFnO1+Bfjm^T z!MFM!oA32ArH}b7z<2APm@nBg$vXgi$DNEnj>}ZOBf)n7cAlckB(E9w#)5}C`O{@e zUq1BwDtOjoUnV*$kGn~jJt&B?Jt#nXwihls*0;E{2dP~rh?DOC@br%G+3nuQCVWR4 z9s%%2l+$X)RZguOcS`>>oD0e9E}V)mnrjVaQqmIo z*|)B~d8Q<9=A70u=O>d5*j=HiZ_}J}yrJH(qF9ONb(f<_=6;3~!CyDx%Z+I@F<4?RxF&(8(8G1fax^5gR` z%wD+m$K`J%3nO(e!IRor79|^7@CN=wynH=Qwj=O*d;1i+@%b|0x9^6HiF*`% z`q^injYNmhI={XJHE}|b_cz=`Yi=FmuST8X=2L!NU|Q`=(?0N-u44G%ylzC8cHCpP zPS>NS=k@ct;h&Zrw?{cOlvjr7hx_#RX2jxxdDTx8rIaLp?S_kxryJ=U=z}!qP0MufNFbr&B+EldxE^8qFVy2_)x+-9_U8PYSK}& zM89@gUXy6$<{$jvq?(`B1(LxY>m6Khg^+TCm5pzDQTpA@1uO8x4jvU&{lhY$9iXhe z?-(3q-_G(vQMJe69}IsY{6pZ+fL{V1JIHv4!oL;%VelFDaQHule+2xO;bTwL_KooS zz-RifBWC+H_!w!me*tkG2me6$h^zgJ@X_nH9}OS9b^9>*=#AUw!^eJ4?dQQqFWLSP z!q=jH^@0_&f>xK>L*Pp~h5Ij~g>$%;cI86UI-ioK`bwba{2< zq?$>S%O_5*8C^NC5}8%rBCle?w3_}Sm8GV7;)H3_Cr_`gM6Q)#AJ53h!c$D15#>`W z(?nEah}8PfBkO>6<)eL{0U$^6`~UQhX5yhoh++KT>mZsEOnda8y-K zm;zj~>SLFFMtifL3PyFbQ`ms%(A{ zwy*OVu>`QFwYjDh^&-D$ybWB@)YM>(cs`WQ`0%bFPi1U62QsRsc3!j zi)Q$@gV_l1F=Z#G=QAb5`0w*MB<=iqOe~W7I68)gRwKXYtROaY=tQUcU}>{AuzMzm z!g>H%)H)vv9CZul$b!F^1sgcNBvRA5d{Gk3YJSl}tU*$}q~49L$0wA{we#^=V@qvw z{UTN&=KD^tmDWr~sML*87zXx%s94^bY^mu#P)g)}E6!HsQ~5sJ5*!xoi=7%w(Od zh!XuZIYvKF%M|{}Gmi^qyVA4~O^}@|}AS6`#u+O)ty~eCE)?XHAo2~d5oaYx^ zmBvmdH8tbK#$;VRKV!9JnzD1hKa=*wm;ky|YX$6S2Z>zyevMNMQz!f5&Ti@M3>{kD zSl`lwZ$KB-*N$qgm;Q28Lt0VSW+MU&+R=lG*Q16-$^{ zKd-)yyL@=;zKep`(4li$EkmTg?|}fU6{E(Cs}#%ol@y{Ty3{Jel z*sTYg{mtuo9l80FpFNYfG}e8*ZgyK38}hIHe>Hp9nj3F8b?%hC&V1!X-Qd44HsJ7m zhZW8KS&wxuFYa;P!*9QYt*=GSyZh{Y-;Ix6-Eda->yDl9jq@-W*&7iQ#^&!e|IVXc zJpSb?U;OeFcYckVK28yQ;MMPa|D^Y)4ch;`FMof)n8dfReYoH=kNaxRk5Bq#>3$=( zoV0c5rAaK23Vz^~|Gej+8AE$6{{3E$zx2Snk6~W18|61P9P@*d_gi+;pkwy^@cJKp zc9rLyC-}N4r(ZmGPLEfAeS6)ef`0vqJ@03Nj~#UWHBWqd+t|^w#_cxo`cJ-xZNj08 z!dSn9x6fMJaM3UBKjWhluYYX|=8lsEUv}Zm+edGH<>2i<>~py{w);422rKxZHOF7q z_ruqhe0X;2fA)GfcDd)hDfoMPoOk>U_y2a@%lpsPiDx`;-^5en-RqNBKb#`?2giQ8B zDtJqB(uS`VEj#kpNBr@;|NHV^CSaRi!Eft*LcDO!fA-(=nkH{(`wUDDkH_PI!r0H> zJgD-X_doe{kLDFK4qA3G%B4+kZ^V9;Gsd3(f2VZ+^X{>I8t`gvTF}3 zyV>L3>}C(k3e8H(%F0S_R#;Y=R(i7{GyDE)?S0Oi8D<6)`|kJqedoup)>-?%*M6`4 zIQ#4qJ?Y&+n#p9;W0f3#H4p?#Dql?#9-Is#(5;N%^ z_|P8*$8AVHP&;>W!q<2Ig7&q9b&q?FSmKN z*7XD8gZB7PJNzpcl8Y4!oG?1uijysz<}?VzX(5!+BMjVvTMttYP^Id`0Er1c&3`dmp_^YguYt~@NcUtw`kbL%6{4aKwbB9mU|8@G2 z*Qc+*fnymR@E(&LYmIT{ms+m`DJ-?peS-B;>l7A1P6ByTE^h|I^-Ak$d$h*H4^W}> zWyL<4vg0T=mEPFI8Dmokk8#G>#93u*I0gKVqKY6AIEc6b@zwx=oJu5N3z zCj(9^ZgGPGMeejz#m8!@1n-N$^b`+sQ!V}RRjBpgvBZE!nI{y7NgmceNM;re#YG5u zekx`3S&%gLaX@hq;;`b(q94{g#=$j0#4FA$t^_xpWl4%Ni&StqEK66MSzHSa({uRE zQ=C~m3ywmI5E~U|7DKV_A!Uh*Gm9c!R;tSqu&#kAF8mHw9Kr>M6ylezII{pFrisp- z6DJq`c7MUc${hUIu>g;f{Dgn16n zKkNo*d`8Vp?u}M(FA(&nCnic2QO}KJcH#i;#Gc9ZHEDIs zdPavcO-GAZrc+w-Qa}L+o z>e9WM@BJw%+EyRcA8S2Al=XrG1bp*Tlx05cW<+ERq6Jon4qfJzOtIAiX@wBD?|0*G%r<~6EkXZ+?gt2;qc>$uC`E8GQvFR;nf-8 zp2W!Nq)5NmQV5xzchYM*Q)1Zngh_cQ70*}KZV4BjKT#F=qKy_<>*R~}XK1|Iq0#8> zi&^kF62DG@_Cbtb?q>YQq77uX<3E;lz&(WjW0`v$|D}&z;AZ02TI|DrJ9Ah};ti&) zMQbEsHp{L8M=iG#@6V7pYR%WMj6QYcVBCY?sP(lL{{WZHuA9J7D{U>dfunZaTI>Qx zt+}=Et-UW$bD32uD3f!-_q5p4-Nd5Jby5`R6}?}_plGjTR&7h)G6*xFNRi`PA~^zf z4v<3l8NV3(v}-yTl1D0m|E8&XAs^zmk%;`X$B(pru9X>Wno^H^=ple&c@q)oZ+KY^ zo1|`r7TzS)4!fqpfptTWSBZyg5xoD0Z|CtXg~zwo^Nyli$HsTE(T2iy%m%y!xGRbpw*z14>tVThzW{|z$Q2;GmE{ttWKBt7NgAe*8*iV zwFYBW_-Azq-2Jnf{7}^K_(FU}N$2Z~WVOB@t(T@2l)|IzqZZm7Kf2~3TPP0KtLzy8 zUSlR99V0XQrmbEQHrial->=&k2K4*;JUNk`ifGuc zuogc><%YE&1B}_c4_2@ts9tM344Sn)Am~_)?F7tpJuKQWSafN=J+|;Eu-I1| zK7bf-zi|&Jm47GkDE?3;}DZ_Ij#+k`{p24F3%S!GdF)J zJT`WVHn`OrijVx64Q|0o&$saULU$>CtvQO4bLukc8Ep7<5+3{yUbJ_@m9iroKf0)$ z;&BC+#!=7${QQfS{19dlekY^xk1td3qSYYCeH3kb>=&dUsVuvoGt=8lkG7C)^f>4m6x0b&sv)EBlLbqhELh@X8A?_E?@t4(Ipz}{^}7M0qe3yp)-N_kYHaoBP>-QQ zJ>u7)MteI{jQ3k$#4GJ?G`I}pSSPLn{#`1)`a=a3jvrm)(WRbas891C8{}7?$Pd{+ z+Q)oQtB5{BQU2T?S0UXQc&dZ)G7dvsfbcLhQq>{uTZ4726m~3>w8Sq)X}jJe?J;Kg zytf*AB)HjL4R=|Wh?8}RIJ4M<|58?~IIc?>u*TZN)~EhxQL!q17{S9(?(N2>T9 z6_k_z!R>T>nxyEQFilasrg%a}pFu;F+H+1se9tQXtMO z$Ye?xm4}r14eZlSRBeuCyNT5VZv}s?GdzsOuM=&|4^h2)!qu2`|KUHaY52dMLVjrI zjZIdfO9%Yp3z@3#vEtWLlJS)nXW7_k^!X$0n;8wVTJ!Cj)t5kZ@Yho){3VzR7^`?L zsx-xEGAPAsimKvcz{|`fPG&A~W>Jg(QnpobvWk0aIA%>%wXw8rLpkJM9lJpmD(9|) z`%u5?NPgPmN0z++R$X4mIeoJk=iFF&{!-k;yjl%C-n^1yZL6jll)|h;R>3ZCxa35W zC#rf>LuBp{Cv%55*>6i3RYEBXyl_=@*s8jhx@z10YTJQo+hM=1#*-Wgn_QQH)qwe% zry?R;Vbfva=Wn6+OENvl;pwUpM}pTEWhh)SL!Cq({*PiVP+640#fo1zessNv#9aLnCzF9!hMYxt^s-OD0X4`RNdnwzC zdnp6MS0?_qR=f~dhCBCF$j792cI+7!AHfWZbuNvixFz{t~Kb+EtS3&@!O56L*cArS75!042)A66;G|#;s z4S+NobKcAtT8E|d(AAbXqn-#zTbigZq3iw+zCva3*F)91rD-?*YkDFY=)sr?n5Xcc ze1ALqse=vmkX>wP+K>O5o^}oNP`R}<-Kj8(H=ezvp&shxTbgzm^h7n#L#EdopO3aZ z^+!WJ9T;PbkEMYgDuI@!f%s49s$2CH`h5TVAzRH$%g)xT>dOA1I)0Ht=OBvYb8&^X;)E~4o9WdzW+CUEs7cf2XpW;)wdh8ty^-z2D zP1jis^w1!28vs&bnlnl2~-fwMx=XmsBcAlrCAJ zBu-duQ|_t4Wq2ZIYId%jIXZ?eSEFW$y?#| zHA49!jIXa4A79Jbw|m#?i?)!{MHpXS7eV4p*SJBGr+R%klrO^g`aeQ zcdsv(@Su|ouwkTvKA@DBg%{CErX}Xk+l-0WkCK>} z6Bi%!ClT=}!@U}?$;yd6#zpiZGdAwwo2z+aVq)=CHdYp&H>Oc+tPy%u9=_^(HO{)8 zkTNQL5Pc{NNA}{hLq0WEJq7ZfwM^fb_7UP!C-URam>nh>-HhM<<~h8dD?VWvM;`!I z->%j_Ev##YTWq5Ips)U6;Zty=B;d_|IYB_!`n&;&@&67a9mOBylmPhD&pcqC{E1G( zYxaHsoE^!>v+EN)`ubyz;nl@NnP3DLXx0a92A{zq8fc{5z^CswLJ=wcuwIa}nB_@Q zd_;3o4qT?wnVWtZRbxj_d5?JFqp1?&;`xjytnTrBzN3IH{phMwJrc^?KjHFttKrhm zgz}LZ&x9Iq*}#G1fzE__)U+69LY+0Fg*Xt#W&mTuhG#~@N8rAF zL88h{LL>$`6UzCfu8A4Ol^KTdkiG<)^L_(dVxn=hPo8Pqx$JG?yjNn7v!hn|7St z4_)+T7p`FOBYp7-!$ABCl-@9?xf;09w2q4_l)jr3hJpAONS}b3zXA6*OK5%l;eRVI zKPen_oPqRF{45A)0L)B@8{4dz=1(MRTNEHG`(mHH_E^mKsNE^0>?0h6q7 zgbq{>NM9N-tVz)32Ar1*^|w z$A<$GPp97C3YOk@xH*8iOW}gWkMeH=FiU!e);Arv7lG+0_-a49fj`-Ij< zpPID_pSj?f`BjF!mv#^~C^p3os8WT(J02c{~ryOIJvJ!Rj;V`yLp} zP>BnskIdOcz}T*AT;E(^Rx4aEeblc$1OWDhO@W?*9D`lbWp zQMh3GsC_&D%-kfYFIf4~n%hcX)+-#L1Jyt3FJA=ax#6MXNBRx`(=u7&g6X3b#dg5_ ztZ>1~cO7s&N0`KW_|Zk{(1GH&2F?R)Ch_4&iKDe&y*?Yp5!8PaUTqS8$B!-wm-YFL zBWT@fhr$q!u0Y|E-Q5M;)=^%4dbsRM{v&u9DByiuPgw{v#?skpDgwl5y zj^_f`c64Zc-GI9Sm@I`0ROW}gW4_$(Y8D|m`#)sBNYvTV_7_fW=%0H^l?*aGf1gS4ryCi)_6-H_c zTppya{X~r0@uMr0zSv0;!$ABC6hE?SX~11{ZR7gJD@-VTRG(eIrRRp$N5iEBz&tTo z;yMM1-+su;r2f)dANw-y{y= zM^~`&m<_jc3NZe|Ps0T&k2*NM2+ZFdUR81Eh0;cV(#^ZM`Fs7o= z`W8dq0AMy6aDn1?47fwUd@(z;zNNrfiX{dtUxD<61F{;phf6~1`v)|9q%cZd!1hb} zZYah4=(@)BJ*zN{>ASYfBnrwy>$@6CRsyqE;eyS3$X*=><~vtteKaoaUSSdw@uMr4 zKC&-!fytWV#RaM_r0+Ul{$;=gDi5lEJAhd;w{d;10Q0*67f9b$=sT;@BtFBBu3+Ot zir??R44&u31=BYUn6t0<;)11jFfbJcTp)d$5bmA8jJ+YWzJb8a2Ie7!3uX_fe4hj6 zA2&*UKK3tWo&(N&(ev}&!2F`yBpW{g2IH-N8^{Bz-?U>S|6<|{{qaw zd%Ueu z*Y_hZ{qFbTg6W$IjN<_>E>L>ELwfH5#=S=3XwO|BeH-B1;z6wYJS1^Zzy;E`0P@s_ zP2yer=n7V!2gCVGV9tI-;)1o0cSs*FXZ^#A3lzU-1T-3$Yu8C!u;)iKKG+V-Nrel; zJ?ryZ_gMw`#gCc9EBMhBEFDAP`~fiSpYX;nP`;cE=R{y8JsDabtl@d%5SV`{Trhpqj!$J0%jjI09?W9De3F@EXFzb(G^S|_4}p3 zEP1YReJ=vj^7+vEqT$>Xn4T{*u5ThR4=G%*_>sQnfO%tMXnli`#(IU}1mjq}6W#`L8EH+WBIee@Q>OknmZT(I&bdw&F&`u~L1N9Ei5Q;7)`Ke8{w zfs5Z8THjFM917EzzBRxt|17jVT9?|QFroC-!|^xZj(*;_z6-x-JiRpDodn#Jy2kY_ zSC~-o>jX7#0{7{@#`U%PQer~sqw($t;L^WpT;BqP38jzf%SPZf?+>l77nJ-2%sF36 zT(J6A2V8$(qP}TdUlK5d3KvS>O~6e4HnhH2gnK(MuPR)ybst(s{|uOo2SV$+0k}g7 z1D3Bq_K(Js(+--%{ojSwcO5kB1SaW_#06WorTTm;Ft;4`;sVVFzX$GhVE+BR#F=p) zD1M!gv0Z+^c=CwE1)JAi0spIj`B35X@t@zk_BP;t2d4U{)EDgen*+{!fVuJ~iKFxe zN(bqy0>*MIw7w!Z+ktuK=f?GQ`~~Z*_|X+Cely^F6qt$iq4j+X9S;Cg@ted^{~IWu zcf$EmVCMcVal!TrP=EeDFdI*V)`u=o90KOmlcDudzkk-B*hhgMUBTKBt%r>VW;7#$ zk0X+RyGdb4A63Fw0v_2Z=Oj8)rM^~Wu z(KzvD;AVDdT;IJ4!^(o_I|2Cy;MR9-T;G=p6G|V|zvICD(5-QO*0Urgls+2Q4F;~) z*`f8V1a1;AKPp_Xev9&N;5jWskM51@%L3+r!iCb;@7xyR?DHDemkP{2g$t#x=lLx} zM{8((R;0rQj8owV9jLxg{>=lXut#Wp^t^jDFuN5ln7&@9&xe8ObfMH2to@z~eUlUh zEMI}*w+$|Hfx9Xubo@x)bqXW31x_#NyA8N;7d5VLiNZ9d?-Af;U);F92Nb3;eVc$= z*t2nc&nZk}`aT41H5qhV!RFoF;r5QgFcANOmB&Hgp1!1UeP1a|WBUFC?#gT@$}4?dzUwZagNuNJYQAH%#GcoX385^z5%tlV!Ao9K_D@pwDD0^cfDhHJq+ z-uG*O>jU{yzkrJe{y4w)77L)SL}9@4l^Bip7X5H` zxO~tA9M$ImIB$C_owecb7mYUpedC_O9S+PC zg$oug>01lThDP)eZZ9y08^O{3;!X)NZeaQ1bmW(pYxhLg_(Isp9i3j=&kslG^S|8D zv92?!s+P<5Wm-f`Px@sz7c731j-9|9ZUjf^5Q8yp!jCRppI?Gm-*+ksa zO~gIhMBK(E;$ChdZgUfHuQw65y@|MYnuvS92{`IMK5BqV$9W3$6$|hC#8%+G2Cfy( zgrG~-zv$sstF`~gq?FW@k!dMeX-V11qlR3NmzI^BH_n!MW!z=4u@?kzPsz4rCS{M! z%o|}Fo^y3xs%@Mt^~(4F$V_~6x^T8LwJ;ywDxY^{+6YJ92>J2H5fnZ67-1Wkl#`mB znlgOI1+&ZN6qMrQhkoL;tZ~Vi*(3ao#=_QNNya9sXSi^)o7>`_S5 zevk*{6HU`Un%OJ!66@GfB)#x@e1grIjFa{7aZL;&eukGA{In|$?RKhm1Ns~6Yzh`r zX?rH6X$^j(MJrAd*t|UF4E4e87&`rBWMQR~zl)5MRFe3c%qci&r)-+Nz?qmhIw>h> zoX^=TI5Q^0sH~zGpAL7>=c18Cr>8I`mgDI`;Fuv4rfV;|{P?>!!F41ocmU8~7!Y6Nw*Pl>WXVOs}tf zF~6H_tYU`xO6M^7CRv`*#Agqw7M9I%#}P{DepNR;DThvK;_t;OCC;+MM4XsZZVb+^ zM*lTI#ti&l1e)-_2z0>zBGCB%MWAv2i$Kxzq@8~Qbd;a{q_)-<^27Lj9?EX`H!C)w z)JnBWvsP%kFdk$=4=WQ&hU7>ihNOc!nB006jy0ZvgUvFnmOreJ-byg3&JTxJF=H z(+*=9%>}eMx7q>KG&oQPRCmLf)fC=tbl07P9w#)}&Z4Cr?s%0b0O{i}^{@*r@bqyQ zBaBv{G9kxBL9GGoWwgUC!d_YA#Br(?OPwy_@46?K6qS^*L#?j^&W#_Rg>q`mKl&&} zI&{;u50Rq#n+^9=+BB|n6F^;*|5VoPa8GfiYbQQiLS^#-=mgMRppSrl1iBIQ6VTT1 zvl}!V^gp0Epg1Pgy#Vw}P$j2J66c5TnTAGhh z@{`DBiW~CBP4UCy@djyLh@ktxpB95#yZW{p+F7Y<22LfmShhh%hr@Rf&VY0UWUrRLh7|;FvzMRXED53EIT2TZ4tsb&H{YO zhTB~!t}l-W$S!l5glQRo^`NJq9J(pI=k)m`xA?5v9N zQYSv(TT-0rES`?ElHUnB!r?3~0g67T!%?=vMa9lpL?`5T0{p~DEgks2^-P=+ihjgm zNz|cg#F010iI1Y=Xxcoxi%yYs*$Z6qw0??Jt{&!Wdu4-I8I9LSluSI;bQ(LLu=LOi zi|G?sUQ6^HW3c%P#YUFsTvZACBOAT_&T>Q5q&iLQs6TuzRPuFbM^xV*15E}+2jETz z{THYMbUi3-fqNQsA?UwBH-J6^`ZDOVpl^Xb5Bd=(?3ep@(3e1|Spef61d6efI~jB{ zXd37i&|J{hK<9vN1-%Ir<4ia8XVB@UH|O34eHQdxP}&Oh9w_Z3+X;$YJ>mmU?EVnD zKc=n~Llpmc2U&!BIC{sQ_L=x?BPpvOVsrrR;F;zmsR zX&Y4--Qaqvo3EYf3V;4<7vyIkute>l?36rJS4~XWT2WBi^*^#!p>3I;YXH+mB8qw< zew_q{_N6cu#%_IDN!eU`nPWU!hQ+cQjgR`?F8J8SS-3xj``gifchP1G++q2c8)_ny zy|{cw8im{jjSbcc%uJc3WLyu&@P~hLA!z80SZgX zFdMBt8^m)+fpqoHvf%@C5 zFOW}G{Isim7vE3b!0zMIIai~Vc`x#FIexqG`zDmlDsz@QUEW@jt(Fy@0$gtI_ihZ+ z3I8^0thRJ8K(5q8wT+B{v4+dqh80@*DWjUB`D3zwbij zErw@VE~m2$E3o6}`215HqerWSTo(e8V@iEJo8q8d#8Y0O+KCt?oQHZual9VX3VK6; zdQ}NIS$3^sn$np*A?5vkB8@ft*P+NyH~gmKcQ91isa7>eyA~2W>p2eA?VX?Ki`X4i z+7sc9PKPrQ)>M9u*_$D>_C$khs#csu_-a83O6PJ5z05)vjoG|ov_zK4f0P!=H<&T~ zIY0^WiPBdJItsK5bUbJ|D5cp2>fb&|PpEu+6Yin%@ldFIw3n6^&9fEbBVkV2SJ4Nl zP9Yz)I+Tb=pr=M>*Q`vWK7dqdSD-w+1$jhy=mw=coDWKQi1{?G zKdySX;mcd~8a#udxck?=smL-)j~(8NL#sXB}r8g{WOxiQ#^cd?ZH?qq?BY`He0AAGxLREESod z3!`N!%0MzJYW6ORmxfW15R!%MBWu+xWc9+wz?n2`+?@|_x$7te9BfK(nY#3`Q z?{`s@KL}SE*@rYfGiQAd-brABN(?y^_mh= zABBMH;6V;pD@qxvhHXcC79DeAasv;-Otscc}itxKe-2*9_E8 zs#h~Xvp`YDdCXS?N+W^Upl;A&(B+^dpihA!+j+fz4(NNh2iA?bqnHQU9${P$Y6W%U z??cc9pdC@K7lCGhVm#TPT|5k2Eq>aX?_=oOjP2rHxF!0v3-UwpC;DZmc42oo*q(4( zpis2y47G&-RrEZR4OLO9ADsl&Jc_ZPgS8f3_DIeW-DCB!rb`+8u=zgfTP5H<&EYZjeqZ&#T(hfYPgoRx1Q&H!9hlO%&_XYUZE-DkMZxqufm2f!9oyuzj z=txlf+*3iX21T7gpDV|MDWLb`{u7YM= zW`NQ<3+goQ3CID({6e5lb6*2G0dy+pM9^uVlR*9LbUyr3?a*q-m0f+mXuBG2BmC+k z`H8|0;fuqe>Z8`b@z{qtHZ2r*)I$X8_Kvgkj!hdMpb^5rQJ+SGCln7~dJjhZ{$M2} zLUE(=ppg2I0N1VP*D1bOQ{w&$^EEfc-4md{Z*G2ke}?lzA9tR?{J2f!$L%UV?oj#h zw*dKZ5AyO}IeCuaRSkAL*+-Hew-e*P*tHowMz>e z_s!|b1DG$G{gHNR=GyvrQ#w~NCF`k2v#`C84?g4)5>-=b)pVWP!8pdB$};(n@`mcE zaUOXOS_0+U-$BW4APabWdLL*R?jHbs6!am`J)jSRc7l$zpqZeLfcm%ZLg1*Zv@G;* z-~WP}e}6-MsJ*~`h#x|gALdfS%j~ln&L1g6bs5@rgSwmu3^v_C0S#lRo1oUtc3h5g z0ycRbvl`nx#n->huT*vXE>*|x2Bq|@3Q)%}7o}(WoKGO)PuM`?_to3BXgE(IKj#2j z2>N5FJd$GHiYAg&c!~HqoJB5sHufr_kCM|%lB$Of^o?tuRmP!+T3@*1 zq8$`8s^aX;!_F<^V#wLRp$npmis1-w`m8mtkfyCh^gh6f8O)Om+M|((TRDX@0?~VE zK#J`F1*DEV508TANeszpTu2I}D9=$iZ5kG6BP{!syr8123}5lqy!bC^QklMlAFl53 zwO9F~RYMFioDO{HtcV`V_@rSJ&~LLJJa~%Wwc$kEa?~7lY=h*TX>!F;TY2IJ^{K6^q-*A=dK5( zbm6&&o1*#xD7E<)K@Wm%0zCwZWn>-$)Pid^~yIusRC>R#oC~F8x(7U;vG;2 z=zE}4ci#u~w;3}cFm^_r*J|biXZhNEYikWYyDl#;bU2j*JtXJ~2O8F5I#yKZp!#cUim$chhhCJg zv?@x^8)WE(J}}JV#qR_nJr>JWzzoA*9>h_C&Jyw6t3N{Wh5=z6O%M(G8_WrGZdlH+}pji=Bl z>WNZsI0yuk2rO+0;4QwHzDhMLMV4mcXAK~%_LRF}`7cCKJl6^e>6^zE%Q|>T1m8s< zTs+C*NB(R5gjuN7`1&CB>-aldS79&1zUgz|wnBGP55%&RBUQ6|bw`>oSS+jb`*}XO zUx2850y~C_Vz*p}VOu)2He&(%*K9l+5~JF%Un=Bf@M|n&fA~<;OQ*DJ1YhC@HJRzyXfpz3{z6FoYl=|`nf<9~@wiAyw626~21*h6fM+IHj*Ei!YA8+~$08|0O?2WlHqqg~W5P#-xCf=x;ug*{5tXLJCi0SMMkxR1oM zd^hH@q6=s#Xjf1VXgAQOLC*sH1QaI>@Olj1ar$Mt3~uB+xX_Ye92CCxaG&=7G)wwS%qzEdYHA)B#E@ej4aj(CMIE(Gq8X zjt4CSEdnhAT?$$b`V?pd=qAv)p!-1Qftt}qV9DKQgWd=l4|)q|I_P}RIiL$b?*&~5 zx(#$O=pInyiMtMTDd*MnY#2JmmtX`p!I?Oq7_Jm_PfFM@s!`Z8!+ zGsaM$lR&qCmV>?ydN1gkpbvt+4eCEe!uX8m#WZQ5YbpkRIe6m$$>e!)B;4m4H|ZMo z_0mS(TV4E*K7_DA9AcHg@F)^@PUwK?;p>`iwBOA8><4od>;dqdKaijPKodRctp^46q5{8h z2p2r5*Dfs>+@s)6sj&Y#FmXS!pQ#OvbTy@2#!CXs3w>I=3lV{S^tPW42W#Bl|y zhbR#`x`>%^+-dLBF{;y!W3N+nF_gt4e=IzSmxEtzfQDVnv@e(S(2&+=ToErvV|sXo zp&`X>ums4fI#gsi5_sH-a7q ztp+^-N^{>oK&hWU3HmlD0(5@`(h~Gf&@fP{o2@_xfwlp?95fu1)+8~G5LVH~(&1dH zgIQx!@tSB}PL?fid{SmwR(4WmcFLHmQ7RH4ObU^ek~TtIDB4*Pp+jCg%TiO-EEkq0 zik;;cDRsdnPZbiq>oBMsV0w2O-;#4 z89OGAvL*|q)5cPawuQ(9T<Eh*rg!WRSe7Em#H+4D-BBb?<0Wrd~arepG) zm98@T@Odt0d0zZrY~KjCbO8?UlNJ?DFLpYTim*eNR1D2`r8~&Xpy1a5%Sw(>hc@SUbCR7KS%65K!52-(6MuzWkvSVk%dKg_N;en9pO&T zkn>#`6?ht5R*a{7sH@=?JG#Yu`K*nUC6^S-h{B!jVfw=@whkDIx*S7>R21Vq>^yqo zm!1+1b(B=(7diV>U=KItpcRk1hv7ZdaLb?|9;OwQ*j;}3Xy8-NQ32$QDJ+7;3%3l@ zG++UL#!&V*49l9~mX2U0+TUH*50xvQ$J6W1D-^% zU0BBUNZ&Y<<3eMg9E|`H?}C&$?T*>`1%=cssXaf9^yIs;3THdAU}fxOcvKQ@d5I&c zY?^O8bc-Rwr+%`$@Oo#S3x-k*g5R^7o(2qF%3YKa%ABEAjz~$-9A|tgww>9_yyYV< z0${su(Igd3FDWZ@&6u5xB)Oa;VNV#g0qIw^oy`8ILMP6BD3~$NYsIky6>j-Ms{%A~ zGlWEC{7_@nC_aI8w8jX8s}bqQqL`O)QBoCuLXU>t0~umKCTAmuqWU2n#O3YN&kW{z z7ujgNi{nQBH*O&TijM7SJA^w96(KKgb{zVz_PD)*dYB?d;T%{(GMfKk1$g16)b2vN zk}0D6|2TldkRck7^Z!D?Mlfs?EUwd`x)I-o+6kZ{uC~;BE`v84vP^Fu#=h3Sb*P%fy&9EvG0aItv9q#NJ~h%hA2#Nna7~cKXQ&8q z@b+Oqry)boV7Rosa7qfdr=wg;wOoPGAbWEj>*3^jz2L>-aLeO?Tqpo9j;d5VgV!|; z9LGJ{olUG>2^?)2Olzr1E5R}?^}tuLZ3r;5@fH!;U(RJJ)n3SD3_VJyv&_OKGij7R zy$!&pf+q}M!}S4IoH6K@y+)lfkID{%4StJ@`o&@g9b-bhQGbpfa*EoYHprrY z%DE;l@T*Rw7Bc|VHvJo(H*)dZ;954;;0Dk$g>Xx2Z9wF}7|g+K@NG7qL6$hMXDZzC zPrs<4BhV{)6x^v%=4q{xl6pTfQ5tXWXiyCX$zr|NSRTjI91!7RdBM<^$WbE|^?hu$ z^=8BlLx!lVm5We%1ZmV;9T;C!QjYyw@HWR;>F292eBBV(S0H$Az-I)6r_ylP7zEz1 z$ACIO%7zSqjTlwvDo6JE#fH4lx{ZHkAk8uj4ZTo|-U;ZXA+{&5&j-YE>~#+~d;q;| zaA4L9d#RKA6si@8=xotQk$m*i)OnLBm!0=W8WbmRJ4$6MaZL#f{z#|O!3$C}#_SQe zH3P;Cn8wAexZ3e_1HA!-(2kpQ3ZF&9uaHyw`HZW)SBPGKj#46bvK_QfA>1;FqmfiR zy#ldK#W6%KEZ$&Lk04ZUL$^JUBpd+bLU453l_F4Bl3y{6`|_h~5@cCtIq4Nu+PJE{ z49Y_r8f*OrwI9u*%sH(9&sbe-)%`5KW;ST%6vif6vlsFWPHIHQ8*4-Z;;{M>Zn?;} zybQLU>i8eN!xXQpx36@TjV!WHr^h|vmU#@%!j#cI-6<<6cgv+%_nKqR!O~y|f_4YnfOgWIE z>EKE31pJ&0c&V8z@i=abnT68}`A9gnO%`7n4Q_RSG)q|0!ibT(Im)3_wyyyjV4yX% zVLZgXOPT?t2~~y;pyTGwYk~fwJ=xr;hx?ejMLC`yPLE_FAf$e1WJ;=y?a#;DZ1fqm z!T!)%&=4N%`9GfHqNd{x8a}zB4Dg4mqNb?|ZM;xxX~-S#bA?E_rBL^nH+xV5TfWz2 z58H6%(SLHnCWqSaYEJ7l_JWf9LVK~T*i|-<2gJ{^L8jIhWX?uqOPgWyU3xa~4ESrK z4K!p7)C61X!$Tdn8js-Da*Hr>#U)BC@ZO)$Mwq*$i-MYc@dMg zUzL_~*GfZ>JT(TP@z+E|RPRBIvr1*#Is3@s+{NXI!5b~ws3PR`lIZ~)48<%@l;eDe z=hok_8goUH{h}d_Fp09F(iEUIFZi-CDz+D87Z%LYjTl+Iwn&v)-@#a@kk)r-+(66! zUX5cgfSTi!Et>{>yA9=+0Q-ClzgRrvHi1T)?&~(?A9r=R_`vbkU$ZYZwI0LoHb6e$ z!j3~NQ(uqR`p$I`H$40K4m>+${8t^K9=qp-5u9`HOtZKH8M9{OhML|7OCVu3z8y z^nesQ9%Md)2t}K6``i)v%jNIKbRKc|@*_hQJNX$CbSY;je-MD%bi=%rcUN%J9m~(y1P$Q*%L3Fd<)@rYeo2dkJR;R@0mQjbm+f6SeH`z zJl>~edFA}o^`j2FcV7K7y_Se;TBlGodtdFMVe>Rq$-yyYFNI077H8Ex8{ zGkW2){D_^Ota0o&$Hk$sJ6OKt6UQu5r`LBCr+zjos_kX}#vTfmzrXE++@%*!>v(DF zn$;q=6g8+5_G?6&dgS%JtKSbF&iP@A>ty?9O-rzch2{4?eNNk&L%;Wbykz;Whu(i- z8usk6-1fjDKgay|^~CYxlKy$~Wxt}_&q7{An|7b`{8xqf&o18&<$G6LUyuD2EbkH4 zcj@f@@2;DeKEAl_soEUqVfm<)gO*%4y=6_+uDla(M{I}guGrrZZF+o4>n>Bme(iD1 z73Y8I8JE2h4S?nU`Rw`J4>B{JdMtBTV(UU@PwYuz`Jqc6KR(7XB0hfc`76rizUsvD zL+t;EHr?O7e`0k0$*%40ED=N8lVFWfS)Mic$Y<9T-Iv(ed0vkT1}*v-dsJBd)<X6?DdQhD(w7kzuf?>Bxw7N47Dxk&D8n{>_1zhBw<+mm;9 zdZ`5YkL?f9rtD=$E;_L8qv%QR4%##+%ME!R%lqwn_{ieggpvEIGCw)~XU1^soniUj zY41g@`C!Cnea6@9?Az6Y_IQHjOJAR`V9$t)Tjw2r| zwe;(SXm{;N&pAs9AK3fok;m_RWp4l6or!2u$8 zY<0!k-~KsUR6KGe_C2tC=z~S==7yydy}bY1h}V{mjKet%uy2UZ%jf5uHDQ}))yMl^ z-t_Tizh)+X*AAXw$Q;?lM1kVV38Yr(gZ? zk^6r7`p&505$8C27oj)I%x% z&VFM3TL<5pS+@9E*Y>{aa0Vgz$Y@jBS1)Mw?Y=t)thn#d#p|o?OTnHmmJfXBkAvej zBp;}qJ2~O&yMGyj{pBnl{9D(Lrw*;TXVtK2Iqk>4hllkYU^}8shucM;xMycl%AAPv zKfXN4d^4YoBfh|JL=+6k#n#&CI7`Yp4aW_aTYFUw9&}0WZ2ef`IfdmF_9AP!tHM!O zVvURI7n?h$Ah)o%ps2#(%*6w@!jgV7NR49-pPig9&rX)4Z+ySO@qNqUFN;mcEiWs` z#jaS)U}xK1GjLAw9QhFBG<}yB(5i~`+?*6pWSSlYnXCeB;GL^;4z>P{bm=n8PB1N^ zIZ*SXS%5RHozu#juc+K!)O;lcCB^bZkb-$0wDJ27aiIyqT=|xyz&I(~qqlM?;;Qt#&k&@lLqrM-kO=Zdvi^ z#}Qi!%1Y+)LnA%9C^5vCr}Vnap{Dd$2a_|z(+{$Vg@{LJXF3dT$fuDEACrk^D%cBl zs_}Ek4Wl%elw03-|RX}f0xj}-^6qnLt zh^A}zshxJYvH?3N_f$1qjbGV&i$gCc7d?9R%Fm=~8OC3ud!|~t!KSh@)d4l9Rh7>z z#VJv)Y5fX|i<&!h!~0h#Cz+AWij&JxRG5F}3xu{?H$Qeo^dL(Oo0>AR@Tt%+J;mjC zm3DRoHszdl3U!l~Po@S7r+&Ra^D>`K4QqZjIcKA5!45>#r8g%^m1j|9Garir$*qFEj&1N;KAu>R|l`5(Ty8KR5j#1tpuL7azkCy*txXN{8SZs z`wN{jj3#wi3BPOl7b!o*i2Ib&Y~Is?Gl*Ty7|rR)43uY9%h&Yvzi~H3T!&Z@T9Qm%^+y!$Zx}+PQRmD$j}R6vaQXPyRs4AnCw_< zj5EK~dL>9>%te0A+umExr$eVI`GZ?N{T2I@fH70(53Z*YA_R*9bN3p5&#wN}f zn@V_$GsY&)Dr3Vb;C~cV1d+f&#Kp#10|as^>C~ee7avH~nT>D4z`rh#za*PwNyZJ* zve}#SgA)Gw>>79mi+Au}8C{u817fv2(X(klY`}0&v4YCVo}g*}OG;XX5&ze=0+~>)!5uIKVA=)5x;>@BF+{Y}tQE_JRJ-Clpc2sd@k&j&{ zyI3|&ac1!eIQl|Cg!oi(W|4|rCLgej&KV)jEDnI9SVf4#iZhFgvC~7wueajNVih=v zyH{~$aReOB20)6eD4gA_B}Q>(kp+&v&k`ZVE6yyIfuploBE)jVnZ@hiK4sZ<#hJxP zaQ|Uh3+x~v&MYniw})j{D9$WafTI{7ClzNFAA*x{`9yJM5srN#5*MjBvlt9+0sOWR z3l$e3mMG3F-T_y~n%`HPS?mS3k7ad=GmAsuzGT^tiZhGj;J#qlNyV8(TkJ6ToMr74 zXBKJTCgh*8!+CFxYNZCNenFYPB zA!Uv~F-mSawu#W^n@CQI^sEVdBgp0^EOD7Nt0|I2+tgEIUte zW^oC)LoDm7IFvcK?^rfeac1#6I7(%Ncu8?)@ue=K9o*z<7Ibv9#C2AjSybz?8eR6O zF8e~4jm8#C>36K+U`2J=3|+PZ+mII{v^Js}c7zcZA-XHhEdHj;?$Twox@@a1>xI)% zZe=Yl#YKop#hJxnU3Ns5#b75heP^nTC{l4DMH!J*qgf_&2zEmOZC9v)Bxd_FP7Y*A-_L zJHZ`i*)GMI#TVdyXW3VZGm9U<(Ro}E;=hVBi$B2q!7|f%k~51)a6hvwT5)D^4!C11 zJ6~~TF%|o@WZE2xgVD8OFBoubM5^KJ%3t_AAaT=Jt}V5#k2LnZ*OT>|tH@jxKv&m;Iv4j_b1AOEi5`6=xQA=(3f% zY?m(Et;^Q-#u?EZ(<6$D5XTf}7S~*g7Rxy~Msa2_5nKezCMynB09+)?iWG-bf@{aJ z8x&_2i@~*L*;2)s#Y%8dEW1Z>X0a9=9Sk2K)+x>`o&ndEWzQ?lEVh6PXW1KyGmH6s zWQrohBE@0+tjnI%WxwdMmW#22#EOrmp(y>=@X0iTqI--=?#|Fij#Yf<}vTTpy zFd_qoAp&qm6=$ZdLrfE$J10&q{O$gNhm)Vle7^V5jJQZ-T7aiN_zG%Sp|hMf&iXCg z``-3*6qe;W=)p9$=ElXv_A7Pdi=^^$XPL{IJS2C-INq2$Jk-Wq={Q2$C^k;te3j|* z@(gXh8gfyEwHH4z;6vf9L#_C(#29s)a(S;yE#q%eHVzS=QCLvqRPl3`sbK%& za5>$>u8g%_e6f}JV9EdgBp$u^TOih9S6X8)p*&Id4eEqeI)8P&_e7t(9eHe}SK)gB-(=`-;~r;I&6?CBn}k?vW@5o8WAM;JJ{@K2+r z^~RegjW_FRa@He^ClSUvgt1eG;jjM%3dxgp%pp@TG0*e$WY1UEzDCJ6TsfY@83>&u z)oCX@wiAYs5=%X4#`~lq=-3h_4BmIZzi(zk+YtgZ$l&U1YGG?O|X_baxF@J4G;Px~B@RNwnxbYb^FK44(Zp1iNYd8~8P2RNC zLm&>d_1NmGYE9L)dQ=q7jmvHIQ8fw3PeV~Gy3x04FQS8EjqWbo*VGUyqh=*JX4Whs z87g?4%;U8B3@wDH=hCMx`oJ~TsGt;J<9(6e{S4gKEFx5TO$|9B9Fk>f0USy*dUwFd zcu&Wc8t-#)U$cl%P)CkXM>1UkP^vLR* z9Wz@5fh%8%p!P|HHIa)mW|}-X^_iN)5JWIPVT)meJcev+f}c){k)Sm)>c?tqbtsNC z88tbzus!Z{7FTVJgs?WllNIi1;Taw7Ne}E-8LJtrBbEiTd z{5KA5&-A>LUelRs7HgO=DQ}82TCh1Z5TvUP`5Y}-QETAW7HLa@Z%RxK@Mu=ddhW`f(tE*wO^aWrD2Iu>dl$m(P=AhN&=RR;}a zbhyl((c!!26Srsbk(!(%lqprUiO9{J8SIX%MXpwDiLK7rR%6=oax7(cx8_ zqdn2p7OGJhVaWRGjBrn4WOY&`!hlIomSPJ9tJpJUJ&kCeJkvgsT^J^&)CcNW+_n4$@WiGTn=) zg_lWFU|arEl*P6VIYCBxqP(TN@Z`9W0^7psq%cp;5=wz>nM}bONmETSvRUEP!yV)m z{wI=u3%5Ol1|hRQMdi8)3x#k^vVv+}_bk{Chuz$he|~V!ebiia=j8A`ZiDmYJ@-*F zW-ZZ+2pQEs$vP(*1wkQ^0P2TZWyp!vsQ!xx4*-Q5%{MZ9D!FJ6Tb$|^o*FV{)z^f1 z*z#2m5BIRKtG-4Sabl(xp*{Ca0J5eg5&vZZeCuaA*Ald%8Y>WbMX6ayw=kLlM6Y&U ztHb)JnyjR+hLG*48AS}t&&pIVHH#>~bZ;!^(;Ji^icM619`=;=l8MyDK=WhJ0A$8! zq6Jon4vmCIC7HqssJ!ZxLaBHn-*YZn+^k3DpF~;avz`JiItXOXB$ek{P@1o*&55wR zbQ=72aQl6YqF2KqcK#9ZGro4j-46B0KqwbnL+E4cA zYQ)K4k3#m>H%0sQ42S-s87{2`ZR5Hq+Ynm+o=K$|qS|&0-B+5j_!6i2!f5giH{wwf zwmcpERTDtypc>Vr_1IbrRA~B8Vb2d=9Q|zfoNjPOX(yG!WNi=8tQSPp3A`C zFlr$tiKtAn`>kHo3ofXpHAJOZ4Ovs0h7(QGS5p(MhssgRFi7^?M_)#&SxNshJ)CYN z`UqOEUNpGZ71XSxlxG?wd+s}|EUTmwF|=YeKSfQEJtBvR`Z7O^vV=#y8X|fD&2@f? zn&4(P9ZAwdy_=4eNYu>*q(^UXDjpWre(>`~#&_Y=Dsj~zg_`Z$241tf>kaZ!1D|f- zDR(r#(FUHfSJQ)y;4|r4W&Ak~#SmSs%?j>ZAV}pF*mBVod`B(GBgIvoNl^a4VMjKsL-uq&N1o;ZO4$+z8zuO zG42R+>b$*R+OZ(LV4Bf8ceMv+B7d~i0l)Dv&x2(<+T*5m5T7A3#^u0c{bd|_7@G8B z+DQb-t-2{v+}KWQgO}SPZ=}IyDJsYeD&~fRO9i+lFjo3p8~JvS#_yjkZRc_aQ&Nq_y{6N({=iY z*2Wu=V_NtBAZ7P}*SQkbW6XtIuJ;MYlAJ*2mP}_29J)^>^)3(x7Bxf5gMWWt%gq#9mb}Q4 zFI#RQB@Hmr7h^VmDFD*Ev7*iU1T<;>d{BnqW^E^w=8;jeJ|JD1N7kiKHS6^#uOt@z z8YLoKb$aNMNyzc!Y4)N-a@FsVu~nN(`IcELm0;DDMCu+J0%I{sw)*HZ_-{A_M&%vw zj?~SIhFik*&+;1WbFIO~ZZO!`C)rqse7GyKG>W7uaPJs(5lIY7Vu;bt7(@C%HRr zcx1Q3Gn)9MFml-G$)cO#WC?A%Bq}kQZgwvnZC#R9r`#h+v{kvY^1Z5UA%R?!sD;Lc zuQm3n113M0>P7T%JxmH#64k8&&k|()lU`&6VQ>?wPk#L`GB%HgECD1g36a?r-{Ou{ss9{mZZ}oZyuLm_6-tA{DykPeGUZjTClN`vL zjo6hDxI&^LzL7YUR`O(-)}*axhHUtv?XFRpgBrdss&x(Y6ICyw1yHQ*V3y#Ke6)ub zMLomA^ie%#(epR2M=UVKSdL{t849FTn`46vEXYSK`%q|1MBKUoW3P!Jyzcb%DrY2| zHd+d!fYSr}ZdmuG1h8LP-CK{uCn6}i)TErxfz)bYgZdX}7=v$h2d#hJVGNor4`BGy z=YG{tAHeYVr5Aecn|5!c$HST#!Vrp=+gzLldk%blbkF4aH*Lo#-k7zL^~YQbV?#MO zyWDmxs^%<2OZMYFvn)KgupNndZq(F8+oKkK2LIZVjXjeO;Hd{$7b{th{S@H?SW6?$ zVylBMNZg0vgBITE;0=_AjO2b;`dvT^ICQ@kVD7S``rG!->7aZcVc)P;hoaek^n6MJ z;dfJT_&1S#rX5DW+aM<<+J=7bg<`x;_EmenRa3LZ>y&mZgPr8FE-n9%P32pd%}wQ->2R21vkY@=w$|XB^3BU@Vi;5gA)z_AF^10* zH{wRXp#DE_P&FaqQB(wn=%hD+=1C7Q`+sYMWFPo4HO0SYxX= z%nBAI2GUW8&PONUVY`gY!Xk@LZQ|P2H%tn?DuY3->s3?idzC-0Y)_ z*lLD=mpj-+HrAjaBFR4XE(s0PPV z;UmWKZ(z)O#fU<_7FY^@^9g@*kbYXHI2_%SSBG4j34@L>JrUDtz7Yi19h=mQju~6> zqAKm$rxA<>m=1LLQ6*anWqrsVd9T{SPi~Hdx8p}jNrXehnW;mo93nIPx@rYKWAl}H z<~LcO?x0mX?mPbbD)W2Ls?fn1Yn=NEwR8F|9`!hiI2t5NA%sm+I-D zRXh%yIiPQbR=2oa=~o$d)_TUsbH?eHF1|@IlQ&nXa_2yhBtwu^7TbQvx9oiM9{i8L zi)VZLlhJLf?t(hRnySHBgI_ez!m*|na zycBAK&_ITtRa=>O@2OQFvRdqCl{uYu8=~Tw@XWU)Vyn-DuK=j}5pr64JH4tm$x7#r zZC@atg;oqTrUS?#v;KDi!oZycs;?H7c&pqS9f?Zp!XVQ z#=8=CiVu|G;hDVPo`a}exY&LvRT!{cVaL6nMkdM(omnh4xYWbUsHKw&7Tze3IL_{6=oik%pQ;n!;nO122=F@C_;V<)!-Gb{9AZ01h%aAWXY9GjdM z8$ZN#c5SeM&u(THiH&_sMzBK7Ym?9Rtv}?ErWf!%lRQuflDfs{GrGBec3w>pzxBw~f*^AY#%E`@AAf3jt=PF0ey?o* zVJU(=hk5u`Jk~1XCD10|oR(sI2Z3y22g^&MCA$j)z+0U$;iJjM&giqJ{bz`8+$cu& zMElIG2-re7o48~eq|C|?qKTz_^&GxEz3M~?XBOL6mkD1umJpTPbUr#76r{0=t{HJg zu3^T@O63*WE1tjzNVnAmJSi@J!W)_%g>dbw_-n9_*9W{VuAU@68p%O)oui{ z<#Q{rEpJbI_zBMsWn}&EB`xM_SX0x-Shk^9n{vGIQ3A-NX z63O2dpm{?3r9;05x>;y{b7&Cqt7((~Jt$AF1L9KjNU$7ey`TqxxL7(r_&SiL`y!C0 z_6wjj;_tUWw+Q;sp*;MaFSNrQIsxb^p`DHYng$o=wF~VL{Qs%E$5RfG$C}gM04e|e z0Q5NSh%5@!5L^hQ{HO&PYNwSV@_i!1kwM!Z823jxZt3Vpx21k1hh)c}#W%2(D;%_HtT#B9_bOUigdw!6Yuglo; zgJPh!gf<@Ns}f=|&_qEqfHbwofVlK85_}ctE$|^fcm`;u&|U{RSkU`Gn$zQ9HdIC< zfTqjSi9iETTCj-&(7WJiesBelrg4WuZvxGd5InX*(-;c0NzxtdXcsveHxBrV$moB7 zb_se5=qnP-yFlfF{t0xDpd$~qPd^4UNobb=X)M)1zn0W)0@C+b3G{~09sp7vya}ZF z`;+rmh#|ECiEjju>f}TqE?&{nW zr`*%;x~D&IPhWLUx4Eakc2Btxf$HuaAk9^7kRkn*_%NI5wJ=pjk>2B6OiY64m* z=+i(?2>Pn?hk5MA-vG>)RQ((5(1}2r?x{d3{quoT`j@+>*8okBn3n^oCO!(Jd07Xf zd3gy)<9h{2$Yo@1Cx3Pw#S1 zKkJ@;6-fE~9FX#~6G*wS1L)5p{lB}Xs|R9MpyFd$B*+i`6G(ab z29WafcR*Ttx`DKm72}`|Ej?!gY3Z24oI!a2Ir6G zUp+2i|LABZU_%8BdnOP>hp^`WY1j*aG>xf18kUDzD(w*<4f}N<6i9@98c4(P~fD6i2((p+)X#tD`;O(AV747k~y!4!VFoA!wIF9{~*) z+R;Z?O)LfKFSHAQP8T#8h)enN1D?#M`gaXbhdiwV`cR%O0pd0V`N2w{zY4kss9Vq@ zKz|eTBoMbBK+Od74?!J3djxF(;syix!So}MhH&kApc$Y=f|Ic7^9n&{0X-_{JRp_y zWk4#ec|ai4T#$X*;9Ve1@w%C9Y}M(#?jseQXc#rNUc;Zn%5`G zn;#COw(c09DMCBR(N1@?89Czg@ z$AOeDqk+^8eHKXV(4QR29b##N9V!LV)S7^lldV7+^CLjo26+nTMoIVkj<(6segdSa z{Q>A!@%N#l9sV&(|NO|=G_w?65{~`H%-#tAzs!PIA zg8^yXQwsEo=->4~%E?wB<>Xo*<@1jn>UQXeF>3jSakcRy^kf!^g z^Y>36O=C!j^>;Rq#!};GEsnMkNMnA-(f$IYt))XgVOvWl0BO3X18KUKI2yMoQC`&n zsg~Rdq^-1e=Wh*=hW$Q}=IXzIG_|*Yv~BiRAWg0CBpdTlKpJx?klMPlfhOjXSLXwr zDySUjSV30;sqTInNW(q=q#FBeAkE*)Kw67$bF|-)mPdQF6G&~{-+|QD6`hRuKq{F{j`lN0`zz2SN$rqREh+)h5a$4?6fOnQw$B2fJPC1& zqkR@AS7?s`aXX0ofZMcaPS*h)Ewqh5#|YXA#4RlHgExSt?S zkb!PZkslNRMTPcwfUC9ZUtglTA$EC5LHqck*pw&E)FJzIB)`jlm;z#5%&>^V!Erb& z4$CamuR!|CM&8{wk*ALi1Got(-d&AxyQD;O@K!qfcCbUJIgM&Zfld|{p$rBaMIfgG zT_tEV(0oA`I&>+}Eke7>q4_{M2(<)A3(az%QzYg)fHda2fi&jTKpOK}hrR)%F+c0j zCLoP(3(#p2->X0xUnh_%{vVvb4}i`Re}8rUFexflUKFd~aBDE|jGUVbV>7Wbu&6WW zJm%UB@Em-Iy9BqrP}9j(VBDM0WX4Me^!q;U#kkK3E<%STelZOFpnV`64t4$#OfI&?3`|wjGzu0r)ws+SD{esJwAm5OZu@}=_12Hpi z!wm6EgkfGr!A0*Tz=km`%ooD7FhUl+gMwKG4G3l%R2ZytwC5d7_*W3Cz@*Rv#6RxZ zrt zfMT>4)sB4*t9C3lb3$szF!V#!xXWjoIVL=QY_ljJk8I`v%;}#(fe&LvmExj?4upo{ zOZ`XJp~c?3pti|Z%cvKI`I?264Gj=pL#_#ief5rgM9MxQYy<>ddscqNv64txNmLkY$D1f^he3VF%1069 zf()!&kx>(Q%=_HthQ>29Fw*mpB^#&ggGOHG*hr*oBq|KL@TN*5LzNcNNW0?Dy5)Nk zCW&t#FX|Cl1Si7>L8BnF{7f^CMeRe}CAjScJCo56+=u7ah1kz9Gz7=v=1!=3#Wndd zIYLNIO*gjGvjfQwvt;^242#6gzz0aQ)Fus=dFsXs;+5U|-3}vwah;$Af2_M!z-67p z4`ganiBtqcg~99Q=>RbgO4|z&urR0y?h~|cB6tj$x*>xI{z_TPm0ARzsqhW5F9_dD zmg0D9cwdR*LGVb$L8Rg!(h{Mx?RY<>?S(j4lvEto3)(kvd>&bumq8qrJ(LJ%lF|#q zSful_6vYXBRx;*+KPn0$6$KIYyXIR9t;-;>@rmKpM8iAQ(aCZ@cs7 zMi0_=+L1=^Em38*k2?ghqBsW+@&gQXnyzigo|f;~ghwn*d(a2#Psn*)*yLuyQgRo`+drtv~(M{3>2=^URB)N3#j00F51FTM1B6{e((M)QiQJ0^ zvqR>VVb}n<9QV&MDOyq?8Z#z|l%GN^C6tD~yg}zX zbTLqROE&{gGYPK+&o2%Mk6|dha@;jXCsM`}rRb*^_1CU5m3T5th!X}OmF`wJf9MJdxqiLvnWOrS_*QG>|}c= zy0n-RNm;)9D)2PkPUhQl;+U!(k-j}q`0W?KZ*W8I4aLwKqd*lyF#)&)>m;I6V--Vy z2LnfdxzeQw81sIuVuqCM#S-}vN!7|1llg0)NH7U$d>n~Kf|)?+RjU$D$=nj$yuxEInxX1Lp!WA2ZI~P$m zG%u)W^oPL8kfyzuk1k}qKipA<*a%@qft%q{_>18#fqOIDFT%YAF0I4SP8o<)8Hfsl z&E_dii7}{WWx&`s)_>^Q-f;EvVrsEawU0xB5e#%^63_*Bnn^$_@H{LahM|BsJiv0S z7b+WP1op`y*g^C|5%o>JaH2LTxXeQrGL8a;chn1wL}C6>j`>8&e4@f&BRndNVo+LQ zi(mnxN;KD@aN!GbX$Cc+^G> zmuZHXdbVNek&dZE%2c94IV((Q>kwXPiA*)ESF+$k+$Ff}bp${r*4%{WV?#9(!;m%P z%CSCcrY)|jMt7r{>SuA5_0gYTIO7$(ex_j=vKP}VgC#(9EA=kv-veuy54^VM-5|#z zB4rVgvPfxUkbil24pDi1pym4j3N@80K}=`5h;r4_3s?`Ba;ho^9t+V!=ROg zn9MMIIcoMjY_iD({R3moan6R#=2w=CE`q>>(bf*LqgYwB1fL=Xd38UI?46H&TeV*h zu9lfMcBAm>PMNNN5YU_8SFsj+`^Q*-3WbyUv|1)op%Cfli_*H_Uuhws_${#t+3f;* zrM_62x*ASlnVBJ){fIQo(+h}gD+b~cAN|Veq$z8vm8)mqAlH)3o za+OH!jnZgul$OZVb$t07JJ{XDFkxrE&LKHMLfcVDMRC%rT|z02Q*P|QR^Cyln~ax^1gjld3#3D|uK=Z2nqS~4 z%bM-RP-&JxMTT{p#!^NE$AZEr*`Ax%SS!P9+;P95v920lwFmHM%Y=s$ zY8x?)z{RE^gNe!KD^8GJfZWU-Rimj(?TvtSE6Je`|>^gJLoOt z@Deg3h0&B&6rImS=we5hL!_DY`YD=Q_<6~+}@?u$3|e95Mucs-A#`xYlOOJoO} zP(be9pnSP|+SI%58SH*`j=Q9D4foTQ;+?ol;9o$pDOs= z5Il-4E{HAP^XD&1$ymgJ{rFC;W>-aM=!zGm=%pOqMTuVVVh5w@sp$2mnQ-3mo$i5A&AXhu385@Vux^T(idu#kNJ~!~BmIpb?Y(!#f|!BgLe}vfH^vO0e2J+5f)tVJWpH z6m3Q4Lt-&ZDDHLDxrYBWhj-t_LVwrYQuHOB*j@Z?+;%tr+qZ}UcRtMjHa{h#JjDMt zKSN1b!~ZrEH%sb#nE&CYGPKQOp4bfbaU;QC*o*XK`~*DB19N!u8gwk12nF(+O@cdd zhs!v_6oXz2ch6pw@dAX^%Wnd>GR}IKUM8Z9S5`JJz?QpO&RI^bbmfFd%L!37?Qs@} zD0Pf1>&=(dvk)Xb3(vz-%RWXPHk0>(c3r4d#V|CJXW)K2B@5BAYHDs=Y`!7#tEy)< z!w<7Gqt{t8D*PlnxoA?&4w15xC>=YKxwZ_xBS=3Jhf44?6Nm1{^U4s17=|3;z*Y@w zMY+&fG4pNx`ENR7e$1HLGd#_bMG4as*`6ykDbrz|y73}-Wx=Ga4B~xo<`o4-4Einb zq?{#E&JyWl0i|t&f2E~vwbTBLeo21#`LmLY}S zdln&s1l+`oY$qfp%njWa&aZKtCsNK6>C{lAZ3hpOmM!OR=mX9_f>h^c;QX8(%YdEa znO^g)k1X{)VH)VZaDBexI+1dnNJsgU*2VW1TDDx*$!Pm#=hq_DO#1$=Kh&N5ti#*W zO-Rg=^KPmkt3}p|-*+4&QVtR&)rxMq9oFga%azWULk*EM9F1mG#wzf0cz$h2AsL2M z;8D0=&%~OfNpVohBwCit2u+luA`ZoEFXkycPwwZa@|Z^qcSzMoRne-CNZCiERiDyW z^(if+fMJ%VpTE@;OIwgcc=npl(qj|Kc;aL&E!By%EE$+Efh!gJxF{AaXGEu0iDBO- z4EwHf>?2b45fug<2%xl$28l+7W^vwq2y4y!FdZlqa^4F!2x&iC

    b`^HF*oO-F+jW{LzpJGmAp?eQ8 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

    ZKP~cevR_z-!ldIw!M`{Uq+pgdGv1x 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�r(hv)H58FPkHQnVx@Bc*7m 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

    l=;Mx|Ud} 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

    H#ct4FBVDesi&6dc*z5M0}!z)QB#RVdXU|*F=20 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

    Bh|T@!{@FWy{|xn(8mimTt>Tb!N73ai&jh zMJw5|OD{vN>f*}u@!<+fWou)b+|o6c>7xO|eYTdik}X_O>HVp^rjHMIRVrH>=HVRw zys}Lr=8f4na$e~MoMQ`1bE#b{SrWOw2<0Sr(Ms_C9&tkVd84tU3ta&8g3+oy`YzBi zqy5mM$AJ_dOMqNgdh}=S`fnh`+yzaBV&2E2LxJSV%X1aqDDOJOqdM<;6OdB74M<@Z zdi1P!Z2?kzfA_9md9*#cOmaOCNVz%^NHL$`(K+7rJ3u^0SQPN8z{~?DURha!cXoAQ zCon#G>Ep$4i`Rt=!(Q$Uu#ZOFDbq?_nCJWi>?pd!);#5R@sa+pwf)Rk4>HXKs8jJu zzAthj8YkxCM%c{D&0%BpM|e^_NThm@NLyw_TZnL?p&rDdGjx&1T=Pbn!Z$9(MGtv? zy^s~PzKg&%GBY#xgDZ_=W_%&67H)B7G7R!&mvGpYOki|Zk{cGIrTil^IbLCMJexkl zelfGWKy#Lwlz2aq>9Iq^G<)NrIk}5g?+3%?qzSSFWqcj7PkcM7Tk26 zHo1PidBQqcI!_y;)l8&{!L(OFq=xwkGR_^iMRpn?vrr#{KQhA!^%t0a?-e9^3+YM- z!}P*4AJ1kA#7s=6E<(CRdkcvYVq#2`5c`?2gfPvxU^_vO%tt=#`LGK@!Scf&5-gDf zOQaGa8cT?1)>9~GO|EEfn#PzwJ3*ijYDAuC+`JgmxMh-FvhcVsM#5_X$}Bvt^+kop z63M28{QekEEuMIZWElFn7SC7N2oL^36D^S{gDjtnL*>)PDDe`>^x}f+2SG6pC%|St zP6`FbT1bK;lHiC`B1L0~6s;A(g;k!_c5BXK_iBXe@A0y9p7#&Ce{0UmP9*yw*|(9E zB5YW~2j&e81ZpvKHjo5X36xo2?C-W$U<^ZMjmI-GQ+pIGZSWVG%mU-8_O$d>DAT(& z))rltBY`~toB8+!Y$nNzcO@_)35-Yr6O95BtyO^)mQU>rIjKjc4xCA@aKzM3DRhXi zaO70>*^~WeC(HejBhF40@j!FFeRzUP&_yC4Cv5 z5gnJbWb2A%D~%=7i%a_QP}1Lq&3w!WCH;<aV2LDHA~lwxv9T1b zl_G4N7v7_Uadcr$C;x#7G?wlY7^s%%=DzK~hICUze00l?gv%to5-H-|$$e)CMtERh6Dq%tZR%cy85qi(IBsg&K;u5iK;$Mbp2v2^o1d_%^1K#2=4 zIUH<^?)|azW%>dgn@IMzifk8J<_3?=CaW%2m9YSI3u&49q6|Yn+)30awZS{W_|8aE zP3EpmD}7O>7w?OnhQh-i<0TB&}v8yD>p+-R!72@29idlr~EK(-C38CB*~U!t6L?1 ziPs^w9mgp`u4?c%MK}jf{6I0o(9c77_DP7)?ymEfSNY+7wwopW)m3i6G9pwh6_+DD zXP5`ho@@tua7g@Zpk+5~l4|%SXfMEKFK!uZzQ>EOSr`5RHuJt5HdXf(FLok{ok%)+S1UU zWEk09>4cc*muzmDX$4BNInLdcC|8J$jtL%?dHL^wVw#id+##uGX*Tl8w<$mQMiS@b z?3yU+R;uBAe&(g|pW_`UTRt@Lt&{2G%P=U`0oL?`@9m6#X40)xrjf5p2)#%2U)(1| zQsf&Ma@dMbRK83~!~PcRLtxj!#^+!f?tpz5Z07fH*p%rR?XSU7hRHe$@lDb$@lE9S-yX3wfr8MT7I{YeD6cKq~wYnOb-ea-T1X;r?5eQol65^|$_7r|!v zeFiq=%Ql$uZH7(xE{09{KH}v|B>56azM@gSqCvim>+?{8qciU4WT`V0bU)m>w|9NE zbns=|>fV6HV+sPN+Z4}g+;xUAm5b5myfK?F6{wTs7;v~n5!Jc-A{N~Pax~CTgv`Zt z6K*5?U?6pe%YoEct^{Hqp(vQ{U0J9;#nT&)Gn`q;!$UWk#-2EIh+q88p4QEH;yo>f zfw!Ov&%tf=w2qMQnT9hit>nr(Lr;tQ+K&rECib;kZSKf)WuDmcV%&X5fcbW(pn>^> zAR0I#p97nDz8W^AzsgIWNYW?D51tBLyHSJ8pUxl2-)c{jMr2S3Ctn-vY~p&XlW$zS z-#~;CTR$Ln3ySPIz|3PD?%|AzjU6g3(K)fDYj7EcevZZScB=(8jm!`xG_5wc(cW=< z{+;Q^$2?%AEiJwaoB4VlHbwK87Y&g_L!^Q!+S1Tpyz}e0%%NmUr}_f?9PKGoLfGWHcX|cyG1|v@>J9S%zWHk#j^{cELY0=Qo5gk*uc~G;06q{llVA2bu#Iu3>j)*Exh6wPkXa4fiNsK%t-!n+5sjF~ z^NU5nmNAdj^yF5Uw@Z|HS)BFU3fx?Y^67VTk(ocjdy1JvVkVI>^Gr;2G_LD3x3qBf z9!=OGlK0h^qVO~nesn1-m|K?j;h)cUi{7}>c@IP>ZKHN%);o?kXk6J{fI`oj8Yx>{ z{TtZv4X6x5_k-~aOVrg9X4#h_i)~w*bgQ@uqhuazmy*H1H;h0=vxWM8M;DNBAt2OR zOXD-)W&HRV_M2I(x8FRe)U8JmePNFjCdj@+Ftp?C+-_G_3$`@;kBzZWm_Qg7QgWc?U=P$Ltrz{=vo-l zPw`AA64Qxv^_XZa@Gsie$aMC2&uN9}!?I+0qN&26jP|nLpUFti`gmudJ&ZrZGoDC{ zC&~}VZqe3;C|+;yqc=FQ)w!I-0X>A|*=JNK>_9$%N~kEd<0yPX2xpfPPm;G z69U7qirE{_%rrts^O;p+dqsF>0n-j@3TVfKMR>rl|v*U5J?E4t)+jXLHpgx00vN@5V~x0A^Z** zxTqB&T+*r#vN>(3k6*S^O8)Ds>811r_?(c^mI!Gwm@gp_Nk~Nb){Kb8V@9H-6_UT^ zW1E$f`yr%w8xbujliLtdqJ`*?F#Pvh(+gwqRujfxFAO3HgDBswJQi&|cp+LEVdykq z#zMn|S=C$z0o{w3({Iy13a)U>SaV@=ET#Ei7}f%un3$23JQ9sZhos^^|C(MZ&-98G z5iQKHbL0&3+geS=_i#1YL12ao36bPNq&v_=+X(-nCCkP7OoiAF6uIp9!_NJh8>4HQ z7<6*P&zevhe=^I4>wxfP53H1-=8d2Yja6t2L)jdF=b|*SNxe0*oz<1UksxzZUV^lp zVSeK0CnuxTU>>KyE`p6|nTFo5r^2>;!)60D4lgfR5J?t9x;aO*RiVFl)7~Cgu)^C? zSuC*ppXvu$_-X6OP8QSKkVQ7li|cr0-vjVR`O^xEjY$bJ8k#MURkfEDkz_@raw8hc zjc6S&H>?l0R93elA0t~SH)GnARic$?zf4*mhHOoloaSXhB$*K92b{zd?adHvN%>)2 zxTP{-5Bcm?WKx->OcE_k`z6!HD83oj7HusO5{>0$O=;em zUcJMSin}1^yd~Y>X}%3n$f3-Q2|ENdNW%cy5BR1NDLwpgG3{PL~DaVcW(s-wWUF?Br)jX zI-O~Ex{z$g%h;tEM)6LAko}-{7{xVU5P$y=HjDNxA;azkQALhO3?mZ5L?gpQOK!ut zgQSG_CoIW+}))38^;A>Nba+zWe8>>*BTqxRSBS`#a#S4^y`zckCq z*h>(zpV?0xH8B17?B7A)6!Ua2Z075bkaLspa^f73I7g%vE76w1zi3;Nb9W)usj*rq z%DK8WIG1I=vz@H{4#vp|*0NUXi^rMvaJJramPni>QadTyT0|_`*5vGW5No`b80GBQ zZE`lLm)K4YR%|s6j`kcR5(kO&#Te0+<6TADnjD;mSmS-VC*K2oZE(o!iu-LvZ5}_TG!7X_+xq{ zNXHqb9iJ}1ehjO0pN72;+!w*-iso-&GmpQ6&FO**@S>`Oi6kB(U7sOZbLcNV+;K8# zmw2Wla*5|6Lln<6Lln=unrJOZNVKg`x=uF%VF5N6YKY<+W{Bb&Vra|6cMak>Bi1-a#dlVl;!AEq z+94)C%doY@R1UsKOhghBk#?qwwhZqr+Ex(LQHWfn>@Y(V(-DR!rap$YOibMDJ*E{g zm1QZWJiHmf`5@rU7FLuKX5v1e6udE1ENMYEC#g0iPQiuiO~a@6J&Hul3zXUj=jK z<^#?hvw_J3$$J=c6xqZ;=7#NRgywLG6+aCdHg2WCtJ!qM z|AQU>Xb8j5PaU4BHe?z$Y_-!hnqX3?Cc4<_M-zqE@sbC>^>}8~S6~$9_Q;S@Su@EN zU>RXOGRy5pXa3q-G`U5#gTbu!^rpRgNJ4q8a}>H8Eo#mIs-P}Z4_+sK ztR{}b;|$*|8x`TZI~A$&DncX`A<7SWK`}%t4w3blrhYYr=}r0>|CcweFA6J*q;Hp- zW54Ih=ap`pbPqkwE!$uf$a+>F>#YJ=-!x`DE0D9AO4sAk+%BbsIkZOscM|>;0{X(3z5N^-lM_x{@)`FQ=5i3>{Q@_K+dv1LF>3gNf1T zXVzR&RWs?rnKcvfS&OZeMDM;hJd9^#n?)(PBjbupF~T|nmWQS< z=8yA({ypA=Aa@0gi&y-5xgQf}Uwj_z6)8UaD0-rbjTaxjPrBm6cVrDa1~zM0zOO4j zry|qa85gKe-GUOh5#BtO{cBvr^_l9BHiEv{zHRkAId1QnYeq9ZjtFb4=Usahr{)L zqp99M^Q`u?`e&f#*9HVDw+j$iqTH(O-w!>7su$_P6QgwnT|R!Q4}V;_@n84Fn}GS_ zap)nrA20-d^DKYg1Ik~(hEsLsZ^1u6XkzDqi-<@-@&)Q@!P;SMo9g}?#6r$R~3w7V4|hZGlww@ukaQlWbR-3xFf)wsoW{>35+ zZ?1~^3$Lz9N=HYKEtyy}8_l0fFXAs6O_)kFx3Oq&gWe|Gptlh>=xxBM9DjRWOh@yA z&ft+QVIj9N>*yYErKUIyIS!LxdqP9WH7>oeK|Ur{yD|)#{$P99A9yv39*~?^S35&% zOx_v(8K+EC3;mU(T$U?kPHr;ORB5Su${8mdR6!xwYLSc`fqcWM|WkMvG5akCO z5vypMLiE3o$!$nGKF1N2$&@x^lIXv6koSIPrQvfY(Y(n1K?&n~YsOrPC44kk|si8Wz! zPz!rE&@P6(FYFnxkAyuFHuHN4Y_f|hMQSF9Bo-nqN{hBM^p{#CZIM`5-)*T_euk{Y zKaUg@%f)SoC7X5xd&Jr;x1xRpT?A(BLhv{PI( z_L)WdIwkT7Qmtx5BDHNuBOO39gyNbDjnF(OHfC_mu5hiLr3 zo@igE#D0U<8qtcxMz<-kSVPku$@o_0e&<}~PKc#e&!48!b==O#S+^}s(fmp!t40?z0?vH6t=BGbw=II33Om+o4sZk@6 zn29tEDq3^sPh+h%?}A&C(|L7)?g?{K+HTSs@}b*b7n{@~Uwq&#e$K6x8~dt}6Ees# zDSl($C2%`BCJBZ?55^Ws-zfwz6P=KDVsNq2Ljp&|kTf05UQ1*;nhh4a4bCv#_+<3@ zKsSA%YO`-MeF?h&{uX#C5J?I|`Zkkji$Z@Ug^sUgmu;|;G`DnpQwWbQT|X16)S}}{ zCo#}ex}j-E4wk;Lgl)SZxatjG_?Ty_3*SBXy_7cByR|&1=rXQ+Yi;@&$RxV*T>^$^ zD;)Nd*e>8A?Amp-3LxHDQN+`k!5BkSe65u~2Bfv}4}dZk{eQu=7>`p2_JyNs<;&q# z5narVtd&>Jo{nYntXIoN3@jZOUn(CsXv|S1C1bIbGO`>WTQA>w$%Jd>PvV`*V}*!( z;B?MvJOi_A0SDDix)ft8<C)bAPd{enDoA|s=E5jit3q_ z_GKWqFh1k5NL5H3aEAG2KcB&ehs3U^`uHxnuup}(9qiGtu{zX%sj8qG>?>jK0Gskf zU$KGj-2*lY>nLPhYv!}K2vsDn`3OhWaj!3#SZV4n9XkX+3K*xeZx_L`9O63rvl>!}S zXc|!F@;MW(l&v%IvFd|xsEp|{!*HxR8BhN#bvdawCyhS6wq|HeRee=Ob=76K@5~fD znia$znrI8+`*!@!m0KhC>TBcFau*IZ^Gf~Q4))-Xz6p&6^Z#$yoJRcu_7Si*!{$r~ z8x<=9&{w`=r%-Q?0YBB$6RD9Q$`97VmuMS8lxA8L-LS3jx!GDI&_5=S{XpZKHFq@M zzBB%rK?@!I-0bAa`s}|l+xo{+nO^*>iP+uTz&w<|Wgi`I<1iyN}_>TW5-_}QU z?d00(>Z%zS!e})q)VQh{wU{27UN!NQx~hrwaLrQhK7vU6NvC)(nt9-&OjPgg3Crre zu&Hl?m}vpNjD~!?bxJV3bju_+?#xD_%s5A`+vBRQ^P34*jL6 z>zf*iwjrZ(O~gn&K*iMxqmJB$j2a&@>L;F2L}C(>dT!FCy2^@+&|MokZTigW8I_}_)K$)y0!7P` zYo9}Z;_4M`CYhHBc%TSDZ#*FWEFYo}p&i&}nYw!CY#o@d(edY(65lX1NHnsr4Z zY?jmRo^eEC9Ff#dwC2#C%4uZIilddXyaCtugov)dRku^GoC2?DZaW{7SM@4mL4bLK z3kxx$7}>*t8AW!zN7|U`AfS5?U9K&EX|QrSXqksCXTud4wg*;C7rD!)3mx(qpd9Lz|PCR38e&uWwu;Y7h$VQX6(44jFaYoZW z=8?54qwf>ap=k}wH-^-9S@u=1`3~QPO=;c^&ngB)k|t3;3yisTuM)f&X|Gvro9zStR0JYi42m`W48vTqepwV% zW7p)H!dhKD7=3|?nu)q5H<}KDh9;`LUn0sx-5lo_(>)u5u_(tb4>?8^WqzolRLSF! zm{gKT93#>IMl=p!L`&gVQ$w#-Mtu}r^kw2qOV^!@s^90#shN}!%qi6sle6tkCXHL- z%wl@+(cVs-rCvM3rg{~@CbRbP%pwxAh}69l?TOG|+FsKpIA+qYwwMKprR+tBGV7M8 zhNWx9hSqR3rlOjCg_K$nk%uO#XG!fC+|w~H-jw0f@K!c48)(csENsdOJoAXeJR)s% z6KyHd5G_U1x)!4j$izDioe-5baYbu@OT3YZ4*7cQ*i*esblBX%)} zNDLy*CPElT8E|Urk}=M%PEzWlP;*3cu|(+ zvL-rzm0B#B=LvYC4FJxHnriI@n_2os$hiYN=ZM5PBB_>WOW|L%6xHh5(28cYRV>pr zn$cqUag=w-nl-$t2KSkCe9|waDoa-!yM#Q$;=dI~E~il2cJe$U63>X#Xo|*0Q?yi` zm2Uyh(#z7c6OBU&@~CRz&Lni@Eg z$y89=s>aX>Pr2VcT8;fK+J0u3bvS+Iw6MFIZQmogbIbO#7>_edKR!i+RUlKc+dQ*~ z#4I8eOwpDiyl5%RYHaSCiBoM=X%{2b6JixU!??ce1yN2V&+?s7hq?J|XG4>w`4E4c zJ4};xShT{Q8FJ@C&{g3Ri91B9@I_mQ;G%t<+?lwQxN|$=N%Zlv;|?lR)1CF6J4E6R zk+>roxg%N%cbZCic2sx1hgjo#%A&fnDO#ncYYxwtRasY8HK`IsP5b_a+E;Hd`;u*u zOPaW%PPH{_br-ls-JTDd+51_@#l3wABoY^iG;1XqXRSm_;o=sQz;tz0l#3ky$)LZQ zI+`r6oq^Tb+8XPto>4O}%U(tMN0p5s=dKAk$MHBD$o`&lMB*Hg>MqfihW^rY#~Pc9 zJF0(eaqg>jacvOno4?glyjFO*7!AZ zQJw1<pN)K>RWOzHk*?AVaT=hA=f?%xz^irjYwQ0QpZBHX1t$hX}H#5eQS$r zyJyX{Y;~>uT>EFpwGAQHJ`TCIzvmi}xJD$diAJu82Cg-(AAaUpBj#QC#8Vvd*=+;= zdgvTfmqF0)xw)mAaplxgh4_K%0lJihdt5gd1-l|01s~ST{a5$11Ea5e3uIm|u#|J0 z_z+`Z=~6n9w2{9yc0U3W&zKIrjyrIT0(T>gfTtXP+4h?AR?`*#&N0`8c#+_u<}UCw zxN8fXjEYa&(@T%i)rsUS<)#ez9EUW|fp3fLMdoYp4lNm8(q6{B2i`FZ`!vHYe%r$C zqOcKmgb7DjhP);M+iR>u{`nRk?1jm;42eggL|ENUuUG`DnBQ|YS4=1xC(3O$hE z^MB7Bv%(0S6NKeWWvdpymE%;TX+u-liscWzvvk^n!oV5M+XEy%x+(CHW%9HI1?NK?G+rzlflz6clDBHSv_Nd{-u(2n!0shI-m%-sl}#MuxgGZ+O?15l#u` z4c?`t+-bAj)PI|xXrjq(U1&@cop(hgmJ?rFdCh#L_VODAZtV!)Ynzb?l-%iEozLct*`K#W0;0Bc@6}{*XkN6Zv5Xh=!~7N z{K~L5t^eeS0q!d-MGzY)xf26DLAV&#xpeEX5zZxuuD-4Uiz^I3bsY|UHC5du=;D*> ziWlW%9t`7I9fq8NT;*cZNx~y5;p^c!^tb{Z>w%|Qu;t;ei|p4j9|@ye6}s{Iz+60M zFl}~wn(;V8p5BUwCGm-ncr)ft$nWQ2*TMch>}z0SBW=UouwR1x4D6R-zXBWD+<=+U zU?uERVZRC+E6Twt*v$EA*aPquYhVwD{RZswV801_DeS+%egpPjVXueX0{bxN-CMA$ zV80EUpDb7ly9M@punUmx-+(nJCsK!kC_nfGT&aWIf=5H7Z#X|_H0GU1*IiS)y9LWZ zBgzlyQ{vpZ_PV=Zb&u%tbv>7tyu)xC4rkLk;9%!;R& zY1fUx*`0Z1EmqsjD{b+6e?c43G%P&Jb27I1$7@OSx0~KM7j+^MH5086FSd2^m%xJ} zlp?)H5vHMn;B}*&1@sW!GB+3pq|!Vc=wYK_u`YPT5dNi<+^a$Bi-&GBKgBfQ;rPYh zALDr(PrT$Z%;9)wPx7kI4J1jMwUSCM({RS66$Hf%UD{V#djvh~d=KX}c2#-Z5hQZ! z5F=e2773P!5|0#f$xFtcf&ET!KsEpu(3$iFakDL-YMLV5KbCN zB#k7>5AK93dD|_xJ4E@xBS7SQx8Ro{QdgJ~>Sm>sNY}+EzD@9__>u<|3#km5Mq*r2 zL_FTamlW6>#_wcj7|v0!qbj|X~1-N<+twP!6Ig2MCZ`Nj% z<22`-XSuR7vgzbJcVAHfaM(cP@h)Jyi>)Xa5A<8SQu^;bvWYLoz{JZ7L~`1QrE# zmDS^?*Rr344h<{ssQj3(xcn}KyqMR^VKcwq4&}F}mmiVjN2G6|iS{P^iNaMl{pau1_(46Dmz~+&xTUtP2TR&%UGZ4rtMw&PqmliZF3k3^rE4;S_ z^48+L;Rf9W32_fAXeylBqp3V+?ueYG^1Qht@|sEt<_;|Qa6n>|*`xH~=#K}YKkl7Z z_Aqksz{q)}_m(#eE3hn#_bN0NsY`Jt0rBd-qF|1v-Qdv^KpI;u_UL7g-Us@B8P)Go zxK6<1)bC}mGTN_r5^nL2t}x8ucrZa1ycMk;5@+{qNRUqdPOlwYSzTXY^~D5)cLtIV zO;imRV|)@(LuN8r4R;BZ^V&i(XO=tSpmvPvImAT^oB8IvMK0_ULOQ2p`7UhE`om^( z_9$#NXO#X8u=$=h!e%M>4>+mjjYw)sqyzqw*inyYMI3gz6Ec%^SyJ6r+@AY^t3{RVs)lRAm zJIg5*F7p@XKl-({6$@J2zK{z|A}-doM>y|U$m4?#`7hGolteYFp#By zw;8-J2!Vl0H@{F~ub8O^ax8qAS9*tu_kb@0Eq=6#VW>p?@QmFB|I9$K2Ub^2uBn`q zdfi(U&MaoB)Be((^wk8@j$ie5CYZ?loDG}VIR`d6&A72ipT0R4HuE|THW@S)FDzyg ziP=ONVu;op`b$$yY&&M(jzr^k@JE?_ejChAbNYa_O%3h=sle8zp*0uQ9*M)z?U07Q zPsevDh9Hm5Yz<*d^}-;MFo<*=rD!ckP_(a6^Ba+9{1*49Fh;d0j6{puKBoIK=-Z6x zLp;-o#B?GZS`%#<-e0t@k?B~BO*v{4W%}?enVwMk_OafdlveFyb^6xU_&%QbL}EUX zHZzFEUan~AJJ)m8x4_3)^PVZjq|H-oNx~lXypxOAS+(1^*MW>%Knp<7tQk7UExv;c zYESbqudLbZreTFN?!LPN*B(W>V8=$ z{1^sL=Oq5^z`TG`#%TG^?lQmjAY^~uJpLciG^!9??fE``O?h+6n%R9Hv$Sal@Uo`z zg1KXse|T0Tr7)Ap>yN8vE?o1|-i-KK{>OV3f*m*cVM2z85p5V9a%eA>9POH)lGpRD z<$sJi#j|u^-gNj7XXljz`bo=qKjP1k^RA_b@_F<6($PFZNcyQ@KcdS>C!b6col9DJL= za?UVIGVPu!ZhhG&=F0J29um3{gPo#a;>E6jS zpIKZ85)V}!HF`jL>9yZEb!)>s?1^WTmgJ2gz9|ptT3HGV5aaJGt5i~4tw%bXuKUBDFF^`N4y5r6zZ?S#}~#%TcGh@q3Y`-TA=_ zK-BJTJUnVBKlmdM^}Ji~Mu_r*cY#<&y4jahh%_(HveeD4)+54&AIPQhvLQtILHgFM zaeXLY|%tNceSw2n!u7huD@1k=@oKk9BTw-pVdTO3fKF=D2 zX5S!`H`zSmf@hL!O(A7p5Pz1lTI)f5@*w9r#OAOuUU0L_Z6%0tJ6&?l+ z(h4Xonz6ej&+hygwD^^$40AZ1yYbu^trZe|O;rgzUNms}^y*8)GsjjbFg0hGBbn%& z&cZ$YoK7#4i9GmF2}QBRE`OfCt*yaPd0d+kEz~H#y!j*9nWf-NF^C#HM+Uk&lUwRG_ ziGxJii6Gi?_!li@NZQz3l4**IxnLP^CO*aW9XP~i(W4xECtD77=u}S<15@S@({XTR z$iY`b4!#z0@V}meMB*TkI4Bx9C|U{!yEecr6A$-*TWdVL9PaTg%M3#;+!fEeS@5uZ zM-;jG;1w^0Z%jL`c`YH|-h$0My&dxHE6+C~@r_8+fuc3Tzi6p^V=doNzBM3hYsX>V z&w_8PWw&OjO~<>xhrGjTi}7xK$h%HZ3e|f=;vJFJ4MbatcN8s^ck|)4t$4RC3*L>M zSy!{IdH2tdcN;?9eH`+xv*#U=ct<4OiALUumcl#ESL9(LrldC*_-y)Rm3zw zWp@8=(Bf4e!?4(*dk88(~dVq`=rN+dQD=~@rb*hv#Dh0R?X z;D(*KO+DroHjT)cTb|Q2B5!VaUenNmx%gOfM%I55!H|kQuu@phQ9``NWEj4}5qRE< zvOZl83tVqsjp^Kn*@^1w57B=%oE9b6tW+Q$_%s z=gY(6Onk-l+i-|)ZDAM;Qf7w8@B(5Cy zi>+z(k?Bvt%S5@m7~Eu@o`roJ>?I+0yTPCIkx1MnQtc|*Qur4w19!ut1StQTQQhWr z>V7x}r@>vHEggK>pr;WVPm^F)fsTby$Ng<%zkO7bZuwES3@hVH4ncIE^OuuTVDW02 zY2Df>SzZr!mb@N;%{)8`o2B6y2vzbTlDvrW?UTu(EeQRksXzQK;iMb0maw0<0lPV?<(mDa-aYWo493IJ+xDv~YbMuEIV#K1l)rI5 z9XFXCXY24fUJFV(scsnvoB0?7o7`LpPvRz#xJjh@aYTC}^w&Oa@?Q8YE%zzCF|%;2)WX@%5IBJtuS|)wUupjYuZ{1_xOFs3`1?*7tj8!Yimc8HHE)S zFRrbpg#5)x2)jgjNXXw;J%5SBUn22WH1b!pj_{X~DY7o@*5GftdNs=5cMFkOGpYKU zC3BP1H?F%(E3UiP+G)KEUMNo)=ZCy~-1C-5yd_e-D%t}07cE0Oi1u$C-v{4I;pd*+ z&(v$yUo}3nC0k|aXrRn`+*Ti?4x!`s9l1Wp;cz=3lOEULu3KJ_uC32`@S19(-3}gg zN=zoC=rYrc>v9?R%XV};Z04mR2*I2=uEskh_rWbbgk%_2^L#q( zf`4XE4JCHOXfWBoKNdx&SJYM7&n#=Dr@s+$cjw4n$noQOwR8p7bQ2%N^F-r&>YXXf zXJ0&EK6FtA#mJi56YC-qv0}%HFLo8qC z7&_h4uv^i--d7Y<0G(&9*8pWMX*a-?Isva{;@$qIK#eaPG7PJ$tMH7A>P5yqo4BL6 zvTjzkHK^aV*(0hMC)duzT4D6a=2)cP8xIT*V%oChNy?4Q4cRN8uf6Rp=*FT zu7__Rbo>jEQ9Z0^Ll3ju&e}dj^*dVIuc%+5e;!p-cFVqQJ)H@;NKc8Rr$qTSq!sPo z$d_n1!)B8VDeo{C029cnb{=`cgr0CikXpGD~S zcQK=SI;c%OP0Y_?yJ`FM(Qo!`zdk;S&fNc6AIE_I(nlicBT;_v7jRXyw?dT90d+{@ zNi_NUzo(DKBLC9I!wpd%k1|AkJk${NQ8en~VMe1q9%1MjppNU~GK7xb+!ocxGqTjj zM3=AKTIu&ew_hvwP14H$MICt@WFVa+l1>uk2k(HhqG8#>P`;gs6s-U{DS!W;y)OZe zqDbHGA&4<>j*eXs`-QI`Ux>%`B3@a9HaqccD)D(4 zY8Rq+UZ7k{;i49vVm$+w*a7iFxWo>K^k`%B7DD4zKgh=8AVV|UT+DYVZn~Cy1;-3) zzhqcsd_HXlM0CHn@Ndr!h|>zN<)QuB5wFNfC{yFSA*k8hKfc;n4O|a1(TF!(04Qz`1TiA3J z|2^yrPz&;T7uY(kz5JZO^{y0*sao)VD&>t3X#bBGLkF7 zsskp%2Bj;3KIS6j@EI3&C0L2bp$L1BbR}5n3d>R$x`gLH`?n6TI!)ctfEg`rEwi8%7R;g1cL zNLsrTM!lX`ueM%n_f>JE_Cy$8{~~_7>DU#0noJd0lwPXnl+OtSz-&N8q&&O7Mfl*zdv4hmDT6h4PC_GOoZCP?#7Z$t8wJawSlew*N3#Cy+j z-Go+D_OkrNC1^Tg6fP?NCZuO?%OCnc=P)iAmNI(z7q(IUv0sAjSp`v7qwT36$O%oW ze(O5YsOkv0L>(blf|Y{qNnkys>%UP)!~}!th;UII5fhBP>m!~9PgyHSpc7sw^*0=dLen80ZMDX=y!>GnZ?k%_p)cp+R=7ij9fxBUek z9>dLu=>5fr80&)j(reFZgt`iASMTuOs1HM+YcYP1OVkH)CGdi%!02LMV5kqy-By=f zM6WpU_U^lvEG0Kq*2NaA?SIm4Jjx7F^8w3v(vBu}?oSv{m@YW-aQrg`e{3)ZP@hg7 zIkHjhXxq*wL{koxcS-DGqX+Hqii~d_-fjz&1i&U}hQMLhqt2@Q?lsV=8<>7*(^&;OE}Y zkHS!@d*axkYu0#14Ek;VetzncC$yC{&4@xcsw=~{_h@{uO)4Dj=fy6NTD=f9rST%E z%_OBwatUpcOT3jWu(u#DFhiS5i{dXTphp;S4~SIuPaJ7DZ1V>=2&aRL`(EC~z}(v| zQy5YuP4sr_sx%&Ageu$j6r+0d)~=$Ywt##P(w>Css-(2c#DS{?m9I^fsGu~tq%_)- z%Oj9UQ8CFSR7ozON`a9o1;&F#KYHJ9)6?ia^!NSn=p3#@=)Lje{9XFVPW@zuezILZ z*`}Xt)lal94JYSs)_pe70}huI?c_J;FUj8y_cpk<;@$KuaBqft(`5T1$G7MuZE@tq z!;x0;{aI?m;#s~C%0-JL0xMB+GZj{=Tnm-!LbwFqQ*dqOE43HlioS62C;0ZmVVmXX ziVj1iqiXj9jz%2rFHuq$x=de#V~m<9qc7CHA&UxDSc&)k>@BMGIEY&q{YLz7Fohqf zp#Dy;P88>L2&h-5(P)X34th$6(oz7sGwe?wB&rj+M0FyUc%njJq#uECbxM+pbvqni zi<6ftdTF;(tMqz+@?P|O`Zh#@_e+z)%V96}mhqBeDsn*Jm!jQ~N9JBQDQ!hyKSmr1{Jq`quMlV0-mN4$|isGcgqjcHh z)dQC3Q6Gd&*Q5`@o(X$3Y%0eckQe1hE>Vu;66Gi`Do24CJ#6GTLov-A_WhjU5~Rbu zgS0+p*r|8N&N;&#y#*F=%7AxnwJ8J7^M@l{wuv-ns70IU0s$;9@tmO^b{@_fWLr8E z1t!XXT%rufCFTqQ+X#7q8D&5lskC3&)F2QCAFzzEZ!s|UE=LrGGBOZHAbO?Vvt5qt zn;JAPs~7tuMH=%c4OGeTv(m^7b1f<}rRzG_l(y?(Q{|?QVhF{OODL9H;)^;0TQBA0 z#d4I-Bg&7!<59bCM>T_nKkUN*<#Q(lANrUIZOo9&OZFzZJ)-P3H;TbCnQkaJc`=G6 z=WlVN7)~)*x>07>LK|i4 zk-VaHOe1W`+kB%p_?- zAs!9x57*7SEISIWS5ULWXIWll*KAyHtud(YY<+@L~*1;vhzOP){l?#tQTY`_4 zb%YDg*GT4xaEZytHOht0l1mI5w8{xeZ@8jQQ2N1lCSs)ifXobx`1%CpBrv)sC=`Y! z28Y1T(fb1D1jX^G?3qL^jU5;6v$TX?HBl23y4?^D(Jr8#i`xl_$@J-XFOUTbEc+oP zI;~_+x@SUX%?tRHZhp||f<`{2`xbOMznM>8lBWw7@+sY8A>U>pOm{=*bfGxiVuuyc z+F#5Uo||n?!St5RBu>}M(*@$x{$zf0v%KEq!DA+(vJL5!CSV5uD3#zl=*vjY@4`L` z_It2tz)8g5L6cJ4ALWVJfv|tUc^BATlo#&hwNTk$S&;j}k5T_bUq~*|7m_Q%x(d<) zqo*zf<{o6iPwFjlZGKL7swhl~l?qq%I!0}U%G@q@_qEo!@N?HO3Pb%mO{A*yI_8{2 zIqI0rk06@S>zJBEIqR5M1K=`A*FsVn+~dvNC<96t?n?3H>Ppx&-q0tDgpSE2bWAQW z-Uw{HlrvxONGj$V!c*cWhqslHcWLr_!LJ8yEvE>-=V`wn+piz|(%_dW{AlwT;pHr< zG@cEM`ED)}AzY^^*DScA7vEg?l4{d%kZ~8^Pr%&o;!qe;lOKmyFFt1%G1Xra^XITt z|6s2)v|zS?21Tb-0(>g^0Cb4oT_}Vp(-d~05bkH6 zE)1`5c!Al5@=eW{E|aq)_!<~U7q7#nDurvU7P|J_0Gssl25iazT~CTCL@rT<$dzCX z_XyuaYm{`ktI$(aK&P+6)O+``De)h6_^_9Uq35>6_;g`v!!f}^Ki5%5x0B|frS$=5>dsR!R9dcKg=>w(W% z4}8vg;B(dk-~4dl6(C)%;ZT|D)Hy&5(Z?8C6B5Fdd}d3zK# z6(Vg#BMOmRq7cc2&n-#cM82gbFlS%84+;^}9eahQqlZeeGvDnOm%ow9v=XTzoYGFl zU8Xkz8{t}jr!b@wx^ed}yE0f9tBP^!#AiC)J zq-_X>C5w)ZS>+&LUxPn|m!P9}#ME_DS85AHsa(21 zSduYF5aO zl_n`}MRTDv+yk4^aj$GXYak?wiCm(X$R*w$6xd^s7nrjPq~_!8h>q(;l&diS(a24> zZQKoDAw1l7mM9EWDpJzvUGc{Tnu_{#2|rvF+ZG-3!5UsvH71Z0H$5q$YYmN*D>*G( zP@1lTO_h5lGA6V}E}=DYiLc%WY@L*g)amTG)~Jhjf8|=&ny(uK*hJP^jL&4WL#-F$ zIyN?V83dm}YRvVO7$tAQ(F42_>YzsIAwlC}ABCxtYSFLOHgf_M6c#5GN+Vk%- z?M+nLBbU$~xx__{z}8bf8QYiITLRWn*R(^|-mn<8=eY0R4juN#RYAB0ns2MOrw-B+ z5u#<2OK6c?;`W=s-a>u_1}!ey-WhM8?i6pJx?V&zt`B$ED{>!p+7!>e;tCP#l{{k6 zj-g`7js!O4i+yPMO7X+fc19H0iFZ^xJ7y>}yot~F4pFWN$~6@(@wwl6g)M+fd<=LQ zT+s)=tKm!CAN0ZIJ}fF6jx##{0mm6Q+=Cy5K^?ai;|M<*g3d|1xC~X+hno3`TVl73 z9gB1D%g2O;3)@~5pmpeZ;cEoF^P#xu0#EPKt1<9Vdgj2UG@UL7!YvRI1y3$f@Z=I* zy1>>!USR*T1uu%$S?~gL7QDdzTLoW$LKDU;_yzx^g0GbYUndK`UKadks^G~b3Z7h| z;03l0i5J-aY{856>nwPIISXE3|E+>AY^C5A{+9}Vt}OVVEcixQ@Sm%KCzmLAa*2W$ z7!|z0Q1Eu&yl6{@(0+Jm_ir5ruaiCRX)o>%$Lpxi0F&kd;PX zll~T2S5pmATdFMuo8qA*DQJ$bV8{zsIjk1Ctt8Y!E}<53CGZ!41$IB=1?E%>uCwe- z-}>{z6kd7(|J>(SLte}YrtDtyLNVP56Z^k0=vcUTktPM=d&geo8V^_WiaHs-xP zexop?={y`?(*+Y7RMhbFc;v|W!Rk<;++T5eJD&_xpWq8GQg~$yWKrDiFA&pB7fKJ^ zbfK%?gJ2&A8xKvkP#W!!6$oq{b|VaPJ?+n>2<7tUwOTOrSh zVan6rF(?;Ka>_9s=D7yn(M~z$d;4>D3ePB@oe59+a7;Wt0(A*?XIVC7*SRlHDsUTk zx&5jR_Gz*6O9J-i=~E~yd^o`o_5x8m!=t~U?T_R2E#X(o`+|sy-s4g?vv>_myt{V_ zyhO9AQ?7Y%eTAl-Vl9U2X?9%)msn_`Mk}zF6h`Y{0{dQJ_>7jsXlr;8_E?2wD~vXY z7h$Uub}3vhaJ+ZH^#i*egX?Q{JqOogs1BX17vZ`ct`yp8+q#2YTj6?~eRsh11iSEO zEbn-*RMG%E9tWB0l4$N9z7|MFX!m>J6lOSN$^Ith?jfg6EKbsgQn;I@Xl+AD6DIZi zIJDQ1yg75b_h6@OE$DS3>SN@#jP`~cUeIg%X{5?;_Y1fYUv3S_54Y0iaPxx=jyL%5 zxG}$n2oBm*gKE@Tj6mI;^~v5xod%SdIBY|DqApFp&)frD7wM38+%15OH~IKm9e;ow z#Ca-gT3YJ^n>v{^*!RQ6rsFM7!KN?t&^WyxG$*<|a)~aFTnW}%_)@tiTF*pp# zB7)hgaX%!-eR^O-sF_?s&Eyi}zQAbQ7uY^m3*9WvY-Kw1ceGkzFi5LALa}Pa@trkZ zP))VzVAFJnmZ9-e)1hoR_onp;p%!upwUA4wMPQ^BfkjZu^INRnu(ouITwBDY>Tgh6 zFl2C}q{oJYTF52TLN1{efstASw$IhlR&Du5#M%<8R@z@%a%63x#R{PoatXDNOQ=O) zq!xiiP|Mp}TB$5FU(?IfJ<**FfA=K?g`tThEiHDBTv^2BtxgPCX=3hLC?5AEMYF6d z^vs&j3b}+<$R)HQFw%;^_O(_b)fHVUJ0sSWSe4RxU7>i~JMeUYwsZvQtgU{{i-CIQqN#WeP(weQ`V&)?P(@V^tehr}mwAFGBjJiM3Gkt8v7?9EaW?V;eZ` zcy3i%BbU$`xe}~f5kg>hN|)n?R?J$vX&-2f?)x9xiq@VCYpu#(zGrHqIan$V+eFfu z{o2zlN^9g2S|gXxn!reF0^5_icJn^aT3dDP)v(qYtLuKdy7r)~Yqu$_kxOWeTtaIC zBdrN+PqemTA84(uy7ro;wYkC29;q#sy7q|F+U-hfZLe()ZJ ze@=xT<_K@+!?t6|56RFKRWw6+j#Z{D-Nlj~JMDIQY))MGu|XlTp>iMt1+bx~rpW9s zELA4*l>2#dx0i?FIhM8D8LqDEqKowd*_8^{7j-vHCeqkN>(NKDD+#Wn*oA9hD}`ODaCKu> zKe)QHi&h{GVb^fDda%n2*P-kxfU76Fis3qpUDM#|#jc!2e7`f4I%Z^9-qeh&VZ+LD zn`&wTp|Wze24)T#o;fg>IV?S^tT9+oCf-`Y4b9odsjH|#vqv7;l-f^xcfH>+seMjJ z#WHAxA3Oc^OF!nA1WQIyF|w?39!DX#qeOw%nXrXmEutvXzmYFvX>`&L;s~I`R?VrL zQ!4Eo{B`1$9QrD3CyUDcdQ>~nVn;JZH9%lA=M^qE_Q=dpF<%oQ=H-l0_Zp7*a>gj; ztJp;|z_Zzv3fD#KN`q?&yZXVklwAYhTE?z)xGrW_`^r`nym|odxQYH?uzr5=Y=2`Q z43>wA1Hs1X#t`1}Eb`Y?SJl^4%A%>Rs|+-!j!LcdRro7r2P%u}vGY%3xcv8|ikVMC z$;j$PpOF4rQIDc0GWt=?jby0G%-~|Bg7dS>mK&6vGu8Ztve(Q0^BtmSfNY4a(&1yx za-KrK?l`?1MEr>~P(^X3K@;KXUCV5g)&>W!NNY)8ZWFz*>#vb(d*Me@#GQ8o%SIfQ_g@{l761C{Ip^S@IY5hkcq_0;>7eS$s_))}dg-pCw<_Qd z4N6bH9P3dx=XsHw4l}4SP~J2vt%N{QOPpur{a6XLHN>(~rj$-- zjEnQsFs}a%3RcpG(%6vZ;yg3uaCqduSA&sETFJPKp+kmbk(*^CGHf{Y0~#_kbNEVy z3$KO3mHDV2O<_SgUTBl?F7;M$(=9Tk2FDsWMo`}GqPxlXUP)^G>2G%X0ODvd#Pnz z3D2ARc9NPOL^5g3EJfGEah};oSsGj)bl$j)VT)yilbdv$rx!Q|0QtuMuX>Spy&fJ2 zAKXQWFlk=rq4JOO?8HCS05V++9_m=y;-O`uI8PSx zW%DE%JY8epp$7s`78*}igC`{h9$MRo^U&D z8c%nFhkCWPc<6S0oF`A?>0$8DP2IM5a7za=xYeuj)zjdi`9xbhw4NR3N!56I89cpN zW+48l)>NOm#6f0|!9%m%I1g!( z()0G*O?f5{m!@YE{Ox?D8$6lJQ-*&s!9PFO*W?)tpE%DB{M$U422U2toP>WeJ2zeX zjma|vKF;#WGI)lvOzY(}jAgdq-%ig^g9pt3aeah3Px`4^yt~{?50z$|L(jtvo{=m= z?dw1seV#n`A(Q8LmRU{zILM4Nct!z@^Gw1&rRV1po_oOLIe}$#J&!VYMzai;8eIL3 zJ{waiV${d4Y?jg6>1cz;%QCa@4;5JpTDD$m^5n1#?k{s_oLF9iCzoYfFRw8yqu0Y+ zg9p_Y`k`Kkac>O zBFm&|`5JHVOkkNl_$U2zd-m?jO#KwG%y#_S`k7$xOk^1vF%g}$`NzvaNsM~^p;{W} z*@}OgXQIJV%rf!#C$nY^tfH1l<`!86t1nZ`1<{-$m_7ER5qXL`2C*&j|bc&4+=_4p^VY4+E+ zm~iu)3ZFO+eV^TqZ@R%lJ$zgJ58X#_&NIslo*68&0RL3>r=(tSsF@xg%h2kaJrBp% z$bsqe@R=-Q^Nc7y{0@`H&oZ=nXYgbE8CoN>dCCo*N|rej|CFz+ zXERYT-FgnNj925qSI~j!`Kn?Wnn{w$sXAo0$wR%avt3jfJhNHm2qJ-*|F1bYCQmhd z;yl~%ZuAc^jC&)4@kd?l0jhuZ5h9Gyo8d*l~ z4}%6zh-Ij}DD;c-<9;-GnpkEF{_T8)44!!`^AP@tXF>HL7+T%wna?tMdgd8C%`9`J znhlu0gSa{

    ;yg=<1ZKm!ZlHA6Lr_CTzplK<;30-M&)q}<^Ip=A z7n?lG;N#?3YVaVK#`EoCzF$qAOAMZi4W3IKJQMm}^o_}LnZa|Z!LyuYsCDd*| z81&rwxtwKaTqYSZ%MG3@fW~>o(LauqRmYApd8n2;$BQcr9#j{|pmS%Q^>;5l#^kx0 zWnPjpu&k>Lo@-d9bsk(QATDYblx8y57(CYjjq?n_KWSylbzh{L>A9X|cHrNx&(|3| zH?T|!{>jWdWk;#Wb0d75^OhS7o|{-^7?HrNd@uDeljmmmIOkC}89XakrgffMSVmuG zTVe3r$}-2{pY*f&iJj;m-Sy`-meF}`HF$1!@SK?RHI(7zxr1eBK4$Crc7x|m2hTxo zT^peu-o-L>PuAwS)8L_&9_Pu#Kc(W8onH?(({m5Y=+`@U8$2snW~j}R_@88x=U$f4 z^|R98xi1EuRV<_H=RSky{up>3U>RLM_ZvL8oPd5>&lim*agKG!2MwOpEOQwCNzcEI z_$9(ToJIk$zG0WwYJ=yI7*;yi;Cam8c_Id$Ct2n#{M-3@!r*y| zWqRPB%netTM5u>P!^hdLK4tJ=S_zrfd7fn%y&gVe@T`e}XD!R@!oQubH3rXfG4TA6 zW#|Im=6TNGS;sQj_$QfHm#lu-Y+ui_%x)n7h%CeNQ(rc~3<>juvTmZ6kWd5ydJgb3r{8!VH8h!WuIE^WZ%e=BXWc-i0R5 zJ1nyu|CBE>ZyP-C0*&+Z$3LZ~Y{S2B;X*FGEH<)?UN_z~c-~`~)_LA%8GX(3J%i_i z7r?gy4ZW8i$f@n!O7nha1ff5#E$X~KUe938Ls9bm>qDT(vo`)3>jP7sQED}8-q zC(9f`o-mQu>;4HJ=X%RdgXc$<=}9CoL%vPNRNCE^F@%7JYKYxu{%G*fECPKm{>i*| zXSWMXo`1o|S*E)To}XF9<~i%bbB;23{>?I^0XscE8$2|NXzO{2|FDccuiI_#{K7Ic z&m@yLGC9Jy{40E%_j7+ScxZMc=Bvc>L)NLNYHmH#13FF~%i}J0`YLpIemL&QCFp3~ zJoKio^Lc;{1`mx~;q+|Iy25Mn?8h?tSlQ9w>BKVAkSA)(32!VIX!7jOGBh9CA2MV* z89X#ngwqq3eF7%t?tC4UL>vMv^LnCQ8Jv-7~ zJICa~M*twR1##K+u(QE~uQF>qxxF`_vvKDO9}$2I^)NP17lVgJnt3BWbuE&gj{-vzeZ5MtV{Vp6)DTxA(`+eHkin z>xbS~ca~RogNH`suzptlv?O-VJxGUdryOhYI|5e z_cC~T$G~&A!PDE|q1BIYdU|wx6iwExXT0GJ8U6Yz)!^yt;E9~C zBUnbS&wULZn(>Cyv*m%cTg~*~4RgroJZT2cQ4XF>w-3gmh&x|Lvy9%49cA#)Oe~xp z-%p>vX7U_k@boiy@HRYnjzMR54BF4Ze~+||L|9C@Z}8BJH_me&e5ud8 zXWngn7acmZ6cw?pL!6o}ny5Go^SO zpH!UvxtX3}EaTO9h8jG>S;iiBs=D2jZ}N;_8NEIaH+V*}%xI*A%zaP&^>~v9U&uw? z^=q_|1`o|1<2=IzjrHD;<`YaFd|4MV`Zeq*gNMGq&=wDUI|OrM{M&jSZSaux+TzJ! z8T}g8Yw*xlAll*?!!r7{UarBD$1)A5JgLypn65)3^w0S$gYQJ+Ggrdo89ZZI=6-m0 z!jTj@HNto?j%CX5Z|i5Q!9!PYah^vc&+LDGzRWDILYA4S@e~+5<5|Y8hsPDw|H0%r zk!5xvE;~Kr4W0=Oo(Dd<>@1U~$l#e^@JwVGdwjQ+K5~c2Gl^yN{&}LoQ|#b5_Spk) z(N8U3Uz4HTN}S_GvB5Lh!83K+OVdpr`T~xVXR^Ul$})YB0y1@pg?^J~3d`vAu+-q0 z$})7#NalfKSNv@9oXj#7{_XObYVb^B8N1vc_&h5@zi|r7=>79FgJ(L+j1tMQ63QlI zndv!|W%Pb*y1_%WJ3_Jmr(e+bl@Kmu3 zl^3OF#%6DXad{TYV1lLeTxIagW|_H=q4~yF9jXsE^Ht3<)Nk0=akCAcIV_U`88VUY zpPtS#`nWvD;HhC5Tx|2WeBq@hA7`egmSsqjc6w?Ip1K%#>RD#7##3kTG{nF&mt`pB zc6u5No?r|-jVwbk+B`vnC&V&zl|l2Cx2|qR^KiE>Y*C9kzZ$ST&kTimABqCxsqjk;2@KK-6Qp8 zdah!bERE+%gXe0NsRRccR`q4S;%1IJU)Qiqn#Oar!E-IkYfU#AJU7R{ zvw~$hGFL-)G=2^0vaZI|&z&rz zxA!{?p1We;x!d5m%iy^u2A-7$&piguy)2W8JW;Lb(zJT0nXmg;MxPtsYw)aM8M}Y} z;ipLVO73Tw^@ztV_f-bZ11vKcGBo#F(EMqHdkPP-j9y+37(5TL41F7t>h!lg`!6>0 zwVGw#!vBGgA@h*I^DxWU`HK9^_9HB#=j&mE=g}B=9y53zHFzF(@Z7sCIl{Hf69&)Y z2G5f*@H}PkJZbPe%`&}&`m6`%ynL^z=VuI_rwyKGW8hh1@H}hqtYsOxmZAE5#K~($ zndy0sW!Aypu7_(4o9nhoiEIj9vkT`k!KY$L?ShcXM#lP6jC9P zt5vAQ61iR>^xZcyWga`OXC!i-;`u-#^AxgEB4;avzLig=MIi$v(yWjP5(z2fbcrlh z2z?WWOh1Ltw?xQ1?6FfwUkoGjxW`7`lgQHw`BoyU6tbV}Zmv{FKZ*2LagCP9Q3{zZ zk#vOwB{D!E%O!GwLLQRH-xTs^iOf*3Z+GINmIy266vduA0;wfA>HL-L6t&|m&oNRg_RPyL?PEmLJr4sHDq=xWP(I`dF;5FCDL0VcS>Y{Lf(_eGKF-&EQ`!#9-AjiA{Q!TibV1h za+gGgs`RXtNTx#Gmq?aEev-&eh4iLNahTZ(@k(TlLZ(TiK_Sf&nXHhjB{EGRt0gkj zW9Ms^L<$r#tTV-JSra_A%mRswSI8QPOjO9B}K-<8a6i9Dx};}2yTE2u&(lt_X?Zjne|g?uQHG=&_D^-nSr z6?29}=6LM%lu6_UC9_H*sS0^bB3CKoZxW$eSMBj)_R)c3(*F)TOq_L9p>id1r$Vlg z$Oj7fQX)4gBvoGUZBWQ;iFiGBE^d~{S4!psiQKP{gXM+wrwW-Uk)8@^kw}3;9+Ai` zDz2|2Qm$nB_ZB&QNg*>Oa)t_Zr$j;u`Boy|t572j7d&ee5|l`T3bjfiU6jl_61i0& z@u`C6U4R0GD0GG3OP+8H+t;2 z7E5G?l368@bqaY`BJ)+K1Nw@%o>DSd5~)!#K8YkLnNk+BN-r$la6apfE(cxEb@M} z%p9#F?*l2$(~*hCA=FqMc^yd7Bpu052Xc~*yhO+}9l0jMveuoVBV9A0RiBP*0FqRz zBbOjg4U2W8BukXwR8=~Q3AsR*d6bX~b>wp(I~>UELy*%Yy3Bh(8XQQ%P~_c#i~&Ms zkjHMP*GuFYm7Wa}K@CCAe|1MILeKxJl=(%4I(`@v<3@(fJYOO`6>_IUIw|C@5{Xwx z-{F=tHqVI$(jbxED)vhxGC?8t0GYW|=qHXD*Bd;a8pzKEa=-|8dU_bh(GDbS!o&;| zyOjjZ_4m-qGa;xNRu2b)3T36~2+Gg0YH$p&LvdXR=?D>9Ejp4xJiR(#12{WW1}d*b z?_nr}OAEWMh7s0#m5y-E{W`+AD%BB|*@Ad@J)H8zJlk}HM z3~Fpv-vNCYa&ewi_>rl5^?}cYi~cW@S{0!P`5FjKOXhiqhslAuDuWW(MMpA8^YplZlF6jf z*`YIM5_3(mE<-8{=?F7-?yAcW^RK!LGymOzP%gGR5X$La9SBvaO%8;r-Fh9#qMX+B z(PGb{G>3F#Fd>zFHJQN_YMKKf{gmoR7Ug1+1IYj~-hogq#ySwnMY;o_Tpa2^C>L=K zgtWR{Pcs3Qmq#mErrhERbc9=6sRN-j&qShBnGU9W&DIev(*h(@$z+l?vKa+ z#C)6sA#L<`Af%0>90*RV-VTHk-Q9su#=1BV%6vx$LM8Z%o(nF)T{=RUu(Hs8RK6&X zHA+WVV=X$uT5Zq~*8EHz;r?(GkKK0rqP*uh5YkVvj&SU2CTi(n=9hE?c|;TB@m(@= z3U}!;oWgB7!pu*d>}Fo4Bh1`!nkK`{J9Qam-l`Bv%cSGQ6G(~NBT=78iS{nic!p81 z0v#Dj;q=4&+d;Wu4_frUSXif!qk>N(ZtT z$O;GYha53$2gX&Er;ZT>3$N1$yUI&tbIKwjgpNL-FAu|TZ1_#mtq=y43nt)S<=wDNRo%2;8 zysb6!yKD+yMI2TnV3KiuP5nQX*x;!a)jy# zH_13dy}_ZV5*{dJ#j|&G@_-CQGR{zc=1>>P5Es6AM{+oYAITJwj5E}m9O_gV>XX$y z(Re$^vu+rL$dHUP)LR_NC%mn!`|R&x5l}2ck&GQGjXEUjZ4Q+JmmNdcwM>R08H7@^ za6Gxlq52>c9M)%>`|JvbS}8-3j5DrxITY1M3bn$z4;99a^;H>)WSpTka;W`eC|EFd zsLy36l5vK5k3&%@lkB*8A7VCPhx(5UMKaD%?{lcg+USEh0vVD)C`}t5a3~th;IN(^ zGUeNFT$5xdl5xhhi9^}iIBWkSbHky|k)cS&8R|n0bpYbAa}##0lA%b(8R{brWou*R z!MmRghx$NIgOWy!`vZ zp_a-}B;yRV#Sv<1T?b6L>=fQ0Ly?R#)Mt)RCk(85A{^>I8H!|_p+0wn>ix?l=y>e7 zo{^zQ#u@4hN2rarZmbQ5dR>Mh8E2@i9EwH`GC!}_y&xRwBN>WhoT0vS#5M2nFE0s) z`nwE8GR{zcb%a`;vw2=PR0o=j!H|qI)K`vBcZ|%sGaRa`3`H`|P_#CIH~0jpbtZJP3%0mQ32HcYa74`E1!RkPx z*E_f%$I8z36?jh>H?25lT46!)(0thG-s#@yme1GFggtEhH8qeK>^&uiL>RBGZGdMG z39YiSv0oRS)bhf=s0h9|AB(5N^z$+Gj?qA~WXl{NHqRikZ#qMXBZhy*!@QUP9hkf4tHK=P2&zyWjn!yUF2-Y_? zIy`gpvBgvdWmUwR9XT^n5zVf!&>y8}L1cJgWH>ul&vXtd7n3;Q-27s}jVEWOax-!U znx={l0@DM*dPiJ2`O_#})s2QvZoY3KR|VAX9Nt|^?%nMb#Vu+>UTdD?_P~>CQ506> zB&s)62w4YDj2x{U8ujd?CV%D0^+EJ5RN+-fDm2Y2H(x8YNH`T+Bz%4pTq_|h7>a<4 zNGQ}u9hZTD8X>6ZSJ$I&(3>z~ao}1g)Lxgb+29-kk=vYGgi@=TT_jJvahu z=}G;Jr~pD8uB_R`uPTquz-25noQ9qBYW#J9k_LZ8Aj6Ao<5b0_o)d+kL#&kyu6BqO z`!5Eon+G=!cIw#$s|uB!0oDT=1Ew7BrxW5u69d(xAVtu?nMzvm&_QaCE2$PCsWw zfSz;x*xV7>G{hX~k%clTSUn39fr!#7^R3CcYnoZudOCRQbCxv)K+TMj5LY8IYp2d0 zTkUj(p!nrnFBAy-X&RXl!W7b5A{%sAg!+4}E@l*=C^E(D1ueX!y0%hmq3SGIH?BG& zw@0bZSDTSJ+{=t8S8}^(q0U?-Mj4?I-Nlog)4Bwj3WpT+c#1Q8PVSU+ujuVE;Zt9O zDQj+h&pBJbJ`6)vh=}FWXIFzbX zN<~C-(wv5dngzv8jkD!umu?2T4yekT&I-1Jj|+r2VzCRZoidYzyClV7*AYs9&5%QJEEUvYZ$_;`wG$mP^kh8v|zp-_#u9-<2ohpM#;6gSSbUUb-YpzxlmuBwmvol{rc zSRV@3H&j=Q4OUmkVN-3mJE?pQwjf0(5UH!g*1WL?_f6z+yt?s3Y_MF5@wq~B(}uM* zHPww6u(jC4v>OR5lx?SUK?7Zi_Dx(sI3Pjg1 z)?X2-4?06fEJ4<<-7K}JAj}=B@Gq>x7TwkU(m-8feUKFunOd7-$Py{VOsr;XeXxRx z&dG1~6^M-GOY4K!6gaj3Mpqa^BxdK=Rv;8ys}V))!w{(Tm?DOP66`KSA94(B7}ug= z@J4VMX?yCx*c$&V>du{d;ATbJ6gPze;}&2kpn`jeh^6UF4v$($$|Q`q!RpEYEg$hn zS%`6vr{+AzLyNA|`zF*nj??b_OOP3inAL&GaA!>2fHM&FlCt*a1_S=ntLtV-@zUAB zK;vxe5RR;w;baxBZp^Rqm)8WM35kvfh1r@I(%_pY6QPut6ERxZ11Txd13_5|$!%Y_ z@wCtR*g&9?hMy=wi*qnHatg{7u54Tg>dR+->Nsd3#pR`!PFi{{77*2yHP-YnAqvrY zW&0U8J!TXI#W}^fQ$$U!4D3}5n8QWP1r-t#(;BOub}{zk1cUwsk@N5M7Utv^aPN$U zu%NwRF*__k{-P#|)`8p0iE2k3ZDpVlBY3-0gwP^8krW-9IxtaYg+wl_*f=-~+38v} ziXog@-^tjsaEo3JJn((x7}$I z1sG_?1g3H#W-vAty3zKhDoRGFl2-V!(nL!v?M$H@6Oh$Fa9(>`EGde$jQ%yRn(l<~ zOr!{twJMAYd^N|DTYI)sT;B*)*4ObYXHp$?;ihoJsf#Nlb>gvv%+8=WEpE~T{piL; zmx$Xva)RFw3^e$I0fs>sQ83(ySxn48BM@Tpip~cVAqt|eQdTbzby&9$>)gCL?3&^q<7Co9d}r*-xXeaG}5?P z^)W{HwQqEhVcI#as8H?^C7gtq#uCNT&QU}U*Us@n3%Um*hZZ`M7_2o-{6gKA13&~}Up8qJ=L2Ra4EEXI^Jduc~F?pZ{aB60KpVn}HZk)aCk zipgNigNI61JBJMw&K@uv6OwT6RM4*eNRuwkq1j(?F6%h*bSYvi=wn2MXl2S-fT^kM z3|O|c=1;P*HFzl*TN4+;u{UZh84gYBQ$NVG*>E+P)|x7bwbeKURSwFDdhv?Zre#93 zolQ;#66|eEhP3pyG4at^9hwZ+CNb*E83qmc8Ii6M+f}jKOUdJJcsda^5pr0@jYSke zTdkzMi4ene45{GqZ>7D(7IC;y#wd?0x7KoFWQnzTw}&paKA;_pv3C^hAZ>F}5KGaw z-Q~oZBD?QutzU|ntF6u}W+FM^h(Q%?cZ2PSw4HrrdzfSDP-7;HdEO9%26_Av*PmEF zY-+G?u!Mu6BQ6PGu^SH`_-o{+Rf-;Ud9iBF7qJ^e0O|+^NYiYh6*tZ{a1g@_y!$;6mBXsxf~xbZdvT8`3M>`~gvG2{F{(^?5lbYss!RHgl& zWk3}}?89pGqW|r4kxfr8wmtac0Z?3X(@@UOlC>SczIvtmQ!(({H>|>KDYiO*aQ|1@ zfF!%I#wDTphF0ZBY1!#ELy5n( z0ffA|B^k0aB6*6+NsnRY)rYVSOK&}?XRu2%_<3rtZ*u7v-Mmf zbMx4szcx^SmQ@o74h9yOJzJclWykdRjhIL|7GXuLmmc(TVpHAx>blCRraG+lhxQe3 zTDmi}=u%>N*u+jRdWdOa{?b-*_Ytu>z5DRKouT1<$L&saBXx=qrlr4^>4>4K-+6{& zET7-kY%A76`d#J9T~h6vAQ~!ZS8$Ho)eEr}n^|j}sC1M?H7eS;t*e-%db+BCok?LT(2qM+Nb`eCXgY6=S zR0rEd5UCEfi@;R}!vk<^mv;YSm$F8q_>F%-`4YKrWx$x%w^_m(HU znA$aIcI%_PfgKUIXN)!?Zf9UU;&37UuE%$y)A(KH2JefE@%qxo<#|sWpHoy=IBuLb zrx9=bgtCW>$sU}YnKv~fYuK>t%-p6LEY)RamJ54Crk7qd;h?$Ry!>&6MH43Esh|}U zv~r#ZDucL!4l|d9wk8GDubIN|(uuAwW3YF$k-S#4M}lEY?87LU@cCkoquZpV=b_&>D z9cP%n$ca_*@M=4+vjeKC2{knaD&fML&^2EEC=&kc^TAmHQRn{QgEKORR;lv}KbdlM zUgeUn8ayODtBS5RnSXFq)`;|~N=<%9`q0d*%F4{D4F8C#im=>pCbG|EGE};Tq-P9C z&#W3@`wy!cRz=1>uL_?x*VcLkS$cXj+d6K}s+X=5xG)V@y(kEL<=i2Gz)LfBr* z>(xJFODKKN^NlIO-~RVn>Fe~5t`bfk$b8Q&mz3^x%aIyBG~|*Z%6$|`E)-}EQH0W@ zbjC+$A@{vs0B68TwTfpBB02HxZ}zwt|7)x8@%C9l?m%5mK>VMF|35+IpxFY1nyl0$ z@VUxkJMe*!IkZ~H(dUT0Nhl9j`sf3&CqkzG=|V0URwTaNklP5ExA3u5GW+9*#77mP zd!1!f;~+yHs*c3B8Teh0Ik%pq#MaW0_~`S{k3yzv1B-DvM&heM`bI+L?zuuPT7F5r zn;?_TACnfJ1&+j*2EIbb)Hb%x*A3pcNEsm+IluTmxb+z1E|!%eTKdu;_Z(zCmvZze z*GTDm3HXnYd8P>t7^(-6^miEWO_2GAltZ>6@@)bBAIN-+Pt}r%mOg542hC>@^%p69 zJK%c=B;}&%Z!6?3f=mr{R4}da zt$@rEQZ5=F)#ukCb2l|`m}q>o^WG*Y!-DvWlwZ={KOy(!nL?^HzC&nV2F*m`+XVkC z$aOwj2)4#ITFTgzk@zUTr$TPnIj!?O1n+9d^k@-s(ey{AMKtxsZ8X z%29ocl)f#%d!C06J>wt~jV}X!0~T4G1d=G*5Pf|umM&`3H5Old5#}#e!d8JHie7oU!GUQ6A!ooyLUr)q)K4fmW zO2|diANBW-LgtpMg#xk&Y;2HvZrjF611zise5 zllc$B@anU&tX? zL_SL2iIAy(pmn|!c;6;vgk)qsFZdpZ+&>>|o9}2E)HM?+zm&e?A?I5y1f$izKf?QR z$P_;;;;@b-RImq1ph>(lM_Xl`ylrlmxG9QiSKS1v3N89H6o0MsbFa9xHui_vR zEq%S<*Wqy%QGb#0OX=$kxxY$T#iwodNd%p7^mu|?n(2^k>6>Da&te>DkXtEbJK-Gb z7REXQO~tpm_`FG22XU>J41iqula_TU4l-13-U#a(B)1zf{hlJJ=yHAFca4-`LHvdJ z#8ym%Q+<9Ca(|MtG#;^>b2-OK1^y{yewA{ljwH8ES{nG(YW8DG=87U|88r~YBjsAl$19L|-zjJ0gX+;1$b8v` z9L4)RWD=i&114I2sXPvc%wV^iD<4NeZX9H4rCe+Im=Bo?opMG#4g}xjkXa$+#QfQ= z&(88#1DQ=yE}W0>rcI#YetSD)c1XE!J%F6trpcE388W{Za?T9XI1v9Vg$SE)eGX$J z*EvSHq!{H=VwCFzP_T8F}|t!lTXMP zmY&`>f`4IY{^Xp}Nt1nf`MFcZ`6lE~&7W{WW(3K}O?Yj;HZY;OJm?QDIH4%7(wDcO z&R<(y!QWCth`ju&QH7Xlr;t`BqmeR=sF!#Ssg6n);K#4ln>6^K-ll&c#`@cHl8RM8aXnG zhtdlho1yyY!As-u~;azjg<7kd>Ic1MUlZW3g{`b)(eTu z=}pT9*oVV**M+ZuQ-qW#GVZ!Sqxw|6#Pp{^+gBHyRRJ}jOy}LZn&9SE^{^dDaDJTDaz!iN^^0i52U?x=ex&u&WGgv&n{4vkMWgR##i{V|GX2QH z!H|3ll55fax?5rkB1@NDh5SDz%B>4z*F!dh)9zL^szxVypckMzGE>O$Kk0_*2u(jr zC4MX*(%W&cXTi>ZP27WFzXf{;>}{~KVdo;e7xr}6Ik0`O^I^ODj{cCRzR&LesPE_^ z3}1jjg6`B4~>>4{@a3jWwc?}PF39)F#Ti_VV74kqoE4&2f1);n72d8u@NIgD=e zRnX0=VHtG=7FWPqA zngW~hg*s;FDi?Tbx{6d!C=A7)iQ~E0b(OiN8uB2Mt<@7skGr0n28hx)12(182isjw zyvX=X@T1P1%tr_?1ezv&P#c+xw&kuT6lMtg$o^wH^6si96s>KjXr*b1!)D9v=+Igh zrtZ#ec(S`Ah~guarU<3>07M$NESaEkdg<7Q&&bp@VlV4tp74ZyGNcc6c_G#1%|R1S zPF}9MOMfPal9SH_;01Aa3op6`^CuTuhXQR-Xf<|AsA&w0slofUs87ks&C2U^X512H z%y4wRC1Blv1Ew3oZG_xy+)?|*UOgFBSHP>a;B|pnEV{`pn$9qF^$vzi^huo@agIS` zm!cucI2XG^PzsZiFLJ|zzr_s;{w~&tWV=znj0|Y~;BXNY$47OI>USE>21vXd5Y@v9 z*r@B)9N5jUPltU4>>Ah)!mfi&s%n7!9_+cWX`T{<{cqTfuoJ-;9}9aK>=M}MM_RszeHrYX zu$RN`fQ}t$Z8-||Rj~76Uk!U4?CW4phkZTlvti!|`wG}M!+shzR_a?mgncXQzrel? z_BXKafc;P8i*#ihYNk*jAB4HbLef`(YdoMZ)PK;ij!xJ_9}Alruv`$BTu{>9PL5`m z)FQn&=n}ak6ljnY;qQR@;jj%QgX#g)hggJJ35e3T3bs4n7G#OKvy{z)U=L`4bV2>w zFF4$D01DHCWUWUgUu;} zeQg#3WnEJ(E{nvR+>3MG3YdeS2~kD1{LOqhHzFA`C^po%sImP?I~R?Oblf6Qwvcbq z@qsuYDl)49kxm|ljf+L=QP_E~ABT;3i1j4w*|495jdo+LflcG)TG*)X);id?z=#ntU=zL0V*VB` zJG+uln0A!iP*>Sysj^!ERXMJ!Nu5-7H2tI4=$uO`8Ne>|kX`^m-jkLKYaC9=*oAk4 zI92B#xXuqkw#lfTl*$(Uj54GbD%*pAES4y0L<{L`1MC5?-+-M7`%T!>V80EU`qy`1 zx4=fEEof`jCfF!%>qFQmXA9-XbM%j4@51>fuz!ZV1$HXp`~o&zGi`-UZErQo^H6L5 z%KY$182(rG;aB#S?NS=4(l@DSEr3$)A`fa??jf zayTT4iYHA0&RNz-Y>`x}WYXBu+(~(-7$V&Fe^U!eH0r#qFh=?-}1o3r?HVY z(ZOgHpZpMcHVSWAAjGr#0r81%+D#E#4WVC-Pd*Sm8Eqz16QCKf4_~Tost8$q;PW{m zrbopco1KlVsrQHS{2@PPMDfYNWD-$ZkKrmeKDj?*;Z0d_6&jzM-xV{1Q02&xO;{{l z;G@^`=(B>OD(jo@>feB-y2k2Rb%DxMtci}c1|h)EC;_S{ewTa_@@9|XaHG-9$0x_3)zsk?hK5kk7qSKbnWzHi*4Nia9gJeSKyyU^>#X&4K8TM- z3yV*_#wITJSNfE{l?AUUwwEiLHT77ejhI(b^aMMUFSj~0zq&Et<0K1t5$F51h>DNW zgBfCc@<7|mcXH6*fJfRxRx03UY?xB%r=692b%FUlu`@E4{3Kh#5gSo1wS81H>JcuH zauB&;ukp#ZMM?^Hozy*@cQCQ#2J8Km4QNk+Vt;keIszVC?(RYj zmwYByqBzvoRx8oqbS@(rJak3z^sEs#l;V>++5I%{LytL(s1rWBQc#Ou0R@T15*{Mt z2to2*v;h<;1`mIbn-SG9(TupUWN}lRz-e%7fXDstepDd^FX|w*`{^tx_fX`|cyi4h zN>x?VRI12*5Gy_%6+$37J%nhg>&u&}xE218B6B=1&|E?rIN|%Xb+hdKr??-Wk?SMm z3~>hoRTcHPmB`9+Rd%~9snPz-HKmnCJ2-<|RRdNf#H*mlzy&IG+!__Q{)CjZSDdj(cBCW5xLq_YX1QlLq{{=Qs?lU$AdA~ z&~y-D+BE za^@?Mrh_G^}$ea zFi=^ISy({Tyl^LC&yKiF$cl>jnX0QaZ5ztGuE`k|P~($3MDiIqGQy|6MG??!3yl}0 z<6;{*(gjedH(~)HKKU2!3SHisykMqwHkB)p8bi5JBs($c%9Vg94opEY<)U7lCmuY_ zb$5wk^rso;`(p6sfr!53hDVJ=w=lMFLOxgY_qj@x(jsJ4eXv%m=$#>2NIi(Jc4(GG z)&6DC3Dxj~RBhxEp}}%9qPfP69KU_Ubj`7oZaL#AJk!DW z>@Kr!Kl)Dt-?;csXD+?{iX%r_)`N^^E&uZ25r3UF^pG#le0Xr7{~kQX&Uo2?%RB!# z;_b9iC-_pI9Eg3~5+n0)Qe4`Q8%@r>TPPFq)V-k(>U^uv&A-`S1@o`ay% zBv13XH|{Ff_Ga&0kM_IB8sBLG?)Na>7%2Jh^5o{DJ~;BLGyZ+%x0A3|%J{1Z-I}+I zf4t$&9p}FAM#jDGBEO7pI_$|Ws>>f=zSSyg*nHJOEJlppkN7|O_{p+&CZF`sy^}|K zJ5>jc#_I}<|LxfOex8_|mzjCN;a3Ic{}K9mhw&A?j`Jp!|8mHISJqo2Tc#g^`+~SJ zjq>d{aB1yve_nY?@yT^t9$GgAGfu`|f3Ii$U4Q-ggT&xj(|a~AhW^(wUU2o$i;kET zcgdoSzTJOHd~JWMd*Dd&lnmeT@!Xo5z1;%6`}7@pJ{G|08NaS7{a+7!a^rLTR&Kue z_Ia!4V!e&=(mR)}y7N5Wnbk{|d^UY_(w%q=k?~Qt)f_m#V`0tOtzRX+xO8j=$`?9K z@|>~mhxDb3OV@mT-@gXG5q~-w{W*-kQra@N_br(l`@a9<>S+zLv3R$h@yGYOCgHXt zN|ycj@E^awYsL3i6gmhuX_GvGvG?wJD|O=;mp;8FY+ITO#tnzX>b@$X*!`qyvH30`n&=(T|>@n|072mG<`eqVid<>0GszUP9~i*7E& z@n`@0gic@ma&5}9^;p0VBJm9R?2a85tjikv*`moG{QT=lxp=Ic@kvL`{ANYh^~;Z* zarDN1OTS!<^-9L?o6)KJjE+C`8GroYe_1xQ^lET)CZ4W48-F>uX3n{Dd>3~*=92H~ z(B>IW{%*hRuWY=g$3=%+*yr36SD~(5!T6;Y_Sm)J)n_j0m^{mR=ZTBI$66WV|DKjO zapBheddK%$yZ__sLf_#POf0G*r%RX5^JYieVtsj|90H6vqCdfB{+vg*2unx@J? z8CC$Q>j%x=TbjUZ!680|P$s^GAgzI!gNA1g3}y~X&*BHjglDCAl&!I>LhVkxUAv_be57zAsSKxc5Yj z{+hifLDA4n%0OMkf_=g_&mYd*9@HaMp~^$S>RHv5bXQhnGIp{GdnK@}TwS$lSSXC5 z%{5E-t)M^WG-{SIxMLi#-v0+7DDTG*EXHOQ|~Y zi4Cl20oHGC1-uV(Jih^14pj}RuB+MG9<-LzwGYx1s;sFl-B(uWt{_i`H3jCl-3kG)M##lE2tEPJov1-MPW4@Udu(*q0mgZX=(B7FVF zhZTnEy=My4V%(t-WACZ(&7OTl21@p{J%9F=ptg$w(Ec;T-TEB^7DQ;QeRn|qZWT>nwZDb71`px3~O$t%wB+E{AI44=dBjsd|>hHc|%2bsNOBO%i!156u z7M+ls_6L6U%j%7F$NjDCK!?JWXzh@$1ZynLM=&;Cx)Q7na8Zav>n-U@uzFy{QH1R! zT?y88a0$7aq$|N%4;MWNw!gItE_!Y=(b_Ft305)I8;@tKRJszZjc`$jL~E0DC0MCg z%MoGIq$|N{hD*quDP0NHO1M%vwoP!2VwTO)m0kkBUgg88?J1YgCg0LU?svenz4hVD}h%aPhhM!FmfeWd2oq13ZyH+YEW26VK*u4 zR)uxM3Su9y>~9rISE5xaUC^$=HYkh=yDx{BAYF-8v2>v<750|G24MA%p8VS1YL>1< z>rClNuy!bHr^5PSoiB|;grqCcYL>19>kYWZz&Fu)Te=dg&2Z7vZHd+v=}NHv23I~~ z-%D45^)p<#jQt{A3DyBv4a{NeK6*KXQlu-v z^1)TeScP;YSaaZ_ww`F!Nmqik5Uvv$J6pOEtT*8jeD6wEg7vAwzEIfr3j2q`epOf; zZuAigdJySKw0bFQ5Y}38zX@r{lrHp0aN!4RymTd4Xwp`d)vcTNwCaDYsJLUyqm!TP z|HDZcozY=LSgg?Br*&Q3I#2n1+DiKBBNlBlGSUY%;A@!T%eAS-Yq}z+d$~22KV_@l z*BzslTg7uKn4U&_4{i{aSw?H{l7^M)kBZfat`iY;(+l?S+;%7 zud~Tnc^mx~pY&?}jtww;Hu&Y@OY(PC-a$S~igql^?_9jBDE_25am$K!Y$Nd1{M}^z zKlZ)^Jc?p#yNARWLzIk$MMVt~1Vk_kyDXCp2oMM)VG|g#Okf}+A(=o>(SZOGVifmX zLA~zR<*HZQqoU$*f@i{JM@|MS-~J*WEATc@f{ zom#rOy1S`p&nuXY@Ns;&`BC%dH0A7RXi3QzAb^)Y&-eT^6(uyaYjiYaMmJ_eH)X~) zX2dp4j&Gb45A;!U2*^upayBM3O^R;Jk8YY2+n68QlpEhTCY}kb;PWYTK)>w2fG0w- zA3i-Z*j@eyf}8U8l{Mlnl%`E@*pzV2ZkdfQXT6Z1v1}%HkmZlfx0gL{&nqHhfwC9v zX?P)JvP={u6GhL94_C7I$$IgrTp4S#BoMvaD0R`EmscEGsbd4BE@=9wVRvl9jy(;V zqKldqL^oC>M_WyxVEOJnP~Fr?&Ch7i=M%$lvXMIb;lAk`sMPeA8gq7=En{a>&dwh? zBw%)jyL=s-u4L26s;-b>KJQ{VPsDk1Gf|V8uV&!n=2hh7H|K2;YIr4QGX?KDrYUc8 z!}E?t{4d)a)uH(^s9nc26>T=95xuS{XY+!VIZb&xn+qK&ljqM7f*Ll(Hm-_?Xl1qy z&+tU+u#!(kp$JW5k_2wjwyw#D+LS9#^P7rxHjV8X2qIFRGLMr)unx`HDJ(g^xj6;0 z&0$TlQuCWvC9!lWM{H3@Nr{7~;@%W8Q(LoLFe& zfKpwwsbNPe6Sv|Ibol!kHkwth`Z_ih#mZg^VqS4^_M`1O0Zr}|2WLDC&5Ra4bQEFb z={CZAn5r#ya^!r8!r(7-`&+*ICgflWTU;3w@kCFY=`Bta+fn#RSVS2YD>uZR}lE^mJ(5J6#UV)ZiR zH;s!INxPg3fS7ct@+b3PPey9hz?&54&c7Htg@8s8khrZI0zbJ6z6%{dS0h7aLv zI$L3yA42RyLh2Ku1g~mBbb=|P(GF80=78+Wqh;CN-YyV9VJplfNKhrnS*K?qUc^Xj zELtP;D+DEq+^!4~n%Eq@qA|zcl;=l|S0cx2kmGei9?jr#_R$TWJ78it2asvM59jCy zS5=@gcO@VdFf*cc4o*Y}&-w5yk^-yU4;`k9Q?l#9eq|LOy=6u3>d++o4K0pF>3N1h z=mIw&)X2%6rg5^2dJAtRs_AO}BZ25kf9NnRdL3$zDa->?7C@kwC$fI%Ff)1$YMT(6 zqJ*g7NS7o+h+M}!Gq2R2kkjG8Fu>7{-Lqx4_d>kZ^auMH zy6s3=@An=u`PZ5Jc+R>wl}|Por)rk|&D2xL9tPnU->1Biv!CaIp0i<<)iwYg|kJt~1Q}+63vL^EI1Y zU0^O3uVMVKI#K?3lz*QrzeNqmj6O-pL7Cz$I(aK>+F!qjAfc0eO-1{JPWCk{+ZWa0 z;*|`@*%#1@(H+!L&3t+>ba8_Fik$tsN})JCayt?Eqt+r*r>Fu%KH~{^Im|K9?P23> z%h?Y##+%d_3v95%vYA+wjKS7e>_UXx80{SRPJk~_8wcM^!OMp)TKML`_YICjZ8QG6 z3fx!lr3qgQ{<-c5dH9#|2ElhcjzqDRBjt_9xs=CqDensS_`qkPc0K-Mh3{GX%QQZQ zPo{AUE2y#?PbBJS7lu>^S4 z0UB+*@Fl@_tni&>@Xj%K<@Y59%cb9>Cz`#9a;NCVu zxt1FzqsCr{mlqH1_SC*0yhvoS+)%Lq+W{P3wXU$*eAhmY&KG1?#SVVM@b zqo78qzYg$8?e>R{Yo#&TweVp{7QUMe++7Cl5yRI4A6HUiv`vO@GkjwN?{&lX1AH3< z?*t^z%jy{IMEGP5y2B@PFdn{Kfh&g(OT55U7`Vj-?soXFOpDNajL=7n(0{?l5iv&l z%n03Og#KdqqESSyxW;I)hA$qzae~J^uF{7!g0CS?Ybs2RZO)8u8oNJTPG_*w9IurY zL2ZF-UhwK1Ttzi!$EM^riK|F`8X5bdE_-b>hHWK2R6=MnniKg;#4{v%D`Ou!LF5@* zk+lILw5Nd^Y~Y5&moIRc25u&NM~fIf19zd}Yk+UEh_MDfDcLfA5YtsOH!+H+L0vz^ z5{($W_4CYFj^1C+dXag*QOHe(Pqxqg@JU-|8QEeOrn_u-$k(0q%^b|>1k0N_7>73G z!tpSdu7$%}4gxE>>M5+?hYkaeW*whkPE(hlX-Rld1z%3U%h~04L_)m1K)fd6dw_Zc zfZ{DtDLBUvfX6MQL%5%H(Hj&-CPt#8#k-t1Cbh>K^&~Hj?|l%V?Tt|}P78PacL}iK z`j3>|Axbi$`1OV-Q*lLzk}ydW zUuxpRtfUXKdcmk0UP$8QI@Gf5W?q1aB77*X#c-K1jo0>=DQ4uWi-aY-=I%d_+O$oU z(I$+EeX=lvZvji>3wt!_t2BH|4PPUCdvPRc*WzCeIxoT}2eEgJ(9ev}L>SiroXH83 z^wop6NARvOd=JAX8{*UOO~DbPy@3DSz{QB0(6X~;)37$vPl2N$CgY&H1HJSB+zBO? zxh+QcC`&VCoB;^i3VJ2)Ithnn8uZ{5n`jUN&FT0Arlq@B-Gk;Cg(qRY8~HQ%W*NR0i>+S5u|dDa=Pk~yT$~}~Cn2On$X|%(4h5SLs5@%}nW0|R2$|^L zhB#ZGI6C8XCh~=%(e_I&dxWB5q--MstecquOLcN;iBX4Bt5T!W(n}LTS9ZvyMCGBfx6VjB^~092{31 zq(Ph0LUiTK;|&cuc)Ur{VW3Q#6%8H3Zl&v{DvXsYD~vu_Vf4lEJw)QVslC>sd~ud_ zf_W5$+cF90tz_rfl-CPOS;<(+N{%RAVZ0K5n+T%aU+z9VoRa3R?08njj;4GjKfNqh+_yk0O`=n7%w?t4`ZB& z-lg@*7z|0GGLFS;AQm$HXwUWanBvMe7m3rQ;uHZg^gMCO%3O~hB%er zBz1b81hd=>Jx_vZ-{SN>M44uI^{Yf~7`TN-;;1I3)5BQ~# z&?k+AzBqAlEO{=}k>mxp;Ehz+f)+Mgtc7oDx2>x~u%6#8S@8iD)>;Wl2yhm(;GQ4{ zO?|eA1zRy&#A+AKA^hBME<%}dJPtamIot%^P>VS*4$Yw$$0w{B;b0ExA$J;s^0v_w zE`$`DDY%18!5wT0ZdqZht}!YHB+MJnaWSb4!$H@8>S2CYfp!C34T=s~yBKs7=o--3 zpqLhjYWxmjwJ;CoDfN5{zf=!>Qa$v=X%FFF@*Y(_n|easJ`w|uyf9c}4C5Ao5I<_<6997kLQxTp6P2xiv1zM~e#iEe5d+I#As3Ob&!}Qmqy_pA?bD$ZXqX+XdU%28GJrh?#rKaeUnxao? zO7f^F$-@8>T1{e<04$uE8W1+Xq9(>+mUvtpFd#!sWghPCYNMuvQglt}Z+;JAhU}e~ z2dc{4JGqpqGL(wAAR|>opHvZjazQ}yHbai&K}DQv?F2&$%(7;^NX`5QMPR05=JgH5-4J|OMNkV$MV;)j)Kru#h#84=V z>=Z+T^hpiUCp9Q})S%@3*&4h6DOq0|Yu4cH0b8`a)o19?!`Gd)BV*duj;vZ~F2T?o zeNuDu$%_QZYe9U;3!eYM44>Z~9VKUN@(rZcexFxmG&HlZu}|kYdpAFh;g)90IC{T7 zBG9{;X6peZoja?IJ$()YiJm@Q&D?!Rg|FnF=%l)6Sh{2S*6H)D$SU)+0hHs>ZJ=WQ zX{e8ODb+`x?A;`969o%iu=@1rvsB=VR7p7XQ39QH{)KmqXc=MDhoMdT(HH{EQ(eQt z#Dm#MXSPv=#*8;~`=r{&;6O=@_BpnlR1?c3dpP=}n&^wuHsW9Mo>o5VEaM2Mi4D^F zPF&r}sHUIVq9*ZNTAP*SgUGNmi%_Z>r&Pr|K~h!pNmbD&8>Hm5;9T-xQ4PDp+`Sfx zdwaXsA%opIMe$8_-0Kp}eIwDw@h0#A{c=rUp8pItp$ATSW8JI;voOL#8DElxEq;l(Lm%FYXI+m$xcq|I||OvXWnyT2tHNQeZN?!6S9sbaR*i7R6xd$dIz-c0+Z+X$Bv*kKiZfb_ zsBBr+)kSqFvlqcuPCa1ki;u^f~_xjHXvnm$?6^vSDD$>Y_g)>MSj#$$2NSqG1cz#C?1M2y36t{VxY`TuH2WfRcfk^4_%$NsgB2?uujpmB*aTnr_Io8lSqtX&Ywi|H5oYZc8Hbov zIDT(S)dHs+tCk;I(OYOIZE@%}$~4B{Ft^bjs5+*L-A#U`-A`5J@9@j2q)%2QeYin{ zf62RB`3|{_PHRgWRiMaiRDr_P^8ZpB{ncKPeg3D~=w3`qyP|@A0bLJ@hloYz`z!pi zV(F6=OP_3`lE*eGd7(EkH0(|idlnjVwm0VNXw2D(heR54_B7_~Ys}f-m~%jGWam>s zobJf+FrPCV-OJkyJCTTnsps}d#+GyJybWwCz#d!i>;MK%tQM$w%Ou0c*@~Rsc;Vrl zq(pxDM&vtD44=F@NyeeO)$kUZPNMSS8}nj!{cE<` zH^7JbPC^Of$V-a|KL!s_CDnW2nYc9JWhkqkjs0;PSr%0>4#Run7#C>lbL2}Jlf*g# zKhA-LdM{oG!xejJQ@|T8U|(`vmbaUuz;@$(>0B{oJFUavcFQl+GK*Z)a=R-%>d6zAvlPG^@lvhyNww04XUtV-dw!ut;B0n^yFSdOwSzn!yg>Ht?elzu zTlY{f4%;V>zeF^zps$j)u_*@I6FbHv9J*uL*5%RrG}#ey6P45teNsR4$<-LiYe9U; z3+@Ov79xPR#zHBHi-?hw6si+r94d(Vc}%a)2=@i?TF=tD3cPfvz*FPJ%hk^FWY(3J zduj^cYoq3jZ#9KlC}n<9aF{28w?J{sBNt4W&kahEXBvv6Pb!kWIBg41lDAd)tcJF+ zKLQR_k)b*>vm)<_Xl+M8g+HBaS_!l-Au%tsKC=?B5l<-b8Bk{LSx~mt&V~}{lS-ry z?-x;_cvp<_2_-h{PMD&mSV7aOpd~%A?suT6PFx7d#lfI;!3B7_4iD>y@OXyDWASk2 z^WrHIb%hnUVhSN=L5n8Bxds_p%)X%XOgObxX->tQTT5>CH0SKcOmH6-A@^7oAIH+;4I`K6l3uj(_=R1pQ zMf)>?feCa5=1GLHjI1wMaqUE1m)UKJX^(*{vn`zm+hKlg0_Bwo-Mi?Jt zd_lGw>ujL{Ibn_H_TLp+?|?JCmX;u_zom^a4z9X1uBm(xu9j>goSuSQ0oJGKK`o38 z-PFRYwZL?(wXj>${LIS%Q050~8lrvefnU}FeX@MzWT%`AMxcW>|y4*eOMS+5)~LikvV z@)(E8I}t}GP8EfN@{CWN3>^yPW#QeFo|=i}dDz;WUsdbncTd`=%ia)e+$yx)Vq*HV z5p$nD6MZ=IGz*mZnyvbDJ{u^NOP^FOeR4%y@-_i4c^2hj&u&XXxLH;g#EPUjKfF;hUS@Bl_?a;VPRSOZG0V^5s@$w9%A;E~;%EKGRRZVeas;HZ3~* z`Jili3zY8A1eNaSle(i%Ha*E>(~~^A?&bg+&bAI$caI*F?lS*0-Bl{xRVm$7E8X=p zbVr}m9eq-Fl1JT19(32RyQ{hY3UjYQUFYDQp=P>exF6?7L5_Is0v0FrI~M9%)z~Z( zI`$rO?A^SuZN{6l3@Q4q4l`<}9%{+Rj^@0be7bQbGn3z3v;$XW`fRFe;F&5sf5AD& zJ{*aB7);%@90}ibP!HZ`3*QeSbQb=95KWAhauvcpP+`+jR%!;IS9S!#J#az!-;^k8xaP z9w>~fJv8ou1)e1ZOBXKm;QisH@_`{?t4z%9I7!x@MdYQ0xf@8*$~wa$FBu40;3Tt)Mr8vTQelQZM^)$gY+? zY4Y^NiQ17o{!5-P`B>YFVQ^alx94DZc{7ms*R^y!!N^!x8+(ao(z>s z`F&x3hU^;L7HjX^k0*`qI~9AP)2hYCJjJR#TSdMpE#^N3$I&>l75^{j;#j6TK~Dj_ z8?-OzJ)oJO_kvCZy&sh2{wruaXdmcU+6R5oKIn@R^BT$H6NHi{?Zf`&AXp4!@$GxG z3EY+8yMUsXCBho;m>8H%bqBUZuin;m?XHg_EDYdDHBphQJi2U5>AGlvg#l#V_UsYk zbRibUvF5pr(Vz_#+p14b2QwGbT|8rXfEB{pz6*_%)i<$@-@1)55;;pH4Z^iL)}0T2 zZZVD#_gh$TgK_ANc^!j;=`u3iu%k3T^N$bn`B|wWL0J|TC@YA~K~@lbvV!P~(_T@b z?X}mGFHStcEpdAco^=k8fF{e996R|56ima4Pm~%VnsT}#tP8>tW!UqdnZkM@EE!=* zGVJZo^k_j><}W1Ui?4eBP0RZUN1`^%@XduUe0yGmP^u>x2c7kLozkp}9gM@te=!c1 zQ9GF48qazT9a`)0O)0LZYwJyr|0|#Rq&c~8=#J&)21WC@@G9Chb@30-GeKb*;_1QH zL8+fNKxtMEv}tKp^hvX#FHRebf5{uBe72i2te^!g@`=wQ@en9h3R`;uv~P2 zY8RYk46$5MGY)kz8^_Nyb>Uzarmo?jtisq1Z+;fIO%H&InGKu1?wB{8$KV*In9DI{ zGruc9yMZ=MRFD zYFbyARns3J%=)kp<1ptu?ljM;Y+D7;4(qDr8@dBK2t>!sH0{pZF&p=Eb@l&>OYqWS zOt|ED%FY+B?_TVw;irT%1fQh{=4aw&YI|{O+{G~OLQjFuQ!V;yQA@qR)g8;VAFZGr zs6P375G{!1d=!+m&=KLX7U+|;Kp)<_j(^GPs(jX#gbOiPK1&|17Q)&4CdA3N*gJEp z*TP+qYk^t{=wE;9`N7tM{z&1ws0ZVbLj6HG8TWI)}!6z@JE;W3-IFP)%;rjzeqV^d6!ww zniz*Bh(@AK2s0FmPqpD)D{UQ%jpw+;WLTCW1@d*rG_Cve-;0usbRQ`5g4f=O#@Y_% zAx(%rX+reLl_$yD2)yJ4n~;8=>@XhQ5_2C*tL1E+DmxL!_j;!rbpNrwjqTEyxEfat zNsy^Kro#~jr8QdCNHvnsFr-@OlWL(4-+95m(XMffMG<%f`JS^B4`B}1u& z?MkYJKB*S^q*^48YLUDU*7ElD2wLHQqPH!0ZBv?1#=7G5#z3#pa!j)+#6j@4MQ zlvdamNv+T)wL+iNisVr%k~a|cHWUXZlej=)$77?XA9W=+_Jwr}J5m^G+y#L#Vk*f` zBE^X2Fhuy05LzI7+3-ygzIpIX6h8G~h&FztRerW4(ns!s-geb*p7<=uLU%?PZtNtD zNGkCa;O0(oO|O)GDZTY?K_D+}btNLtEH5{S;1!7QanqVCIVUDDVv@HDe5nKJqit~r zmGAA5yd?0XFBv{=K#CDB!Q&K%Q`m!Zei4f~>nD87S(5N^x)aD*H^EB;ueFva&&Pim3sDa=NQ9>xZPe>(xi6I{+8VXRP3NTT8 zbv0z>^_(#C*iK}w<7L68031y6%!2MHyg^8#o>vFSm3j{O_LGnq#$~W@l-U?0Nd@4o zb%ITON!`=x0=n0$D^y`*CaKHdOr{4V)ZaL};ri=GV9q-7k3TND2$T~Pzxi4TACH;EVJIxqjjcO34LeGXGJI zl>_DTkpY;(6p}+FML8-0fy&pfhRa*>g!+kc@U_Eqz4D$~BYnvQqf^rdrVZekz-W>) zC~cjEGdPWta5H8|DqDOIX9zE=Oq@X}X}nt)#2L^9xsaTGfeeb}jwlCfkM7xPH%yj3 z{u52dB@tPK4)BpHIp&hG-->eRF>nH>Tfu4aRM>qx%^d4!ghX+D#N_l?#fnEva4hCF z5bK(hqn8BIYF4p`K`fuA-lsUnh**iR>GR>c|MN2z%K(8%t`{d*sD9(^-n)!m%}b0%JC8Y_55_O$zd*{9B%xx7MH(=MK4=^ zju)5;u$NrE{DBQlw%YBanNAkMlmi#%qFf*SczHLw9NzPd za%{)Ho}UwKaws9t;_lx6)^&C{oH0f@_L$_HY?H%FkSK?q&Xk>fpmM8zP8Arl9iC#7 z!`2z)pavK_sp0Vl>~fL>W(WTD^iH$MfjU~1bGpEo?Xa6oPIrM}>F6@bJ0Gy;hqW23 zpYAp}Jp@LVbNrqg&?Q*)bB4f}?Wc!LPR};T=_N4ca`m*y=`Aq4er7I~dOO3kt@+{V zM3lp<=iW9seFSC={@KU%t3P$7UCvnovmO6>ef6=)=_@d)_-8H}KaGFME~lTsnC-By zO%A$0CL^-a+Kl8l$iIZNi%SjWMtqKEz4bDWH`_*)u z2lDgY<_CYX%jqvL=KQ4Ffa)t`bCjR4~8)B2gb+0G~OUGPnzwQfEjx|5S1jbzN z=h)kYdcOx%!`xm^sm$r&jy?4{{aPP)5?U5*POQ4V&z)Gpmfo16@A zqa3=NrYE!hYnPKLFbD9j%gM0G$r2b|wdyE+<=H%>8PXO-_!$RN|j$xlelO zT)Ui60>c@eo}V0>oY4YPfq%LIXZ_n}moo+-QI4JX*X4}1$;lNMbUMO?9#6*#%ohCX za&m2Q#t962Me3*i#)+5P^D|yx%=Rc&cx-a!3JeB6T*GKu z;lEbBWtTHgV0PeNulKn&IbMM|1^;xR=VS8`66N4HsLS!%+kz zSzwd1P++>^pYDPAFWqC8!`?es&O#$+8$~>Bphyz-t7&g54rbAc!;w#Sv~l?$u;l2N z_B0o`jz+8`#W}&?aLt!)w85F8I9UdV)=B3zIF~8T0)um>;w&^cctldT9tLNt;`B5) zyA-F`;Ka+qXwwbOaK)Kra26>}j={M~ancRW!-~_};Jm3gXB!+mmL*)O!8uw@Zkz_E zx8ig+I1?1dZE%(-&Rm0YgW~itI4>(s2ZQsO;v8#my0M#pJK5l*D$XeeXQbi`FgWuR zr?0`eTyb&@&a;YBU~s-soJj^JPBn~)1}95##u=Ptij!w>o>ZJ}24|b%oM>=c3^6#nOc<}@M2BphdX6NG zkCn8&5vz~loMv$H73Ua(b0s;D7vO9KXHO6(>KIL15A6pqMc`}+;yesa60{b;M8#ob z4B}LS^AKtYxpGuOpP6r<*XcIab>^O*YOAHqJdZ&PE&Ob#PcgamY`U)~~kSSgouA zH_D+$Xy4;gUg{}#^0Cq*W6@s?P9M+!=NWLi2XPXP!)8Q-lRSPxDz7m8qLz`CMoua? zYs?&8h-p_D9G;DXoKc`MEyPM=ta?#{N=_PvUpzs~8q_88%J8p2oWbDS6~tj;cLZ^m z!xmu)N)E<9?2J^L80J~%#ck%K62uR98L9KqRm+EckRxIVIn4&ApHRG97_9~d>)`^a zX{Y_=hMn*#cL~Zq2Y!JOypO<12;%hZAU9?OFz18AS`Kjj0Zx}7P7H+@9P_#{XKPW8 z3q>fjzW$nB0jteYv4{y?H?9$}&cZ(mshr-$aW@*OR3j!hRxLPDj?l5LSFwl*j^z`v zy5XO0-JWB<3*_)gl|y3mSjkLSypJTxktp~)r&Gh9_MM7VCwS&H{KeozIg;>?#;ZMW z`hoN(Z&K&)9R7BRuG&I^il>dpP3Fg;bjibV`!8GVFY-H&oGEtc!)w6{=odaPSi ztn+0oai>OV{sM3U+PFo#_w_)mjVcx~!8u$eVsYSPTGHuhy{Tdm6C8_nD|1Nf=*8QH z2GZK0Vi6M@>mm^=v~5Hkk3cwLg035vD&u`ingu~JklVuE8e2E|%) zjvpPe)Uu|zR4ihGW33H}HD%zeIe}RDDi$%pv6@6I)rD!_bSl0f5NnQ#MNB*GVw|~4 zd=rW*@pS0|dUGqwy_H_yQgJ?VF?XK3Mkc%Y8lI|hSCM;yx58EHD|5MuQq#g75|Ngh zsTmUR*)h-Dn&Jw#c%@WvrO)M_kerg?Qc(AVR#XG1DfKR z;hKRhn$>l<{ajp80k3yqHO_00bh$RN#FtUwom=TC8&%`+Mg}3)IKshQsC%A2-NG|c;-UZzEDew zZ~~EGdMX2m%pBy&D5T3Zh9HxQgQZC&2c#K0NudfeGBZagLs(wOf(F5bR`l!#ZOIBY z;1EF~^QM$jf=iQ{nwpoICq$<~rEF$;D@n&Wn~bcD$)>k03$57dO}2=U*=+>E2*tZS zpcvx?3juYTa!efoEFb+2jW*0jVetk6K12_&@m2>RTC^I-3h{;l8#Y)^N^qzbY8-sb zKzXeh6p03cWzUqZHbVt=!@FDsf!-`NL~xO*SF=3eAT4HUe_Jf#&;Yr4%%nBl>JCpz zD#Zl7B##vt{E|kDH0Y$L=#Wofgo}U-k4!fDe7RvPqo$^KsS90`^)U`~O|CIxguRQ$ zFaj#oA20}?j3JJXZn#`2LQ14pv4s?snKMQfQN8>w3@AS{8%+;gFv_4m+gT$!){*Yf zp>@Z`E2_(#(+U6sV4&m$9-j{{6P0$syp4pxh1u3-GCRl!1LBZsH6v@cqnp)1hzM?w zp$saFFx{*~!!NH&g~}r!^Espiw1a7qh+#8UWy5gjfh4BHR>;`h=8^Z#HveHF*6S` zCiysokopI$oxB9l`NE04C0?r?Kx6==<$bzlyoPt}jwa&u78RoYax7hUTS z&^B}}E6`V5QsFr=0zLB%IfGVZA7=JKh%;yIpmcA|%E3h*Intfwa;J=$=*pZpenR%R z38P)|X_JuyN=K%TOeOi z$7PS2m=&(e4qSjT!O8X+uFItaPEHY5FZNM#u!tFI!YxD6LX<*=q-MBAVwEE&1G%%w zRgm;xg#K`Y3`LeOIS^6x0Q93Qh@KstExCGDg1NSA1P4PWkyWiU69yE>P#A!bwTR*7 zOhy6@^5F`>&2B>0oE$myp+YP;a+y-H^&!Jphs4kk7=py$17vxHuddcp249T_vo(34 zp2GfGoTqz+&=ni!<%0!8KOa;+sGLqeFA0R#FI?!7;FOebREs-1HKl)gQoyCA4@pZ& z8#o{(Ex@BMH6>->z=5Cx2BxQjCMC^@8}AtDSbh8c$+LcPXkVzsVDmE=Sm@JU#IZY- zK9h?}2-^S75MK$NfK9`lJM1^2n}dZ~mzI!eeinoL3LIbDMqj{5obfn@2;g0(iMIzZ z^trT@7W4fj@-D#bps6;T%Vov!uF<=9F-E|-5>jk9t}lOJ!zF~oeHaR7dX|AH^~TEZ zHsIQQEz`ZS9af07{5fJTta_e-Az4Vc1&`oH@wsj|-eWUxf+PRBq98v2)8QD2;~lT0 z1jsWz7bB2J=ao2z_6lFO2giFst_0MFC4XGa?RKm~yB`PL(KtfM`w0B+fq9c})r8~S zlu+_MWpD?F_GyB|@kU7~d3;);(dp1uogi^cHzb1Nzw?JSf$K8@i4=IxUs z%X!-KAm$a|zM=;%oc_8a?8I&oBY^k|C2t@2!+=XUJ+i!xz?CRWBzdggCBPMQk1UUO z_E!P(tiqvLh0I?f#JmH{zqw5hE?jy0BCJafhn9nbE}Xm;giQzL#4{w0^%kmq^aOtp zFtZgdoV*W#s{v+g&&c_k2;2q0yryvBm~_ z0oTmOf#Jg0OESWq1Lg~b3#Y%0!2JZwgJ(;5;p~Mwr{4f(r@|2(Du3I-{~nlkQX=P% z<8*YY#K0?DD0#G(c;F5wY`F50-;XcoFu73jb|X9;xYN=j=a1v)Bw)M>7fyfd50(Kl zo!g?}!sU++5sAu*BU(f*Q&8yQ(1yU{dY z&UHy#BI1QA?+)<0XE?N@Gb78p1r;y^m=Cfg?(_)q`i#Q7b97{R$3k8PFcWemj{Qxz z{LLJTes^4Cc@H9f4KUrtOI$d6VR;7tb7Ed(c~=5A4wz3AE}XpWz?`v@JSNK{xzJuW?&Xhjx5iQ__qRcT0sC8 zN}h(`Nx)1h4B$e|H#nbc0OnDJ3#UJ}x6Qz8EQ&0T_4^Gl*Q>4a;pDM?{|e0IQzOe` z{k{mylxYE6sPb~Yy9St<(*w9r<>h?*Qed)XNF1-DLdm24ZU*M&b0f=RdEWx&!kH2m zsk~PJvv^iydEA?HH!%HX2XLYC$NBRdU<%yV+0t~j#1 zM^M0Jz@(H(95$VX)ZYQ{p9W^5C$c>5S^7p{MCQWCP-sGjFf{DL! z9A{NIv@3AXg}Xj~9bs<*b3=6qc_OC#n*{PYFsCevERXq{4oq%MWO=6pcRnyTD_pqp zZUOFLV3yZLmdEk&5n$d_xN!1XfcqSn+kCCd+X~Eg3Kvcu^A}a;(B8#C7gQgDBmcOS z@~FiUqq9TV3+FGLf%`#W!^!ImT#qHK%VU2q47kDdk@H7+^A!eO;X>t)@|FX)Y-wb9 z9Dg4KX3%*O7p^}jMDQ|T-acRAxK}+?dpiliBQL;p#WINtS0B8dSqRMZ3nea`{wjfM z0_JBEE>wBh|Mj^D>pA|&@-{%82bh@U5*Lm0Q1Y0+e!!fxBC@;+;KnNqyuyW&w-X^7 zfm`1YS>8C{-T~&6l@b@O|Ks({Il!c^iY)IW;5-TguW+IA$MRkT+=A7Szndeibl|<^V37ymVl?UmC!LYQM~1k-~_~ z;V+at>Te-%MVCdE$Nv6eg^47O^R?T6yJlTvd9>%v3KK~l_4he&?_A!xyyz<=rZst| z0(ab%k>#cXecWtlwu8243Mp)i3k+ z9&qq(q1U<2jE`0wsm0#pW-9e@kfepi5Bc!xuK9|v8y z@w`8RyZ*(Y<=-iB;l}g-K*qDc+;^A6CEz?%{wQzU-45-ddn7L0cuxC!SYhB5E|fg> zFRudk@V$}calP&fU=r?=xJd0I8JL9oBgjWT&iH%l`J=oMz@7ehWO==SD+J~Og$rlT+ksmLO!dar<=qC%KNK#Kyib66_KC>y zQjqQ*V3MAcxN!4b=5GWrr#{uXynJB%3KvcuuitI~=DepP%NqvV{lM&0xN!1VA2HA1 zegF=-aP_+gVO^iaeJ~t!;ri$O2zwWp*PaXDLiP6>fOEDuw7=n?W4fX2?<@rG04CuD zi3``?-;4Mc0@Lfo04|ig!3e$vm^U{CaG~-y48g-*a%lB0OI%!-{N04$kASJ)EOFuV zHy!cs1t#iMi3?|cy%5|Pn34aGIO;iM{=i=a%<~Etu6{L$`4pH>Uz75}<&W2I&etUd zUg1LNFBy=T!1>>h*l_uyy}S&}pf@EB(}j@rTaREjFdw`napCgE{Ts(@kr^Nqa})_#dvk!+@FdZe)3hh<}B`z$;uRc`k^#6S#kGjVupcxYp%8 zw4?VWj@J*N?U%*s< zByr*T1I|zX4$N&Iw=QohFy2pEm-iqrH-6f>yf=U;+1|RmyMejtv&izELpfdsX4U5s z$9^bOeXu|M0hkZIh%Arut7CRZ47|dHlD8QlX8`xD!iK94%1ipPZSsZ#chtXI&)*=0 zk+}<9Ugob5xUOHdE^mUuv?gx>aOpc+m*-KK*5s`KZtT~Q<#E1tfx@&V?>gY-eABwT zD-@%!djWZv1EgZZ|OZ?~W{w`=vesrt^O!E}XnA!1V#S8c$Z z1)S#x++W2(C+9=<{1NvDFn#t##&O-}dWE4pIS;||mt%kc;>Zz)`$ z9D#R{03!D5egVu^3Ky`0z}rW3++JY*Yr_Q>nDfy;6o&EW0{N5Y{3kBzC#hqd8xD7L z8*%O1i0jZs+zD;Ob#5c>BPCGcqhO_s( z?5{@JaQUu&S(6Ksr)3rCHbi+7fh$m0Vb2(6l9H0n9+i?l#+6Ki16IPoXHu56DPZ~b25uYyT|8D$r(R9Ed+9MT_wLNINn=QQ(Uuj zcwTmyJ9}wm@j`EDwx^_SE@EWojLIk)UpPKDbLi;{YZsSR*Z9gT?7V_0C``76J8^vW zgp9nLg42^&w7odi<0#P_ydu%EhR)2M!pFpBX4X~UVau7B-pb+{ucvlqZB41-shreW zPWzR4Yi5e<%`EYa!2|22uLJh0Dw&VZ?hbQ0lDGwdNtNSuT{_M4@;xn8<-Vj|lY1vk ztVY?r=RrbJ7Cv&~#WSV0ZyWAM=6UJQZi()B?1L%7cXGJBVK0uqPvU=x<^a!N8ts2L!BFc|KpEN;2x{R>slk`&pYM!&UfQeIm1sizIUFWzIQ(P zL{3m@N;2?5J^8_Nos)?d#yXvBysPnt@5XxJg7O%QUti$Il??PRt&}Wu%IvAF{I3@Wc@^ z3ig>$C(u>CVxPCFGNYzcMA!p$o8@Gt;^P}m=iP|lLi(Mw>YA$g_<9eb2>cc+UViHR zdtiBKr#sq)AN9zsPg4$~OsL|9t=y8W%3t(#{_O7cUXlE%wmbdGI5=vXSEr-T|S9+Q>r) zMhoAIJoBo>+P+yRq*&Rqu_B*ruYMf5V_mboavJVa zOfOh*;4K6_2^3qD{QW?yL5o0fy(jKI)PZvK53j2f?X(`0uc%%MdOGL@pe3Lef&LS8 zE$AsouL;!J&Za^Rb*Y=(4am?yE&9(GPfc%6I^yH0Rkksn?nBwE?Tuv~2tLQfb$Y@1 z)zmhQr$!XWK=-9wg1?;@Pj|uw*b8^Sm!kK;&tc9t&s&RcZ?<=GHp?N6Lmba(^YUDN zTAIdw8TucDi?IifY0B?SOJ=5Io&qKZH#UF}!8x`Gl+n}y=XYY$QD%&`yK9N-~CPlLHIa{Hbuy#ZCe#RGk zF}@p)50H{T+njn!sF_?3AQSSS7CsI6d!#sUNQox*Yf)zCN(b9}ee~?Tr1g=~APk7NyVc zv=3mtrLyFlgC`kN?fF%BV<~6(DPnT2*#lCcMW@qm4@jw~!i%Qxxdf+k`)~SGe;%)j zDQ{|3O+}fAI>#P0RYpCYf}wPImB48VuRsF1eh8*;oy_$KfO0A_1V!qkRaVt3MADtW z+ybVIFD{faax13_{zJk1O!6sYox!j1RODCH1|@hd+P1p8a2&8_0qaBho$&3AcIW^C z$3&-?=Oh5HJK84uozuXGR{YKEZ*cx9DCRucYoM6BXs?4_0{SNCEudRK(HHSUBmSMB z?|^cyyA{+4S?_`N1VumYXCAkK&I0`x=-)v<0cF0ogLZ_{c7bN058Dko2J{Ee0?>V+ zvq66Zy%H2-qQ3?7XVCwE{sNlDjuUs)e*}#Ird~4IEv&!$9Wenam4vv(2H?oSlT<|5QA}ByE0;X*I$1pn!26@VwoML zE1aUh&;nBwGT0mZellKRjkmj?ZdIMuo1!uwtkZbV3dQe+GBR(cgLVZ?2JHdb1N3ZA z)RR9Iv^OZOGx@P)e>P}e&@xcWbN!gFYAK+!fmBeIa{#DyEW-6X8~Bub9~WBJ?-}lzKb|lzPNmRp@a9DD{{DNu&sS4ii9vuY&io8krgl77%o#6`i!0|&@l<38UY8(VW}qDpMu6^g`=gDVrI>}# z9d$ef6c;WU=5@l(riak!@5mpw59_KKgRG8(HB;VR9QEiUb1m(VaYiDH^jbY)M4jp{ z3Ktq>a=K%)QBF-;*q3qIayV0l|2yMyBC}uh)ScwzBw17e+fkxyNgTyh>|s9vO9lYw!=>0EEjUy9QNq&mQ;PlXXWogZQT z<3n~jX%$%4_lao9KuKP0e{?iX=Otjc1ZaVnp`_)36eHP1 zXdsyG8HrZbR4oy#J&3B(T;Q!1sqQhRW_99xp8@fTYz9_oi&KS+9fsIiisc-O(>s}S zQ9QS&rUn(^bbe?+tE-k^9l1=XC!hIO8q5@F^a`jVU1TEPC`z@6l3<({*QW)|$mT&| z&!cyQl$NrY%X*C#^C_d)Oe)h#~(D|TqK)I)+1hf&f6m$cq2lRE&a?oEuSAcTeU?nK$ z->X0|FVR+mavfm}Xbos1C=P8c=xw0uKxwsCfW85GB`9|ZUIohCGFO8h1La=>+8gvb zP+Hs#poO4Vlkt~>-UNCc=*^%vfUXDSr}Z{~J_mX`=m(&G0X-3Ay%Y3g(1$_OK_3Af z2l^;zDJZTL{57DDgDwZfu5tgJpihFn4*C@6UeKpOJ7I8p26Pzcv!KPGEuj3o9m?i^ z0rUmX??JJP*?&5$dJ|{?=u4mtpznd+0{TAaKqrHK3AzgOYtYL;zX81kbT{bTpx=VBMePB719UIwcF^xZkHU2cbnfp1 ziXA@we9#|3{h&XAJ`B1a^fS<3K)(b174$dI1E43PN&ODmgH5X)>L1hrx*W6}=%t|1 zpf`cWfIbQu3wjh97V6la0~!Z9541g~9~7@V@i&8Z0Od!(5 z2YM`8Un*!P&~(tApaVchf#P16e-7wi(50ZmK+gvq0eT6j3-mtF4A7TAvp_!q%>|7^ zJDdn=ouBUMh`AJOAQ9@M%ZA51m--&{Hr+CpVjQ+#()D`8HqE7qYOx?8mJ=tIm*a)o za&Cp>b%)y0-T(7*tN%aaGj6b%W_*EpSXFtgm;&Wv6jFDtJr%t4z%rAuOvSs_yoKR( zK4kE!YJBsmLd_pJR6c|mfxg0(D(;!5kRxVDCHRg*hFe_q$O)Vo%L^P#zJAf?baHM< zUM!|qE|_g6jpKTz5GvN-4567yC?~K9zv>b&6D5Ol3!jKyn<^NbS13lB$j3v527C*v zc|GQIRvRoVobjFxHW)y#%*Fx%x!*Xi@KmOW+$RR*R7%=nE@Y;Vlwb&7B3lz-$?dtzrUi)T}Yn-T{`>Xz)z?BLf=%?-I)@HGC&1^g7Qo7?<=f_;}dN8&s{tFmSIS#%EIv;csDCe;+ zgEoS`0=fb84bYcB-va$7=oZlLK;H&Uhs<|C$ANAIoeBCrs1Ni*(8Zv*m+r?LSNjO` z7SK;YF?ZCqgT4*=8E97+%jck&TWDW`a^K9qL32RA0>#*`?F5|$`ZZ`N=r^DXLGkHl z|AV0a0sR^DJJ5cZckTt{eDw#=D?s;wz5@DR&>f&Zf;ym!{h-r85!e49=&zusz#b2P z_5=M5bR_5>pk7c%l;&Rm8U=bMXbkA*ps}E*V!m+<=nT*}&}%{4gMJDc4|+1@fyaXK zW5>sVR)RV~Ie$DJ^a{{K(6>N4f_BD?q7!HVXlKyNK)Zn60E)S}|9;S}pwEJy3i>PP zX`oqXc-=r}fOZG10PO*K59k@7{|4;|+8y&Yd=}fk0Q5}IM?m|4{t9|F=!uwrrGTb^ zrh@WQuxX(DtT3(#{1=1v2VD<39Q1zB5uh7Ev6spJF{leP3iG!N&|aXKpn0IUr{J#z z%?7;=bQI`j(9xhjgW_I;zc<$Rb3vzrjs;x{iaPZ_33@K*+n_T+zX6>E>O>!cdlLS^ zpv9n>ptx4?PX;XmoeAmzod-G(bQNd?=tj_L&=)`#fxZn|3;Hk6I#Bja_%yg51DsY5 zdIIQD(7~YRfzAd!AG85<8R#RR7lQ5py$CcBozQa7(?M5&rhqnpP5{MB(LW9JV$emP zYd{|bZ3KNDvCH-hGZJ_$Ml^l8wgpwEC_3Hlu9{h%*`J^=a>=yRa2fPMnH z8FWABKR~%^y9IPO==-4mML(2`Lw8_{byPHC;jHV`mw=mTxgKB~RIfO$=ZSEk_AVIT z06N%ZYHmkC%hX&rxKX*l=c&dRIMMk%7`<@lj>)s1MmL5uq&pY=4)Zq~)LLGy-?OX~ zPB#Sh)&U&y_Tu;}4r_TC2Qcn4)UJzIUR>gctDRa~d3F6lgg?X$F)q0?OI&g<=eKU; zDm)r>fW?{95T^?)x=~m)7kAC%*yR#T`N#ZHC+K3e{)%4!U9b#T-|%+>EdoskodU{o zO$D{;>R2c>0djO*?Sz2-CS7sN8f~!+#$lSIx3s3KyeeN+O<{2jZfgjIF)`hl6&Cd; zuC#N0fmxaP*1eeHBOk}1G7_~#8Qw~{kjmO{;YifVd}4aUwN|8dK2ikpf`i!KD4$TG!C*hfSwF`J1FiEYIlI*KA3hV zDAw(?yFizM-UEttHtk+etNmOIdDNM1KkQq0uSaidufcD%AI2eO365J2)_#~+2p6is zbuxD_rdm1{e7&Ag%WRiivv)yknXE^4O}s@y7AD)0DOw`?rZG5l$Fi_qFqJXxE&dgH zV)-!t@~41430eU96le+P)1WN-GoV&|4g=rRENu5#&qug*?+)XzFYJfohKTw^BNQek z3)EFRKEa$8qU$b{I*szPOuA#*EI+1>#+Xxraxp)ckNTOXvJmBDzp@2ky4`S&VD5Kt zAJ$e*#-Y8F-guDZWLmm2mDztpyPXjI3>!Gh$WA}#HX04k#FTr7#jUXft~%6s%DKl! z-h3IROtBO1uA!UZ9iutm${u;^sA8+;`qMbrC}d|d&c)FJB)Q)(?+@#mtR zsNZ>@9#AhR?}5(;eFGHx_5BXSSqRE*9Q*cd_B$Ck>Q}E<>s;ezgjvU4#-Y7r;O}v>p%`6twIikwPYM^RIqO@9 zeF(3tTZr|DK(8o16ppb*?hzn@TgOmIL!7Tu9vp8D@qC{=HEtH+lzrrNicP|@P=AP_ zU849OVV=tJeGJ+Q^ixpk?{iS<`wP&yptvR#`?~%Ox)kSMfnEx_6LcNuH=yf5cY!_z zx*POy&~HIM2Hgw#Dd-QN)a8Fct$i-XIM$7>yx)+~)1W@RettoiwSE}qH1Owv-WIWb z(C3QJN{af?O#m^4cv3i1{q)Dk5wyiyuOHS1qZ_qBo7M-Z8jo)Zw(GG%II_^`6+~^& z>F4GOBmOLuz#Lv^Iu~8OsL#74Nc^+xtk2_dc9Y`&482kxzkr?v`YR~MhTlME5fiQX z*MMMc!B5+02g<%68gw)0QJ^1!#(@44G!~Tgbqpx>z-e)yok8P4hl6$i9SQ0L^?;rL z%DPAdWt$p;#(Ac8wDand*vIAO<&V$J$}MzfO`I?#XPUcUOh$fAfxDnEV{)N;OwQyS z)TP8awakgr+-cbo;?AEuaoY64>G?U@=?ZYXres9GBodRAF(oHNLP<)_iP~u7DkH1V zmXe;8t{U=Jn49I!AD=NH$CMRa#HrR~awcTU(sWaaoCZW*{=_2iMUhQHbV!m`FmY62 z=EUsjHb^Ht#YbzCuEaN?xDp@SUV#0m!Tj9HaxcE@xl{z6ilo2AmcM9iOzwoyIn;PT z;pB|m359N<#}g2lB6 zGoo1)`24r{3N*5$f10&nTZCu|vCbL{@um;DW2rRO$$5Q=Z&Dq;l3P>B z$MDVuGY2KD^_2}BT8GDCm%8~8NS6fx-27H8eBGA|9f=i0a+(tO2X|c{CJ;+kbiYh#m8?vla z^msj%JJai1;;r?#MV2LArun`OG16mxF#Cyh_SJ*jQ)`N=@l`>emIU^bI-9vH=6A#0 zSY>wO9?D$bJW=x#bwp5V6uDLpF;Wx8$i*R{6cNExrV-j1h&4kG4lYIzjyXFgG)~nJ z)4xYYh`d+8JVk~_DTAzpkrs1@IZGv~l&!18HwDjqR^dCkogm^87(c!`$(?`Y*w_cqnd65EZNQPVFm({VMi!a=2Fb| z+-dzq1>R?fGa7y%f-u`BgrtzYLy*A1qKFq@lvU4YjjAY~TZ_eqSmzX|!|h&}nl=~% zDXNB@K}DH&F&ai9&MSmoP2cXsU9DKrZPitJ>Z_q|Pnpq}MdSED=*;?gdMy>v-VGVV zr>?DVCMatBR1rm_Z(3OB17Y`u3Zbk34t;c0nnv*5Z3CwYtzOwit@alh>IG9p4_L)6 zf;aeNzS*&(`&)>Y0QlIN#Rr}-8;W&q2$hv=eshw2)(R|dmiRJjs*201(a1dc#oijN zI|76;SZg|94rxO7uL{`#1&BFVEiU$BoiTc+T!u#|$}r89b?w$Gn`6x_D7b7Hf$=~M z2gJKz@Te-;JlN6Gc4V6oEu+6^cjHAK#_|D>Q65iO3BH^yTIf+UG$|Lh#g;fjAaPmF z9e45yhZZ@ICMYeCr`?b$F7|wg#M90c z7+cLmqvtU7Pm~O4=r&k7y~B_wy)|6<7azWjckvI;- zF)avmrh)b*%v#x6G2XtRn;WND14W9K$rN5K5bJCgDrD%;j7o29m9M6%+FLrR#w%t^ zvfJkD2pzhx`=F`W(4iLbtkhcER)}@}E_x|Tun8|Ev#CrGHe!r-R$K^P;r$(G{*&1Fa6 zUO2En9^{O5z9jn++49Uy#X7QxmO_iVQKYXw)0b1}t63^$wA?{snm35??n`qkFy(_; zZlPu7=Vc2U-Vz)+P-0p@h1KS2s_K^t{g#CaG1rc_0%kb6rmC)*3lg%AbgNF1UFk8% zpqkX6m*6~JXpk3zfw5!)`o_f`X%n2ld}u0Fe>4w1$ED??OT+XS_eXB-GW*VJI-Rle zmzQ2FUhRmPAlHBs9NpY~uj%*gyNkb_?fd<>#~ir8y+q)jdMtbOIV+F5{j*cY=eO^9 z;a03$2!49^6NWkGywrZv8;jbX|JWz5i)Wf3|BK^0+;jcLbrt8vT+?Ubt>O-HwFLXXHF|RaoXml>)zk-%+v2bzgXN?hnyQL-~Q+kPs11fSDi1n zzp=bf+~);)I-){1?zdV5bt5^_DaHO8Pe^yJyiZ}0@w0FR@@9d5h z*Yn`lFTZjBn4NE(y8n@0YqYU3<6-I0b%LYTQ?TuFXZ;x;^!V!hUoZI2M69O?{@*5? zy`bINiF5k2-}G{GeEG9j?-BeDPk#IhZ^>ipc4#xJKf3C?{kRX08)6BLe}4S<%y%YF zdhnjfBU~|F4;JVy6#QL%?)_zgGdnG9^=VhtEO`$4d0Fsp>3X&+q2%|@$6i^b4fW6H zjHN9s=%aq4`>tJh_M3N4&!1Yk{lS(ZtceQ#Ki)ej=P&>M<%9M$%VwNZzY_X?Sn$VO zJ#bC;xlzpxTipj96noIsJ{;1!&H-g8y=%f6=M8rfog_{U0BiRy_|(K~D?* zV@F*Rx1oDM(~l27_uXG^`3?&=QP}&C;P8yPXaAO@t><6*#M7y7_lZU$7%TX%rDt`1 z|LLbLzA-a-Z>Nk2%W+>_^1mrQ@X$ZLertZs>T`Xs_Pra=O$z=o&z*kMSD#&(e$~x) zt$wKC=3Gqjv3DZDG2ph}zMk@E*3OnCv-*E|?T=_jm4dHjb$9(nswTVwv zVc)di7hbZb$IiRoOPKNIz^7*v_`#3H-iZW9zt3*pv%01KsLvWEfAGs6ldy0&LGUM@ zG3T3Gj^Dhl=j@(ad#(L)rKWN3Y=Yz7*)g4FNB`7q>^Z0Xt7%H%)sPcU{_*>2f1g@0 zfBAg(B{995zpcbtxZpd#J!<#MTd(P|rt`(!mXEs+wzgXEFTJ?S{##yovN_s0S9|C0 zmwbo&@q+*BwDuFu+i}#XvAv!-`mq+@w^+x*eXs<_rlN5x%S+mC`Cxt7j=0p+MDd)c z)*JSvl@6VWjcs#rA2_KTZ>OqF>Qz5@VDFiDJC}Nk)nadLU2#QHt*@@kTa}cW+An41 z;?kMk%F>FuGS5t0dU~t+%{yE%o_SJ6*<$g&t`hmaE=l^P^&6blw>9c|UJu#o_jvcryZ~mPa5@zOo8$$&u8* z4_7&5)*kq9%w24fR{d97YO!?_k)wq*k4IAW!Sy3Sc87IGxkg%tHPW_MOppv^yHzE8 z^`2O4K14xAW)9!du-bjNMju%IKFq00J?1VLHx4&HrAJ1LlydkQUW$9>M_`<g0zqJky0y#onM4-8+Kx3;?2SIXI^!ISM* zmbmT0jX6!AgEOYb^NUNXO1#CD9xkx7U2st6f@x`uw?4f-{ZQkJ#d$0V`#gszVUck& z^Uwv9Ey2ROjD9$S6K)fwmR2oXi2JI^g(*qNo|5XM;UM1XB%b$A>XS5EFu*56p47^d z!3Z6ml$4y7uE2do_#sOQiddM++|&nhlWNXQJyJ|H=O#5t=0=o2{4uLW-Ujwhl9>ai zzsT*t!HV-IrkXZjpf%aFfhm7}y6I_pB1Uo3QS8I49z&Ubs^()b}0aDXLwx>fXfzi4AiTNFH5>29`rIy;Lct;HvTf8=0M)49&z$msLLHfD9T;+rmxVjk6uvJECT8yv>PponoW3TE{phW zpH1`qSczB<+5u)0(8t6_yG2oRB-XOgnF@=dW;T%eZLkQjd3W93-C(RMZIIX|0^uuXgfhjVsJS2LIH9eyC~95@I#y_J zS`;|)ZDHcV|ETB&bZJtF@a{~~*(1zceEsB~1(5Ho#vM6fq1u7TX{T4;d zw}Fln+IKCAnx6n2CA6Pe6gAHQ9WAsMEQ*@VKs?Q<$ZWAFYW@g>ugF3BlSQZjC5|s; z7Ddgop0>f$hGYAH@^6GiQ8UfcW_a3-*b}i)N_C?}MP`#lQ8NM?Q)pXc&axQC8q1|Os)I0!mg3unaC~BSnI$mh2EQ*@vv2}=CD>5%y1U-pu zDM~xXqNusg)3^(fwo&u8r@iZGM`N8|{T^pg)Li0e<2`MWr`_mj-}1D_J#Dk6ZSk}& zPwV!yJFs8iB`N(a7C~=V6gBa3oMt6CKi{ILxfJMhp-r$TYNi66A+)P4ike2CGljO$ zqNrI6be7OsEsC0DKxYf>9*d&pK_Hy60Pa3wQPg}N=yO7Q(xRw&8mLle>nuWB3p7$_ z?G{DN{{W2=+N%~t&7Xlr3+=BKMa_FaV}$l^i=w9RNMqtcE4CtVK~X9_Rw0U2aj-Tm^KY(571yHP-@NB(wz*fCoAMdq^>Ma>jXo91ah^|YUR+FPFX7f(C% zSQp+WEJ8cuX`?)Cwx>0C+I^n(4NqI`X=^;~{*!cP(*b6?MMb8|BD7Y6)fO$RMd&>M z;Vc)l_FF81j9U~nwI{1>k-5SmXb?|p^0YNTI0*)!L{3oz?QIcC5U5(Xd$~m@L7*C; zO}7Xo2sBP;3oJqj0*x2i5{poRK$i&ZZi`TYKo<+`VT({&r@FLEvk3Yb=(m#6F%^o6 z%vg(H>uI|^ZR`*^)dqRH$D$&0uSM|TX}dkGVkpihlsIm*s0fFsC@pGU1iDO8`fH1# zrUU45q5a;XsM!uQL1>Q+e30 zvk3hHW4r#tf5F??7Ddg)K=`H;v~d=p-wxN)&7p@@PMZ1NH>N%^`bXn_dg9wP zLpbQju~{H^cVK9BIrCNS4xGlT4Y5&b$dHOt8m8e!LOBY)`IeFM=hrtjm1kW|s6m9c zI*pQjQ2vg>(SECwZlT38k$kt7rk{e14rd&*p#1nF=S;@Bn>b6`UUC)IfbhZD2~qR^ zw{%n>&wM_re1FvO&6zx%-w%}^TRsY3lFAp4=Uz1Oyz!H9$}qk!y`=gh&VSzYj6S#O z|8?oP_>yr|A2EMEYWZ;SnLgu_TU)vcTefw#tdG+Aa=A@qs%3UDNNHDam+OOIt;?I7$<%x)!giMwB%|M<9#WHNao`jW@)k z-*7CPeXH$y{#Fif48ncBnZq9g-_I}Rz>l#%e=CQ3ePDb0h2=|^a-7FB-O2$KpXB_~ zP;3V!3X_*b64jC9#f6Enz{QE`;%iJQ-p(v)8a4)vRMjeZO;xqmBrhBwxMR{|@066r zA1gVvKVxb9;x&C!wadok4gjodR)(~!FH9CDs@jv)kwoq0$?D=n?bd7hq*{4! zPo6Z;*DCR~T70b$Ur)W&j>wS^Nkqx1@y8nHA|b6jw4;ZB@cT|rnq*~hBK{OOSCd-7Lx{#XhUQ^~<8iff2hc8DN9vUQ zduf#^Znkho4`gsiQz_FV;kT?W)(nvZn{L#Nv`s5tkz1a6irfwqFUk2ak*~D;9+oIg zUK~k`jU+ECOjH*pFD_1uEq2bWcg;;I#SmT2G`tVsfVoU3!{)NKtK=uQvR1UVH683E z<(-nU){TgIM`@UXynrN@aI}~cc&O>%#`~yY~(aqz+rOMVS7pCPsg0!qX6K_51zryNl-B;DM0V*x1`)a#do~clYnL!(?5c^a0sRjrs zqs%hnTUzx|&8h06np4$BC8(;8wyOGSyKWyHTPlT&&^Ii0s?XILSB+A&tH!C8D^)cN zaZk=K4y7oM_?B9cwYo4^CHKiHXO$dZ8rGmtoy(MQteaKKYLakcHKn9T$nB`B4Jb$0 zRKrMnNbxnTc9w}3HfE_5We~MEQ{i_DGt!kPCo_-?%ZyY70&$p8S^R+=gp#qRy3AAJ zGV3xa2!wT+a3AY(De7_oUVZjXf3|cDrt-XL{aOymKO)U}VR21JSB)=5DP**I znHrSZQZ*>GrD{;>Qq`ceRi0OM-9El_>2m2j#=AB&I}Mr{9d%v}I+w`{Y}0S6WmswC z>|mn#EcuCaPg`GT$|$}~nZ>sWF|hbHq4;jiY<~mA=bPK&bjeZnd)@wVv6tQday0I1 zcV-u2BHk4o0c=mkwr5WEXZ+@s2A38El;h z&IR8mgx)X3dn!d&Xn<&m)`_%gAJ-icmn8CMjQ{1=Q%eqI^y*~YYc4tC)=2W&OzMvQ zwD-;ThStG&Wv+LWBv%l(Jkuwk;Ay`0D@pN~@T9n#)iwppPF>okV%#-TBwCC|60H{@ zQC1taJk1wVvScfQ4Dh_BW8feuCoO_%l)bA3V#U(2{nuoQ@veI+pg|gKSYG7R5Sjo1f`~UxPlNRNy}=CwNjM;&`UwFcJW#k7pGRxHB{Ahp@dSG zYAt72-myf+5OX?SVHlKi%)uTna3XgC^~xn6Umz)7G2w;iXH&q2S+B6XQ+JfgC_N}1 zW0W!M>9#!07t_=vkJ@!I`Tbto0P-*xYt~983HsFp2%7G*wmJ?fAN$J@B zhqsZyj(fQyqsQSbx&p&q(g0+f`>f74_pV<|on1ke;c13wP@D6a62KIDN2mBW%yMv; z*>RXX<&j1{h328GdP}pv1bT?^up$lZZOv&bo^LbTUBYayQI;ZuYt13IyIu27 ztSq)>YukbnM=SYBd+RGr0}*nvuw`8z1coLWFJmJuZ^_#Q5zKf7`m_=48SQO)50Uh8 z)T8MIFzh1R;5Ow7kG)8A>&{8m?oM9dR0{KGn>ER!qtlI}#|wR)cbt{qRUU5D7NXK9 z$8u&pXL*$(Ms}nvr)vj5O>pQ^3T=SybRb2UVY(qg?)jC)T@#^PWkTgq2<+Ogf@`5+ zK_b38QMD@>-<1}aPbGKGz)gNSdHlZ2ETKno=1viUP08_v$x#Cm@$O{RF4YX^@U6rQ zL9q%+d{=*V602=zFL`09&{I__)xI<#(~a!MrG}#hayD|s2m z8o?;;<=3;Ek6B)r5mazm&IVQ5Lr_8I2+A=C%|Hc`Juamamy%6R`CM3-tU;D|t)`@; z7>PoG>AE9Q z*fH?Qup@SjLXIXr840`6k`IP7@yS9k1HtBukI8ZIWjYGP=Nw6VnXc0Dr5z!@>TrBy ze__exQjdfiv7~T@d|w)HFO_KB>s%3ulsfk!XXtJrP}afaIda`Y_+yp^8Q^MZt_YX~ zCTMw>VcR;S4ZV8UgPOu(9!A}IO6*a3+YZ%hvG z%#}7P`T3|`wC;$Mb`1Ps*b!td>}cW-QLdi-wp_CvLAo*>p*hJ_`i$F3mv=AKKaX@- z_aa^1Ll4sB+@txh<<{{4Zx>9zwd2h)wdvC=Gg_CN(n|V+e_uc52FrXY6;`@|Xc}M_ zkdVl7DC6W(POr7R)|dUoU9i2C+a!^<)>Ux5qZDNVVx{PBQW%w*Wv#q5(3j`mC=}>X zESKGlxEyRpC~Ouagc>q(5F)SXxV0Oig~^SY4#|fiW{eXa zaX4t^esG!nP-*UXU?XfZ?t7S+e3mJ zAN%CsBR9r^j|?$f>cb^-gIwTV8`xYQpTlCuJk3O(1^eQ8=-x*Nb_b^7J04gsC05!> z(`ucP+xkFjXl2B*P)t-;#{+F}fwd)Y5&ceGd*1Rr64lD(qaK_QHCS@0%*QMoM^;Jj z+G?>3=#3@Bi?l^j(-lN$C8tJ~FZ@I<8w$ko9a9-5196J7r%2XhM-o|%)RCSY38@kZ zV{aIk$uE_`EyZ6JkwhavxrQWWjh8VgU9~%7l#GRiV(J4tE74L_3PP7XfZ0WLV_NnT z9qtCt9cG`>VRrW%X1O?A9l#XO>^T0emtGY4#~iP`+#E@){hZ)2t0((^kd6IwOQvQ`eL zNT=!K`EU}{!IjoQSu4k4nQNP*xKyA|E-qNF3PDHLNH$eub+s|e)DB5Nmnf^tBp$&n z+N0;xOlOW!mvP6*yPM&fFm-|m|8(kuw0dC>G^||0UZJ% zk;~x5PflYu(TWBpgQNH+0*>Mr5pWcLBLJ9$n89tjvk6e2DB!t|Qgpivfm=JRFEGDFt4v@cQ_(!M|0f~_ER7#g*SxmfuWdjJ9 ziGcu`1~8>T;!cYdOL3KWLAZztzY9_}73p%|LH5PrvX~x%Zhb`ALdR1;%g{t{uX_aZqXn z#TTlRypwczg}lm9(pm3;Z=2zIfAP(QmB}}X7`4K_@Xczd@(;qd{l}~J{m3g9R*+Zh zN6NsZFS^A#(BlR4DEGi_f#GQX(j^<;+0xc0f&aEfRJg)Vrldw-mX6a~g|0^29;^{z z&!uV4Qj~k;Iju>gt?t)*&!~&(WcO4TF`vu+{1=FCvEVu$;05z;;KK5t+9ypif;xdZ47K1>o#D++Kr!J#Z=8yfwkfT< zGrZXeDW)^%Z7C+RXT8!7bNEbByj!MCOMwH-4^NxYsh`F~c%o? zm7c~-JHot<&u%zACdb8>=_oL5>KsXYnXc0Dr5$mWG9yvg%tCD+o;GC)St?5d?qymi z&$Ov^FVm)(5xo3b58=zSsZX_=NTY}FyezYzViIClo{25%UM99OBgj2%>fB>u3$iQ| zL7XocDf3H|UN|g0#i*}mgzPoqJh?Mlk$EG?a!GUWtg>0&o!`Y1xel&LIx z>5>;I6c07aTHEpN%TuOI(^IgVGG(;om;{G2nP$`})1}%#%giD}uv4a0m=Rr^o-$=V zbjp+&<1DGnsb)=?ZerkC9c0G0l>}5mnSGU6)GL~0%2dP&(*&3(wzbDHS!Rxrt>)mA zDO(OqJUS;j&58*}$xGF)4w+x=7fe5#w2O*=%=^7{|iAt<|CV-|kghwJoCnM705 zF}heAH%7|F&F-1XuEh4!w?dOTUrrq$qdMWq$!|jdR|hcD>fBtbSJYm6@jL|!9k@3A zfj>n8^4QW+S1uf_mi=jN@0ra_$0T+r;#eS^$mPtk zI46nt@5*>F_UVBl3!5nCz}`A1oSL4@{eV60?8}hxXPNeV^4$&|QohNfwZriekZ*pi zYsI)BEXELY%`C*$izsFiYn#VqRtdZI!J1(`#8>*6QFyRlwXzyz)s?^&t0_odx~d=u z?12VJg5=(KCL=@=J8X38c;GC!M4@!ZhaOu}eCP;*b_x05aR>IKduO+@^Tkc3y4BzX><`_YxSiVsc2tQ>YiP1P03q0w?-wJmODq#- z$FAjo2(yvgqWD*MoI%ECEz#{b_GjYm6>;}YUU$&#g@Ni5{Afq(Gx(FcLL=v*saP|? zonqlxF?hxsm4#=V6T`rOGh-!7mLiovk*4@tKLbo>?)AP4m=&t0+*wh+G~0nieAinm zGyV4w|B*fUC+8)tJEjIAkBDbnw%&8(9DAte4F2OX_B{SF`HxH5^SJAX??Mq|YOqfr ze>|A8z>EU=KB6u#Q-OW}TFlG`nlH3PKzE5dGIxa7raWz>r+pvjt77|6&>Uek92%MY&lR|Dv09JEQrTe-6Cifkf!QJAm#XdK$@y= zdGw@5KL^rOZSaWPQQB4@P0MzVc6!tg5~rz(0%@wsf&LpV3d~R-hFM_hfOzm~fte1p zO;WlPhzGP5n0tVD9BhGE2^10Z1Q7X9VAcTfnAZZc9_Ro;pMXyIn4nQWD!Y@3B;?71H+%FYAkD|!9zE#MV?dgZ)gHBZ^cx_}$A1H9 zKDvNZUj755@^W$^4!V-^9SWrKaw$-e(53+K6srO=8;D2e7MMjqtStp*2@sFTEsz6g zO9kBz8jr*+FmD1KB8XQps^km;Qmr=}NG0cVAeEf+fmCuX_Ov=rn-BCg;a{sqcLS;9 z{255|_8ySU8@`-*Q+!+jbf~1|Mj%bg*NDXSJ3yKi9(Ai}`2~=sh2P&O?Y}(jPe7WM z_dGfPA1G^DE(5aV3#6q#2S`i*CU5&4AWiccAWicpu#1U@;})2aK$_A9AZn2U)9le> zKpMvyAdTafK=(_IUh=lT_qN--?Ylrz#NEGv#sU?X197;9=J!ybDzW_}(2phFp+MC_ zs{_)sTd%@FQ1=5_q38eM%FF?18UtEK3Z4Ura+k=4A_HdxP#oZ-9(&iG>)-A%H7#O%F{(2C4toMT|nyhYe33_C%o;Cye&TuR@;|=?vY#;m$^79 zfHaP?Jh}u(%8sF-gY^V#_<~<&Br@H8prz{9el8h;}bv{M>&wj zG0fYZ;cZ8H+e?8ojwL`UyI%#;G(Y0e6F^%ezs~|`>Awi1Tl-RkZDpvNV=fk5qoj`p-lpaD|1;y|i*Cjq@7?s%Itk8_5$1>&*P(6&H4mKxd? zXrQ3`f!JRuFpmN8;OPRh8i>bD7nn96j;IRECLkUyU0}8V@j&SUvki#HNEevz#$1km z>QNhza$_SMj?~}^PG402GGM2^1nUm z|8b{Jhk0}}km|L2Jo=tTF950be$}I09u*A0MpTL8a3IxTR{_-ttrh4Cf>PeyL*Cur zz3n*|I!q9E7kac5NTu^mAeGLQp7w1|TjOcJ^tA0j8s342J2cFr2_D_#(IXyh^k^&4 zt0FnOJgpdqDJ$&+AdTZJPrJg?=6G7d(;o1&pLyC#p7suq=J%gKn%_ePy8hKMKst80 z$fNl{TF+BJD!UH?JuRGk+S|SZr1E?oE@99#&-UmpkACXWuYfd{fAX|{dD?&@Tqq|2 zsk=DPW{Gz^(0>V90i@~s!l!Yev(SD7q&^mx0#gh$OlSjuICoND1_7NW=x!ie_kmD>VEc0*TlaxfN4x=K>%K?*2f4am=Ft&A zT5C@LQjJ~#r2Ut3fK;Q$J#9RY_Lio3^b;U0x8DJA{8wQ945V76=oly22Lq{OAM0r+ zd)j$GSM{YPtoLXE(3L`K0lGxcT|n9^eaNHDKx4)BRgeDc(Yqd*W1YJqj}8OUKITy# zoeHFUxf)32>PtYHzDK?7lR)bC=N@hJw&pnJw;V|Qo(-fSf8L|(yzQ5PG{3+0v^TuF zV~%&BjP__ekos5xq&?cN0cjaM4#Zi9n0XF}SDnPn79iC$uL5a#eDVaRX)gEZZjU;E zRBs%1qC>|3X^pxRNJoLoJbE5THPTj~3nbpZdQ^6j3*};uCIM-9cK~U48$Bu<>_R!* zqqBiDRX2E)0Mbx)c-rwNJ9qUSJ?zmBfz-#JJ?%YD8+wZKI}%9U%>+`3Sn1LK@#xd1 zIv-;^y2hhBJzDM2?>u_nqeCiOY^MTgE=POX6i=J)Y0EtAQBQ00w9TIOwx>mgxH!%Q zQjSjm(!AZ`(YJuKcDDg(slEcF?M%0~J$9&TXKnz}G(YIka~}QKqyGRYPY)mFe4GNL zv5t^r0vXYK-$i11k&_LdCYM>_^c+oN-U z)V2ml+nMQ}_C+A&&@zv{=WU+@(s)1dSr^KQKuTK-r0vWjK%Wsk`52J4Gd%QL+nJ3( zJkr0wYzE@2T!HBX;#CXr{Z zFX#!N3k0nJx=_%1po;{x162u1oo>v1q8T3a=*K|Xg0*>c@EOKDB<@c3XgJXILOTcO zCP5c^bQ#b>p?!hwB(_;Vw+QWeAZn(A7da0Z8TQY#^10D}jD1wljb(mhk2PsYEOR;>7?M3jtLN zx*v!a4PYz;G)~ZJpz(r=&obth65hvwbaZmGM}vWQjDE~a0#ZJ=dfVk5-RIps>fP-G z(pKYNK-y|V&UPcigMjXokdFaUcY}e{-D%$4=e)Zsyt^sh-AwOpp?9|wNbB3zJ$e-A zT#4;@pi3p^zXDRObpq82tqbTfLA!u>ApvU2InXqME&x()%mrF2;VlAEzD)QW#-`H0 zx)NvRo-?B&=F$$2XDLG+nSLWCyQ+Xkj7gIr15^*Bb>+c7Mz*nrGpAnql%Na zug5-!VY-!J4K36*>?(p4(j2b3Gs3!HXAUQs(Os}U+ld@}HtU5cJV$FxVMTRPPF8bE z%7xFaoq}XxuOjW26v`P@$yOe76>`E&z(FTGMJnV3+aiN5ct}&)g=YzmXR^smUa%`G z!4V|qdm=^yfK-*U*uEg*b`;QCVvBx|bq8s)?nVPm5_e<0yK3*Q&bylqG+Eru^6ut) zcT2px1W=v0`?7cUU7)W>3V!X;+a4X#$Jw3)q^Up6qceb}N_d|G(tOBD>)6XKPu;X; z?ZF7gZYaQcKilzU>`u=b*{(WBNLbkpo*Gzk+cpH|+$Xz#Ne-_2lcxkXm!5+ygppFX z<$9()Xj47B{3jPeU~j27=SS*1vvtBoc&fsBdwe%G5crhftSW5Q!0A0g3GAuv&*a04 z#23s9!t)!zksfUPtl}zqe0w^Cb#ht;k8TWmcl)n{9=D}E%5LlUHu1;hc`Uw51pHVa zt{a9Vf4Vt0-bshpD66~4Qg{bD9y`e3F)oZvddV43rLCGaO{GUGH#dPdLtAp<#t!fJ5kCzvr4(!F)EmP zx0Roah65?dP3cVN!4Yz9Xh;y;{^+2`jcJdTkrX<546sf1J$vcOEWOZfdri)I2{n-D z`1)Y!wWTAqscp+udaNOVRD`%Ka`03-B%A!FBqT~A_AUv7#NnEBiX=DjHFQ@v8QTHI zrgvmK%ckxM(KQ$unK6RUTQ$EB9deD?@HHj#Gg&j*%X5aIdsRk2rm< z`QXkcwOtRS@%}fEhS%+Fx!|ZYPBcDh&yJef#1b%5Pt3%2;x}06kEbVDEp7&W>>mp`%wtaoMX-_v({qJ&&Pqd)#OPw z4)XN5s;PQ*-Q4=|4RurNhn#g)(`EHjo8~nRI|rSggG(8QdkP&e<>;3mWXj4&xviAf z8qSq>rlwWi8{{3(zF%t&HT`^Q-azU`YG@2*7dkAJcsc_i zU<)34?erVf!Ui+F$%Kiqo(p?f?=+s%>VNJn2VQIS}rkT8X59WC={{?du%-t}b zhxu=qe}wrTm`5QA*n-^rd6+o#uek+gUzl5A_JesWlGh(5lX(D4w(o^7pMd!>m|ZZV zFpoi57s2F^??9N`!f_DHZ7@q(=PI~(7s=`Z+<5h_f-X6M@Dq-nbVY`3UxD;d#}WK3mNW9L+)cC_XFVm`H{Fu z0bAJKnDp$SNW500K|s2?fe8b%4$LSpV}RBOx)ey~FsA{jk0y`6v8<|+1dVj}+;^a^ z(2&Neay@=yLRE!+4#MwC_}xf3kq1>}r%0$-V@Gil!OZvq;&56N+bf+NojOyHG^^8q9tOm#)|=wiUCp7JOzhJYqJQK z;^n+1XK~jZa3RNdG$A=_kEVNWW5m5UJneEcO9r2im+_p0ng~CDuaU!{N3w`p)|GCD z2TDiFI^A+Bup&*ZbP$`dJ8`6pdZ@o|23!6$av7i1aDin&uw7l*7v)c=4CoXe^aIc){tCOo(z~ z%johgqmP$7mUB~X%eu;r2W|wvCDB`22_gC&6RKf}dN#7!Zu!3M@Z`>GhR-06v$kTw zgFh5~kZ1#)V4n)dispJmu~r(#9XgfxRUn-bcowJ*f)g{p^|r5h+ZbeTve{ZxO5C`GM=NFLm(*iA69qi8yRZIH8JfYbP z^X@~$8~&kMUQjo6-c>W}=EmnXHD1qpnL&_>$++B8=m08aKU0Qwgcb8PbdV0ysu{D5 z+nK1KF>~F##@W+`jsz+zqcRRsN1=5pD`P{)hA_tOGA1|7!$xG1S$#9eLlHq)8Hb`u z_NUZh-KeY#iow!n&czLTGwaTuyKtlgR1TY~B>Xvb^Kp3u$n-$oX+UWYnxNyu9!5c* zonF=k#_@R$VFlC=+ZFea$89J{^5`N<#N2!HO~B|kHvbGJ=ER$M$ZZA8&%zu6^BR~# zVSWqdaF{Q{L|KX2;&vBpy@*t85#fevxKdimqNsV))7bk{cezzrOV^EZMZ=P{oK6WS zu|UHWzd!hLZ}8=wRQ!IZq&g@EERh1>MM;!;1rphS&C5igaqbB47m3F7N z;CXZ@63~{Z6U+1JL?~aVr5M!Gs%lBBQ+^eB;uFOPF9YBuz42d?*lSIeslz5MlZdy( zm*v-9@fl=fkJ>9{utH#UN2Nzq9&t|Pe9=JH0;wLm(IYm?O1sOWM}Snf{RT*NTc@XS zCPnqwxgK2yq#ErGk0^Vp(S87=8tunGs?mN4lwYH9^D)!t8tu=ZPjhNOqxFY>sPUQ2%&eG(>!N#-}6P;AKVkQyv}f5i5lXHm4yKabTWb z=*Gh~*yjxQZodfou+Y&Dd$(Yix$6-8lc#shXfQ74GqZooW;ETu4fk#tHwzj(_7&ww zTVUMlss%=*1xBR3Tcx$ZpVBf5M^p~4MS)sU-I%O8z9v~aXk0R0jy~2v;QYsc!&62v zJu`@VIHdrvXa_U`$%x5_d#RvW(DE0`WZ05XY@hjr3x#td;n6w$uuv|+?{tm}LorS}$5;_{usWuh+{f>$|+(Ag`?Ge7#;B zvv$j?Iwnu#RUMbx*BjI^^G(|u)G_5-UT?6S4hlsDe(qu3w?HWH=Xu83T#k2$e>3|b z_(`p90smDv zk{nr>z)<)6;=~2T;$YqDa8M|B)vW6@{V;fq;;zjLIXB2M=(9W4C*Fo#=WBMQ45xCtf;e*w%zFc-pn80K{_DZWd*Fc7IQ5Jk;KYg=SC zS+r+i2y207bLoH+5M2I(7y?^Y2!L4yF(0&WLC_Bi;%NLnyZ;M9`uSls%s9z(R1~j< zKWmwKt7j^aGLQT@)>sr~DnH~gv)b5;#?=xXeLDvB5fbW(kc!hJ-U0(hrD@8n zwthm22??daJ1I(qpYI~rLHN1nDgZ`BrNt*K@ZSUNtkCF@e#qyE_zev5xn@D#G~6vR zjSAM`Uh3EXMFO()>*P%RIyqCnPR`V?ldlU_jG$Izddrc?pjO13do%L@p>Dnc=1VYH z5$2+NR4Wo`nGr=zx3w)YJ1q*A8E+V=+Fep=O3HA@urNJh$lNf~DWIhD$0yA6#h`_m zPCraAdpjljo9PEx9kUaq&^RMwMlHxlrlCB<$XcU}yd37?u%7^vjGXEjNu-PktZk}qoI7*gT&oQ1TQAiCzgO9x>YyCya}U$ZuZx2!dz>wj z2JlI%Kamy*QB*3u(sseW(!xa|r+I8=JXysM!Gx7oikP%d`HSIXxMMN!$0uA2OF;`4 z1N}JVFzmx9hBB)l4np9QCpXQgYZ7J4ivC5XeqrOl-O-6DQ@tEx8$0K*fEH#9{g5%A!0%HZ24e!%zZ`M6hw+AGY?zg?dC05E7?CoJC@PCPirW@DbgObjyn(#E>E^QX^i zoI_pUUwWwuQV2;@f$Iq02|`v!IH-G>4vsGI=XLKWF#jyPkG6&IHCSpP5NRP0X@^&7 z=o`pp{47Zh+ZLA z%MvKWk55<++zDE^2TVUK0p|1z`@aN=14EIk4Bw~#I1@Hi)Irt~9Mi*+2&&q%Z3)~9 zx|RTumH<)Iw8NLuHd~Zc0#28t*NMWM7PZ1Yc1*fVIt9etY58S-C~SLDFuBGY^h1sh z!te9@pW`{l9E>x})xnml{4ig+N~ByR(msXK*r!lhrgGU2V~)V8K*aTdi%l&e)X8A7 z_g(zRF85pwKssfKPgv0J2knedzk`0r_B#Cj;5sav?zNjPsAw$grJA`Jq3nH+gXQx# zq+u+6?qS;aUVtAfBA*r%57P^^*?c6-+h7id`6Za=!dwdTN|;z;l&&GC?6nw)v>1t^ zW-DANt<$2c%Ap$pa3 zgq41ndiDUn9K%0(AgpqDSNg=RGtRg94K5*x$SLlvra$E`p5Bml)=k`tY3P4L;bW+)RDc2aR&T`ae; z&|v)GJs^!%h*;dpA|hoGQPi}-m(tc-By3B@iznqAlorAjA7`>!fsMkgw_)Cl-_Vdy z&@J6iODsz_9P=9L8|$!btbA_$b;1Bx=Xkge<`CN&FM$2z$?RU$%|%s#|V0abl8B zJ~p+$?z9k_=!Z$-Z$(;wJe#J~&#rH(?%DUMTQA8SemF{egi8ptaAAtHS$EvrVt zWGLL5rou#|EF#kB4yA3h?yN8sx}|4#5$&XB$(i%uD`pM`%CCh6z?KgRS)Q=K-3aQ~ z5GUz}Tr9z_rAIBacg%HjN91Eelg>`FNi4_DJ&c>e*9SirHJVA`+%ukYM9MiLU93`C z8~iB^!o_Q6w}TMS;2$059!bk!4kh;Ca4xLC8Z76y4^m~0NI6HOoKqS(r?kvgP}Wsu zwPE2!7gn%uI`7Jgth}sy4Gwf|XC0SrdRp6g`E|Fn!`?QZ}Cf^CpEE8Q~OkX^_EguK$cP_LjeX+TRT=IRm{g&}5B3T<&4~<&Xdh!C*_A1g0@fSHk4< z^Awm&UmZ*`bDC!+kusA=n=YlTx9+n0MthvlV*np?LJwmCw6vL9%!3npLqn|g^QwEx zY(J@*XEqP%Aj|lbr>YeqWf@VA?Ah13C<^fhor`KgqQlC7b3l{}&PDMkBYoKMOwUE_ zE&uj36GdfEX=9?nG%Q8_*nb#K0-kfNyq;&}bu3IOit}MItrx&#A@Jj2Ed(Mh1R_-e zN~01`T9y)6*BPPW&8uHoMOcma;}aeTHiH(HN%|p6*_S^j$Wp(TB3=K#FsYXcHjaR# z_wE!x6GERU3V`fnr@=jpKfJl&L9mNydI%=d^)O7b?@OM2M9MxQt@cV|wO3ju``k2$ zGVoclC_EH$?1Pm&VfJBp9lNVCtF&VuhAZap&~o}fBK?$wlgIMuv**<{m7my47W$bB z>AYsm!7*M)Sw`OrhgJxiCU`axDVvCNDq3kz!LQQxJDboVn)7;K(?5E{rm6Gh&hI_5 znh<2((PA!E;am}6)fJvqM9L~6?QAKn4f#$hvzSXH_mzD>uZ+|*q;-R``mPmU0}b5grfca^8D1yaAyd)jY+)bCbL zdjm-Qa#w$gq~J)P{G+rJU^@uDsF3(jOB@T68s%;LuEp=vkoeON-Fy<}__UIBszG%E z1I>OoC*ZcDv70()h~JJTuS0FODr+i$afTJ^_wij8)4}hxm==Dg#e6JBzO`K<(rQ4Y z^UF$GW8F!Ip{1*mUs1QoAi{q|trC~)c4Cit;{tq%Nm;}vm;M{*ur-|Vo9Bre)m_zg zsWaKZ&>g-~_U`mkHd*>{a<(<2!*|L)S?xU}U%oN6T;0@zyG<@xxRGKHg{WT*=S~(F z?vth80q1syFM_?hwjPp&PlJ_P-C=DM&^-K(w=$r6I5{{=>hUoiaey{MXk$FO3TUR# zW_xry&^1E4$D=2KG(5JMYWuQB|Kn}n1JXFS3tK~`CQ-x_3e@&|APsN4x1HfpqqkiK zq_N!xq<+_U#P5jIwi8Ih`?I%w-=mKqH)?wvkfvn_kovvEBQ|hqOTEpF5HXqk%C86c zg>WVE?DXKDFozQS#x|E8q#t(Zz6^7CK0U}l-Baj*3F<-aSGYE<2jw-d9%P(cwC{(Y zoQgdg%|Fv|CrqXV8cy^e56@9ONThm@NcEu7s0WoM-GSlMgPYc(5pZAFxGIE-YTQMu zdUQdT$U5k8s5`F~|G%m3daK6vpbfnq*n_&$==Q9h_NzABliC>`Qaf5n*}&=t?!$m; zAwDq<1a0*i4|JK(SV6QJVlK&CE;Pr>2^}YX1JCHFAr3>&jPD$M zaC5_9*e2~41}f;+K8!Q0Ft7$93gdN{Ov^T_Fm8rhRTxC7Fo;xPD2?T(G*KAExi9*V z@#)K*a&QLD_Nm3q&N#iIG{S4@A_uYiwA*bJc86=^a1Et*@+_x%weXTa`3vuEX4?K>$Z&>T zC|7v%fWx(te(0tZKY!bh>7nr8&OR)>;1;8W@z5;E1%~h;$Qy(pJO0(t0R3tP2On?D(sAjz z4^Qu1SssHF=?uqUpo^pg&-S!2o>uE=6FrR$otAVnQ2vr$3fsLcY5F0TZ@{l+-%DD{ zmKBv%Q`Bnil4gA2lK!GC>04kj9gA&Aqql8!Dv_2nk(RX5Skg+%_f2~>u7ta3)!G;w zx=-340ye{*OW^LVs$I#^#Vu_Wn4?;S`nqd7t*VpbQCs7?Kumv3?r(j=$s3cgeQ4NA z;uf>($v=MKnL=5M(u1opt8cFexdMo@Avo|E=w3lA%{K&5WrpXJn?b9_uMj^z-#-*z zOG3Fi^?E00;Z=@i&_>`l8^4+9GR(Qkp;JeU!95IFpYqmz;O!Z5dc$ETKAz;j!-T#r zy&;(|bsZ$`zK!8~vYZ{FW(2nsISjU&{|kl9G`4eG__4_c~X}d|JWlW^|Kb5u_ z?v;kx+|$i-oK|$(D7flTC?{Bc9l^zTP<0PgX9#S`2*>vDRQ@fn3$vYmxax2uev`ou zeR3}@^>!AYto92btjnxQi*mD>@rT(AF_V>$=`fkDt1X-F_iQFoHWTSeh|<=>z0y=^ z?sdO&VsHAL){*b9`>Fc)uFJ`?I>Ul;PoO$Ar)Oe6aK95*F-gDk z2$(AoSGn!JOz{OvqyI}7TEld|Q#ze?B0~C|?vP6KaA;Q=u-g?VKH5bC zcKJ##v)_3#5~rhIj(P1tZyxP!uQXVH*{rcN-o|e#em(U{|I?eIMHu!8julz7hq>Jf zz3GYKpfc&$;3fs>iJoGMl80=lDkRdPB*GCch*oKjS!5^G2iUcx@RAY_o0%4}7aSc@`9~OJsH-H+zn3&n~XWRqe)>TO=^>X`8p=iY~yuAHm z(8}@qCVr=u;h#KE>e$_qwdF!xEm%XjoyaIbiM6>&(Th!uPi za-g@SGTpfk=DZE=%JFl0y$v;qN`%$oZTyzt7p}teLpL|!cO~5Gle=Gb{0UOF<<3=x z89dD_M<1AqKV~~;VZF~Zg!^U~#5OZsQ(!V}bud|N**{giPo$+wq?>${w$Zu^@4j-g zcPJYi5I_|#(?tO?RC=UOx&_DRR-9pK>53qk&Pt^*=VT&U4{;UcvO}6mM^PKLo-L3S zCCL(Hj~hFGi0rTk`QsDrZZ8Hc{8bzMu)9s2e`K&&b7|%id%LyM?}l?bj{?(5dYEK2 z;&TtvK&^ZL%rTbu3lt;M^*qeeU~Yg(K}V4_GaoO&d<^EVU^4B{z*6kj`eG;2VkgpK zR~n05Y0`5WA;+_AT+8U(SQhoxm5A+&p|RhcTp%T*lfl0rn`iwU6&OT!l(&>qX=DgX z7;>Wv<>GSPo7QEOT`-qhvLi#COIa!xmoLAmK~~u%aXET19V8aR?W&JW0ffVL4FW+* z>g`1KtQXRWFJ|J4F_S%ET_^)~VLcR^EUAYwU>B1Du`#QDQGI7tx&mRkI^(#@DkfYl zE@Q&5QNbq6aUpJ(q(ZUD+IwaWs_d#$AU388tM7LCIxAg)Fl~CYTK2>+UygCRlpl%? zi}({ZN=z;XRd%sH5F69A(WR>^C37M>(bellSFa0QJ#7+D*}1GfBBQfc1*y}n8#m_6 zglNaiN+9j_z39Y$y43R1uB2_j@qq0$2<}`~FI97m< zsEz5d@!+NlmXRyBaO1%-V|dd#{ZMNz!SA(n4==~I%U-t}e#2$1mV^C)vG}=%@$|Z)9?O*J{Vh!P6E5&&NTg**q;oh*TW{Uj?tLNVaCY%9 z;tlcLG^CTqmcf*q(jQLEgMVK?=7vutcg|>Ll_DkkoJr|0i0gMsu0;2uEWRsMyUU;O ziF#j{QSXmJDEgi6aG+~23s`{9N!_83V}P_yvSHP;r|W^(%*9NDw~YY3i{Bvp+{4M? zLi}jQrwS!G0B?L}ja`mkxW>}Y0Q}hFJYi2Y_EhaQFb?;)xKO8hs2zUT|Ee6f+!>Gp8(9)SS0*oFa7>|*GGyFz7_!o_wTXu)D*h2GSRl$mp$S!R2zuoY>4*pQsPga}s3qW&8&nXW&($-sd;SRjxGPlHb_G#j=*zWk+2()14e0D@W2z*soel!AnMi7f3e=EnL zA*1=@6V{g0Otqoyr}RV3#JRZ?7f$2>^Rqrxo-%)G9S(3Wmk%&!&b=C7epBNDUU_hw zjI3O=E)X??RVm}6WnIAPM7~tkiIky4`+<4i6PA&APYC*Ona9hV_2KX{{ITQtytHL|pG3TL5e`O2cl`a@*qJ-GGmUuZS5=&-D%|luS6Y3} z@uDYBef3H8TZ(mHempjSk5f{m}jd{4PxE<|zy1&Wv)|)33r* zJ`@qW6z z!`hH0eJ}sy?2g9ln)t8B5QBlyA@T5ppvD@F}(q>wV_ z&OZ&Zs^Y;w+U9bGLD3~ZdNbgqK)Qf@B~bn{oDN&&)jiY|!CCa#uo!F3^(94j^g}lj z@OvPwE2d1les0~InN!PW&Yg*)*JsbXp}w&kU#FKJw@{SGaaxeU*bsnwP>^Iidr{?% z29t52eKhz(qodDqJ4g0MUp_=yK15NultgK(;6-U@3mvyhPK_5XJkY(d`C|tuUT7~6 z2wCCorNY47ORl0kdjNvgYc>w`=vW{v9=0rsMgnor65~m%JrqR^Z236pW>KIg<*O45 za&V|R(GT5>#qYPS9`ZPpkyGc*7i|oS91rV_>%>;V-mW*wz@s|gp5afyk9i$~A0ON; z)XX^Vhe^430493~-+)P>d=Mr@awSZr>misd^tdlBA}ubWs99-ki)7hDX&jJr#EZfB zO#Zu$=Oj6~qf+?FVNiY%KMJ;d3e}M2Fv!o%Xg5k&eS!w$x;J;<#o{YK`cjD?qT>-@C!2NtCm4yJcEdoK}0H8N_!N3m9_^4 zjr<50^qU}q#$Vgmv=;*9M2HepfuDOEgIEZIEO7}K#P@q(vS6@XS8C#D&oClo7?Cne zX=Iqv$gsd*634|*Fy6(_#RDh>Pr7@;oz5@9B7BTG)5K0Ef8Xq}-*nZ2nX{+4D@l6U z%gpR3kzeKbxrcFw&sV@)t?*}+=MRzche$v9Q(7DRD=m{hYqr7yOCmX$#Nka(Ov=?W zrynwi{JGsVfmHEXJ#+NSr{ZpS}=WjedBnv#J%L%a42&Bm87bvppY>w zd=CoQ^$;qi?*^Dm;}@-v{oXT?NSR0!mGh*P)(-bd3o&sxEIuqIey2xC+Ye0q2kPP; zm`KSBG7-1`2os;SOvEO7kwi}XY0sWWnMkBeR2rG6w0z5e72FTkzLu>}U=6{IL+!m% zoo*0Xtd~ydwEei`OVueh7up$}@cGGhxi4ap{DerJPV5*fwHO_F-eP0EiB!f+CD1ZK z?3(Hx$SZ*U1zG{mZm`!IHvwVk6SQWae+yzo32T|9piux_C2B!go`N^Nzl|R&-}q2l zPCuvMNAuxe*^irf^~`Cb=1s$WM^op`X;{!yZ!af1A1|}#*N>^6J8#a+xg3K?^rQa6Z>RJ-@mw0w-DagAk*`mKvDj+@uDb5=2p^B; zsT=Q14*Onw@GV#~^UHo3=QP+)8xNEHG>X9E;I7IPk;)WN)cgpx_0Ee_0eY10f6=Ub#hfNK|^6U4%}5{+wRG(j^TXF(V6Dve!r#uw({$ zU8h^}NZb20qKWHd-bx($wWPE=`&ERS$xg3mCKoW8P%t|);?wm|aTg56#u7|zC>VSV z#2uu%TH;r};)R$nEe%YV7Mi}`kq*yFf!+i!b1#M;4qFI-@4JqG{C+YZ@7KfbGa-4W zANB@52JBm;s7-%r=u`q+W z?FPsl(?dCAnmA6N9M&M$Du+ZWheX=SDy_}BbF!36l#+3th^?zqa`mxXBexws@lpLw z-G%RL^A%8L`RLKvs;!0~7)6yHT@IwBHw`F%>CJ^LIqbO1J`pEZ$Z2Y;ui_Uz_l$n% zhPv^e&SS;_m(%7o4HJFjZQ(Ti1Si^j;knPlrSK~J=i&0I-^Q?KA+L6S68lRP=}>V$ zX?Dr}1_N=X^(~l8?+!aKpX5uHNK2L|YB)8mG-_(4q3Lhw%Cjp8nj)}{DrJhI?uZQ8 zQYds?@I`3=T}a2s4|3>P!w=1OC*0w044%k-Q9lW983R^a)_ zzgA!(EoLIEz)EX_d!@05hqWoUD3zg@vuZSZMJP}c zaJ7A(z;xFZ=qxJIT^;dV8S6sNo(MYUYV;<$7m?Nip0eFTW#If51<*azhabla8Ag40 z3x44(_w++IT%b59UuC$up7+Ym)=^F{26(bhuqZNWgu6RA@L^f7hb3u70-46aHmsGX z08A5Sw$6b0FifWJ5nC}9`640GA|cY%A*HQ{d!=O#eXs)5e+pX3e4`)gTc*W5;c+$< zN<1XS^m7n?*zI5j9E^YRK#T)DU}Yh%=DnyTCDG zVA-g;`RJ?jp6_4;@ME8#)cI4yTt~j#xq`{~mLjVtc~mHUkS?j=4|ui^DO-qi0#IqI z;YDd58C&Z14_o~AFTG_;qh$*>y{O_NQnnB&Ta-q&C@qUE9k_5i&os>d_zIS1xQ;D? zeRyGuekd?3yqjGK%1nI5h1ZmsnRWBet>b!WF9oM|V4#MDn+nDoo=x~)Tfew#oJrxX zaW)k{_Z%ZqjuB~7p)@uXN(*s}C+_RVtQjlRa_{&`1oA;|@u2d*Af&jC1C30DiZO@f zS6rj(=VGn!lIc~r+P8Y%e5^jro7+p?W@@i6a~XeFc}=v;odlEVy3#WD+n%{Z%3LB< z`bt|5_eu*f7t8)_rTZ$5%?LGo^mtGlAIdZ70a*-k&TF=PVO^MWj6ck|I?Fli^b@h1 zYB~3q=Nyr8jz~GDG;&U9nVd^s4!9jIu%ca@iY*U2eadS^t+*)99aY)nB4~v%F+C;GV%35WB(8cH0 zT{YWHmR8N{eM^?P@h7Y^n1%}cf?Y*iJ1ruIqxYoCeW+#N?>qyElz~LLyH#l$5th=j z7}$T+2k2tojBw8n@h{lLUYTFt;^O)9^=A4pGwZItXdYG@_C?!fugv7?W)HHw|-tOzU6sGq`V{2>Z&wWSEXh1uKWY=t{LHm+o~Y%%JR4JY2IC0KX?ATMqD^Kd)mHm zFD!StcvozBccA4RcC3r4=SX$?dw)k0g zDB55ZGe-fvDTqogJk7&diJp|-7hxY>ho&DYKlHQBZF^FF7tOn_zVV`&b7t!NTQDwo zw@+}~m${}I7Cy!uR(iijyUO&u3X^I2BTTlln~`f3J|g8Uk&cg*)@I$wR8Mf-o?Xm} zd`$+q8_Y?#$+#Bw;h7owVJgY6tAafg-;q4y3^W#(G-8>pw>^}MF*3p>x61Kz593^l z90w(Df#uGFo;yU!9U_%HrLBQ~rG+H#L*>rY{luM&p)zvP8}3|Zxx*ov$_|lohe)}j zG;&92S={NU+~?s*uI4f*JGTUDTvi`#T>b32MRn|>?faNHySZfi;ZgIuR^{WcI_Wn4 z!)mmrJm-j%b4050m9`$?DJ_e0$;yHITI+J@svzf<1UZ+hqvq%LM)p$i_uN5a++kgH z2jq)dAO(}j`LdNatPNRtBT}vrsjgC58{8``2iM9!EUvZonrovzG_EbTT)WG1?QYAp zcF#2;F6bdWS(?RM4VT^HQOs>i=iFZnJ1Gkzt%5(v<32L{kji5 z>Gx3ei)AL~)J7a&8Pb~eY}cPO7jJzErIRP}K#&N)l$=_yaFjR=SlGBS(kU)Kwjthz zpv{g00NC6mtJ)G(PwlA86Isp>*0>PXAOP%*Sd*xIDj9z&5#OAQZ*FPp^R=}cYyIQB zL~Xke`lbn+l2x16y%tIHBw5uSe6QUM0Kw8jqZy0#!Pt&dBB+`8TqT) zoUE1nAb<%>F9Jx$L1A*TBhT{7yfX5%Ur^}ReWIPZ^uW$>R(4Vs_3x~4LYRUGRy%1H zS8hTod-K(mSpBxAkhQG8D6pj@Vp8WzuZRU5+>g~%Kc_)96zD-^Lt$MDsfd{|Kzcgs z6rjt6b_0-pNdR?jx3Av|#EqbO^vcg6Fa>5EXo`LZq@i>HX(%6uxGFjxNMqwc){5$Z z)CabuTH3cf?Ux?418FFI5WD(47)WVX1L-8(bspX4(GP%h^Zn0&H1#h5X`27w(cghI zlmg^S(Puq6&!hPswRp4@Xg2)E%$q>(0u`7YK-+}&9?%2L4f8iJ zArfY}AJ6XwZC z(`zti!h9X(H(_pr*$MMan8k=U0k_)iC(;fDQPeyRTgqUO`MyQ^T`470zbhrugM=vE zMY3;~D9UflCFCN5xg|kSbAhK_>}mIV+DcE`yG^RNM?@5UD&FZgdGT(Mnyc0Ea(hck5iAV{L z!`3Rn8d2#YgvqpW7|w3pa7#zqA=^$dXlecoXy8=yD3~|FtbvJ&EE35x3REJAR3eF@ z<{NND-WHjMEsC1&0g>}X=7$z(SC}PKB(;<%YIed_!`o$%-Rm;YZW+vR3lBeyxBCXs zcn1$eL;u%xPRru>W>Qy?s@?8R*FHOoknirG@2>E{84zQ=KO^XBd!C@SrK-03&$6pi zwcGrO!Y%6u2Acn3IqXuK#-U(MsMMVzQp}c|qJnq|GYDTYaFgtdF~Z zG`z0^sgFmz?J6J*@8>}3cN36?*8!wH{s@$RuI?|e<@^>E6(7zz9SxHr{Wg9q^6)iL z^g}nl$M4SIe5c>tiaDq8v+A!KfBl>}^-Ya4r)mo*EgmDwemGg@Hf3{{R^Z$=HeC-1 zX<-H0Dm^OR5{3u?md-`S$!?W_c$ns~_ywyAlyEci@imxrFzNV5XPh%u)_ONz^A?&oriEwZF)2H2llL>vF(Ty{k*=*N?J2ldT8LvAGtebJ zY0I93{sn@HnPU(@e!)H&wmq>n*TfF}Fgu^dZ)uRVxh8hT&zrrles3nBd!E=~+!grs z!*39NeEto6&GftvlWFQ_+1ugSOQh^2QoXFSHn>+>PwdU+?Kt?||{51jnkagVZQdWk4@}S12?|y~CognHp7`AiCZb^DC@?W4X z)0+j^ttd}Bl>24N5eWKtRYg?5GiYvM%E}T2W!@Kewb2o za9*jo;zN^~8CGhhd)5#sYlxIJN+WBOw%=K^C#mVqCpEq0%sxoXFe^3VJ!^=RHAKo9 zrI9sC%fTAG;yaJ3p;im3gYbf4E>%N6R5k2m9FkXPKEGdthH-^e4N6P2Fz1$33lk}4 zh?Fx*BWIMhzd4gjW`dk~JD<$-mN9#f8O9aXG^bgaxzuxpNI65KoKYG%qcm`)rK>d8 zCtG$J6oVcNf+BqaCy4KIv!d7+M!Vq2<2&6XDLxjYUGU`bZmZ+_q4~oXc6vpE);G@AZyJ1=!$bNB4qO5UPN!RtinLp^5;**24`y5C1Fq*_GA$cy zAMbi!&O}@D`WgpySqH?=5q&c;@`Q>9p;`fCIOF zNsss-m`p~AtrZ**sJ@r9-JT+3g~-8VBGV=aFd zAop7LiIl%Y%3r0Cze?K|{<38DAAe^fE#dD?gZzD?6b|Icmfv17H$!~Gnt*YIWw+4s z79WQTZ=;sC7kl0kDQ}6ix1qFE2v2F?ZA(}7myK>>6<;uN`qsT>e#-bsgu)VvnG=Do z6EqwszZ{0qlLZpY|{Zcf4P*nDz4cV6QhIXg|b9gG6L>=V?x{vhGp zt-hoai3;k9D)5)-m<*F?;ddFFeOQQmt1J^KzlpRRQySYbr76F2oHpw|#s6!^3$MQQ z`z`*w*})jQ&Vct^=gqqB^E1jQ^O)IZ*)e5N$1q2M&Np&YAP4J?0<8dhI$d#H;@w>d z#IrbKaujU-!n_vlf}9Q?GJ6Z`!%B&M*fF^Zzc+JMn*1f1R)E2h^oN!5K*BQ+EFXWQ zEGyCoA?ZKHKNdfRHCRdJL=+^`1Wq^eyVY?pnZ8SH0bc@MXaN&x0TV^#_D-dJ7w(nT zW>Jw@?`eCtc!#cFvM^EAnXHZ^YPTiF0&h=N7bj}F+_D~)@sg#9GCHV1YaE78Nc-ZD;u@Coj8AirhZoXL+#zx&TX1-Qi3t>fJRghL8IyBCP-s0G5n@Cy7x zu%)JQ1(jM?T}5a$YFa=GSoK{G(( zRAmfntnMQ+tdN?&fL35yfOO@Va{5=HJqq-{f+#FuiG3WjO8i(td=5s}>;%X!-M)?A z8vH6k{VMw5Ijl67rSIveUmHrh4%p{^~`89 zC_d0j;d3f^fjLDsBjTd$6ssF}bCJ=uRwk&}1A+bsO@JgGbly=NA9m+@Y7ygbG{xaf za|&b8Vf5^KZdYq>%h$@Goq4X*2`iPDq&OITS#e#l+SU*2k<`wjr=so}*)_eE_`k(IRXBq z@XvvN8T|9%V--{5mGGP3-vxgOeA?9I@ZW&H6#f_RuYmsx{43!n;ri&y8&80L6MX9M zX85eBpQ7YcO(msjDyc;7fFhyowAE$Zx4_PhE1@yFFJpF-1Hpp_- z1bzTkC^Z88_9M3`#>ZF`Z8JR2O>;QG z+{9sSchRbJHjwZ(Ap#l_=f_~a+XhfR41m5FEVms zh%YiSod@e`#wJx&Gg7L2NU4Q?iuWe)iWlpqFR-4)pPwSVP68@lb3L}^x^&%h)8ec|-W#z$A>4Z-#yFjE490OFbflbf_QI`t%C}v#7@Vp%6BxGY@5j(Os0vY! zyfj>J74lXfrgaz&X94v`MWK*0;Il0r2%mY$))k0Gs|tveDj-sc{Op*RbUS`%OsGVz zB+$GqhUcw77%cNk_2UxMJ_*hZ5yD3ztTVz={Cg;byCEzMVW}#NZycyr(_QP*WFhio zBrye@rM(hts-dQXie3NaAe8D!!$IerAp99T@2wZ((8h~#WIIj3)sEJUFRrX_?MAqL zAx4@}?wm)HX@m_lG|0|*?d{X~W+OcbT_C3^I&{7QvuGJQUxAObPZc;-pDs{fW}4sy z3f#>;T@dZQv%#|+^Ue0yIS@vxD)s$u@J~WGOrw!=BX7c|e$duRyUcb%nH4EzR-_WG zzUYJ%kHZ7SbDNO8o&pUotY}@Ebw`GTg>?kNY9D32yFoZfQO?Yj>N|od!opG&d~t#W z?!BWa0*`#CL!8$T9tPLj7BCJCfgRQ1PD6+;R;i8bmK|_ihtCd*+;&jpwu2(K9Td%r z79Q)q?U>e7WUwuKHr#ZNpm3P}N8xvYzYKm)_>aM7AwCYDd3yprt+3J*A}Ljfq*Obg zcw00s)_S46C`88!*7y)hvOT^lV=o{LD$_EAlFzi$dCQbD2>m?cYsR5YIGOj0Z44Y= zn|YPpEK)Pi=B(PgEK)Omc9tR2#&c&GF2qworuQQFEW<_cS%w$GXBl1spLw|yKJ~zc zQdLA!stidb%4Wujw?X5)Wf;5muoa@FZH0L?{Sm^vdw?(wQ_ka$u3?P#Gd9q8{cKr- zSTm@)3ZMTeuBdA5>+ohDZ{ z;pRq2#N<@t@>CFx$tm^5f|`tKE=(F@PfXzr$#vnipRoP5KHK`q+PTw~=C9nuv!(fW zDnEQDCaYGCZZ2$ZrnVf_E_~I}@Kpo|IDl}xC-KewkQOK z`w4_LA{BO%{9Xs%$3!O%@xar!@R4y&K^*$Mqup%njOv;?d<-n7rj$F?$_*<;+m7v# za=Sgr?Rm}2b80Wl=Z>nFL{uyFX%Cu_fhNtln|i67+pm)yVwK5C{%c`4*@$$ARl|=) zB`4o#7`3iDXAWg2;(+T27!6L%v}oOWq|e*ygY@SlZ$9{dgP&xg}ae3EtrXE2yn}R2$3Z9gDYe4Z|)fUPB{eqvR3%*Jhe6=q4%T2+PQUy;+6};lH;1%!x z+k#j1*In?6=Pr1~`(G7&UJC`k;D1!(=jej3(FKq7pwiSYH3d&f6+9_b@QTNRS3Gy8 z8f}-=J%ghycQ722f(8GJ7qRMB%jOHrpAYB(s>B1|#VEJN|ZlCi&$Rqoj|Z0+6C$Ndh?H9FrFhQ(uXt_~a;&w- z5bY%<{3je~IBa(m2xo@8Dw~1u9*$m>@fe3mWq}{+R9STPZk|*;r(j^Ub85=` zSIe%f<;Os4X{}av-&%6CwXmB~)!oYg_P0?DWw&~qgE7eUuz}ER-9Vd7HBK2RZ7dY!s~cj7EBPz z2#>=YWhPXw|Np=hF|MmgTz zoAO~huJ)K~h}wgPc3EqUl+qe0^xWRPDgg(bSAA9BdB5n*I8@)sI95cB4-0szGIvXVlgzW~Y>0}fPF~NePWwB-*+!kD zlsZYNms=F?NyJyYJu$-mqQ!2I5nGFUYlKfnwOEdiQSX)#cgG010FFj@hS3@+r8QE@ z2o;Y;sCav#wE_PFt-T)AS}nd%{a@4C<63LzBz4s#rL;y$X-)B{HO2cKAqQY?tRs$2 zI1a^u8TXw4?6KcVKmrgX}PimFI)4VLB1IL$o3?>-~zxcby? z>K(~$C#H58kXlk#h%X})*K|ui@x(++U!pW?O4(ewgpwWO5|wg^S-8X$=NA+8RchVh zyYImT)YZ%8R~65yD6O4RY94^Ar`EWt{h{)3Rb9<|ec@R}Ic50dL+Tlh%&DtGmAmEe zq(?u?`wMD8Tj^bv2}K)tOej{~enQb26xA6N=l~BK3Q}(g&QW3gdD5mTap_sByh4QVg9#UCdTqg^if$=$B z9uLHjB`W43p=?n1fjQ%`Qq#S}Av;@w?{^__WpR{ti7Q0di-pA+*=z#sw!&_kvIVLB zRDzgycY-J(2!Dl0CH`t7pOTP)aXJH|O3uOeYyuN+r-X^W))n8n!F>wA?p&TpupNcp zCeo>o;{1=1Cxqq;wbGNmkb?%gt1tHaiNz; zx?K0NNJ;(lv_dkO^SDr5iDgZ*3tX@oGnOY*Z(OKS_|CuXT;i%3)NEXcTBUpbhP%cn zivJ9w6O2#?>odjaUK16>l`V0h^K_I&-_7K6Hn_CHp&32;W%M8|7|R)p1E&3qZ&KEK6Sj=NI*7fQ8W7!9_NVimZ(!#cpH1|yJ*JClb zD$UGA&&*zZ_!@(g(>uMYI^-qH%G0(nejJKK#(6;&iWzG}P%7 z9soZsbYhNWT?47#K6At>6(E?j202L-%pjzL)<0p)-$pwyij+H#xX_Wf#wpNGayao27g~>h=7;V;pB!3NT<9~T znX?mbmkdJjd(*?FCN8uC7+#C+V4obujtgPaT|9rswzuof8RnPMK`?hZ&k;U3oOF!~9ZMl_g$swEDth(9yYRTsHvHS^Im#!8twmgj+NQhx?_Z+m zymC?z;x4aad~&)7hWE;hU3_hq`}}gc3MR#ouP#10%u!tER4u3Q=w%=J<)jH_CI4~I z9qW^G9Jq0z6Y$UUygO&@V85K>1+y0awtkND$)SX}&?x*<&aVTW|Fd6CH^FSdzb)qk zpPUl~GXnpVb4$}Z&-mr=>0MmNDd$9=9L{>gg);e%quU7=pqrvZXZypJ$!&)x`{Yo= zaiQt>M{!v58#mtIm(yJ^X^!$b)hFjP!L)2Y>4I_U`81y#saYYGEOWE+#@p}rr$=%f zg5pfMXZYmwkZZA)F<l6|^%cx!{M)!bJ~^yeaiPxmXYABPPe0<9lO-5uf6>n;=k!*{>F<+s zx=+pk!Q6y@y0tUDL38iT7l(v#q4o~@8Q_yMP%tgGW7&e)j(=M}1ATIG1k-Z6kt>*$ z{Kr9;DBWv!K}rEpc@o%SRxKB>L zU~WfNx`N7@aVV<3H(w)ta`Jt0*fPh34n$Pe`2$~n<~_fh0-u~wJ~^WW^C%soZp*U(Q&;Y{0**pF*FUae|qpF&%!L|FvJvc)@JY z7uU>Y@M&2K9)81(9AvS8To z+HxlOD>RWNpWeVzO0H-0&13&v@OQ+;wc!c^tO zG+(;>@E84ZrU~YK{M-2|^2sR{%v1R1n7^P)k9K}JC4zD4r`RW_R4{hFK6vfX-~4jQ z1mnzCsZUNsFqh(=X`c4nFE9AzlnZ8?#=x^8J~`;Fpr6MW2>0Uh=bQX;W*{UkK|PC2zcIrW0+g@0;g!;N32`_nU5 zFwT6{N9Cl=rzy+ULUAElT3Z~UTRL3jm(zfdxX_#UXKv``Mdc`lH6MOlXf*yQr}67A zKKILEX}a5u`93-43Z^UmnXij)yW(!Yobv>;2LE^T|Q81wkrV{^jy-xW*RBo>vR5|2p6aMY;y3!}- zYQf0p4pdD_&)5BO{va6VIQ(j#9FBaTXZ+KBaBn9RvNt`~BE+rdYkYF96HF%xfeW6O zxE>*KA!og~&L`&v!L%&rMxUG;d~$fFqwc>zSgYT<2@R4rUpEWJspp$~a&8gK3HWF1 zhFeBK@m@K%3T6xb?ee$emS=z#N8g==96=WVC-?`+Xbhc=9hD) zPtF}aIke=celANsAfW%cTQE-j+~t#Vk6_py(v==I`ak~k+=~$Ryw*KFIrj<1w!_!| zp3vx*^GCrr^?aXC&iyVqeajbPXyz@i2Yhnw_sMxsFm}E+e{yj^J$*?343n!Pxdwk~I~Lx;I~s2*#P7Kl|iB9gcDjmb1(! z=TV=W$6RuTKHY?F%A20Y1>-EQ$9!_0aLHMFcMoLLE9XhUIQ8>{PtH>=IYmEz5zrp~ z#V6+}pPZ)!!w=-4LRcMt_$}F=o@WHZElUmtMfbE%&T??$LKoqm{owrzdVS)T^Q>U_ zPHa0+bjy8m{t9kf=wJ9x!ZG{8R5Y|+{j3lS<=A%kSD&2c1Y_Gz{LI5H_se-+FwXk^ zoKFsJOOT#Z@y}GeGwkIf{c=_c##vr3_~fh-Ow0A+MW38iJ~=N5<|zEr1<$vvMu>a7 z`jSu1%YtcH&MQ7SFZ<-Y>XP%|rsSS}{k-Or^Qun{%ol04(-SP`Z$3G%`{cYK7!;DY zN6vW}4V%|~-V_Y~ZToq{C+97}v@GXspPaXRa^4Zlo%rXqM)m(XD&DY-r4tyCzIti%MSeMKQR6}z@NetqJ)fKp1koyg~_~m>mnC%(^58uRN%AE5FpW!?%#L){wF8HqRKmBqx z2<8+=yZV_=&gX)82>)z*5BTn!Y`>f@1jF5f?DqL{pPVlR!+nJkK`k5m@5B6ZXn}E| zTY<6l{H0IMSAv;@f7;B2WYUhS9j9YW$l&VKM;J~`hDrVRhMoK*tv)$F3Wob8aP0e+7hZeJFK3%zwgZz4itb0BoS(qO zoSuYY#pA8Fq6zV)=ih>HJ|FzaC+BCuV2~kY+WnxFm3}#_q3-*^pM7$EX@#6$eR6*B z$-(UeuGMmScKGD{$0z4E!MuQf*5$DuUxJRvtDoNm-Ltp)<#6?td!FQApPb}Yq^E-~J;^>f z9a|wM#V4nu$U!F5ZpZNJtyIwm)^3n3j+`RCCSx-MQzUPG*et>DEe4yRFkGSU=BPIv zgqIvLlFJq7K+RF_l#q9@;;5DWWLO=ALux($v||}!U6?+*(By(`6W#fSLu;d(Z#bNt zq&wGeIOb5!)&@RJA?`GTDbbu$4d*<~nQ1uO>xiz}aGuhfD-8!9UKjU);cV8Nb%xVc zWe?*hJ3S|8&S!>`r#VfA!&ianUN#(T@h0wd!?{Cq-ZGr!niChYueC;V_BR}^Nu_HS zvN3$`fo`ag!?z#k@(hPNdeePxIQg3MSHrnLbG|Vg?r%lcY&dvxTwJN){Gd6b4d-AE zQ{bi=&MBHxWH`e#r_gYwYtB)IbCKo@G@QFM=Ox2gp*gP_&PST_hT;66IiZlPu|(at z>}NP#HRk}s!Jft9b{aWjH0NK2Q?EJ47*4b19AP;3YtC_o^MdAdF&wqo8$JkNI6E|^ z!f=jitJ1U7aQbV`dxkSvb3QVhd7AUF;oPD*vkd32nsc?`{6llzF`ONmQ*1b$^?>zQ z!|A0tIfgS{bMg&muI7v~oO?9qbHiDuIX@asQi95RJHyG-oWl%fn&xyeoQpK)P{X-h za|RgB^O|#q;e4w(VZ%u}KwbS?!|A6vPaDom&H2r6uF#yH4d-di`NeQHXwH8O=K$UU z!F^>oIhr%UaAs-FIK#O~bA}tvGn&)UaNg6LgAJ!6hjDPphBHcYdKpfU=JYX~S(mhoRbbz*P3KFXKK#ZhI5hTJZLy~YtH?K^O@${XE>d4*GYGa;f&Fo+YIMQ&AG;K zR%^~>hLdoxl4BW8AI&-4aK>v+55uYT#aiy;*!zDjG_g)hQrFsQI9F)SPlofp=3HVp z{K}MacDrhCh*fJaGaQ(T&{OECbZ2Eph2Nwx2bx&-IASUMD$RM$V7}6vn+&I22PO0| z!|9_rcNxx9&3V^wF3_B)o^SJUR`@vUHK(7E^B>JQz;OC^M0(JUM>z|?*?{&X%K0le z*{GRO&aaFGdyR6A#VzSH98pd+&XPJgIWH6A;w0lN=@2L8GH|B3IR7E%SSRK}gco3F z9lh3l;Ltr`^7V=4JY_hY4#m8>E7ovu*0?yAfwSRsr{pKVp?lcKS+6;(3}?U2kc|6; zXnMMXv&_Yr0Z#fEPR#A#(7j;fysA0(7|t)?T;+jKUB(r}h* zPKM!ps5x^C=V#5Kja7s;1lEGioV_!6rRITt%Q za`nfY9J$t`PEK#edcet%SBLm6%+m-F$r+iTI=eU-;G{V@BDoUW<#sH&dYzLaxoC89 zB-U(jF2fPcdxMiBu`V_o5Z3L`JO>zwRw`n3uWc}|MRh_>qO(tz+;RM=#3QXEMrKe! z7bDFaE~tDl^Ow6g>EL|t;xMQG=i*Qs|8Q}b#CKgBX8tw9!HM;)wicCUa?UscGbr#C zhbd&N0%_Uo6jJg;Cr8Tb9VbW1{S_xiY=dJmlhb|>V?FNVWH6@>x;V_~orc30i;=?P z;YZWF7M!sz&T&Ut@@cpzrU9IJE(|{~SncAZVB+csl$FVQ59WPFM@O1_Fz>USoJ?wd zc!~p)NlcE5LpfP44vnmbi$f){KQQ{qq!K&2I8hL=khdSJ3I5@HL zkkdcFkLu@QaGr2+UI6Dq7w1=SelZ-jBuw*FT^(ue$$Z`D%3%6X&M+5;u?D+1lzfJZ!@T!(ahUfWE)Gtt?oLi$=KUlWhj~BR z#bMq%xHwGnfi4cyoZ#Xx&2cUc)BHOUWpdh=Y2M-DFwMWZI1piNb8`AI&Hr+7nC7ot z9Hx1Li^DX3=;AQV?>jltwlvBpMcW}SZY_3lm@VsFCx_XxUUPDoE$am*2Uo#NpOYh) z^#dH*5IGy2946U1LPjY%JxsFI!O4;IBp6P2=~C3|org%DvJEkKn=HDSo$^>l%7Jdoc{Gz$?I=-9>M!!#;Rznu|p;x1n zHYSEm9p6>4h{3hY$Oi9cORQ7`gRmaCXYqH@6z1w!#Mt>#*GiRGOd(^PzyEQ$(OA=T zEMnZTx=1XxFl}%sXHyGwEMnZTx=Ji`_7ZDa#~pu-#=lm_BE}u-SXZp0Z|hkXjb+z0 zVi3!r4L&_o&r?8HD>C1Knb;}(Kwpa(_qC3bShhB9w;p;k8tZ!fR6fA+Pm(6NYd$Kn$SRbIpn zd-jVjqp=>)v4~NU-q0K+yL(MtXkVxLad*3 zEWwDx_Gz|cJ3Ys^IL=n|G$Yv?2O8J0h_SVyQ0cB%Pi=d$i+v@Gvve$C+_5rTv4%eK zNlr9Yo{mL~J65JE)__yX{}PQgNyj3_9jk{c*3rK&#Vwkx=L#K*7g z!;hk|=IdC*xMTHl#XA3}4X;FFHR)KyxMTHp#hUxnS4*R@Zql)camVW8igi`a`nl0q z59(ONxMTHo#hU+S)t{rWmg`u=xMTHm#aeuNBRX_jhp+2c#JFQ+xnfPded5W{SnG5w zV%)J#cf}gtd+M}ktZ#HIV%)L%ODv8v=zh6n89G`!g}>-n#JFP(a9!(xXZn5>jg@?y zl0}R=))^AZ?koR!Nb$|lSY321Vi0T4n6YUS2aThof#zBuJZ_kdB^YZe&WcLvMiy7) z7uU`tnO9X_QB_elU(N^4M?V-Czn(&J|5 zh6_|O?Jv8zWaWe>ngT^W3TH;<70#bED^gceQK~-p=z`~lVJuLYvHyEHp5lP-ip3_9r-4>t3}pE=X`wvYu2kVOntmO>J<>2&#j=aDYtBR~3E^%6Ck49SWI!jjvj}^ML58AMkws%tZBE z&~YtgnrS6<1(n5Bk;2)bsU*j;Sy0U&&6>PwXlY(?)ZJ4Am#|v`jML>?)>lA3JuSqtnPYQ+A(JOZ%Qt2)h zULW73RNvR|;f+Pg_nUmd?A#rh5m~63Y_ObZR8=zo$QEpuKxbFv1|v7iJx5)(ri4q;M(%o9k$jHdgP(!a^(Qdd` zT81{}OwMdgh_PRsbESy+ee$5eP; z74|i*C>|TBs;#b>P+e2Wfw&tTLwgXeBM-)ozay$~ZxkHWtDZp--r|fZXVMC)Yb)wh zQx|a2mSUQ02VXQAEZr_Li$1*`n=OxzR92VbJ~TL*>x$gDw7xE)Bj(|xvNkd}QdK>x zqN=#Ay2d9Wph3lj^Q(a!Qe3KH__pB9%L(U;liJq<*67`&w=jAmm=O>>&T&KNi_5#k z39Pnmp*%&i$L_?TcT@k}VAZ0uT8ebrCG{1RWp--`MR~4|+kA9=H2=VlEXRs~1P{bO zLf|w*C>6JaJ{hzvweHkN8)tPjW0t+vN3DrdkBQ+Jp zm6*B6tuHT+)Nl?XP*iSsn98Dt#{d=N4n|9k+c)IFmRzI8XakEdmJHGz`vNJhqVO&N zXwS6;kEobcfr$!x0)Zc~MT&fZ6D6}S+`{Vex~hn@A0AM&3CXP}t~ItD6E!AMS=>;} zioR>?pz0d#2CN!|V2KsADl5Lk=Z1?$Qsd>wXFwntOgnEQs(GIkEFM`ORxy1>%lm zj7h=j4Cpx!Q^4V2w9?vGUu~euY*{0#tHxK<)YVI0d$bSL#9J7nPyfoASW@jvd^wLuC}6T`jDF9S&>oYjor5TQy6Xb$IYJII-m$aGb__6eu)_SXoc!;i}@2N_!9}1rehNRM!KI7Zk(TgFtLEhULqA00hT|LC?bkwTlsl zPoLugMjSz)mPQ;HV)~=lLre}wfZ|5eRF#$2SC!(EFncX9 zEqxEu=WhO0XTIl&3y`+QDT^`E*z?2%3*6)Md0Q44$n1IQg2Z{#*4j~$FBPqfDA)5C zW^1EnzyS9!YUZ9tRn?NUr~;$Hy{<+kA$4rN_l3B~j6FzPKsDOqlm*M$qhtkFpgm4m zOmTaZxS;y8$4QGJ%$cxO)(dYES{rTPz@kCfMd?EaXAeI!CqFN5=+JESt*?Q-1`X^n zFjIX|Y+$DPq}aer_2sRB{W7yLIjExMW)BVz&C4G#Vz7x?%Bbo~VJ1pI)M2Btb4QIB zIe7TU=v7-0wNJoZOz&Jt5Q2Q&r4C{?b4O(74I4RVaDHBae+XozCekwN8A&(M0%yOhRIWI1>{L=~IUZ!6G)xs%+E%%pP%> z6@iLvkG#y1Ka9YlBRLtvp(d4A*45WW%0SgbaI-Ftzwl?D_vooO<~-7muGpNHd&0|m z^h)np&OSus^(gNxE_&VvpR_9H=un6E6#@3SzMQ#!&-9-C(#y+A?C?J262II&FHz@4 zUP-xIUP*a`*DEho$ux4yqjDN%&B|7h($i!4mR`G@#-&qg%CRQRIxQo;UwUfP;Tuz# z>6yKIrDsNYr10zrN=QxZlin+%rvyz)91;4Pb?H6Z$GrV_yndlqmpMPb#Z_G|;kXw| z-d!#+$+gWB!>&3JFZie8Lppg1$pzclR#L9s4r;98TJn*_{f66T%2&APr?|-F(ziK2 zT>47q5>Mjdam@GPlG3xiI4)8<--k;I#9a`Cb9{P=*L?yPz7V*~0-o{16PA@~6-<+@ zcl76{$WON#zD6q4ucbp`YVEWbRp7+gO2%1O@chfr_RW)L`LodCRrBYDS6pR z(6c9fPXWt?dfPQFE`~gAwR6aLTzdkg$Ck%ePzr!qsBy96y${?Sz|>BpwAk`SAnZP1 zwrU*BFDSoTC}Wak{e**#`U}c$Cio{{A@U?yjI5SG2gzgl<^ePOED&(9ZRM43fwC@f9#1oZGUz0SMmzJlFybx>)j7Bdi3N<=p{H=>;vz>xJNj!2CtyVwErR`!`^oy->-ErN6ES-VDq^jS3e_9^MnPx&rf^ z#>J9X3|#6$q!9<*{y2j2%U2{{1?IDh1Qyd?*dHY?!bd}K(8WsM8iZv7lXS7bV#@1) z;9QMS$l&y`y&4N#`Xw#PI~2hs8q<D7E2P_j>CmKbvGlhY!N&vBffW=kmOM1M)?i>Bci@83$NX*tW^=QMiz$!Y!O@p1 zjQt-ZZxaHS09S*ToakbuuM@)V)ffTdFGwEkWjSz7c;$~SmOPGM{;Dwo#9xp+*0=Y7 zd+ADriY1S)r~L%X@mDJx?J-E+V&MJ(ObI&(xC3#R@ucIv=S1)~0(0QCM5%m;JkNa! z`;URZbi7VrA}{E=m*cwE0n_D%C@$7@?*Zmbjbna;uKNu5zXS7^8^>v-TE=7PEZQ5uA7{`d}P%vD$mK2NQwm zd7Hpu%Hy!09GH(ZE>`=u9k`=zx2#TgD0##M<+liWISZI)?~LMt%I#L*th=za&fN+Z z%l^Jb@Y}#Vb&tZu%5Nj&y$4L;eJ#u5?cycCe5!G=%A*_P{Q%72_bYj^^4lN5(}1~E z<6@=Hg1l#edG>*p(>EN!n>9uugX1AtlhNXzoxK=7-;{DA{OxOO;#>}4YZm!TfvpxX~eko{GGf5>Cl zI0y$_TO2|1HiN$sm_I#ERBU-1zkI4O0>odCJZ`<)@d<2G^Q1z>N+0Eo)0kb!TLRq8 zPqi$s2ZG3apZe?Hf;yz3Br zZGV*4X{BX7goCand0SRui{e!Ri&-9&chHNLbq@}@ zmgIc{%m*(iTr7KL^7mg2-Qb{Wss8qS8FMDDC|oRgMA;=#>aOJ# zYs{|XT>#t=3Wkf7z9SLVpfLi(Ur_lHaxMO*ysl8OU|O3oxH+oJpT!b2i3rkE7$8q#UkIIzBMV-7KO5yHgN+3~<9W zme&)=8gI-hBbox<#->}=b}QJq1VZTj+mr(6Jtg{yaF^-+GN9jxGq-75we3!1V;~ z@V7CJ#X)x;3QR7Vcy0c-W0=FHQ&hLPLL$gVF`uR*$UK03Sfys2^ z^mCUe?f~HW0~6Lbb6wF(6i2;G0;awdxF%rk^Wr@DpuFY4e4ueH<>ND8zIWq%`C$F} z1(@G=f#Y=(P}$RP(8bCx%cCzaBfL0IKDq!m4VZ-**HS*3fw{$v^W~!x0><{1TO!sEju24n^x$JAHVRm_Tvs3@r^u9-g|e{fmR;Q3X> zvnomlM@s6aBgWwHkeqQN#*WC#&FVU0J=;v2(3lY4^l-g~~iK(MzBl8st@J2%FAiUmJ zf%U+^TR-7QBcUB1^=G3!U{g$Y+d+6_garz1K{H>E;}~o0C;0*yyr9^TM)lT}_g#W? zVVHLgGx+A*WT#ZmDopMJBP(?FL^4){sLt`?Kv#TOt4Dvaqx6Z618Q!1e>suE{Vf#t69mLckbMIh}A~uXMQ8i;Yf79^?iGqY$Yde!W9oZ8WRRq z-HeJ_>=2)v%w&x@jD=cLk|Uh<4ob93mfLEyw}T>V&x2^YMVW&Yq^MxbsEL!tPAUjnT{WPCrDe2$Ng-xX&iHV^g;KSg!z`?;EXWx&)^{a4 zDMwmJ-`KoCMFk^rMur_pu|*v1y-axIV3nIL`Xa{wkzX)s9QcxDhY%Z*Y88$eGB$VA z;7LBnA*d&H(4}(GO|_2j@bQ9Nbcd}Ytc2tbp>(dv8=J=$BL-FCeQSAH7S@oE9FMw@ zR#Y1lo>mlTsH-W?osXAmiZXhmVN6JVl(ICM4JY1oh^R%2eDfQxHe;jJgyaKZ{CK^( zxH7`Uf5@rUoLgO8sddy}(i>?gji7(3t||ij4C^qUueSx46qlh` zbU5m3Lh?8}$dk>=YIJUad8ML9*s+RoE9&M|)JBRV$qKKo`JoLl*JFCnnk6KkY6lff zs41R}C82dzD%j83Y^Ji9FJu>0MdlT$jlsk+M%f70)hKd_9b&F#9R)VOYavRJ2#!3R zfo;$ek|*22?rgYlOxfwdI9)=#{)09`(q0Mkl?xq1ujJ+88P&JH2&z`{Snu7K}A^CDtA}k)Zcj_2d2kT)H+5tJcZU$DSmdz@W*B`{V zAA_afmGFvLWre6x#WfZy^?JFUdHpb2MR-Xz6Sa67y@(5Tt>eIX(zF3m|A$pXFzPFv zF+Z9q$?e^Mr4_Z1+svL)&<`7Nrb%%~qIoYDNxN=W`lA0&NFI-z7ZuIQ$n0w!gwxa6 zepHrK%tc*E!Fi>qkjW}jEdoA>nUGwC605I@G|a|p;*l~_zoou>BPg_7n|ugD%i0 zR>vMGx(Lx%GH(;E`CYs8__8YQ=1?#@N5{D67Lh@ZfsT|BDx@_St!f>OcF1Mz- zxNJ76WTc?DqQ*KF0b&x~@{SrsCI;jQ$!+a+x(s`alt~3Il^(&~E2X$n-o=#nEAa(& zWeP>MEwDl0hbB}ViS{tMgCRZ}rjL?T6@^^`O-t1tsUtn529A(Co>`5GIwTS)E5ZAQ z(oFA1J5+LEdaRR^1?k)%Kn%7wEmRpO?Y9fAikJWD5Q(RUQcOj4NqxCgzO5KIibc$g zG!#Z=P)wqq5 zvi8&lyF}SY{wk)_LapwRA=Pd+Mr?D7i_rDfNe8OhH2*Fe{ry$t45?a|;zHO>LG5Ch z!#0#d0>C|0C-tOLGJ2mO*0#jmn-7-0Su&cAlwXKpx)G?VzBH^sB2}lgL5f@7OGR5n zs^Pg^sUf4UG=iV*3YVEKP4FUj(xVq+8~+7_cp6gc1n{LHwg*rgiUl>rw4r*_hReX~ zihz1oSY1ch_or#3P2RZ3bg9V>WCDdW&4ofD88n3CV4OLb9@Qsw!%$ z>uRcJSCkIH7>*6jkjmoewK9U@&4_RKmX+lZPiv^PX!5^Hv*ihP;FV;W{CKeh)8C1G zCcAlTb`3z)8Voy;KDNNp*2qZM+eWFLnoY%rs-vy0#Lj-)@C7sUsxA-78xa<3{ZNYB z^xO_><>2_IT~%N_YDq}WW8+XXt9MU4ut-RLS+y_zD&y^pq{h&)Zjn^ld+LO%>T2f8 zxR`gBj!}hlkzYA$gCn&Z63vy=N?x#;4bwBdsM!MNK>NM7a5oTpvlpk$3Z z3DFusORMx+a7}f?d@0AWpb)1OR8*p?8d_6bKf6{MDz?5wy7^@zeE`n&zzJ;*?>VHj zc()ntsYW7`b0f<3I7nLS&<*Z;t!+3O(E?(mZY70o>wNYfuRrAYO~1bUQt_pswj;4W zy70RcoqB!u@7|mH-Pv`&AM{jcF{WFEf5gJN{d(S0SC#SmTdTi5`6R5R*(CfP$9C+W zJniLntKXW_?%bz7eN*j9pA`DC!@&>U^vqS2XSKcl1 zZOOVcf_rw{uP22LyZq<-o}8T3e$HnHt$6d%FPGzW0pV9wp7i+Xof>ZLeNxBoZura2 zD=h0B;UDqbG2;%K_*(OgA8veZ#fPh~y!J@k*C&N;sd{()6Olz@0&5#k_eq9g&G## zvVGX5caGlvM7PD(nQceltFFSYjTElCI=SKakB~)s4PWa!R{Lrr>lLu#JUV6;6HS=D8-nw8? zFDZ2Uk*8%RmHd9_f!9=9S&fqq#dqL^|F;hg58wBHzkbxN=KRTrH(U(;KPLRbzFR(- zQ+Zowe)! zhCH}^P3rsSUa@>d#=9rS!`QzQ{u@089s1#lzg~7rZravEaz-x1at}O@OA5X5&*B}+ z{`So~=hR$!R^98TK7dz5gnz&bUHAL?^J{usd)xh&E?ab49+qqizt`QreKY>aL7P_2 zo7(fM8~%;@(jk#@tU;Z^lh3^1KLgr+{re3mf33#XbA>B!ha(!{qpkc9#(P3(%<&KssZVlgy*M8p;<$Z zh&*)QfXeOHjlcGoCGWk9$5z50b^Nq{-rnK0t4=ukg!j8G`RZcmtv&Hw;!j;N>$JBY zm{c&KYQv)|$6@)V@P}R3d-1W;OZMDBos61!kIYpPZJ#p!GRd_{8_*Y!kdHe0JKD#tNdAjxYzg+&kWnC@& z|4eK*a>2&^j!x+I-2P9ktosg+T7|!Q-0+LbOWLjZ=+3f@i5VFw>g#d2=ohWhtSPf= zsZ+J#dR|vW-e~|s%v`eVeDGDJJ@^GFfn^Cr4)}X-)Juo3-OC{Lw9D7%mU|6Oy*?M86_H5#m5_8+? z;MGOBsBR5f{NB{Oa?Tg-gQBRZn^#lS`rNu|2yX0W6*ugCB5-SsD%<)*>_HPyI(s%7 zsn!&zD~s5AkzY%|w;0rY=03>mJoPn)?iE#)txeLdGki{QX>~~j_Ppj$eeV-FOESFo za?n3iR+Q|$oJwvdshh9Xl;N%wrh1FrtLiSxz!a?71i2nlt15@BNtsKAwyx@ubI{kw zT=pIcGKtxHRbw)Jue)>e>|ig47Y(oP4FyvoPk;L zy2zeND2BZ^^k~@AJB2ys+b4UN00=0XhesVM`rZsG@hCn6JCV<-uCmg`rl+PwN@k}H zfLAd)mFGQEPfk5s7~qqkPHNRjUxW@wO-;+}p~0t0_#R7gMI4*K)HFm>li^HF1Fo3i zOif0rN{!?|{+Lvxt*4}|SKsv1fYj~Vi}darbd5dIWk%*c6P5Wt$azLa@1XSVTlMzs z8FY=^RIf6Jp8Gvj4bl{_C2JHh&4=}hBa*vf0w2@N)*mo$ zyuZv&{}EI>YcqJH5-on|@6W=^)l{Oj5)@;!vsP;=(Q1PkV->fprV_1FKyjwJot3Vs zMC)`=4+(FerV_0)K|L%yt}`Q*XiWn3C*e)iRH8Kl)C0n+)KsE157hm_J6BVQ)>zCs ztMpCO6nL27#iSw9GEq~BRwXFDaM8}1t*Jx{lX+IT)u~hV)QVqjFTH2b6Jwq}Y3t~W z_7D_s_vc)t>KPljPi2*A85hxFIxZt4z58rzAQrM3FT|WQ4!BTZ^ZG@b6BcdUvS@Yu zxaOJhO_gc!&705JIfJ2Pck#cVaN%aEa>D4P&#lB#$>o=W`OKSeKR!H35ItUQ3U4l0 z8s1iR4_uYJ?7_CPLtaSIWHQkoN*5}Sv`H=P;ZJS?H<%!KCb_D#9% zA$s8|u7+(c?A+X@Db$=B-;@*IoSV>;lh8b-ebean&BIgV;)tKWrnw-#Y25o1kiWLM zpncQ0_07XOo8V;<{GJN5=kna3#B3oYUbY+N<|dZ%-5AH714=`roQ<# zNlo*hqyk@_MlZc?+3!1dj#+xi7I-W|h1F4%R{+&7T9qy#N&=##t7x-TwDvKh&6bcK z4^BeaV#4|0<86a+I6 zg2{v6E%4l`I45*Y8(S@-`Q!=DpN>pxnP=lsUt#P!QBB7*zg4ib6C;cCiIbc2x0N;F z`2n7S6gB5>?(vrJo4=ac{N-6MrdU_e?CH1?8IL)|ajCIQbBVD{vqoiWj9HtkRvxQ0 z$!ZZZp0!J(-&Xd!>w*@fEf%R;Ry7*r6l`&G1Mc5T4g9+UE#hq)Ni29!I5IcBM(!A z>IiD4P;7DM2*t;!vxGVWRFzQdyk-bB-QcPWuHN7l8e9{o0XW)PH{t&{p&m5UyP(1% z?;oHp5b6t1-Ep+Fe!#zq(FQ$|qD}&(V)OuYp~N^HRF=dTZg6LTQc@OyQZX(E#RcOj z*0rEcmKgVfQj(tprBb>cl#1~csD%<^D=2C`#o7*vx@l|e2PKT!H3aDEJH?Dc} zXw*J-woUmvW`J*<6L(Hhb9hIAs%ZJ$MmLX38`B(4MWc5l=+2;1KqrB24>|$#4uuWx zKqr6tX1j*In1*$2*sw+}iNzllzc!sBs|%Dd;*q3vlkk{uJW$5^pQtMWNxsc1I|wg( zYu;A)zv4K<^HvAr5Hku#zhwN0!&@EZTWDN5V@|MkqC*m|;diNxZIJqQ$!wVVLXx~w zaUd88z&4^qX=uO#xOT~SbgEA0%PE^030)wkc*rTI^A(t-!qE8&Or6N70;lTJ1q#f3 zGjxFhce76y;H?tACh-Fp={Ri1yr&{Fuv(+DFhr!{d^r3O@NqOU#S@|R{jG_bYG+N+ zRHD@%Aq;J2Wos(Y+Le(kXRbLG$WM4yNQ@N5?Pv})wQ0_YZ_15t&Piy>m66t&?FGOA z$GC)Nh+Vb8iVN>(PHakOJ~O^)SbX!D2~ERfL{-pU0Pk*y3n$1G-u*l-e@AmtQ!+#FO7G@p9i1DFbM^% zjDeIg22zREYdW-@^`@qFZ4BO`cqyn2I1%Dv7eod^?Lq))c?+TzJa0iT4h!N~9DVkE zL5SK}<5F?hj@L{@LZK_PYs&FGA}VzPm`bUnlu}70T2JcGc5;uZcQ@zMij@m0ww7rU)G`}1I!oNXN|oVzOMvN_jqcc40t0jjOgAM!N|gYqL~9LVDc<{<@|v~j z(nR~4fWkebyNP+J1DGtm6fC$@y<7_4Mr%RinF!royJj3}JPpU>eXsFAyXG~$T0KQ; zmBUwM*QAtINh!Nlyk`(!@!WR(3^PA-C5AOSn#U!qYqRdikg(7P2&;XR_3j4YBtJyK4m{8 z4g(3j-kN5v$yOTq1(4z!L=?FP5k>AnM3L(1f55ee=@igo+IWu12&sthtVJjurWbuw zV;A_B!tV+HGWbK_FNS|M{3iI+14q587)hyOB$a5b*P-pK4Vv;*4pI9{L8|VADCFDD ztLkb5cva0fOgfGGlYOgdW8K{#+jhJj)rV#SMW-CQLZ)GXRu9LlNQ5>e=$2kb*yPFxJ4g53{l^ zh!N6COFkd%omeu}OJlm!Xp5B67Ac?M#MBJYd#jlnk&@CDG&4SiX1wp7c=h8AZ>5&j zd9}nFGi6hxl$J=fUQ6oMjyAjJ_Hz+p=eMAx8mE@LuilGlyv$bWgRiC=t5J>dHAW+( zltxJTG!owNDw2&p_^YWeVFkVQ20(44nt0oKtQu~y`ZOYZxF`FJ!|HP=j(aIy9IB7! zT^`B3hu6x?S7A=cWS;GLs=A2$^ZILX*M>})VPuVNh}dK(qameKL<)~9fL6TKni92f z?C5EJroNN_1Yd?v!Rr$(8Bb?~(%B6Vn{VDu@_Z|f^Ks;Pw8uEaaF}1+vhh^o6N-FI zDzz-ax2Z*Uh!x;?_kEBa494N=d>dC9b9LLB>WISYr{h5OjP_2@+PfM|r9Dzgd!&^1 z6pz|dJT&9~RqdUJD-CNwd-t?xdwZ`uuia5|Ub~yEHCJOaM@ngqRHC&4u@rBmro7cv zZrd@;v+vtwW+29myWH5X!XpVibs#eXElnNZp@*J1;KV?Ti32?_j2FZ8HW4==*)(V# zblx!vhEf<-4K-tJVi<=_#5Fj0FRq+>Udb+?0j+Ek%&bz3n|u}*$0@dB8d8yH=dkZw zOO0D#T8(&th84829R3CHuY!+z^k*REPB zQmSA`se)0w*EG&s-_U5S+7QpmfSaLUo5xthYDuMy2p{0FdB$PV*)5*oRH>OhjjHsl zsjW2nFa$|QXy5ABL3)L>?Nlcla@+CxsYoa`q1-R|4vfz&`X)y#;EdAWfgtu zNv%|&xsg;IqPJD&b=hnn_ohF@(;QJ#fl(7Fr6y8|G8LtGY~K~nUH$ign$Sw2BE(kH z&#h6DthH;kvg#l*=D;gRRl~KaMjKU;QmP`QIzYu+iTo%YRJCYxnygu93a@VpZ)gf{ zYzl9}s)eTTmZtEwrttQr@D4rv}yM8I24K2;zK6>f6ZDW>(w}9RZdK2i4pf`YCKc+c9L9&OYY0>Jm=p&(* zPC=eo9aFgRl2sy9uHoS^g;gxPiH27UYMSt>3=g;KI_|}Ww-l6$d$Zx)14_kRW_Zg% zsq4OCc<+Exan~E(SD;kf6kMH;L{h9S_>bLhorq92RBVvw*h(A^KOV1Um~Td0Vy@zr+Ck3oHVS9Hn)E@yp7KjUkz_po;+P_4kr~vZCWo1f%Wr2 zV$@O%e|z(|q%l$ZGyH8%>vLIIdxw=BhZHF*qrDA7dQ-T8m*x#Nym5v%#qerDg(XHK zsMw{w7@^dVv$XBIPnLEy4sU5Q4l$T!vPQ=$ZCfBP4#(2AC&ZqD&t(aNe<6IPW1%kTGUQp6G$~cmq|}s`;ynqx;sr13TC}+Ui@45Tww(8Yz70G0P#ai2?jVNd?Y98o}#} zqY_6&vBfRJ~CkA24&HKyKl;9rP`bskiVu2rOCy$DJv7jAy1Z z(`_N}8*y;d>8#D)gUvJ|4~B%KF7Jq_4!hXdP&=z`DZ;!}mvM->1jp|%6Xim7Lw%|Y-YC@X)MSP#N>f_`sG~m!*`=yPxw(V|@}! zr_GNCPmDiE%2Xh$Hdune-FgscyFEa36tYiJtWrK3Ro>Bl^Hx{2!S{oTU679=l*+L6 z{xd4dkyf<+&Ow;BAQ|UK9CzaQkG~*K_7$X~%AyUndt7OCqdl&i#_Vxe<&#Xytk z_!U0WvO^C%$C-j9r3#jm>Twm1J+9)#YKK$xSTuMbilsihKSx8%E?GUUC}1yalYAbx z2^XY2ixX)}kWQ8j z4?6E%F`MJlJ>y-*;SD^?^7Clz3%DyjskQTH=6=|oQsAPgTGd&~BB^1xmhE_bp0~x( zUo&4p*)UCS!{=SeJMd|}Yv3=0|9ALI?|blBhC@sll2T-fE50O>csGFf8?t zO5YDKbem^O*SVc{Rd&T&v^pW$AifxnEk*5Rjy<$!HKdK*IC5abs^lyl&YAF>)hVcW z7>AfXIKF7HcurHr!wdKwdpvvb+%AhJ-4UPHXYn|Dz_n02)ASX5rt53?EQX<`7)YsN zAf<{y@mLIs=bp^4waoj|4WT-$?%!b#J>vsrE;~TXH4vR5%ZsiSip3CH`MlepqMgd8 zjoHfQ0A;+VZZHlp9OTU52wEK4GVc?&tgLBjV-NKp1-ll2P&)%w*PI}YoPAweit?T1 z;(i`SgFF< zM0c*od20AEANf+sBc+r_N|ZMqcfX4^g_^=i4Tm>xL#w=VT*~R&HZheriOX-_l%MeJ z$7kybKlQ~VY-wg&7p)<-ow2>5v+L^NFd&Y9Y&&}zVS_xXVjPB_h+}xP&zz>Vnn_hJ zvtmCvJgBR{Ze)C7r;G}CpX@mfmhj|GhXVQ;wUSb5C6#D>rbF9VUusI(>AG-xymv5qT{r=rs5sh` zPL*XC0}y{#iw(L$CY{~Bv2SCeWb3sO^eG;_G7d3^;rP%l5YG4xnN?jTwGsgVjtaE< zu55%i$Qg6bv-#4KamK8l+qcgMC(rgD&8_pX`M+w zcJ4aWgE#^Rv62Sa|Q31TDB>=KCic_H{r? zzR0(ocQkx10)}{uk!fO&&*MI)G5R{KlKP6uGJ7Y?R`&4jUg`&2BNd13cx~^~|A#GQ zP<2K>q?CS0sfQnmw-WIc&potyhVOR7QWD2;Eh*`Ggcp01#5hzC^)tq9>)5P1R=0WA zXk}$#~sNt>D--kyzo*nrOj_KkTBAfBa zh*szoMxmsXLP;fB7~NWmw_a0TgL|eY0`^p)K|>{{LLY3=>h^&We@4AD58#58NGo(I zaRq8AmG~TdChvJ&Yv&myl2S?}l_+l~DBc?26;B??C5_kfAkl|#xc9Q}n4{BKJDTfd zMiO&glj09@O?P4S3hstgczcGo$DG)dRh$=7Q(o_Gh|YKg$eFp)aZ?>AW}EAJa`Wv^ zj=st&PQC@FX3J8UL*Ir6a9f-Y;4rtAbA-r7$-WSUI|M2N!{EggsL zcx`r8Z1IQ@3HB6eVGY#ws9p`6OWvV&ns9Nx@FzHkECt37}Nzp^<5!^r{d_4cl5~f5f{A zYMQtIH{j^yX=)jV81~=4+7VrA7RsvYdiV+tXzc}<5&FRFUu9X0Sif+b?x|DSO~bTH2BQksXbo}N--98^Vl z%JpTeQu6h2_7yM+XpGLzxM~sL82~naM@lQF183`D1hr$_4Wc@KQR zs&y}fnw4R^PomB44ZN_B%h$7qg}(i|x@+oyP|fmb|e&b`G*bal>}rttes;kEu{I(H$q z)#K&pHY38o^x(mltVBrjfec^tdPwa?fHs5Y(K+1Y@D}IEX6MN!=gCIr$p+`idgsYn z=gIrdlQrz%mvTdt{7vZWH-g>(dOhg1px+0*X7qBVZWI5IQasbx`3z~tZVHQ5r$NM^8(aG;r?M`(h>29R|NM{K3vf z%CXqeaRI4)&U{9zemYuret_^zlsR7r;z!f?Au;7DbOx1JHIibr>}vzyGcBnQNSUW- z{%}-7rVqVlV@HJJ0dphMIzd;@vqA4KPgH0{?W}BINntA^PmZ+b{5N8#qAD?me9`1)KsFZO;mB&gR8iAL9(@I!|(Udf63l0;mozZ4H6JTn=j{K zlp%9?sFsMNf?5VhTYSsL-XJ0P0js-lDO|KUeZtc7S1xDIr3`ifn*ByT#a z`)kgV)l0{{i8}ro>iBB2SCD$)qhOa+z6hNMwoQ2nZL)Q*2}c?Z+r1AW+dhHc2IGo6 z+kqT=(_4&fpq;p_P#y7s^Z#zhs1acQ4$-FTGWV9Q4y1XfQWJu2m%ra zk02-*@{~YGViKN;20==QSgeY+zTc0wN?UEU)fyD5wpt&xDlNA7YO!)HwA7}STYum0 zTC?Zu$2lPaz4!j{o6p&2)?Tw_&CHrL@5c@nUB-Jnp3QjXv&j+@>R-53ixl0cp`yiJ zmzvyG{dVXRrsy7vqRVfcsBw#~jh>cX83uWaFXO}hhqw5?>^QBA<14V)?fMmL#`jg& zR9aqbqs5ncp~aVw7T@~>$Kp#!i!Xg>@g=0iSN*d1s$Ujg=C>AKLb$OE|LT_&yZXHg zoZ}SVEpdylDkO`qLjL0W7?|$6_^#U7$bD)Xp6mxUrohgUSn#GX?o(S|)PX&^xp@O;xN2% zc)Wvx9_VE-4(J)mm_NnzI>sZ-niGUHCkW|qN^y_DpW*`2H1jf3V#|aneyJX5d}hgv zRup`*@F}mZ_hA9~(ht+dSs#AHN=;b4`y<}qfQw-TWg9WFJq$MEkY;2% z!OE79%9fC>A}VeZ=oJUq;+jXyq;z`rd~=(NJNxzN)|dY9@w@Nb@!6I!%a3W_GjAYR z&0|`>=*@qw(dvTu%ht;r)WV%s<1vltt|@X1%$l1)XJHD`aWG|!if<&KQ38zxq{U#e zrDJb~dqJ{r-pF-jW(E5ptWqO*TvLN8urIQew7cYE(obJJ6?py_HxujK?gJPris*WMd zRkW!)zzSnhG_Nh(__S(sqhPR2l@6aA)?T`2)w4-$_+POnx!3xYq%PXCd3!3xv0&Q1 zXz$k5sU4^(w%)q#!?=!H)RBE61h8`Rt{!Go>~h$%HDwcgGf_goddEadgD?cFMn0}X zdxF`iUO!sfdI+`xztnQr3q`viGUt;+0l>!Od}ljO{9MHZfM2g4UAK~yZ;*1QOSw}h zDVv>bYdi7s1QAg1tk{VB*@%o|m%@);o{ z#a(Ud?K$^dg^#i7x*ev~bW6$Un5eS6n^1N3lx_3Rz&kF%ceqlp2iequK=fQ802Y@G zHdO6TJ&24($(EgnbgIJqG1FHAI|nxIJ(L?%YGJcFnGbs=?0VQ_j$T9Sb+9jm{Rr$P z*ssEFhD}vyfz7IAG3?_YGhFH0%64cOY|3ysZ1yIu2CQuuAuWc4(wubsD=x!8vNX7A zXZ%$y>}88n-eP5`XwRw+Y(ZjKO6|3NHG(!}plFX2q%}7~Q&AMM5Lm$FMRge?E_;)U z_du^VSiKIE0I_lz1_f5$HIR*)gw;w`{~y;PpIp`VFHxOt1e3+hm(J@T zPIcY|lvt&)E3nJODrU{3K+{V<96r2-XPVVeze+7%=!KR!R!=~DP19_rqOGwq0kd6cuM@>?kb`L_m10cYP6+K%8C}-!Y6`jc| zj)uZ)elG=g0`QQKK)QzZ$=kk8z_TgX+lH(|Fj;ctV`BA~1-b|xH;Xtgc$9hH4Vxu6 zc+!V{NHZQ!X(s-}Ks`Kja(-oC2w~%`r6w5oGrrkKAk#RI9$|(bqMK*Wf_(2WSHgu+Sh|>#?Th3BeWJ$#wLE&Qqkg{fLzjdFy z+r?rfdy(Ek6zmy)7w*BHG5z$#GX~G$R=d5!8^7qiMJSdHUeVhDq$~OdPzT2=LX;ze zhKXN<{t6dw1~IPV@Gx9@rWuKXLMG?J&V@Y+Hq#O{1&B(k8AM1kh)|mI0;m-CO9Q3J z7YG!$%i_LV-8j%5dc|RZtto3gqgV7jH@}~X{^{0RGuSEqK0JXml3g2@OptMtRF>moc06Ev&-o??sp)%k`c)lC!mm9@|)3A~K)>VmzB z>?l*6a`_q?GO_ckX(E~V>Qv_2m#kBn7WNdqDzOb^lWg9F%{uk>u$k6Bm@?aHRf3SJ z1fet@VUT;Nd&+gqieoQN=`sxDmgDX=m)%qe4u$?Ns6_pjQi;+=TpD$-R6>~jCsbmG zQHhU@O8nWV#3x22Rw8S)mLQ}mK}c0XaUVlD6i1a%992SbQcDcrto1ujrh(F(wZ=f( zyFS$Eec9uEImoNi-pyu-)}k>0-hrq(WvjLfh>dKY<5p)~5oRT;%SvZih+{3qO|x`! zEsisk@fM<#-xF}14UuIz&jCtYtFb~JfX6kQSMly_L+3ZN%tJpMEIfs0w6`Ji^#<(< zvQ%K+Fj#}A@m65=5-2;Z!$!t63^N-ZQF5IegFF{1#dwT`&A4FRS9%I_kZx5mLaJhf z^xUZ8C?Ca%I%S9wd2cB3%-DH#rwgs}>H+fGoz(H|X?u?2YKEI7cU@@yu`N<4YN6SH zFii!z8bFEjuO6<*GHZf++v4RP{ji5M7tbZ${PXn!{rTq&1Ky1B=AUmTP-rQRVFr7A z-$QlJcsv5TKkP?g&xO4Sb~@}jq+j!qkme&H%}2#C9~BqueeXSlGhFB+B>2uv!i{KW zf+bbdRa1%-KY8B``wl!)0}Va>kcN%mg6`Go6Xo01(lo~^bvI0~@ffd|Z9Ct`)6VM` z^t73eTYMNlHs0Ri^CF51;ApZ+u zulq7$545ERBzA2|yDj!NjM#r|#Qvrc`;}JggjDQ=RP2hQ*cBJjb{t{f523T_Vd7l@ z1a*Bi+=7Eh`k~&Oj)!A*H5kYEtB=Y2c6Ys0{w{ZyR&B3V+sY%;qty+{fs*C;#M>M& z4y;bR`h1h4`g}8N#_e0MS&b~Pf+eJaC8UdwihI$}h4ncD6ZD+7k4%ky+dkGFmb;C|re3n7l`Szj#aLa*Pwz|m|8^p;!^3RcWKx=xAL=>81Ax=mouKh2CD}|eb zhbEYP{{Swy36y@AedTzf-t69H_|{s6>>LH zqf2mbu6pmrJ?~YBGxdUTrwQuCEx?@>Xu{}+dcnoPf7<5WKRwa%WwgSs+j+I3Ti3ix z?_nI`;Tpz`@2Pk=cSN(YhvwZ?u#d<4D%e9{uZGQ@^VP7KmNl>`2bL_&LqeK|gme>+ z;rMgk4U0K2g;BgJp#S=`Zmk~!b?9(xwkHKaxEV8*kNOOTun(X&fTtB=kF3`$} z=2O~4e*Ni8m8Ba(LbSbU_^oo<=@BhV&*Q`Ag5shWM;`|w}xc{k)AJ;|3FZ&cW;`Lyc*QZ}759HO!qFK)#yFzDM=zKt0BX9;yp@kM&0Z40;Yc0g-9K}5dh+DCDxSZ({cGP5 zTy1IhEhxKAYA0#3!P7O^RU(56q}Fz#@a=LD3l&4#QbH;gLTL__MRDIXP_Sf)ST=8W z{)1xqTU@bdJM^CrOMwv!%aw|Skcx$nibZi0i{j#Fi+-^p!Tli|J9uLsEMM`Ig?^|k zeevvxD;2Gzy?jAxjJH&Ett<>@93CXrD$8gi71l*66+$W%LMj!-Q7Ve_NCg))VaxEl z{c>0;xMdq6z3DCUy6}#HXhfIe^6>aFj6}gX;P^XQmGNr3w;!KFZ?U+Hn`l2=YBlcSM>!$=zqxd zU&U)eLpMs}P5`Mg@$r3uzO4WItpCUN%m4SR|0e}1XvY4Tmh90ZW{;VXH)Pnb*@cVh zFixLcA=c^ngNEmy-jqKqcgXDKrpnp6{DL{pd1u%I9E0YKIB`+-06oPq;FRp+&&jT6 znTD%h%9{q{o^lEoo4=fSTOvkb;r0y(i$$?TAhx-j<4^&P5Qrmqg;jm!TYqs$fQFk}Vn)9!F!+ zinEJq@FIrXw)=Pp`U62R*?+W-0K~YZAZp%eX@r<)e}u>(9zFI>ATp%iY5C*DK>|um z0w!0?udZx~8+kV-jQn4G{++-2UqSF?f@c(5L*|{rjdK2%kFUx(cvWZIxNTp%N15(*zPi{ApS} z8~=mlD;gD2zkazfW6Tft@e^YAPZLUFO(>JB38lwaLcu{yyoi5A*fZjNd;x_b9-H8d zMunR{%C2x2@>hMFgqVLCNk&&A$>_!+Ns4d#viKJJmiG1uBY)Rx{3r*Xf`T3WU9Xp- zfBg8ELckcrv_1p71KwM`PqeaOVdJ3Ms+vz@lALKoB3(FHx8W4s-x4D;G}DQpAd-{nVvYtH#Eq8*rVNsk zn0}g{-E`Mfh4@c58le%Wmw8jnpr#lj7LVj4*M|^G90?t#ud<%i!}0oJJ(ipV;d%^H zM&rhiG=5))0u%GKG563VDi8Wv&p#N_z*kH4(iVBw&Si4a4-v%zU>dH!gd{LRle1Ld z!|e+k;hhiz+eQW^f4+Lgcg1^yXlZ|<;51<4~}ZncpnkT*V5&*Y@X z`H!dYxn;w{d=3{H&V9Rl(nEYWmPk&@GkpGW@%=A``7qy-litL?%jbv?AJ$08NfYtU z)ZEhc>Jwo;oDN7%+J%3YPezE(kwTNte>?+Dz5)suln)m%{P8(5#D{HgauP>SNWQbI z^+T+h2l=pToSc;7kxy2L5BIAlCy|oo_BTF2`3dql3NFb>@8I7}SDz4{zCx3OfBNpY z`Su6Gd^iD+oV11icxd{D_;4Q);*9^qe6a2Un%DS`hvw)IANIHQ#fK9H$w^P~9}i8x z5FZZGl9L!B<-F~)>y8hnizPTYX*>R1`5YVKlPxrq64RBv>c@|S`G9qRPj-k;|8DR( zL1?z&-;GcI5Fbi7Iq6&Yr+H`I$EZjcGjBOP5%0-K=^p*b3Gq2eXeQ&IzCSnq8u5Y9A4yKEPV!uA0 z8sams8+=X|8n2uOhWHE;np2Q=me^sJ^}aM5pEHE!L;Sn)85H7^D>Q5Ij|4e`mL5Ah z%tvZDpC0Ch_(;u@)CwL9>$U&xK!p^P&tSMDCsE3=>G=EF&f2LU~zU|t(!+eT_=4Jf5dN?M;XROeag!vT1#jl4GLwqI)jmxL~C!_x!=EK@MIcYEc-E>U~@j>vQIT|vgR2H6o z)z`y(rU=bW51*0{pQ%DqZ)nPne*U5`A9O(i>6#kiGhJxv@K1B*z(2Nx`IN#XIcW#} z-E>V4@!?YBzWP5G2#q)2XN3676dJbgG&Q|%EegkH7F_)8*US)~3xy^Ra;6U5_R+mi zx}Y9HWZ<(FG=~GCxiH4Z^wnnro1DZJlW9L?Q^w^U8enMV;L(02`J8<5p??gA#c9#x zB+k>gVa*AJ#om4_tg~;NFv&v$H=4P4l9Qgme;S^7W!W!;!zve=Aqa~j1e&?AuoU4` zz)nsYfPYHmy7lc>h51wp&362|`Cbv?QzbOH{Kqq3eKHC`P|npt<1MFEAwD%ib1D8= z|NN;(EjoiiK9>khr=fv`vjB{lx80eCcZ{2mcJkSBM%Ei)KD9z~D`?zw%?t6FFEoGR zKc1}g`n6#`3xuZC!)Jbo4@*{Z5;c~o`R!R391-TTP-q62IO7Fh5Dcb^B|SN5B>(Xo zk+Bv{P*6S%LgVdk)Q9*q3Jq&cnkPS5^>COEb3w;Dlp#%Hh))x+$w?vsK;J4m?$2R9 z%|bKAldh%^A5=G9J}>|5M`1pTLVQ|6d=?AMFY(_K&l@LPv^mUYiO_tAe>dM3hxjZN z8cI7A&wJ-kOM-GwY~oQHSQ z)f(b+mC&&E0GU(!jW2#5=Cev@yyNbxLVQ*WO&0!X&f5IRTVXyB8PXN?#AkJg&l;g| z`BdF{E2^|$x{!t7g>4$%sN9I5OP?!&M)6eII5TA`ga~A%Y+h6_k zC%10G6iE$rgXOB1IAS zC#H-`*M1C_Vf`3g-WJ?O^`%R-g1Omp-e!Gi932OZfS7TX=5vD?V=+CG6gAdjPBa*e zAzjBBOdm^gk-=nH3|9+jMpz8yxy6jMm`4m|y2ap7mzWBR`N&|ZEanS?sj--BW&uoz z#S|LM28)?xFyFKo9>}4&!D7B{FsE9~?FKW@Vjee`t1RX%gK4ywGWb~BP?cx!K7Kt9R`zbF+Vk!9E82ReS6D;QU2D92?Mn^PVYb>VCU?y42W`l{9+`R@9wKT^ZrhG_K zo3t#+tt(tC?Q=aes_Y9xm}d-Tx#ip=O?g~yF+~Q`WHD_9(_%5N7>p;*ASy_FcFJsH<*4F^N_)uYcanx7|rDylH%p^e|cy$ms5Iad}4WVTnIBLggGaK znHa*%1%|=RMhugkLCs6;BI37!#caF@_}Fhw#0b$f8w?-yl{0aYbiD6`^ISa14lw9v z;OH=(xp)L4o$ALd27vQ(6MC71PRwV9a||;uL+79m6B=;NW2-+GwHu3&aAtSHndikw z=-=~VB!&-oF+=I=E-z*nF*jQb-j( z#kiBk@9SP*l9T%3pQg{H52Cy3#&CuSi!^>;_W_ff)Sq5pir%l<8}qf!_#%zp*ZsgG zCsE;TRcB-PjENy>Twgg&c##WAlasOp&vzO(hQBjmJs>#m{sfli-#y3T|}8h==i zh%Z+fw>uBN9P@Rr@kJWHuSdlfJ5>xzjT_caj4#soeQg3p^^mmZE#5jJ7S?OV7is*y zzAwJ$?1m77{$hNQ2EIJf_<{I39{-Ht-;TJ=ldkmMK*5m4AJz|niRnhw5!=Vb!aB|P zB8}hIW8#a>rkg1g_=6d1e38cQ>v3RW(&)S657S~{l^b8A@%#Fb&sW1AUZ{xqy4v_6 z4Sac|@ni7?g%D{BnQ$Q*Sy!5m8DFIFhs9B8Od6jbF=2Jg*YAxl()fKnDZW^tvo=!W zhLzGs-$~>5^%G!X(ir!X_dke*b*k}28h^S_oZ#yu{4v-3@D+@kJVcSWk&B zSLZ)C^c&a4d@V7)NaOeQwD@AJmW)S@8`e$67ikptV}l_b`LtB#j4!^BZ$HDMHGjD5 z{KEJW8uc|@eQ^#ak+1iRFQH)&PNy$)VtO9Me>HBp^sNI{qL!$)@kJWHugyMR!(M!P zv72(-0%UxV#_#J{pRYIXd~;#U*O|r_Y5cyP^Z8o*_($twzKV=5()fLC@%dWzay=?P zH@`}aFVgsZJ@50CKmETp#(Y&9U!?K-`nk{7f+xR~AM>@y_#%zp*9$&hdrqipjrqFT z_#%zp*NZ-1GltHY8}oIe@kJWHua|tjW=(!88uN9Z@kJWHuV08SmK2&l_bLB&%-7?_ z7ioGp+wfLa(K4yL9$yt(KyZA0O>I3sy(I6W7V{#G=%}1Bey_EmCR$oHskScK+)@>d zmgeOre3T-8e4%4G)Yi9DU(!@wS60byz?avzM9U`S&N^>q zNx{tV<4T4W!Oo3d7`+fD)*BaL+huuO9l+X!jd*WD&^68|Y^KNDTQoYWptu->c<1-P z_1z%+-=6l87Sz>VQeRy)wy7GQn8sJw>dWis%<#!;RIc5|AB|2aD3Whfg^&e>#kq(j z$Y=V=3kqiBM&T-MWdUAZM;!2udc77F70V~F=+S)sA?VJpWvNp<7keGP&#|Bgf$E30 z66KAX zDda8?AFqOj;xAt<#S%>a2Up(fv;a|N=G-=+*= z$c<{Io)_OyG8K7hZ@BSmNB}KK$Q6^oql74KLxN0=svt(1ZdSh_`%^5W&Ue5ahjAfdowcMgCORf?@QS41tenknOMIe420RfGI ze)v5F^kb^uT{6ML10iS$N6yMuIU&OkKVK@Df6x=Xd@Do^jSA+WU#a}eXOf%wUQvLT zM_opZ@kdIWSecqa;MYn|2p+BU=DUXi+NAkzae;gX@3`OOL~QMsJ5Alkqd)FvPNUj7 z3i)rfgj88#RQ~9ze z>dfFhK&UgLFOKjaak1>jZ=Ly-<3~5R8lww zjdTeQUrlpAh0&xn{;0C^;>(V`3aLTMin=BUW`yS`PD~)^Dw*t{GS=5L1ngjc?rA6*F!3%?TO~)No@roq5{xeptcmF>^h zjJpWMQ`TcWo_&N8&reRSKP?>GhGpH|ybeX+fY_P1)hw#7tVQ$MtuIKsF=%1M*G(VQ z^AZISPhyal=4IR<68P{2aX>N&hJIkoMvW>P9WBc}Z%p+32?fRD$DemzR4+Ujb>`?% zgGc4-od=`x_0oe;`FiWYsI&5;=)(IxbsZg*H)Tu2=nXwm4&=Z`C#5bzVMmf=%8Ar9ekXd*F{Bf#L;z;(-&iHwjlDnvwoYP`{j zy5z^-x)GVEHD*H z*gY1Fu$zrbA}4Qzx!88l_5WQ|-3RcI8IVZW}FVF3q5=jy&#E5k(pLod zRn++TRmS)&UAQo+j=8ysZ0C%;yurh>Vn3@Iy5_b=vhOD zw^B2(dnyz&7 zU`3sbLhro>bg9F0+)P3-qja&m4d@cV(;lMB?eOlnARX5+uMg5?|8w?#+ z3FGnG1^m6BxuF37OrrQ<@z41=XgUpDSMlr9h;=nQG>Q0K0=Isb;%;y}G!RqV_~pQ1 zJ!rn)BxDKsaq0d8L!*@O`Mm?jPSCy9+%>-(IQM9AoRjd-B$D42xQzhKzYQJb5>H>q zuiqlL;h{;y?=`qh2Tcyvo@o;C`x@K|K{LnDC6eEE&|LzW^OgXBNt7Rb;kFDk*BQD* z@!J8q`#`gPDY=IpHd$%YqfJe)$miPeAkPDy2)Le{12Kv>I&) z9vZ2~G)fttAN8-#&G_m&8wi-L_>~wM zrHs#SFB~rcT_tt}(Inz`G{U_RG>_h*bcy7*6VA_p=FwY~E)hR=)7}HkG|^;I35e`;uyGJbk@!13feF#fnxsS?GnH=GL$jZ((vM}3(Ax|8lwszm(y z!g;2lQOfxISUws-H}~$Y`8@&WZ-QpRJxZ4bE1vv@Kz@&a=KXt>t|zQ`@*4nr$$hxY z6%S3K{M`<>Yd}+XKdBPyOD^1Q2hFbx9qWyF@niYe37Qul005Ine(W}X4w?lI3Ynbo zjmNJO&ff>kLl4F1;-!~a@fXl+cv$HeZajViA-`uq^XYe#E|L6r@4@WvLI=O6bcZJ3 zcPr?U9zpxd1`#GvdjABsS3&cmO+uEi{b&WhH$gM~2TGTS-z+$<0nHx_U84LQ0DgZ1 z&DS1NeoRL^`Hcj=95lBXxf&#;Qi&M#_vMVUGZ$!{Ln-@n?O_aoYEyKZ_JN&&@9=qZ+;Jf=G^D^ z&2Kem8h^fTes_ar*bDpSw*oY^FLuq3S#b+!E__Mpy3*$tLG#^Tbj|M=IRD#lQA+&x z$i+Q*JOUD%0GtW*M$mm~XjyMWo$x$nCGdS-$DhYUGs5$j1L3|5boUur>Qyw(yeRYI zD{pw1C7>Gu{28FDG_;2&pz9C(M+y1qi87GLor8z|8toAt8p>JXN3jS-|FU770h-B% z4%GU{3K-U18RYAHyI;dASf#x|w z*Ht=R0nNL9x==bY!S7F?=`?hr_f}8+`H}q_d{6-oO`>!#y(OTj3(^JBaT4fSL36*M z>na_aK-1x;3#EhQ;TNEJ+t9J!q~$Gkx(Fy)ulPG?{u$y2I&+@LrAvMbci!NkG4V6u zDvtk@SEiwHvGK||>3VmAj^*g9A-a+%mW<9ATQGj&__4*~rxh1WA3bhF|FYs~qswL# zO+6=XSZ;3rIPT-87fmggK6z@{n4-ec^U5X`%_y39PJSH9sf+6Q;m3*C`BmPu?405; zRb^wA)t4`X&^C>dT*u}LxebG?Ul09JRDcO@7A&1)K*fy6v8kdjP zVt-NSQsY-GeWp| z_{a=zaIRYJd-n>zv6YS zQpi8!*$Q1}H9g(nbAV#pPlQcwC&NAq_9?K(!af!D9N4G9CVNy-t?jT+ht2d3g8g^c z;A72ks6TS?Mw!vP2N`}1Z>|hCA`TY@WJo_>1MLy8%f5sR^(0YgBWfVC`?6Vt%J5y| z#slvVYNnH!xfjBsQ2VG@iDEABsCXZTE8@6}A=8Q!D4*on0#i0HM}lk@m_-5iajL58 z(7t8?x5whJEslF>g>t9G;`5=E)$oy-xx?ZXSJ#a#uWV^(k{tAA^=5D%2cf|*!0pyc zEWi&f&Kux1i;V^Nj>Y){jD4%djQ%7%<_mR(S;DeSvluAm)pFRwU|$Y{i&TV1EntYSY@gRnSjeMG}BO#xPKpCSfP;OeR2|lZX`sD02E`V|~{z7nAijAh;Ut z2_0WwU_WQ3F;L`iF3Vq?%BnQZRbC8RG*Z%|*31!^kr$HAuFWXI8$tAJSAADUvOq zudT1DUJ4!8LP=RQ)K9LdK`}imGsp0I9%78O8#CQdU^DKN6VuDKfhHd)re`qhGhq*b zJq9-5)(NoDmbA`-eHQGCV4n?}X+H;cuwJK}nV3ZK>523xQ&qM#H8|AYGP~%@ z$jls2IdF*`>5*8Ko_aX|c|kTJFX)@d>wF_G=x9h@_dy=6egSkgqRjSnVrBLg;ARHo zML%qcHsYE6W#kn+oFjtshR$3!CSK7EjsfEI{~0&x&tb5q8&)MiF}_n^XDhyyIyVFF zEQ=SwW?7sGyBRk0q4fsXz_m&mVF&f>TX1J=-53Y!x<}y_lpFm}kJsXvbHH+QLk2S& z3xM(D7OwK*R&alXcgVmR#y42Ml>@~zRKR9gtb~oai)~{o$|tV>c3J^D^I!vZ=EG)s z>tF|E$a2S2xEc_Y;WKax%FtU@FaF<_p*9;)L=!h)#4oUvDRs>?jDN6xYXFKeZG=sk zqCJrMtqFEeW~cSQR1);tmDxaeJlBbp*DAP843t;;ITw6smwy?V@kE@IQHJOmkKSFK zEWKYguYJ%)9`2-Px>T?a;wuNQ9Q=F6vm7K+2y4(hXF27FX`T!m(|x#nJD7YLbbXxV zlBC}7TLN}ZBf5Rue)k1JdMD9Bx>QIROozoS6C8U3%va=>HIyy$wI?vtf13M&qTC;V z&9?tR*r;=O0hyGI@4!Z0bIjR_@g+aJ-8vLJegL}>_77n{4Eu4|KY;xs*g<_53V+NI zH&@t4$4}mO!^U{hDGulZ{gCD)JafCP5AGSqP-_P+u8CLqumi@7;>3eYJJ@*}Z@FNc zg5}~?pcv0PU>^|x@PWINL)kDXpPdCaU3NgtHi7RXXf?2ezW1@Pm&7yeLApMH&v?3kft z(@Lg}pL8CjK5hEcg7K54mx(OD=0q~zLdNiD#q{w!2|2p1yt!Gf3czS8l9_@bMNV0B zJolV3e7&!!yl`1db#qzXPz+ilnU9i}q2|mcKAT&uM|LJQRF-o_sV}GwN71drdtEhE zt*p7FX;Ed1b1Ynbf~hdyFh6#d1XGNW%=e+5JWyX(SKC~RQGk5B)L!L)x*?L;gzCa` zlLf}9#ZOf9{=ISzuveIjqZ@DBkJjMs}lab8RU8k}On#vn- zvWK?_BX?aiV_DAYD9Y-qmz3$1Mxq&$T?$`lWVz0Dv7tG~06oV=iw94d&PBx;$-K~Y z_9w$f$C#ZRpU&hE!+*%7khs@DeIPi8nf4t%xw~$y}Be;L>MHil4e{2R>pHzm~f9|K4$9xDgWbYtFb~;Id54kQIgub zL6%e2MQZbhNJf9hva?l+hZEKNN#V5bdSy5|D3Qz=NO@V=!o2+9XcCcItUv0iY8Rud zWZ}I|M964WX^nt;nj@L@$gxHB)k_=k<<{ydTfU{dye;AhUWDT0!P~FnI&top6AFl7F0EdW#20#|56dPD;;Jkc` z#+wpCjkpktVJ$4+a?l+;he+mK@uD(@YxbBk}3Hf z%+y%U=VQqul9}pO##I+IG*w9{u9RwjY6D`12$t7P#OfGhi}s=yd@#Su+ze-_za5F! zf)Hy)Oe;eADD)fIg$Aa)Ns0*dM~jFQgdtMQCQ2G7@cxOh)zwuMxJ5wf;zJ}fX`Y~8 zEO-|RrF$(3<0e`;6of_#siemv)FogBPkcR!Y-$@S7S%`z+l?-qWc%XkrPHb#aaTzT zmjA}o^8UQaYANFb;Op~X0~lPclT2Vc_glySsc)*TscgWys;G59<=q@*P58O!OBY3V zaGsQ{M)Xk^mzSY^ZIM<|E3WWGLL**%kPC)ae$~TJOTW~u@mOlRwOy1UcyXN6Z%^+_NO{AB?)Uqm z%g>csc$Giuv09kb{QF=Ms7tZvY3gFP55?YCyxN!=w#ZiF()YSHPN|&M(9}}WR9#gI zF;`m^iIsV`(<5qbGz#4^t5oc*4HdqDJ{P7?Bbhzoxr`W5P+!~J(9+b>vMq zU&R|Au#aSpXVp=*aOe;$3`8=Y*V;#Kt@IX|V0$DbhMIMY#BxG;WkW@6d3{lROVcvx z8gnG==~zfB`H{CYcw)<5(PD|Mq@^xgGc)NO)ZvoiF&LCZGB*bk7i;9CxUygJnm-D$ z5KqO`B)2#y zjkRNwkjTZ=s(b7wz2lM15EM3N4<3G20KIi5Bk8uj7vI0J&q+HzfBw1hHA$(Hurx0C zB`ICJPxA6@?a!Q;y@q4D2>pFQxp^v}+EJ*W4WooDSD zv8EbH#ym(y(pRtf$9<1oI3oShKOFJY%a4BWB-XbDUtf3X56B@v9*t!3xuyQ~Z9lAD^+D@PnLqD&OU-ml_XvK% z&?~Ng`r$nj#?6`7W9m(xKZ0X4g3mj)b52LyRloYql-+0E^u|t1JM@N3Gm@6Byrpy8 zj#rQE{NaGL&V9T)a{$G=E6ix8k&$y`i2S1G7yx@fA zfAQIS_uP!N(?iJTov;1)gW8J6H+<;KZrpam@=hGH5d3f7{qgKKrcQbEp{eIaQ){bF z#@x8zAHF!X&&4VKIDW#}$NjE-#`GI;v_SBmoc8eNlQPHT=dU^LhNdOYRAXHzmHcn- zcSba$;@?Ldetm;8qV+;7(q1X}U;O6iqWk{%`P)64R$O@W($$dv3xc0EeAl~|*4-BE zU488F{fAzS$)RHoC7+vXa{u|g-{11H0S|7w?e4{!F2%f`;HTf){+)ZTD!aUPUE6yX zo||#6<2)?*k$2S{z9eOQ-P0fbspoU+#^&MJvfwZ4*qys>_4KDce)yk*Ux_S0;XfTR z%}DzB^wvv{y(9n4{%?J@X=dZRAERLx{NsmgOuOrZY3-kV|Cztscl%$kSopNytH(an z`C9gymtFhhQ+cnSmI7r@!32Fq(k};(KI*Nfe){!W3UhY%DVVepbC-($bNSv)zxepo z`AussYI*7O2QiN&_`{y*f5@NSyMFKuw>_|C)2iFXW2>^@&%FD;Kc4Z}=p7wP<_!7h zrq57b2BeX{GrD)tg%hs$*Ey+w`u9y)KW)I^MDWwE*>&QM2Y-`s;je~1b>XyD;D09g zLGRtOYfZAC>+|&H;3+m>toL_cL>M83# zt;bO?!C(9JzMZ$f@RRi^nU^?k{OFp$I8O9%^8eS&o|Be;c*wDl0Z$+Lct^{p&>z8X zDLsF6O-0Yw-oCTy!?e7-EUh0#q5*U&N6c<)YQUY#3$tsmTdX;Iz|!GEPnnIKb7oiB z;@aj#<#pN3EsLsZ8?y8A2IbCPTsgb8zOrsnRrPF48`L%ons=aVs^=+>s>OLjh7Fso zHv<{#^!!1?^G|QeAC@~rHr1(Pm2U5Ao?XeCqGjYOS4=j|u4uWWx*nG}Rt~LdsA=ZK z&X>e!x*tqkZGCll)57wWdEmGhBfW;E!TagES;h+oE+t0hz`0an=VNtE^MNyJF0VUq zCdeA@=E5eHWe0`d;__JH_CuSjT2-_()m~CtRe`RUCbIj?D&0xM*%fvm>%q0euqb&; z4f_Krgf*NdJP29Q)Uu?hzWb^5l@JW|7nUzQ@JOI6qri4Q5(icrR5muU>grD3`chl2 zeP&!BufxoPknSaV1^uAf`nv8$Y2Rs|Z+hz0?5Q7kBo|7851bEL4P4TB;C$*hV`6Hu z?&RUV1*UDtmn-!?%|KIB-;AB83m0K>Ra4lVnE7}Z?P`!U2${{^PewK}2QF$%ryp=5 zZ&wcvu+y;=`h!~jK;u(+aM&o91DEhJY$7-at@6?Z)yw39(gTkX_L-JJn`;l8Q}sf$ z53Jb_oE2_0J6NpzoVrs?_g#T_`kwpK>(l^Zy#)(Z)iyVlw^Xt-YH?aYs7Mb^>|40f zvH$V5y{8xp+bLHd=Ft6U`|8GpveJOL?Uw5OYKh;`?j>ABfC)fJ7|=fJ9M%;x)$?9;L@76kA_=u5M{42SDE+1WYy zgAMWN;=bRU_S>V4!tm?^jDqEqmwymg4H3DV8JE@cJW6|MOxk%~X)lG(Jg>C#vQ^rW zL-NP0Ky)>XA@Kv*uYAnUjhFO;8{hcRJ-A^EAM&41M_%60c!BJn+~dagOR_TR5SP_K z5$}N)(wNA0WBLfwdpKt_G4puL(02g71oOg&I=p<2P*2Xm36$n6wz%aM$4gI??oNwK z!Hn=cydCP47^tT+-9Ty1E{oe^apjo%rH`IYwSm%{*DUT$i`#&CwfVxi1JD}rvBf}X zP7Y>f+XOejKxxinfas&A^MrxYoOH~*s^1I)r8%1bDcxfRN^^DqS|FkI#XR3S;nL4Q zY0h#$?Si|)Kxs|{!laL$PP&28oVkG1Z&>W<2Qwp&2O6nFna0aCyu?NV$R1oI=cP(zT~E)<9{_Y>S&~akm2EdcvX34g>Xc zb{Z(nX~GO9U3)r<4V30wV{scS?qxs?!lf_fFbVZ^`WYzAxz*zCw78Tbuo5FaN(=S`<;&xcvPKz7Y3p;Ry%MAwV>D+9fH0J~?+|aeBbFzWboRJn6wYbXxH3=7f zpqWrl=Vb$>IRi3r0#I-R4V2~#1N05Soo%2rXDpx%f}3EVG^Z5Mb%L8^pfsln(0akm zGfyjZ0qxLH2-}L3gP0j)8hQ+YFTEOvmyVU3)q+4V30=!~8Ln z0=Vr4N^|xALKfrcG*Fs@qJ{n7y?aOJ)c*7K%6mrtaO#gw-905Q9R)JZ42SpJbfBB< zf0c97RXo;>iRiq%+(C`FT{+2Vy%O6(@!)!{W_+uuB|CI9TiFDslMAsq4&NGar;|t9 z>Evm$7K{FN7e@yNVFGEyiHoua43MKl+2@{Cx^8ccdpu;)Q0~RovACP zx0misF75pJRU6R2IqgNA?Ztcl)+>WA&fj`vu3mXF!1mHkF!G`|Y$Ce26TZFZbuR+_ z$!+Z)&3TRy@ED0-?gdlUuXycARP4?Zbo<+PW+9HTm=$%d>PTwC|BBA!UhDtJ2o>*5 zF7E90qw5&GtKaCg`ej9~+*|_04!kfHh(gL*#I|UUjcL)IzxA5EdIMumhg~+VMZ5mi zYu4&@j6WTAwiiXL8!&KU8i4&k+N1U+T5`r>+DtfKXSS*tfZW!$&57e`!lMiK?F;Y~OJ3qg#xf_R5)@HeYy8>lzGpDK!xxjN%Tqz*~n z=1qEW8=;hLu3jp z9wC3xPF>hj)rMXJPMogVlHrL*mctOmeA)P9AP(t>Ph_emJPE#N*9)}2Ogz#>9#dw- z%JHfd5$Ez${HI=ibo-w9gGEwb^d{d`TOw!gk(9qIx)NDeoW6D~%L~YpS7b^7kE|<7 zUwhSD$p4c*5Z0=XlQ+MY3KybRr|ks(V(6+z6p@%HTzPa6pV5ipgR;d6q9`4@xq2lF zU4n2R?=JXH=pKKT+{FA*KSH9x3bJ^w$Szg{y_L|46QtypfUi(#P0_xnb8E_`t+%dY z?efX5y7U?=q*7U0uPm0I{0fnc#DwmxGrN{YMFM%4#7M@6qK@Ldw|!B>6ZQU*I!_c` zk};e1nB)b-iIQr|M;H0km>__Vd#fF5NzLebJpI z!0G#X9s>)3#oGn-Bs;LLzn8q((*Hy-?D<$itMv~W=7nUKf2fv~;AI)k1 z;G$HDU(3s0HE^zc%o*u;0(|opmidC0rzL7XB+1fTJ z?62ceoDy*V1R9mMi?bVVsm^*p zO7}RR%f-jf0deLaRd&7oNuX3zy|cx&51@MlcPt>ziex$G08+m*0C655)tL`S{ay=b zj?mo>Nd4XqNc}z!Nd4{tgdrgOeg>$&aN*!gUB_9d6%Yn~pj!h->6l?kx5+}=0bwu* zx<6XFUDlP=iTW7H;w|y30HpG}%|cIGx?O-UXk`2VnfPJ$M7bOWNVyyXNV!BURA%Wm z0O~7THUd&EcUspD3-!Q!i^{JLpg|J9{uasybcW#00mKW5vYc^%iUleGq%o+lP>Y4u zSm;|8`mTkZvCtb9`p8260yI&==n=t%djjUrY3b%$ zI_}I4sana{%#1u2iSc(y@h&)fn@DN70&}fj(5p4!*P( z4?xwKgGw+PbxA+KeF0|y&H$Va*i*+8?e$kJIdahdBnc9mtet)mwQ+znYfAyCaG0#W zyySU(?-p}E7Zs1Ta{a_9Yms{X+5teo_xcJC^{hM3V?F;rOADO{0!Y12u zig!3T$*n1en^U~4sHm4N#W55;`!27`D zZE%>z!@J_52Et_9K9uB1rkZVbapWfgqOC?RE2*tVdqGNDVM=>Jq^&U0K0du|Lb?#J zV^A7-g0!2rJIO_R+tb=2?GsYk#-+4Rh_sE1v`ml9X?zJmZ0E8OF7r82k*5mdOV;TBXl`k}(zhiAmW zS2*|13QmSLw9LabhMM=1`B8-F8peZ}kEVmS?TBeYW@iIxfz8Zc1bZoLY%FiR8}<^| zR0d|bDgz-^2104hi^dhRwg%d_G6b{YIm{Y6!8+g+;1Xv<9$ei_0O$lWq8YegM$iv4 z;siXLL{@XqO1?d=pY5`S%`ho+$V!@SIt?>I9btt^NQFuW%PF8z9BY2X`Ae9uQZ3$# z-YKfu_8x6X?S(0A1u5-?k+uRUB2&VOAHmr>&C)EX<`YYqDnThn@X!RM{0-oOQl=kD zc_f~Tyi%4!EZp$L`qjR4vwmFRy4PI$FK*a*Ik;{J+968;@%kpGI^j zAy}IOXy!z%#{;QqO-OTq5SGP2t++Q06jbY2x0%x40V+;G`Kp-b*hysWW#M3xYIqhe z(d`k~m%@%*0clo(Ve=3FDy+<@Iw@+-h4)QKqbcOuIC zorp4R>i>$c$C((=V%+$S&b$;vSaJg=srPY>skg16%G;mbMZvo8(xTaO;FSga0rT;ei(Hs_qzvI)Ks@h z16ikrO(Em3+=z$mm1;R56%QdSa)U~7tj87S*K%m-4ss3G7Sq5XOTtWCD^qd1lHfIP zzaXHj^uyS*=0782*HKz%2gOz~2gYOJ&fsk8`%6epo% zNPVD^xfwC3>_Rd#5=bU^0z4?6pnEr^WN$xprNpfts#AniN`yjE!fKUdAQzB0!*Cmj zQbj3(H5-nib*U_^a6dmF68fRC9EImzvKIqo37ilYF$8ekOnN;|1zQDS?Uk*8$UnpH zz!(LIvQ2iADRwL%Dk4HEB0_0S2dEXd#Xur9_LKsJZO(HMP@D)~Su&54xTy679gSPu zSXpuK#P{8J*5a8SkRJVzhMn3e-BzfEM%?#-qf^~8IN2%NT!vd+x4skQl&^prASEo^NM>J{uGDG>pv>R%MsGJE~I!*mpb^Lkz7#! z8jb!A-x7KSXF!r(WYX1m7UdqtL&=)j|^lJ{gCE*JnWLI@sFw83_7Qqb%UKt zNiehxc6JyCjMQvV+d)+DDFi=7c6h6v^H-~VPTN9bBZmf^Bk9TCDK;7pA*n| z`k_eKJf78iS(j5-BkJ_F!Bv>Tfm*)Z_tXJ6}f8|esC7=4v33!x(hbrb+-}U zxmJ9HRD6WAxm4U1&@0Zb*X~$M1sJz8?}`r`!~``G^GHrX0`Z{-;Cz;${?JOYYp`_yiV&<>v{G@bm+cG<&bT%l#Y_HaTE)w01>OoUWSgwmWR;6rh&-xYVz#e`bQ zIj;*b{i8c#s^o^eZVRggEE9IX;)&{fBdQ@*RD@JigtP%vTnEylIEZT1&Ky~LZY$c> zR1+F>p#rm9vwZuuVS@G`1b19xP z0_smcr1=``X(-KVlH8_B>jW|l8+MT0br<$Y7UtP?7kSN>S{44-PUU+1Gt6Mc`bdi2 zrTX8n8J90$Gacsv)^>@I76U>$$)z~f9g34;kp4o^9orD=vWBO4!9!Tydr(%59e+Xgr3w?M?$r_R1S8Oil_f*1QhpG{Xz# z^kvLp;ID+uc&s!zJr-%!oF=3>O-Ltt6!#eD6&HU$&Z?ay+|s$}Nsb5O?!;*yoxZ9g z7xly@Y|ztt9xO&z@$2R5U0U*#pXQW&xre zW;xY>#tX#Uyi6dL!eFS5j-?eh;lf}t6O5f0bFn>&yNeU zT6`ITYsgtmcHp*b_fG3uz|(xAi63O5Hn88Bg~cmr@Pm2W3Ig^zITp{sL-QAOix|h< zuo+MIX(c1>6wo{-qJW8W*aFtobGjZGGQMk z-7-9Go$h8OEaK2D&EwX+f_*v@g$Spz18pE?w&J)|M~iMdpu|O&BO;2!&30DQ-lAIx zw_wqwAJSZn=ig8hHMXKYT{>@M8a6tUp;^ho+9y$QWf4Wym|dSuCFc1VD9wzTd$cZM@XK!YZF4V z`8{l=4HI>`{b)}nhd3q5W$gO%*54fJYDPW)C~-zU3ReolmHTcKlzu3^Zuz|wZo!PC zpMH4m#PhFkMxGYRNKcVP9qhKaQtQTATzO5{;xf!&#_mQ(lkxZ*Hsi9_bUcUKj3uNQ zOGsN>#j(XzT%vk7+w?`_cSQ9h04riP$vR12!dBP?xeB!dfjH8mbGJ*PrjAS%G_ng7 zGsc^`jSr(-)80<85L;AjgKGf|LkhAS*2au?mgG>dHeLhQY&;P>G$3rBVe4YhcD9SOb?i z`c1*Puo<^<*wj+CR9b8aY3>rzalYbSG<3mnzFWYMH&`^3iWeL2dw9^Y78t95(YX>b z6z5q<9yG}^YTLLs+h1_rGtwY`j=W)6i?w4+97rws`J`w)UAlxgP%v zpV{MW0pEex8K;k6GhTm!&1~Q>MvD?5%?3i64T@tnD9%5b;Yyj~)9pzu>3Da$o+)u= zE{_BoE>LC3rkYxTm<@@A&(Q`2?G-+C%oYAdz~zCmK|iEnC#RG>XfdeEx;St+V#Hj% zO->h7_?_3PYQ3Pkq3L9)@7yT34Au5#k#B)cThk>-qY9Uh3YSo@PTCJaP80E+fM{?T zA&Z|zI{-nlK$mtQ$Opfo>6NLsz#`s35uR^}PlY!N=~CelQsEI2;myEEc-0OZYs*-Q zqdTafzbMTz2X^q1T%6uk9QovT7n{-SoM$s|d9EuUYDQw6W8FpLmfM#Or@qB{LqCSw z=zyr`hYE5Ep7Uev=UlzuFk2?u_{|Kg*wy0RTQ1$HR)OA{n1*RrSGO)D16_tI%H3~V zE&_d7886N4naL=&$a}rKQ`=h*d|8=(Y|qtx;$+mr0^iSym5_>+P@3}xl>L1gH+^j2STpgRHR#271_lI5Kcr!m@tT_xoc0}C zUZEdPf8f;|aTguml)!vQE6PrPe_y`szDFgBnxj1y~qKKFH5VO1=ut*dhH z+wNxd?ysT#iZHVAxQ1bOKsZRYRVeHZmL_&Okg8CGR6c}s5?pZ|@TWMxe4dyMLT=oM zCnUD#T?r{(^GH7w5alz~RehGME}KVOwOY9dcZyd}!xgZ&NN;&{;i4LRC3hO2Zp!bi zV?1jJ;ptSyiwfvfxJn3+ajk;Q_*NT%wpf7@Qh^dmbI{9i6t~Sl!KU_!A#m7VfyQel zy#jrxORYNyLi`8HrCo@LFGOmgSBOuclv0RK!)Ek;W=ib^R)~aDh=kH)Z?@uI1HIy) zm8*7U%rN8O*kTOE!0yN?Hm!jJkuo!dxsO>XM~M68?K&vJE(SR;N%wTRr(F0XBPl;c+S^4jU7SOu`uF0GnOwWiE9O7GidJ7h*8S;yv6P zae6>zI?KXac`nBje_VbvTv$=Nef{ftaVjjAa#GiYL!g13WeSMl5#aG7o~4M1ppgJA~;5zC=FjL)sG8K>KgE}a2bYdAuxON6wB zQ(Oo9DNc1Mo+{}{Ae}SWItRBV;82j6LfJY8*AQTa+rB2sAb`_wE?8MxJ=gdIv(GO|Z!TH?v$g0-nUR6WOV5vT>D@bD| zZsz%>&T{QymE@()q_I|)S2L5wwkkKq)nUAXIr}Q+%^25@VKcs;n0d5eHfITG&Jxn9 zR&lIq700&AbH3hJGq@!mN2PnblkTq-+;V8#e!p3KnnG%duywmQ@dk}L#DqEG>VNRt zr%T{AB#=w=gQ6&_9Us_y2;@?zjdMdlF92Omca-icVJzsL5*Ew_h8xUbV$K zsDZdVQ-%1bCB7qOzH;gfz$N!f&F&C#_pfBf=wxgWJUf7RiCB2FQ^i6^#X?9I+Z6X0 zcqz``vEuwhM@FKKKwtRsMm*U4Y=wJpBP{(;GAw>~c{>933pOK0Kr*9oYjkzfx(+DMMKvo^;A4s(>vX{?+9)m>A=kR26xUVy<~l9$5hXf zWj7ALr#S1!OQ#!gaCqcBmjFy{{bGzN-Q~?FpaP^XOBO1*!h^5d0>@?8EZI^pUZ5+0 zTLmbU2O!K5-VK0s@$+6l7zDv}6QHXFqLu^)FHZp1h{x5Sdo%nCqAaSxQw#Jn91m?? zH>Sp4u8^kcre^JMlfP@+a8RrQ%b{QDYr%2WPBYAhdijygJ|a`Mj54mSVVqe;84t>w z=4q5s()_l={#v5o$6;^ z>0V1hX$~q*;f%Qnyeq#@xra__7sG#|f*UJYm1a5FfD(7)2Ea8Y@o=rV5bnbRjST&; zZeSDpA+$k_w~^70YUX#dBCrjOOzVUP0t_$MxS*pdbwM(0>AIM@;54LJbApiO1RNlx)h5c#FbfiZn%Nk{esff&2Q^38>7SMsfc`>=p~>4)-VXOCaVQWKW% z{)jhN&oZo_Y$Hat=oGgy4rxZV1Cd^pEg_XHp)`J;+ELsl14+Z(<#jq+Ki&G$A3lEf zojX3;GG_TP?R(~t!8~|(!j~4=elo6Y>9iV;(Tn$L9M;_Ak%f^5zS0CJRn~L*3p5ru z&8Eqgj(x*Z#0S?S6KCS3aE;(`%|_%-Ut}vYb~m0Y@dT?t`ss_O0?!}gW@0@Kgv#uL z;M2&0wYu(tJi?kJQ=aKc&58KB9-qBu? z-d4I3n+A7)se|@2!I}2axJD~5>hYgx02h$u=%zhWvNRb^%MAPnAvSh`2<+S{{g#U9)?xDv?rqCK0pr{a1zUYWFL@7C3+oT9=_SRcl9+@g+e z(vg<}?&@K$2~!Sx^scQfE&)5ds`(}eL%=rc<2vLS$_#G$Ydr+rikDgr!wq;4l=I1< z0ATB_eY@JOVge8#Zbe*4$~Q>4)1}-gl$6cRwzU-J6GWgk&5G@pd^REqJ`;ZQsC9o8H%0{6S>+^&=*>jA#JWhpk=y~Ul;?QM?PCxfmEA05`YVGP~$y#47I3|Zby zXs3H-b|PDzfp>gM%;9X*9+ox)q-Piauvl%t;~J)A12UQ;_0`Pz| zfn5umZP$F*Ghx@mCUbOATd#wCDQp&+$^ z*6^w~6r?N!7I5LEeQ+5gF1YP;kG<_PP6+@z-lMmx?S_@?K%>CQy9TmxldxLJe!|DK z$R}6z{nMaaRAqv*xY5J8A5g0EE}+CJjU5PGPKYvVCI$L=^ur0rxA07}8tPZ+;Q891 zVxv;G1`2D8x7%QsD)vvY|B+a+sn(5dkg%DaTs#=BI8}IP(6N$9*7>lH$NK`*iiM>*I_S$O*t)wO|@NwJW;hJq-skjO|Fwy95qRC zqPF1;Hwms~JQ@nK`MngJKjemFfpm!V$=kjj=d&qTJI6dXg2|Fgl@hDREYL;pxLL$0 zn4`@5ZrCir!Cl4lLz?k;c%!!(sE6mUm92?FeMpy{J%(5Zfl9JU(%4u*6ki6Fvg)jSS-a*Z?-NHq^kSGUs`IVB0n>o~8 z52d9$e)eqEBQqYq9!J2J`Los|s#09D9+%^=*CWGFhGlY_btz3RnAsb(sT~0<&RUP$ zjwl|Tnf18AQjeC~Xlwm29rlF{^zq_0x(krE(I)_z&aOb#56600Kcr;+kdkjpOWrmm z7yp(oW;;v1s=MfzQ}_u<3;@Y1cJ^Am?=J}!#CgkNZAA9lu*czVzYSxUo;XJ1=%TIL zI_r+#gu>NeEqc9LVHW+vX|bCS%aKvT#co3XfRD9;nAUMP7%v0U;RA`{mhEC7`_@rF z=Eb8L5IY}PL8N2_k#ZU@LrU^qRg}}%uX$`rQcm=ZeYyC#<2fg|=He%&(Ba*PE-$|y zjj>aH(;8pS4qqIwUhKDC?6qFtThrk%{M5A8w#$04!}_SQ)w>^Ss(Z1}x(Dx)?FPLI z^bS3n$48?3hUcs=or&aqhRk;q#kWsT!@!diXHk+W)^f8oj|*MWcaf&91ts-u1T_l! zx*IQnir+u5sM(j8t^_7$eJ+Y&E$XvT48v)_CLDQI6OHKSgZY(MYYzk$ik{vYM{G0I zuafK40h*8L7^nR$AneQ*Lp7F>Lrlv!)dzTxZ)swrq=}J|yU!($=b}izG=u4b2Gv4mvjX7C=1HqG&M^m#v4H9xypyJnGEqu|OwX;7Nja7dP z!@hGijycx)i|F4Y>(3eof+=V1W+I*=MUAzL)83aqVaPuGNg$W)o&wGWZUA-$79jt! z9!bf1Bqi%n@>q|OXCGI?UoQ`T&`{2bTD-k*Kiw0z+1-o6-)=Dd`ob?Aes1X}K2x|C zu|$3W=*4tVfwGEn;VY?2HN`n%{A#-bzHA2RIOyz8xc&{EeLaR@PQX!y!(*+s$YwXS zth%YayMlC^<74d<=nbKs|EE8N$x+6G!*t9yn?AeWY{kT6OH2cP2Rt7)U3c*^fgyOvkkGx+4xw=jfJnkac$rus5!k z0$H!ifE@Cc1DTf_#I`QCQ8)4BHA4xSkh*J*-QG5 z@U!3lG7L+a$3rLLBpgaQYEO2fKiE_+f3_1|;}HWPiW~7;G!bF!`4Y zIza@NKc39RkGyjPpSg(S=VFgxs*5T1&@WKqFAnRKQrYk`#0=!vuB^-@%O6IonyZhi5YR!*muBu;e2Pu9r8oG*#3hr@nXZ*UZ$fZLSTpY zkkBATL2LqxDRMCK&Bqs$jSHYC14)!$NRZS-&6^4;Q~1_t-a=4Wg4Y5n{=m5wzASdL z`uMiwnYiNh=Qys!VSoI~Fq~;G!!b6_z!}75ux8OfO;d!hjs=w$im@iayCfP$f_+Ae z+dgmQ3MtdW6;h^Yp6cjwk$+k7q-4dDlKc21uMP5&C+4mH8!KK`?I0vHT=9|@S@Dwh zLsk5^1QjoDQU3cCU!y9XOX95fI#uy`y5dR6iYFy2Uh-J+lJ~#1;${1dta!ud_W*uJSkc6q-4cQUYnA$531pQS#-*U;#&6Q z7KZ$8orMv;pZTwZFh>{h(H!f~my(TBkP%t+oUu#lB27&IC3^(k`bvsR9Fn>UlvNyz3tMA z+LndS4Cpr<?!}U$iiNF777Hm^ETm+yNFIwt@?sQ={9t9AQsKRWHTCT&6^5a)^u%#6W~s}i)5*glBGgQmWt%DR3y(*DtPq}TgLvP|BRS|k3sFU ze_8${gggV<IPGm8Yx+7q~wc-lJ@|@N#6GlGN|u`BvD74Q1$lR#4yVH@_1Dwf?dOEKANEpkKG?KUe%ySZ=iKd!D=ZNOyU# z7%%0OHT2C0|4$e(w$nW-62=V76jTZ*>ulDQ1s1(H+q~OrBd) z>7b?w-@c%@o2a7^XUooLJcWkL_j4}`%}jl>pqP4}pg1oKr+&8JG4+jticEcl;JM*j zDJZ5sC@7}BNl+JpDi;(RbAzBFa%A7J5jS5<+2bNS+sspf0wG-gQ8`ni*1Y5-E#A1m|5H-Y-|E17MdAy2gi5wXyRT-FE ze!0IQ7&Gx^N|^Y~5#fz3k(b{wdWdUB<-Zf!SkA9S=#}Mc*+OQoy_m^nVbD?Y_6U7~ zZJyo|UKD;uP&7(e9}F0-4=fc57pr__!dbrIgqu|!OMa(_iSoN55*C%w@H$@1EShOz zO5cmnB$CRL%oMXHGsWzMGewE3A_D%%awR@=9D;~GJQZ~{_5A~tRiC{ML*t7-o+^J? zuzyCzjp*tnr+;MwENQ+U;S4A=hk%pcvaZo9WgQasa-PRIzVtGbe${taP8eB_ekFhdAokw#Ky%1iNB zrh{P(#TK39_=l?XE_?W2LAvzfv6%yh4a+7iWCSNWBP08E8z(c1^Kz?9*08ObV~vZd zlN>DDurtlgEDg$ZP;m_$HXGhjvsDkvDy-+$j7|$=ZBT0~PjHk$PJ{mDpt#1H!N4TP zV8Ap`-c4^UlO94Qy;)pvi$aoP49*N6+?2w39Gq1Tr*KIQAI>c6C4azUEm6)^+n`~i z-jP+Y4*^%Hg0kxAB4nQB8At9*3x`JQ;ba@OVbRkiN)Ig}$&sn_{QI(pwnpn=-<0Hd z8)q{;U8D5yemTi85ogxPovU8o7_Fz9kU4;}smB$ihpYTajx3&W^gZ`SFn?;amQQyf zV@=PAQF=HPPjc|)j25#nwCA>HJ=|lJ*))hB!{(KoExR*JRxK1>2`qsJGJMFi*1p1cwUsA3)-RQ zLLp-<=L@3r^b<1YA@6LBL#{mOisv(~Q z2J*FESYNl4C5-IJ*Djf)UYrz=Dj`o-c~hGg8QiGpMZ( zt%iZy>+516W9`RAM(G*V4m}s&DmaoZCdZq{&Ojd*&bm2$A zXgx(jW-rcWzNSR!!Sn)gC7y4T2$}5`J;hOaN`(x^WxA@9*1@3ccF1RSk?piJO3ySQ zvk_+}j=4Vf%h7tK3z=-x1!uQ()1vgu05{3e7iXs8#@3c=qV>!aGP`j$%V$QE9#jwX zWbllmZ)*}N(4MbZLdI&(mqh8gRLEe^!ontA59tuVM8>X%)AuCDAteJaE{)RT6EgSW z%ryV#v!S0x>zOTNF0_=7FG^3Dkm0%z)3aqj_cx>Ulna@4kTJ`rEJ{y>kolNr9NjzD zu8h`GDP%$xJrz-U{6dDc#!~syuxTem>!}hleN~!qfp5DoW!7K5N=0bRqV7 z=d3u%(T1~`ujNsCt`#zg^`MKi>A6;G+z3Cq9K$W*H;gwV17~u4d;k~8;lrg!j(kWb zc*|ud`2b3AuGN}%=}Cnm;?!tPsp3r2 zocW5AsX4bQ&K%A8z2cN=PO6#~^wym773Xx#8LK#BHK$&28a3w+iqoVyr=`eTOwgQS z#gV-PeXm!XQCj9Hi%h^V!(q01sY{->TV$l!o_xINZ}v#DqBu83aoVCd-JEtkl~J6V zqd09*oc)SZrt{U0Q!BVrG^bE;j@O*U;H-yCnDbX9bEcN*+!-sS$aGj{1~`RiEn&_B z;B1fJ{283tu<5Xjs|)l*aJ=BSVT)mz5IEZ-IGez!hYf{gzNAb9X9#A+5U|MHKn`5K z&c$1bQ=vJhc9k-xX-=NvjMSWZ#i9KK919$=Y~wDAjI@nsqByTdao&yM{4I)eID(Tt zanc~BcqI;Tzhi)d`GNd$gysw+XB`gB5uw(DBkm$~s7I_E5$YMu0b!)2$<;t7@}6Y$ zZ*10&saC-^{IqMyFOSamRSW3o#a@bcC~<;-RBe#d+8j4VKl!**=Jvd1Y<{8aPIWw+m6&Gb9L)`#Q zlB183_r70wI2_l_DlW>Hq0)KtBffN!a2iBrOtr0xyGu9iyNpiSxMl&>? zynp3q;ZS>2D9S{}brU#A4%QPxUDfIA+;FH4OadHbB17E_PLhMxXr?Pn^-`fI6B+6j z5sD?xP_s`w{L65t!73DGB17@6D#>AnI^(YFU^vta6^b$lrCT7rMz2FLUz@UChnbjZ zU7$iyCNi$uL@2W~?lvCV77lfz3PqX7P%t2*kdp?+C7l`9!zvVIB17E)PB>p<=kLVA zwi)UL6^b&Ep?)kv(c6>_Q@d0s${>`bH0~6k*ix9n?C~?v+neE&PXY^$GLdnu11D@7 zU!5?1SvXXG6^b&Eq3#l)&>e_=0{~~nRiZ*sCNk9B;Dk$~?!A}G!=VIqh)=NHW6)%`f+&IhJhI#W-+3MFJ@s1h0K z0SLwmHCu%eGD6{kh}g+m9l^2o*bi#WBB(f->A6LPqKsJ@QtBZl)yXFo(oYleD2 zg`!MksE0);wo1BBdz8Vz%}~#%P?YIl{25oi^5CShT6|A;9?AULsz5DX`WM%u=JQ=- z&!}`C|5Q*{2A(@<9JtKhGb%W8uj-=y@6 z9FG$9O**1%hE;TwZ=7ew*y)8i)APp_4)y{wJTpBr@zP#>6SnM>Rab)y)YRj;0Z~^O zqp(>Kckmw1jGTf32;!PQL$O}xR0rnN`YXpY`2G1vZ9{EYHN6=L1B}Yhdm%lZDLG!x z^jOTC+=2`w1>(~q#dC6|W_aK${CqZDR!_Xh=CKCN^%mshPR;Z%p!&?I-JdCuUa@@i zSN397jZOFzJS;!DBPCyZ(@XNM*pGhcH#)K3J|C~tw zTrYy^+RQP64;k;2j@G|y%gqejQ7)rbhg6{2Oewg>}3)7RhWh%^ElTNFs74qLuQ zq3$CC+3LP1(qB}9MF(P#{fha?d6Z$4zKC41iX&|xQhquG)Q7fh$}AQzYII~g!i&A5 zvRP|2S@oMuSMzMu6z}`+NQwT6Jc?X30jjNx6XhJlDb zA~D}~JrEQ{gR+bMu0Xs1sLWC6?x^z|0bw zNMTt+Sxw>uj4KcW7gBp9VT>5#)F2l&%y`Ah$whqgL>CY*py~)XcaBVW^#1;Q)faF| z%t>ZxJ?^#qQqERBu>;4b&bWm?3cZ>o&Cv=iJzS*GM~iaO`#oDw`;^6QNB-Kf@@iE+ zM=Dz+ar!vf{9s4L!9Z12t-tYzr7D8SzSED%U`;*#VcM>!%rM?7@K3xzc|)M7rmzkb z+n&H`Ed4$~%}Lw$3Tvi0r#W!Mf?=Z+wW6oGVwM}blZdY5IGs;iYt>z*9vQ+v$~#h# zmc|%=5?Ve2w7;>(%$uAyaL`H|5$|Ly16VtSJ-(unJYU{if5p7wU|Geysbvj~o}q>Z z|1b4dG&SHR-B&?R+)~%g3-~?RxaHL$yp8qhG9O(M{wL&Dm&J3NFt1)vi%VZ#bMqMV zwEl5rwUyQWhJoPu=gyTE>EebrVN$3}qpuAB7M`ewknwdRh$f&H`rfS&bsH}2{!?HYB!to7>F{K%tE4-)`t2vX$ z<&7&GpOX{WJB8<3Tv-^E4u7RCVS}=$&dc+7^CnLimpk63+TIZ%0-?Kz_k#A@4yCXt zBlg>!=uMExqF6UR(kCm1PU(}G;~9nJJ1cCI&CCs;Yxcjs8kd4SuY=$~C79_U+<& zVAW8;!gX^^jYnQ&WW+;bKxXE!A?~oln~PZ)S%U{B)iu(^0Wxn7rhN|Zf)>lEXb}l~4`%GU_7UxWhc%_X#BkJ)hg!2sJXM8pV#|>E? zBQ4kZN+|i&I3_v6m*KQycb{-?6&H7M+K73ex zmt8I`!(*4@W0ZTN58k0%ZF zVN2he@J_~CmhT)d%{R~B;^`}f-y+DorsViAJXZR4fq#4#hw&i} zIzA?il|F9AI2m70pO1r%^%zTEHN5YJj595 z$x@CF$YSX`0Dce1bnKZ}-$cj_h0HP~mq_33kXd<3VtrZA_dI0wE4f7F=foQ`@A9n~ zxOn!$EtF}eIgDpdmvZMrHdcPuzElN5^^n=p zN6N)ZAD;;SOUY0lT`Yar>0+dwP9OV&j{O`)DGs`L=}U%p05UcG6YJyduX~h?P>55k^s#<7 zLGJMZN7nbQl1ZeG?c+a?dn@C}`i{$#GKuuDKKelJ8zmdBK3M%3Sq@{yK&i7k!o|uj z?WH%~Dm!ja;`E&bxgn65spR6-$8N~gLT1w7#QL6sTnI7)hDf=1`k1~v$ecSgu|96s zngN;pN-mzh-H%O89jf?l69ggO2?}tn%9p{-==n-9?G@g&=nrGK)uq zwE?$0Fe)mJ>+EI!1vHYHc%tTLEE>`+DKll-3 zigLno@zS>pG6QpuoW8M;xgamGz7>e~QpkK@k&BhSgOEFEw8J>wn^+$=abBckKnfR2 zUkcRx26C^BNvx0Ce!f*QN?lBQp}q&lI*cdACDu0{r*A9dHbZ9BgmApE>X-T+hRhy|T&(ij0=W(o9ma2Q(8U|i2f=R-WKJoN za`Eh$`Rxap(!k2DnQPRM*RP0Dc-Y^?g70)F0f zhj9xIx_J3zeQbwJ+YBieuRrYrxqm>W`%EbpuYR{ft}kQ`DYnpj^Mk z@+0eWR!Esd`VPahH{?#QOssDy*M{~W+js-ebl!Ta<5#GSYHj~{sWo04Pm)h^-Fy}hRo{5uv{#A zVf}7WG9ZPEr|%ue{Wh3bAN#9AN=B)R+5d4qd18~p_!tLWy#Ai)J7vC<5rR0yN+0cS zAmq+mkXRqt$fKyGC7k@eLnnIq}D7IK#?JhHx4C6h=W^ZOv=Zd`O^eJ?4Q zBkB7yS%ZungcnKM=;)|UafLdb-a zT)gygesDKr7OhUKZz$v*S27@li&Y=pp=J-{4z(oKcOf*Kf1Q+3>SER}=Lb_ESJawV z-xZKs2AMCET)g?(A;?{HJ??97koqVW%U*Zymf_Aam|oDHqRPW*~htAoH}6i)Sx=q2{-c`Rvwkys`2-0{XIVa~SnF z=;GOn0q^S}bN%g7E?)X3Ku4RB5ejjNRetGElX?f%k$x=o#jB535xxmBo;#%+%Q==l zu9rLsnVVRUaPiW|`Pvr9WZfm@;@uyyf3Ahh%)1loqy1e6nXi>xGOlB#k3-Da_c)BZ z)+g3iiSVyOX5hV2j^|kVSbifRQ+8isecciMW+eksxLEo;Q1dY4KED6R`c8R3$|Taq z^!0<>lm`>*TMH#iA=C3ADHpGOus$w>%=m|otZy-7T#p=C-!#bNJ$ht)O^|Uuc4U2p zkQwol#QJ`XeAGgw-{Vp)kv-oDnX8{jtdHyCKUFdyg^N|cTp#*9*M(L1!T_tsg#S?|FuDG7-YUwa`F0uVUWAv zX@^mXgD#%F?eJ@c%($N&Iem*D^O%y0r>_nAeg&ByJ(E};)3*UKpD4L_`k212A@ka^ ziS@DkzJ<(ypC`_58|3mJlk^LlKFbFOAR=D1AEab>EnJ5Te5@3^vCG065H`TW3%M_p zYznTik0NT{Lj~nF$~c8C%B5jnhHd`_KmYVdJLEXuIOjRcBXH2My?J8n%V4>*LFRyx z>l{ap_B{7_d-}|L$QS7$B0l`O405+CS=O6~m&HN><=nu>A+t@%Q8VP)WPZc?(!hTQ zG9N|Csd5R+ab55LWWH2#I$lwJVL9fb%P$?qc{u12$&G}}47;2yAJkU^nN>l z%>9vaQTbqdeF8F1A3=`sZi37XB^NIr90&JPW|J+ywtSoex$ck|uH+KsV>Dz+BITm; z!TlANL1vzk4%sa$mPo z&hdh@WwVyz)!T9Hlsmqia$VXf=W3_iN$r$7rJZu8w?mHoY40exLXX?+9xx^+e`5Za zg8brwoRYk8!~6IOit~I^y+tE4hh${*iQ%7L;w{Q4nOx)>?aeJ6>znAE>YX?;D~4oI zQ!Rf%JQ1(Blr=0ISuncNH+o@hSxul~w7##VSTZp`cX*$g#`zWX4Z%tq zyP$Y#UQx+t8+Y==(UWotyv2RoY^tB*cnHT_!{GuLdBbPPE!wl>4((aFf!eZ$fWL88 zV?%}FsgyL@F8fyo8fJ;)&5GCt9Nx^@zpngpW4JNG<#6+X6C`530)a(%GsvBXKZgYH!UW{Lz>$u_beF)gnGYUx51}7D0chs!cF+@TKLKMH z%9H{xV1F+heoI|c7c2_~>hO-(L_{4ds0-FL3?Cl!HwMM^k^Tv8gu?&4ord{#aBiRx z9}ATKy!9XwYVwJ1JYX1=KRMnmBNu0;D};lOTDBPrOWXmafaaajNoO$&*j>U_+NmY9!6R1oT>im99X5x<&}NX6-K5bj@gNszI^3T!%C#Sk{1d(|q&&)pZqkK}saJS^EmT*iMeWidTz-EY@CN zGL%TjdT?d(!0}b$9YPVyEG=ADU0GI9(Nu#ZHdW)zsy;|VQ2X)~r$9YkBp2<~lwrQx zv|^d>T*D1+wGJ68+^LW_s3mI3nuXRebqy7MQ9PB}uewgOVm$UnY4wEdn~pZicI*bD zv*ND@i}rjkknQw-;56U^z)Il5KtA$$6o@uxJO;cI_yiEN@l)U{K(yV^Uf?r8TKBWS z(-6mVz<$6@z^OniAB4D+v>Aw1a^tr^uEuNw^3Lz~z<&U@0}le<1ma(y#vg%`fjfXc z;Gcl_?XvM_;I+VAz^{St0#8CdcLN6i-v?d{`~Y|<@Izn)5NVC-5BQXkrkjF;j(s+l zC)h$i$ALKU4bkwQ$8l*e3}x6y_G4h-&>x7Gy{p^TZR>Dmc!`#7doJRL=(d9pspepi zUt8&K7QMN+;{)5$n|DJeZ#IhRI?(~4F{Wxmnj4Tj`Tttl%LW;>I5TgwmlJUXdl2rQ zU@^Z3fmuNGslsml1uVrimZ?Kkz%PNzfL{U8mm6OL(I*?|yF;)k?h_8ZK>+>*m;|K# z90x>Lqa*Mv#N7$V{@n?@2$%|-0fhaASms@T_I~{@sNW3ur9%(h30))m^-TEN`*nuN zhAgqau8&0ZD7tp}heW4~=x>{cu^5Jsz4SSnk7!Yxn=w7kXUmu(+#tjZ6x?2~i$;4wuYEjWm;vx3US#cuV!p;Vd^o;t5IwzQq^2_mGhBby zZpiE`t_pV+WKko(E7{%Pdw;kqkR63=w+(d*e05b-NEU_-IZ3<$*~WB|AB4&gOlHf% z%oSG8`Jrs!)q&cnoC|WMglHnTQr4}x=Dd-zmM%ifCUeECkHg**a(1L9AVX@s1sgq(XnC%c#(^(D(oC$B$A*-s( z<}_kr)=?dkU1EN=UIrIu);Ze~lW~jU-;G~e(;n^t4g#(RGG+Gx#XJqzgzJZZxVJJM z2Cf4>0(=1Y81Og1$APZ_p9JzgY6B2sw(&HuGva&}I2rg0AZ*@v4hUN}a1Rt^*T06n zuR&Nh4!Rw-@zsm=G08ShVwh~m5{J_Ogv0n6->&7@D*9A8x-w4Fu?;ErUCr7yLblJ! z*{O3lq`h<(_VPb(-ZZd{Ft7??-qiuz)C3y{X_=;6^-2%McOW|eOgTk4X*1=YS z79#Iq+^|E_(SF!QdV|qj@oQnD*|@#}$ow_{rvrmPwvG9~Yk>H}K2uL5=h{s`C)cr_5?43|^Hn!*xbJ+7|-vh6Mf-V0m?{2aI( zn1iBO0mNb8J|%QJa24=T;A$Y(7+Qc^fY$*(1zrz42wVdki2R~>LxX^~0PBFa0fRv3 z3M~NM0kn@j%Mkwt_2S3EOr)29JUsh399w@7g z_gMpvhhH%g9|JN)y|uvxd^}8ig+YHUCNmS?lnPqovwa8TzZ7SBhRQGQFN`8vpTsg^ zAL<8Ybq66_{5~m08pW)it z42@aLw`B#0X)!wPj*1W%a6gbYMOjSAOj@!DntPe5}k&lP!w(cq|js zu?*OrU`7T9P`djtmtna)4rJLp5o2zHd7Kyn%=~f;u-exigvbAo;@g*+wU}0Ov<3$A z!f%Sg(Zw>aV;&`}i*4y`9K|-C8jeA8_ha~am|fyT%4mt z7?+AkPu`@hT+Z7z-pop4vD*ssWVaRU01&pa5y-sasclqWggLeNtbv)0`fixFTjs%S z@UXW{h8YGv=J7^uJIYUgF-kTYe%ekHU$q%2FkF0wD!#+2ZL&RbqG)N4)-kRYf!~md zIFPP`WDu7asWn>5 zG|X0{wprHET*jy!-rn+#xB)F5(|11?+UEOxRs4#Tm|Dz+XLv3ym!Lfnye!cnvfi4_ zLR4kLdSjPs+D}lJ`n3x#sVPj9}TQ?hVB6_0`i^{ z_oboNfQx}20DlCu*DGYjm~B=M*C6|$Ud?g)MZ`19+R?@TP*?c*)_3~oWw}+mtsCXH zuVYTwze@~yOlDb4wb>~1-w%280nauIfzMZBMmv0X91qdj~<~7}u;C%5(5YE>%qZ<#jG@VN=D!58lEGgX2OMnM|&QnTwy1q`G>7 z$pIJNw2@s?k-y5{;IFOli%+iQ$YELB3tGozmILk3IxhDIs{lOQ4~qFG$%`>!8MsK&)pPHv_TmXsiWZ2D}Y; z1@I0a>*G$Ky^eWbY$@NU{Rr2>-(JTIgK33dQ%T z5L(Tt?+L~**MCGjSk}M*s_SpJViH)EtUrvW;$DfoS5aRqXUvB}V}Wk~xew$m;M2fA z0Jj0(0sbDi1Na$m7cd#R{sQD2_g&y<;2t2>@{NyxbAfw-%YmN)(O!&wz?Xshfv*7n z21IHNtkZ)S90#UKrG1fNUVHnD!0L_0nVPYR=S~GmO`r>Y;Fg1&LL4|g)8Wv|c6#wQlyjIAWytP++ z6&@HU=sH8rtmN?Bja-M@AVtKP>1Lf;pA8?6GGShvz_Y0f$hO%9$noj~Afs^sF9mi3 zRsl~0)&ueUCA1RQ6L>H1RN#}q(||7kPX}WEfN>`9kHFr*Pl0Cv{|!tBa!z>;kmcDI zXs;vgabW#e>*xe^%{sabhyA{ZVJI^i$B=gP31%Hls;iwEXb3iyRg2m(ql6Z#YgcXQ zb~W7+l<8s}uwExB{sqW0(|RGW7qCB&buj>ld83g5%mfYu4hLofnXkb>ds$UOcRKvc zgx`n3?R;GEnq|f3ZgzWSnDgOx32+$d8UjL73`pS)`Ipou~GEJz2<#Vus2Shx#|N#33ab&+$6DM;!sWb%2-z^;{D zC7&&E)?jUL6vd7PI*RVHiLzH6Eqw6}7$nrP7QRNY2`p>YKc;KkUnksf)FaFPB48~Pb=fu(_g}(G;piw z(VhlLZ@WE(6q~?0pgm#O63@BFD@OgYUN9Dh#sH@QrvhgJYk{+Xi-4GMgcbvRKqk5j z_%mQR@Xx?XAX8WcWFI{T$hr;y?fnjmmz8H$AjeT_AAJ-2#@WVEhM^3P5xfvC{y5qs zezs6FuK2rl&AicPhwH(?tq&pcB- zU95bMvE|zXIqG9yesMeUjj>7ZRx-;ML9H$no|oTwx>^(AZeg~KAP%tsNAAp#9g}^& z?tu{VjcK14KLExXD&KDcnbx;re=6_WC@?WG@OA9&U$FEod+*@*QAoI8lXzxF_fX}3vIk4Y{JPp4Rn;kLC$vB?Dk=>4R<0ez}5J~LN5WA6u z5t+Rg6j@!YGBn>o2tv@(tE8c5c@N?tTQt^iJ1ey4WSUuSoq(ei|JS%rV?Nq|Y#W<_ z)xZ~lOMzQ}_W-eG7Ghq13$&MC9(2xzpXs=U+8?FK@}%9R!r#7bz%c#cN6cwQ`Bhkd zh9t^uHbR?@F)8<5*9~H<3~={6XQP~o^f2n>vKFTk9>jq=`I=lb8JEkP+d@R{)8Y!b z6j|U8%$X}UO_>$LaBA`TA5c?|!*nbI)=MfFm5R9scFOYk5J(&U2sj?N7fAcZzK2i% zxF0wV_!*G(bpUt^@N?jUz<&TcLpSzEMAh4m5h2=xe!hJZ>cP6+<2)|f?iq$tBVt}V z>Wyy|V5dzW=)-QCx(4y-dwKK1m`!JC1K+j&j^;tx4;D6tk#Ro{v;8Qh3}X8(HY0J3 z*6a`?b^yW6V-l2uKV@{ zD~LnxZwOS zx#owbqr4qKjx?*jq3&`%$ihIH(29V{+*di*@v|TGrUOUmanaK9$%SS6sd$cr{#85nf$X<00SEoHaK~fs0sBWMFc+8#oCxd; zECqG}(pg1LC(IA(|F+g-!>K0FDNZ1YQNiyG5aUfTMsf z0zJSzz+7N|Oz84}3xK16cL2S>O~5h0cYzat-vTEBPl6Q|0M7(Y24(^affoUbfQx|B zfm?txfCqpxfn8vAmjKTMUIsi5I2-5zmI22A@y=7I0q6$?fpdTl0|UV4fR_Vb16Bh+ z0M-D%1Y*Bo=o{b_z+_lsBk)up_8*2afb)S_z-Hh$;6mVKz{S8uAcnutLf|#P79e(s zgzg7k3w#iWx(WRPcpdO{;2Pi`fHwg@0^R~V4tBj3*b8_oFbjAGFdKL$&V_(35cE933jk05&e+C=~d=^*&+z6}#J_lqU z@I3Hl;3nXcz!!k80e=O29oPo^6u239JmPo}$T{^EU?%Wo;CSFGzOYQ2Ydp!ANVxzGvLR-zXLl!=K)|c z@E<_DGi3Y|SOPo<#JfGlzkrK@Ujp%5-S`iXd$zs-?gM@c#4|s(*ASj>86AM5fJwj^ zz+~Vhz>Yxd+cr7@9|NWU9|t;tSo<=%0N)071%3r|0ckJYfOZ?ivmD;XY8xDQBKKT` z`=!g^XI~Fw816YBj%kMt^8F#2OfREb8sjpZ#RSo1bMLabSMtAilfj7#=gXFd+U8w_ zyf2_}XNqYf%{|P^61?!U>_s9=eCw`|b5X3&^f33@OcSE(^%S*Ph%%Zs&08pV;WdYP zvrvF6SK271N=BvPpNzU=nfC;a2c81t8u_WfDqt_*6~NPhi-B(7VCXmt$oB`*fsX;t z0X_{p7ihPIX$Z%@$n1}}ro-xGJ#kIqHXMU&YdQ==nS31QMcP78{!iXp?dO~G-O^08 zkhD6CNM>hq5lXS9jB5bl&PFZ*TOS!;E}m!5RD#gM2gsA-Vcm z!D9L_2N&xlvw+lc8L$XA8+bdg4EQ@>Ij}2qQ~-Mb{lL?JbAhvg0pL}@%YoP*WXuDu z2i5}b1Hvvt9|9YI9gv)$eldhmo-|7_zH_APoGgTqtI*gQOdd*N=E{j?v%;Pnd*%Zkz46G z#TbiJ<>Zw_#l(y=DZLD&uOvUuS2!_elGlS{`}r{5hqo-7aEp8fe4dBF#M#Ya^oIZYz387;S6v-w z#B&I#dQ5d)8UDW=EJJUd;^HRna@AuEY#xaAlHxjF@TN53kLeAye13r!YhB)MFyLV2 z@ZnAPHqb&Je^AS38zU;~n(znQ3!7>i19NKqm2SM{a4}YEQ(S}N1gK*CHu*HjPed__ z2z-+Q)mRKlab0X`m|NC3cZ3LcG5W|9R}vc;ej-~RZ14rKEi=V6Ne9lYtE*OJG(xEJ zH&@{GbR^XW@r$uhD#dlHskpqX(x?5=U#7T9O)pzEtLyMhqL_JQK~FS8`Emon1%XDt zPb68&%Q)XLMRa^j50)=dT>VTh-?WCZdMtYe4L8`&n{1}Cj7Hbprc@qO@3dh`k>a`zjYECvqY7`#mj+=KRGkV*d~N_gEUm057k_pZ zM*CA(KzXn@P*Yiqrc%~`cAMhbCE_az%n4NH;%hl!(`S@y?2Um%ejop{ifzIvu4i;( z6%BPhC+Rm@#D+TU2w5U6K^WHH?bv2-7Qs~h%6haF)TL+(O6yzymaiwgXSR;Sy3 zIDjzQ=Y%HJ185;pDiI2YV$@46j30#V+FUkTP zU>$o1`~p5G)6Eh>?}zVBfP=;?{@so-D#dkgtfYwUlwH;}m~WH^a~tZ)D(lh4{DozK z2E3|};u5xCujsHfWQnqWMd%I}fVhL@EoX|WquD1{;swP@(U|#aa_nzoVKG~phtISR zHvYR&F0$Q(M-w%eP~L;)fSQzzhrqKP4`Bu_-TC*fp~c`)dcFwo2o>E{2a4LVG;BF&Bgxu zvIe}0R6B>O;bnNqLv#tW{68UQh`YgGRZ)kJ=!vql*|=GSY`25#0bT7Pi8ff%^Y;xKc&iU~^i5WR&BbZK00OI>e9< zWwz$xKL5hZ!BXMs$kBSV7<+~BWkBK8*aWNUF5B$t&Ty5gmgNe@THzW#kEv301%x!{Wq*_$}<5d=gIhQsn4!DDbUfYDq$bwIYSU$st=hOxo>w*n+^?`~p z4FNG@lASYWNW3|Tnw||GZd1>yYsB8C6xTPRtFn1pZQSE~i2 zbz)kHPLRE>=wHOt)!t>v5u4q^J95Ak0|f_H+_ua1J0^dkSD61hqRLD7aT1Q;7HjPc z(R?;_U(MibJX20_{YLf{(T%}Aw1~Dqo4HfOZ@%L!-i#N+AeSU8^9C{CeQ33FOFB52 znJ>Cgk;>>#iiu3M(K-tYM&qt1#kD#9oLe+RPCK?oCLwI=w4rLdZ8p?3FBCOY8Oz67 zzkzC)>)3|6rus(FL9s9Osm_#L?(w)*QzP^yyju|Uz}u_vkTglW&MB>m)1V!evdQMR z$BaVsdzfJxX^y*kUiQ$fJR64`DG7_cM70q)`d5A{@1WK(oY(_f7pTHD{!Me0{7Qxj#IAt_k+*O9Nzhg z_fFWf?Wqr*6W@UVzqb1Pr!P9G`NxCLKk>8Me*W$CSl1Tvr@e4y=_%8Co)ca(KjYBP`mQv_cf>->M8R+L7w^2$ z)qKt$&;Izz|1AF7WIUS@{6n|8bFaMYiiiL7>EE6@2Dk z!>Qf}Kl8DBo}?w!Bt`^c`l?wh~i3Ox4^{E`P+e)7OIzQuvntNuFk z;WLy=N7-{OhN`{`-S>{~Zrpx*ktG{xOdp z+U|b)%Ilxol=;R5$!G*q1^?B7c_+WK>6h2unVbH3kDN(M@C;1yKP@}F;dh_BetE-+ zOMCX8wNgrkTZj0F;JB(KJW@ zzutdfMO*fmzb-BM<5%BK$;C5D!JmB2>`(9Rwsp<9m!11|-_;*3!)AHGf9$f3JuXZB zckl5Ro%!dMsU>Tn150UXj&27VznNBj`I5_h*L6Iv^|M;EdBJymcHI8ozI|)Yl_y`@ zd&z{Kz}9XO{OhmndFbw!pKnce%`x8m`E`HC9#g^p&-Bzui}oCMMoQloIz8JK{0wXD zSSL(#Y$=_vtg1Y9`yba=?r~=F9map6ANUFE%cvMW3%e2K;AL`m6~6D==OG0``_ES$OTVMp4a%CS6-1qy!7S7x&P$|}sIy;c!eq zi$^vTIda(3cr0~)x85Ye?!?PjykTp?l56`bCPIg@-MaG2vBX%$wd?PxNGIm#Ee(t3 zM{D%q)%2sB#x!FdgVEz?(^GM5)JQEyU&0HqYw8$`_RaJB3oGXOE9M=2ituF^AC?~i zN3Y3WgK>u=#?h;4K6a`iHMPG32~QFdIN_;NW<_01 z4Ia~`mt?rp{pI!Uk$^zGo7dUy3*46p2KZ#ii$-}d6uu+f?)0pIO1Pi!|K6G+0+wVl zHO=AFWLi_xj2JVmsmXN9)QB926O)RxWs9_BW@NZyr0&>8l9iqP14J_T2gu35jG_Pi zoMaCE0g5X#`-jNM(3o}d{aVqnQa9+2}Ke3|5vBZfnP|H2$lVCv%{!P-kH9 z4-ji+W>!?WWtv49(Gh+xD~he^SXI63Q?mz|SvdOiqMMGQK1m)zr zWk$W=4N{bo?}za__0Wem!UW~yyIw}M;1w&%$@jR7d4gB2D5p_~=V3B^C5mzy^?0_0 zZ#N;oe5;I9s?nw>rxC)FDal)=D5o(L#Wh5PSf;2{W2K^;#x77np=GzCoW?#-O@jA# zMLCVHK+P9Cz8yx&X&jH|OA7?Ai=v!HPf*Q**Go}O<6KY+1@8hyIgP=f775;PML7*G zs7ArdSCrEz0o5RQ(-q}3*5f%6bCha4peU!&hG#!R!Rusn#?u~BsYaTjoJIwxs|0V3 zqMSwpsKtUeUr|nD38*UtZ@HqJ#)=b6eXAAaG@j7BpK9I#%{!=hw|B+Yji9fSu}4v< z#$H9?9Sc0=#^!RQ^kPLh4emf#B6tOgavIY?@m-r#W0sV=E{=kMCr3$F_e`$ho4N##+t0L-RIi zUYq9i!v2+!Ld#r5r5e?WavHCJS}iocp(vCZs20K7tthlNP}d3G-xY=S25ObyeWNI} zH|&{MDR^BJB10b zGm3)Mfs$coDavUa)^ga5BSJWhY)~E%TP3I)gckm8j1+1g6yJ|ZHMS_qX^g`QUks6I zOjMN9xCN99d%L2XMqfM&mvR>>%4y66m4mRIjAs;;YHU=L)9|^aZ>mwDD5vqb=55ft ziM_G=L}KGGK>iK5VtgUS;ju2WR1u|`o&V>hUq;hSpgQIym8JE&U( z@1Kft8sC88Tg<6OhqEN*G`fJgN$^~XavHrr-6(i&MLCTzpqPSGW4xlA##5U2GtJwo zdD}E^Lpt7CMc7WpVMU?iJX`XdMw6majfI-GPV?4lUdcIl&rxVuuPF4uigFt6bER*p zk*+9=N1(=t5Ze@$YHU}O)A(gy>6>c&T2W5pBhC9%^Nu^ulsjHgh)wg-HE$y*zUSG= zNIqXu7{wLkG*T}xd0iESQAqQKYhJ15&CtAh%?oPYAyDH)Y@;ufRH`vfQLuZ>+oE{~ zK;?@NBl<}y)$l0FX>8QIO`3NA)OZ=9zoZaCQ3#=Vn>6nLs0lK}07)T)qR{JU-ZstS z=Tjz%5EB)J@k3Eg<8{q@OY`<>-hRy+nu&L}gqCHB!Yo5ksI4sN3)@f>#tKlAMTjkm zN;S4B3iF78;(s@=_Fjs@JOb2h2$5=BpeWQJs9ObZxS~)lpr|?3*rX_@k&%u4BqFxO zib@qf5hBlN>;Ugh5n`93oW{qX)(PG|MLCUsfx1iZzEYIaIBpPj;0WIFigFs=LER&G zJr(6N&H}Yw@Xl3~)5rpKuiy<=6$Gn&S9p$6BLDctmci-yn4+GYTn!t_}V1$fe}Jc7$Fqp zH1bAD-&A9)qMSyt=1tSQ3eB6Nd5blVpS5KiPGj-K_*R36ZL6YEjctm;7&=P&V&#2Q)4Uy;w@dR5Xx>51Gjhb2 zAyK9i6@@-RQBLC_P>%}Bc}!7G<5^IT3Ep#xavEDe{Y3D#D#~fR1&a4!sm31_sq*((a|T=RBmo_jRjzJzAX zautqo<1P zW4Vd8k4ewb=Jv5Xy+KUwY{uiZn7`lXk8LBv&u((}%{UKR0)_j3Bim2Ay!7PAlxWMrS*!P82dWH=;;30@=iYAxWOtSu?43U;>?Ca)^p(=rb9-j>47t4jB`Oz5e-+l2QP;k{LOZ)+`BFT7j5ZH27` zyQj34hKdAZ>6XsaxLyQ#Km>V21bMvGyS}hxLT4eh^RC4x2$lZsNYrv(BZUQrU@BWh zc4v(5iFCI%OAl2u%Xv8;9%+IyE0%?}N878A{b$$dp1#y970k$EDJ&04Z34}}qo|D@ zT?cp%&hM(q$+f%}So;u4dNMRQyq4%%&i_H}n;-(HI_Nq;Xqw-{%4E=-B70s}dVQjk8pEiPJ@5$e*tGL?nm7=6ACy>JHAnJVwnZAVSGV5t^yY zy42=cP7Z@ebSlR@fcsnp3_q1LCgu4Q2rwJ!Gn3QbdKZRO<@(-vFT z@)AOBi%<%zM%v;|k;kHz*9u!tVuKM{rqA@D{k42>$&1~MmTyJr!D}}Zq)`U0%|frY z&`c2TvFJP&zW7paehqfGR|o2`?;0=C*EQg}sk+f`;Io^)%0N|>`bk5s{#gUt^R{j1 zUzhIhE*keL@BUTZ1FO6TS9uSu@*cJ{^p*lN&$Q%~C^R(fg2PKUr-`hzlnVYD^3hV$ zyoZEE4sP+LK)p@97t{m_}r646Ul zjP!s-pZ5Sb$!kP+_elt0_7#XwB1yRs8ref@jR%p`u*UsXjr*lWito#e&;SlQyo8xr zx~2O?N*(&!l*Iil|9{5*mfwqgZX&c>``Zb!xC>kI`ijm=q>&w$va`aL;=V=f*-Q`F z!>uoBQ6Xio7lPeN!({Kr?ya?THtcAM4z`w;2$e24JMUs+YROB7LHC-{Qrz9%8d|nW zx!pVODuE=5)U4FyBW%}0sY#6+Efd@j73Q=&Tk^F<6$>v~)bb3eLLeGFCFfs-fXf*d z81$cizR6%4mLXh1z@C_Wxs;?51f_<^p!8s*^sxqIy7#fS=Enk6e=(H3v=qd^gS&j!B*=FQ%3|!t9Y9P3Dvs;vywFKNUM$v^}3=pCWBKvIFcO%J6NMxV4 z3#KBwMHV(h7$Q<+2Sw7DajDI26pISuh}J!mR~u=vm2v&u+wRnyj_cl=|Xyn(4-xPHcT}yP@VteP+la zGuuKl4zn+1a!fq|*=^#($QAt5jQpRRr7vZFn#EHl|H|vDuWQUQiA=We*z>8S`$tSg z>%MBsb6t^cYtu$Qi#}~a=T!vc0W|0BVTpnROE)LYdnE~W*mBJ>G|IQoqi<~~*t+zuj;7wv zGvo8#G+JQ1@@>-UiX6f(@&0oDIfG%!HW~Lx;2| z-6SVH*SJ;4?Lt(iy2T>8(VA{p3si=*N=st42(NnWWl_=AQn~@AxQ5lZWb+yrn$=_x zncXN?wiK*{Q3l;2K!(;Cj!w*n_no#;7;T#YLu#2K1_|_QE;U(}lWP{t+b!OeOLuor z`U7xnlOKU0STqrl0O30xS zi7xLB)Lz%0uUvwL$R>Lij7pl+9r&a$z9;bIs?ueG(ILzTy)14qXxlBN%Vg_Xx+(1t z0|ZZRDF|);Ye!V=(oIgua!Psl8Z9DZ;pIka!5TEW&S+@tUeiIlLH7dPQw--Vd1;tW zY@{KJYD&uMyehBrzTs%NMr-LB$aaQo{D#|Fx)BZ68upVn4x_#1A<8)2w;OX_PUz@1 zqL@5_!k!7xW*;otE?)S<9~R>Dr_m*Fb!<+-qU$^P{~Hs?a9d9E)m%;qd42L1+f z+rn1w!OHvLW$>O6C35*}k?EydQdWsO3M@0wcj*fp#f`4ZUcp5RMDyK3ZpzMH=`E#u zTgJ=F!WJ~jalOJ`l$4j4j-dePZHi9lj!}=pkG|)$1{a-R>sne%*uT{qLL<_#tErZP z!d5ghO9E`ZEn*@flD0}rRQAC-IALM_T3Si1YMq5MvWzn(00%2qb)n}BUrWLMfv<_6 zs)J3F6IXG!5N~{os*ezK>F(8yi|<$;%`$Nai2C4#5u9f!jY3fosyYZv3(p3+j&d{tWU%4_NVYB3+UsT%r6bsfZ-RxL}^HuATu9~WYN!vLfuGj1SvUDBfcP3xIv)3A%Wa+voJCoP2 zae3FtZ0f;j-<`h8(7#03<4d||1rd9`wPZg(oNZ zdW*}=I!;;TY#EolYJ4)6s>X{t{y)sU31C&l^*??eFUA<61bre})TmLhB8EjpL`{Gw zC{aM;R<_6@K{g>EsAv#SVvNNq*1A+&tJPNORk9;VUFov&6bK!B}Zw?DlI#NbGB4w<@(!$oi+a_5Tz96!$630G#AecsBPW*QQ|71>%} zj`p!4Z`h>V`iiY`W2Oy3kM=ofrf7TQ4sXSOW-` zoK1IUU%%J#fvD^s{g8(J1g#86tP#imCS+QLs}Go3BYLTtKu8nsY)%T6?q zT4Ew&iQy_*pk4^Ey2q)jzARTMTC4f1X(6j$aCsJ@2wSt`+8Hf`%S%a=^b3<`AVf(U zsG{YXGYS`9F9s@adA3#!RMGO>d}pA_mS?Y21C_TdXq=8d;4(}N<*95PT_V?}b&^&a zN)d)*EuIk$}! zalvy^n=^;7Bf%SFCPSrmjZ~kD7f*x$4i6ZgGd?QTO`w}uZn?^AiZ=|SBmlKCh8S0l zLGb21Akd?9I+aR`OA!p*6jm$a>F{CS(}#9|QZI=H6OkB3I-GAu1~ zHhVt=6|l?mG&`Rwv6R%6TYapD;SqBrhev0JN6_}U0YYW$Yo8amb4qMj%I++(0sHPl z8>EZNVGYWX?Sed4zMT>{y@D)*>6PsZ=50^T>jE8e{zGQ*tjvXp9f-F14bGpW`};d= ze;?UP2R-oXJJxdsxxRnbFV`Kn%@j{umj$xEV_ju)eOXRj`TO<5^6D^nC@a871nlYX zMhRal;m=FBdsdZBam9A&YDtPaG_1yL;3hcq@@gA-8rNarG6q&)xG6QjqE~A$8^0YT z2$R1VhvbEImCM+nsJMrn#>)HIX)J$e^D)Rr7_-QjL?WgOlU5K}ADY?cYnXj5-+p1^ z7{qS4F(Hi`peSh5;jmKr?pVk%yQ20O!3$ePnNz93;{e=&?OhqoXHK`&WR=@5e02ESjQA=d4AE;J!fk%&1ot{%utGr)Gl~>=2aLh z=;X9vXf&NQSs_%Sj7slmQDe;+^%d`98ngvPW(&-;6&O>V(D5YX0nERca)Z06uY4Z? zEnwOLCd`|1Zj~hlbM43uw6PdvGa|K3Bxbm>iQE_xIcmY$;+PF3e-~PPho2rs6^w7J zXH{?^F2&BYraqnR{F-mxZl>1LJABWdRf7sEF}YQa$*l@ZZdIm$+4U|M1{GH3xoIj| zth@*Tc%W5@Dd=)cL01$4bH;|MOlun|Y@DsR z%2^z0!@ZK3@%oHE^y|hy%dht&i@M%6?1Q_py=|7BcG{c{&H3`xbaN`nh4Q@KhUvIS z{>xCmMsE~-BK!QhGEZkyhczuMT#I_2Qx6q+I-LqyK0E554Qndj4o@zPX_2OpDEN7< zr@)R^$At-eUMnz+$Ym-Q%??Fa6|3NeYelY+mbosZ#xwVy7Hk=#10F89wgVn*Mr;Mc z^rb79rjhbIep`p`Fc#j;_;l^SOSn)(&XDr*Et@;zly`BCJi2GEan$n&snG6;8=kPL zqB33kk4h*lXhb=mk(WQzQ27wbPc!-%>3I@NQf>k9eGu2V$rG8mv^o{R(oxDda}{r` zbxLwg!(iDPnRm7Y?Xoliz~(E?nsLo5ultmqb@SirBtd2Nc(z+O@;O zgF15}?u@(+PxSA`ii3|H`p9#+ZNaR3Je|WV@ljYAzTnc5pk_Bb0j(cYP}k5860zRu zjNxUKAE#+Cg(9m4fpW027#7}evI)73>YfDp3 zUQ?HwLSd_9p2mcYxG5(Txc(hfm@X_Y6b7Lz6M1ee7P5B>Y>8*S{Lxo~L1qM=~X;kd5hk~p0I zlqp+IkIBR?7jwzbMrJ0pOb&R17TX1RbVAesr2P%X$nr2SsN!}IAxm+mEE#lXm zQD}qB9qN}7bF8W0X`UwM9h{E6J=s7S>x$t8^^X%bH>0 zy+~mJT%0b>Nx7(0N-37>>o>31^de>=kiT#lO@4a1BwV(Z@`KXOHmbKJAVF^o(a10j zC5dTXC!lFI5YRLm0lZ7OicD{H)^@4O9*J_WI`cV3JdzV-L8TVvK)qHdDH0}kLf`C=TQv_N?0Qq-{j6Mb=tB*WnFVUe0k~^m$xpN9??aov6Uv=k} zBm14FIr7*9)qD@N0GcM4Kj_fCEJxb}xww0Ur(rcC3mcs_%`oh5T5!5BDB-K+ptb!^n z8pb?`PL+hQ%Z2C4Tq*)|22eYK0RW}FiOe_vE6^y3Eo2uJwul4@%#)isC+8aP7IAA3 z#u~A}mIJoQcx=nwTF&)S7`n1e9FW&kTF}(xdb!($6VVyqMI>$l()$dr zm`%426*G3jEN+odHvEDVrEmT|TVK1R*6>Q~&M{uOq0#pCF$YUAvxk^0+12P8ik1Kx zaR{$W1(;GGgbqjMES}vdMrI~iym=%oN4a*r^$>TPx^CSU&kxa?+`&v%m~%Z6MIyvA z?_qw0WFbi&l-C0`=WK4*t1;fcwTqfc+_$>dp{cX;QOiBN#KY4)T;kzE53fV}=;U~q zeFWQoW+QKT*5MW`Uhd(s!Q`58LCv(9s>%EWR4{J*%xZkl=ky5^W(N4U&%|kE0d~@y zRHi5W<)lBKvdK?bP%~wEfBux2Suz>F6<~z8jUD#bJlTSIsMN0ARkCs+mR|9zgBXVC zWMR9SJvoKjVc}J*t>$gdsTsKG*R1r|Dwn2*U|1+5tA|-VR1{(blC1rC4bK^Ov|qx9 zB8X6TJ;A1*+UV((LzU_1OEkJHF@CKXvD(Ws6?By9WR>0K^X1a%RZJD>xc1VxfgsbR zHy`pOgV5RFTolKp6LA`!i`sOIRmQbDE6TM?1fiB~sM+n|<(h>!D}ngN?014QB% zY)a~I)M{j5elxCQZj1RK(`{|y6MsynENDrl$G=?Gx-g-O07a*$Lo?r4RefdQg1;qo zaO^Hzs0$4xYTI;z&zon_$>u|(RAC~Gy2EGBv+!XCp}?EL;)5#5f0^g6kW^#|U2liE z=>lZL(?#P2$cW`Yk`Y51e+2BJ@$)wQ3lP&!q1<+m;`i*oDhQv0HO$&fWBBS_hJ0S&Y3DhKD>5C)wM*INOBx}QkMB4FTsa-`?R3eVzyTN7@p&zmC7~^DA&pZ(c9`72 zmEh&eI6b6c4MWj3#b8CVkYuc|{+;A1$1fH3`gfD7L0J~#(OANRwKBq_mk~i2Qivpt z7vj>0c4!j49+t{PFNjGKa-~ymmiII)<^5nJ+z9m`Jir-dkGI#Kq8%W^W>*uTuV!aJ z%`}D?S~o0Z8$28xOZ$W&Q_Sh20SFO4-itsD5?V5asZ!2Rh-=I9E#6D1;g@AGe5j=# zlGjhi>-XnnhAq?lD`xW3>say5X8H{GRk;Im@tQ;Iy;Wc^h-qkVQZ&8DOXPPpk8`3= zaVE7x6>P_Mc}*kvB8F7ic;{zFhpWyNUpY@C&^J+!HOML^1Tw4>b&RDzZ^6>I=HMx^Y9^L>SOghSj&&t`7$D1P@B#I*?;V}BHDMT>zx zlB?YU)EV+p!7qURAv79LX)gd>C|7$KXoT>+4>Vb5TY;ts+5t3GP##LuG(jn#>4Ny| z=^{Z~MDtg<#!nnt=g=R4G<`*QWUG8L9J<$`1KzH&$H>9%D2ZZHk7-3 z>U~@Yq@hdz9t|gMhe4X>M>P&>TTyfaVIC40MU04()^BG@w+_2}tvJ51_$9+u}k$ z0U9c_T?=%t(A;2mAWci(9!O2Xf@ETBKZZNPerHybfE)wv+{0ms2VR`>3!Vm(9=MdOPW^$=^bqVxvWk7t@CpQ=clnay!t^(Rq&{CjIg6?#*<&M?}q&a&%kmhWD z1z2exIa*G~Ao!k0X%EDDCl%}t^l!P}16}B0F0{mj_5;e17~BVywNfg00O%^9++aQV z1bqmkso#Bfo96u->JFqSI0{Hp&<{vcFvNwP;X?WOdJUZfw3A%-ULZ}u-x(^`P40pH z10-~Jhq?f%HqHZ5`&I#cF86yOP(orn3Z(gEjYDrc^e>>Jg>Ppp57p}q2h!_K1X9VD zI&>wFUgKJzb`tk4AnuZt3Z8O&Yk)Mbz2#`{INHB~-jkG`jP)amZgl8Xpm!v6lS5o* zqO@JGpDTAd%?)+~(wz7`AWeNYpgIZd1H>IxbAy3E^@4^1T`OodP=larfb@PJ1UeA3 zRPY<1)e`!9pnRbq=bG1^o*qRQ%B3&%hEal^^&;X17bPP4Z6F~en5E=dWu8m z0GYPYpxj_OkY3|*7kaHjtAP58lxCn&f_A}^?;pz54hPbEI|=9@2^|KccUc9bcR3kI z({d@0-fu0C-sO*gGzC9)w4XcL3Lw49r-Ae?*SXL?0jcCI4*eTQ@A6B7asz(tS+B7_ zkcJ-N&=epoTQxv?$bHlTwHLG)NOf>OkmiGrf%ML~AFjse0;Dl|I$D{d4F>9`8Ui|A z(1k#U3Yr0=^;IoUSD{_)X#8Ta_FC?9=yM>gl@G>?EBVqJ=>w!anX`a2rHg>{-mZ7( z7N9b@#yvo4)z5)cUi&TwS~t#A%MU2*^lw=oTQAyc|d+ZwFG1AF^){^p@*Z z0%_SF0i-4QI!9aTXzPLcN{oL4RR~J$XWK^Z=6jsb&IIDFwYkB$Kw4@i1N}&7bAWCT zv=E3pe{`Ni!9oid6@8c{WZ8`4%(iFT5r1v(x2)P|S*xXd^D z&})HIL$^3|KTsE3Hx)eL&|08E%#=pf3<3 zHy8?}WnmtWwr|%t^b;5Q7?Ab^UvTLEfVRk8wmU@kc+CxV2GV@h1&DjW<_2AXZWi=8 zkfwgGLoMp<&`^iQ0qMBnVn?fYv^yN_5l4F$NK4P(9QxRy|2VW$SKP1YDg~tXdjOEO z;%5PA-+LyI-tQ6@dMl8|{W*}v{k02y8%X2+8%X1(4zrRgfRr{4NVQhuLT_}T54zBI z9BsSf>+yZtPLFcv7NCt{g@+v40Hk_8;Bbq20jW;8YqIL93P|sW`zPxi%>z1JtNfmF&dKq`ehE~}JUAeGVpq$7vl0;#-ahmuEF+7KYkoj(QAH2)iD zf3e$f*gsim&p5Qtk*G0~%xfh;{PII?FbqhgT;OO|IKHJW^Z|!f0jULFbLj65ed*BN zC023|AWh2^j<&?n-Ua%JyzR3I_l15$Z^ zcYHg5v=-$q%)1I-A0XxH52V)}2BdrofiQqV`mS+&H#)w%9p7_69fa>C$M>e=JNjtk zX9?{Gq*pr$NUwGcP)7+};zDn6p??J0T|(b+p_^UkzQ>>!B%ucZspKPoRB|~`N7t)Yt?x)o?wxyD^U+ci}{+Ood@w7Z0^1Ja)0Mj&ndb~wJ|v6hcJOeV=_(ESp64$uRF#sP7^WAx>L9u#yL&_jYY0DUHD{xgu~ zrhfpbWs3Xip2ex4Cy=(6gMhk9O>?dbo#fCQpf^O`RY0n%J6!0`fnJx;6)tqW3w_t2 ztw1W}3&(fhaW*Zz96A9=`A!4UtBrH02Iz1}>3m090`!I4`2#@b0i}W`9eM^x<-G=^ z@-{j2FCcz#CpXCLXG8Y{QhA2}sn+U8ZpE6Aq4oNTQwwr-fa&Tr^=B66HS{m2zlN_t z^?F|D^`~q%Xa(6e@yA8y;yE{Go{rANb*)9O*s5a80RU+gS;LTAF{ zGgPVup@;_$i$0;8pi1~o1JW219N%<@W&!<5Vq5~GF|GtUK;quu_-+PzRQPUpeD^xO zCmdg+L(c#`E-`)&q>{5eCA$_JvZ|QcTzL@A>|-)6)*jFqPiC^cq@UhY&D$o5utZHt zSZX0&<;UwDZrK~Mg}=rc&sY|$F3kLyOWpOMzYh5gn~)DHa$NGpJ+fS!`7WRMq-_ahut2tO$}nXRsKjDr?is?i(Rrix3P zUvrB2R&Y7L72LOPgb;KIb}!_$tjn_?D5_1OVeiiP(}U1rnK#!{t)} zKEFG8T+cG0vghJc`v-f1mpup0tESSsY>~`{Jw)z_3v}$**^wtr!wCa7yPLVxs;j_t_j<8;qJR=ePI zD)(a?%t_W!$9yq_w?D)X(GRbk2aLXV?UV4)E3VA}UkQ9J^yvYA5`6R{Ywv@PK3pyH z0BluDg>i}(TmKt`t^W@piq;od>qP87h-wKN9HKTfGTK&?b(VDvp(t&x$-;Hm$R#3WL-`U^ zMpkYqfNU);f>k=IC0fb*P7Et#blukDCzfMEK9bFNL23Um5(P;rEAM4SxXqpTIAN zzZU*U@OevotfRFKk=8my`N0w3Qd$p#@cA=G8{%kK*5SYQXqJ0_tr`NGO8f5vuHiUQ zvoj`b4eII;3x$T_<_$U(D0`+m1EFj(t-B9HW{!q!GkPg-G}AE-d7!Z1M|AX4MvnN-xF0@BjPD7 zY#ga_u-8c;swJ%(>nplqaTE4(%=*@=yyV#efmkCMHq+{2nJSVLu}nn{Q>lMvyIWCpol+nStFUyhGSBV| zmBg#_8Q*LchV{+K@;tc$mI-DZQ$@30PR6YFAQG27!#$2rW(J!fq8V-x!lD_DahT!m z#nJb>&v1n%!?CkGt!Co*8GeVe6xXzl>7em3 zgUj;Jne@UjAr$7vT0TD~wC9K{C*8VeEx?I@Gb7Co<1q7mgyVZD{D?!dGaN6^ z)KpKKS~Yn{^_1!w*{z=~P$qgC8>6$) zn-;7t$=u8!i-o$3*z5uW390H*lC`qeKI}U%1K3Ou%>auK7Oj04XEz+^Wd|dud2z@9 zXU?daI&;Fb8B=I=chW{vH$ak@+BO3}1R>T8uw!5y)3F!|#lQ5pNbe8j_k%yc7=g=U z)Cfds1R|~OmB#8`X{{N7GnRNOqP`t=6Y8H+SC+$F5Kui~Tasa{l)@Is^DKZgwNn2h zyNdSn;L}Ad@I%m|7GNA&fOq0L zx>|rpEkKkXF!L+zb%SDUgDV2mzLtiFre%1<7AD0nS(^b6o@=+F@tz2^`5iE(@k}i) z<51(pIL`a-HJ-7>f?(?khPagA6mN%5I zK9&)jD*YLpK3w zFYIoIm?xF?0+6oDTkmM;{?leh+Zol3@^t{xxLq7N%%O6}SK(;qIdp+T3mjiPkoNCx zcIaM*Ryn>Gfb_cm=MW#*DD6wf$7XF;=`ZdBqHx*0*(zx>+ZLy;v#QABFLGEmtl) z1pgrT=wsG0F~5X=D*WZ}E8+hN{!I9fz~`#WN8#T9|1tOlxE|wZ152b$0TI5*Y(nu( zW`pvB?T)s?(Zbyx_dyCY4wZS_z#<`}Rn08&=mMol>zjpAn5JCVm;}i$>v$QA1EAFf z>{y#jMiWJ|(FLH9&Re33_JeK%t#2e7F%DbhDja{JO~j!mdX{|UM&`c^Y-2CN9Ra#^GokzZb)GxGR%^H?)XhN9^;LlLQpi1LF*a4T)CL83Oi z13YpKH4xQI9%yvdXAwi2E81eCcsY)q5zUa7JghO6xHc*=ZTk2bRrqFC(bVx5ivkdw z!LhO1!wlSJA$;^`j>M}bqr~d?Es1oFJ{!}j2pz~HR67h7H%2kLDYqffqfDs&$_ZK@3Ws&u@A#m@mW`E z55ut6g?SdnM_pMSg_$0s4k4m7>raquW^zBHvpwNCYgSen{UT;!9P-?NgHM;#q0Mm* zNBj1*20Fftjf{IvYUe8>kF98~LH1JcnFc;TVJ(WvuAxOu^rFN;#8(IF(C9a7uZkZy+~| z{Phj=RTIiIP$>@Um(13ML~0l! zHH^||7^TGwgT1d=7-W-d=HqCdM^`Q&od;dC!(I#8@sT{wI7~YGSts}^&5-ARFtUxA zz8r#Ncx0!DYapG&WgRN}y$N1F`h@-tsEcX36F$>*7ksLZOX^j9M5;a_?M*0ct>KGy zSM6|B6}YA~^+AHTsQPAuT9!q9=t>5k7HT}SQr^(gRv1MSCQqxXDf)gJRp>^T(y@@m zltorNe5#Gr2JYTW;33w z-&VlZIA&8BJe$+mWNgiok-9x2bsKiZiA&g;k-8-#wT0hJ(2Z@pG`ydY+MJQPu>q@{ z8u$$qe2Jj}U*B!O2NxRfg@y*%(7YKKUq`ST8I|XSzKyV^8&t;Pn36@+UkK{&Xq=h- zkI>F>v?`z-LYwMn7{>=1ccG&-0BPJ?9PMr(jl0~@Rsw0}j6jVmo zJC4`vnksf3ru1-Ys^qk%)T)TbcB;gS&ud02)?elXwM@r<;4>}Q`cf*^cDP$D21Hs6 zi1aa$(pDgz(ohWaV-@^vgxfg^4>#=&RwLK2i0ccgEPdIPc@RSBd}X5Z zArBi`nP;LOxbd$lQ)satD$_ovm5+spV`{WmJ*89;;ej)7of2QpdXk;WHiO z@Ocj(L8+=pB2^@jPBkg*F~cV<)PgNpHvg20czv_kdWuh!XK^#l9PTEZvm1BB+hM0$ zg$LWbWn$WHD|BH(A3YP(HovfYg*v=nEu}QLR9RvAC)8ONf{;T|(qEYYE{sqlU$f54B7Oo_y3UgI{0_%O&1w zSRyqnk(Lmpv4kj18j6C9o4OjiqI$-*pfo7=TZU0Rdu9l8X3P+l&3d8DKG$$2NsU(z zl)Xf99N`;})f?x+Z1t9@L^2L}7U6Ka=0;1TZ#?iB=a)z=gDjuS09roXv`UGM0iV~4 z8m<=%#WeJT&vcw%498kX4M(JgBhnJ7G?qxEwPHAaPbb}6o4xzcu%nG1mTrU{9XtIM z4o^3&j@~wF9gGxd1KJHp-z7NS(FQtNrK62-w3$F^=~|%dmR^j|uWM<>p_VVfF)Uj{ z_SKe_mJ1hGOSe+@@_Nxm>{2#fpkD!>>6mXCv4m^Hh}6(n`zr-j94)Graua zPDFBBeB$HY?vspW2TJq3Ykp-e{lbmg2NW-@X8P(N?W(U`W6&5BAe|{L8IvY96^sYs znwJ!sDEm?L~2+fZC{nf_El-ERMYA9 zRT@{fBR<+!yT>OwuM8{n!nS+nV_3cymd$$M_VoxPPB-tsq>n)?#Y+3St*1TTBZX#FeBhbH6EG!DJRkuFnZ0xh7r)Y zKACKVQWx{vZP+_oxbndjq^V@eZ}s8NHAp9I!-Fn5lgsM(xX2t0<8acMwtOdD`ZCPq ze!s2He%u_cod);DG%{Z^2-mWX*XMaIj(&#tENsIxy$t^-_^-fc?p+6eKKxhVGrh0D zXXCvQIaqB-q&6hd338>aHGDcj?tPomS}WZY?x>$7`p57TwWJM)kwexL`YK)ZrTiVq zpX*uMH>;4>^Q#3$IxcZePN%qexgW*q%n$eO!#&WpJm{9Ae09JX&siQb*_UxT;K0L$ z;Lokv_wcxV?S)Vcpvkl^q{i$k-6JW9Iv?lTm)DQl_ue3=WtzCgkI#u7f z|6%w{?{fIG?;o9giPXMCYG0+THGHON&G2ndDO5Xw4R213;@eZ@+d0!~E7s6X^f17F zVALg{y?~gBQe5BB%E*!7K^;CQ!H^Bk$>;RWKZRr5rPUx^o= z*Qa^>QOE|UooV_De5UKK@M(s(of(MK3`A-MrO^yZ3s;p^%c$BGG$(4f%YxgCA7vu6 z&J4=O)S0ZvO36!nC!jvo4Gyvo>uDM)+E+g75Uczpz(0u8eT+jMc47~~5K^aBHMwd=k*uMqo_Ybm%$gaq#$x%=q0*Asi(66Z`^Jf_JL6~XweBKPr4ng9<$Xfe zwEtg2fd`1%4niV|1Ti0fa|N=Zu53kt_wS*1D~|yqE7SV+{SH(YTDPWiIEUlDRCz?I zJR(uvS@P{7d||$D4z>V7%llxVmwn=oh zymJ3?*1|Tg{Tg8dBC28>h98FG)O5dS%xqbUTO<$uG%FQV*XWWq%~RlaE}g%02&1o{ zCqW)Px&~QU7ii4_|LD;(<(x^Zk@Kl?&RkxD%VYf;&X1MtCqNRKOjEF+a~-y-l}Ob} zlpp-rgtiafGblgE*5fVVw~N{m+0bp zUk(<&q2OzQpkTD=;^uI1f!TrNY#`2Krtqv?8;i`{*^3d%y3cAce^2hflQ!E82#ap* zz&PD;Ou><2tt1Xr#PI41s>k)8HV(TZRZX8hdG3Jm*ea=N^57}cXHA}|>+5(e>+Chz zlBWB$slDBtk=-Fl`?b|ZOvafbrfDkU&ywC@v`0!>79Vs^`;3&pn-A@5% zqdY^1=7+mLKQU5_8Hf4dMjY??HC{A7e8(BVZY!hN10U8KJ$>5DEL|?9k@+JRhwW11 zRSS8|_Z0Xifj$KOaQGGQ$H6}xKJRHbeCC_Ip=YfEh&102fLVfb z#dws8>`=t)@D)|S81RHLgjNBZ)=u#)WMlkqR|Q-TIpq%=?;B!nb9<-+NEt~3)_)QD(Bf(7G?AeBMM0sJhWNdRR1=(1( zl4TnNZk>&9DN8a&xJ$Qe#`xSMtpy)6+Pu@|B$N{VGSM)k>P;v}A9B1VsK(JQ15z4C zN%}n^T0&zqyU@=aEeQ!4gR3<(1~=f!-d8ydp`8(*g_@3ol6~Rl;P?m!V@Kx%7>7J) zOoDw<0OHW-m5rM;Yi3Q^)C(q$KXaOFV=z{}d;3~!&Jau^0xN5u! zkDk4DS6tALX%~;5AyUIkg^25zDyL(?e}u_@X^q-F0S6qH_VdY1De$=J2@?iY3yE73 zTGEhdC}FwS5-|PN8wEUr1C9c=dE7?8R*z%^NINa1bg@R2U+R%-kaxowZB2JBN+orB z9{jHGN5E&_a1{Jf_^9S;$HK3Ie--@m;Xeg`9Q^0tPk{e7_!q$66|yJ7KMp>&3#>gJ z{$%*H+f?|pId`|$(odwNpC~`b1DDbY49XACOc)v(20{73Vn@5y(NIeu^GjJk@yMIK zt36{u<>X0up8bq&IA|D(h*ulf&i9&~kyPEz1D!I14gt~;I9q8&Wk4?>87b~#)JnEz z!J}g~r(?Eff5~S1QNZ0I6+PpSXAq9pnd!ta+s~|?D*4>f!ano4o$4w@kWNbKRLD?| zmGZ~n;JpsSL3bC-#B1ISza#v6;O__jUijVM-v^)5mOq2fblnf1W_=wxP_q)LS&8z4 zWhS(}Ja=py>f}|+RLKXErKR0@N14Pvuk?M^|pO!1_ zF+@?C>Mdi2Z4agw5iy0zqcw%`Q4!tO$%u?Yh0!SMe1)A{{n#jot&1v%NEJk+8B1yRAfD3Nma$$z{1oimnx4KYV@*cvXo2-J*8hd{G-cYj zZ<((?#`TJDSeGeN{nF@+Z<(vkh*W1p`JCAdl(yU;o!4oSsxw|5n?|zo^y*a<*9~&I zxoGo#;d+%p2Qzu5=i%zoT+p;@z^uv3>ol5v=CG#=?GL1%L#%ML9{^=9{Z$C1%a)mE zA?)Z#>1P~f=5uh=`y-~)Bm;%Qv0%lrUoZcgA?gebEUD- zR@zt8BI^+Gzg>&G;+KvyE}BvE73%hzGh5HHM3msL&ekF{Zm}UQM2X<}jqq7}-DFD0 zt4?7=sxTt0Rg}hBMQK!+H}i=XZJFUd!C|ihD77Q$)(7xK!u;7JUSJ|*Tpj}%zeHRpF-)R5}$_8 z$PxIhbT4xbir=yZohJ2V$4 zd+W9Uq3qWd;-H&~=Cd!C(^nx4oAN;aGb&pyf~B(}y(r2V20Uw5-cSWU9Ep%qpo9E#nt+F z04@vBbVc+c4Z^}E|c308`Aa_kk*0ra|u z&PcX*?Uk^o6?omK6;SiavKjREYMGud;1|GWu2m}#sTGKHG@>+)MwAxr^YC%(81QE6 z_SjsE=;EUN$4fwsJ}_Y%b}P7*Pv_n7BMv(Ao{?QJp3}(aHO@F|{N!n4t83=QlxQP{ zm3SCtky`2I@Y-8(`1KN}N|~OC@R_D+Q!nl7x;aFuHzKW~8CvNi`(Eo;KRF$dy@5Ftp}xtZ#qbJ*pAxCM7>9X^)2^Me7eg*w z7(e6m2^IJd($Hx$tGT&g8?#urEK->zIIQFKqeYQVJD8@C@R_brrYLg%Ma^?Ws$3#n zTBfwM;8$8ixmZ5dSeUIevUA&-=4ufh-GqyAm`aw6JN+I!@p%x_HP&d3Uxrl85vk^gRC7wB=9CuJT>4WA(rdy?mJO-J!_&Lgn30=D*4=J= zZtuO>P}WA@mj>2R8MB3=lN~w>Nc&b}fwE`)DF~$j^Kj5*%KFiFy%Rwq|xWGPC{T8VJ|TJz~9MUOzh0x*GKe)3g}=NcebaE!FL(sDssjL~1}H zHK5XHK&6EZ$kux~c(Y~xuWG$7hup!DYQt~6mu1iV_-5K*{ixc&>Z%KdOv4PuH_7_( ziHb}uc(KX+2g7Fzeu&BZom}Q8Qr!`$?vzH|DJ`bECRw|bO?e#3FymPl&3I@SVsAe% z4voy&mOENi9;@4LuCOA=w~p6jZGn8?+Vb{BL3=s{5vhWR^xYMutw21b#T2yD&~K5s z=0fhkRx;OK+1sQc_~O;K?HR@jWu}b9r|PuVc$2Xv7`=6IdLvT35oy;@X^n`dw3y!T zB2Ttl^;PZBMUWb;&iwZ1e7`z#txn&*sLoEGfi;P3tP!SI6c+F@Jah9pF zIymhRsdk7oS1FCTN@@Q~?Tr17v=izj;!fJ49Sk3(LT7(YD|8~&4v}g{Y1EF=V%n)M z?eb0Y&ZUqVed6KgozCnyh{Iqk_QV4@$n|f^+E_KkpLnpTw~p72&N**}mRRCAm}PSQ zZnSo&(;AU#jYvzJ(i*|9v1|#|9?$u|1erZJuh1O$Y`yr(;AU#jYzeo zG-^$0QLW{zYR<)!S;N9aBgV_n-)f!g{sb|Kaac#pme96_(U$Obgq;215rjL2mpD6gmvxp@6p&#(j;T78zAzs}1i{Lqm^ga{J87)qXxljMLR zq!*RolR{s?fYrsW4R{NJo2Qt8mwwj0X{7h@jZx(|=~(_cE}Ou09PfsT*PBMJl`Dg8 zB?z_AO2kfYf#HU`V;5moh0Qx{^|8z7y z_fWpQfc_$(M>*Q54q+K+@Ve%shN3pLy zNVPu5yEN~GBX6#O>SyTfuu~52GYOwvq#XD+z|Vz$FZ^BL--3Ag@LBtO4y+wGBCRfn z@`GCtN*lBferiy@JQb#e+Vk~Qv6ard(~|AwL#ssjK?)L7UT1@{Hx<)a)ht=r1p;kV zb0@Idji;f!5l_OlOPv89Uw=YzS(g3`Hp3e#miTYhG~&&gJdH3QFGE49*wO1H4c1mA zC-90?BNT5dU*rfZ#Iw8jloH{7QnDYzL-n&<4{%ozp!X=pI48g+CDIzk@#q zej|M5-rd2kxtB={t|l(M~~lbma`=aDc#RnfD9v zBM#-#Jz1SRe(D7^6Lo>OFWvHnb?lz5dh0={J?nVAK{$MEVs(ZLMw9TFjvV+bLw`oj zRBaNeHi`6EkJ279e9`52Hp36|UULX*b$1gpC95~M0)W6EeF5SqB%7W z>Rs^E{6;VYvv$YO2pi^ic%uLGMUAs^dNyuuw>*)37~2PNs70&Es1|QU*y#~1G7h!a z6Gu^->V~P~$B!%H8^I?{n=!Vn>mS=xK~U>Vk9EYFo`7e7bhvCHvNIo7fFSWFn#mU&;W8 zDx{hQRmQz18 zuWndgeQ7~m87GG_bn$J+ehCsS&L1gL-@y=*Xw1C;oiCY$BV_HbUkfx=Xg33m6GR1m zf}=0ilmM;SHfr5Z{Sac{}g=I67ME#CL+>IM3f(}^`TDN%T`T9`O;6P z#@q9=hobv@>8H~&?Ku(<8|4SvjO6z60YjB1z4Me^le?v^JhUtq+sI&vE}r<~1^n%9 z-DEw#X4;!oi2I;0N0&96l3cKAdJ8TSV0&kJn|G%m=Z)e49)u zV=?CT`dK@g7UnjhyVZ2tHScE(T&sbvGmvwhTX9=*jrt0eu&pU)IbyH14D7sRVt5P; zn*MF6EYtx&BDF}A|T+T-o@P{WnH0bH=d6W7lt=d0x8tf_Er z5l-r6OWoq_I9WjgYSUC`VK4I^zZIGa`U9l|o#_zc=z<3{zy_UyD?9_f+@KODdwn_@ zp((`5!$Eg5W?lC~O~qXP5snvdM8CAeIGkzc8^^_rEDpsd%WV5h`=*A}t}X&%@ha;4 z+SR?Eu_s=@WWti*8&_3RrEhv*J(<3jc?8nxWY0i5u5V!fZeMUun-Fm61YfAGfdsR3 zLZ7WIG1sKWd!cr@>~bLqa3~HkBaexe+G3nz5=K4^iJ_}(XMrgLc|mI`dl^xZcI^2g9EWpE|q*K8tH5?4@-+krr2?{Gb3_N-H$T zHtMk#A``f!F`Ftf|)vuZ*w+xJ9d zUL1~jBmRk5%^rP}MShuH&hYUbyBT_)opi^tW8ohOT3`6QpX1=ujOYXyGZLv8iSnf| zDeWc0moJYMl(x;$V&f3k&%y#I&cAteW@xmxItT5Fra(t|YDeC9_9~zsLV16_9d|S5 zv?J%LqjqE*@=zx~Mln=}D!`lP3fs|2x4i26c65)ytsS{!+S<_@XZ!YHI-+w{C@j)< z#)btl&fX0^)7b$&?ZfI*iy4vHhbUiWpp^Ea;j_go{=!kla+WhMh0=woClo$5NjXnuJ{6++ zzCb?Bl}DtCIFwR!hT|LKXq*YtP>d%H!pcA+Zv_x%MN`2Vpiz*Vd6tu^?ux^@F{nfR zw}oaR;DpFb2IG7W$5S{4_*pbm&({ndhxNdAIlh05bZy~hQ}>-eH_T%8v5wb_u7f-Q zWuECc2|m*@$kYMvlx*sn^79|qcq7*ncosJ6VAT1Tgg>^J_yy}-g{hY*tOzy zQ}Q_@wO=pL6qPzO0%())O#sSnzo`gCadwXF^gcMFj#z@k+JuNke&e-UUM{!91=BK%?aW8g1`UjV-&a;;VsL~2JOwWHE#N2NvE z)k3tZ9FyefGGu?fad{Vnbw*e!zC^jaE5eEqR-|F;-?8tVh8yEzF`$~LKN6v6q(c_~ zWjEVJ2&IXNanMC45I+MgICO~!6tZF{rBl{x#4Xf5nKC;S!m zIpMFc&$-0CBTDAE%FG&HPL;WfJyqr+b9#v~^QOssi88ZlkW>A>yF7?312 z?B0fmk&AQ#eh>fqprLw@-usL2sULK~Bnz<$)GS1#S%@e<=!0LS^)o0sNh$A!UD(L+ z9dc1qyQVG)`^u+~3eu$Y%|awg5=d4IWnDGfQ?UWVW<706CUG0Bc0iwE}Abm zv_Cdd9WxH|1!vj*1+}X4Cp>13ulYK;!cBnrxnguUSBwtliqW3!*dwrxY2$e=j(&zX zA0r~B_e%H&z+V8Lc3lXcP2M8-yqBxsQx7azYC|HmA(2irE3Mh^MQz9_{6f)aRMRQM zpr){iHfHK5P0J(8|}Un~o# zTaiX}tc-b|kHM!E4o09_fk>@Dlpl0POr>=(D3cWmTD3y9{Js`f9vaE-Os%!T&sw(v zwUpNX>E}aj_LJqbecbsCnzMub+WTv;gZtXM{f2prNK=&JaGX>*HC}|nI;(Lg3|#?r ze=?dr#A%vHHBFSyhl+vH@JLLM8Ny`w1Ri?C@(PaM_HDJV*)-*D$n##%@i$D+)g5Hm zP`+Jwq!q-g(Jf3WAI1AD+c2e7knYv4&It|&m##@V%Ap|+odu-pnWj0~Tp(QmRS%TC z;arMPW)^Ecej0Coobmi49GBvVJ|AWr_Out`I5|thS%a5v=STsySrN?cD&YZ@o0H%u zDGzL|ynV}SNBgauYGQgg)xHC?DmB-JdqlnNDZ$v8eVDP5l*^ZmP&c3 zSC@MPuj*Hh^myjK62rC({J6l{oKT~%H*Q2t&mOy?;~Y8_NNWTReHBe{2#>~1ZE~GM zcQ|xEkS=_E94LF^@jHa(m;+v{cYP6P(aBK8VQ&Ndq2RP^S&8fau#0wEhh44#@g_b? zAm2J(GumjpfyaJK$2Ry(%ctfsAeT&Pqd}xuh)4&?O5-3|Y2hqnM>yZ&lkObm_Vij+ zoXUp3OezijvF%@n_9M}jmZpe1zYFH3E?u{^$cunSK{B|&-MUWHiKb++=~1;1salBg z17;SbJ!DX{yJ|;y|3$U@GoxDCx^udXArh!)QVQpzFe>x*Y?c9>kPtyn{}CGfYA!;BGn3!YK2I(qBLqn zX`WWFaVFNSzTKr*YFs>P!=B_#k#Eq*&J52%T3eUq**m57+T*G`{|E=i#D_b>lRh5T>E~>t%phdTRWgM#Sa2!v0 z>f>(0UrT@I%A^>Z^imvI)yeBc)p?Uq=gUr=M5<0AT`8(G48~<|O_7e3=}ejME~8Gq^rB^&NYzQCnNVrW zgh~skvyC<3A4H4)-AwpGT8lHWL+#hpqISxnGd3(3(W3i^(b_tvH6qm-k!C`rF%v2c z^PZgB3>t9!5C>MVd`Y8c^AFtVhP@#yt7F*zl805p5~Mp~r#qVsFcz&;{XGrE=>c36I3 zE-|+6h;g&!5-K~(B{Xo{+^JPls>jY8p&!($!fU8H>pJ568oQfsIlk01*Ia$d=rVkb z;)0?RylZ!ttK&|;mU~{*LN#|2#1^es5DPb_T61OE`dL^$SDIx->_TyRFc&R<5Gbw4 zp<vtl#$rKJ-5&k!e0#8KM%P>7IU z7ZMfmrVF&?)RyH^;nW{Z5Y-S)5G7>de@mp2|7|Cql5hi+<_1nbe-b|WR$5AO5Kg>J z2@~HOiXXfeJ_Wf$6Nycqy<#xNKkNO{i!UDk(u+e*K%^6U_3CwEfKQD6vBL{E z2A9Gw#h&B?E^I$)SR)e_~dD^LUN{&5x5R&IkR7)(Z~le9(E#Borq$WEVR~N1FCW1TyJ0fb1n0})&?=eu zGj5d=XD^>W07{{L{M^gpo=otOhRJy7KT*@Z91MiP!`It*t&)zXPc-{)0 zA^4@7TkBp~5tqZRPFT+OVsbc9m`wEKFOIH|BH>x$<-`4Bat;ul3-AlJU~cXEKaR^eP=jT@#dfYEG`FG0dm&z7YE(JF*%2VnoQ7YyswR)UXL4% zrl+g$G~?H%=g^p(!-R*m8QuNcU%5FhhZYFi{jiuEPU|ES_Bv;^91fL7)6-3Ow&2(D z9UhZ&gzzxuGj`E}U;i>Lr@QdHk6$b2h?txsg{O5nCBoy^KS##oNJ&rp1e|mmCT>D? z7QHXY?TG>}|MZB->4n(IMC;|WxA5e6a(cz&93?y~Wprf|_Sz9o54#UxdmR;%bByp< zIlFJY1z8|^UwwpU1AeWZkBQ0Q3`a82x}3hkfQxN+u4&y|WfR=F&Ycil?Wa z@c4E=E+*%A;bCdz-K@Dd`Dt7ZyP3&EGk)!T9Uqf(qVPP7U&@(Vy%&mpR6nJ{8qs)0@9QMtVZ~zQl*iG|}SoMFOqABDjE{jt$s#^nr0NLbFWm>e`$ z;1R0*pWDHOip!ZGJnQhwQbjjDCI{UMq=)?<%K7rxFVGPt^2a+9g{Kj}R?Y=6In}~*AbuG; zb9yET&x`oAa;jr;E)*VWduJRsJ<6A`qUo6|JY2(Rzptsn0z2Ryu+DMws+bzIIIk>mGQ zFOJEXD?GFa(>!{gXHbzu^@FMedDXAy=f>n*Dm=^~bVqgj0LqBUxeOu6L<@ecelCs4 znI}B^;Fs==d-l94F6VNDBoqF9&5OyoLU{J15V*|aomzw>6MjCtA|_|P@U$-H%9xz_ zF*&q&GI1z=sg*gmo_>A&z7`74R{UE1EQrZjBs`t*OE+Q9+sfl|pfX&`m$N7)2iXNY zEUmoO%R`SmGA?IvOwQFYId#Hg?e)T|d9`sl>_vprQx}s{FFdR_=(fDQFhl;i79rtr zcYRDwgYek&-2WNZMn&`Cb;9H4pN5#69}17v^Z9*8!Z=YmOJeEyVN4Fpj5N0{=SML) z*T>|rhnbeM;jUi4h^Oa9;qmY5hM1hCAvvQzd-sL7oSR~Dmd51#Sa{GFi(CHiZ-&I> z+$=nWUOo2Xn4F&o4{Km*_mb^{4~fgUMR@%B=O-~aw+auRHM6Y#>eaS!O!_b^UpHj@$c)7 zn4CL>rz?IL`}&6ZE8}wR5}s!K+Ir*8n4G(Xr-Z*ax;7-y!H=fr9^u)DUn}SCn4Eis zrw@MVcB#C7dtA{RqK)FMh3@pT*=nAUtg4 zcgFG8cGdgG<@{WDkWk@)hwU>d(I4+Ti1TEE+Gfb*ANKiMT+Tzn!+x*LKM%&_pjbi< zcavax)*hL9H7@6u!gHIapI^k}JS;pM9neZ|9eeg}aXHB1xK>wlEu3KGY4pB+B|QE3 zi(|LK#Tc?g?f!`H`2C+>#pFCHJg4H9Zsq0$P-;}pV+ctmioNta8k6(5@caS4)ZwcK z{a{sG&J)7(K7Os;ACJlTweYatl8fV=T=fme>a?pIj7W?9tF7rI( z?-7zrP@2`x3o$t?5otLOv~=tpPtS`nIe&=Bc}aM>;Fs=~lb%5Z8MXV%2nna>rI;M3 z13YXm82g~JpF$N9m9tKG8u4rI>y?)Sjh>v>VshRPp4QWYA{R-|8!S`&n_J}p@Z*#1?n zuIuH5=S`syZj^KVp~bN~hn@se9M8WE5js^^ytoT6uxLfcd4WBJ8^V(I?7Roa<`*! zkrLelj)GmI#69RJKQfey9fd36=w5IXt`MU8gQL7_C@(q6zYOIVN8tt{bjLc%p@#As zM;T-&k2=a_hBDVt?l6>79R*v>i969znhfP+N5Ok2;s!g)?m0>+bCe#2a=fDqHIzLa zl%pJFFH=xgI!dXbJnkq}hVq=FEHso`9pzp_ zS>-4%8_F6-`OHwBag-uZu%ldTC<7ejZbLcFQC1sD2S<6^P})1nzHH9n zc6F3<4dpOLsWz0u9pz#}+1F97GnDT+${Iu2+fn{(D7_rzOGBw}l&*Q2o+})s(op6* z%9V!lLr3|gp?lqJ}j`FUdG&o8pc2nTyIm)Sq@)Jk7#!%9=-%3L{((!CC zltUfmlUS^N1$wQtoEe5P&BeOaP@Z-aSqOrNzjKt6c2zkyILhUQveZ$YFqD~&@}Z%m zuYMTDK6Gb0o>L5kJk^QAQO}vGP8sF*Lc>$#VqI$}dpXK44drK!(rhTZI7(rMAQ+S2 zvjw(#bmKsw+uu>@4CM|-Sz##mI?5KxL77j>DJsM|Zonz} zj<__aY0B?GS%M=?IdJzN;FHlbs~&k-yV>> zw@Ct@AwQP*Q_cg0?jm=sn+@d`j?!c(2Rq6RL#cF>gJ2nTEEi{IEElJMXBj%c zY0b}MtiC?wK~Ik6`PDJX+cC`@ZuM>xsL2GXN^u|jYj}l$@D`YSsIf@@5R|jv zrzyixhn?ss$eFx&(6y77W+pHw@hOsj#`qM;&*%9R$%kh;3S~TnYh49Def17qFb^4` zOa$eD5QQJ>xzkaQLdlsErKUBukQ_DLr%2BHd5A*IFAGsx|^1!4eet z6uGZ%AqsDPJB;tFe3U3iYDgoeH*?DyAqsQUx)6o2{t%*2^0OfdFW(rVFo`Qe6yC<8 zAqwyPp%8`lzRaf_#oT*Sh=P;gM$PdL_}K+)MSRAI*1SXUQm zEb@e7{TY;G0!36@r;F~tIi14$i@H*Y0WtB^aQ`!@&Y)tv505NgIKPn!wfj6 z$wU!;6F7c(_u>!Jv9^;8N1pJt-UUT#NXDAC^TGYou{s?95*&HLvEBnEnP9Gtr?AAt zB2PHh`x1-VV5~8F?D$PO{wXFFdBU;&5{k9o?Y(Q#v8I?<381HXz5;{W zwAPzgnsrfr5c+9fIEkj?-#-|2TcE-46r_jy&OOZ2={n zH{RR%hu5WJ9c^NfCmieV5{pB)Bo1{}8)unV=c88%* zI_1=iEgoEP9?$-PL*KIDovO2P9x<_mM`N9-v9^LSTdWsMEa4G>9Di7+vi}*P_%+){ zU{uLAhP?;u&}3qf$7(~lJ`TlteA{ENtX>K8H3y}6!m<7tiuF*#(b6X&O69bsaTCmidOP^{yRnD9h8*6}75dBU+i4aKS-_}i<}u_{a~@`Pi37K%0d z@xL^rV~sSi$P02Se*zkOTxZGVu%R_ zoWvh7ONapn{`WoA-P7IEGnSY9_dfTz^-NElK6UC;)u~gbs;jH3NMn!nwJp}F7dn0! zk9Ce7i!}CF-`HXmHT>^2@mK?TEYjFxeQS&L+bJ(S7msy=9*Z>gSleu|x}LoJ)p)F5 z>aj>;kM$p0tTiY1p|du0W33*GH1=5E*peXd zY3#9Rn&K_x_mBP4(mVXG9*Z>gSZTIc^Jc&0kEit?Jr-%~vG%aVswo*WIUZ}Dd}Ixd zH1=5Owpe#QJPF;7A;UxTSfsJX%8*#>Q|SJFVAD_IvBv7LNVA95fV*IGw7RLIs;PS! z!OD)da0hn9miuWdxLL1%T7IxTd}gS#&EFWT4!8Teqpf~_V_{L!OHmY6mTD#ke4ZX! z9BFC~%IE4$9Z`R^~eE)pxYT4C; z&r_S)+X04`ci}#Qq}#M<_~IUKrTqSRB~?`*#Qk)<$+F&;;Ej~+p6|XC!ia%4T{c9u zaduNl$Kv*oEpmH!aYv|idL$I8MA0K1P3;V3j+y$j0&{l&zrVI5;GgS;EGexjK)FCZ z&rV)aGN-^_Qi?wbo$DGZnVuGOq@+icKx``Mw?-`uRDo%sFxAf_bcQpZD#$IwJj==! zSQ0>@g;GS5pw&iE8o*cYilQab+1>3HXy&Zf5eg|WSF7C7XS$=Om0Am40u2%-c64c= zM)5XwD7Nt`3CuMs$UOAGMo|h1ehjaljWE5vvng7R51RcVVMu?xgIuH_1=Z^vT3#X> z0_ZIKs@9cKl&1=uu@ix!Oi8$+s7ZsVHM%N7+sysG?V9aCi|7i(3E#wsai$ZTOzrx= zI20}GZ0}j#0cl!O5v?+%@Ap?oLM2Wjq~j#A)VGzPQRDG!gU~ofz>zp;sg+S$Gb zMdS4|d6N^!=C29C6uKqfEE@^g46J!pZQ6y94P(26EuC#mEs2B`a7@su_I6%M@lBjV z^{2TinJqu@+Ba!UZnjnc#j)*oV%IvCAd#DeSAkuSg@uJxg-X}mS=-5-+zR!UTZHz< z?#VFt<8e>xubM76o2MDrGweV++1nF0T25jly*Z-g*u(5CXIh;-+}UD~n(7VE#7eO` zgoZhRpRL-c^GS$H1J1(e#Iqye#prrnS(|n*6|K(MMr&`G_DoC5j5j-Lpru_-E4SxJ zf-K#xRr&2Kl=7Q6hw?)_l^rWEz@jwkQ1n)AlnyOGQ`Jj}@X8MCIuvdy$DTd2Ix(P0 zptWlPBR26c)-s%Gf^k;m@~)ot?vNvv7%->RkZ9^q(H)I7M0(MAT504h6q((|ve$HW zhoj+6R=ZsWiRE&{H0A0ZH6AP@4n$UaGR+CKceY?;>mJLdJBWh;T@UtW+ObFmb!CTC zSxqN~o(ah%bmtgjszy`Q8SRWrZ)(9mVmUVL_xmeL0#)Lq)sJ_fsE>~?3tfU6E#u4t z?i_@kN^@a9D}c8!x7?G+QcZ<=j;DuvLrQxSBKrOHCC+G6(&nCUd#hoU-HM4^O8Z0u zPCTO^Sp=jsEx$QhqDI|n-=UI7q-m8O!!PGS2N-_&D=Ngq%a&P*Tkt1O#$>13Y=Llr zzL>%(af=J#y2-*CuXG3E!5p+eJENg`<8(uHIw7CZ+}Jdh1}Z3fo5ix%Gal$T+AT*9 zRl~|QIY-oBby{$SOBJK8*vE-N1_P-HP&=(ld%D@O+CvSUa<07o{H31A_)O$>^l`j@ zbRL0>vL=lXtY(R$p>8yP96v7yjHIHs=!4$&^&F;1qpC`3)wCT|B05tQ{C;UCESDH1 z)EEq2Q@b#h#vU(PxLdFxJ{P4T4pz&+%anwiy*;!z39?9)jJ}rIJber$&>9U=+0ai$zm@^LlBh7&WonQ^M!UqB!ZK}*$~0x4nk}21 z8A%%Z(Be!(kCr62mVOOwDG3ofFsJsZp}kchg4JTIc8rZvtrQcpkS2c)=#u9SvjwP1 zli2TQcXrGPN1{D4K24GfRLsus zW(!ZkF-dM+ZGt7YMZ1t&SKiJFbvHLXU3f1Rs;j6^ULcCd7)j`MHc8R(kYFD`N_T+j zkd~Gr1w33Bq;(ZYa%m6N(O6{ZeskC^IWFy4+vLU*N1<}k=^*UXWmZH$^k zc5WlpF@>l(^}WlKUW%j%;|Ez9OKMY{cyfDU$tT6!XQuno2_ z5HDCdmxV+A33vfw#t3wG>9>`5xr3RUkbYagqz99RD?4x-EbHx+=3UX$(Tc2%2QIW^ ziMq*G&u#yOflDyh)3Gw#(c0G2(SmK2|7!{57r2yX_m7v{i?iF)ah8V97)f+=2gXGS zncppJcQLO{dntpjUCpT*Q$3$lL|XX&nkGUImC8q(n%hJF&16DL9EI8Kdgxk~|3)g- zqU;u}bmn|_G2MlXx+&!@X494Bv}wUIf3RRix&M@zB~_J`GiLbJ4)oJbD4RBZT9Ml4 zep->*=zdy}+Hii_Nkx9ViI%7pv;C#BXH}PWMB-6BA2?D}s{P zFP(rn#w*C#6=fAQGfOzj=1R}ktJCrk&aBoY&S(1lI={LC8Am5R-At00ZqutOq{yWZ zDx|Q)KMhM70~rDg|S1r3PqMM(IHtf0?@^?AVzi!w89!$v11dmVGo8(TqWm} zOcJ7ahLRANSxXsi&15RV6Qh{qkrB7bpBmH{qZo4?o6@0YyT1ZdEUH3phNG`|%SL#=LKBp)={nhbGwX+Z^<5*o_^|jNdj%2;%oGCl$1{ zHXHX73MM%29pU3onn(r){RyongbJD`n( z|K8=x{i-kp1<8CZ>-fT=6AFBBS2+HpqJpA{ClnOLafI-ubmGK`K3~yEa1wNS)~vLd z+C{f+tvh{zrg3pIopr-`-am!ww)jeFqVNqvF6iQ$&J(o`t4|l_;6NK$@UCe-;QU%{ zsdeLd(zWASHi1ywDLQlSc?rP!HSO&Lx`ILL;!6@{;QEV`F1Nt%q{9jhy1un2R|if zFBUS5%Z>fHke?&nVZh(0(zDOW0-D0z$RFAFK6l(EL-U%fP)`{(LYL!>h0n zcD3TS7d$upqdhoBr%{yd{HQNigYLrFiYi%o`322GpgFoGPUn`t8szUZ(A-lSr*q36 zMfaXgqbS|;NBcac4(+#IQ6(!co7s;+^QKOhOn%(d>p!45qA@kUJOnS(X%wY<{`}zg zL(u&m%i!sf$&dU#(`kede{S+)dG|aOa-OTGOn#O_ViX#vBZT<#=lT=+=^p^UHG$6P_tl41jL-7!KObjd;iB6Em*fwx37Q0> z{(SI?K{H>cL-9$ck2m7{a)ECJP1H`O=PypTH|Wj<&BZ#MnXbq$PB#*C*MsJvA<#V! znopc`j&hLSx1bq*8UVOd4OI42NLGx!jT|znb0l$wx^SMr^`nN=VVL5UaK(BGp#mf=@2#I*MYd>hp zbviwNNEdYaXGaEIHE8M*=g3+MOICz zDsK&ztE2A9IlM=V^1$?x##s%sDocwGTi(5*r7IF`b)c*2=akholsmAqXO&l%R0Zk} z^Ra0B2I}XynzS@8JT2jXztV6=QzRVfmUI2oT!@~NZv6~E<91wYII=*phr{<~gqkAp zwF=`po0nprgUQ}BAGZx;N^SV6%21Ijj&pb!hcqj3?QKNlk=ORj78g4)DGuq?`u4!t zL)qSKIMD2PjESR5!re$D+v`Chbq8r$q`5@ybIkivZGVK*UR{L0CM+na>?jc&^AyLG z;^W_J?+D=hxFUS{rQIua@OMFIZ+zEgH%fv21d=ak*K2&i<( zj&UeEHvjBYvO9NIg%>~B(^^KR?<^z4-N#|&D3>xG1w6}Wl+#(pixB2_l#y{*#?iQP zQkBto@4usZK}Dfne0MN5Q^VxCs!r{5peErm9P`1lGVko3>5!*B=It=}Ec4;;na_Oq z&ieI05za=KQTBro@pybC&il`BeS^zccE&j#c>4Pcq3lIccBW!D7EE`2>DZDehppRi zJ9O*Syk>hkP_-zcm;k@&&Qr1*0n{K`-C8uF1GUBNoy|?{d`DY~@9MqY4K5)i7I}9W zIfKtKQ{EiaCGD5(k52kRS3>KcL- zfw}&Au%>SI+<6W2Y64IQMXC`% zNm)ZeN=8;jYRF$hWm&LhR!Mchk`;r+C}%Q(>T*?@(Rw0>f}*Nsb|dgoWD666#HZEI zp59P8yL?^($$`)<+BW6lAMPFOz+<&f{42ggko2c$cUjtuKuH}1Uf)nxQd!*)6fqv6 zdAx6-PJ-Q>L~W?#+u^cytk9PAv)aK%uv=h00`IlNWv_*oxFI#;%tg>xF9EIec=v&> zV*Pbfdx*_H*d2}Zv_#RiJ>I`UvAMdhy*=EG<&i3?xnv%_gU1^|gR*>OfMfPN-eUw; z+k>Swkq*RTJNE|m*ED>cSX|tLu6tFGZ@;+Ya&l{D4_>t$*VEB0U*-9*E_*5z*yEj; zBtjcM)pF41f_@g{C<*XGNNfS)@lG{3ENSXqGFjqHMfc_L^1I9qoDtj=jRd2xW*%>~ z8M(Bxvt5_LWMLQTZ3&_C@9YSIe5!U3sIM^?H#fBg&2Vi3f*Oq=M={$wF>-J%D+N8v zh!rdiM^}csLqW;1qE~6YWssQZF+bSe+~XZ<1O-oxG<9J{KC1bEe$+rSmrY!89qb6L z4608ArRHZF6t>jJ@)9G&OiiOQE;P^*!BVEF+K~vJZv@+mVWVTtPIjl$Yl!LJWl%`o z+o7J4;pw_Uc0fsatg>nctWp|WbKxaSug7~Slpk+w_>or|z6EWJLMzBR8hSVbb^NomuJw|hxoSAB`b?6oy&KEAgM1Gn?WGo-f5I!Mc%&l` z=>axLX|K|dE5ad+rCXM)Di3wHM8aKcla%BwAj=Q(byGYbAF768m#)HstzgjvspET0 zcBXBJM-a_^L^!z`5F5iu=p8-YIS@`TxV*4v5(XWpD4K@$*6<26lRVtFiy5=GLFkK@t(dAxVK zg^*XA4wkpGNQmzo8gZcr@X8?yaDqr^3}gX&*hzzd#XwP&Z%PQpa5)}ZqHNo;ibre| zx65memPR_8TD#DwLN!g{2*yz!uhguw+TwLvgy$5GH`B1Rt*3TIS~2EVRTebrjBWNt zmd zC}y=wgm_C}^VyTCrm_U>V#}N_y!0gsvH)Ckaw3&b=^#~fG%}1;Nl`@N?QpUQcQ*I5 z;aEwJ_cII=rP5b~dh0`7Sa%o2Gh2DM8()mKgv1E2+xioPg0v%{ww6vj)rzV*)Yzyc zHpg#72U0Z0@rBY}x-gnu(S#L=-BIcEl)Xy)^ks6Qj!(td)gyy}1PdbS&lYnLvSEHn zQ$nlAP8`e}Ey8!qafK5V!%OV_bGh`k<($nb0K*^RiOgiEx_2?DZY-6F-wS3kwP6}B z!rUNQq_2{TS3HHec6-9a&Tpi9e|vP;%Zx*y)%GIB6Jsy%S1@tdQSB(;#SZJuE2$-> ze)X7E9*;F1?`1CSwZ1bFt%-zM!>EpssY>zoZj5zA$#u=cXvYI=Lq;%*r`@wDTFfm?C0gFUsT8xIp6?{{Lg9KjZP z#hDFfj%bY8BZ`)L?KoOplR%kY3@Bj_X@JGVyrufu&h{0d2tU@sLyl_5(<^5Mq#e8^ zb!v9r7PZX*X(iiyaQVauqQp-tv!T8(v$hInHzJLKN^!lUZ+wa&Uv9`?cC9^C>D)fD zDzYUX%<>?WtEQ@4)bJI17umEYR*{^KRP(}nsJ}LzT(qG(eL(sFl~+6JuWvb@5%9(toTdkyHl4fd*kKw z%&#=)^9lZW;G zbmB1we0uF~zrPIouL%C&wTCtyH21mKb#HB4`}kW=tiWq3%=hM|UElHQ`rm|Bf7tg2 z?=#ugw>9APpWtUsJon1AcYisvV&SYk>aP9fS9m2P_`*?J7Y??c|I$6RpPg{+Ynw4M za0FzUn^tl4#5IR6P9IqPMsVBn*?-sz=Y9)*{NV>o_MZN9_PQ6($Uf`A_g}#47{T|R zcm39iO)rny`kOIpw3(T+@O&=#?oj=^S9p7meEWz`&ieN3|HW&qa?H0QpBq2kw>Emv z3ok{kXnQs7zI^OfDEM~{e(1w+^MjXf)E0EDzv|4bcpV`4KfU+Rg4gP5@4c&Tsy{Ov z!lc6ZO!B#VQRab*GX6b!=E;ZtIX0)^YSgdb|8eZy-&A|ci;6Bf^s30p-$TxC2>!;A z$NO`ezZ<^Km7Q8~-+W8}jYQdU)BgD84+6J;{LS0hk#pw%p!WjQSF7ObCvAD}jP@J+ z!$PA*A2#vAe`(sIg1@e<;Ok$$fBo;q+`0aSTUOk62Bx9}-*8*(p4-k3o*llV|AYBc zb8o}GXpm`c+T@$t_gR@y*}it;C)rP3GQAM5O$2||;AaJwT+s0N-|qf;{EMDtXybnr z{4))GXN>xJ(Hn=o_0@fIyOunJv*7W*B{%KCJ+H~S`SAMKSNH$^pSR!mPfQ}t7kp^? zU0YxAy>ZrMk33%Z>aiJU95)O8`SE4L-+KJ9i?1)u|Lnk$>hm=1ZwmkSrfv8A@oz6L zja+nE^bce2#15cYV5DseV|;7_>aKYyF^K-s3jl?x|) zbnRDYUr!5OD;pM=Kl9vgr(}Ne-L-j-b%F;be{$0rF5Pm(raRxvo&VCr$LH7g0e_m{ z$9-_?mWu`_O#fhY-P_-MUt6kaw+nvuk*ELt#{HkW{HR4oy)ovJk1oI*EarK0)4ZSV zx%rtlt{Jgr_{F2oJLMkeRJq{y|FZkLQ`?uGw={TZ=FtP6cHrDd!C!Xqh^;q1`{+Q1 zcd_=`Z!i5P@+tUl=Vn)*xpB`?o-u3pdT=oMDdzMrf0UcHuJM!$+M2UpdHbf;jah|- zd7AbG?7;i`;;*H6L06;`n+z@YwPEVK+c&0n(!`?|EH|gvSA@Iqp^~pV+S3~D^c5D4 zD_F3iWkDG0&U;!z3-BBs?i{ydSJ{M?C?0Ahy7ROEuF?Ar+k(iS%PQiU8kvle5P zZb7s8FloU><5;xBUY-4}G|D#4!|jHuh(uRLI(D?Qro`gS#B7)fhzAUvx2^rGz-&fm zWc*IX#-sl7rruo_51!QV{5teZ?6BQx>FT0g9g3pa#M7k4+t|)cJ%#RuqOMdM!i@`e zv=22)+b{0Yrk2j;a8n2OUfB&=zg!Bu8wwk3Z4Wo^Iv@G?Q8%kYsl)9HOf{b!GeI`Z zz#OHTa_zyC>(DjV#zWUGyrD-cl)3AjWMpP$*F}xV^IaZ+81E8xl~FH-MCfvMl}*d; zVWYV0x`bC@Q_I~jMCe@>S|uM`?s|^!H9`>D9Nu+Kq2=fjXv}w=71sLiE>?CmmFmW3V?JNiRo_Boj&UWHwn6EH*G6P`H zx)L+^;E_R<6Y-8$>+kUp^)Y3jhCy?TCQGXq0m~cLZ2#^$U^>DXfv~ThovV1)C9?Y z;rJrAbazCE7WM`!P1dhqssW40W_b_Ai;o8YUyKXW7?{B#l&xjxP?k1m;yAy>&@62W zpfwU>GUlWRWov#N%F=E#ad(=yHvsiZ3?F8n2xV*eI+UedZsM*oajyWnL}HA@vp=D1 z&8I_IS}UOI1h+(ovb1hMKM~wY9m>+q2Xw9AF4Cba?FvBG2<~bf!h{Cqnp7GYI)svA z-UuN`cbyJpY3~5Sv<0s9I+Ue>iPokK8|Gga{`$t2Tg!e^_s}t))fVQU04@VV>smm^ z@Wy^CYXMuiR1uR4g@pyETb+Y500Roh~LoSImbr*>&p ztZLgP62uy}Jqy7D2y9zDSP-kqjd}ZXW3?ImH5sv5Pk)UkR+-aZkpsHbPx@nlyqKpy zD^`)wKQkj%;pw00iTQK-OLM^Pi~Vu~Bfi+rThc&Q>oQK>tP=QW;gfk9(--H=&$efo zxMpO>7VjyRU0Ii166}6w;~0|Xj`muq{2KWUd=$`O?3jTUY7$I zRBedWWb`*~q!6k$#cFc;8#jvx{VKB05&3dkk{#4y zr+8wud8p2eTthZOk5m)spV*L;{?!i>$zR=I;a(Sev1VWx%B+dR=FSf;LY2loJPoxv zP>Ho<%5kL`rufBiJ(>YqSER+^61*``rwirbC8}C`n~Adp@v#W5JndE!cMl-q^Rx%? zuR^)PtXpu$n$Q$LX9=zx(3t{N16n1}nP%vDW@yX|{Usnw!Xu4WP3T`HG#o`#p)*Wq zr3u{uh?Xc*`yW6*7B1@m(PCw4uK=Qr%hc8bqGij}>@CKuPiSDVlclK!XFL)BKQ;FUkrab{59|w z!ADot$JC;@_R{9+P`0)}hqB~QVTNXF8%&(N8kN|eauYS%j#U&+QDb^NLDY=Htm6%z z_TKIlwd>kxrbqEXNu_1NNthmaBvp)Bn_{3{&CAqtluo@Wsxy}?rl zz^8s?iddYQiMJ>z#np%KQyiMfI26}#T(^C*4ml7KxB{o7BoZw&K*6C0djYBNpsS#5f?`s!68Y#hY!{xe)><8powz&NDY57(_JrPtYo#bcPG^tFb#vQtEdNG^`8 z+*tpgj>Nfg&`oko+bOv&U2@E;k{lr=IYL?5y&K^+pw*#=UcCpKiHD`S`;#dj*& zA&5$`SVcu8GDOt}c#1>O7{^ewscf9$plIgCPQ}HBkWO1TMAZs_kyybT-3rpwgiUc3 z=&8_S`dd&}tgd__;C`;Dc6u{>Hh^2;)13973#-dL<=5SF>h_ z4;;if%^JJRk|g3oThhLAHEV|Od@|YZJ7$O?G&_>`XA?fjmHJ~|Y2K{ubLJjOOw6Ye z6CougLRs3w_*XdUo5G=euHKyUY~V`{QJ)QLRh|srV}ab7rF+Dxa-{Lb)Ufp3h1)P> zuU(p!fZvLqylyEvc?bQM1A%Qd165mV2O7Vu!!TNL3wSWBjgQ!$;-HCDn5P|w{~m#+ zn7DEi*J$Dvn7D30RIxm*5C6$+$r^-Gk$BOuh7IdXTf&a(ct;I04rw?5tBp4hqgqvc z8Vo^WaWolh0SrAEQJ2ddwS*r7t&sL0ABk8S1k-aih_f=ZKIY+v@R^VE;FBqbf~uwo zshTFFIxvM}2c~e24$OEQLq%*zi}HD@R%!-DI^l6DLyR=Dmd7tt#8l<+8;BIbX60q* z7rcZox%j-@;1D+B&>D@!m1XohZeMbpu3pV5v&}EcTCoEo7u|P8jv8VMGr#ImEliZ+ zM@Ux*l#miAA*VHgutZkq*@h~-bHHZz36IkPjVXk8XUbl0H%QMmdQdIu0^~^vkB|}` zAramj7?ahT()t6ry+4S32`lh@W8TSMDj`;R(yMa%t33bs^CI0KEPOJTU%2VoMQupl zs82vBond`1Mx$o`NZn(jeh62YLsX2z@S|~^5^vO}s~46&_2N^s$rr}bF^&+FT7lkl zWT2dLY!Jl4T8K6p6n3UFyN>t>|suicQbfmH{S0T7vq~_IeREUYKWsd ztJDU-##C3QnPhr5?O`{Q$d`zP<3=SGLP{)z)L2pB9>BfAIhB)!_rk#_y6&Y5mjKqj zXIk3obsoJFf8pIv7sVg%sdXNCwz~yXnKEWPL!hzvzYy-R5{-Bdw*2+N%C+HpE=KB|d%UkJYlKBnxLX@*+=>TVcI(oCA0d8f=%Fo2jZ=(pD3>t zj9+0Ix5CoA>u-2>e#65gVLOVyyznco!C;5Wh4m&SwLjOA8uQII#f;3-@thWC zS=PWubeR^X{fXgz8ho^nzFPQ~!AHB(E{D%@Ujd(50=%vzgp`&L%F?##q1o(xgwD_s z^ytKdnvl>Q^13T zW989Zxvz%rIpf{+{{ZKFzri>oaFyfQ$J!*#_Zz096Kc^&CrPKxtxlMoJ7DEli?e(9 z0b;tD$Z>ko@Hhp+Dx{Uy_f4+H1yw&Q@79^>gCM&5N9vP-D;RYKQ1{kSsEqkJ$1jw3TCAlj``+& zI<9;jiPk5*UL$;#XAXQO6~m<}mXNAgLRs>sJ zWDT%5bk0fNw~2G~bc}=6C)Y1vu9S0oIfHX65>I&>VsB?Y5gV@(zdaaBH=6Ltu&NF= zC$-R&-~W{e-l&u~z7&t5*)p-<2R-+ms*i@cqy>r%9iuWY|14Jpu03##6pW_biyC2B zAJA*253s5kLaJs6WoaYOcolA>4mlqbIV#K%X(y`%qa8SFVI5MaNl^=Tq^<>iC0S;E zeloim;xS(KulBeq1Ic$AWAVK3s+~Bo2Ye zxQY1pbxEHGSV@|Yk~AT#?E$&Md31;?f_BW^33Bzi@4Z@giPt^;yI%g$kcrJ zzf>URY(OC9jJ|{kSrD6L)COKvDZ25{MyCCUNMizbD|AJN2hB z#M-xKh#cJL9|d03$y$N%Ck_R0ZUQfOd*+RtF!O`BESZ1Gev7*uNgm{;BlADtQgVJl zAR|!8*g7l(J z9TuTO)h*Xe0%wgy`J|^AYNf~w$v5e-NMnz+mo3&c1$$vgX~d#2p(71qS#}L)8Pn6a zU-?0R)=mAo03Mu`W^df5r!B@m^R%jO1p{OV0q~F7Rbsc8`$);VG@dc z%3u4iK9LVqGd=Ac{2P3-6ZqiC5H#r6BtPrFx?*%99}WZ3(>CDW;ImHxAJ$uX8a0-3 z@~wUd)`F0=T)9HC9{&cP{Sx@_IU+rc4{dZMZNo9LbMo0AA?ayb@Ne+(Ch$2xXbe94 zZ}}-I$H|ACn_WH!B=Dhx)A_x=JcEtv9kn2l&w)a-0slsRh9&SBE;Lj4kL$T#Tyk_G zA4(4`PN#u~2Xb<>);l#TJuNk#9|(<=&p`=%SmWtwC*Yq_*>K&5&{d~=I25$Y`QQXT zlyG_)YlQB@8D%df@)?DY^fYU|ACka_EjT@mQlh&st?H{pK0bt`r$HekHaxU@r+lEk z7Cx~@%l?(f=P;qM@)@1L=WwAhEZYgkeH=~XlP@%z@Nd-n;R$?>5SrBO6ebpVe#OG) zhy*@I2~7b1w1A!$zW!lie#Qum4|apLiSDQbK2STPMNOk?8}>7>bk_SZ2(j1u(FuHx z6`BbCS@s)m`y8H=&v8OiW3gk$Ch!?6G^gO7?va12zB`f6ID{yBXq0Pg0-xiBrVRg- z&-w!jev!xrDh@tlEb=)%flr~(&@#}S^u#~jO5{_7kn}XarCfyxe8vln!Kd|SKXYkc z6NJWU=f?{lpk>7l{ev~1$Q4rrycK6)*rE(a*<(`<)0Il&!o@;O__9A#o|)-i{gn0Iu{u_k8! zOvPuoi7C=CsuVv$aAGOyEHo-KoPg;~z+7y@qc}!SPoq8IxJNl7(Q5!u_@uFq;+TzOvF_Jnk;WeDM2Qu~KV90M6FTFP zdR|YIH1=4NfJskd&r27nsK%ogiXtvkH(R7JV&&6xYMdlYPotGEXyec%Jr-#Y%QB)a zmRLUgr{Vh5t!qAw$7;}Hk;b0Z$-tzia>LoqoW!$KvsSp~oVPJ=RoU(#=?-ZkP~_$KuvMbfiHni!`PIqhe7Sj~BfR zH8Jw~i5`nI_O$#G%aF#6+TAb2V;K)Cq_M{;kyvbOOiMWIL5IMUc-LC}_R%~VCB^F0h%;7Ir)SnYiYq1`SH1@Ot63dXrhkO0# zvUscu^jM^^$C@s&X&_~*^Q8Rv5=D{3YN;Nt{j9N8NTcJ)L; zSb@_HFuc4A_xLnB+NMo2w?mvB356<=n@9&vqQgPJWP+H}cp9bt3d-;239dZ#Jpox# zT2&y2En`iI-x>j@H{;~TLcg#owT6@+dsSp+zSnX@oLj=_Cp~R*8qTj+l~`82BVVNf zIbYJusGM&+tsLdBpHVJU=5l$zANK{q&{*1mJeaS#rMz!;j;_<)C?a{}B%{X8e;UW3p34 zDiAKIR+qW5Dh*UPl`l~arGZojd-K%p#5mOJxs{^t!N7J1PEwa_UmsE;QS#?1U(ex=tRRXMnWY7%t7w95bgLAR++)0Km6UF$|a``4*B ze)FtdXNcuYTRTG)U_Z>(g<@Avu}yYlEzep#2}h`!ZhL2~PCRK+!33e^S*yR6vsTyt z8PA3Kkj(n-gX6WQaBV!8kj1&2wc3v9sXOo(a{z~OaD0OECpl}iY?hFie~ON~MaLb7 zrS~S#8E2ox={T-@$VumN)*DB@k0sE#pSAk98=d9t1ydi5=cTovdmnET=s0>e&sxpz z6&(K#$Mw@Wpv6VU{F-!vQGY>rAAzR)RCO>VxagAQZv(=P15HkdRLS!<0%21@Ge@UOCO_)S zQqW9qBe&%IsL#DRjS%9`t-M=-zaDf~Qs8iV;&Q8B>dVuh`CO+La z)0aaKwo#`MLj1Yqk8`4FVJud~MVBmpQT)y76Ou zECyX!duo11LqU2#bK`PF$Jrb=ej9;r>%h`#%r(*_%ioQtfU`mK1DQRP!^4vD>*&U& z-qF{@z4b-Z|JD8y8)&@^bmtN#|m&@rQ~o8NUY++zpyBeTt3~Q*Qaw!0&v}oPVC8 zOU94#djK>o=PSBY@>>a-(^jYE$MOz0b%!p=3|{MS^cuS-+<=tmy%m@eXd2=$N_u+kBcr7 zms|eG?=H~%1oO^x$@Gu?@AIJfSf@*tzgIx_4QT%OBXUd5Z-0bs(`kede{T7sz2En8 zlouCWvi$uDdNuM2r2At;=-^~b)faZXoD!L4KZu~X_e==x}x?a&G%OAQ* zZJth}DBbyOLg3S&`{mD4^E(B>e*w)gHz>Mf?QJW9D?sDFF*Uzo2#)A9iqbuQ)W3^C zck0hm^BaNSew`*2zby#78FW|Nq^Od~kNlp}X%wY<{@5S=8Fcru0^ySJ3n1(R&>VS- zkg4Z9m*+Ph^rad!9k(jFz2Ld&^U+X{2SD@Q9g6N~cy9W#01bQPU07UwkD}Wz3BU7! z5C0FovB5>hblvz(K>iAUiO*MmC1mmz*)4zni{RHmGsun(E*Doaey883X;+pqc*r)cktEuLCq64=TE3q2!hYnX%wYNMNqm;E~W23&N>@<)DqvU9b#WaS+Vy1(hP$@mq3&%tk^t>dCgW}gQU76i?q zZ;>i_{>ZNuH0SAbsrX$Dn#Q+&>?8arJ=IjFxs2F_QVKXuQ4(mgyx zy2pn|H#kJPbwi|kZU}U2M=vDM)%fwM@A&B@m9r|RS5?+ml{A!96dx9>sxJ%93Div~ zJh7nQFqiPkhCp3O!|b|Xd7!j$MsQYOPGHuQA{WX!oN9~jWoLz(alZ7bDOKgI!E$w& zSvfaAM~w2o^peI|4YMjsiw|4gy`rTHCv-W`RrPbq>Ke)&*x9qnt4pc^^@sUbMW5li z2^V%!_rlZ4iWij6DV%WPi3>_`!g?sWpwzlQyTa)?>DEb%TiKsovWGJyriXj2YjDQl zC<$y4Fxi{t;}i^&YWq}ePD8)SJV|a$-O;|;IIn$q_)KoC$7Ant;#?$Qe~A;I$ESk} ztB3A&w3}*7R&siWW%@O)25nC%6To0Fv_wA>8Q(zus^#B0k@ZGngAlx?Efs${&PuFA6^O$gMUpl_& zE%siAF8~h&)~k8Fn*k5UsOdnp-$^b|j8JzF`>05B2}JIdZ}JUHDK=m5dRY-ag1Gav zHk=cPrFSKQrWv)NOVM-8_G+I4@5g00mhV1XG~*L=BvS0V0`L#uKM4O|`0S-%`uYw8 z?I`&F!hJq2!;J+%y*6A8^kQG!7`omE*ty{`+1j5$4=mg>hI$@YTLeSw>^6 zm8gx81Y%j8TgkY$78T_?RFfQIYu585OH}5AWhG+{wdjsS8JRbPNtq#=KIZdi_|E!0 z4+^qgkI%RtBjPk@H2JaZG@-wAmYs2?A&maEp_IKy%FbjA$AanZLe*rpNt4+F+o|V3 z>rMCn&Re!?Zi8ZJ*F>>YT2x)n-KE&u)$4r& zX(+m;j>YXEq5U#}wgg|tZ%4SLTV7Aa;lCY3Pd8E5fshqy&U`_ zlE3AVPB7m+L@&v&aHv?rCp|6pAQrvasz4Ef&(}oTLSU9(1CMU_df$X*MFU-zzO~#cOUjy)k@Wb$n;GYYBJp3!+ zPlW#~_$R`D4nFKf-$wYw@F}v%@H4=33VhoAsql}1k2c-M56ArQc{)WI{8Qlv;78z3 zhtIssfPW|aneZu&YWUB?pACNl{2KWGhF=Rm4@MYb>pK?ysqoK(KM(%x@E5^<8UE?; zUxnWa|IhG4@IQgy2LBuQC}ZCNutRwC>l+V$8T>i$+u;Y{cfjw3-wFRZ_+9WHgWm)H z8Tc#V{|$aG{4e3Jf}aTkcP9K};GYG*9{$@lOAHx4N{PW;{2D#Ou?>k1@ z%geLG_tGk>YGzfIRW=06W>?P%%njC8l+*<3gY^w1bq&FaKwSX+pQ80@rL*S-i^>&A zu%>SI+<6W2Y69qt6v6(Q&Lag)9%;%-<^)_4^67jI(qDH&NAsUd$2m1V)2 zStZp0OI8dPqnybEs>@YrM(c?j3W}xTgb;AwiCFd8pgu*3O>h_Rw)XI9hLU zN2t|@Z!e~51d%H zcqYN&2iW5HIAE&H$fcc~?Ro(x3%ihUQezP0Q}H3C$9s*zxVfn{Xoh33>G3uiL5^a! zcXD@cx3Z2#tXW2^U}-qIGK`}JCCiFlrTLaYVy4IZ!0LLuV~wETsgb5G^kY%Y2lS%` znz@vdGlMv|GT0vKSR7p<)jHdtu%$+pmlz>tYSGT?6`ga)=l6RggD;b`S5eB~}F^=F?O3o@}cWr(VgI?6*y%d^_h5N=9rHwd( zRHT&+%C6{=NT{iGd2@>lFR8TmLj&+JMtFH^J@gzq^pPu@Yd1b*3P$lAh;{@p53s#R zW0F=@5yrOKk(MQ^%0t~Pk#HAw*cM6L0`Wk*3mB(NK4=XoA$yJtjM| z;l?9~WEGeTrjvCC*EP$1VOXiwzq~?K+W@T-!4*;j~P@W#{-ea z+W}$sbcA}laKdV+)ohxg>Tiq0o!_XS|MhrZcMalGqm!HoO8t$JD3X4>618K&>~6OZ z@`}^JE_N0P@ts2>E))S?IYa?Y5DATeEMU*%z{z?ZI4Sw2gz)_r4%-9*DyA!w3UfSOwo>a7oTHDTv@ z%)pd~`59kJNLnKMjz6JfNIMd0Yw5%!mFSy87Y$LWT?CnTnNi49Wu&JP2{B(2?^_zEWp-TT|4 zD=Ls-#cF%jMcE|hG`@cY6NmZ3Gr4X)^;VJ8fKsC{fYmK8=43qH%UqgSeP<+E6A873 zTi8t5FWZ}`F~ktH)^!ad7*pLiu$d@)9Umy-slwyk!!4w^xTGW8-5HH^c70V1BJAdhNC2 zXe>>g>;WFbE@Q~G_Ee=$`pBxtmV7YFgH*1Xs&Y}o zSL~7FYRKwscdAXKvv-vUuhlKYD*A9c4E~HrXHOUR!-l4?@VW)0o!lGu`Y-}EOokD( z9ehBF_XgE4d@Dk#!a1IJ$5N^Z&~WWbTs5#)7?5hYX*Y~m^owf_JaW@FPe0XkQCcP* zE-M5-Iym;4ai6}v;?qUZ@AiF=`!`)G_<7Z5%>U}U%T77wh_fo*+i?0zSR$k7Gsa%B z{P>sdoL6&d$A)_c@eo>y1ai|p+<(8je)90;?Wbj4bL{M&pY<@F^8~+S-zB#k_59cu zFMa;(OK$n`5ye=JCin@Le{}yzAJ3gQ{G+q)A79yY2j>0oOq!dv;J7PtzB=jE{9)yr zPufy^5guCW1%J?`|Gxc!`NcVB{AJ(AU%2-OmovJuAaE& z@Wtr^tKSH2dp?_+E}Sp;@rNHU*?aoa+3Q|BBm1le-+uv1qy*o4-t}86HoZJ*>u<)a z(Pn1O!eBWto%LX{FdNv9C^GyxB0u_ z`&`+n75B|Yx}#9G+_XQw`GdgiAAj?9cI2G-Kj^&x_0=Z$`bk^fJEQ#u|FF=g(T7dE z@L$+iLh#qM6@2~6_pkrmm^;_saLbDO&VcejcDZQ{x5e(c?fl@`;Y<2Im_If5HY^Jl z{N$V4_gR@y*}it;C)rP3GQAMX{RDs3;AaJwT+s0N-|qf;{EMDtXyz{n{+WipGe-Tq z=#9hP`s%*9T}vLqd==gi=cYZl=QUY3A6_5(>i*yV^Y$D6iOKQ>f)7o@%5$opB-3IeIB==CZFg3-n8w$KmP6IrICwHi~eEk zotO{GB7X1RAGYTwA6z;9svGXO=)ToARN_^*;7_>aKYyF^K-s3jl?x|)bnRDYU(X6& zD;pM=Kl9vgr(}Ne-L-j-VKQZZyn}}vF5Pm(raRxvo&VCr$LH7g0l!f2<36}`%SD3| zrhl-y?(J{BuPwzV2ZEn{uGH*Ha4(2vjEi^7&w&%0z_Ui0+rAB3uj&;L4;VUcTl-moiHOd~_??W6r}X7by}K?RJY?gkb?BMc zal_Tp)#Y-Ey)2e+s;x~vO={4MJ!{k)?QSURO110FxNt}NP_wlC@-Eef`XLVWcRiEK zrNFz+2c24bxOvz4v~zYux2rp0dg9H*(SCN!2H7+N^NStb+|#`W)19h>L&=$qhpt_n z%}db?W!`uv8JU^cbx~vDdRK=s@tN#h9250If6(XbYJOUF4;#g0*Co6PJ9q7dF+%UM z(5jXtp_XO4o}(VT27xw*cb!vcIr;=z^Id1vyZcz#ISr+mDvKK*T9{C4xVx(<+Oh;) zu!&RcSCx1u%xyMcxlDj#zBU@#Sq@DQc<=b$o$bZXFkc_;WCp;X6^lq(cSD^=BZb(K zetBnymfuj|%MUeo`KG`Nclmff!FQ~0ksyF4Lfv$$n@I?r;@jznzWk!`dMaauv5iwh zA#>9k&rP8xZCoXC|WYNKsNx&mXi_*VFfP!ZxY;89l{C1fEXiN z8`PmJZ5tpJmy1PJ+zS9Hx-~k4GhYFn3);Q35twTwl&y`_p)3uHes$ahChk5!oLAmU z+onU99K)O!aamfs4rOb6Pp5GI1E^18Y}Fy0NT)+tS{3F_ZQI)}59kiT4d_sob{!zD>&n)CrbAiU9f0l<+&wy!rTrGr z-GX~mhqAP%0o^0GKj=`F_6DF^1jo&+31w*?0=ijnpXgAQb_V8QS@LYHM~AYsk4)U( zOk6n>K+#p`P?mNa#ER)l#4XUFEUg?6ez+=h2diH$)()I=(<7L+)E<5T?u&coN!a+OYX$;ew%$s* z{;JKfvYeXODW2M;*|92h$|Q~*W>~Co^Rv)W09Bjgr&R*fkEtZKW|I({lB;|njOF%w zV>KE5wHdJ*Pk*f^=FjOb$%&nk7pL*N(+pJIS3A%+SZC5cCsB~ySCB=OM$JIgO|^nv zy$%_VX9Bs#ddTl%fz7e1FI)RDgNt>6L7XZU`|vaz??wse&T;x%VB52#MKRSGowkE& zpF$ibz2{l^hylmcKU|b!NpYt}ahepmprL4`z!q!KyhR|6r{ef-$ zIQJ2UK30rW!cqe04}8h;Hq&RP+$_-@$W7+C(e<8KsppIRa?w;UoxPto zBMo&Qs~r(5^TaBw0p(X@#7I2i)eS;n3p<}DQ?4E?fc&?h#$Ks2Dn!`i^jAHn;!4b% zfsFI}1M5^eul`k$4CGzW-#EyMwbZ94#>x+@1Ka0nfmbD~_pClMSBusfXJ8AXTx%I} zh35!K(;85|Cc~DhE$j-UwsrNBek8aFndmc>O4#J}U&vLrD!Q=GW0tSx3SE^N4%4Q5 z@&h zkcT18nt=;_WEQ_4$R*eK{ng}BH*jH%mF(FIxk#Kf{Ez)&1B6#Uk=Cz(wY*I~=eU6Z zMltgyf&1M%Q-oMIGWHa#iW%PW6DsWvq$m zvC<*F{qC(9LCr21NegiKKYm#kd$DF<7!^jcK6id_5v<|(7v)Yjp&2*~M7dYM6K~wb z-DH9LEHKk$4@pNwGw3M{1Ezco8p^dmk!zHcL1V1^H@*u{-yg`A4(iETeMGQKYbw&3 z3b`O3tNpQpLxx_Na*X)@!t7>h3xJCP%Htw$?LooO1fMLp^G#>~5KlJA)9}7n>ktTU z+;!+9K%Iiy3~0VUUz<2CfNc`o{`fy#pnCkP)J_A`Ew~W=*9i1F{#E`y26Tqtc(2m^ z*2L|Bj(E9*<^oc5!vQI}BTU?JCS3r~H;9p`EixgVnWAu40a_;fUI#Q&puYo}A<*7z z>bT3)4l|*tCNvk2ipwFXit!UF z0gnKj2RIjS4qy*pO<8TAysFDvgG6^h5J&cbJiJ}Da5{CuC|{yO&7X4 z_}$s)4hI7Yofn-`=;s0F6guND!T=*1Zl_^LzjLaIs#Wywlbh1-fK3g@hn6uoo?K2uPQB2V^X zPu?Ss1s$t_7oF2MtO3qh4UEHTpm7-g->3$!{>A#fU>*!cmo!DiMzEm=O_32&A|sU0 zsFMs}p28w=QSm(4RUo-wjsl$_6o3hW=>g6u7{;Ms4#IWFe?u^q=I=uqhGV);9UHIf z7>C44#|SBb5z3NdBo*#)#8)`Gj_rnFf#p#gb53e(ki!powa<_VbprOkaF>tEaEk#@ z^sH|>r%wJ1xMIgBfpIAMCS30uHbp~+rGLFayP$(ZGz#bL)EI#^^f~fSfy;2r+Y%|Q zd@?QQ)u!Q0{n~NPlu0o*N4xVwSM@N1IKWx8VRXtB$TDC*F&?l4LX$2 z7DVhj)xlwrZi1+X0mrOU!Qb1xq89z8_?(>^#kU9WM(2h{coE;3x_J0NqQpZ;iHA^@ zb{}FX+ygq~BA#avgvTe00`MV&_G?6R*G#O%)>0XTK7>0rF<~5vYdEgk$X*;Y)A7+! zaWOVAao~oisvR&mwoOcYdMfmoKD7~rGCQD%E;i0fD6tVzVk4BL4T4(X*6EOljn9Ug zfY9Pkg$tkZ;Jz5K^6>phsxE&7Bf=RHWV=q+?>~coHm(XsyJj5H?1$^tl+x?$!pEan z=;&(=@w00Y9U{3nJ_j0OP|jBH%U`42`YiNJ+bOv&U2@#UKuL~}k{ltt9z-mK8`Pmh zh1*RdckC~KsjeAjPlH?O?x}9Np5? z8rxjhMQt4i6*)w04o7!X*ydO?$sh>%V1IDBDKbJzWQ1IF?THN;>8j&(e?DYQu(o*7 zIlJ3F;G9Kg9K)zhwHDo+hbb;LN`BhHA?jHGjKqu?dKN`0VY6u#;LdPN-#Ibzb7&Lu zbTfP!+gspMR4t~c2q{q!Qre|()GmdyYnL$sQUY}CLJjeOgE*)7@Ew-s-1x{49|wwG zp)o0E9jzF`^U3OT-!VfJp*d(#BSm(lKAk%~rpvArKeI2GxrY)HXF`=lBc#McNDUMf zjJ-tnUwO=nrh{4{YiWZ0-+i!8_jmz}Ei2wxxT-s&b@j9;n)imz!VK4e-rb)n>q(0B;1m0q}af zTJuQpV7XVX%RgByKH%7k-31$Ao}AYm7O2$3VZKvzH;#X{F%;xIJCN$liu zfr%RcM7__`ern=w1*GEMXW||Kq~bnf;$8-%;;uJw9|2Nv^T3sJt9jaJ{I3y+hSd2? zb2LKofu}*Dqm?)kK50M0bq22E9qP|Gq&XOVecZ?zra{>RGEHv!P`4AtbFgHECwOf3<#+iC53w!@f1#)fq%}a z1Lq7r!nUk0PBAntw#86;JThkD-6eGq?0ar1A&{;T9+cZbr!n86m)||wzfE}k;U=^ z7p-3Bx7Z#&CDlQ9^RVTH0Tlz9Ex2+MY6eszxONk|1W>Kut}>xt15*6hXR6RwP3X^N z=+}T$8tLGmIMb3S=vY81v=WfwS8s;WDk(ZXZ>Z4A0jbn}3P{C$*o2-mLpK0YG5&6b zes4m1<5^pU9tB9HQ3yzJo^3+&%+QMgahftuy9Q8lJIGVY{3x?w2N&VN4m-c3w1bSp z0o`TrCnU3jWNJ8%0cch`$l1g*;&xDOliES1$tg8Hdm1Ko3c7#h<45qBmn-z)KoiQX z>>wd!2MH-VsBpA{3I{tF3vdY=-?nWIbjKf0lIZUQ-=xb^APDOADe-tK%=1h)nF}vlCndRn@`U4?{oCTJsOpl7nGz~$P zrOQ%RtsFk{5r9vovp}Z=Nk|EjkebC&IL_iIoOCET&j!Ba3cP0nTa~wso($XhrZNX_ zDq&+X($Jw`36?joE&g6JA#AHL+INZfrPY>L>aB~9L{0qA zYKxX$jW>@2G)?Mliis;Xah$DIbPG&eHy~BheSnhJ^csZjXiYN?rFK%ZRSL(e8wN~n5 z=)^{%@fywd41_!FF5`^EbrY`tu<402?e184z_(T^nJH)O#H1SIotWGv?ZlX-vk80A zWSNgq@Na_e)0;2{7^(>qQWZ-`bz%y~PE6raG~u}I6~h}};~3cXD9iN3Up4f949m5I zZM9S%!?G-4$!gDDd7O6M%}FO5vV%m?Kt=s!XKwsCD-+-swAYUl2Dd*8>kfSP92i@!quBc%+cp3 zoYNBhcof3&^ng)6=~9QwUQ6eC^B$>2EN@@rZag{G^9F2kV2?`6ko}NDXCInb2i`)FAmf z6Iu&M4P~DPl-vruiO>1YorLTwTQVJxdg`e)ad?fPD^l3Rah6vp(s?HCMnFoD z?g5lsksd@SYuTt>+8m#L{~3I?ZKonJjt|%ExQ^d(MM5myQIWXiyrD??=@Q&e-q4)` zwKHs8j8%b{52phC9g5-uehYlg8+`_!`TRmxpoM9MeIle3h)|X+(Neev+a)&t51+qDeBGVVYoc{(BwI zi?9!)k>cy{+3~yqpB>Lz@Y(U4W~vto}G~St%Fga?X%KH3UnW&zG0H zr_JYh)%j|laY%Ckt`FkP-(1)fA2}Q|)K~lF`$FTDt7Sq!-VIbBEyFSWC6IR}{K-1< z8BM)(eF^>vz`YEA0elPv`p$#@8hqyWb@;5qDTuGeri4@-5>hW?6>gnQrw<-H_PHGy zky7Y;f(*@jku>qGeCveu&@%j7z0R0R<5Khto=2pAbTVFNorexJRhK*ip&Zw-I_OwE zociN^vg%L=+PdM^y0vO+tF&r^(yFbt z+S(RcwOE(ZiWXZ`YN>v|-#K&V-FNSMAuRR(O>*Cyd*;lUnRCu8ckayG!ovA_o}exh z;-}1N!+HRCQ{-gnK;2|rChB|D67$h0oeEfua;ZQGsXz$@)??UpsXZ1RmtlQ*!n@xq zJl}G(10uYb#cC?NRaSU}RCt6$cr!64xO!XC+S07HqdM?}nfAquoU?XHJ;zOQ8MYm# zz5l0q?&LXko^VR}N)Z~ZK_M#jV_dnoT*vl`&aJE5JkCiR(z232fortS&KQT`T!KC^ z+Kp{#yYfmtO4SJG_@+wTSo@!XjR^&Xjttm_pGDKa8*|FykwohYnA&( zxz7RIisUOR>u`T&Ht*?(li6G{$hTr8q+%tME+4W}+}nmuMC~@Jy-zPqTYji}$47Uz zx20*lPnR~=7c_NCY1)?lxu)e!aTW1gFJ=g@N%-j_7vkf6|DaQ)WRGnWMy*EF?AZAU;HN4>aRViCgIRI1V? zmV4;Qe?Bgjbqp@LTQOW=nzzA+I=CgZojuSU@CU-b6Fwg>*TZMN?t)Ksoe3Fe6GBMU zMJU}_Z$dL<0!MLdlM@I&1LVU+pcH&!`{&#d-QEb4aacIE>c931blTEL>s|^c90KC~4e*)nO-5iNtiTAVzzC_p6n8J^73b^3672XPe^(v=1B>A< z0B)?$$QXxx53l>WZ9c1))i>0-N4EE{vx#jl|A{n0xLn7yX+$VCDv&zNHi$tj15yo& zkjjUUE>lum7osRG(eV}QL2+K^)AKQrv|#{Xcijfg58;X)Y$)FbtkXGTJr3|t7$<#|wjAZ&kV3Ft;98}dm=*u15cfC`Gh3YOX`@oo+`uh!*SUDKWb2kM zcJI)Vt!Y3xy!X0O-W^P4uc<|N=Z&PQ=#*{r<(-|xVOxGPJX4IUj~Nn4UFPs3YGz0J3_w+an-6HVKuZ8k6^JubI{kSGAf2na63|EqeE<+w_T@Mm z0DS}~)xp@_DH7bPfOZP*&o=ZQ7Wx8^HsvRSM)`5gE$bb=I*MNoBXeXY_BR2gipA+J zYqn0`5*%tbn@)tHVPxY8h&AzJTy9GMP_{d-hwsX#2Egf{B<)AI_zZELuZDgPxYH3v ze*@cOap(r@#~Jt;mBPZBs)ibT^RG2L2H#XHZmVy>ms=Xb*z@S!PqyAfrx$H1LTIA) z=NpsmXCFCPn?oJvp^eq=xmr|yl}y#KS8 zq)H;vl=RDrVn|GqmZm5%E6=L1HbiwD<<<=2WH;4dkkyXUPMOxg9|gY_KA-%;@HsD9 z2me0!3*bKsAGr3H;V**!C-{ru)8fFdeJp%fYWpJijqsUHGhl7K2x;p@C|$;7w3H0z zC!iygF1AXW$#8xF9HDfX+@@`1I9q@tlrD#S(FXO9FG4tW3%{BMdK!WJqxL60v3~Q3p!jXC$Cc7$JvaGHy9GM2Fhds!r=v3`G z*Wi*r=4Bi%Z)A#Y52_EGp5UJgMd^igj6YnaIzVw6!(gOM2I-C3a@{?Ycu%# zUY54;t(0WAiD+Q`|Ga`ooSYc1uLxzTq+vBWvto-V|jm+Zo1toPAhx1(|y zZVo?gDGPFQgvQL`=efzj zXI}j)05)S%m-*iUpJn(XeAY|WQ8fWVY667Po$V$xLw2t#4x_Hs+cV>@0DvVt!?G^^ z1ZzFbyO^@wTT=2jrwM-Jd&FDK&p=SY=CsYFyCn40_axAL64ZE`OLw|2D9zNKoK3JS zZA(h_=FHSLH^$D^KbwLtpt+slSU}}sDm8$#)4Ul_Vzamlp%jU$Fs=hQ)?*f2IB|y0 zEEwllT-V|{!D|-LUZ$|Hwn@j*WbQgQ5y$abg?;zuKCQ^hz6677rtM$Ub|Pvv^HT_) zc^YYI`YcF7)l5j$Oh^Zhit7Ts;yAd5lKr!-(U*KM>Oos zjS~9m*638KjR)Q7gc1eeZ-X0vBi3J(^g7u%SLpFb)*P4$FDlt=TbKMqM?y zTtR44h*g8#O5mzN7G|g#{)t%L%EojTLXyewb8*pacbsbFaz1w|@Mj_+ovZsVpj3Xw zx0}i^5ux5z%s*v%3BvtnB`^-VAI{#LmZ&n|yXP_t3$&AnWL&};!B?0?ATozcP!%Ig z9D0&xXqO5eXz&<)%9JS|%L{?K8$R=Q4}7X*He{hHA*3oHq*JGg+hpkc;|P5v5O);O z2T_;}*ZE%vG$X+OLV$7DOH*=HUh&ysZDAp#hmT=mnAqPrJjmxj6=yVmv?!`SN5B3BALr^<q-F-@3w^gj_5lG^X~>^ z95((#aeeAF*1)?9ROa$3e0?e)cP6RMTbYkP+L)+2#oP*-#$`*8ny%vJy*xv54*594 z;b&Q94%y#YGM_YZCg!%5=qIG(!Z516K=E>p0pum>yA0CPW`U5Zk5D?_6grCgt%1^= zZ5FrP;-J#i+b8h=)r%hAKFzCau{$TL6hE^i z)a`6RH0I!~2ofw_Q<5aRbaOO$78Wbz;^&hq=4OMMvPQAU?a-}48Z4v~Mz|q4v)T@E z-FMlH+ehPi#9o$*vh=~HV{#sS;w}J#AR8Tcr-3BjO)(Fc1}NZYlX3$&PfMvo$4B4Crq&1 zwPvAmANhi_p`JrXS8tl+S=X83bdHz72Nms|BW(>YX_nW1AHaxGwSOge3ya z2Q*qBK9zkWbe(`c6X+H|BP8@8K%WY3qlNwmNV%|CQZ7e;Mxg7#$=_Q$l>(X4n z39UH@T~MK{dhF|PuPo19u&(=C_MUvOuro65Ltj7eSc*xajO?A}xdR_XiTHo}xK90_?GFZ=IBa`%$CTP$}kSSF-=&4lqN zg;ZR2<8K#v8Aq9N3W(#Q#|;j8lm(nWhmUc-^9%Tw!+#0>-SA(A|1|tx!Dn|4Yi`d# z4qt_TF8trXUk(2?_{{lc_-COMTi{QE|3~<9;lB=l6Z|*eW17i%6aIGiTj38vp5B6A z5C1Rl?}Psi{H^fcgP)0X!{Duh3_?1{Ae8Prh)~*KhVwlGrOOKrT4;vDyc5!er?l=2 zna3oQE*rX)--)d{CH1|2q1VEL7I}Z?Eqrx0GWv{il8PLsw zyAaSV0>LN(HTN>$++iR<=Q2EK4Mx2s?MJx2kIP?k8D}sq`nA^dy)R(oc`T;pG7Z;} zx4ON4&*Cm_=0k{C+{_&p(H9>}O_ktqx5%VIk9l2xkmGOwH07pnq z1yp{!fKz@lJnk>X6!%;SnQqr*ap=6g3+OTabqA-ibwi2p?sgYm$nK18uQ1c}zSujw zvA1{5(0v)M^}>wp{tq(%&Mw{NhWc2&qq{lW^k=+-BO>%o>FQ1WJ>7pMK6>wVjeOS7 z75bw9eFX8~gD!xy)13=wEO0q8xu@MK&0AwYStiCe0BKiytBrAw4Sf`l^7{!Ojr$TH z<;QnQn#S9JwDXHsT|Pi)e_X8dbez680lr&ZsB-_oCyYayH*j6!eIm4{*`b@8wm7_E z+R7zM!uT{;jrM@j<1w+I<8z@~6*ybzS?AAg@h(9v&qH6OFC7gcUl0g%DPrCs6nWBN zo)<#q-s-Xz?+jRuZ^EyFkHJg(o$zmk&$8VPpK@Vmq1A+y|!iUCP^81mxExtT<)wF9Fz0;p!6wbnpuybeNr;&=lghE4v(^o z%tZ``hlQ)3@BMK(+}l~U3FYs?ewnAxC_D-HalnrPei-omfbZp3Wb|>R+g>Wc$h`*N zT!+5+vM9$Xv(S7CapoTHBoMj=P>n$A0CDa+$GI7hj)7T?l*{uL`W+yx-v6?=Ll95t zID*&eJYQg3ln&kDhIx6ulW@2ImSx_vevOd%$c5XJ z{T9uDx7U0XVg5rc8Hc?MeHpX?#_X%-wDZEk`o`tqNQ=G-o-g70L_#n5&Q@)|GS6vz>(%!TmxY!>R_AR_n2PeWCB6w?Uwj1)7YCnq;N!* z=ZUi(u>bufo~7HFkDtM3UYUJC+GdcWRU&PRs zCj=<5L zc`yF?qc=7$&o&=D6Eq&G@R=lh0j*=AIlQQw{wvMFgMc{iv{M&aL|0KQm{ynX(+mTd zK6ssNA$DwYAg&x|CZPEO)dBjNKus3M#&4G3uCmZwfb^m5`+(+3=uZKy1BCC30J=hO zn*ntS?j1l^3$z2!H3HEX{qHLN3tT&{G+cBqpe*??Thg-HlaIgJGfqA(`gw_}ePg&P zf=v}-r|lqg9T}_J>psahBjb)_Jxzu?aMjgvOKWAc8-2iC*DV( zz)P`~y?ZHUH}CjgigDhKIV{43&v!4=c{|o`PO~L`O%_~H$Gqp^^0us)w`^y5@CYj} z$_Bt^YL`M6Y8ZsnFbJhPZ<){x?%onQd}q|+9MCA8zwgT8!?&C*6@80ho>xlyBdj07 zaw?+lXxy*?2+KuSNW=K9MT26xz-M!13U(}#&v7{Qq0n3lEdZ3*6qX{CrjUz^&i^w1 zQ{en<4&$&>s=`&|ZF4-+zA%EBqO+bYbNK)A^FM5dig3A(<>pYCPnPZk)Qd11%HkLB zPlf+W_+#O}1fTMG89vRb7Wz@MBBW+TC|zC@D2|U+iie)DB-7oDv?PV z0_zu@-w^m7#{WFTI4t~ZTt|5gA^KICy|jaWAbERq2HX2~Aol4)Kvdp1T&`nYLnxs4 zIp=%e&-_0E|2X)M!lz;%gHI)XA3n?W1NcZ}!r_4K@U#INq&h)LqV;st49#$nERecRik26lNu;>((+H8o&nVRTa?cE?uLH|l7P zX$GD5sl#qpa>f6juVUJ!3J-SCB_}Pyx}>RgWwGE{idI}vdERu7@~w2tLs&Ep8&o%>`BV>ur;HEFrk0wL7`p>&7O`ikpspmGAYJE590J22K;4^0(kp;edncrlCWJ3%<5zKM1`&&BfZ5^Bg=|UPoaPzA z*hS(o1XwCAG%}RgGS@5>_mS+3yCl3AS=4i=6`F)nD#Rza5(#axxRro(qOk)|;?d8I z2&LFv_4yZ!Uw|iamzJD5ZhGH5w%B8iweB8?q;bn z)AsKRs7J%b{49dcJS{d2-2%u&6;DVNPe@;7DXt6jij&t?iT4Hk-zi>II}90(DqeB1 zidWp1rTB5(D1POar1&L9@r_3DO-AwTAyx5&RPlsV@rtA375D$G;>SR4jzjo%=zp zxQ7koA8WXy_Wz++a^j0cyN~~YSXzx(rdY8MQn3(Hu_%sWQCwVWarQ$joR%o)##;XA z4yE~i&Ca;@R4TD^?R<_1;c^|Vg{>d{t+k9Ym59BJww{DkEQC}nilbN*7e_1`x9*Qv z_Ed@b#J3jhbN&a`vfNlpxfKf`6$>F1i{dC2#T{_5?8#dG71vsNDwVyrmSSTq9CfI* z5K^%aQn4tGVo_WivAnvqn>xg&C$CQZPnGeEg>l&8_QTaTzOiUO*aY{A{V#domRbA1qV2)O0Qw;Hb$h${XVS1vBs6f&E7058H{c zrEATbPOb$}sS#4C5z<3t6n8J;DsEq-HdJIa06hM8QhPCKb1gWS=YJ-(?;EKNw^Add zQX`~NQyitHxZ4qew{Two;T(VP^+)11p<@_rWj%mYneTc;po9?;1pGu|k<$eNr2$$d zP$r<|0#RrM0&!MDA+~FrwMd2Gxww#pasjnTDD}BgAOL&iuo@cNnX}6UN|dupB$PR8 z7brGomkKU~(8~mhm$TxQmT;ssR8u&oc6t8LGtQV(y{rLKO2!*hFnC14ph&?Pc|+&4 zL~0DSc4cGLlKPsKIeN4iX99JaZcgBAy}=6$Ph1unkatQtauIZt^D~k+%6X$eF4f>s z#WMq6KP@Vf;P+xEIm<^!Zku941pU0AD9m5jKmg)glPfa!^fW^hWo(AXAs#)JyhB-} zf5r00je`QrFa?-Wy(nDM8aMN9PMG=M#>D3#r(o=Ldy~939+|%`+$iTi$M97-`(B~O z%_`qr(vjO=Vt5FeKko{fl2WPDaHCRp6&0@-nmtM}HhXJh61vKB*UtJi3Z{?CDT4n~ z`0d`SsHSO2^Wgg0x(|O1&GF@HQC+yIb#PwZb!em%Gq^Sa)hrJqo;3c+NzW0Caf55a z)yo#-P9u_KNKR@P#92A7Gc?nQqo6?J4HkHCZB=WP!BR%aNt6%WGdJH=p%8x=Mkh1^ z@ij5;6f-yyWyCju$w_VuA(lK6I#zGxZQ((VHx|t*ISIn_I9EGv4oMRms~0fQSU2VM z!b(gxR;S@a8pLW1x8W&I9Lt!TbQ}W40@`}^`gasBG`VeZbBNHKfM1s6nycnME$A3N zY(kQgDh-cr~ zWCi#fE;MK2m$9pEIPSh6AHH2kPU5mgm(Sq=KI~4ClVIS&XWB83{yxZuxlK;$;x8_` zoB*G`z$Pc1j9=#G)uo%q1o<2xG@J43=BICf58H&~qy_jzww;yj@7x^Z!^xfGq+CzA z`UUuK@!Fo`j29xH@#g2K03UYx$w{PSeqR6Ny5oZR;p2UB(pLPs*gmnz~>~Parqp+<6CG*C@F9KqIJdU>!bjm0X^VziqLrL*MI;YuB}K; zIt5B+4LRe2K1+l7IZbHTz`5l*HNa<}(C}+=lz8F7BOow;xu}KYBrl(V0X~C;h8kh) z=T;fS8O=y*&v@YgyuCv z1J4;A;4?yKeurO{tK_!Zw*>jH)kSX(+i=S@BEY9mXnu%a_IBmR4MAtc5_;|VETLh; z;_@jB@EIvIu6%y?!Xy6;@;O^*yz&_t;B$`9xaHbhv*3?GKBI)jTds2ge2RqTD*V#D z)Ya#)AfIA{#LA~Az^6oL&gCzzoQFEi~SCqa?s*jL?V#0KM?-t5CW9d`g98 z6Mu2hjS2AKXeBwRdp?reBrl(_0Y2k|4=t9t*m}#`sBr%Lj29YjxyA+fOc0u>_)W#t z{@1^}734E9z-K~$&m^H?|HWK>)PR@0H4W1!%+v_+vkpcIml-U zLSp-`$pJp)Li0V?JVyg5e;oT{kPl0Z{tGmR0-`Gq@ZkVDIf*>zI(|I*;~<}D2uV)b zjbFE16#+ieg=V#(Ir+l1KM(SmAv9bb;_{gu;4@Qb?!s>hu1CVnVCDd z0Y0;YrUAcn!v?@#hT`jH7-U7y=ZgZbfTKX#ljFTiKM(71f63+G-Qwo0Q|C6UDw$GQ4#X?r%gh$6~At|8UuWqh33Ebr7nIl;=W};K1+q>LX^vG zf0_e)B0|F+3aWQb&HJ!D$freU27-@kKal_*RBx1vDUwh2i&wP;`5=p+;WVRLuGRn_ zm@jBpgXl_c`96fBqw?GzC6GO$%CdAzevuhzvhcKgM3yBjraMhEx>1$(B$Bk z?#zwv|31j)0)!+d6?w|FD!}JLp>g@t-gaAFkk3UzMcKR04|}ELByWB$3-GyIXpY7&-AAAHxguDuH3&&g zdI7(#{aha4gJ_^}`NV(z`g(xR6#+h1_JGgY0G}%Zd^p04=I4QJ*+YZn>Im?;D!^x5 z5BPKj_^b=?xmsxY2l!koG~M&LF2Lv70H1FN4Jw0J@d@WW zH8PkVJ`L&fyQ}wa1o+(013t9USUxuhAE2El`2#o32}w>c_oE2>5>v^ScCi?~kc!3V zi#@@8Lu2VnE5Y1gIlpdWX;~fT?*=o;(tKtx6D%e@$&Kdb@HB%t%F?h6qU&cd+!jh# zWHEe2L|0-l*Bi_%i{Yy&x<-rPd^p{e7W0 z%rb+y%3?YV=4y-K0Y7w?Tg=l2v)p2~8cdeOd}1(}7IQc|RJgttbE?4{ZZYEwW~Rj~ zFqrc#<_d#pu$cP|<{XQ8(O^bc%-;>B&|*?eC2Y2sK?aj!F%t~tc#BzVFas^7!(h@a z=DP-yYcanum{yDVkHOSh%%D`2&mxPNY%mvF%nE~Px0v+?bD71wXfV?)W}CqjSWJ!? z0G(u9tVla~} z=Ac8A^D2v3U@#Y2%y$i@!eZVvm?-B^y7C!oX^IVoH1$cVlHArz>GZeS(4^T|cL7rb z+9>83V47nv>3A?$AA^}`9u*>%&qW4PZ87&4%ovN=WH6e;)!=BF1Wy*<_0VYO?f~Y9 zOgDnt_MQ~L3=3e!#9(qKO+JHMUc)7$cL$i^#IQfG7>o}bXO|Zra$`waU0w_s^H{Vfjl^mIwk{@Cs~01&+P#<&xRGT5 zlK4x!48VSP#n8s zQm4pv#$Y%KK%|n<8~T}360>2%;TS8yl+%*LAdg< zCU0NfcOn+d$01GZ8`W=i6YG8xi!`yZz9q3}dvxDA_P-x$?s@l|$suXnSh;*Om0jg{ z_a}JX)46r{a}(=U!Fk_P-v&%_QV72=Cg*$iTSjXHx z6xGm8^%@h4G>B#E2~NDSu~@FB3Vsd4abtbg#3D^>T6aq<8V%kz>x;AJkt0! zFj3p+^^K=dbT@~CO)S#Hro{>twT-uXU2}Cb)+7^)G_kSnmsm8@WL)apwCYSO(!|Dk z0GOyW#{Kv&Z%5OTz4r(wjdHrj@Bu>jwASQ~FFT)i58~1mGN_9mnOH)DRThXfU1L4e zO{|wqETLf%&O0%w6Z2^d#@pIFjL>L{O2tp1!ipF{@Z#eA1m0`At z_1!?M?*S8yb@rgTA4OvwXJU~iHmyfuVlDsSyPeTk`6d==Vq-lT6YJXI*Oy0Q6`NS3 ziH-GGOstv1=gyDDnrdQ^CN|dhC6)er@A&N%jR`Lr>O?5>xDks-B6t%S078T9NFGzSPMZx$I$8x|@y6}QX zRYRpLt*dHmEvlTHn^#<9NGm7rkv7juI;wJ9(d=_)l^4$%KdyXuDg3;m^NY^MR?g;S zSoT!a&;YQ0Ni*&vNV?7$Ro%+3HWn4lE-otrA?}Ouv>tQcP`{utTst-r4v$A}BaKxJ z3}zyXFe=aPl_)BjT3lK*D;~1Aq%03v0r{+0^5Wu|c|{17uu2~fe7I~wVl$I5j z%*-!hL~|&TKb$#f^C6KG(JSMlSH(w(^uAQ`^iKTK7!o z0JXG_=hK93ofRY~bMEu#6FW&)z}k}=Q>x?z;T{qSZ4nWrWz(XPgm9U_cZg3>(@ zpg#$$!RPSFueLm~Ophgr9!J4e0?}Ptfstao+LVuS#iK!yAjhcKUD`l-SP;XjU@v%) zHZCvNlzh4<5wCG&(kLOx#AN6iP18jc#4BEm3c4XEs;rnkx^ncwaLwXrtyMLPXI4d8 zibgm^m6a{wnq?6T_A6@`h@pAY;`(sWPz;@IjMA27b2}c71!(xf=62e`WoX4$G~%{$ zbX(h4e5olsuBx%NAsiV3TzKI^y~&kUIX0ElWx*@#3%uw0Rh+|O0ONv+z5fl)j2^w8gnRo8QqKRc?6ULR5p=Qa} zr%}UdMhzKNpu3+&73lUS>z`R5Tq}Z&YEhA4TahQdPSCgm=;nU~>gj-uUqX{T#YKcn?rYB(tC8d{gNglhps!g$Oz zgG^Qqxi1(oLQwAgkUFJ^-p7UyH4NPF>N*?Vwq!|>-sI&a@}1N3hYTGOin{zEXBOlY z3?G(P5XBM7&&wM=e0V4{Jb%Qnp%OGdeNxiR&K39Us(5~*?r_7z2Ilgjd!Km!9Il6t zAmnlBSurcB81lkUd}^W}*1(r3-DG%0PF9Ioc{N?J`d#qR+;Tck?uNNPXy?Siu`n(Yach2F`}+0D=$FDxx7gMx~#Z#W%1}dyPTNPbQEMV=4xEjobvhJRcj344!0ZT;&3ywI4hfUS)lXmGb7z@&>cM=N0(IdPS+_FWkJrqbjhX? zG|w11mOmc92Jm|iG!?bvrfYxV@mqkf%R%$Lp+mH|{BjZSF=&pgBe%r-`XFqgp%Fs- z#LM4i;OB#G1Tz4~x$k)S`zr8@K(ofsCCcAc&|L$XriB3D67hp6J9mL*gP}VJ_wn-g zI`A)p=7D+uaEbVF&D5U^jS%7|9={#H?*iR6^D3u1en%~KIjJ9yALVxj=z2FOO(K4r zcP$3Z4nvoyyzhW6WeM_!i!Kqr>k)QTqvL!R7hNKLTM@PqG7F0u*9e-UTa_+Rc`3hq(DYf> zJwM9tT+sZ{Ll-Z9uYoQTGvZru(IwIc^LO|P$Ql=2clrArXg0JdT_S#bhx5LnQOfxC zoQ8^c-Aa7hW!0Yf{nF6viQiHz30-+%_x#RA@I#>4X6X2aD4zT_0iSvib|mAXBV9au zA-`>)Iq_mrDP1Cdqe0W_k|T(cT_X8)fvyuYWnb@}-{AErRKFT}LMt3S*Z+P+S?`y%Xl3yO^ zLN_T{qWqCxg`sg7#^bjcfr~&_a&!0mSl?O=O?Uj5ziU8u$t~UUqkbPVG<)LrOVIs< zOJ3j-m6!ZJFf>AlpLpeE{(5~2@6mD5CE~~Oo^q>@*q?a(*#C|JUBBCuED=BEZ-Sw5 z8OGyBd#(jt`R(2F>xbaW3{7|Zn7?mT~!W^!=}9HPbL$LF{Cpt<~EAxp?F2f;rwG)fttUlI8I0(9x$ z+cUqBhNe4y%wIX^S|912ADhx|gXXM9m97`Oc=BU?yA(7_9#gtR@*}@HK{NFGO4l8~ zRiLT+!Jhfu0-8aO@0ni@;+V?3wi=?MXbd;-X8$?`VXbx~T| z>CAjxlwTI`_k-riSUNMm7Nt7`bkBn3mxj)!D{_g_^#|RbLGzy;(Dm-ZA%eK*EI(g4 z$Zu2^o_%o9bytpX7Y>KRMQ7*&<)Hmu(uMXE7hNJcrh9c4Ru$r+v-$Itm-=|73m?tK zMQ7=Jq=$4r z=m8z;#}fg%@}f{Ebo$uh@sq}nEgL_rta$q9afQcMmQ5R7IkU9l?EEwG@{W%aK7M*> zMe+106_sO3OJ7=s@;!svBYvk86Ce>F*sv;}TE*n!@IYv+P8^dGH5MxZ~ z*y0(JrcWAQQh5B5mgP0gk=9xtx@_9a(G}Cj_^?wZjhS3rRyytY5JmqHuDfy7I!W2^ zoY94I#>|vM221pi!IJvMsz`mfMa~vfoXJVcoY>pJwe^uXl0BR;h*#BkLF;*AJ-DfQ z5xxvGGCL{6!!ejx-G|sZZTzzOnn+ViQ(bFlK*cGcDa|N-{i^!L1)u-CI5!MG7$=P!GKjpO_A`%gZ4Dyf{*D-&T0h>J69w4K3=J^!(%=fAA{jwMYyekKQ zPCq=`z+?nRd$}Cf6rU^@hcw6H+O`K-T-+0b0Uy`JGZ^=~Enb~74}P7ajO|ANe9L1Xy*t2m+nuYlFU^*emt z@-i>}@cEx>>sUj*DZ zpMDv~)$jH_ls9I<+1@Hyt8Ad%V)}lao?*&(W}Gs9h{`=5b)3@zbW>4RPe-X)Zr0Ut z2p{PyBjdn69Qq$b%ZP89ayi>H^d=4XFjGTAeM@~)qm+v&xXvTd_GBC(lF6>gbzj=; z;rP@k>qrQlLXK07C3E@kv*inyEq#frX==b4j{@g7VA$0KB3wE6JZ?*CRbx#UU*|yH z(7O@c*I86mGp4?3L2=3W#^v}h6*6OkYQv39OY+f&WM}6Asb3#o9&V6tyRP?Q@+Iaj zpqR(LPNRP3>L|qQXW1cUQw`R3l|~{>5y{+E%OetQsBCU($%i_TXB!15kwaC3MmiRu zDbdhyV;EmYqoBqwXfwJkcgeLg{*lBil$V1%H zTHm^i2}l8RY>0>^Pjc&6q+38YGc5kD&s{;QOx&;#!g6g)9G+WUkDVSB_-?P8AWeva z5Smb5F`)ucb*7DlTvxS8@udm=C-k`um+M%6SXVhk`no|*1&Vd60zStYGvJSbe;)i= z__N?&4*z`kH^BcI{Gs462mVC(^Wd|#&4YWR!buY$iA{x{$+f&U=w1?WyY_SnzZrw&~Qn(S@v~Zi9-DdgN97_xE&VSt~{uY3RX-BMEF;tSK*7+(h z+bq3l?#EQ&;iz!|diLz>?KZFq_h)7|ATM-3gIuHI=q|zO4{ewAybo?4H~0&IqFrAK zzZCvu@Hw7X4Zj2a8u;IWk2kpOcf!9C{*&-Arfh!|{yO+?!S96s5&Wy+^A!Nvg!VP? z@n)<2CipkQ{~r9?;p3Y+{D^k@6!>?;uZ4df{8so6!M_#$!|++pzXzXu3ow`oIlZzE zKbm8qX;UWQvAc4{w9?A+iYv;dO)svPK7R7KupFguk_^SP@nvK1Y|tzF#-s4s$r)c( zK56{u@zX0uPnkTkbXMiGamD4O(<&u?<+##{QjGhRHrpwgGOMy+jFMEAS4^2Td;0A1 zQk)N~1cy6@M>jM%q#0d2vouaZEDSSsq;oEERXlonASE{|{T<|Q`uNe6<&%mhmwK|| zvN*<{OzGq?TAJfbBFBQFtbEE0;HAhOCN4<`LLEE3WXhP?0g}EL8=*ZlF1qLPt3Eu& z644Eq%-n~t<}_w*I?D%t+VqOz@sp=liX@MA(z1UK2~@Ul`RDZUT%kR>p{k`twk4nf znBaJUxd?p36PL3F{OYEzhMm+@Q`L&0LqAX*it2#jL{&qWL-I;|C3RU%t8+L)BH1`8 zFuFYl9d}wbzc}yRJ%sUPT6QT0v)DLVShx&RBP%Pp0-HVk$l9i5SUWv%S!0Xrz6@cv z<~hz_L>QhRLR~{sRjZF46ByZ(ASX$HdsNYPr)8hxa#&c^vT&rtI|t*dwCrTmp+?Nq zG`B`7Tb+TxOtz6rnwlC+0Y?hEa9d3nGb>Gvl^{O{rk0j{lgqfes+ST`HB0;T4s-hg8%$#ifWzjV!NnLu_go7pG;Jrpd{bKX`EGD* zF=FVLv$NvU84WT02V4rtdjo7wGCUR?q0ASU@ARsXQ>E;{>?Sj`{%P6kVA)uR9;s?< z;fG+k0ZOEm0m|mqg;?iYyQErn0f^B)1`ELcm-;2O(_rUS5it~2*cNPkuH*`AOdF(S zKhF9hl}T#ZxOxm#A~g$FjtRHaMCzMaVU7aXf8C76&gY4g?goq8N-nF9M#_a5VQ^it zvNhaNSuj+1q@tC!lOwvhNFFpO!G~-%Y=w_96N}y;sl;s+ViFsH(NkLXObDg2a!G!{ z2y}x`5bJwGZT)goj~v`Lh;(HqfHn@2!A2-)S!1}Z8Q+-**V-yARpbvM0L?Y#y4>$7 z=Y!dA;|6i&&`-_;MeoN*6iMI1>@+ZYFkXn6g*1s$Xa)H0Qd;)?JtNK+0bbuj0S*=O zVVCL_pscAjEMgk~0ikhhV(WpeH?3M2iVY*&C72^_Wkr`gGg7@y7aK$gX*KTDAWPjM z?b&4*GFP{jM4GB7YccDpYOZwk%=&!? z%B)o*+S;4Op7cei4k)D754Q9)8?7{B*(wi}iZ@B5JfR8g(AaRewi;WGq%s{$8&ke8 zE7tP!g%Uf1m!ZNjtroO3qS)EkKk8+p=$ZUDI zZCbdwichGG3&xnoZ>ja{r~ZhNA?--GuBHjE3B*Qy_UmebjYkTGckI@5*14Qzk-Gbt z7zI@l6>m&+8j>#+s5u4SS*ohUtVyf%e%f#a_YID8Z6<2g=U|kZCcS=O8;#TlR-r49 z4Z97on9U=*YB2Lvk= z8x`#fGj;<{?@37cBSe^Q?uicPFL3~~IyURk#EwB=a{N|OGDA)N1&R0?Tjylpr6D(U zCSg-fd&9%8=>srto|b)eoJu&YDbiXV3D?#`4V>{w%Z{z%?qElZ-dG~WQq~wb#2PMq z?M$0#W(yEedNWHBHs^ zRgI;Mt&x>7nteJpRq5s4^%}Y-AIx$WjjJ3_M>Nw{Vk1Y*l5#RTAOgAZMDSO4gs+l?Vy$5=v~Ciho)#p zG8t{=@~~P12UD9pMIH+C--+uMv}hPMJ6TD$_nY_aoBE!#?X#afS9L{F>SWHF6MtOg zpqmDN_}k?l&TIYrupcJjAs5fJz`y#!Z{}QeQr%ZhOYOYXnbVAv|0eh$CwygO_WYk^ zYTR??B{KE3bp^9wVV{`s({UV7y14R{_Gd}G6@-#@EQ+qZ_F`jroF{?QkB2!BQJ zUw!)68Ar}~q2rd{zw`7{zu&kV+aoXskd<_6 z`j}lm7;vRCA$1buDfpJ~v@O?Vx1IEd6aRX_e=huB3YNwT{;Y$)^Y7=UO#9R3r2q68 zyX+SiILMU<6!dt;~P)R`Ax;tM;@p+rzo{Pd@|-I z1poeN4}LZ|drU#W702EXS@BcI=NE#%qyOneS=FB(ap?6;PGS4`cwu&UD)}6jGU%!$ zr~m5y+2!XoZhfR{2Idh3|BK%pReIlhpZy^ta?$xmwOtPR|4{JbZXAB)2@8@tSHD)d z`TvC+l9=qu@v0)o|#Fl<^Huzw_6O=dK!?k7aF;X;#t& zT_5FLb@}wC{`TO%hrFD&7*&0R;D0{7ed#fG7QA-+?>~8TR`bFqu-s7aKRo!R^t(=& z*73<>KmEsjcl-k{Eqfh8KH;$s?0O~i+67l{cq;$Z(^60gCJX+TLq;F*`=@^L^;=7F zKk8dN`BKc!DE{wNyC40<-+sL)a>dtLUmSG5#oVFq-uwybQAF_0=su50ckG_&gK2uJb|Mxo%f8pAb=bil8 zfUDlU91VxyADoxkcV5b;$4xlv*gtj5oPML@yeRm?ceZ?fUc;hG7gerHJ*D%*MjXI+ zDEXYc{+t*7{Fjs7IC#>)=LX;K`EM~VE%@vY58nRs*KX=}JXxcU1MtlAOwXA& z;4Md0WJy))!a3FW5?~F+h(q=Hw!!MdGrUCaJ6YN=}2exxKY&r2IqL-0htq^fQIGl6=FN6?;ULXT#!YKzwN78xL;?gra{n&xIU zQ$5jWOc|?ml#B!N^qKJhly-$4u{XHBv0;B(&Lxts1CXcI+J^e-1F3;lJo48@HM9R& zY~XZYQ&8C{u+IBihVzaFKrmVpy$}%{L~y6Hp*rHCA<=ckRE`ZzHM=Mr5tm#|2e|R zDV4D1`u*n=UV=V{y~X~s!Z|Akid8J9o>Wt9oT38+yyA;At&mCTD6+b>+0IccF*B=L z?gN;F%ea|Sw)@WA<{Im`nyXrCIDob|ZGiTcd3XIgRyfE^6lQNCdofmvY1A;Xj?}je zY1@kt{+|03Gw{%^g|kOJFLi9@#I=U^k;77Z_UOJds9k|K9~yms#;SNzmyb1M zOR!EYcY0nZH(cEuIvZYnbBOmtL#Ku22?BT`^rl5`Mj-U;P$;)xh=h#@4U%vmh6*CT zz+jyH<~?+OImKjQdOl0q7Aze7?7&`5`T-NJoAs23yP_!-mJp-GNF(g*$Ah zD*~JDu%WKR4}9TbIPQ}*L!V3)pr8^H> z+@luvI-oJQdN~6yFHR`K8EBw%=TVD$+~T$YDwP;RF#}F0!x>?qbZ5QA-D`2L02(VX z`eS~OP=*sSP`b>2EA9r1>jHGH#K^?#HK7bA%RuQ)yTx5@agPETCoy-BjNu_i9v zsWniBv(Vyh05nNrY&B4Z^NxYiom|XDS4z4A43zHhlTY&ncZPw|of1G*f*Wg~bZ07{ zYQfDgP`Wc8P>tYf4V3OQ0peSb45!6F>CVM~<_YdH1Eo8ifaVJBIs>IUS(rU$?lYVm z1HnU)%Yf_UOfpc0Q*NMi=QcnKB*uCJr8^G+S}3?j43zHt7*M_7o-t6m^CF-{f_vFO z>CR?Aiv{<(fzqA70%{Q4`vyvPJ^@rGxX%of?i`G{=CI%nF;KemCgz8k`wZtV21<8! zS=?@mE5ds$lofPi43zH70tDu`<`^g)YazLIx=){?x%L0PqvoE`Kd5-()Q_g-XTlic zOtN_Q_W4FovA43fua;X6G0B{tpEtOq=z}7)!F{ohhh=M_pf-~}l z#@jX>u@slxM>})uil=v`kfs}c}BUgy*6vHW<$EM)LW z#`)Jn9iubLMHC=kTe`brV$RyKT^$qCR6H+;SKcu#tD>`Xt4o;KF)=eXd}7wr&KX@5 zhEXPIJImHjb@{BmXt&e)RZ?`W;bLwmOjWgZ&BMsg`!oO5n=K;Vll0DB^CU3d`^SCv zkK(?wlT=eXZ)6~t5?9{YSq|Qk2j$z*N$zVqpTcj)jq-cY+S2xp2`OvKF7GHwTU&Z% z$ArwaW$QX;w4;3M!GRlFrrKiM$lHpJvR#7Nay$2pc(cYG8@OLXeDCv231+WRboQE% z29NG^0m;!fVpKF?bE1wMOr=*Ki+RT?FNFubX{Csu(80 z5K@qZ7+NQxsgzFVnymn>nOaGSjLzsR>w?9QxT2$U7nJ=9;~8bAm3Q9Q#UNMt)<(BT zN);V1mv>?vgV|Fv>-xPO*ZM?baO)GxIG+X!hnXu@o^ET=F`z3%|Cob?cUUnDDAmC#2&Y_d_gLIRfX)=$ z4{hjl+@B^m4n9v6s0qJZDwN|~gx@0sx)Q${$_;WFdb1xV9a4k%M_mjlwc+-CDMaH-A{7WxCACj|GN#ie2_d4|M2-a-X{ zluHF5jqxjs`?H1kh0Y@-ZXTd~fu;iLCs36QU1CEo0>sCFROd24lZB3tOnh8Ob=Cvo z152v&Fd&XxQk^FO@!=%Z*#wA>B&p6TfcPMi>bwq!j~}T{F)Z~#fhGew6i|*c7f>&O z>Hz&%LfZggwFY8b3@BA_R{~O<-)QOX2Bb3h0iXimvJsF<{3VO~qs4syNOk#N3uVKs zHAa6x1BJ@~K!XL!x45${ZZ@DH5;`ByNdheZbhJSH7O;k1Y(v-B(CYx5Aau6@$`$BA zK&ruK0Syz}ZvZKmEr2wQt$;L*4*(q}bpHm#ZJ#*~zyGOm4+o@ij|8M~Lx42yAV3=T zOh6j96wrynWf35?(>6el1DEPt1L$dix&ZNkD%JTJAhnI(0-7Rm-vLx7p*sNaAu!e1 z4T!Zb)k#a!2fkD%2hbwHg#hv4F4Y+bh>vusPNH6O9V}wzc~d)|Zbfsl;RM{7ZgVyt zHAZ8cwYwv0ZFWa_%G#+Z9p!0jr>1ojWv(sGM8N8erV}9;+J?A%3Rt}{FA5g9pmc?{ zGw2wN;YZmkwhP1)%<5;eI?~prcZ^F}J0YcGT-w?Rl28c~@{Y9;vGh^2?>WL50DIZ> zw&j-$gu2TzhK>Ev-(G7w8_jb!Q9_84izw}}QHr{Wk~P&MiOr)!n@10jGKM%{UA?hr z%k39J-cp3kYY5^wZObeU!O(#emzxpBilaJqE*iR!f(?vB2Ts5Dy1bbLJjMg&qT>&BjxJ z*de4k&+=EGm+-3%4caZ|V_dnoT=!>$(hyzTn^?Cy40B_ov@mQBFBp^huCMzOD+eZ!5tBsvS3%5m_% zqM^2+7?5r%_F_x0zSn!0fgQ9GjYV;0!>}FHa!+kPi(bU{W5sRtE!bb<-Cv9qW0BVS zDjZKxEc`==QH_p2$610+g@R@T%1$>VMx(6gEDCH6`P zb3O)_?ySYV;yMkK?%Zo}_gh@-guz0@cNQft%0h+E`q@!701rpGc;*SALiGpS4{#1( z)XEu|fYVsfwlN|i#Y|YBD)k1MRVfvwf-T2@a%4Gme}QHIm)MXi5lW+V4cUKW&1VQZ z$7jfl!+v=Rt}|g{>R`zB!(}vLdm{$SG=eVF9zD8g1USjjO^2G(YT98kZEe`Eqo*~= z?Mk`jAX08u$t?|)w=0#H1}e8oOqs~75{Jy~DkWyQ8M;b|X?b$H%CmJl4@lRs>}e zlAtzjRa9ma_3Bn3%8FtZcO`4PjKPh}*rX)EY&av9$@3#jtH%^R#zhghZUF$|Y4>z~ zbGQw-LZ3M>4$Ywo*PB$0IGBUk*h6D5U=K~g0X^o8 z_ZS^HBXQBKhI*LaHSmvve+7KhdFSi!$HKo7K2FV$o%NIhhw!RKLaIhW>2gMg;E1Z7qLz~iC_YvJ*D*bc5047i;AZ&+{NctM=~P=h!7i5HVH6;(GUgo@i_Ah9ZT0^7(V+WgObE)Dl-h?Rq_N8L5^Y!m5RgQKyr3FG}oxGu!y zKe>u=NW<>so^GYrghe^rJQ%7CbML>14w2$GHuyY#kNHkU;@o~7PjXD#FS%wTxe-=! zgj8~b(w(OeOL1KW3f9N8jayTawK3E~t^9_D_nIOWuc&B5uBh4ppY1a=#&HepoCH0h zE2OW@?V)Lvx*cMs5m+lyskh?F!=3AxzQ0$x6XIf??t;$>a5sF`*RNXf5mNCHQo~c+ zCPU{JpW7>`0OK}muK2(~oWEJa)+eVpf%s6DoKNC5Yp(D@vc@}fY7a$dJCf)*EFsC2 z{xGj>-cWj5KPMcdV)}{|6Co87p>%octvK47;?S(E-kv%0`O=+yXY+jNF7@OMmhWQ849j`JNriARTzAe1)4i;hF1{!a8TxTV0I?o%e? z^vAUx*Y2n?T@9-0T!x?lJJ+#waEE(*GFYB(hkJ5cAjS`B_EULoEci^5iu8`kl9HWv z<|7^cdiZz~EB4PvLv45osbUGGOE0CkCqb_`Rcv>9#hcBJ8KTf6C=^Qd=rc~3Rb!m6 zMB0m0-o-4GD6a!hV&z@WLYoVojOE;3lx=2VNv87^? zqAj_j0nln%RCRvEF+IQHhCorw!$|nd$2mrEM_R=ZQpFL{frjE92fgCDQCvqUrrXQ1 zwt?2!GIuv$O-FBc$pe=S?U_nW0H=_sqyW&d0u=)~Mxa@MRAFI2i50d4p?j+^#-XtI zTv8G3dG=3XoFZ5fUtvto-_u-?q6)hoKJ)P)e3s*QlwNBZAypV5RhZ(aFvWGNu&nY$ z2SHDwGV>xvG?z7XQBnX86=qc|!gG?3zGu2T5jkQnnBxotq*Fy_Tih6nn_+QtEUpER zYPuazVohJk80Lc4qpHa`)HKH3&eVO^wCa`>l~q$KsvY}#+f=6K*YpKO)0eQrHkO^`G4R*J51BTXFGN(agjBJFw6jzkJ4?lNQ-#eS2z8P}pCtQQ5}oCbS*DGD z!OWI~WqHDOdDO>v>7KAe+KcTh2Z6V~v*6o8h1d!!w6|Sp8e-CMP|Lc=oU<#f!PQ+? z`gu=O3m(SlQ&RK{$iB|<_^olg?(;;bj(Hmhe+~S>MwR`nDha7731P|-REoRbKr-&% zmjUgpp43r8)O{T_M2WQge^f{R6IA4BUsfIc2u~)gqo2WF4}Z6LQt4wAOGp(9hGblj??JW(OnTlq{*h zuf8SdSO3E4Fr`Kkvs3z-P`qd&aXNy{x;<7b|AYCrfg_$5-7lew-nipEDDVNT=ui!_VcW%;-l+G4Cy39!zg;^opPYl>+O82qc(}&7~$v90!ewjY+Q*n(H z4Bi+(Z_Lvv@JGQv6+Xw}r@_As{vi0wFHYf=VN`FcUqY&1Li)h2xJ{r}+}`LHb!@Nn zJ8Q4>JL^l<@1LV}(@r=S7P|U9?Mu_|eU9oEOHo9>55uQ^zYCxGeFQ%B`zU;N?HN|T zgjBzTRKJR&eicXkMyoHXDOl&oCniP+ zGz8HTk5oDGWj%1~f`2+^9m3A@RXWDu%oF?Gzj`ZOV1036;e0(5LT3)K;~jt=7S|Lx zIZz?N&p2;|wBP*TFqQ%xk8VYW2SRvPfzOO?gm=GJc)t1R z10uSZ*=v0yDYC*Nq{1U4!kdYu+^e@Gtu4)J!;5~*FMTm1$1F6&O>!Al>ZZN_r+H?k zY3{RGIQ`1CE?PrkI~#^jI=2r03I@ccop#5@{Rv$DPiHU=!%x9AG5SO_Ur#9sVc(%^ zN}+ll2aXwPwJFeB=NdM~ylCXTbJLYLEYST_%rekdR`TpDeQx4ZY-MGm+~)vpMe>!E zb+|uM-kXy>aq?tEn>@&hm5_>+P`dMH6Pn??ZJ_i7YhPAx&%?Txi(c74hTcUlrMnMq z1~0xNzI0la`2e7D@sRQNK;{!$)b6f0KS~|%HiqqX1Q2BAhtX?B5Hr1 zyaJ(lxLhf&LYW8S&Q;s>2=lLlV4T6Ymf*_aYYTDclkItLg@skk%?&F@b1Q3AgL?o! z*Fi8X*STp@bJ2AWIhaKDt%G0(9X;SY?!zwgv;$W%u3VGAs3e?(4;a?p&b$`Gr{qtE zG_-jkq^cy8?!0C~Gn~x^+6Pr)>?H^F_a1yOm^gQSvT4i(ld;m4>vOcNr1+9 zbhYMT{B-HF)H@cRbD7dsyG*IPbH*!J!KxD>b`626@iZBe=o*;GCdWClzJasaSULin z+5_H=nsqkU0?Lz6%HMAfcQ6!J8ZJ7&J>VsTGs@TEF%IQ?1FpBdEuP;V4zMA(3u4qf z%o-Q1v4L?M^GN&fj^og!hS&r6Gf5LL)~J#dKvhXdRY^#j z0L8HhP#lMBTT0VBtM}aw^0^EU9W3JR1E^e}c=d`8^mGiP^S{5H2i!oPkQs;V8Rh#* z7JkH`o#j?88C$uySfBl%`)pH$pf*pP2zf}!e?Bf`8s?(zW+NajLJY$DX|3n%g zT&`ou89Kjwo*aq*E|`cXq$3d4osi-UIT?on zqI@3cR!B8f4K+Atxivg39I3}qI;+AZ%j)XFk!gT>I9mS{W@8sj1mEN_FBF=$BgXQ~ zcIFRrcJ0jGGseiyu|g!ILL`*#yaX!6y<(t59r2~x+d;u$Rr`hzAn&ls^tafJ65FYE zOv^;e+Qp7mT2FSkT+!=x&{*%wz;@dUn>Q9hkk*ThNAC0)2n$2-$0@7u)b$|v5t`!j9z2wN$iH6cX z^qt4;fMy{yRX$TWS?D;8G+S_+0G%%oCHyskUI#Qspm>(~cZ9a%VtY*22Sdet*eYpR zeNREmNxmkGaq@A|f7ff7o}mFw(P&=Q>h=+1_ysJUijG6{Ibdu@OxH0bbsRAIzQeOW zxBQ9?*WjKK9eeUSGSQv~-{wK>icaX}xZm6A4J4JT-_C*Vh@gfQ0ezAY)vO3ASq89L zbH=#^f=?Okz~vpHT#cGS`CS8l0{rXXpAY|f_?N-I5&q5a-Ddj?=s=q#LRzB;VKYCd zsP7C})kP@X`3Z2;e1?4RlTfCUyKyVjQO##(=O>PjXNWzhsC7v&X#uB>pUD5LKX zOn4^4GqLhw&PKki*Li5OKttA5#No5J%ZW}_YBD}HJ7d!0LXS9XOe)^o`q=E~Z_*QUaMOSd3b&#h=$SDWMnRYjH;5t*b9d5n*75b&Gdg|RugbnxAJH}!6ehB=( zxebrwoi^oRs5*$S!Jzlnu;`3wD@dftk6j+%vEw|%bsf{DU3+_gRj^a$=QjAv(;e{H zjk3*BdnKgyN=Um=#dR4v?MC-F^}QwKpv{>&ExK{5>fF^ux=)> z8;}!9$d!_R0(%9*hWa$YIGijF<9geQ+N+7$rq)2$>!yGK2?lfS%yo<&+{P)vneqq`>aCxnF0j!nz!TzUq z=BeIT?=UMjLMk^xYQ2i<0=?pV6Th;AG42qMPZHgUtQq0{_auzNETT_#s`w)gBD1IG z7ZyTf_)rXXd$3>iCg76C3hGv{v4ZlCjhP-#Oh;+$*f?U$=_D%_LMj$Qx|l$5k0YMq zd}4|2@rs%IevSza0FxZ~pm5>`t&>6LEt`M7`x1mt@YPYqq3~cCPT$1##_6nZWJ+Bb zHo=se&t&#cma#@hVR~Ckrth~o^uc0tbKx^z^Nh`LT&Q)GkP4TOzHCt3CeSO+CtSQx z=*mh|Q~M!Scam#IxPO5*<4|%rxb8|YzJu9$C1(wCUqt7Z9MktpuF6QR8b0$?VM$E*X507#cSe+*aI0rsC!TskTK(B}7R30mZQ&P+UMl9qqdim`F(M{=J#^ zSImnL?q9*qI5aOlRNmxm)keEVQ@bBEkuPhbc0x>?8R(&HeSpetn>eK5H!r5Y8N%{* z2B#VG8VH~H!lRgUqI~>O;So~d5mNI~9L-B{0pT6|C}qucZ(x{yXpB*WB0Fm8bD?36eJ3=Zu#Zh*O z3(79EAF^u)Uw^aam0dP$L|tG2f}M~?cGJU+Elm;qc685r*BI&f?Jl0|Fbosf9cpBE zn2{Z)0@UsZsq6@;>=Z}YDJ~$pEi#Fb$nf@5X(M3l-%H`Gw0CxEc<3V8+p6KEmlzi+su2(&6%Zj^UZc1t5l?Xe0UgY-Mk4u8QQb9ad^Q`?O~pJSv2jhp zrrN5={ta$>R4HqXVTFxh)fu@BwQ?h*awDXpTg7#ue2NRmZFN^(BB`+t>P~7)5$^wN zG~>7x| z=@3$@QXH*HabKo%Y7UTeV#fa{Nl&DMk&e_kj?}eLBBatGq|#9wrK7k+ugcnZOvFW3 zZa4;%-g#X;pbHZ$o}-RrXlu@9h@O(hB{W^wlRYssqk)uB+JlioKz-R#0?NQBheJT~t(7|L^CVbMM@#$%^{j|LgTTuh*T=Gtc>)=bqkf zBe1yy$P~{?(k1PreNRU+cLtpAN|z$-tbMuCVI|oTG`i1`?#6d}{k5GEEp0(JT8EHr ztWvG(#_xD7NdZsLl5`WtX-Ts4TaFwK$8oKd>r|23M<&oQ^2K1?O?-|16#QeCZ4%~i z`~*Mr4m9yo=y5?VdhmI(sP0tG=eTr7P`}gGa)Q@8n2VYe8ig2ny@S!3A~jkmZZEfx zlJ&mb!ElXMs*2fZb}EIu3E~p80jzY@uQ%g#`PzikB`>)`?{TklwYEOVKA$xHnH-Lj zJeT)0_)$!;O6pTs%3~2Y2;`mvy;;2&oWuVmpv>~m1d-KJ@FMUma6Nc7_)qX0P`0I* zCE89zB-4qAQf}C%^7+VUL*!Ne$9DTSSi^hs0ACd?e_M%B}MC(6m3{iv@vF@TV4SvSDEw;KGU(c zfirTkUoP~^{6gRNp>@(b4NA8?Lb|+?z+Uz#L)ryu;`?|S@y+H)=MdMEO4ARNwkGXo z8AojUkubuM+XL2n+fVcg!D%zY>-6ftdWRmN-mq!ZKROG0eHKcCk zdJIXtHgR}YUGtcfNL)__CBAo!F zaZYEFvMh@~+Ocj(v|iP#1$Xw+#(D7elv8BI8k=)+{@C?uE;%J};;xjiY=^Khq;u{N zH|In$IVX}?HyGVB@Qp4m=iGadqPOW}Ro4+KT~s!bRPDs|wL892Hyszd8zA><^^KW0 zOBhLsOuE-gr>GsdYhO;$zrXpcd43!7(%nu^av?*`H;ltu54mWgb2AOplYg6=JCagU z4@EM$DU#XqG& z;J#F*fB&XnXhL}{_w%%E!Tdk@dKqbe0S?DWy5*TWnd$Ym$`={VBrljog%1H=28Vzv zLCK$2KLxXJ(RIR;qed>-MD_?`yt z3oZbqTzU7SF2mD7Ny{Qo@E5swO6mMgrbZ?+?vi~P`Vk*lS^v!eRAc?K&WSHM4^ypoR2lFs`; zDFtaIrW8anr67`DKP6{$-S}^G(JhIY7cW_o+)h>s$?E$vgegu@3OA=N1^LWhB>%@$ zkZsPZSR^*_&byQ0mV;zuI@~uX2kvLD=fj`1I(H@3aY`wQ0Ef$Trux|^9p~gY8OC64 z+y^$Nk49;7S|pRxBJnzXevK~OO1i!$eI}9nLE^@~P0kB2)@;8zUHh8RZ_QNmw(zA< zgw;h`G)IquYo?mlC&yAYM?ZJ?RC{$ODas^@UG!~NMjGkrCLm>L-+EU!52>@(v4Tl4 zaLU?7vfU}ZFxkBi|K$JI94B+c&T%BnJ{$`)}cnuw!#ODN1;xx;4bbFJ2Q}800f)~kb4jSDG_(n$)``;{hQ?y4A z(MZ7?U39@4-5*u(!%`Idyg#VmXWN3Wvjtyo3trxhVG3R(Q}800f;T!Tc%%EDEqK#@ zqYK{Xq6^;W{-}Z>*N>{tmEl6^QTo-jeQn8j~K=_s;hr@ACAc$TLaj|p0Ip|`qkw_Ss2QeQ~qmxx7 z`35Vuv$l2F~)HBjQU3Y1*sh6J0dBAHwj$!t9s9W!Iii(PX#>&9((ADnC+`W>_7-wCtDjPAcjwiMWGkv_^~i%2G0L^9c8bdoJb7u}89+h$Yb zimb@Iv5)Pw5>*xnBb7xqFE=O56*KgC?LxJ#?UhB&6I)pZ*<6tx-sFl%CRao=F3NhSi(bhVYe`ZQ+vn$^6TOpC$-NBwUwSIp zX*e{dsYw{&?8ot7B=@R$M66oR7#w5xdz@sOvt|#VFPo_QrTDA7V!wrhNV`pJvEB6C z4yDO8kxZ_MWF8VTx*G^*boOIsZTw(;^jFlTm}kMud0)BNPT*r_QCInT&eWedn_X5= z#cfR4$3(ttmfJJe{jwQxX{&1?9p**0JT{D!PQatIBz>;z9Bi-mW7r5rl6A3>q!u5o zbyDAqF58uIkdD#5-H`@r3E{tT7wb?`tRu7}F&n0(=$H-BI*Hj(E&VnzlXGwp#-{#H zT0*5=&w&LK;@-m>2x!0SqnNULBTlT%kMhy#g<2&^Jj3-w(2lEaSj-+++$Cs1BBgdgkVyPnTmfJ*ygnm7%#o z!s$*a&G)p3QLd-{;9^dRC?)=Bz88AS7OB@+PO0c5lhS;(UT-b;tSS$cTdm|znosgZ z+~1a6JI+Y*D}LfMM@#hF`k&GCY>XI^DPEfIe9cnoFWu(q+RWs?WN2QmzI~;?)ziQ< zB*b>tJdDI9@^OfQuMN{(1u3YaB=jHhMpXU1q5t7x(s}+NYy2Qs@UNV@a`L@E5 zn2F>2pZt35NM%m*mGLV%GXE_(Rji#IHK!Ik5?WlxI6E@!Nb||01e%%`UcW5fj+A7Y zFUMo2Q=A=XqG>*voQu2a^^d7}vGI`%=EB&Q52|Ve3}MXYF_A?;CGNRwHS? zb^JPZI>*_OPCv~j?NVZqz2Lz+%?b| zI6G!&zQEcksNHa5yd6n(bUt^Bv$MD6$kJcV)%nMHpT*me)){SQ?>IZznzNW+X;(d4 z_MQ@NhpG@`Cp*s0ewyRt&u4{qeI9RTf6ejc&wg=sax_QsN7A+E;XR&;w{w8zylFWA z+ZV$2w$lUoA1SZ5UbyQ&@pcZ<9B+IMjI+~Sb8g~S+*_I7ofU8AV0`GGJ?*r6oE_QB zN%J{&{&`>7FY$H`jk9w|oShz;bF}<&yl~T*oIJK39;P|ZSPsDZ9b)sRr{<)#bGYVs z?evVZBZEeo?+AV+7V9qg7)5M+@-)ZWPIKezN{$$Z|$fBQ8JA zPH(hnzN`4%p5wCaKm0x3j>I<2CpTR?c6!Iz>7zMLeEvG-!!P3P9H}|p`1Fah(^qq( zXOLX^rQgqVHnI8BPjgoA>%^yToSpufBfYe^kB1I=CEku~6Gr!|{p0Km&>ZPG#Vvhg z(6{k+bgl5w;kxk|5NC&p6z3vSSj({pc)!D~@pcAk&VA&wjAY`DiL(@w$Y?08dY3CmL~Q;Xi%;};IwH=_NX>EVbo$px3*+sK(wx=&I_Vl2XGdnlX+CKe z;tKa(`LB38WAKTN&*(Ti#hT-k*Nd;GhvV&xjk8l6XGf;g)I)y7^{rlfSG=7Pe4^ts zF3wJ=<~Zrv`2NBK^>DoAyveVVKc#VY`c@gr@Siq zPfbu>lQhR0pNVmHCbz-P@o{!0$Jt?eLAvA~-b|!3ZvXd>@#&hXIXNWP={Kgt*_oy} zjr>ZkoU~>5f$?@^mL5GWPm8lNU2~lLN!%{VHOJe&rpMW-&>Wd9NPNyed+BNM@u}3D zb^JQzUJ+-fN^|D$+nyuq#WP#t?F2PPwuu}&RdIHzHAk#LQ#I%Q@NF>{o%%RCb#ZnY+F(aYGkUyeh_fR#InDP3zp@G~eed+w z;?vcnIqUg#%DpkpPDpdI`ITJh)V!RDOlx1w-@>mGpOfP3oT52Y zKAkK3ANSaR`1qWvIV<>e?406C51|#8tFpBPzRP12{EDVbw!h;w(j0N8xS`e>h5nWD zF)!f}?CWyq8m)8AwWrT0GF?ut)pT+-vNbF25LYwPY6@M=LaV88HL^h`F5qgOw3_a& zMs`oc&2=^3Sxt+p+0i71Pfa*+mVR8^Zm#AitEqN1Q>^AdS2NFQ_HZ>9Tg`s1=3cAG zaW$`5O*dEbmDO}~HJP$-!gX~uM_5gjtC?msjjm?C)zrG0+pMO})x2Rf4X$RZ)nvPx z?$WK}_I5R;R^xXy@~LcbBVCPt?hDNnSM$B)3~@C%wz5uiHN{pl+0~q4HKSe4%~mtr z)qHF28_BuMM)YbI0nsKhC*=mYi&7D@0?`l4=nm(>(PwB*Qyns~P5M7Fo>* zSM#*hOmH>dTg_lsBOiknH_g?|vYKOD&8=3`#nrrEHJx3}Cst!xw^;14gZ#<|7M&VC z-fCvLnn$eW1XsgWqILsZO<${tSZ=bKo-XG?52r?tu(moIWBT`g%h|yV^)s63_(e2B z8C1@T(o~~a5v92g&AKQ}yN>+zdF>n~8e9+eT*X!+si^S{haDfoCOFwqcGjWEq@G1$ zcz`S;wR3WHK%C~dI8Ak&ra4NJGjg;n()Dv8Q@}KZh7pkqip0m&$i{-ckmYI^rRWR2 zoFhcj*Q?Q%??bEC!mj1Vyc%u!Gp|NlUhmat%j>+FJTZM9EnKRRj&q(w`jRM(jA7g9 zJajmDXtqXi^3h075wRl?`X)*v5&9}hBN18`r4c*pXk!sOa;^2{22}V zKm1bVt+QQ|dV)|ST?r>TR2WUNQ19AM!f`_7$dpda=ScH)(R%qW&S@dv+ZYOmP>~BY z>NGTIzHEM}aO%$M7k?EAwR0y_IN?N}YXO=xUnaj2>eLPg6h=bj*-*lX4z*B+l2UWx z6_Jj$p@b71>U15dn+-L6=dF)MLIrIo;Y5d86cuXkD|?3`p%&Xv!XcC=H_mWFNxB}( ze~qGZ;(C(}C7kGUE!Lr&+_*~JwlWfGg$*T~=uk^^D4LbdLjdQT>unoKIMJcbM3d%o za%1S+HT@%@Hri0ai4L_?he}*GGVIb9le3!_3!9XxP;Bvg(K zC7kF`7e$4dd;cdCsT0HAHk5FpLtPvd>h$ZMIyw?+uni@g=updaDC@1h=vsbRBvh$Y z3#XkrnSW&!q0!}aymn=lh{NluYwBu3^Ys6LbLCmQz`&d`c^7bfbzpqi=$hIZEs z7@wD)^e~M4;f2bzz)d>A8NBzuOy9IqUKa|Kjn2s}2v};_=vKM8Uh2TIVS!0QCl(h> z96qeLPZ5|Km>ihQLn{r<+zL=$TZ>pTyMh0WoVr>KG;hcb1SS=X8U>O61+_IZ>Vj26 z8iT>%#7Nq{Qlhh0&)d zF3?7thw`EV6%%&*BD5ewgeUoXT_Pukh4`ki;r+a*EV_*whrNj%}`X zno&>@@-hmG$Z1dVhY87(axd3Od&FAExv!c$@-hpHbRkMn=;wCgyrpt@&MGGrqLf>- zog_pl$ySL26J}OaK%!ylZ(^>l;86jbT#mXA&&g?$uRd&YniSlEKv%|+Hr}=ESt0>vaF*_ z^-B;VrvlPMnOE26ky(jZSf_aKXz_bz*-(|udS_Vs;RHj6LVd9o?$BS_!K>F$S)`~Sts{BoAx5P7YOM3 z9d)w88u`izix54{kF62WW^}pt3v?nQ-l3GoMjc0j-dTpGP9W}-HCOQt%Cw(xx>Z;3df8b zJ^0wsLj&fih=E5`4(v5BziMt??<0>Km~S3_aIs&0K!P5bpji79I$jA%!g`L2@A?7( z$1hiR;qld_ubgpQqMq3JtEg1 z@o$+uJ77F>bCaPuJg-;3{OpL6zq$E+j>z>Y@y^T5?bD|Z*e^G~ADEpz-9OTIqHodl zTgIu{cIsZ)6UKQT0g(SsbKJpZUzGD_!V6Y3&oGYxh~JxYl&U|9?@<2LFh5~OE1)t9 zy^jKjPc6q0D@2Mo&GX#GFFsv}&$TNe9FYPl5b$mkijG}#b^kLWMO;ATuJCSaiH{`j z@mOAFZXlK?8*xv@@iG(go=U{?+_o?0-7YWKXfnb{UU7T{g_{WIH{PJ-LLw8O|Fc3@hI5GAd4)@sUb$sz3Y? zF8EEg98KgWkv*v|jqpZKPHj)F)`j6bYnm_RJU+F(!wA3g6rT!kh)ZT~ z1%9P)x=b}ZDYr!JP2!giXO@STD7_sqvjomX(^ALpAnZL4=PS!g7QfZ-+Lig#yBy+@ zmB$$TI!^bg<2l47v$qMqdN^g}sqKw~cRrl=EiaY5ui<=H(Yn2zD>*NRxK#F<;8a$n zwkH>oFM{*D<)vzGpTK!InA+Y9?0pGmT(#lJZ=&+e!D9-X@Ql>iR?-JI}l!1>G*NU?1_Gu5ORx8U4epW5D~@IJO2MC}r#SNfMz8hmQ;oYeNDzkkGXtht2w zw*}Al;l0(E+Me{M9h!WqH;1@n>0N=}FgWQU!%J5Gq`x{4PP64Dv)3LoOW>T{oH~AT zW9So>gQ#7i{FC~(7T(Iat=s$Aa;&+8`6umn&l7#>-yGtS)n|#{0WF53iTosrpVXH^ zcze%FZSP>bi{Z>W$?&=)u_yDFf|GsffKyW2yNUuh4$ilKGQ9m#*c%@9sl(={wkNl5 zmcglAV0hBsBucNu@1%u3HSP4&_M|?a2j^bPOIBaj!FwLg&5Kgoy9?eLIE&>eaa=Nc z62B|pgcql_Cl}uDfm5_3wY_!lCc)`x0;mv}x+QUnfe`3$S)Th4S5SOg}$qg#q z&hn`nIK)YRoy^{5IB%Yv+FqFO+n?i8i#Wu|c@x=Fcs~T^p>rd=MDr_|KYsyd&+`l~ zS$RnNJsi$H=cl$OP^Zq5N?G1*v)1^LD!XZxj z@kH@khkg#6v6rQ`CpTj)fV0Ep5ndvDvi>*<&f!-?c!~1wZg}OEgQ#61dtETo`AVNU z@T%1I!fsx!$LayCJo`n+U(e za$2)@_>Dew?V zdCBZa{B~Q;eC_Vk_V$CodV|z4=+)9 zq+_Pr8$OluW@>xaVs8SR?=7!A{}b7h`0eu+^OCny+pC3lwB;abm&o1*d~Stz{yVAd zN&oURoDVE7S^lkn_YItTR;RXiEWGt_4qsz<$@)Lpj~E4~=-t%zWPj~M%R$sGQF^7n zIt$*E_gc4ij^$W$3Clz5T@SBmZEAZ5!MhR8O3O=@f1BW~gR|=W)b?cms@(^MgQ#7i z^oqSb;Q8eO5iVJMmi6TTIJbIu$?Uxc=jC;&?MeLpV>xnOaf$57e#tH$`qV!;#3hU0 z9{BC^QQOkn58lBaw{Guv%h4z1CsF()|C-?i*Qd58?PHncq_QXL!F%8>`XseI$-jpz zr!{-4;N9?P>-OHZoYw4p1@EcPTDP~^a#Goo{Oh>Er?zs4OIE&;-kzTujwbSxtUQLm z>+?lwdk52j&V+ORSB7_R5_|H1@S&T0>Wps;Zzp((#-r2F@AYr?-H|P z9BVFN{KVcp@c#5;>-LsgPHXmFfp_Uot=oIqa$2*u0p5LEQ`_r?kxwnBHGA#;!~B#( zT(a^Id+KMy5m8*S^5_O{gXJc(*FZhp;}@Sg(Zd}?`;@3!)b61>tuK`Uq}=`N$)Rkj?Xl_WbOAF!oLWoCM$B@ME2Ih zyByA+J4bkl%Htt;cf+aK+3ZrVK3ILj8*y>)xD;9PEb$?UDg-otP% z+9S2S0q~xOleTB-_(}Qh3un7-sqM{ycO;x!EHByku?5~&a6aA3*b`o&`f@G$9(%V_ zuW*QycA2Prdq{nTb7;2VC9BW35&lv*gZ7Q^64~pEy}RLjzF&lwD1KjH@3{TjsRH|! zj%4v$h`lB_-yaZ3MzVT`M;qiPQT%eS_a3}o4oMxqmkD2VXgihJ!|^KCS0QUZ6Z^@4NzF{$mz z{d(_P4x)C6;wR(L0KQMr5J+vW3Jcf4*}lN=2$nFt(mpcb^e#+oPv-O0mZKw=#Gdr` z=fa!CXA#6D%Rd?4uCyFYuv;2jO;b<0aOUP^zp+n9E$eR1pd`oMYF@>1E$8rx3&heKSl`Xcc=d|W&A z42QT>_WUL7)OQ@>lG%F#zwV{&)Mp&xQuX)a$1@+AklLQC2WMH1Hpow+@^}ILVtB>J zwQlb;%W2Kt)$nFaY~9|ameZQO2jKl_QtS4XTTW~CUV(Sf-IKVPHXlur?yk8Im9Kae=;BUPiv?8bBL4QMD=9_`q6MYm8G^P z_s0g{%(J{?_Ey0=8_v|}sqIPp&V}=YNE+}u^-m`GNwY*gJcBp8lUgQv$ zD*t|hb7-aErLs2=&M%gi%3fYoJ5|mhE|tAzI7b8x&$ZXo;(4_TdvMs8VL95MHk!+e z*@YH)AYvi*wtO?`?SPW*V;ar-1~|ok+cEfOC!INj@dw$#}b4P3(Eem#ADeug=Mj<7KYsS<%#l z3D;%1QbY)=;uR+U%qyP6N5<)1*c)nXN(^-TV$Pe5{&+YiTOPx<@Z#*rc~6IPQ8dq% zTjacQUHxh}w^*KgUR}Nsp7d*v!CBn~-bOg-Czw2R?Zu=+>~(|F*YZ-OqY%!xXkJ`8 zq&-Z5Q{Duunr(>~sg z95k*pXX2pocxxy2zJd3h^MI(>SPrw}4ToX>iq6$YozCN9SGBmTMNttiweuLe`*1CY4H%#4;bDts#9FNY1 z<^MoXF7pP!{lEfHrfG#>A8-&j94rD)2Zw-{fJ4FC!C|0WCV>-v85{wA03HiUI!A)v zf;k+HJDa!!_~T5s-XrgNs>t{1FT{UrOx{VDo`hKdu4pyy?0aD(Uq@1u`rQ{gFXgn3 z^Auk=jVh6qwUuwrNnUm}x!D<&H2qFgmo93KSmQ&zSy?h2l}})HQB5aONqFl`t?|(F zIPEdFMEkT*CK5s>D4q~HPHGpGCiPIe{v=DX8Mh1k)kGwK+*Qph;$;>Myx~FAYh86q zL>)156(K(1!0iG1O_$x&+*n;+87!%-ZwTh|YVNG8l@ULQsE$y+&VyC1PhEZEY--f@ z_Ann4KF`?KzfvYrujKOlLaQIhCzz$20^m_#0XPO61TF;!gBO5f!5hGF;A7zN;7i~X z@Jo<)a);BgT?QTwP6sD~!wL&`~_chs*Y}P!$|!%L2cZbV)N8SeeRg*7?MseVRh8(0;!H&F|&>` zK7`10RdYtw)EP^j&u-6j5&%kmNE!Q)r&#^f39`-Qcs}J>Vm#LAbJDiq+gX~p8WrsV=KqBn6i^F!ja3^Pq$ij2i+qXYRzDj;P0m>t|D?s{j^)y%o zJ_j~|&x6tyUjnZMUk0Tut_1%Ez5>1nt^%c;{tmY1e6NF&*Kb;V4t|c?3BBZ$A+O{ygt3llN)y#g~ZX z<~q8zs_N#tO6C&3f%TkRn}+wn*#1M(eHi-99Cx=`2NMqYarMq=1LP+4&ae7sZKP6k zzmxs^`?%e?W51$+ik6{=Df7Qj?aY5El5@!({D(A_&kky(j7&yZ zXq29QK+@|tNuSg+S>ih7O&<{ci2sL!Ux4uA+Ozc00sN$Sh?B8?H2<9X@Bli#V-zX1 zUt1satCl>~f!e@#gd%pgr8dOdcI$$)li0c-X&#Nf4!mz0>Oue;j&t%)>Oz{X3lG`4 zAf1KO3(v$Q6O{yz((j_{gUlXeIFzE+8gF6Cd@;b`IElZM^>!$FTP1VB@K4A`f}Qc} z3(9RdY$=DU!2V!tU;Y;=Fi)+xZeS;FKk$_OIr#8Rwn!Oy%09s>#A4_4yf4_i9FOmx zMQp^B^M7H-Ez=8#^N5%+M$#fym~gba@|gIJF8aXOT)s-b3XeW+k~ z-EmrfUbMbY^kSsJ)i(xfd5dM#$ag#^Yv!al86Z2t4Iy_`HFnsODd?CiCG~U#hvTFy zq@M1A;y$Zn&Zy@g+!_$BL6-r_9E9;Id=|JPcs1Aw#7|{{dx6yHa3Q!eI0Nhg{t4^~ zN_`+h-reUvaXCpo`*pw;^5yev>xMLAUh7f!IAlyOFC>(5+CmKTLZ%HbA|1&NE4 zLuYhXSbZ@niQia|K}wZ?2Y{s@;{|=b3QONI5j+~41j-z8GWcikc<^j+DtH;l%qV;- zSO&fWmV@iT3h>`x5cCm;86ah=W`dG8v%uK=J_vrQ{JsePF){fqVI)2Kay;1P{2pCj zH=(96)NCh}+nn=k2XTJ-Ue`&yB=5y^538+1C2?&4cLnEw67ME3HZRC;l`1b1)jbI# z_F3zzhuWGK`MmKtA*GXI?{oZ-WiKrxgEuh4a_8*t-7Z?p6BU~42X$RJb z0~wnnFTUnD93i$2NEr4@l;Fc{PIpWlkdrztG7u;`5XcThS6bP&bnm}mSQ#l~y)vCL zu$v;Hl6Xt8bTI`Z9XwfLCl|bJw63W@_xcPFUS*-$3#R1wQH&=Nc<%7JU}LDJT)&9A zKzr|&%)5{}mz5QA2Zs}w1!rYN2AuMI79Ckx#SqNMRNj)OgS4OtV6`iqfiPq&3hDoi z^(Sg0vL3c!@^r*caf8&>)D?{@){DMcH(Zkh^bVONnA^;OlbM$6yj)A-yQ*^YM&vyD zM(?0mo>v!~p{c85skvIcDps9OrPw~|oP#)-txR&xg|Q*>w4ueZYGXeftB$vS3)4SV zjN&At2NNPdqv)ze}i9`Cdu*OYlOFCmGZ-u#nuj1e7~>h*Nkzcm=o@X}A(R8oUae3SJG) z0mr%EWFM_v$Z-KXiAA)y)yOQO1g1O*b;IZIxuo}D@ zYys~9uLSP}p9aaR@CNXHa7St^>&b90@Ii1Q_z<`ld>DKfd<6U)d=%WBMd)MT2=H<6 zB#`x7_(Jdr@NeJ>a0B=x=%a!?1?~Yp4fX<`0p%-p&w|sy=Rv86FM>~jFM*$dFM~VM zZ>|LM!B@Zv@Kx{v@HOyhkTMUy555lisG)CwJArS32Z5`>0JsL61ilN-0^bKu1^)rA z1=oQazz@OA;78!@eqLV%4g}YORp2L}e0T0s@LBLP@LO;LxKjqV;ex%uFTetDBRC2C z3Y-mo4bBJu4PFLPSHt&$-+}joTfkSrAHdJRt>EY2&tSWb`r1TzPmsA=SiU!xmSBFo z$F9s}2!pqFo9RuCQIYEfJ@6}ynXgHhV_*wDy0Z;7MEcymK0fpRg*GcR;5mc7AJv5TtUdjJJ`B$q}T(G}`R2?M4IaCA{} zp}8a!Y>1jbT-@2LEnvt5;u4u?ATxm|Z{{~EYlTcHFcQ1_a80yc?>=~ECKoc0F>r`; zXC~Ur++eMqnFL$|Xv_pE?5fzgC~K&1%G1njR}C{?r)s*ZvP@A&rbRq2s){*q`Z54h ziV(8wa(HR0pfnoV?j&`SJ2g3>yi&evQb4Na>YUx+dQ}A*LNoQmbu+p}I!Si3rVBP! zxh zMs}UXtgPujI;X3j9h^~KFgVzx&o%uAM_)d7hQ2~2HEBgeORNet^BNXM&P1}XxRKY4 zOI$Pm6VVp9TIJyu6w0}z-rR@PfR4{BIa7h;WLGZBcA z`h=Urw9ev_f{pcagO!?^{gWpeaz07Lx~NnX=r{zT^FhZ=7Er~W7_&hZ)aS}}$yH-? zu4xmuL?=U62r;or*fdj_X}fl(OB!@^b-tUdR55nt0s(c+liUJHt|-IN;R~WFYj?`` ze99RoHKa!*Vq`7%PE^$JF*JRVaxu%u05qz*se_}+XPEMH^T?^3a(%i1x{0;b>YCxL zUQ965pO`4&x)Im;o{qbGyn)CV=R8|hR4MNWOf@`9BRC$Zz z<5ca~B}5T@$tosFIH`upJp)U=3Bg*k0ABIElMEUXT1{Q&Dh*Zo#7H+Glk#KCltV5n zh9CzxM_j&zT`Nw$3H=h6KD%tzVDf;A`}%@^aV%YDs06vj^)YeO9!{#gF?*S5^DbPz z!AXkOednajNwH{G#Au@vC-r5#F`;7%Ie@vi#5K59oWx1j4qjnHTlcu;+F z12=!{1En~YqODs(qWqKxH&)k?2E(QmH&EV0XtWyVqH-qe%hgn;x!60iC zRRppIP^?A6zktI)xn49Jl>OKdpsZJq1!XiG1-5`=z;i%!;lF|^%lfinBYY5>tz$suMX_y8M1z8J+CxJn*0jvhk0NLXYbKioR2|fzefLz~J zCxH7h&94PVg0sO2upT@cWM~e512%#AG>8y*EZ7V-fTSh72s{bA8$20Y3vw+X`~&!B zuq*4y)4(3!0&paFIv51c051aqJRh6|a<5c)8F(>x9k>kq z8_1eJ{4RJY_zidkSW9<#6}S+*23!VS3*HD`2R;to0LuFFM(``}Ch!;V7SPW+@>Z}L zcpF#-a!n*00`CG(2bY7_f%kyj=^pO|9|j)){{}t?z70MMZUP?x{d9Maf(L=@QG^GB ze*-6gPlA_#Pl2nzXTT3Z>PGly@HucHbIj*K>6~5#v%%NE!$GD~;r<|Rj|vY5-vo~b z-v*a}bhqKh!PVfa;2Ll%_%66B?f-r75by(VF8B}deDFh1`iD=!FTu~iboP)pfPF#s zRKoJ5-Hl*1_!YPj{1ToWw`^D4ICuFfNOi7Ibh^Fg^W*{7>;HeT zdXxc^NvL;G=d6+f(V7kxdcvQL@1Ah%@djb)pc#6xnRgbxN& ztE2b!@1*9oqu0mD%v2F6bH83=eW*Odr_Bl)EA?#VO=jl-SY1_ZedR3k;o%`{s@FH_ z1;}dGJ0!OT>SP2kW~SDW2s4{=r}=s&F)moGBjxUEuOlIjllCEPu^$ThQ|)%A4NBYD z0~`wO2~GyPfmPsMU>&#*xCqP!F9r7lrN7!A9E+_3z&YSSAY+_j%nvh0Dc+_KX3S7M z!ClB5-d+%fqjJH1U>+z>a`Fa(@G_9M41^yAdxJ7BI1>C4gsbNT{Xv-*90kh$HBae> z&jybMWq+D$`r&_q1HtVmK=#DLa!qg$I0+mK%4ed6fG>cmS<;6K4*!P6Pm#;?weXZDr(OWEHXqDUXxdB)Rn#~Y< zkF;Z7Vj}x-&Up)U7wKIhpH7z8cNxfa#O2twHVSk)WV6aqn4OsAjJU2wKVcvNWz)uL z&5r4LUYhQq^=P$9HjT(}ZaS8*c2OF&kd@Bz0y;9BtTLw%B7iKTIU|sH5<&7I;F^l$ zg9Mlv9l(stvE$VjG}^z?8{l*%$!3_2R?S?K@CH{i3yt1va<`yD<&E5*q&G#^p$uT8 zt2#*=%5{U)%r)2lH@J)z9b&!vf1VDp+zoL8C-RofJJ`*TdMr08v8r|hHZ_z}L1L36 z^Z^WXmi|x_J+kZRJ;SbK^{vtI z1J#dv;=+f6SAmt_HK1G{z7D((ydIQ2i5tPK;LYIn^#6B&yMuoPj{%p1OTqiV`@sjn zXF$#w&ZGuD23CSAKz#=TC^hp1a6R}UxF@ysC2$=0GPnd>3CeZfSHL^KSHWk%*TA*l zDzG!->FeNN@J(4EGd>`Bh{sa6DTn9=o`VqJiHcg*M+|a3&9`2ao~@jtjm7_7lZ!+uLpky zSAZ&w`3Tq!{0>Y5cV<1F4n7T1X5l8**M4vx>U0Kp2-p#91a}0NfStf)U}x|yunYJI zxC{6$xGUJ6_4MvwCvZ=2U$7fE65I#85!@eq3p_ylS*slkR)amj5O^540;CRwp91s1 zw?NuS+`Ofb`kTo?wa{(^?aDiEISjwpd5eURb|&~ttMe8<@;s`ZNp`8}y1J>(nQ}tM zIVa}-?>BFek(y0s?{ZD9D^WL`2i9~ytJf!X(9_p2WI-Y0sU2S!H|#T#n!emS(#kae z-BX$S4u?7E10|oNucB$F0am|;vXDG{7aRw^2iAbx-w}Qe{0Nji!jHk&xu)#FWn<6D zx*sVs?|Pm2D);jbB_R0 zz&k))P9_d9>66Pf*FHsR1iJ3&((CU?}%DzVgS?3D|n2y zF35{Dyl4IhuXP+anN-NFbOGeJSxB*KJ$e?>5*;A%EaWpR+V!ZMq`Mo&jKBIZO&ORo z-IF99m}T#21Bc_Jeo0;51I1da{ERv*b#DVGS-KG{0sjToft$dk;MXAcB&p5dr{H(s z*WmYHXKele_5ptai$TUdJx>1zT*&{Q!E3-@z^B0W?dexR#zuYrc?XcaK(zz7KgHV- z41ha=lfh2lN#IT(W3tKw9|ifOaQH*8D;V1rSzD@Wh$G#%cAv0s>1~VI_>YQdixNii zL-5H~+v3n*sJNbQ(hsR`G({;r=r!hS`uG2+@j30u^K747T$GFmaCA}CI=aK_#+6sq zaGR^%P@yq6zAQCna3x-9-+H(9c_!M@QZ~9C?z6qZmlkK+Rf)55(Jd?T{Gj{LZw~x$ zgs-zQzC)8)_BF6*HIxThPPoT7+KZ6s&#o$bE3AhAY3f=^s1-=5ZPZO5QzvqBEVw3v~ z!~1|2f>XhZK(5=Ui@}@0WgyoR)FohSUC%);L#9*L@1it!V-%7KDD8A3N9?l~5@t8_ zg3q;D*O@C6m-D=x9$@5Dj`P;>xI4Z(MV@KO89BNyYaRC)C;lHnK4!R^wNXz1hA>~( zJe$Rkc>*xN|GDM0%|RVR>Z&lx*?GifKfTY+f92f7Dt+HIqOeZVDCH&t?}b*kCw+#b zpU-9MXS}n)q5R(uJPzC+tOXAMr7t`P{1eFQ-@{VhdVuGGJ;AF%_SN(~uX&*KmA$~{ zz~10{U?1>(urJ8{f$AtQwj5=zQ8LuY;M<7sPH3ERyc@sRYa9|r>f>;Z7ur&e`k}cd zU67u_)91j1xNw4N99i}nhisKp%Y&D47qlrHS0#(vepvx+gVO0{?zbN`bfQZnirw?A#Yxi;e;J;={};#nU+($uuJ2cwF#1>WP0EhT?dln; zA4u6qo(8}kU;#J=ECP83N(}`Ufy2N{z!BgLAlIgKn;8vCn<)lmZZZ!15F8Kw6Fd&w zjdM-}4*@5GGT)d2mV;A4*>5icxu&hk!ArqP@NzH+J_*hMp8;orUt{+{)?SCG4p|p5 zDe9nxk18HHe9-XHvO!};PbivLRx+%hxTvJ8q_kjMY1y!%aYfV{!_88KVpvt z;&EdpPAZ*LT%`81gwD#^NWtkMoIwQ>iV~bC+uGS(4JB3ugG%Gh>s} z5gJ`yH>$j8mfAB$&jm(#8O%KGDf#pj_gHQxkt-@aZg`2#^^($Y1;a;|mg&6Q1I~*y z51%TG@{}i8cE-5OGmJBHc$JN^j@^B)GDpr?Q(jxcZEiVSY)a31o3buzDk~dTS~|S2 zyeT-Sw!EpSps}%h9#OX5i9B=gyvq|-UaG?*`N1(2Cj=`)BkL>6<$BeDuwH_dQ&u{! zA;>Lsm5ntGc;u7?Ti9PNoEHiEr$dU9cnIlz%#x`>myRnXN zJky?@RYZ<7g{u1ZZ{{^b^UCB+0&?wbKvjKnMQyN0b6peH?t)d>Ok|JYwf+nt=~?3)ub5=k*7E|SglUzG z9_fTCE3A=aRIp4(+3?Ld-*zbO`6NC}LDRDibG*uqYbioN|)fU@Zm+bAXIk)HV zSd#kuu(p)2dx`1-`Z8rm&zeBW%gScw(IIr=?@`hr)K=BZrEzrOf340!=}4+f7r+W9 zU3YQKb-|VfvNl-dHfY^I-qG1pQeQha*cjOwQh5Y>BcWIS{$z0sT~4SAcW)g;pWkEb zP>kJ{$VY5NcydEYz7p~+Z6oLD4&j0}W?*lfL*1#a^n&%$O_Xp`fr+;a0(611dGT6E zTC{#M3lrY-tZNfRMfa)FZ=J?;up(60SYKY%Ktl@_m)A6M=WTkHF8A0%jg-9Hxsk5N zDsKkpd1Di^r7C0!2PI*isT~V0{?kYTRJ%(I~I04C?kRL)E*a zjB_^zt1IhyE1%9RDI!lLcFIVG&mVOSkXjeX;i$ILOP-`m&uUmqkRQB4o`KNKYsOJjP-IWFOKaua7Z! zX7rdmSdXx}cI9I5&%1jJM#nGCq#1hF=_0mWXr!x?OnSVvOv>x4d$tc+ZLFjewYMVvU{#ELYEK*Fz%q@NCS?45ZXC?KGA$jnjhHREcJ4`

    2VLfzRuG>3au`i&}^;0^Ox6OE~2Ll;f`A~pq@k54>EYc0; zZCy#+0o+r+J3<{UokQ8|KD~K`QhL_2rhhT5(c64tM;qOGq?TQ-&+oi%rl>B|I8P^E zZdCA08}u0XiMM5V;vrF9A+@!5)L>n&S49Vo)N83PwXyZEvA$)V&fcm-KHjpdsikTT zZREyz*?}_sW|{3cWuUn@S$6CCy93d;GamXCJ>!u;vJ8!kKBMVP=LSvvl0JO3C(XU} zGpe#)W_cvn39sC3+D#XCJ#fR1&putg$hZAy{Z32t`<5McanG;bnETbV(9fOj_bt}X zR-=F6#El1@R)5=$i!a~hpxsMu9?3OYZKv1%I}ga3{%poGugu9f`Th@9vfsrCGJPL+ z-s#p$A3Cr0`0Xz~bj;N!Kcw$LM?bUE%1qe^HQo^Vw6)^zDAu_cz`*xqrtw z|LFAC%DX;(SYNwGUsrp`JxA@*a#^24cK&MF1HYW3uU(_x^YMMg?>_N`rI)rEmK$2p7!ePW4}IP+3OqGNaC6U`j+{ZZyC1XwY|68+kLSbu|4_2o(1}*V9A>E zvsw;(=YY>n{^^u|vdJOu@5%JN`Ndz)sl4dD(szenb@s9=zpUq3Vy$1j=Yt>DRNQ~w zdNrkC?S&_8A-!yRW%}NI|G_D*j~jc}t>cafY+n;Rhwve`*C#E;QahW`&`&~ z;uGZ0t6G0mx5ERO6+iE~;|2Aqe|R#RFLM7q<=g(SGiM+E>MfIskE>gE*NXA%lWF}+ zZ|zZZO3j%| zKAe0^<_+BQt@Q)0t=;j&_QPu*U;kOg(`OFJW51I;&GenT;_KWq7nVNu`E5V+dL?}p zP5or8f37qY`EpE%*n6zd2Dh?7=1_X zH^}t${P6lsi&pd=^5KGU@BH}7*h21!)cP?8PXFSn&M%yI(6ocz?0)7a3wgFc>u;O3 zeb;I2zu$MnQTx2NbVBJx*y$*CI&W_J`MBB>=ATe@*7gUV{Z$=%W?G;1)pi@7d-LMm z7Vmn-zVna0ow|08)}M36Zd}uW~+?3tD zrEi~ur|<@4`(QF}o-?=AOmL>L zQ8ib;Q@O&tQ`x{_`91sQAJ&+EWNvT$a%H2fGOu}Vno{ZB6ri7sZ{(%QsDk=(X~eJX z=6Q=su$-5Ng=S)jM3RIN=Z-{X+pSdc=IdZ})3zIGDzDvkBNR<#b7Nz$ zu5#XQVsCDFByqo@7P-}_f~_{T9ps^KlgPFkt8{kqrc}6#OOGxT(bD2ttodzeeATj7 z_Zt*NW9Y=jy0)h_s)expo?YIu?U7&+%&M~Ok@$7JKxIRNbX9FB)2LLkwJh7G<<0`} zH%RY^4J0^J-Ls~yc3XQ--gL+W^EZf7sH(Q6;H>!W7AvZGHUenkq-_}YW z**f3GDNGA<7{-omjZfuoW5!t7_8gwajTFDZSl==$IInVMuyWS6$Eca>F5HJyv+b6G zvl(?{yx4YAEx(1LZ8z@DYa$(-J5A;-E%g=L z8WxmIn6?{^>RgzbnoEU_B5?PFADRg$^7Yy@6p-WIr+UT`7rJOt1U$ZEX|YH zv_xW)=Z#GZXUy})CNJB>MyEjkNK}biZymQjeX|op?zcTh?_Pa=|C99Tllyy~#Fk`l zC%fDX?0rQ3?|EKRN_~6({^!W+^9P(H|Hy<@;a4@Qygwl0^ZO+{$*+s=Z(r36uWYb`5!ba{qu@_xm3Jvb`s)t4S8;F5mipVs`9w)#|A^Y3m#|CtZ8JVUKVfh2t18M7PJG>LN<8ZRD&wxHh;gS$ zZA$^05!7v++hWSJ^xv@}yD88A4dd%}6t4Be(~1AG&`iGO<^BNX?w(jfv|%M>X?-mIY|zuKAqM#od6 zRyWbrO>uRPxw;juu9WLKJR3?}uCY>vy1`0*^&`?kd^6O~R`RPIxLUYC>*PJsBKg&B zNT+FCH!JzoHArF^dsgzROs)_ffv$s^VxJTKJ1cKMo zN`BQ3iKl|l9c?AQ8isV9*2#0nBKg&ENat&vyc0|$zp6&!2_wRuU?sn5M&jusbn~p_ zS63sM_+4)$>Om(**TqVHHNe#cTwVK}xSEZ<4yxEn8LHGue)Wv2d%@L(xP{>;9b$!* z$QLV7o48j)d}%#a^7FVkPv+_nE3K5F-tFE&J!7Q|^@5fB z>L70HxJZXM)JlFOw+-=>6;}FN$*+o#mTBE^EBRF^(j{6q(Mo<*iFB#f&9IVRH6mT6 zb#txcSM!lB*SgcKUFNlN{TYn+g9?cA-g!b5mxf6 zn_S&(uI?YM?qgS1($xujoR$3QG*`FC)jjR%o_BR?UEMlYm&0u<#}K~`s=-PbDr6xdBilzuJ!b1myjO8EOYB`BfLB>$Gk+EBV#_ zNY`uKL00mse54z+u8)=cssQOmtt+w;trm%IJaUdwEBRF!(#={|X(hj^L%K!l8m;74 zry|{|b@Q#{S7#yJrgi68$*<(rrrWjdYAgBGZAf=$-JMqQtA~;Ps&$WB$**2Ox>M^` zTFI~8LAp!p-m{WleTuYP>%Op(Uww;ox7Ph&CBJIVok{m-UAmPRqmb^^x?Qd0SNkE| zr*#Kf$*=N|?$^2_tVA0`dO+(2Tgk7+AU&vcC06n)dD7`2t*fw-U(H5(SnK9k$*)d9 zdPM8OR`RQ*NRMjWxmNP4%aCNu%urWZ$**ojdR*)NY9+sV2UpFmwC-gq z`PJJ4p#E3&PdN_T~{ml)xJn_ z-%*A-z)F6Vi^R7q(e<{HUkyZhUh4)~$*)Euy`XjDtmIcykzUlgax3{&Ez(O`*I*^T zIvMF@t^2c;{OU}km0EX>mHg^bq*t`=N-HtyB3-FmId|UuExYdVvg; zVF$VA6?yE+}|TTNQTY66213+ zj&8V>{OVa(_oA!YYk!Bgua!uft9#Vd{pjj`c6B%8IAL$Gl3#T=z|mz`$*&f=y2Y-p z>R{fe#==MdwYp?X-!uO=c5(jjiJQii(4O7xvbtMJWGKU#^t^HBY* zQ*=96iM|u*bjljbM@Oj$f0Ac1z38Y}r#2Aqgp0<)-y^6G6 z>t45#U%ij?iPn8+C1$xupK9GEEBVz=NWAfZbNpf@zw+nlw?ClkWF^1a9qDt;+sjJS zNu)2du7{QU>PVz7weBb@F)u;dsC6T(HT@099;)h zYNZS{(Mp6s`rd@F5+f(l7Oi{PN{pOHKWN>%R$}Bt`cdmXw-O^K(ob5q#Y&8vN9nhP z5UUPWV&p{nkLGo?5+f(l&sukYl^8jZzSFwiR$}Bt`c~@(S&2~yNm7}iPPLL>{oB=j z@9HKFaClR!Dbyi~KY9+rq;u!A9W<8#v`dP`Z1|zl8x?xuG zs}iI%tvk+2epP|gUhAr@O&ouZXiVwGhj`hx=frWR7PmzDe~2Z^_~pzCfWR?$f5TG!V~!~jVw z69X%;_u%SoaCO59d4qwD!G%`JP?uQAuXY(^d^6PUR-*J>U2j*{f;1vcO6D0WvG%i) zUu6x}Z>oU^UuSBD{GXkDI_=-ZLRa)vs?N`7^Lt6S#ku6K1eySjT_ z-Gi>~X;=5Wt9!%Mz2oXOy1GrSuH#U7iHpP~(@K;F5(_+Z-L1r$6DhB~=uWqiUtNrJ zkJepgB~}E4t5&=05|~=^!&Q~n54v~UgNJ-QHm@VeO>j#b57jl+1e+4wa2tI~RnMxL z#wk_7isl*I7Mz!t+q0pnLKQSM@vX${LH(x;o}h2&ElhPoukjr0+|WD7y`k4UM8ZuF zsA3;z>B+5p{SRo)?w)%vvz9;be6!1{<+<4G1GCKo>-M?!AtMWhmXwVgKDvx2*NKvL ze`LJ==kj6DkWv2^`H-@F3Pukt`#*};A6-6w^!fIkUB(?=y2(ab@R$njHsbXOR0N;? zc%=S-Btz%;r5ndSU$k{4Zpo;vON+KX7tU=*n^`()>vQvYK{nF(t6Il**DlzYzF_?(^y8P#YQLm5 zr~T563pNIh8+-PtD<00|R1Zn!{QLGvl0V0$o1lX_uGwwru^l;|Z>Pg`a&}tOTjFR5 z#qq+~qt=_mQbN4&DXhoz*oDdFDkZX2#{48C6qPs^7UUHO@HN=Yoxy zI>}3lHZ3XIyrgK$lA^6r7e|@8NIJc>VvAQVdA^xE-|Wfr=!$U*=fy(N7Ad36!rv5I z6{gKMWjv{9llIqiCujGPf9NN19(>zJ>fh8YUncilw`MA5Sqo-O^E; zbdl2aiQm%ko1WJli?(z^+6mK_7HwLvBDYwRmX69COMv-L%G;cbW_*`%T63PO5&un5 z{}dJtyJ(Z!t8RL3KA#zoo(aBOz_e%J-}I<|Vb4F!A*$4sUx?V!QJbseJ2ZUJC^}1M zL5bT>bQYB?*!cfZ_cicYR^|UUFz3^lZqr91qnx@FQ)7UZ5$1TA;>&Uar%)&i953?f z7>I`Tzs}Ohl=98PW&g# zs_kgnTs~f_GKM_v@R`Lsk5Rbu7=^nGqpCWdU9R0vZO5}K45JXjV-)T@M&T~QsLGC` zs!=e_-em|ib0%|}e*=q_@!68D+E$aU-8w#9xdknMyVNC;lE(*?M29B{+q7e%mefGG zdL@tL9cxf-h~%kiyefVJ`D%@vkxFxAhp)+dQs5%=j9h8mwv(z809CauP@3q@GInc~RNzg3~k zcT&8`mx_{4YJogGK?T=><9kyV4^mCqs!r8jPkpM>wX4RXZmDslexP*KT1amd3bqiU z(PrDUrI4JYh8CyO<)GI{lysV51p2mc$w$*Ie9P;2&tLlgInM{_yN+S}?Dg6|$>-Wa zaKyi#8@Zo_d*mQ|YoRB~Oj@ki3F%J&0y4Le><-*N)8*C3l-vBep`p5Aj>gY+Fo z(O;{FYCo6c$7@*k{Y9x3;-<}gniV|7+kQpq;n290gqzbk6i(=B->QtKfZh9rpu+o++w?3~@gpZeA6*f=oKf~jHXI2^qrfOr_ zE2b)A&*5c*xc2SCKXjqb_2F^_1B}iSgyExUk*M-P+k~MJ2UC|gb|H*a2RrhwItZJ< z*+ufD#u>;b6>Hkm2kByfjGJ+JP5a~yBV{*0hzv@W49^Tml`O;8C4*4JR0)(G zi8L4UrY5iH&vI9thw>p$&TWwApq}y!%@uUO5#?9xIeDEqSu#pE1PPj88YLE;rQSM8F-F%LuDh3UK%&6vgz z+oTKA@jIJqx2G%HVPV!<>ljPbZiiLa2|e9~u4}EN{{yMVOMxU^?AN2f%f$B>yCP3( zxZ@QG5%OE9^>AYl@VMC21Ex+8%(TRdH&?FIQcH4iDf2C%q~qzrmCaR&RBZy~z6Ir8 ziE^)!R8qBFsTG_PH?{X|JORu@(U)`Pi?MjJ8lvA{j9fq*oo6Yy5g*oHiKI7*Cg-h^*;Gk#oC{*c0g^XE(uW~evdkyex z#vfu48Jbp_X*ajb1xlx@@n5Trna}rDirvHb?I9FNl%cRWIga(A7RQ@g#u8UzMn|#A z8i=ubMYqnBAzv4K;kClEeMPrkMlaip(60taWxQ=j*Y!y!+fmT!beeQ6j57GTzUg!; zylT3834>XMexnCAC)XoTI?Yrh`UYt`&j%@~Wa_)DL0ev|ZP4A(Kp47215Lg=FB%FB zDw5LVyJK3kNPa9xI6sy@6G-w42a^24p_pGZ5c2C*KQKBkX6CD=gh@(>sB84MF z6)6%vqDVW9BHcl45$l#DgpMT!Q5ZChMuF7EV-Rzv^nkDCVaUosN2zI@G|pV|g>jZ> zWvX|+GOQ4f!8ts{4E3|-8>NBGmT@C&_F5Juqz_aKbj}#R1n`65U5IkKK}&U7W>ju! z+6&E)$`m%sOhoiQ-kh9>G<(n(PFk$(4NJk(7#m1zVK`JqV={qYdcuKnXbg*HY+*Qj z4vjJ4d#y1pd=8Dd0{I(_A*9BX{u>&jV=2CW-L7>mQ+v09sao1OBBV0aIA62w6pz7K zJoXR!@5Es)VlVrR8`vzM+az?#HJDw5rkci!)O|OMf$Tkn9q%EBTiVBH| zxR8LQvtP0J`e0$u*f0tolNcJ*4GZdq&aa<||87>AYd*8Ezb=riI)LfSZU`XTbY^#| za<`km7TvPyI2!NW{(K@`+X~yg+s;GnP?do)gY|UP8kqXscH(LRdBUx{M>CSOtmli8 zpQD;Ff|=d&X+ydy;d%uxF)VVeL8mblta9GzbOml@*phA`#3Ez@Q-+w5(xuKY(o7EbX}zD!hgHdKprM%X9*yz*M7^)XeMtrSd(FCK zEdq^)5G2=>)CL7v1uDk3Q&DX7$Vjbi^<{sBXPYF4g{^dwNmN6D+-e3G&s1$iVA2`I z)W4g-w*nM>(>0K`)#DI>HD(<`&pu4qLaLIiU>)xs){Ps=PW<7-Fw`%Zu_ zN{#t@HS`i|t+&*pMSEHgK6K(^p~?VO&n(bjEMv*(bi%vx`uT%9FO~DAB1xF_X8vMaoneq425FQ6N!XR0k|Y*2 zcONwsLP3z~OwstEQ!Mj@4OL6PQbNdZ5S-sA)iBOZnRbK*uOUkj1R*mOO(*a*QO@RU zR$LPW2}SZGH5C-Y*$M}fq#`l0HN$J>fFe8FJQ9%%LJR#U>?(LuGS;7?F=ip- z^gRR|r|%UC#_1gZnAPBaHRL2IS}V4iIcssV<&;jqn=)`Y6*srA27LaX-a>!}$t_z6 zunQo$4FIzu{HL_TIZ2%)GT6i$u&JCOB^Zo7UwieyO z-SM!B@ag``c6^n`DjzB=B7{JhJA6AMzT0u{v!|HBECbLQQK-a1G)Oa?D_YTso)X0eU3Rsw zkXw-k%yQB9R@Bg*wl)rARY*l|WvZm1(5{ev4Fc#1wKDQ-PAlC<$Mhe8#Q6MIY0x>Pfq}(fz_I~@W0y`lg zWGow)tVZ2>0qAJ|HUh>>fUX``H~O2Yo5C8`owhI_a%KSJ+zQ8uT5nZkB8@h)(Psz7 za_Gen7UqpnRKiJ8sw3?Z=9y`N+P3;G)JuXIyS6JyiVpSeK`5_g9G;QHws8P~(n;on z67mL3F@ZbR#xRh;trm23BVano{|HSwLRZ6ap?#@!A~pZMBXYl&xwT1ZGFoFotf4nr zEA`XHXpKoCXQqUlnE;qnjzCgAClf!{JqYCAw@2=G>%9~stXs)Ufvj$|1d#$Ubrgt+ zqCiZGeX~~}JF;qj(@B!h6%{geJ_4QkKwz*~vce1lPa96&h<+|V2Pz3Eu8;*48o@~k zU3QVdcS&+R(nM(8r-6boODH0xENVhDMBv)x>&JOJY=ZrPiAQL4P6W$50beaKB5#Cs3 zi&5``wl6V4DEY}IdCfU3DN(T;I~F2$n@SNdQAh1j^mcS|hn` zjNGr+dnrb^owZ~NWZPM~HBum^jsh`J6o_fThHv)@r0oo9fHos5d}uT5?IAM;|Tr8V|I4ol<23-rUbeaL6oxHKyZrhCPCi0V?Y?9ZU zeRX;q(f#|!BKMClmo~{7>V*OwMFv)r@n#BO2?WZm zU~3S_FUNh6`+M|W3KCMVaFMKvwNyun#Pm@lCW|65H56&8S0q)j?n`jpR^SSQ^u_q7 zhhD8%sjzEjYdoCrFjq5dm@l;@&PKAd#Q?qo=r7Uj82-V_N4|6^s`!NE%N5I3J zpV;sm-CE4Cwhg})*wQ(4wR8>^EuCXCi`&s*Tioj5H6BiQm;)f2CI<;NE=`8T>}xHi z>9yf$%`Ls!!{r{PL9}7!FOVI@na@Mdp0{xE+(q@DQ2H2rQe|#^V2BblOtM~8by%jI zKl94^xucCc%6g6BcY#d`3}#?}JxB;Hz6yJr0A5O5i_aR=&BHsZM@^r8v6eWPQB}9p zVw*?Zl9`gh9R9~frzL?PY;;;8-z!F8;V~+>_VRi4GwVhhcT})IZt=w{MWcus8%C>R z?naqgY^18EC%=~z;KP;+@G%0eVavTHWKvY$ z10Dkr8#}F@mA(<(AI^cui4ePKK3&x+mKQ7M#!aZ3S!ulvlOP%=Og9dCEApl06qLJhikoW_ zoH|$C!g+J;N=}+9@9;PyyCwbm7~=c)d69b>UElwptjrz+Np`Q4zgT7^Gbgg;w_KihN%l!~NnHA@MBVGog|u$<_F>482Nhy)W_%j9}}rR4#oEPBOK$yjKkoV(T)E& z$26Y|$9SLFD``${m=heK!#wH7!H3NDNptMS9RCT2d`u*lkq)&XeA;7|q(&**^3c^V zZL62U=onqf+m&W&yON}}t$xI$OxFtc*1?c8lTy#gqA-v#^klirSnYwdKJqNh$>a{C z7}o2Rq_mKZ=TLm?mOwU6^cYt%fO$m4fspUD5ckgRV8}TY_k5@)^$?BgL@{%m2cn6i zw*(I9(*Np0O~Y}hpqsunq8R)A4TMQj$O3gs^s#@-M3%|rttF8|Zwc=)bFSw;$3rY|H{H_8TgwpW&RX1OY&4aFbDSP@hu#w3 z&nm&JyBOEGOUdr;=4n9=D zWz03n|EL^{A~vC7>pgEX6-=+fy=y#3XZdESVD@8?i+@Wr3Ll5VHmUmR(&5sp=06P8MR0<=@95_j$O-Vm-vybThX+bX0|t-g$-8Eh2?k0T*e%)l8`DVb;9h(=$NS_p5qbSw{9*tU8r zAVx)WGNYorqVKihVbD?g{)JO?vhveOuC_294v9(&Y#x=DYGD)PQPJdX0-P4LONr5P z!K3X<+QaRxX_M92Xm*PW5a`+E9DMiLmqfl$#fg3LL({X5ou~T64Ri3FpW2!mW9QBz**E-oTbvx+ZkHIVT=u~;#Tey)|kL+ zL3S1srFEf_Oa{3v1O-~)JkWWs3diBCqzoNH&7iz;HW@pnWq0(7A!6c86EdSo-BZ0n zSIsg;eKL}Q#@PhZX%f)Ukpc$Hf;#n%~E%8yd8t> z7bMk^+qoj&o5V_*sgI`Swytf!R@<|8cfO6`x{iN; z5Vp|2@4~%4Nrx=x30aUaa@;{rxQH4N)=0uiEB7gYuZ*HKtxl<*sdh+ z_^=D{+V16phkbvBLFT-2J9kw`2GxkD8K{l%n^z}7SxyvkDz}PTB@PuW$z2_eQ`~=F z&2$bGtz{t-w+v<>iDQ0qV4b2W_ZD{GSR4|Ys3o;l1w$^u{HVp z;_*mH-$;S83@kZH$R$L-Kv2e3kSvq9ZmlEo>{__*AjSyY%BaO3D*BQnLqbKN@qb^A zG8QG@WTjm>!4{+rU6$#UGf6uT$X9Uk0V$fSx}}ZL@M)jQNEa7ET)sTaOUR`Xr$}H+UX0Ko`rzLtG*2m6zSTm^2usdqbpDj$uq0 z3_IK;!7wI@mT23ZJpcfu5G_Dgk{3fy1Aji3>9jV>9#>;HCc$u=Kc*Q1Yb;x}iE?Fy zTbHCw`)QMJk~ZTogvOyoV4S@+j-L;S@XRZYmRGlTXDcr^Qc2#D&ZbvoRv#)aLxjuA z1^rBUP1>RIGDNt%yKNjl9}=^cSI#43EAFmPGCN-F#$5&omv*O(BHY!KLxp94aACLG zC{kF>g*01M$Uy23+Xe{RwgyhbwygrGx3&!$>n%p$&Wtg`WPO+yT1GgYJ%4&(raXkz zk{oB~=!0bh27;6~W8;_#v`fYxYG7_>1Q`cSgC9aZo8VK{=s1YaJTom{3zJ~fCG(IA z#9>B5lJb&C;h@M-21FXNnbBlS$J>K>=ZcJ#s-bVkN@^g=2|FWe?5T*q15U9xG=jb1pI1&7`7!p6(+ z{FLRw4g(6%MuTQ?K#x+FdZpI!8pl%Ed&>RCdy+u?my^#~Ch^f@1;s&14-ccuTZO4y z1zcX7)>R0?J2Wv@vzYTXi#t(FJ3rsVa3^@`!g#om@Au(4LC{#&Ftfffn7w3lFlWiA;5z(fv4C37={N&-5 ztW4;?T+fe+(QdguK^bir3xQ=@pWty+d$a(G(#H`yLjCUYC_PjhM2%9cP0Mm?t{$t6z zBR+aoeg8)-+3ehqco@kt+LA%pJi$rvO}8)%%E{tFjmqIzz9@rag|t}Lkj<;!R=gs0 zF1BIqi(`_5B@rGU%2bxLoR#H!*$lHySEKc1B-ZytZynq)qeODqe}P{vx3-NVibKSI z$w^+aK37^bnF*{%__G&r3+T-C?V5?(mJe=_GlIjKc1oFl6Gu^?2 zg>}=>P0Nm(V2L==--|+OcfPc8?%df67u7?>u%83(pS<$9$}XxK-ZVr<_GHBHrayFG zcmWRH)6#TvSHGg$9!Ftu2KDW-7J#7X=Hg)4+4$e@=F?T3DhnZ|#629mK_T>1^b39A z*Sw1RKkzOPc^)RgmhXh>?Mp<{5yLM5R@}vOpfM{Mx9NGjhv#7P?UK$1{Os-vXU7-y znCwp5fGqHWvc~tN4$L|aEq4}fyT3!`8op1aL!`!+=U`Dga*-wW;{F$K%VU$;qiSTO zNmLcm`g#l7D0ixF>Ht|%o%i-j=G8UG)qkIkeQle_qYyb9V2<6y;%OwLgO>|cBHaTb zqXSJhAApRmL_t!u2b_!wgJolyZZ7P1^Z6NGzS4IwS#nWMmKfVjNwVQ}?H|h|mJP)J z{F{$c?wc*!^bIk(I%lf;+QC>Pktq>4W8NOqM@n>6&bX>M%c&Duq6JbSRxKY@%OsR1 z2~9p!Lev^f=(Hb*mSAlNEUC*GZ~tlQB^(yr5UxIFxVFkJh_=vEs2KNCMz8Zhcod1` z2jhW0D`*-Jzx;T`~5Cg?{%*9m$FC@JUVaMoG#}_&f<6!QT|r+2dRow9KtB@nB+wID0-y(l z_G=)`;}qQADZY~(x&i1R3HL1i|4Go#@L$XK3ede0<29f^if zAT9k#KwA32KwA3CfwU}>fV3XdfmYy`AI!r4EAWd4%kaNRXe;sm7D4=?kk;~fAg$#u zfRqRPDu&jVUu)1jK8BL3JjMg5?*fOKfHW2IWTVuGlK-Kg$AGkae0RIb?OC8CQqK>5 z1vCS{{NNw>e+Fprpg+2j!9rud*-yfi0)0W!8wS*0!i{xkJkU4AcdA1x99jj`CcgJO z+M__jB$XcnX{q)BHA`;&@wh@uH5iCoj|b-wNvX~U(o$6cX{n|FX{qJ`#U#e3fwWZ3 z4t>L+4M19|=N#>~Kzwz5JoqD!a{LX40vtS6+IxUh4+aCpB}O@r*62o{6lnRugFspj ze%VmtwmbBOL;Ygb_jrd+b!Z%r=5`xUiRAW0pfW-C105^qap$|y`99-(e+jfzr0_c+ z@+Cib4M_R-cc3T5mm3vS>rMpvp3p7^($Y_IXf}|x!Fz!=OSqo_{g0p$ysJK6O7&5o zQbFT@cyuQoT;XWb9W4QLs`%asq$OSBXy10U=YX{4KLaY37%v08CHd}kzOOmoH=S=^ zymui_VtfSXWIUmY~6*PXlQQPR00FTMEC%sBxD&lm^ncUvlVCp!1Pi zJXi~)ao+$^oje|2W7L#C2vh>Ao*$G0Jq%9f2P1$qMh%ck`Z|Yhb?9Co)yao}R36_1 zqD_ql9YD{EWcn51J7Z%fruRc2O{Efp*;YyKa-icR zw=01*32mA4eZcuX>U<9XJuW4PquLJ(S_Gulq6284q!-|w8%2VS26{tMey^jQ;%FBD zX<4py=yr#maA>DPe|PAl<89pGKx)S?cQk$@QfUcC`+}pbb+j#x*6wHr9IXUz8rSlb z0cm>mK;MxXecqw(mcN9&`yWma_AU*`%z19 z29U-$-_btlX!9KHZ$N5&ir;NZFbzmc(BRMyfi%5#hw=wn+L;br0Hh`Ol%p+hv^yN_ z0Y^LiJ+=fNbEw9l>wuImNg(Cl{myrTqrK$9y#d58b>;_MKx#|!PqemVAkban%dca$ z2r37uCJ0rP5MB+M@0UdLPOX55DGTKXSA-AdN9(5WZI= z;VuPI?VJmwzDpeKRiN*S{{6$D{P)>@W-yRi$8&+yZcG4DeVGEp5nVjE4oG_@e%Vkp z;)_5U_YokCyBSF1{tQUtb^f{_lq4$I`mB-9TmI`bfU!gJ&>mIzd)MGfRn5*zmKTt4RvUgL$iT2z0Ux> zOVaxS(7OeFA4qND(+>U8p?xmgK}S2f)YkksheiOsSL^1`3Lus50}g!?NV&G&p;jO* z{dR|b52T}(eLy;D>36anwVVr7A-RnN`hcJ+AdN8rNMpyc@mK3Hr3I-52U%h?9d;8 zltX_7+SZr(7MyCiF#|};(g?IpeD4O*d>;c^E3_X2X(~Y(v|VWZfi%XMK$`N0ft1e| zI&`H&Hvwt;xD80#$2WjfbJhWA``8Giscds-w?l6LX?x?hE;YS@K$_l2AWg3lNYk4P zWTXY8y0HvMThwiicDJLg1=9LH4Wu&P0;H+D3ZycB9Y`h91*DQW<}@prIFOMRkVCFSuGT#8CHR3l#HIKhIH25sbgGoT@JKLcf9eMyr z^L-ph^W6@l^=Jdqd|v_5R9<(e&)JqX5J>AW3`oWQNYEajhXr*4JtF8J&{qV-KBV8m z&JW^1Ulm#@&|`wm0{WVu^MJlCXe`h-1XTk)E@(2)HwDcC`j((ZpeF<+fYu7S1L)g= z?g9FaphtlCCF=ZOEzmka8-cznXe-e71nmU+zMyuX^@2KpHVEnh`hlRlA^PR${Gb?U zqtFHcJtb%`(9?p>0s4`k3ZPa&mjP`OG!baCplgAi5ws9!i=bsdKNhqS=vhH`0X-*Z z4bWCWj{`j~Xg$yig0=wtM9_AiZGv_K{Zvr@VOEFU@6c!kmmMVAkFO$K$=?zkmmLlkmh#Mxi+_<4pjqbZeIb? z++K6&Js-BT3ZSn@sjhSAbI$h>hkgvCHTtDP2Y_@$Tl5i&P6E<##4sQoT~7hhal{-T zP32}FE!F3NbRNGENJkkz15&x|2U5QL1xWew4UIgx zenFFgv;+$rS_-7RdK5_Iu@*?nw;4#w(gCDa^t~Uo=schmqB)-e(wff!Qoei{NNfHu zkk+ylNNf3?5jO5fAdPz&kj7mGq;YQr`kA!G6p-5DH9#*4?Qx*(g7~%E9fGz1y(DNm z5WlURAM6I&DQGXy%Yyhl++PR^KBnKy&JPNKb_wkvAf54j7f5-q)uG~%mR9OexkLPt zt@bH%fOH zN%1`g=o^A=22xJ01kx4yhn?>ZAkE_yhyE96pTy1oxb+?2(5XP`djZfNB-~|=b_LK- z(TJHqs&)Ksu9jfA^GyS(c77S?RY_$Xkfyf@Nb`8n`5tqD<2aC7;ITl%g+n(3sm4AC z^f@U(c|{PME52iZbOr5`Kw7F>fK;k?IrNA_F9PX$?5jXElFGjvDj#Lr|A-HaOFToA1Ki;KJSF!rkw}eZ__QmJ9bo7w%;jZnq2f2N&)yE?h9$a_Bf9ZSfy; zXtYCVAk~sb9r`(tTCR2=<=W6OHryo+C4rQGj{<$IFZJ|gphpFD0)17`F=MT@7!0Jo zV}R6m8jzOY(++(PNK@u_cs1qxN*niNAdUNRAhk%7oNuG^y&b4kO7Ipb?63%_=R89_9uXplN*7QlN~@hmhU&thC2aB>w6lIYW9Ud z=ky~_lR&E3PXMWAUvaTbZw`>^^BN%4(~Sr{aw&~K>rZ*7|=mM>wx|#s1@j6f+p8kD>WZT zt<)+Yt0cl&k5lH*^W+3J1ozC|`hn{iab^@tJ z>;ZaP%C`?lc@RuMAC^M3VgjC3FQZk zK>Ez7Lw5o3YxViTJr3Om#IM!o2WuSqDNv!r{hdR91=93_T8oAQDPKMX z^e#zdIZ%Ho%WXhfmOFto?k|A~#rHSP_fO9E_$!0p81a1%kj6a~NaIchI#ztAIp4X? z_b#9!@x9miKH_{g0u_tzX6L)j`Tp9Wy+8$0j}C`Af%*&WfJ3RO&V5KONL^7DOXCZ{ zmvjx+vxn0>&tL@sKkB`0T4my3q5w?~+!}9+XzcT#ng%PK0RE-(J zL(q&kFvGr%Uju%_f{RMvxQlTZ1~ZCa-Eo%OXIdlPP&IPK+y!-w9}flv#}(T&Z3uNs z6Mdna{Y&VZfVR}h9o3b0(}KRi<;d+XxG&cT@}GHflN;FO%Kv^uVL8D01j|wim+6d0 zpreC{2K5gn8&nXib2MrY!xaR=({Wc`mA-lX23E%GWW^`#_TnxuC!1>Ivm#|e>h^hQ zZV0#GQ=LB|?>7C(QM^-Gc^}8dReT$+D#p!UX49WW*zqTuLgp-$21nT9Dr|e5$X5kb z9mFowgZ?g5evaU3Y?ah=u9DfDm$+Z{C>9@4BtO3{@N-{sl3mrJKP8oWC6HHKenT}H zU5}*Yp-|YHZX)iLNn1N$t!erFGdUb=mhy zcNt4^o|c#o!`S4&qLRw(l3Z_;f>PdYrQGeS)gt9i%P7C}_M2Q}Gy-rBY~{90B~%wG zw@EER@$GkP{D@mK5e*}$bY!H*HaX|#v@0w<;aOC8TO?Jl(3M+!>9uAuHKlD0mDX^N zEyOEDgxjJA8#5`H;%}6csEOP&P6kQ9^_db$Z7SC@Tx<&VPL9j$oqXoKY{@cA`4G@o z1Yt!gScxW{&#}Alz1pE=4y7HUt$9S^z5t}tv|j;fr~W4w?(aZ46e@(WX}HsXv;^ER zskC_x-R6A145V?nB~rsZ>rlH3_ZLSiL5Vcn5FpKCltWV;YH;X&Agu=%wKT>SAkFs| zK$>2s^W}1$(#~+`JRq%kC6J~v5lB<1cj0bvhz}h!+!Kz*MKVp9Ls~^~NJR%Rw7}7x zZV-s$KxYrZ>%QZ$9EHA*VcFBgz?qLndOF5=H~b3We#h_Ws^`|tua~XvLq|?)ys~~e z-gP)!dp+i1ub2e^d%a_W66y7BML#znm@oG%O;YX`$~~aDzdkr2=;!*~KcIA@G&LsE zg+2HcxE&D8k!U!oXYT8QzCnH{DlONU5D6|u?Q}skD!2bvz;6J0Vn${E%ifn-YcI}AaCA+i+Mh`gC^F(JqY(%xc`Lvd$|9CdkTtxGX{xI!tHZZkZ6M27w&Gj z{otO4;vEH-#XK7B-Ed=YABX!cxSZG(!2JMZjm@SBE(sq4_g=Wi!sWEO2rlJRLKpe| z57UxS0FjOYhzf#V7~lQ@TcOfQP!bJyf>La{4Y5rJ{!@c$EqHqny|^rgYbs!BWRk9E=3LqHXmu@LQ7G zrJr-f;AmnsJYn)jRh!d$H}Dg_=gfjox*xy5X##u(OwVkUiMo6fN)ivIBe0_R4&CTb zGmx%!eGy34Kc4~6b+4a0-&dS(94hpjqOM!H~@@|K|4W#Cg-!MJ}3Y{Np2GV)j zHlW-l?sxE|B9<{%TxBqE=Xxft4*nNLOdR8!i?BQo!+nB!VK9G5-Sh?1X4lQHoZr}R z{3rp|Z95 z)X^|sB_*_kw3PA8dtphY2?~*iA%l{VfsT9~PbA5aqk*6ga`f5r>l+$p*WuN;qa^)O z_)L@Z=hZD*BxFV)?=<~P1TE0uXoS(Qrynh81><=A7-{L;MJ6v3l`8+q<5rj`^5`-{ zKO2*kn}IQ~Nc;fq5V&~=R}S|haEHRZ4(>3xkHS3%?hd$+m6*3Yq^IVMNX;8jLC}m) zN=qA55Io{&93E&mo+a{*64^J<9*#Y#JQzAg^bEU5Z8Yz5h-_2ZaECaXQyRxmxfOZ> ze9;2j#n~wrCrD$T{b~H73e7kSgVpcg{~V@5`*|U{x!89XVa93|TGUxY&3>}f27}AI zDQNH*daKvTMqvG%z=%{}LD7Qd*dz0K!IP|?y1JioQtp+AfWhn%kQ+FzZd6rXdwY{<{#1%` z{OrZL?}DK5=XeI?OqAjt>Yt!Rz)xB=htArniBw653WAZ)DWz2ybZ8~nz*=LT)UPV` z1A#9E{cu#RPjlbYsJ!OUd8tvc=Fzd##f8n66iNV0n)=no)-&v;_Mjh5KNd8{QkUd4 zkIPG45^Ek8ON}pVt}c`SJKFnI#w3Rwuk_0~x{0b@URKrn1~Sa8aNmV5mBA`RRN<2F ziz*!BP~pCU--sixaK%R9*ljInoK@f8oBj&qX)l(8!aoWwOt@SP5Oyh0BU}o9G2Eqa zm%x1p?hSCMzOOrFAW~%@DhRe3-~PcigAT0>nEShP`7k3P!@W7XSg6`>BEz_h5ONFX z0)*>HK+EAD6%gZ4KwV#r+N|KR3=|F;lrz^O4f9`f%qLRj z6BPto5L#&zgVMr%=`7GA<~qXgXSj$SHNan}Z%+&R){G3+wd^qeMYwO!KsE?3fsDxCQ zA?;`vN^yoVr?sDu;zEM@^Qd*P@bj-owhTXeO#@(7G=jXM*5;d_jf@PU8HaqHjNc%i z&oztduDxnO!?o<)Ebe9J_8JP%t#g|a?%bw?JGUv}&TYyKzT%goZ1!S#OHoO`OTyYz zf^~pJNlb$KQ@FH3yC5I!l897hLo@$DZRFeqw;;KYGY$*Pp=QyMX8N(l!1Lf&!>mQQ7|Ak}Mi^NeC?l_edm{WX6A(uJ)G?As z8A+rTMQOAsN((E$GB4{BoD&emvJJ2s>#hea$~wj&>&UhD9%XxE9GrqAsKRmSeR7*zY~K^sLI>oE zYUQ^ zLJTFwKyZLDWlH0$x<;`Pw3vT#EF)5u5p}bUcFJ8@h@{A0asRS%d<~Cv&=>)RZeyAo)Dnirh)4TJ(-4VQ$xlfvpM>o>@)j{hPwHSW-Mr! zM+5C{dTF22NJ;Fo)$z}R&~0kycZe*ld#@!&rzfxCT6@6`U^Y6DgRI{SWy62NkaSaY5z&^AD% z5+G6uD2)w$eD%R$7>=M_?+B$8%f~ll@6{YFNlUkLKYQ+51=g z$S!-$1R$NQnOAg3b026UBExaUA=~Tl`ze+H=>{y?1aq1hQ{ zivX8p<9$AUG=;pHARd+%9arLHxVOSZLkMnzdm-GFaIb-j2awV@z6EvF#zCZFB+{Xd z(%KPTX<;$`87saU(v58mWGS*2}8T$0*xXoo%udKYKC% zE{p^4hYmrn2BSahE$6rYV12EaSZ#b=nunX47*>sf z%T$g=0hL8W$|53N4OH4z6V51;d$+57bLZ83SzEwOQgK-!$Zd@VA{;Mrj#reE3D7Q! zaFTJz#UlK^p5bIxt21K6;W5}QuacJw8};c~v?((Ga{TBO(jC_W_a64S7cpA@Db7WW*h0g((;VlBlygM74MAzGsE^XZ z0|t5SJEs*7hV{X(JX+4NuT7o|V}rGQ_AHN@ zEU8?dhPYTRsFs{5k5fe}!1LZo6PQgfm-niHjk#d^e^ z(y-h5Sfm}C3K}cIr!>VrgYDz6OatgGf8CQYJI&-nnkBHd_Tb2Q$je^LzZ4olr8vtF zuLjdtCJdzI3C&cvEMFa5GV^DSnMBG=BDF3`+hW3XA0HiZ&6^4QyKCNM+%@}Y+j(WkB!K-}+ zdaELb%fCad3(^==;AbzEfpd0_Avp2lb)nJMi;TXGgG)nkFPy)y0pQ&;!W zz*Zt58Npiv(1_G$ivb`zIcTsK^QUdapBuG40CurV55i@+9)e5u9RS;veMHJWB5n3c zW3yLUn0c%DSrqM_Ec@UkSCoBAKphon(w2RgvIK9!%IW1VUs!!Cm4kPsAM7Oy z-6}@LYL?pM;WA%nS!nEaNnd4Ct78+9vWZ9^3@B|Q;wtTkvk5(7a8VCz`de?Sq=PM`wW2;s1FM=k%H-TYbLH;l%J$~UJfY1bv5_@h)rB($2XG>w6SxC-FYq26tvd%)C z*$8!C+CK%2b~J7&J}9(_j)tB+_=nKuI~vxC0*!l%qosi~E}xHT9uEU)+_jFj0Z8LM z>u4_mY24k8_6H!1%l-e{zZnls2D%dVC@zLHY9-EqZy93IAn~G=I1Mf>%Io-DkKd4p z`ZEs0ych0-jFGjbL2UvP?S64xz;2i2Fm>Kgw_R3lhXraNx*f=6o>9a4EgbP-Ie7Gk zW#N$@)}t?KtIdE&n*ouoH7jks2`2-Frj808$ZeHLggcO{8kg#{YL7MKd>rbdF5>i_ zJ5C$*Mlc?q<@bRZu4=EeneNFj91gs?aC)jWdpI0$oy?Pw*o$TwLicc{SbFHSyEn7L z@z;sASbD-WdpI0+b>Z}^YxZ#XPK_4Jod@n7&J;_}xpwzvv2f(oWw*TtZpm>~!_{p) zgu~%eEf&5OatI;n0o3fp0>fRg^hjy;a5!A*!s*%4?BQ_AREyOawML%h;gQe^&-QSE z@MUSoA8=>{&`Uxa>(Dfyp9^iSLs-2qZ??M2q3-}`dh9cIN{k&2{o47y1*CcOL(9^X zX-O2F38cOk18I8vu7>)~a;U-it^(5B?gi4g{KSYNo;Xt9b|6jf&(8O4hu($qs_*GQ zn%htyjeEI6lbr8uK-?=74|vEgw;kkR(+bqt+QENdHP%0_navI|4hM9fgL_UcJIF-s z6|*4l?Vvoh%-BJ>&1najC$~_*oVfw!`RM*xj?cqoS?)B$0lu$A?I4lbK_az-N~0ZA znhXcdp&i_|0iA$7P-vSF8fxIq$jhPT4rzj*%a^jOS^WRg-1XLs9l{zqJ8%ed*IV;+ zM6KbW%+5Ixv!hLu9ju;}9uD*r)F;k~plN&)fSwi_8;CYTtR0mMj)2ANL0@d{vELWF`Wcq)1tg$*9da}CR8wHfOpZcn;p`}M0dSO= zjKeS|;wKM*=>~nmqfnuB`$y|*cZqN(;3BzWVaZCfv=^P)Grw{8F;6?V9n()ANR5Td za^MvM3D)5!j*&#lNFsd>th99|oEd@U_zId#^mnw&%Pe-h!u>ppVSJ18`tpqy$8sEc z&>l;$FTBVWsLL)GNFXevXA5+|AD4JzlJFP4o?)y0mI(E$K)Hqb1boR1E7U1a+d&Yi z6)G)8RH%$I2){M>9i%|yiU`#vNIxc~m*1s|7&Bd}+~(|3nP*h6eIQ7d0~@XqYv5uD zO9cCz6D*MmmPlKO(%3?jCS7V_*00+cxuSPX)rvs-K%fw+C(kT?PK;Una!D`rdA4V` zX0F0Z0p%7R7yEtTu|;w$YK51rMKTV#9376&gxDgz!keW6k6&#VaNTsnwDy;{>8I!jcVYv_jLExC1T^H#>v%)%p zz3rVyXjuMfdK;IE`zN3wGv|2}->}VV@sH77>xh1_4zK1Jm#vzw)!ms9? zOIl@Xn`RH4CG(3)`qM_z_()HJoCXq^-NF}W_N?K{z--y!GQH}2d-@JB1 z9O3M%P#$EY;XiK1CsOfM^f84^t>swkTZ{JECC#@wHGwDByFko*zZ>b}|Kr z_=f*f@AQ=&F?pz`udc@9k>D7VGtPqmvgi~K*haZYH;yrdeHR~1W^~yt0a`VFG5mNf zFT$}@7*}gvKMz{;*>M82^YELC-|UPGy}jd^XB)Z(#~kd%l=Ui2_5*K6$omBbprP{R z8GOOdmyxDhs$ze5GDQQKm<}56RC`e zbW^R;b|Spe(3-us5vaxW&#Pd4*6vB+NcPfqJPNntG8)n9xoJI7> zd`!IZpnVe~+8h1s8xc7s?efG&zXC5_F6o8GooAzPx{ScZ1M~7VhYojC>bGBZYm~<8 z_)W(zI;HSOrT^-UXpx4wI4ZTKkfI%sYi^irB#M`Z$-w3;xJe}VAtTD?ohXS^ltg%I z4nisIF@wz9aG-fe7kxIT?^?xkIwPKb_*{86@z~xD9(DnbBE@43?FA$BjvVy8X?{_@ zsuPdOI`G(RFXsKGpXB4Rftj_V&3VB`QG6Bgg+RK(QsZdY24hxYW;+@mM(Zlha!0!# zNLOMG{l1QY2y2@pje4oMr&5sl(R~8n1+5gnui!VN1pnlMQTLA?+NA_-{mi2KMHR7c zpW;z`(}5P5KGiJMgyx>?AMM3*aCL@dKg$rY@SP|H?u5(Lx7XpaoNvIT3HqZ`AR<*D zB0Z#~v~4EbJ6>Fv*c&5n0`+X7n-so#GJqg@(Ron+QH#A&3`XjFeJlH?SG zx|03L|E=&X#V>{*udiY1M8i!%P?ERc7d4xV!!S4FcTGl;S;xYI&k(tmB53!^e`#Nq zc?Ub&xET;f*I`+Pm8g|3T`U|VSgxsXS++X3)KJa|bl60s(k0RzYD(K`!ilN$rX6<0 z6tcncHoH|>qVvdTXL)@xqb95cNiej~UA}w^1F6kUw70Db8}xq6cIdhf^H(vnTsv&DI-!u($hW-BwP!ZO&WD(>JbH zBR_kw4D1PyhC9{}pN1G&u4mz%3->v=RCI_e!FoIo_c6FXfy=U^*Aub-2I`?=CsMH! zso0f9u`5kR%jfZJsyA=l!0hb$0otvVNM?X_Ftu1DqYLm)lg)G9L<0uVzS3OeRGc@I z5{9UCmxqMh^hXo2%Ix;2<%>h}hS`v^&qG4)_@gFSW%hH(8%8rpw%fe~U8V$34l^9{ zl9bY$hX-?>$LP=$zL144#M6U`n<5o3yFwzl$$pSX1`z?Fc#0tz2H3w#``X zvWW>-3rkoq?6NThvs|b&&r>70$;Odz4XVr|Q!h7`YrExFXSZ^BX`1qAv+RjsPLAf) z=TV7c2g<~)l9R1Lm99HN1R;TMwdLwa%R1Bn46i#eyzap8TDt@^cJ2u|FEqfeg4XG9 znY+r&V@)6(YQNynv3;!Xc|aOtnxpYOpGw;fq;dc5XcwTtC~X#y=5a3&U%ZX)WaEGC zQNok(zy!_2QtxzCg2^5t8i{ zfw#-dPlIKM4#!`DQIRP*hTr$YzZ5RZh}|$^Y<>%@#)e3Z4UrlfrP0_Z%^S64%nSSf z|5hK*Tagf%Ti1mv5~jB;^ksguLTb%1=Y1$C;Qn zATor2H(xKkIs2CSM^OjLmOox!M>{LR9q-vLv&olnitu{?zu)yJ-!r?**Jgxf<2A}| z@|ATn(6Z*CcT)B92fW+h-UXCZQymwn5C(9X*+e8fsxy0(ii z6W_}Su#&gT zwzj4?@@{KOX1Y=jB+RtWG8ugqmYC&)AQBhD#ipMG%e(?ErT=^IM=dmwN}s48*kFA7 z2TvJP5b!aChTG+6GDM8!PzWnunRj<_m${X1RJ`v;f-1J*Kr}0HOtGv`S*57hE&|OL z8x1md5HW172Fo}M^AY@Bg_!lqc8DX3%xv(m%(^vLe<;reTb_xB(-PgM-(Y2eW%>hL zmg`S&DVlFP(GaODEz z+=m5G47o=!6b%{8AFpU{_&LxfMfS!s4tt)n@%zs4_$L>bpXJ>NBSuVJG`((aT|=py z5}!SPCcvV`hQ<86$LTVAwprVR)b(xYRE$mBVG&)I`2^~w`c9-wB{~8OJYCp!DvH4a zyYb-PV<5Zk+8!AAn9sm&2bqrm^Fr@tQ05Imy_9)G$~+=r-j!HsYuekVxw3dEzVU!5 z*W0!6j~x)D!%e@c!se>j{$F2X#_D|K>xrnMY8W*lx2|!N!ppYTiD>Aw&Qt(4^zY+0 zCc-Mlq5m29U7E4aQID8H0;OPXC5aKAcZzwV75vFqWY(Gmm=aB#^bYJCw8U=J8)Fv)p!^$m+8ieCzwVR?qZCrDrAkT_4C&pozarph*w!;9Xd(`v=i^Lkk zBg@5hV<##V@Hfx#g!|!ADIb7Km0Sat z<$4e%msd<3 z=@Nau&IA4I2wxe8Vcvt^%OSot*3BPwSd1l`S^Wz9ZWJ8{h^jgBn~I;W=3h5_SS<|nnHFM_7%6(D^8 z{5DYTW_mPaM1}L!sTB9fLVCTE;6F5?PK?7aZ{gRRv6yJ4RHqB;7Bz}WG1=~y_Hp`M zvRnm_M>HYKt^)qHn87kDwXV8>741-Gl3upR5S<<|(oK0JV*QWd5 zR^#~hYW#39>ke$assJ7kG(e-n-%?`_e>Z-(7<6wWsN0scRKv)B@@Fa#+sRy^;CT?# zzZ4js=u4ap_c^#1z{RnL1kKV5aHqii3EX9H@!hAyU2uO2m-+t;?vrp|gp0-Y0AB`5 zkpC~iWjkL{Zuy81&^Mz@Tg$rO%-4K7%f-oAypS%2LA!I@uWXMZ+N495vuX${-?TkkZH? zrIA5q{U&OR#Tx$Z_22AT@-Bp+EcPD_!2EBIOdjREb4)NU#!5dk&gPR_?`R&WbH3hD zXLBc0bJ%+eSJB02%Anf|jHqMuP-J39bzOV-c%yQ*mPxrw?Hr@M@VbE6{ zgNT$tM5=pAdjy#)?GOxFa|9T4sK)tXh(XskXwR61Js?FnWQSMOpmHyYWe_c7nW5hT z2J!wbxU`x$YbP4TueWMrB~peFDZ`XThAGW!tlTk?;|trh%N;wvrt=9A?eod|JN`l(_J4mOMgHjl3#1k~N{>B>ZASGzukdI}cxa zps$`e7zI=e4T;Mv6&uKaIDk{yr-1l+i?}S=^G*5OL<9X3)C7bRpP+H!a*v?dR_&?xf*4%pRqh(i|u>Fj+bkfwJh z5L-PSBm;4sHy%6*^l6knKUfchjar~#;2P8lLN6686W?~An+0_MeMS&1!e8+#!_QuP zl+Ctb`PqO4=#Rp7Ff9AvOW8T&B~`(L_0C;^ZQYXEMue{JLJxg$nk*>?Kkx%f)O z*x55?@avzWeF;uzLogdi#(hN$Hn=O`ei3dH+~2{y z1@1w(x56zzx(Fk$d_jH*^gi-_>RaJrMLF?JxGA`tm<)n;sD&j`3rnPreyBzI=!Z!6 z&r+ZCJ9k6{!7q^t^{#*LYl8}cKLSxx`v-qEs35olxoRGK)rIB}?$OroMBrTA8gw(r zXiM*&H82jD%O34pez%tOS%XvA3H1%SqBwf-j2ZO}6R@_}%bxC z56-xTh}|X$mT@{<7O@^K1#>9^sbGjyFhqJFNNMDk(jtsJ2OjT~k=dR(_>BCT&&Y1$ zgCoGizrFX6OyqdMXW~Y~#HS1s@!kSq;@OUgM9M^>0{Kp((zb(FO3OZeXzEyqSAMM8 z0MXi!LwZcH8!z|+g--Y3@9K1Id*;CZrSa@Nx*I%Ht;4pa*6}!k$8>Ef#pwyf*y^-S zh9K$MH7-GXDtuM7^ustqlDc$Y_SCcVu(Clm)UU$0$+Zp!%Qi1vr4b`I6rRU{VR3oN zu4pW1Tcty)0ph;jxIF&g+uP$bFw(f=!9zeV2o1XpOt_bUZa{kZ@~L<2!a6`(Dzq-3 z8wKS-z&9xZE!uG%58s8L(>(K-dd^fAsyojKk+ZbiWi*VcR`KI<710 z=PsB&yYWV8`pnHxDiv3?;8oc2}Pea)Rc zAB7j2p)qkrQctks1Oy%Q$6ZI|KNx4 zB`V-%SJ9XL!3zcz1Xi#52W_BH!wLd+dz!~egUoZYY&%z~Vw+yc!)J4)RmtnA{CmEH zAl{buxm|^;@EB8l+OF2)LEQt#ajZZC@0!;Y*}|e9yW{%>^)$O8K1x%>MMgzrV(#^m zCiuqiv+Xy!UFB==J1;VJV;m|3L={|8f`4*h?B>1ubNYfAb<;)VnYz7vmCtM)bg%ui zpL=dZ_y#@QM^W>3dgid7_zrWQdlui&xu0^I9bA@m7sQCapv=(mi9p%Lf^mC-b->vt zQK^4{o2pVos!~J+0Zoh2It?laa#{IuSo!T6SZ*^vwAR=+<>|_HXZds5*VNn4H@Vu; z(yWB=&{+?7pi26(-0z4MQ1*pjus%jrlQ;{sV}wR79V-a`x*5V{ppk1iML$P~%+m#tBh zk$IV~gxd;V%CaCBgi>gFr3Uq+dDvMWQoTuB-?2wtaLyhhfOb17D5O5xGx)i5aC2Ue zTMLJwlqaKx@t^{T?}v!Xhu~EoCxP}^(DL~@ZZpfI7NV~MEdjJ#5USZtA6J4#9ibmD z>f?uS$NSgu+l^oJBP)#aA^hk*l+nj&jpJv}oPF)+1=rq)+2ns&IS)eD&Ug=dL)kf$ zMPIXPqh$I^w@6eF>;R1t>@VFSk?NzSM}5@vFllJ&D8AA>zRkSRHo9dOUk#8g zyLgCd->YP|=7zTP(%+q&m@H3e_2i>FVUazZIj!C~pVZBG@oO#WYc$-}O z(nd;y7rgOZ7J7!jod>Cmp^q-kJkH%53;Kdbx(-tel)D!`5x&LXb__pWZ$W?G>*+iD z@DE3NVaCA>CwLd!eT*y@dSUa~D`#GMt?!|$VaQoBf`dPt;euS#n*;mp9QIGZY^D)}8? z9av$^ByU4=w+HlnK-M>xfWq?8F_c=Xp(uf(3Wu%&Qt4d_lv{f9;Y$u%E_0=v+tJ8r zTB|SO7yX4b_Jdpr+F?|w60`mvKNkxG`RAlQXaN~5J#nplY(FJFVD@J<)) zMI4^gXv-VAD<*V32INM{weT9YE4Hgr4`s>GA8h&v#oJYRKsNHvd8wbYYV)P|#j&=$ zl3j)Qzukn!>g`cOM|UQ2eF?>n%ehZoqMZ(!F56OwxmDmn_)^(z3o76r280%f5-@Rl*-XMMn1|xst4?AF>mR_0ikW%y{Egp$KY#|y z@{EAXGL1A1_;*gsL@H(?ZNN%vMR=ug1?iAyHrn#~?kd#t8k^eHXj^j&`OxpTn|xbr zEVc9N;pD|!l!OejOp2bo!2A)flf20B8@IB1qX=$2e!q9kEz%f83^rB9%HXVR(e709 z3~5vfENir}bp(3i;vig>=U;Fsd>SV;qeLnNB7Hl*(l(lKVn!p+;oS~EKKVWp8y2oc zIvtnbIL?BEYG^5V<|$QdqFeR>nLN59&`*MQU(#} zGf<^Hf+$K8Yt;RqfoCde+Vc8%51)3ysPjd1U2T!q-)HfQz8#5i7=}}iGoAKEti{aw#?12(KLIr!*Hb(Tm)LZpWdl(q%ol}5|q zp8?AGWE!hKnuxN6NZCT9dn1*$4)K-tUt>$%kztE_7EA z30^ROCQmLjNpHppof=a=ABO@ipHWq}Xi@coMc8J(KzGpi`PtaeB5zdAxnt(c33aSI z6EI-@o%n%AL7AaXM$==Nu7=BUT?3ch$El9FM9N$uZHh|UV!~0tycp}qNKNVPG&q<}ZU z$izi06mcm)(Um|teVGoFTlMF`mjbl?MO1*HtL$zW z*iJzkk+^>SsoMmU`A3&^Z-X6SnO4H(;G`KY1^5Oyq;`c!1xTars>kNmE0$n*oq#PpBv8B>Dwp3a-4jr`?iRR)FCyqUthtI(O;s}ozhmstC-x{As zVZ(Z{Tiqq6E?a3{W^R6U!rqT-i#IzP*?y zmCbLM{SAXk9fOFJK}7nZGNr9YT%~nm5Z;89t69<<^u(R(;UArX_@--`Z}eT?EN1KS z1}wPu*64=@(a4kPREnRym}hhxz1Wzo62~1PUhm55eV#?_tBa3ItNl5h>@0)GR5DW=UyTI9K|g;@snh#ktY{ zG0uI(a1Kv4g>zpuoEzmhN2Hu1QqC!joKqS&*VJ*Dybo;M2G-0xFrNg$WZow(qh%Qu z+kFz5@w0oeD&J%kxY0IF~;9wnZ2Bok>@0Yru9X& znA$Pz6100IId$;sXyV!z*D&r08W+o_HfTyS_EJMx!5|aatgC7*_Pq}S;T)NJNg{!u zXh{B&(a|cIyh7!akT~npilpVNPb>J0*-UG5)yDl5IWo(d!g`wm?G&E*t#7W~n5x{^ zT)8t2z@hzZKu%7Zf9 zmOl*MPeCiJo7!oFG)1BY;o@1u_PBZsyFX)1k?yQXp+kkV!X=`8&QhxpDnrSUyUTKXRV zY3Y9oq^19@LvI3UjC?c%MIUkKB8L_^)a1}^AbrE!AA#!e%MbSBziu3Q3rLRx^aICq z?H~>`L&B8;%@hRif0_Fd_^OKQ|N96cCa44h;vNMRDquENwRuShix5CIQNa+B7YKwT zWMNb5L)40hwN)$bsJPZDw%Xzz#RY$2i&ZOBZE26Hs{bfbA4qv_+Yy1?H%aPjkD{u7Ys=Qy~LCeCfZQkr)? zVSIgag;_ph7_RB)TAb{Q+M&Bie00ILRWkKYzG=jDaL-Z%Wp~GbZXO=+W|$X_n;R=C zV{-Z(i|gpln0vFR+V3ClgM@N=3&SOiO~6HA=K{O;?PE5=+*=4k;6?zs_Ay(2ZP35w z$glNA2$8R9H?ER&z%`cRP7Zxqak+*%ifnuAT z^LNl~pj$w>S^90z8qjw@ZwGx3bPMReK)H6a6IeAAqfHGcXiJx^R4juT&V9hqrd~B* z301Ee(57BBVChz`8qk(5U+PuzFq@Y!(&Z%;#T#RIH)vZ1kA={<j$Zt)VP_Dc*S>ddYH5hiwj0*}<6# zo2tzXu+<9hT-fG{4TU05b1wjogJinV__tmC4m^L&rJsJdNUM@hdptFlVYtQ(%W;0t z_CM~h@||nU`lw!`nWw7+Yeduy5R`G{q>{tB0?kL?A=|0W0UZDyG!-ufJrDFWP*h|o zkq1G0szlPJN+fOR&P_m3w;7yJh%KGxH)8?`lw zsP|TsZ8e9q;a!IJ%s0C{2VXqhNuFh>t}zb^P)Ax6!lt@&Hub8T=ECmN$U5}}Al0q1 zcq<>sEbZf0uqk=h8y~kB*EO&yd5^-T{BD3v$=eK@3gcbak}sTp1lPlHv7w^j!g&u+ z7U>0f8a^=M&O%lN zZsW4PjKHqz7GcfLL0_e|#%e~cFyQDSJbS34Ryd6F2wZk`S=P>pGac80R)AvgA_qZY zXF;54yAhOn;Y%W_y3nSo3vH^%D;|ry;(6!NdI0RC;Uvx^FDV}ZuZb2!WdW!3ZWhde z-M?{;eu&}Ilgv!q#Hc6fRaghDl2xoJZJa!R1Pvx%b!S-Fhzz<96j^1e9iq;(uUQnys2oSTw{yHFoK2t7goW!o(iyY%P(5VX;)%s>#)* zX01^TZAvw?Db*+*Rik(zs(EV5f3wtdNm^>o_^*|kS-RA0G^(LZsfISC8pWe(6mPGq zW_P7#d$Ll~R?Yl?Qj@Ps&BI1Dv?JPD}{z(`I{Q|0pH6;Gqfqq(55t_c+`yI?QPA3l^I(zJCc=|wkl>fWrkt-Tblm5 z%y5FO`X}0yW@uBIQ9No!@xllHOSWwR0w+UcqX&L?5bSy(b43ZZERX6WN6l{q+rgGo z^V$!FV_VG2m*936g!?Mza`zmDX=^diD#h)Lk}UVAzb=Wf*V!dmTwfwc7AbM;*xLEC z-CyDhKSlv`M&gEX3RgbQD5F^3WRv|xy%7BsD|kN*=Q7}p(N!jX%R4SBYh6CB{jy2V zEFS^;`sL#~Et|CA!_%#hbR@ltsGC~WZoaW61z*HF(%Bj6xWc@GnnW#XYptTYFw2StAe3fTjDr>DMyQ$BimUk(CsPnGZpDfmI=Y#pekyNQ(*-Ze zsQgJbTU&R9+cvZU?iOgucJ1RVJ4L$uhQ?S`O=WYeYAjBnz)2K2>g|7do9SfalX~@a z1Z;d#ljV$u?KzatEZIArB|Ho%9QE349c&MZ>jki>!{jbAHcnBR5YZ0uYUBlCTMynM zv2mKDLhFW3S-GA78;{w+Igqd^SAO+fxn2MpPsqx0u7gdDx3T$8kFD>8O^v8|&cxpY zhXc`MqLam`KX;VF?nbVgh~M*I>mc7%SJT*R@EV2J2eu}$4T7y%Y(rsd z5!*P}=8KJa@;R=axLnf!*Dd(r4#ytHy2y!W*@@kOi|1tcHzd%{iEtxbX^+~?lTY>1 zZw+>O&BXbyF~gUpeG9z0hQTPa$MfCPYgay3zTw*u0jVP@Dq9*QO7b!<$K~9WoaNvR z-}(9tUlvEj#LK*7QUG-n#bv!Bd=%L1&aOdshO^M!!kb7iry?xtY6>m|`Vg>KK zVSy*Q!8pme7kmkMEm#b=n^Ubev=Yaf6?nH;mb+F0>Kf+J6kJRYOFm5>$B8rl`hv~? z9SF)^32k*8Pm}pldi)Yl)VKI`pqP2e_ilWg%~kOlDIZS!G0;=-`$f>v zpj$!9KtBZ?3)&8G7zaviABxhbdKubOFGE|pb2nUBk~3tffHt-1hGja#c?_DoD{HfbCQD=yP}CSF4V3*2o}&D%chvBkSpBaVY6cPtSWW#UJu&Z!O#Z!q= z!IqMx!gDf1Vz!-Q31ZxspU4KMr{;f!)`{``8kBMVMz>b@Ca%su+Eo70mM-tzD&7|0 z6)#!-C22L}CFE9oG4b1_PmjY#!N1+76{1k%H<}u+KLtNdFj2v*QJBQb%V<{Cm^K4r z?C{KX+l!8JinSUwO@b)Cb(kgjq!&I% z=;KwfGxgstFO0vxykL=9>Oa~}`S{Bhy1X1=$_s6(ywH{|i#v+Py%vg>th`L;ci~n& z+#LbC`#{jk%#O@%H`_^k!*TPpjriFPf9A7}o2PA144bunMd?Nqstsrq*5h!!#8a5r ze6w&XHK~i4+U6m13>@yP_Hw+6U?T{}U^kV$x_R0&5;FL%1mU*2(lKX|tsUG0Q2H1n z&8T~@YbBz7xeta)Si>|j79I)rid4VcyFw+bUQzZ8(%*`i++)ziTG$_ieGTmQ!hRR* ztIc#2{dTgs&C^Mr&R5pUc|PAub;96B4#~)JrW+eJqv<{97s2+K;4XuW@2h3Wi?QlC z_XEZU2RcgLYp|&)#ixeH7mJlEpVF%({Qic=DT;FCGiEjQxDvMQ651-*W}#SiaBhcf zB5YX>2XTD<*nuZBJF~?W)&$@@W@kEL;nqB!A7UR!@G{(n_?iIvVG}?q4`yLUjqp6v z=J>m@N!9S_;;wFPII4#GhW4p{y8Q&7VOx&^wwS>)GL5GWxR0Z8+FXp^pU9M_$x(#g zO&(F3XUQY1crh(}mfQh643@>TYp=cNf15SI;D?vMe-VVASD5r<%plp7=MsBF# z0d1e?d>0e+^sm$55-_+8LKyX80KDQ2l!cXd^EF>u{^UBjyTReNa%8 zQO`g)Ud1a)Lx$LelK}*c{piX1D0lb}WEK4T-#Ny98F{t*Sy0A>=cTiZ{L_>X+Ef{# zO>JIPytNvaeB#o;F2!@=+8MXNlRB(*S=r7NrLD*wy+f>Q=hCNgkZb06G@On>c~ZVFX~HT*-g6uPF-7S4dx$3^ZO4TLob#+gaFo zf|QGm6Pr5NIyg&VQ*9XaruOQrhOJ&)*TB{wHkJziWQUq-z~z=0o_jV3zxbOahSN@e zYeqkVaFNckON^QMdkYNZyT%O%t=UCs$ipAFJBKYBcjs8o``M6DtLltQ>Xc=VlNrX< zHHoDXg4I3H?W z9p^)vI?jiAmBG*GO0K0l-)hMjGBi^1yvyxqb~vSx5sK%1uXWwv_a9O+vSCZ!9`u51 zLgT?_qRbh8dq6)2;9{H5)6QM{ECQTUI6K$@-1_c{Y0 z#(s>tXR7o)-;gCQzcxo83=}q}rwWWm&xkfTNtfP0YxDO;o3try(x$Yjc+{ri`LwCa zZDLVcw&OLmGSFUK4Wcf{oymSb#um9ot~m7_5K z>t^&r3}*?)B`e2u^^J4oyJVtmI|%sF#%_1bXFtP7VG>VNIJ>PVgMJy0a!|&lLhG9k zWt6^YQ~IV&jlvXSpKR$SCllh)&9}LuIF$KFY{@}yWj`|aS z*u1YgKwlnt&%j)FI6N_{v*bL)Ly)KrGAX$Yybf}RkIF8t^eNogust9?YG6yAne*Uk zYx;gv0{bJb=fmCKDA7-MTr+U}3wUMhN|QV%6Ahr9ljdWf{Mg?RE$~^0mYnquav1&y zT$JSwa(;r0WSpSs_$bivpp4%{oxu-57b=5kQyENKx^pK`iuW6BQ}6I7-ZO@mY&9o` zL+{{OgxJZ2r^j35N%DL0BzdbmN#5ozU|@6|zLXa}+;(@$UV)+{hSOYE`P8@UL}#S4 zqz0aeV&8#h$m+54Ww4zkyp^y`6&n@kA2D;D2DxE^GOqqYv^Gt(3V7KjPPa!v*=sxo+6nXz zrV!Dl3K4DT&h>DmPBY}2*0ia8+tj$)w@sVcx6PbU`?hIQ53Q8EojQ!<^SmgITy2#X zi}cFjayeL=8!r-11UQ+)Lh)8e<8rfJ5!BQ$5|-5SJaq!LHMg@1-aKiL{w<}h6v1)6 znkA2{{w}u3;Bl)>mQxPfMzPI;jXV9+Y)_rrz}en3Xv3cEv7DYQyw$Lki!H3g-UHVt zF6I!;8|aVhv#r;Hm*ZQpqMzQlNPn4Fw4T>e(JcG7)jCxauCDnJ#nfGm<}qccobH<) zT!>-?R?o8LW1OdsY_)fEv+0YvQ2=FpIX>eeZh_`kqI5DXRiLMUV&{K+JSg^C%RCP| zwWajpFgx7@(xyr;ZRxT$Lj7hqSHT}`=~9lV{S4lw=z zUhaUe^_H(U#n%RKC|!E)Z7MSVoc44_DMS6Bhb+7;fPJ=Nn_z5zh3y37RtIMbY{@&} zf5Ww-zCdJqwLPMG1U&zt#PmbV-*DZZD8Wg-3f<&>prMUJEAxtRSG;?}sHGtpRTa$@ z>H`mWz@omI*%u)j*^Ss|t==kHi2)0~6|A4Q$}Hm&2yqSL&Mts6n{zdDHacpiXAUSg z%+`YT1+4=u2CWA@9dsTjhcu0#T!U=_T>;t*dNXJX=mVhhLDzv|3s3wt&_$rs)nZV# z6r+(>YCu4nstvTMl?%mlkok(2q(tNM?GWXBxSteae8hR@((`tvop&h8rMzU>5hYmJ z)F|)6*FA%8JZ>m~_h(QE)p^3ni^v(kF&~f(V*G>d`@r>|Vn9Ds=}26Y>~7h5)y!mG z8w&>4+GP`X7hN!7V6b3}ZD~fSNHf9Y>A*qw{uWoWnqjx!-(ur72$yRZUoN>bjeRt8 z&_1eI34zBV zfXY&BrxXKB^IuR9icL7!UvAVkcB5#*GJ_916+RzWcIc-&uA#X0H>KO2?08jA`L0Q1gROeANZ_jePK*M=su1ehSJqw-A(RiRuc(LaQ=}HkCoNsf}2Q_ag9$w@uqJq$(+%WLhuI zf;K&z4tMLBHXa>uq{3JKOLy8oKC^##U&FFp_{Cu(;63|?_2PME>6^C8Cimqp_kAwD znZ*~fxC?nj*_*I$!pm8zK`vkVOs_))w&g~SX$}R_+|mi()REqVUc!4=in z82=;6u>7MRww=>)&9w8+)4qH2&kh6Lw6U8R?|DQ1rh;Mm+w$K!stvyn^cc9`4>}!m z4QMCOZpduaRM4jKkv5f&ipP9ZJb%B+=g6fU(Gtk`9T~#kIJrJ^2}kehIdf@e{Jwx= zclAuVlw1De9Jy=M(&D6cQId>I zL_qPeU#eoEoHL+Zt)71hK(3)aa&WP88?BkIpj1#tuY$4`VUR6Ls+jb|IT_jnItFwz z=-Hqce9IonH$YjMicM*vO_e6v(jCqM6%VU-VhcT|GY8|d<(bPmFF&pQvT^N~pVo2N zxQ@$5c3L)~6AOcS#_M0*V%262xw+&o3>U)9Km4K}CbTauj&_wnVenSZA9fg6rY-|q z1gKZXi7^jYU8!)_Fb=G)(2r?uuYn>Nua%&T+qIxnY?e_hZA!7Uspqtcw_fA)&XMpP zY3_awtW77H+_Tw{%e&TUvj<#cFBp3C%+l?y7Y}z^C>L*1dnI5PkXibkpSz9REq*Qr z2I%(vT#>NJ&lL$c1jieiNZ9D-3KomIM3Oi^;~(ymjL>uUZ) zRHpDOD6gDVTo+tX_8100YcUw&NAlLdelP5I!M+;yRrbJWdSYON+H@3Bwgn|nJttCU zf1eEAUxYUvwpYY93$|Cq_A}UC6WdkBc8{^O!lwLkl|3<8&q8Y(&fCzogAk?~Y8?sNWR(0Ysqg-_pch=HBSg0?C_r;*54BE%ME_8WemKNA z7_`W43%o-u&lwO5!!>SL-X6gWwK&XY8>>EOz?0&6CQ1~XMT^WFfIq9`ix)f;g})Xq zlAqgLY?J(aPybx7P<}q6e=c4uKexMn6?m)bs(x~fmy#E#U_aA8mE)VPqmr~y|6Hhk zy63hmQa|0zcMBIfR_8JuvRy-+awxeU7!x(~FKElCXLd5jfwFTM1e$@NC5P9Xc0LBm zY3KK#oOVW$UwCyT&b-M2Wn1_K>}tqDn`#SbOXr8h#WllOscr5#6z=DJ-dk3>by?}Q zWu>0){J5=vY7|R%9@tMNDDtT9(B+@au4M%XdCte7jVbt(Kq5(A z1Dy7w+E!_u-}BFi+*uHwHXd$O_Kq?GQO^+vA~A{C&*3P)9b^Qco;*&5tEyle6<;8( z^I%i&(JeDPHUR4Fxm#g-5*d&s>#0wO?N8vTEv%ox_E+KUf-QN~<>pupVpvybj>j@r zPgG=9uN}Ca!ByxR)6q{)@OR=m%C5Th#vcsjJaw0WxQ4=&u}5>}AvD)M86WoK@=7DS zc9y|780C1?tTyJW!mRCyn#D(-r|JOQN1q%9jLM}6~q=CizQaf!q&%F z-Ljl)NKBreKY=UN>#Ep4EL#FMe^X399R6_TRBh*{cUb1hPFFs>SjNsyGi&lT#a7dm zWBFtp{KK+4pl8Ml&y{6G>@HC1oo{<8z0;=jPMaE*Dc*XG3+fo3&z0vU9o3oYa^#^} z!dPB;?)n6HC=n zWd0A7MGA{6@nN7FK&hXXKv{%1s!>IVHdTaZOLqoElxqgRWh6L%5ps{1L7TsPQpe5h zHXj}l)>B(Jx90a(4eMnLx54S0;OI|E;ft;WaeCF+VTSvMRD8%wKGjR(F9^Q@&%eM* zKP(7b{Xf($2xyn}AvI`~_oN(rg5YK4$}R`x-f~dxEeGXlu;P}3@&$>^v)f75g#+}BWr`Llw*w@$64|T$M|5t8d;0qyUL&zRxso5a3M_DSZ zw!aT$+?c0!9xiF8^6&ys=HXIM=HZ2)%)^U7nU;$|sRuTXDi3K>c}SajZ&2~JXk2I> zJ|(pdc_AxeDkH*IEP6u>)z6E@ul_~g`9HZwKU9AYTq_R3O^i?dZ9S$Yp!z7Jq54=| zVz$UvH-=61q8UQBugqYrwnvTHXj5vVO`Q~{c&+fFc-{p>&wDJp)f!vjJ=GfhP;1BF zx;&ZI+Imn+xYl%^5Io+TVf(dqlGfT|Mr*Vwt2w5hqV0!Rkn@1{wh#$Cg7?L>ivQe|2}KAUr< z^FdHn`4iA*t13^M$_3ie9j;I)-r?GoZ2#7hZE;A#7Owci*|1n!xUfqL=e4LUTRf4* zwd0k|&83^(k{0_PJKowff4X}F%!;yATOq?)QMw9?H+ao>LMQWds;~?m6lvwp;XLasOHF(Ol0Je|B#|5yd9`s7s)cp1a*wp;?cG%SX z_CDDDCO)2kO)X*ZNt#+t<3iYKaedFYegoSD5(Cb^9ue0gVdKeO*r*K~Pln5K&V)@# zo(bD@=%53)(CE#dao8$^cNuIm#KvV0Y#jq`HEh^C1{*7VE`~RV+Eq#C_ zb_XuJ77*xw=%)|dNCzawbWOAB8=GTI%|(rsoODZj5C_aP6sgQ!J~75U5K?coQzt~S zJZMHPnl$@+>6P-^UAn@1qjG}eReGVTo731NfR%>9SI!fAUpQ}?q7uS`3s~UPX)e0B zF))@$#jHcSqmMM^SfxRElsomu`F;j|RcSs>HIW?_I3Fm^H2|EXB0HX2K+nYQ1)#G* z7lLyBzXU)yHMQ(xPrO?_>fB~*QFo3?a0b4i6e7I9MHUZQOo4oj`# z1-rLSQWE{8mQ6Z~lUr*2-P<#88|NFf(vRD{-I=<3WA~Hj*gVGvq&p+sO z8nb}Axx=Q8;`$UnW$`UmlBIKA?g8MF&w`N^8}rF$ALO&pPdlr=ravO8Y@>~h>$R#+ z!m6NlW=?W;_ zHEt*<-N;(5t@6-cv-{9pon!m0-h>Uj%Eqw$J5*|r(TvY*P{wJF&iHRk#?z)Uo;Eea zR=if=74QGsj8|Ff&3MK0X1wD4uQGl_ii}_MKg#&II^*kf#@FkN|JGzYZ7SnwQyH&# z%y`B7|2E@Q{q<(N;(0S(@%~pCKQcweFa958{5+lUjXL9-bjE*YGM+Y-@wBOoS3G9C z;;}DGd?hx~E~`nE)s|ZfYl(i`|H6m+U~)N6-|%izJ_HF-SFid}^@frrmjK^o7jLR2#z|2!D)M$Y=RfK3$+u;;% zE%1uxEkf22Dp;afN40#8t0ykk907}~F7o^;n+0CJ)vFRiKa46f{9s#UiM8|vQt@oT zz-nW6wVu=7{i95VlMNa6C=-w6Wt91vQ44KKEwrV}OhNJPg@45hRm+b#(R_Dm$qHAC z8iD*5)Y7cg!W}NEw9uy1LYq>H;!!P%x7XFe2Y7iYO3QyZyAWe96Sq|>W=p$SUdz_f zNLX4%;Id0gp>BuSv?#UErqn{4Qj6kIEs7VS7ObSFILiFTR-&%qr9}-}{tKmLzAi1? z@ubv3n^FsHN-c^I1P zt(DJ0%Sv07lDe!g9DmDFqRR@0IZ7+EDXq|^w4!*_isD&X!J-FF(|GG}_w$$?H&6R^ zGmh}J2UY93!speHrr!KYKJek-f?4loKYMX5pYZn%Tzsl{g0EesA7YNdB_l^rw4N1} z^-a~g>AgeOK>WQo<)iF)+GD(AE4}v(NR!eUZAxpjsU;A_TMfU8=h0dxr8U3$I)|z6 zNQn3~#AZ3Uuq9XDV7O9M9dXh4)mH~zAD{Z@hw3{4*JFvohj$d~^7cr7XPBKMQHU~2 zN`7@RJij`zFICieqfsYqN}aT+GjbH~LHJiZk2>2}2(J+>_JWM$THIYBoCe?ibvU~a zK9SJk4=sbTJd=%ZTtoSOt>NrM(b`Q$YqTk?(WVNa;;|4a-Vf2*%Dteq-BsN`CbU*v zG2_2ib+Jq?TD#t8jW(q<+LYE5k6Kf_AELEu_kz}TSJs|SXsxNHZjb8g6vvv?Wh14o z2`g*&X|3ICv__lK8f{8zibt&}-Vf2*b$dZ;yDMuiSX#qM`43W?zg-K{+V8a1xcaZU z3EGs_Xj58KJZeqxa1^4m4A*j8SjFANeDTv`_PO#9P7snAy6r7Yd&v3~;?lwC1ly%z zG>R`NHy|a%#C3{BmgvtsW zklrh&ckgsZ2T?g>YSnxRLdi}N1ioy6Am$>7sWX}rdzp18RbKJ^_IdzKKRy7JysAZY z6?1DUo2FKpeI#m^2a+U+apsT8H<~f zBL#qijh~p}!L1z~WSh)YDBvA1WWn=#v2}-y&&oPrQ0DTojjbna{P1fB*-g(wLOOu6 z=VrW#-B^*q*bNpN3vVKJLxjiJoh&xS?x$jtQL@;w!8=uKjNK@)ap*8wY<*xGDYnoT z9fx8BC1XawyoM1ODA8myG(>DJqF-UrWV|Zp-5?Z=igURK37v|ev{O7T!j1|HH>bon zx($Zgm_!AsZYo05f;U2x5QZNnQi&gFyD?$pM|=D`W4%8C z*puKH1=mpcB#}lvPw~iAdd4&9*hIb=ns_)J8eQbF7)m_LBS$-6W+H6d9Hn`dyM*T5 z%nD12iXt`XjpFH2w%h=wSij;dga!3omJUgOy~oMFx#ymfU)nJGl?#$f zUn0t~sXZ;il0x&uHMfjcHr|P*;a)bTA7_N%B3E(jw6mp5i?}}U1BQB~IZ6>}P1`xP zuYKW?7V#+E_|i(npoNlbUyNGOPtqd)fD$ud`_qgPsM{YOCL=BK zEilw3&4B?q^qm%Age@s6u_-J(H3Io$-qI^)Xe8jy3aUGGuE|4*UPKNVb)(!vb=+ zP@Wd)K_M^`mJCDD_owSfxTHls!`+R~5dk@@ooNx>R5>^OU_UE-hIc!n9a!v@yp@w%Sr(Zx$-+-JG1(U}+ zu3pFgtTq^*9KqQ2;>3U)sacVkKq5PwMe+Bp3CfXBB0a7A$_>cLm#|Wo=K{gl`IR4# z(_b(wY1DJ;%A4*C#%F+FT6xDs(?1|*Ah>A})_SJv%`bj=bWqM9!EC|Z&G&%;IZ~2M zPkqGN(mS%ZUocZhr~`a*70VE$%d%W_^He%%84exTHnw`d$=} zQzDoi6ao|8uA&KmoSnG4=_(1xDHTlWc5IknT6xDsQyP#n9NgWt8zTh6H-Fvu3=hZ| zDH!$|G)2`1e;d@#sc`YO8zTd9MhV81(`Ea09fNY%I;BN6;qJy~R6tHy8{~`;jGgag z0Xb|@(;~f*_AJ;2p3`++Fh1i1^B(SQe8vXkoF*79P#*)^kXZ+#>if$N2glxV!f63H z96_Z;_J>#2`Tbv5`$|yG#DJU$0XdTd!*a-2tXq)wMNrOU!EC|ZP1mG=oYMt!Kkk&X zsODfajsA2^5sa;$(*ttO5X_ZYPEqaF+k6wDUf-T0glkaLz`=4woruNS=^lrvQ@ zTQmj)->{=Zd;B~NztbX@;En?5^jml&Jo(dgwqUm4?#5?YKn_Q$X_2_bZ2XSLXZz($ z7YrM4S5A3APK99Di_!P8e{^~_C})OX?Dn}LAg59=ZhpOAeE$bQIaPwO^Q$r-Cngx? z7vp^K!-qZ{lv6DjyI+n4u*y$;Kn|KMV15tP9spbA;$>e4`xkxa_ z;Ldbic;n@_2IX8Vn2or*@wq4<=jVdiSC@@@`aFQ@NQw4%mAwGQ8^ExQqWO714yq+E z?33wx*Wm9D3CdxuNsF}N?#5?XK+bZ(q?U78K+f`joE3s`%d>Mb*S!7dx?C_UKW=kCPTbCo1OM;UzBx(}gA*m^X2E({*J) z&eekX8hLsIY@bf-@nulXuLY9@we1fZ&D8-p*MOTAIapk=&UW*aXtex#UMU#6|GFk1 zhck)i@onY+t`PzV->jiTV(#1Hh{@{R+cJ&6qY|t3|z~?HcDSP~LqhMHD z>2mzJ%bp9y=O)4MC1+R9HwNU~EEu+UtnVire>?_ye*LTx%tXjR=P%~wfSg+d!9bEZVAY_O)!TdEXHDP-wV(H_~Wx$Fxzl<({)=w&h3I>4^B+^q0ffI z=MKTx{ow5ZId=+%sY3;I?vFK0494d!!PxP+Ga%<~!PMeT)4$KZ&9Zvt|DE0|Hd<7&(*cp(^{`vkKScQ-!24anh$Zg=a4YXoDr z8}|p~V3@L7Ill|Yc_1L?_kuYdcWQUx^<&Yn`StvuV7BA#rt9|sIS&b@JMJ{qU2iB2 z%J~CayyK0B0&@N+n7Oz!tUrxA@x-8Q4sbJS7-cKQo3*3(?Qh0Xa_vyfkR)_hbrzkbkU`}F*5 zK+f|XIptrz6H-st2jn~-kOOZBt2Y|4-mo3?pYJk*@%cZ&Ohq&ggpKBffSeb>O^aNB z`@XpDT-^VypqveYDL@rrfZ(jttNE9cJvIWG$)wVb~MTK9bx(o=Zr*8@dXF16; zP5f})2*^RPL!8;uaop0m`K)Qdbp2g0Q&A4xe19t-=O2Puh&y1;{fB%}5|pz=F!s9f zKLT>z77RxesA5jZSBt8Ga^4Y4juoG`19ILK3_oVx6}AVS``MbHoc9F7bh-8G-GH2b z3T74VO#9fA-w7FK{!1{F=IZC40XgprW-adNxMr1Sqe1f5Q;t~DB6fX$KOpA=!SuqN zzJIx5`2|5a{}#*^+}-$m5RmhsU{cH37LfB{Kn`1;v`7x`xO%Nf8yk$z#{oGX1>}6v z207aW!&2?0>yv<-9fCQTcU)(`8SN8{&wm7C=hu#aoKFQa4|lfD@3*TtDk$eO!R*u+ z5a-i?oX-Vw3+{~b&psZ6%<<>@7lP?ymBY^ia=sMIJ-D;1?)UNRXiyGgk`@_c$@wxM z=PSXmgfKowo_!KB*&m;;1#=G_X#3(Dyrn7eRylcSW<$gKrDe!C^cQ?N>0&@5ji?qm3 zAcMZk9^C<`Uk(n*W_;l8#%KS49DKJ47}odpxH4b3G$dV}1;d?WuABn{axw)|4jDA1 zD}PrXj1La$Mp$g;T{)QnIb7LDi&Q}dEKbcYcA*pYrz=Y^JuNv01>|%U49BW8MbGu0 z5R}tRFm}7zH6Z6;!LYxe`M=&yEGVaYK+eGdIo#`xHGCz;8T{0T7<~ED#Z`;6NECNh zKZgY593~i^6UDjHAD&$QKu``>Z18*;_e>q$VF5Wu2*!<1)eSeGEAz*P=Z>j%!;Q}o z0XatrhVw7_4qq3|7ECMLT{%YubTrVZ!0pGkXeeyLx;;4xdn`MUH?BnjK$uy*MZb z-$VvxJ=|SA_YTN8!6PSpzQZ2bE9ZoOoW5<4(=Q;WZ$Qq89y#Ij9gcXt@i{RdC$|l9 z@&a;l19I{ObGT?Z*?fmBm^VK80XhBKAZI{8PXB5pN^;4eQM`FNi@ z3=GH_ESSMs&LJN^azjwg5W#E&#w|aC19DDkLwrsS#OI`doKxB$2j3U-rR$V{oWeH9 zVTI_$5%DE2HQ@OS8;ySg&Y) zVK_rIXQ|;#)SQb9r&@D{cQ#7Y*#LYpzZcKA<#O2g$PG7^hSaWg>=SI!xZ#WNX&L|Vsi<(nrIPYlALB>}a zho>+v84TazqS<9Qvoz;+!&$C5HHLGS=A3Rg&uUJk;k=_cF~j*@bIvfFBXkov$#C%D zO)+x}=Pb=R!f@tmPKn`MtvP=-oHd&Bis8JdIj8Clp4QH6pBPXkqBjy{!8Lc_f3}>O{oMkwxHD|2h ztkaxK!}+`B9B4R4?ytgn*l*Bj1O&AHle2J7kZ+lF(g z=KRBOUeKJk45xh;75bBg(^GREH=GL1dDL*O)12QM&a0a9kl|z=q$J;BIFmG|&~TbH zXQ1KyQgagHme&KEBlSf8O5Dx>nd=*#Fg+xjNyo{yKK%N{BSsXISiNh8c5ECHb+8#z~)F; z_uHHS^u@JvBPW-Ebw=HJ0aPUC=E2t8!$A>rdfFV3ycTlab$vs~py^IF(%!FWp?Ooh z1aZQfQv|_$-_pLPvhkjMq_Qhtw6}nB0%(HsG&nsxoUTXV+v$db8kft=Sc&l;2fM2D zG8wBp942+EheLJz-NT{EUiWaA)QyINAI=zrJ`7aF5TWNWtSq#)CiFaJ*x?=yOWj2t z4ol|w9u8~VxgHMVywJm8oSQuy#<|hMVVoOm&OnB>vac1xfsD^8o0G@TR{@wv1w;R} zhr`fUcsLCGLJx^jyF=e+jP%4&(fZ zhr>9(@8K}cZ+ke5^BW!x0bNb_l^Q4EvIRDYZVVr;C;V{luc{q&oG7pDw zKF`BpoLf8`#(A!X!#G!aIE?dIHfI2SI1@Y^#(9K?!#JPp;V{n3BBSR4jB_6khjBjI z!(p5c@o*UD4jvBUyyHY$GUL3(=HxM~8-`ezJjQ3W&B-O^tdlHEF5@%7!(n_zc{q$u ziHF1ZoaEs!K7DOY9unXj>)}v`hj=*DVP~7upYf?Z)rw(%#<|(%CQ3%^nWZ^;erCb?_Arhw1vWhr@I|?cp%ak9atY^8+3Z<9vsQ z!#H2>;V{m>^l%vG6&?=byv*iE9lXfHVVswEIE?dR4~KDXusICe=_F%*-48N?PL|D~ zCufw+VM3juHirpy2H70x9j1=6@-&Yztg<;WhU{{hg^}{y!NZ~GuROjO#g9E4$#)M& z^4-Is4*z6xq&z=kb7Z9V?RYCb^yIXkU~wevEjCBeKHKJq4$Ezh=y{6GVFaD1%@J)} zHPH%7Fpp|X2hJ2EtTc@gj_7&oWXo4B11q1TID(OM?XWo_rwX{6aV5sa9Ag_!K7Pm{ zoQl&=259Q=8a_oyi*OXkW!j@|zm9`gZB}5kGaYup2=6U$I(s<%vU#AtjX4(_js_FH zUIeGRhqKSo_-Q!yDLthUpGxKIJhtF~O^J1csP;vS_iUeG;;TaY+SR`ptC1LT)?a;o6@%kDmzWTsdhW4p6&L4e_ zQM+)6@%lPdeB}V+j-eC2hHGEMczul$Ul;_6S@)}_TN5#?hA$do;LD8EahjRZRvS4c`2;N-VmpUwByfGXr zzOsRZ#kudcOFmBcI*8K*7-C#)sIbO~FUF9*&fE9c;)JhU?TZ+%uhYaAM+MQ2!?l5K|+C&D^G`y$30)|ukV)yBK~ z{^Ih4uQKh67_YCh#Mk}^Cr#@j;cJfeMU2`eZeCUV-t28%YXR@Z4?f>FLEDqm-(@bx$COE4mFhbMHh+8?Wf0&&x&IORsN zjZpRjv@c@3zNUM8J&-d1PZr!%9I1T~#I)t zBF5{ByBpHX>3PHNd#fnn>u1^*Fp$|M{Id6;pN^{9gMa#_Oxz<7?4| zy5A;Zc))S0o)P2q)!^~9dQ$mS313HQU&MHQ&GYzbc>0Q$6TbRsU&MHQHF|tqa#9?_ zKezP$RQn>v>#ND*Yx00;(-XeNXkWy5eKm_OjxTAxx_%9YQ*KyiYhT28eYJSPx@+yA ze6uab=5U>HO-6Ucj5es+Llgc5MF*UW(rsk?>bW(0! z(n}%oMix6p0>0H9o7q@VTP|lVSJX8}%g6N0DT-=n`Iy~eb8Ki~`H1Kl!>5cZnlf_4 zxB;c0IngttXX1;c4J|lCwW7AxDdb+XX!MMtvNAXn^0S`iS9y8O+y-D95v^*c5Qk#h zuJ}F7e2j~& zt(jRDs~XlAi;aZV8tW=*>CVJ5A%!{SeD7%Vw4&1JlrUydaaj&j0{9tTcu~>hoM=%o zZsIy6)Ky|qSndl+dlg4~N;7JEEiNsC&|DF!&KuA3yEC53Da@r#zDbK>=5Z`4MWDHo zL<6YuAc{+I?6X2tHr6*ag*lp-&5Siq@d2PHMhq@zBy~A6+y$SW_xdR+og&JCgV&4e zurOTEqHy-&aCTv_t@t7oeo29sU0ga&B@A(yEVbC{X^JTzNcn_0u>}(r&7B)-Zmg-q z5%P^S{)nRRLCLB_;Z*vXiduh86_-va;_=m!afESwWB#z(`ikbE*k~G+B7x$P?@Ntj zo8*ixsHo9Ja)h@Q5mm)hmExhP9Ebk^M=AYDq(V1IomtFv-5C`gtm_-K$Ndn44jImb)-M3tkw1K@z@I#w>3r^is%F1_rd@Hd`Ja z$a1t>whuOdHT7t2?WPWXJp9zYpm$R)S*YAPI=;TSqM5QKwYES+Jj6>O8cScuc9WRg zSr-`9W_l!qH=BNlr{xTDG;L!rDW?6D=G^018dr7(q7an2qPm&2Y=1o{M3Ldw)Xk4I zHifvF=C^Qoz$e^tO#kGOihj#q9qbJ7R)|7VPi-0E-`6?>+`SpeT0IYCM{+*KUNz9* zc+&vys!wa0Ro~bgYicfPtYjF*t1m#SoT-@goY6e4wxTXJp`oHOmK(K8m2~Rf_(`&J zrR_m|Q7v))!hCPx_pwES9gQU3RUJX)N>s0)B;B&1ee$|_^8-btq`tOgE^CgBlfKwe z!3c>;ksstuvw*A?#1?3p5EE?xt!f*umLq8E<$2I#Ng2u(GQg+tp2MAK1R(Nx1>dLUp=&g+^P2Igo8 zwZuxb29Is5nTeTMsAyBpQem}ZKh|m<>_}^E*m*|bXmFB5#5b%^mCbI?Z0XYWg)~0i z_RQyl;U}6N+tF%zLNm*n6xt1dSA=Q+4A0j9=sA9K%mD1HnAD7=gXn}JrGx~8;{dBA z%Pm6@#N-(X!8E?Ir4}Q-$+6n{O4WWFe@VsVP=GDaBWh?(b#>9gnkILs(*}87aYaSa zG%&54nGeVGO2=+w-ROEmd0ai*#?HVOrDDw-E={Pf#mK3+zG@MwKYJ8Ua!q0_fruND z-RQ~Jbc&%Pm8ZzgQ+g8eGYZYVo7695bV! zAFkX?87bLSUYZ)fC0Rrci4T5rYoyKtU2=&TT{E|aE4lTl{77xJ`!2L>-lk5w(+#We2+$23&3KSOf;{Z$^dl)RNm znzSS>O-loI2gJsYn2<~@RI}Ryn+CinDOwLs4KgYn7IM{aiucejnr*4lNxd6Y%V?Eqy>X$f3~QqXASP9>LIFS_2_>mRx~2TsUj@$>~>9Z)#H6+U82g! z!pt7a8y;(xao(`{Mt39`T0Ah|^R6)Ihf(le(O5AzS-7k)Bg)*Bkzqi_I5-Opg4lo# zb$w4A2qv&<#=o0BF+A9ielZy^Ro{rgP`EdDK*Y{78N$7Ns3wO~nTK^=aUmn>W;g=0iT zT~%$YF(16xtXb+uPZivhf77*pwr(Anl`Fwu9#69+dBedvwmO%gNpu9(F+x4M{W-^?~lly zcr7d}FNv1t3?CXDb!t)B$dSW`N7W~_3;UN8<`?Fv4|f;lsV{dI=Be*b7Y@#gq8(9Q zi=)NEhmRgMu4shuT1l_!gWSeTxYwbj!$+2l9zAqVy^a_gEgn01%+OI|5)p1gr~^aB zYXgcUEpQ5LYP2)8R6HtrYSEbDF++>ShWBNBTwK_*s0adQ46UD7-#Cw(Pl|^|3-{Wn zELu=Lrii*9ADm7{qdKzVbEMA>4owG%&#>9Oa>)zPk8;T^iWXwGODRWp0l6BI??t$u zfL5-ElK^iyNV82*xZMTJ~PqxO0Nr6b!~G?Q>+TM#uz3=@~jCr_jlf)LBeu> z=NBl1`CTz6KR0hcwfS9{mtQq7ry}vYf@X&KT~$yCW5Uai4W>!pt9|mT@mXpZ*YtJ^9t%`0MDK^cCbNj*G`{kGz81JWu-jSM`tO%ot$8 z8>qrF>7U^XZ$@>D@u{v<$ui+qC;Tm(J2$E#nUj-@I(kEYPcDY24JeI0ofC5l3i7iP zCO3a@UQXVC{yBLG9&NcfIRgd^0L>dbs6gDNr;o;Is2AV1bNtPhN90@e+$v{(gPXtC z;X1cBZI(&z3|!(n+;nMZ#^=L-f^)cUQaJ91j5?i*HEyEoyB3yxuz%7vg0sHIO*ihY zp6ADP&WYM@su0H=ek}o9=TO}IFr2l6o$|P^ae*J_gZ~ZoIv&o~dT@`1wc z0}|~FJ^SK^mmi%wf%&V(ai4scyk3y^88CSbSO!!J*Nz2t(I9~+Js~VRqf0N=Rs7BbrXLj!lPtYF z>0mlA&ud(=^3oFyF9Y-WcOovSJl6B$zgHOd9#&p9!SQ6^vUVv{viR{ekzv5h*0^N) zV?F;FFn6$`z@(D537Bs+E}6V7kkL63akk^4Nmf4&gWCb^B2I5yG`xqUmk#;B zI*GV_6)u_nIs#X&F_cFWra#t?nZTXSiVTxXf8F7>447LqE>-*7|5?~(FIO;PjenTOq(*Y4@ z+<{8oe!zvb_mp=JFg-deTrznl!?_8V`!iF^v0ihJT4a(mR|Pf4Zw^zK7k8sUns8{nAtWc7{ZSp3>UOy(&O zrz?-{he;-{5N^YPx!A&m$>Z>5Eimf~Q_H&m^1cS<+^E7OOYaCcUjfXfqSW%Rgyf_b zN1Os&G|A*~*fIi`sU@l9jf9NLfq7lylF4KD{2?&=mZp|B2=WGN4C6-=raxxcJm7vi zEVVqYhy6oiL|77eTfrYS9P=Y85++&xa()@p7y;rI7C)B1#lW39GPOLG=W{hCl{~i3 z*8taaYHE2b&$nw#DtVkAJr3O6qf*Ob{NB)*RPwl-@&$1J9-Ug=6yOdoi#W}=Xxifn z(;v&r4Zy4&qj1UEd#3k$jiEf6FnLUGx3L)Sj!PXs$}7+q%A!doZ!~a&PTRe_*&3sy zh0A04y8yV^<5SCHe%zojspM^e;~#;$WxC;l+^M#zg(>`spM^d z<5R$`I3u;ZlYx6uV^YaudcOhg!!uLMV}EqSS!l;`(eNIoKjud@Ff*p6mdEqDuF@D- z#e~W04lyqR_wKaR@_Io+*RvzeDY$5o^&eZ{b{a6b<*DW609Ogjl^U09{=xS20bo{4 zPc82p;GWbNSjB{;_hg6}QW0_H&qytA9wgia%psKu$964D-cIn#fjPY@feRa--U8f> z!2C3p2sca~hwBZ%+)%A>p63RT;hM`~NuL>UR^p;bwtmnI=dHj@tx>pS?ekwD<5pl6 z&Q>_q^RW1Bf%84UTw1Ge$<~Kng#Y(|xqq(0B^%#!J>rPEh!d$#gd3*6I^gnwxkclW z%|Fx~3<>kZwB#nVpOqe|Ozn1`aE;9xu zS$oRzcONiEwJ2P&{&yjqhXeEE{M7QQAa4gSlNKl(?_u%d{HPq5r4$U4EPlmsdkB~> zH7;3u&>3Pf7Db%H7N?fS{-aD|7%oj%{2Yjh0T(-G_wugM7$q%S9_#P@z}Id7uZ-MD^zQQHbUn_7?V&V#yEI%kO511JmmrCAz zU+Eer%{d&`O&Y`BV%p_6_6d;W^}+QBaR1U+h8yMc zZtJ8-;<_WauYu`up$eDt*QgVGE?x=#O&UXgG||q{z;p4RgCDs_$r4Z!Txakv0dA$n zvR+F3e9!HPYXxTGZg4jMw^L(a6%!Ue%Dd{~h_f0OO|ozY!EFOD?SF3RC1k$)T~IOcx)fmvT71 zpA@IgU8MgkT*H<{oHKFJm~!RY_fP=0I$&Bsrf!RM>@0<&4;Ql;ZvU_SNY0_k9Wd7m|)fU~bm9ROz@In1{W%KsxqExa)w~sB!A~g4>QK%01KZF)-;XQm2>c zI1-pVKhBp9902MJ117FozYm)xagF!p;hHW7u8kFt*IQ!ZJY2h zv~*a}q|p;ck1QT?%-p8=l?{!}RX%pvgvmHmaj1_wcJ$COMP;QEj>%>b=dL&Gf^_Pg zNG6C=GGwaS^FLK>`JY;h*Tx%bVog(<8Y?wV$E3;kvtLzB<5Y>>)EUjAYU*NhaX3|F z$t=7lR*Bc(u_L;`Sh!wG20p9oSYfS=2_efxB6rC#dXrM8lHn!U)`MDYkcqQ zu?^idxm6g*tKg{H?WRyI%T?F z0>o|^pAs>|8=Hw8lMaXMu3G%rtbMWnaZozLx zt`jbrgYdkhAEZ&9o6pmIx}l$bxaQzGq3ycSuiK4}RoALgVTwlz6=7c+3Up@Xw@}gj zhv1Qb(>$xD2_!RPL_j;q9i&8fe)7Et5eX7-t0_Z8mKpR&#pe^IZmAELWPJk zZB3w`Tkfzr7vN$5uD)0=4#jU*UtC5w-KQ`5A%?V1+x69eijL}C%W8^u`0JWQO$u*KXhNTv;JW(M+9dEZ&8?V;z4t9uF{5Lsm(=c(#)|AcSA`@ zT{8EgD;tiT-iG5auo$yT4q?MliT<;u2_2N2U*mLz2&VjG*2H<9qP=kmiVABBmg@PRl*u8*_IEcZU#Eh$`X_Q9uF1R(JAarvu zLdX%;YMYho5zNJtDhP*R_^V9#vpulsfc;#-82(j&Md77eq7|NiH^A*0R9dK} zqOPX8zP8FEsXZjUn+WhS6JUb}_6}pjcA7()%*?nIU{kYmAXt}xl`i4nt($fjql8@t zID<3iixe!(c4ry~XFjffuZ05ndq1UDXETKH_fq}40IfWK|6Tvi)xXbDv3LFndF-7X z=Rc4b)hG&Q-C}({7WM+ozX$b~_3rne+}`^j==q>)L7xMC1oZzv9|P?IKTm*CW-BNQ z$Wx$KgRTSp1L(7$J3yZY{RVVBXa|G|8SxxYJc5b$2Ym_jr=WiVWk$aYx&rhS(AA)? zf-*l|1ML8XzYf|JbTeo+=o_H?i0)gULqPulIuvvZ=y{;;g8m)!JQ0#>30UciIHq_G%>&_743 zjD`%uo*6hE!6B5*kZO;cnkyQcG5E^N9A|j3x+nYg1!bl67(C;-k^BvBz`^UF3|fyBUml^0<;}yXUI$g{R!wk zpo2j71?2}^(VE2Pf@XkT1$qGJJ)oJOuYhKOehAtX^lMOrE%oeR&|^?f@Mt4G4D?XY z$)JaUR)Zc6It%m&&}LA?HGVBNb;_Bx73uxI2oW%H^?z4Smj=Tcx zx1jB1P91Nf&SP;;XX7yyRbz3wimp*oA{igoAX{965!GJo`}asxk{JezshVNTs%ciI zP&o&q{85=vTv-lI@t=v2d0E9wlv_3RP!4LaOg={(n^0iMM@NXE(_Hu%9jlw!JPU6> zdIk{MF)=Z+JAOV-VLfQFC0-IpGV@^LkU=GrLRaFYjWKv|-s}J!P@GLGyZ` zT(dm(1U(HDaf?p{Jr1-Ev==CQ_Md=W3VH(QuR!~P-U@mm=tj^SP`+uF2MU=^J}BqM z{Xr*y4g{SAIs}wY$I+<7Zv*`)=vvUBp#J*xB?|DjaAQ%SS$eRyU-}HZ7Q6GXj$>gX zjq`#QR5Vr<)m2TvK)RYI&ZS-`N!m-v5g7IvXy@3$hV)tgy`Xh}b~WOPH#pEurpRndY;p6dJ(GVfcLYB2EL)ZNacz8frwLu^p=8 zBu!aoBM*lpHKOrkgXIqKIV>+gTxr<*^LMTOeTM$Mj|#=%Z#7Jpc4vxJc33Xi?(~8f zcNUBBn2ZlbfpR?v{P=3nF`)N?js^WA=xLxBdpp>@8E1W;1d6eNb2=!;5od#;|Ihcz6A6l&|5&UOCbI`(4T{@1I3f)_@6+R zgKh;~0s1ZIFF?Ns{S{~z=<90GEYNE}2ZP=SIu7(EP=7m_hv$^vB5rOwc_>DD_V^ub zIo2nVkKc#lfU6(gHu6xt8MgG0=I}>{&@=ac5JnEl7v@RMzo5%8zP6P*X4^_SV9(lC zCSJ9tkn5V=w5M3k*~_zq)a~gWx$bG>%Vh+nH;M}j%FWX7I2^-Zl+w+?Jfpm-z6IxI zp$W^(%tnjko2zj67e^Q4W#_fA`R0g8R-UBUtZ%HDS>B)zIF{DB)iil>tP z{|0;(iEd6~OIAwYS4$J5b3P`1erfnE#x zN6?L+81KdZ4f-%>dxZ5UDCc&MfsO}#9F*P6lb{^4J_Wi2^l8w`K%W7<2J|`5J3yZY zeH8TnK;H-50E*`{&YwVgAukZ7tf{;LIv2lR1FZ*r9rR|<&7co}z6ts^=oZi%w6$-8 z4g`G%bQtKnpqGKZ2YNZ^KS6H>-3rQVLjMxa1^pPb2y{E>QqUcsD?$GQdNb&!psPVY z2fYIn^WFGwKzD*N-!Sfqe+P>GG~Nk|FzrAO15E=h0)@`vC7@V`ir0X41f2uAALtdJ z8KBpJ?hkqo=mDUQ{6FHp1U{gM)M|qbeT%l*!IcRlCabML#`gPRF=EnK`;H@pb}<%t#@lLm z`tCeXyZw$j&s3D*Bo4=pC@q_ZDc7^+RoCGt_zN&wm9Gymi@UI5(WH5$Jh@vA_+02s z(brD>V5y?*`u~$IjSky0jIB83zV?jr83H=TGW&GAJ!@Yu(#lcl?uE)>E_XV16U;ta zHqMc41LokBnRQH;p{tc3%#Df?hEM0tu0;Q`EGkeKT%A43M`X0yqbe%r&I@A{J3Sk! z=CD&@30(F;o8hj8i}&6Jj9WPoxT(xgP16=eMo#k+^gL@;~ z6>x8Y`vBaV;lg%0x4?ZGE}DUcjc|Vf7q*7)?hUXd&aH4^E1cWl`s-gE^6S<;K!^43 zWG7nxP)5v8CGHcRfn#FZuYWiOm**jeyb<`TQwJk4@3Z$JKNUV5Wf@M!Jso#m$943I z_H!>v>Say5lIp;10ws;kL-azP+>807F5ypX9_e>LCa1x@Gl6WVpG?$En6la5{APWH ze4X(=UN8*(@E+B1UdVx7BWp`9mQuS3A`b7>&_$}Fy9^+vI&MV5HWIwvk^`(u-tseV z{_^8}q=9+;EHz;|@yAR3wHeK+3|A@fRpun8Y%=)J)Q=Ko~4BjEOdI~#6axGYm1 zTz?&Y6!cu&OrDpYPcMSzUq8YyOo#SsaHsg>c4aYiH5tpfM)PwZ_#~|;PA+0ga3$s# z`%!Ch|>9zKrpB*U_hkL)uHH}oOk6U%o7T=Fp=F8NphmwYUQ z%d(Gv>*puN7LamO@BVWLmSKA4@iBMiobA&)hB*@S;c$m^oS(H7&^%!s6Lc?Ekoet@ zpw1nNwu@dke{Lt7b@n_9k2u@@1+rX*{!Rr9!I11{OvL?=2!FExyxiYe$h7x&AM^Wo z`1kO9k@}MVEH8OZNmUv8ncyXPa28x10Wk{h8E{9#9SwI3+(~fHhD#ZYg?l&L@o;|+ zw;1l9;G%EeFbMHaf=hl*hU=Hno$xmcw`&`YK!FG27k__=`y0?X#F z3+IA=EcaBn`EaMfWti!3C&R@IdP5o98F2l4eiC%%#w{<~Ah6o<`6=KcADj8V1AlM;Ka<9o(o? z`A>dRS0Ez$et@wEv3pm*Js*3CXdo$chxVON)81B#EE`|FGxGd}Ka9@MF0`A}7-UT-Wc|=|tvf*O> zy8-Xw&TrrjfcsmxXb+v0aQ(V?6!OKo@2&srukknSEZ!}gi9TIq82ULJ_h}v1MYM!x zV%5QI{~CZh3PU}wUWlT_Gz+;eOs9+~BNVqpF#v#xM^8v4U1JM;VqT;}`H zAAlF9cZwHd>gU(&F)uE#k#vF=PZ(aTGQ9Z1Zt&tB@X+5k_v*zNo#F*P?Ll^!clS=} zMt9R)%14$k`{s$L6Fhm!@Z@R3lV=j}WFQjo>g-e)g-lS~y7DtT_qUY{lZpFS-1!~n zNm=OvmLsm3c#`*2lUHHC_5*Bvap9XU!^c$R$>Zueq-Sa$Eb#0#eE>*4ms^B3Xv zf%`Jtp>SV;%ly9$x3l*17KHP+<=%Qy*m0h~ex6lZx)5KmiQ^0saW9WrSk4^asUdSs z6rHFWe?hrvJO2uow)33?d|>Uu0hW#7P?CZcgK zkL8OM^jGlVl{53;ukZhWT$!(JaGAF+6UaFi^!DmI`^x@45yP;)ABKB$$IFZQKBY#6 z-fF7(G3L%nn&U)d6N`<(yL#O`gdcuh(t#5pq?j=dP>1l)9wIlv{SpdRbGPkaovTo>0#alImQO)LUou(ADjPTy1R zv&cX=9k^WxX?T}|E>JTld>Q3t2`=+UzIgiy82gg_RJm|Z!E?0ZGVXOW+^g`rC)_*W zqW{!D9u(m|*y)zNAPb=3zlD=a#!VSJwxqaV^hD4zvcn+jH9I`6bOFA&d?DVcV(Iwo zBR{=zi9Cd7#=8!RdLrUo4&iijMi&*29X(?7N~UP_85j-NVh^0eZRbF}erfMeol$4?IZj3_uKlpvv86VIUz zzK~U1Fk*6CN^VwqILP1R(IZNV#}$Jp$DLC!c659s$D4F|Iz%V? z^rX?_$CZ$IlOVD{_FE7IzkW1%G*@GfsKUpyPq?##wcjEa{V_(z+8U_r%`)PCZ>>|7usU4?G299D(fppsS3ss)Ap8D#0gi>&wCz zo(yEyqAv3zjN#hKMFSQMz_RK<_BRKTHXb|Gs!D6ltgPaeX?J76fp~tRgo%C^)aeT% zoA|nL`Ou;D*rk0*2|sSfb(F((?N9Ie1$EflR8gLbPwSqJJ+OgnuCq!MU`|zaY1rpK z3;xHVlOq00##L6KwFzYN&0Hv0c{6XgggYJ6qJiwLDI7Vhs;UXsmW0va31pA6feWjv zs|*8%OW=w{Wfj=jUA>?L-cQFwMj-n}H{#i)<&c$mE^?aUKJpc_sv6tE6PEQTL^#$B zRZ>_PzPPfkqC~Q+{x!|FTrV~~<_BY4fo$%^)RLcDTUvt;c7>f>kpJM4nafgs^}7Tc z?@Fq4eLTfJ-t`fa8lzn5KC!7`{b?Y3rc0Ipo-(PrO?My179++VbH?Fg&2UU{jf9x~ z{jLwmJJns%KMb7`t9jT~I@etRQX%U8&92n_lsr!PWM7MBi{D2xTPL(ul6P3|FA-%y z9onsx0|%oW3}inGn`~>PMk59Q_0ku6?un{;9HyKdHjBy89t5(NNzIo1kemRR5{CAY z1?liv6P}0fij~iwEnlh>-DUGphc>f>A7_)ye!8nt_aEe(iU<$ucxJKGqAtuVAB%9@ z*y1TqLDgJLUxeq)AAzieE6zkkmTVlmOP&pK`Xf3n{Gd(M8h=lMG%BkkLDK|SPof|(CVsGFFJqVd>nG{{OzJ>E zm6%Jf&WYvR59yu*%_%9F-w#a(o0$LZvfQVldxToaMxd&^av^LY%_m=MXLG%HO=%c& zjz** zT2QIIw@LF;SX*6MUIRN+!R@|QTbS`vV-r?I8H5KRaKctsZzJljtVaK(9X$*I7r-3V zFQ`~lgLMQI<+ky{e&j&*mr_04(!+pI^w)P#^aG`-I|HImn6GFdY3L+7=?VOZjZoORkGr#sFjNDs&%0v)Wj1sqIupqaA(`uQcohH*~q99(|l_2`}mjeG9 zOW{0*RpF2tiSRxzq4%-u zHF}e9`oZs42}(9}C~DlO%5Yu0axlod34@H#GQLtBz zSYDcx{iJ@69?1igWcd~?=DVV}Q6em^`@E>S9Ce7M|5U_fOgK$&O9D$c5}*DRzek|} z_~LjNi8AOR%tmGP?D{!k!<|S30a1bny_?_ zeb&;o8SLz&im`O-esMLDm)iU7uByy{ei$7HWFH$V9go$eMt>LEQ;9x}woW)*qpEZ+ zkGTnCUn1To;XSH!ZiQA5X$WgD?y#`51UuEah$oQ!XP$==H^lPTHgjN| z+5{MBQ5tsYzL6xyRbacP`^H4&zZ%6)*Z@e|r!kd+SLW4@LHZ^OV$Fs&nI;I?GfzaC zpyx0<9NW;GF2!CN`|3ARHff0Vu)RbuAJ3y5uHw@8M(1Fy{HQ@hgC ze%kALZ&&{M=Sg?&JW;N=E|A%$&q~}FD~D)FsKXy38Q<`Ma7p^a?&w3ZUNNhEy?vjM zIx$u%m|HjAEI8Ums4Hwr|;A|guLCEsh&Vu`nFOA*9qWNybrna$47z={2 z2Wv#w@A%Zq7h73a;VzJvP`P1s!gyye{mYT~QHHu4t(~XC^YjjSM)Rsojo75o3u@}a z&H#iT*WvJ{NPNHiPBh2uUB&KB5OcS7SIRM9kc`WmDon6NG@W3+MRiH^1WoLM%DQSC zURP6Dc4lp*jIgM^W48iri?_d_v9Vtf^B$}nvR?52y);9<#~%M0Gh2ak#28G(qPFtF z>hepZdzc+d8#;7$*m{VwjnwlL2{5u^PAOjhyq#OhLG?1Bbx1SkM z25(RmYMe6gXf#{flKH0&lpgM*VwqW=lDrL($=ol8PukaF7Ee|RGH;)FZJZ}{7NV7= zp}1(IzOxA{+FREzBbpmx(}>!dqY>fkWENWNrn0G}3XhCtGV0yLcNtVj2j8yB&8PCK*!TW~E%#`eokIt0u4h z{DFTDcr|b#dW<85UiHqJ14>VMdFz{9iYH8a>+&tK=LG)OO>Vg8h}-+WdGuS~tejdi z?{R#3Tm1iF$=BcfDSW_#e}7`ggdvMIgs@Hv31p=_y3dWlJC2zY`Q~@e{NtY6{(%V% z?#s(csW|ig9UF4ryzJUltNXovQYtd_vd~{1FyfH6RzG>oFA95pd2qqF#j;ln{$KuE z>CTleeg4`7wO5}Pe(~h{WUVRaw{}1O-Wv}-Zu7U#KUaEnN*X58?!X*MR?5E59KFwH zA6!4+hFgDi^~%Ouu~-=MsGtwL?vvjQ`E=^3hkWwm-whaDib=*(uxKkQ<&-}qc;>)QZu$oC{6y$8djB-zn<20FJZR+BA=`#tU4eBfLO*obzwUWt`p}Gv-rs-q zE5H3{71k7>=a!YSpz6fm4?Ael&rdz^z%Ook?7!Dy4Xn_YK0o!!wvorBm3({8-qGxuU?dX*`x2hf;A69|I53N&v;|vgx}sj@$~$(%8KK09Pd7i z|Dyvk@4w}V>#EL6yYZy)w_o-I){6>#-v0CMJpSdAUtRX{kC)#0vtx&1K1}Efb~Ih^ z%+MK!fA`prKL7ghn_Doy1leb$ytHiEK0S|Xx#{Xf{a<_XqSwl>2S(`AK0IgXt+VdU zUUuq7x4m`L2bW`Sq|hI`e(*)FXZ5L{aA5!8uRbxo8uLuu7|)``zt}Nq^J_=!c(~UR zXH42ytg#mQtKXb6_qW&7UHQwuzP0b0tG9=-Hc;qoLsz%Hb^lR!9&zpqTUR}B{`{0w`zZAllhtNN`XH%d3BQpzYhX3Y``$pG5-!=;U7Ykm0 z=i!RRj~ZUgUYGuhIg_zBV_(Lz@$kn#s+|4kbssx3YTmiw(j7SNK>NI~!l?5z~~+9_vWHD`AEhPPLge;n+`-jW^2`ze|&Jlm#5tH##Zp4Lg;r_Pi(yO?N5Jy zd-!ipReyKQgP5xmdfq2jJpGd%Z9`VR8`=Ng@0Rw%zM1_P&#L9m+<)56_XbR#(&v=l z{&m^QSSu>@7oRy`TVeh4<3D)u-+%c1)Jqm(&5h6xf9l97hfZA|x%sV+pIZIa8qiPJ zpYgoB;?dt+bjrXLr`)q`(xCkPuqd@j=qJ7Q(?6ec)U3HTe;aIESGM_g*jp;}x{66{ zKh0ir+}p=~cG-V^{P*#WlaEDOSt;)xTJur;OE2D+I`XbDhi#k*TXKug#~(NAZ?_$= z{<`DOKmN^LOFy{^dsT%#{En*qE>0a?_0-3or9ZdyOq7eJIxFRX?RDRuTXn(W3rd!y zozU{d0=z{DJ^PD&wyt~g#_mfFx#pwY26BrI^e(u7r%67Ljm;sRiRH@cJwuayWBSP>&H{(e17*) zi062;Wmzd3&bal47yl7D?f2LJ`lE+u-FrONi3{BsaZqUbm@EEsTH0sd-<0!YHTFac zee$wx$8Nsw&so#|cRp2h&f_x*L0kA)6w!4^G+888x-lSk*N@cMc93uFLJUXz-~g%)qJ3=0M_w zm38%{Rk?LILbS3vw_m?Lc{3K4&8S>ZR)sS~XJ8(PQIs$2H*nCP8M84ISP?eP$^H8b z?tgM^|3P^JoaERC|M z({`a!Hi?#Fr>PdK(-AC`SN8#X&X&51Yico2Hm6VJf~wszadk4FyXP69#q2mU{5H*6 zvO1n$PzTdHpKp_uZ7(MdzYCe zTY7F+XQM9Hk0;d4D04qY0O4Qgextw=Au{(H1!Xlg9o2Ndnsu=0gemT9F{}b7X`Z7g zi`sEC{fA2eU8O~rbUgYP1u4~uc61+f$yLXr@iW`9q})uYL$H=sEk~DJtZPs-jXmk$ zVf|RYvg-NsaZufE_NuT-tG4=LnP9h>M24|K#w<6RZzgbepCL(-a3ika>`=#JkC7Ud z&*>;xJ(kmSJdRF@48zap0CSLg&*fEN+KN4qxs1Z?c~;P2y0~^hXL;6nvn4MM9qB0e zg%UL#Ud6Py)LoynSBj9p;O@4;vOKb2HdjJmesHfw$-U*}voQ?cSq4}Z&alX1s@!T> zE6cNXKkg*89x2IuPBdvVpX1}rp41S`$6_*O_p=_&ThxNfX+>(i_in^CvCc-G*bsI+ zb1~u3jn$REyBpp=RM3$cACrTN>S1MT7oe8xW)=`Z`Ndf4qrvw?f96XsV9(>hTXI$9 z>^+aC3g4Rwn^)V8@YQcgt%`Z7xut<+RfcDKJ#IHWd|_)ZHv_v9bBwx`Vl^Q<4gL3A zJQeftc0rS~=TR-%dr`&4)Dh9f@<;o_YLw7NEM+s(b8=p8&x+YKxu?OYtjXo?fw?E; zo-YK@Nzfm4`eQJjo|c>2v;P3&`DA&%+cCuioZOGOSrpApKW}apA;o^)-1N)U+(-%J zAG3bN2L2Dy9eCKA?J20@`N$%m8xQOuHV480`wdB zKS+0wRWQrAL4#aL?YUU?qJ*vf#N=vkNkMDEU{?q+X>?L&G%734n5gzvc1`=@Du|U` z)T(1T?MvL4&c(jZvDt_JNWa0!vvs=3N{zul=?hf;>IgVTg2| zA1o;7oP^&Rwy!}!o|@)7DE^8J3OZFl8kT!ciGt2U_}>M0H-2MMP`aG*PFm2p8|xp4 z(w+MZLJoksN{C*VVI@j;`0Xd6pmPn-aG^yE3OY9e4HMeW4GKE<01Xw|{RRb{09G+* zd>IA>ol!uk@Yl_`!Ju@9ryP?ObcSQS0#Uk?Z&1()1MMRrS`A8fcpfonK_?F@6L6{@ zLJTx0=$rwRFSHQ`1)Xs~1wxx>P|%qPR4BAkgTPau5kjjmDCk@U#IJOvJ3QBzDCjH& zI!$QT8WeO!Koyv)bmuICg3bk&w!qS!v$Pj1?QfR$g{2L|DhG{kut7oRJWDIFv^y>B zUQ7GEr9Eb8&sy3#OMAo8-m)~VuF!NpwY0A+?HfzW!0HM0mt|1UnT(YXY2ZOO=PIC) z!i^;c1)cYSaPA*C^pQb9ryOe@7$V)7XHd|&7f8cCU{KK60Cbl4d($Aq2Q*6KGbreM z0mRyp?tEoX(D@GNOrfPs$p8uoEz2NC8c6f<6N7@z4VHGZr7gp{h;9hm&Dm&B zy7P`fL1zqBJFu3fJL3!rI@5s032ml9L1!M&c%fAp6m%{IDi+#h1_hm~fhGuTsX;+! zIS@}hPnR_pM5x`MjTPE`1_hmmfzB4%;|2wtGOU(h?$e#Q1_hm0ENz3Ob-`)~^~cRG zM5v*bmTzfWfdY8i&FO)450fP3T!Vtn^*}gN5UJf{P|z8O^$QG(E1vLZ`c8q3GH-) z(3Sy}3$4hYpfeSyLTED#3OaLv<_PUVgM!XNp!0=xsX;-f323I!nhgp%E3vLp%gYt* zM3A(leP?NTSQVrG1{xG}W?5RfrQL_tJsq*2#sgJKYVR0?8jnLDFBIB1gM!YpKoIgY(D?(9#`m;AXeD!9e`5^_I=zm<`Kk!p&6x_swm;pOVNlSy1qi1~ zf_AGxK_~TS4S_|y1_hlGAPrk)5GAfU1Rd zt3g5MKA;6cd&r=mvjd1RqrYYl^xy4GKD|fpQQ_Hz#nC zBG@p4(7OSulQe1!LYoJKb4QWxPYgmifa-;ItwAUUP_58zH3;PZx=3gb85DGKdb{a% zHz?>7S=t0kn`dcNmNx2S`K|<4yA%oJLl?H*QdHNJQH3&UWpzac))gbgh4GKC(_tU58&T$4I7E8;w zv@p=28jC@Q#h{>bWPg2{?i^!K&>3uL!!2zI&|wnGn+Byj8x4XL9iUHP84QBu2Rd9r zykijFH4F+mV+ZQfbf?%Lw8TI?B*X@T(w#RALK>&&Q>0-~(774tM-t*=gVLSN20=!r z>eF;*szE_#8PE|DVxvLmK^cTx4brE`l|jfA(2<%egODqO!12NQ6ml~Nas$eh5UmD* z;|8H_4bi9R&RBzja!7bj3GoVOMCr~3gU}8Rb(}>)%Qgr)33Rd0at%T|2((aWeGP)v z0cm{Y2BAj_bRgaiQ4WKG&Ssz-p=~t?b{xOwI0qe+KeO`Rx0T&B;^B#ppZMj3ei>as zkDsN-hU?l&Ed8mgEi+3qqtk}6VAK8Cr@XRuMmhI_Vu@$JetCUr%4Z`+Tq!B?`QwJ4 zOo?p0;J@=oD!+sOiyOE0eBu>c&7lp=p*NdD8=FJ#G>0}dhdyo&ZEg;2Z4PY{j{}}B zZV7EKzl(u{(6}ijv*}IzitI;PSl+wd4Fv6{@C0yW!uD- z(AMIXqRkUl(f?)*6b<~b*Z(H(k9S(8e2l=G5cr)5tFjUW-stuJruWB&mMI$%_)P@f zFkw}$8yLCAdBOjEg1LwkZ7116H*Bk9E%M3C=g2Q}O^UqJxHZuD@wUdbsZ$~s zrZ!jgOpR=9+?sdpgqF)Utja(%!rp&AIIX#8XJkZHapdd_iD;v6t8L~xk+ZWVv`l$N zN+M4h*JjYygvg}8M3)d55hy{@k&n)MHp6ifhYNW&Zp|_h+}0f0-W=M|9NNjWLP)Df z(`uW!y`^aTgvgYviIGsC*hU%(OpLr*%pR;^{M6}{A#r+(w~kH0 z+XZCs)Fb##*Q!a#u`33n&BCM|Ek&Co?v|ofaUJf~KU=*tH*G*V$f}72btOSG>M1MIBAyE~{=30Mvo7?c;|6YSdL=e0 z_W`82BQn~}(sJ?DCDI~pagS)0m|2sL^_rcc9gS;dMY5W+k@e;YsgdG9^MpVoKcl%I z!&@aDc_FltvfZ+8q-bU1nv~|El^!lMH?3#B^nX@ld!$8v7v|bh3<<5wY~kz23r+kw z8l!4yA)0Uj>e7zIYpw%Da};H6bJJQz8(LY+CCzm! zj|hbUyu0!8`LH;OnJpzyxX6?h(A}7VI?bV9 zMv8u^r7qertRPT-fQRQz{OH`4EI$Rm<;g!YvqLw$5L#xEpR%m+*_7rf%iIWugqCHt ze1M0M&@yO;rqUc*5-D0D3AW8_XbUy8eewR6?{3Vz`eArP#Gywr`-U18jv#Dc0*|y5 z-GI_BX?!++VoTF3@F!{@SQzTWE|sV0O%$Z1h5u278(_?CK#rC)uF0R!vb-2^T1!^k z(vq`Mi?g;L~#Y?T7k#cLW6D6yg?$~}^qkP!)O zjvN5P0qb1YJ8CV8Hg7B#+;%HJciXa@|23hwtYsz6n&ZtHS_5Sr(%OevgpyevPG}R} zwe{$!EcKV2pXqhW9$?uc69N+v9%Kn%I!kz<;n#~ZCz78!r@3h=e8oK(l{TljWjdcs z*_`>UQ1|&rk#Q2f3w>aNO11g<@hp5RW}Mi@H7R`#)k zo9Jn}J)pLk>??;h8f%bw^%%tHK1A(s( zo-5POrMmqmOs6r~{tIo8>OsCwBhb)`DfV90s+Mt%b)LH1QMeHU`(k zw5ZTr8JhlP+pYYBJ3MDT_S3tO@1{4xJ!pSc0&CvXxVy&gg(iLo9#d!RXh}l0Ivt4G zA8Fy^=9U1h;Bw-|zoj%Qc#1^lii{VU$TG0c*%DL?=rle>s*`!uE9hRUnTobcE;lB? zI3Z3cgSBb2_}VjKTjVNzKrR1r(oCDc(D)^xlQm1lXqJ{IY?kuTEHz29)K0tHb}Ksz zU?;glh<-%DVD!CFNmF|w%jk9EDLde3&wF{>a|l41x;NsRx+Z2Dm6~No-xFPMwsClU zMttTCZcCoOeM}n2zQUnBViwsRCC!*C<$q?*kj9I~hU(>ErM!$}UbPWIL_BQGTAHrY z4Cldd1(IPkj@^|BZJUv;e!9kdc^03$n%mOCpYlt!mwBWXyWPBD z9v`9`#o%2ujJzz==EOI5TPANwL_K}Wu{JMSz(`7SmqIJ?+>BO37b&1o0&Svzo1`1yixhC3MG+QMSs>kOTRbm_WdQf!@VYU?hpsHlPU z8&@$`PVMlwz3iiR)c&EG%J4%fURhQ>i43^yamVdnON)a-i6qxG@gwA{`1>>(~I@{<1u=sYxt|RKFcKB-Hl2E z7uN6{f-#WZ1L?NNf3>Fw6Z;O)3Xg6-I-{k9KPOnV6BZ%b32lYFP;K;QYz)XCcmxxd zi;&`>T@%*}z7V~}Wc%baaVP4N32g<@q+lMFu19Ite3068O))YODMWXvg|Tuv^+j#;S`>J9EtjWe3{$$CzhF^5sRGdOq9DRN9R-6pvJhtMH!YZMz zsW>x0T-S6S{$u!yU5GzIo{it8)Q^hc4&JEhkMO9Av>5g12m}}s7dryPREMR@iIyy9 ztXr}@p_WKOtfx#?M|}Q?04DnbGyBSe%&Xr6G4rt&M$q_g4B<0VnU5`}foXapv*{TP z6Rpk%c&l?})9rljs!(M4CIrK{ViT=Ub3tlkIjs;!7n^8>Fu(}Ev^#kFQ%jPl`gccO zTAKJjN%haSkNC#Y!k@nCuNE@p^Yv&`w(Rry8aOdbrV3_dJ|=b)ubY`ooTNbB-1o}J zww9Jz$gxydWH=2?Iy!OZTVpvGX~s&iL@UXwhzN|77ucSNK|2ikLdmX(zIxe&wj76! z1tX(Bmyd2Q)RUnt$HJc*pF8rP&slVv?51IDitqwIWM z0Zl^A)-^C7O;c1iGn$w4++TKHc(S4iD!pE2@;N7m}GEp3I^q%B=bz_xU~P|%igblq<_wOMdwhv?C( zOWf&!<##-F)OM<@k?M5!CqPl-O4j$G1UCe6b`oVW3 zYD&s+e4rhP=x-6mBix7ld~HchbzP;rBVw$gM88y!sOuy{oC)S1-Px;lCLEiKwnd7z z3E$mzJGAWuDJJNRYx0dq09^|Ls3S)3;CZi?Uo5bM(3Tm`SGp8Dk4(vF{^@!UA~6$} z`Gegm0aF%=oyGJ%`M9NME84To7;5;qI5v0d7PCc7iA>psSvdBLi?$(T2m=e*1p`6# zL{pfD)G>Y6jFHVL+tywAoCJ)?P{Ug0QKGQ593x#ZvE=y5(A(#~yU#z~Znv##Xhp<~ zdEMeQf|vo0)1~-^JH>>lSbXW!NNBZ749!M{GsDo%|4P9;Gpjv3^Nm^VIDXCK$dR;9WI7whF*4p1q#Q^jVg?#8`yRm`r$;ea8$W^B)Otl_q$r>01<);0)=1Ak{38gWu{DJfDcZSiF@2>pUcMvsiY{BaY}w$E znagadd6HRjk^d}&G4lioM>tS1eauFd6Z3oVR!-^406`cGSal43C1g9wfSx$b1YWEU z29w*Qrs$Mz?LMEs4?cPo&N~OTW69!H1VkVxd0}siUZb{!_+u1WoEht(GN^f@(PZqv zYeQj{yxWs&@*pceE3|b1Jzj$gv6+RWR5>RXi#o{Aq0} z0;hf|oO&bN9Z}I};`I?)p&mZJ(lSGMnAvwk#==Z+Lq|C%hb;$c7NlhbZ<7kMc0wS?|wW?;%;HX3aIvL)0IlZ^>&BQn@-Vr`F`Gs!IGuA^0~{pu7y zWgWmL`}FeGCw}=n)zBM&-M$?M_oE*}kF9m6Z{GGUL}M2Upp5z5;~PKdcXIzdI_W<* zssD4L^&S;ojq6VDd@t-=YP9ObG~mo%lJGsPwbVE6E?ZE+uxx6ltLv~DY%o&ViN2lk z_fA@#nBuhM)1%FEa(-esI27>I8rY<^X}w}fj=o7;__q9>?ZzL;=aMRK`dH5vXK%@s zFWU0$jM$}zGx;yt3Ub^zvP<_xAX@b;-HdTw3QOXNnFc(8zAP;YELp_Za09FfYBdsdVg$aDcXqY`X)N-8`#BCQ*t(XSer1a zfi;lmi%r?g@eHhl#9+pV_yu!jBJa6~jL)#TZSvH$1=vZbd;iiLET44_Mnz3?&II}m zhKSRgDHfe?(R`r8#NVYBT?52nz%=Jppa&)Foj~`2 zv;MYQe^?}HLL365Y4iZnGD&^o>=9478Z6ix-w5L1CP#FaoFh`$#5^kMt-4?wTU(@j7x3i{fjJgB$EQVjH- zJiQQzU4k5E5zy;`mH>@Je$t$u1E~(Z2=s96+!!S)7_S7P7p|?-yNv8$hS8TcV(tIgMqjk z6nX%ZFQ^!ZJ3rH$89?0cndZy`;x5lLXBE&$K_3FCZtMhFBk6VvxaeRYl}vw&&Id|C z*c|5)AmzbzK#xk;KLEWT=y{7i08%OZ8%V?E?CXX-2}r~8JZ$B`*%nO%>MPux4y0l0 zfgYDMB0$GVUVaY5mGwE!9YCt5k67B1mi7*iYG*f0L4Pf=}NOkRFi&D_}Q;T^tkm^-GAl0kEK&n?~TiQfRy97ve{C5_;0HnJ16_D!MPD|^V z?P}c^APqYoNcHb$K$@3d0;%-*NsDgaT8{G<`*bsqmhw9w)s5f*u5NH=s+OGJhgI$5 z*HaZ;V-Y{m%AKES&M$yezK;N@#;ynA4pB%Di2G3?L7;O5Z3W^k)HG)Y5ci&@IjPv- zFShO67duY+_ z1F7CW45WI$7U+C=x&es0g43LLfVdYp&Dji8Drh?pcL1Z|?xFjB)0_;Ta-nqxsu0u@ zh&y}JoU4Jj`!&tE7f5TxQ$Ra~Yp(*`BTqL1sU82wqAx7kX;JV;`1*l_?E$1A1^}HP zwI?4)d0J%Abc+@OJtAT6u(Y)ny=~EF7X1ron8e%-dwdH79Rf61Pyx{Cf<^<~Eiq39 z;@-L(rvymzaubkRy~lv6q`WTyDK|a@QXc#Z=v|2=?MQqBK+xep8kW0_i@F`<(sC?1%A(VNln0|M?K~jui-v(TwabA1n8I>g1El@pJMGi^fwV9ByrsQj zX&+hIc8hu+?Ur{qklMeIKx#{hfz&dT0BN7F5{P?f)0_oBs=sm3k?s+OnR)66}& zu+%{N0OdHD$GH8@gMqZ~T?(XSy9-Ep|B0oY+tYFGOkvn+i&`vt6iD;j3Zy;S7lEFW z5Pt^Zn@o=L4G_-;$Z;+>)~%P911aq~pnc`(?Lb=I-vDWOp8(=s+cf7XAT969Kw92+ zfVevswGoJWeAArmK-}4j+IXDq=S_272hvi$V^Q|;E^U}a&jH;fxqr*jUhm~Nd`ru5 z+JLkrejiBN+P?#-u6=7!w-a1iE|BWgSwP$!i8FJ6v>da5xQjB)sRH62%QWW>ylFa( zo4&t`?sJjJJp(P6uNbp&fUdB4g5=NnPnXXLbbT%5MhD|DGG<4If~4*$2q!{Kf}979 zO^~zL?Ief^F7@xuF~x))vo$V{cfi(r3^LgWHnDU5^`IC(%h`1H7I z_(uY%;*7Is63|r=Vk(e^Cu|-z{T`eIZKpNskAPqqQDtZ)1Q+vjuwLnWG z?2AAe_H`gNYwrW8soMsmVZR1iDj~iF(hyz11PyT@koxNmv`qZ{2uS_K4Rmp=DHYK$ zQdCNNp<5#RZCwICW{obj(7uHGIPNQ*v(UqgUJOG&Bvzy6r&mhCZ;r)(T}(f;$Kb=`o;1no;Uc!!Y~xeQMe~05X*QuI$gfumW0!%d!*6<-yIan z$>@wmh2n@DH6YcZy5 zd!eux`AjzJ@7-k_V1woilp0R`(Wbf|(5EPQj#B`1i#%Nlq+P(}7CjB54IuUDYuql6 z0iE@@vv3Fa0~ht|WG7WpWc7a*_Y7wrxB8cqRLnD^&Ely z60=LoF3k6Tusc70LP03Mpzxg8Ve=ir{QSK9>CS9#?DY%qq2+QO6^{=s?WGiYQrB3P z&v4iH>I}<&GVWjFe$OqX15-A_{cMu^QSsy-3Adj_O~ePOBjm7qQ3`tH!EoWgpzN(M zT-0?Mv2DOV#%q_0 z0n)J78Wfb*TJ^WX`s+YrPd0sq067k=wl;KB{wt7;GzVS(WDVU5cmxw1yV4=`4~U9( zc@8RO0iGadYfO zuS5!#pc3(`pYc_zgJ$;vSB(-X1oP!ri1VQcr-5E#6oTeOjV+NHTcV(|5x$i6jzPir zxiuq+D35O!9+QK9Geo|($Jw9Y`4}H(8HSvtR`B#Sz1Rzh{f@1)X|bdZa**e2MH?tgy*VHO*LiJh}zX%Y8gz81m?7+&}X2 zXoUOG94MIiKF(ix0W`{Rk0&?}f3 zU5{DPwG(kx%4Vd6Ezokj#cB|r08yt+vHHRG4y}#CI)~;7v)Es3t-*9{k}d?-fMt!q z!jJ4L8xTFbN4H1z2SMLL&#-8$Mbj*rV^N(&%Yg0!S21&9(E~s<*E!C^q$RDfJMpv_ zH){p2UZ{qBpr6!GHnzO4@M$B%^uhfV?&H1M82#L`wzA`@!$tUDdA#YPYIfMO=qdB) zUeVf<+t3wnFWK_W@HzDKV6EqwAO+yN4$X0nGrs~&a<*+{bDa7bG`rc^S@4mM8$K!* zOscA`sTf%uM$3vf4lNt&v3s%1HQ*xtkRQE9L(BgGIL2uEv3RK3PNdpSgmWVy38f7- z$Zu)pG0F?NUV!C6JBvm8{KF3J)QYd(aB06#VAtl8vr zg}qL=#aleQzNu>{ASt~5L07E!On7Pv_1U}R1Pd235jlINX~Kk?M8O^eExEaS6i+EI zS7`n>pe8&!-KSs-Lvwcz?xEhsw#fZD2NlTv=%69vM^&X6$TI!0VIWk8@ttz7(DRX| zdodsDk#TgmoPmZ|3t{I1hvBk<*27%{cOl$6;a&`vmFY?FMwNj`m4PTIeRZY1V*Kq| z8T_JnE|DNkKy=9k(GO2uAppuN0+~$Om$+$9{DNQ@`Z)&oAaF}Bw9S_Hdn5?kqseun zhRZa`bnpsQQ?EgWsqFqKQ;C$RL_y~fcvRXG2KkxFBcZJAE(+jn4!y_5XY&%*C_lrY z`|R6OZaGc}C^@6Y<0+ZyGP@%h&oE>(jsFZUqvdFoIn}lE$!PndgBst0m|`^k|3HY- zc(0jbK2{>*uv*s46@vN0@q2_3!n0NgL@ER#)oi6vvz3-~h{e86`>c$NvQU&c4!RNM zJ@`bR2e#eL#oX%wzOBm z6u!nycDdJF0Mcphc=;9mm!J*xnRbRD+e>l3$EHdySQImuKs7h8gGzn{Vi6_Z&zSWF z5K0y~{K=fj&r9Sd)03ZmMaOvOl~VkFWYuhKRdfAJPdUSkun`XB@$-M##*uEqmDs~Lt_r*gl$ zcUf(<+iN?R9@*!$9c&Gmhf586*mqF&5Gi|zaPTpFDUGIFX|Y-kE!~VqPE4Ofti>k8 zkR$dgxs9OWw#UK8@O-gPSs8}8r{$k`0RG9vS5y5cPzT0VhYr1>Gu}I>^S+^2DsrC5 z9UbP|KN5SDkpvZ)<)I=|VL4l&5+PEF5a~#)(smkuaSEGMBA@LAiQJ1+FKS03TfA1g zQ{#MBv@_t@K?&HwJ$+vwC;wqNNu-=4isM>n=L_(T7r>Y?D=Meo!g5T3bocUC`Id&l_OC0mmZQ|*ea4M^hbcG!A&j4g;AlhO(wOY0!}V#cWwu`d8!@LJcNsKaF6 zv8FEn%d(G1*+&#~TH#A+YYj@yzJ!&UW2-v4MdmT8946aNr;Nk#?dk5%@w~#vWQL*c za$NWbFO%CF#}baW=b?k__YHJW0J*r`i+S^pb7AaK^!7XOL-m$O8Be6GzS1@!ywW<_ ztkHPvX|u-0^d~+pLv3uccA}Td9UhVqmUq~92l>wd96L-)Yrsi(6I`6RKG1YN z>+!s#gfDERRp@zX7qlztLCLuoXsD2WXZ+Nun^)$6(&04>y2an%u6dWgQD73t}?^Ppw%xT zJn+>tyPsB3Q|@AVJefjo}WB^k#v zFKIed>+d++f^1V{Ua`@z@;56%Bktiou`vw&T#uVWV|v97_P8=St%G%XS7UB8vZLIj z;4%*!{Gr0TuV9x!T+G*x;SPm+IovsLQIQ+2gNsR}2Ijc|e>5AbA!{`oL@HLIptIII zO_wn^rTL8U-WVie#CtkOlt@6{L86&n0oie(XeH{XfOa)RL;>aFb}x5;Xde*x9?a`Z zFrETB3ofP)D9{E9kK^MU&~nGexvEeFL!^QsQo$%~J^U+;g7NHWY`i?+T>hiT_Iba9 zk9oMA|MG-j7i zjv?7+>reTuuSGINlyAs%SO&hCdevv8<20~b5Ntz#xDZ>z47d-&Wm(aMk$TN7U#dPt zsy;+PrwzW8_O3xeSz@WQzgt==d@C(rkec-$PR#;qHl;!>yB1{ZhMMU* zUw6V~>--d0qiiNpHWO+0RcULDKewZgd7CU87U20#NXR{eV&-!&K4vEivyt579)qX6 zmE+ggcV`U_fGLlG#Qk4eNDgK0!jazX%>2_{UkKOn#Qw5wC zK!b?I30bKrIGUmhRw;ybMrRS?p6!TEI>bH0=S6m6HN_4roY;=@AIw28p#YAx^BiEn z7qR=0;T(snu#*dpeLEJ|D>x29K;fjVOe8plp`Rw)_CyH3;M@q|$8)g`xPntrxq?$M z+OcnM4PbhH!3}_*n1|tTnGbBK5y3rS1xKWUBT~UBje=7e3`jD;@!K~SbaB6aV-9#} zn~7s~vL;-B1Ml>!IF`PHAI9NXJU)8Iq;)KE#M+tT^alF1pwldEq@_)2uBpP@*Qb1;ep!r4XwanjlM6?pK{G(|1_pIbPI9W5A$QmCD z(J^m0=s~P;A0x`gttg39ltlRSCwwdIK7-t5w9|ETYDem*@zj1DHJ*}5`TtWL{ZG6g zPx@cg(J#Ab9sL&W3J7W^T$+YQtzd~%utZu%mBu=%wAg-nv~R-&6}C_0A;aXRrbMeK z+FbF*Q@y-oddsp_8^LhG7T% zD%>ALmPDBR(&Ihsi_CYi}(EGFMao-43sTzUjE^rMDk^rOx$?U za^7!Oz9+@Y*G&jb8jPwt))OaRPd_M5zD(aQ-+Mq}p0FfTM*bdxTaDkphWksnzlF>E zu7peZa@W7gmq_JHr1Di7<*PK-QO{6~E5C&DMX$(x-XZzU=#+eC{Ey|ksa^S={6CW~ z7RiWwSHtDV?o)6n->2bHzO8U6-!*V4U!L2b@+DIF5~+NZM)@jD`bmjSWn-n?2i|y8 zIqvKb4(i-t55n}HNO=T2>gJyTKr|9LoIGo%i^?H3nlran(7bZYg1^7Sov8XT4E+qk z{b9S}>8s*l0`XV7)z5EU^E~01KC7R%ySfo1=IIl-%-3gdDTasOPsKo_Vjxm6D2-xJ zT5MD34yvQ+YTT3(#zx4U?$=y!5N6y0aSj;%15xM5;Q1|rD2C+k2NVq%?PWgO2$%V^ zGyY{j3`0Nc#(oxk>FeZnzgczoC`xHmDxnfY$9!+Jf|YseIy-bEEmA+J;t)4Uf}CAcp3X?yNpe^cxW$hG-eHvL+$;W zWhjv{lxQz7^j~|Gq3rSa=fb@VUUa8A-Gk7^$ar90O_XjfUrL#8cgleLNvC zBX_y=Z7*;&ZmCo+%Tyv|Dv>bt91IjUZpInmS&I(ik?n#1PRVh<>|GS-iq9_;1-AV4 zd^0pZ^Vuw!@6Z;TEo}0(o9}SE-2TsX=s58W)@{2V$FmVW7BUQ}&q{xjt@K37R-&NuzImE1Gl5D=wtuxZk3hft%~k0L%)oiob%A%%kC%*W2oz-PdD(stvs z+&tLWnwNOr-ERiP(jNDq-YaW6MV ze5a0XOJxtyY)d`VY)h>NDaV`yVd6T{3~RE7pW`f$<%6Ra$UzX3YD&v0L`BD%l(^o) z&O+6=$-`wixx|`^R&MCmq&N*MJ2b0dCfo?zO1R75vOcuH{W0ACgL@m?>)@_{dp+C_ z;Vy^EbrUzjCI6u6@=oyuu$plqtr|o@Clmjb#D_hZo^52aANj8AB&?vIY1SP75!|=2iF}X_b-#0!0&;8vwhUtSabbIY) z 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

    _UonF(aqMN%m)n?#PKN+M;##I%NQ}I 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

    w(Qc`B5 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

    uxgzpQkD^gy|uWg8uB!i2A!pP5%U@mTZ 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 Date: Mon, 10 Feb 2014 13:25:28 +0100 Subject: [PATCH 22/35] Updates for objects --- Code/Game/DanBiasGame/GameClientState/GameState.cpp | 2 +- Code/Game/GameLogic/Game.cpp | 5 ++++- Code/Game/GameLogic/Level.cpp | 4 +++- Code/Game/GameLogic/Level.h | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 335162ad..254c3b59 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -483,7 +483,7 @@ void GameState::Protocol( ObjPos* pos ) if(privData->object[i]->GetId() == pos->object_ID) { privData->object[i]->setPos(world); - Oyster::Math::Float3 position = Oyster::Math::Float3(0, 605, 15); + Oyster::Math::Float3 position = Oyster::Math::Float3(0, 605, -15); if(pos->object_ID == myId) // playerobj { //printf("Move message recieved!"); diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index 29287f76..b76970b2 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -105,7 +105,10 @@ bool Game::NewFrame() if(this->players[i]->player) this->players[i]->player->EndFrame(); gameInstance.onMoveFnc(this->players[i]); } - + for (unsigned int i = 0; i < this->level->level->dynamicObjects.Size(); i++) + { + gameInstance.onMoveFnc(this->level->level->dynamicObjects[i]); + } return true; diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index e15d9efa..364972df 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -13,6 +13,8 @@ Level::Level(void) } Level::~Level(void) { + delete this->levelObj; + this->levelObj = NULL; } void Level::InitiateLevel(std::string levelPath) @@ -70,7 +72,7 @@ void Level::InitiateLevel(float radius) int offset = 0; for(int i =0; i< nrOfBoxex; i ++) { - rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, -10), 5); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); this->dynamicObjects[i]->objectID = idCount++; diff --git a/Code/Game/GameLogic/Level.h b/Code/Game/GameLogic/Level.h index cc34408b..5219e52a 100644 --- a/Code/Game/GameLogic/Level.h +++ b/Code/Game/GameLogic/Level.h @@ -65,7 +65,7 @@ namespace GameLogic static void PhysicsOnMoveLevel(const Oyster::Physics::ICustomBody *object); - private: + //private: TeamManager teamManager; Utility::DynamicMemory::DynamicArray> staticObjects; Utility::DynamicMemory::DynamicArray> dynamicObjects; From 05aa3cc9e91795e24f7f99e89c668dd5dd539436 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 13:55:01 +0100 Subject: [PATCH 23/35] Added on move functionality --- Code/Game/GameLogic/Game.cpp | 2 +- .../Implementation/PhysicsAPI_Impl.cpp | 10 ++- .../Implementation/SimpleRigidBody.cpp | 36 ++++++++--- .../Implementation/SimpleRigidBody.h | 64 +++++++++++-------- Code/GamePhysics/PhysicsAPI.h | 2 + 5 files changed, 72 insertions(+), 42 deletions(-) diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index b76970b2..ceb45520 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -71,7 +71,7 @@ Game::PlayerData* Game::CreatePlayer() int i = InsertObject(this->players, (PlayerData*)0); this->players[i] = new PlayerData(); - //this->players[i]->player->GetRigidBody()->SetSubscription(Game::PhysicsOnMove); + this->players[i]->player->GetRigidBody()->SetSubscription(Game::PhysicsOnMove); return this->players[i]; } diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index a71c58e3..4c3a25a0 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -102,7 +102,7 @@ ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 r void API_Impl::UpdateWorld() { - this->dynamicsWorld->stepSimulation(1.0f/120.0f, 1.0f, 1.0f/120.0f); + this->dynamicsWorld->stepSimulation(1.0f/60.0f, 1.0f, 1.0f/60.0f); ICustomBody::State state; @@ -115,6 +115,10 @@ void API_Impl::UpdateWorld() state.centerPos = Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z()); state.quaternion = Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w()); + if(dynamic_cast(this->customBodies[i])->GetRigidBody()->getActivationState() == ACTIVE_TAG) + { + dynamic_cast(this->customBodies[i])->CallSubscription_Move(); + } this->customBodies[i]->SetState(state); } @@ -129,8 +133,8 @@ void API_Impl::UpdateWorld() ICustomBody* bodyA = (ICustomBody*)obA->getUserPointer(); ICustomBody* bodyB = (ICustomBody*)obB->getUserPointer(); - //dynamic_cast(bodyA)->CallSubsciptMessage(bodyA, bodyB, 0.0f); - //dynamic_cast(bodyB)->CallSubsciptMessage(bodyB, bodyA, 0.0f); + dynamic_cast(bodyA)->CallSubscription_AfterCollisionResponse(bodyA, bodyB, 0.0f); + dynamic_cast(bodyB)->CallSubscription_AfterCollisionResponse(bodyB, bodyA, 0.0f); int numContacts = contactManifold->getNumContacts(); for (int j=0;jstate.restitutionCoeff = 0.0f; this->state.reach = Float3(0.0f, 0.0f, 0.0f); - this->customTag = nullptr; -} - -SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc ) -{ - this->collisionShape = NULL; - this->motionState = NULL; - this->rigidBody = NULL; + this->afterCollision = NULL; + this->onMovement = NULL; this->customTag = nullptr; } @@ -65,9 +59,26 @@ void SimpleRigidBody::SetSubscription(EventAction_AfterCollisionResponse functio this->afterCollision = function; } -void SimpleRigidBody::CallSubsciptMessage(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) +void SimpleRigidBody::SetSubscription(EventAction_Move function) { - this->afterCollision(bodyA, bodyB, kineticEnergyLoss); + this->onMovement = function; +} + +void SimpleRigidBody::CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) +{ + if(this->onMovement) + this->afterCollision(bodyA, bodyB, kineticEnergyLoss); +} + +void SimpleRigidBody::CallSubscription_Move() +{ + if(this->onMovement) + this->onMovement(this); +} + +btCollisionShape* SimpleRigidBody::GetCollisionShape() const +{ + return this->collisionShape; } btDefaultMotionState* SimpleRigidBody::GetMotionState() const @@ -75,6 +86,11 @@ btDefaultMotionState* SimpleRigidBody::GetMotionState() const return this->motionState; } +btRigidBody* SimpleRigidBody::GetRigidBody() const +{ + return this->rigidBody; +} + SimpleRigidBody::State SimpleRigidBody::GetState() const { return this->state; diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 1b699e9a..d3655048 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -4,42 +4,50 @@ #include "..\PhysicsAPI.h" #include -namespace Oyster { namespace Physics -{ - class SimpleRigidBody : public ICustomBody +namespace Oyster +{ + namespace Physics { - public: - SimpleRigidBody(); - SimpleRigidBody( const API::SimpleBodyDescription &desc ); - virtual ~SimpleRigidBody(); + class SimpleRigidBody : public ICustomBody + { + public: + SimpleRigidBody(); + virtual ~SimpleRigidBody(); - void SetCollisionShape(btCollisionShape* shape); - void SetMotionState(btDefaultMotionState* motionState); - void SetRigidBody(btRigidBody* rigidBody); - - void SetSubscription(EventAction_AfterCollisionResponse function); - void CallSubsciptMessage(ICustomBody* bodyA, ICustomBody* bodyB, Math::Float kineticEnergyLoss); + void SetCollisionShape(btCollisionShape* shape); + void SetMotionState(btDefaultMotionState* motionState); + void SetRigidBody(btRigidBody* rigidBody); + + void SetSubscription(EventAction_AfterCollisionResponse function); + void SetSubscription(EventAction_Move function); - State GetState() const; - State & GetState( State &targetMem ) const; - void SetState( const State &state ); + void CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Math::Float kineticEnergyLoss); + void CallSubscription_Move(); - btDefaultMotionState* GetMotionState() const; + State GetState() const; + State & GetState( State &targetMem ) const; + void SetState( const State &state ); - void SetCustomTag( void *ref ); - void* GetCustomTag() const; + btCollisionShape* GetCollisionShape() const; + btDefaultMotionState* GetMotionState() const; + btRigidBody* GetRigidBody() const; - private: - btCollisionShape* collisionShape; - btDefaultMotionState* motionState; - btRigidBody* rigidBody; + void SetCustomTag( void *ref ); + void* GetCustomTag() const; - Struct::CustomBodyState state; + private: + btCollisionShape* collisionShape; + btDefaultMotionState* motionState; + btRigidBody* rigidBody; - EventAction_AfterCollisionResponse afterCollision; + Struct::CustomBodyState state; - void *customTag; - }; -} } + EventAction_AfterCollisionResponse afterCollision; + EventAction_Move onMovement; + + void *customTag; + }; + } +} #endif \ No newline at end of file diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 9af0e256..c8bfde34 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -142,6 +142,8 @@ namespace Oyster virtual void SetState( const State &state ) = 0; virtual void SetSubscription(EventAction_AfterCollisionResponse function) = 0; + virtual void SetSubscription(EventAction_Move function) = 0; + /******************************************************** * @return the void pointer set by SetCustomTag. From c87bab8808948d4b616189224b533a58095dca88 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Mon, 10 Feb 2014 14:00:14 +0100 Subject: [PATCH 24/35] GL - started using the lvl format. Objects on client have pos, rot and scale (not verified) --- Code/Code.rar | Bin 0 -> 81567 bytes Code/Game/DanBiasGame/DanBiasGame.vcxproj | 9 + .../DanBiasGame/GameClientState/C_Object.cpp | 67 ++++++ .../DanBiasGame/GameClientState/C_Object.h | 27 ++- .../GameClientState/C_obj/C_DynamicObj.cpp | 7 +- .../GameClientState/C_obj/C_DynamicObj.h | 1 - .../GameClientState/C_obj/C_Player.cpp | 9 +- .../GameClientState/C_obj/C_Player.h | 9 +- .../GameClientState/C_obj/C_StaticObj.cpp | 12 +- .../GameClientState/C_obj/C_StaticObj.h | 1 - .../GameClientState/C_obj/C_UIobject.cpp | 3 +- .../DanBiasGame/GameClientState/GameState.cpp | 227 ++++++++++++------ .../DanBiasGame/GameClientState/GameState.h | 10 +- .../GameClientState/LanMenuState.cpp | 7 +- .../LevelLoader/LevelLoader.cpp | 35 +++ .../GameClientState/LevelLoader/LevelLoader.h | 42 ++++ .../LevelLoader/LevelParser.cpp | 190 +++++++++++++++ .../GameClientState/LevelLoader/LevelParser.h | 31 +++ .../GameClientState/LevelLoader/Loader.cpp | 22 ++ .../GameClientState/LevelLoader/Loader.h | 28 +++ .../LevelLoader/ObjectDefines.h | 172 +++++++++++++ .../LevelLoader/ParseFunctions.cpp | 111 +++++++++ .../LevelLoader/ParseFunctions.h | 28 +++ .../GameClientState/LobbyState.cpp | 9 +- .../GameClientState/LoginState.cpp | 22 +- Code/Game/GameLogic/Game.cpp | 3 +- Code/Game/GameLogic/GameLogic.vcxproj | 4 +- Code/Game/GameLogic/GameMode.cpp | 15 -- Code/Game/GameLogic/GameModeType.cpp | 15 ++ .../GameLogic/{GameMode.h => GameModeType.h} | 10 +- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 173 +++++++++++++ Code/Game/GameLogic/Level.h | 9 +- Code/Game/GameLogic/Object.cpp | 4 +- Code/Game/GameLogic/Object.h | 1 + Code/OysterPhysics3D/RigidBody.cpp | 4 +- 36 files changed, 1160 insertions(+), 159 deletions(-) create mode 100644 Code/Code.rar create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp create mode 100644 Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h delete mode 100644 Code/Game/GameLogic/GameMode.cpp create mode 100644 Code/Game/GameLogic/GameModeType.cpp rename Code/Game/GameLogic/{GameMode.h => GameModeType.h} (63%) diff --git a/Code/Code.rar b/Code/Code.rar new file mode 100644 index 0000000000000000000000000000000000000000..e048199d0ab00c9b70f45a73f0ffee88a754c309 GIT binary patch literal 81567 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 I4-W8u0Z~xL#sB~S literal 0 HcmV?d00001 diff --git a/Code/Game/DanBiasGame/DanBiasGame.vcxproj b/Code/Game/DanBiasGame/DanBiasGame.vcxproj index 01a92481..83806118 100644 --- a/Code/Game/DanBiasGame/DanBiasGame.vcxproj +++ b/Code/Game/DanBiasGame/DanBiasGame.vcxproj @@ -205,6 +205,10 @@ + + + + @@ -219,6 +223,11 @@ + + + + + diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp index 840e6267..11d4dd7d 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp @@ -1,4 +1,71 @@ #include "C_Object.h" using namespace DanBias::Client; +void C_Object::Init(ModelInitData modelInit) +{ + position = modelInit.position; + rotation = modelInit.rotation; + scale = modelInit.scale; + updateWorld(); +} +void C_Object::updateWorld() +{ + Oyster::Math3D::Float4x4 translation = Oyster::Math3D::TranslationMatrix(this->position); + Oyster::Math3D::Float4x4 rot = Oyster::Math3D::RotationMatrix(this->rotation); + //Oyster::Math3D::Float4x4 scale = Oyster::Math3D::; + Oyster::Math3D::Float4x4 scale = Oyster::Math3D::Matrix::identity; + scale.v[0].x = this->scale[0]; + scale.v[1].y = this->scale[1]; + scale.v[2].z = this->scale[2]; + world = translation * rot * scale; +} +void C_Object::setWorld(Oyster::Math::Float4x4 world) +{ +} +Oyster::Math::Float4x4 C_Object::getWorld() const +{ + return world; +} +void C_Object::setPos(Oyster::Math::Float3 newPos) +{ + this->position = newPos; + updateWorld(); +} +void C_Object::addPos(Oyster::Math::Float3 deltaPos) +{ + this->position += deltaPos; + updateWorld(); +} +Oyster::Math::Float3 C_Object::getPos() const +{ + return this->position; +} +void C_Object::setRot(Oyster::Math::Quaternion newRot) +{ + this->rotation = newRot; + updateWorld(); +} +void C_Object::addRot(Oyster::Math::Quaternion deltaRot) +{ + this->rotation += deltaRot; + updateWorld(); +} +Oyster::Math::Quaternion C_Object::getRotation() const +{ + return this->rotation; +} +void C_Object::setScale(Oyster::Math::Float3 newScale) +{ + this->scale = newScale; + updateWorld(); +} +void C_Object::addScale(Oyster::Math::Float3 deltaScale) +{ + this->scale += deltaScale; + updateWorld(); +} +Oyster::Math::Float3 C_Object::getScale() const +{ + return this->scale; +} diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.h b/Code/Game/DanBiasGame/GameClientState/C_Object.h index 1b87174b..4782270c 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_Object.h +++ b/Code/Game/DanBiasGame/GameClientState/C_Object.h @@ -10,21 +10,38 @@ namespace DanBias { int id; std::wstring modelPath; - Oyster::Math::Float4x4 world; + Oyster::Math::Float3 position; + Oyster::Math::Quaternion rotation; + Oyster::Math::Float3 scale; bool visible; }; class C_Object { private: - + Oyster::Math::Float4x4 world; + Oyster::Math::Float3 position; + Oyster::Math::Quaternion rotation; + Oyster::Math::Float3 scale; + void updateWorld(); public: - virtual void Init(ModelInitData modelInit) = 0; - virtual void setPos(Oyster::Math::Float4x4 world) = 0; + virtual void Init(ModelInitData modelInit); + + void setWorld(Oyster::Math::Float4x4 world); + Oyster::Math::Float4x4 getWorld() const; + void setPos(Oyster::Math::Float3 newPos); + Oyster::Math::Float3 getPos() const; + void addPos(Oyster::Math::Float3 deltaPos); + void setRot(Oyster::Math::Quaternion newRot); + Oyster::Math::Quaternion getRotation() const; + void addRot(Oyster::Math::Quaternion deltaRot); + void setScale(Oyster::Math::Float3 newScale); + void addScale(Oyster::Math::Float3 deltaScale); + Oyster::Math::Float3 getScale() const; virtual void Render() = 0; virtual void Release() = 0; - virtual int GetId() = 0; + int GetId(); };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp index 3df74e40..71c46f4a 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp @@ -21,17 +21,14 @@ C_DynamicObj::~C_DynamicObj(void) } void C_DynamicObj::Init(ModelInitData modelInit) { + C_Object::Init(modelInit); // load models privData = new myData(); privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->WorldMatrix = modelInit.world; privData->model->Visible = modelInit.visible; + privData->model->WorldMatrix = getWorld(); privData->ID = modelInit.id; } -void C_DynamicObj::setPos(Oyster::Math::Float4x4 world) -{ - privData->model->WorldMatrix = world; -} void C_DynamicObj::Render() { diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h index ee25a992..d8e7023a 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h @@ -14,7 +14,6 @@ public: C_DynamicObj(void); virtual ~C_DynamicObj(void); void Init(ModelInitData modelInit); - void setPos(Oyster::Math::Float4x4 world); void Render(); void Release(); diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp index 49c450b5..5e5525e9 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp @@ -13,6 +13,7 @@ struct C_Player::myData }privData; C_Player::C_Player(void) + :C_DynamicObj() { } @@ -24,18 +25,16 @@ C_Player::~C_Player(void) void C_Player::Init(ModelInitData modelInit) { + C_Object::Init(modelInit); // load models privData = new myData(); privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->WorldMatrix = modelInit.world; privData->model->Visible = modelInit.visible; + privData->model->WorldMatrix = getWorld(); privData->ID = modelInit.id; privData->lookDir = Oyster::Math3D::Float4 (0,0,1,0); } -void C_Player::setPos(Oyster::Math::Float4x4 world) -{ - privData->model->WorldMatrix = world; -} + void C_Player::Render() { diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h index 794bf51a..556fd6dc 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h @@ -1,21 +1,20 @@ #ifndef DANBIAS_CLIENT_CPLAYER_H #define DANBIAS_CLIENT_CPLAYER_H -#include "../C_Object.h" +#include "C_DynamicObj.h" namespace DanBias { namespace Client { -class C_Player : public C_Object +class C_Player : public C_DynamicObj { private: struct myData; myData* privData; - //Oyster::Graphics:: LIght + public: C_Player(void); - ~C_Player(void); + virtual ~C_Player(void); void Init(ModelInitData modelInit); - void setPos(Oyster::Math::Float4x4 world); void Render(); void Release(); diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp index 177b032b..6e7a20e9 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp @@ -8,9 +8,7 @@ struct C_StaticObj::myData myData(){} Oyster::Graphics::Model::Model *model; int ID; - // light - // sound - // effect + }privData; C_StaticObj::C_StaticObj(void) { @@ -23,18 +21,16 @@ C_StaticObj::~C_StaticObj(void) } void C_StaticObj::Init(ModelInitData modelInit) { + C_Object::Init(modelInit); // load models privData = new myData(); privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->WorldMatrix = modelInit.world; privData->model->Visible = modelInit.visible; + privData->model->WorldMatrix = getWorld(); privData->ID = modelInit.id; } -void C_StaticObj::setPos(Oyster::Math::Float4x4 world) -{ - privData->model->WorldMatrix = world; -} + void C_StaticObj::Render() { diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h index 799c0982..3bae1961 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h @@ -14,7 +14,6 @@ public: C_StaticObj(void); virtual ~C_StaticObj(void); void Init(ModelInitData modelInit); - void setPos(Oyster::Math::Float4x4 world); void Render(); void Release(); diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp index fa5dff04..fc9c7d53 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp @@ -19,11 +19,12 @@ C_UIobject::~C_UIobject(void) } void C_UIobject::Init(ModelInitData modelInit) { + C_Object::Init(modelInit); // load models privData = new myData(); privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->WorldMatrix = modelInit.world; privData->model->Visible = modelInit.visible; + privData->model->WorldMatrix = getWorld(); privData->ID = modelInit.id; } diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index d8547943..8dfd99f5 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -1,20 +1,16 @@ #include "GameState.h" #include "DllInterfaces/GFXAPI.h" -#include "C_obj/C_Player.h" -#include "C_obj/C_DynamicObj.h" #include #include "NetworkClient.h" #include "Camera.h" #include using namespace DanBias::Client; - +using namespace Oyster::Math; struct GameState::myData { myData(){} - Oyster::Math3D::Float4x4 view; - Oyster::Math3D::Float4x4 proj; - std::vector object; + //std::vector object; int modelCount; Oyster::Network::NetworkClient* nwClient; gameStateState state; @@ -49,39 +45,123 @@ bool GameState::Init(Oyster::Network::NetworkClient* nwClient) GameState::gameStateState GameState::LoadGame() { Oyster::Graphics::Definitions::Pointlight plight; - plight.Pos = Oyster::Math::Float3(315, 0 ,5); - plight.Color = Oyster::Math::Float3(0.9,0.7,0.2); + plight.Pos = Float3(315, 0 ,5); + plight.Color = Float3(0.9f,0.7f,0.2f); plight.Radius = 100; - plight.Bright = 0.9; + plight.Bright = 0.9f; Oyster::Graphics::API::AddLight(plight); - plight.Pos = Oyster::Math::Float3(10,350,5); - plight.Color = Oyster::Math::Float3(0.9,0.7,0.3); + plight.Pos = Float3(10,350,5); + plight.Color = Float3(0.9f,0.7f,0.3f); plight.Radius = 200; - plight.Bright = 0.7; + plight.Bright = 0.7f; Oyster::Graphics::API::AddLight(plight); - plight.Pos = Oyster::Math::Float3(350,350,5); - plight.Color = Oyster::Math::Float3(0.9,0.7,0.3); + plight.Pos = Float3(350,350,5); + plight.Color = Float3(0.9f,0.7f,0.3f); plight.Radius = 200; - plight.Bright = 0.7; + plight.Bright = 0.7f; Oyster::Graphics::API::AddLight(plight); - plight.Pos = Oyster::Math::Float3(10,350,350); - plight.Color = Oyster::Math::Float3(0.9,0.7,0.3); + plight.Pos = Float3(10,350,350); + plight.Color = Float3(0.9f,0.7f,0.3f); plight.Radius = 200; - plight.Bright = 0.7; + plight.Bright = 0.7f; Oyster::Graphics::API::AddLight(plight); - plight.Pos = Oyster::Math::Float3(10,-15,5); - plight.Color = Oyster::Math::Float3(0,0,1); + plight.Pos = Float3(10,-15,5); + plight.Color = Float3(0,0,1); plight.Radius = 50; plight.Bright = 2; Oyster::Graphics::API::AddLight(plight); - LoadModels(L"map"); - InitCamera(Oyster::Math::Float3(0,0,20.0f)); + LoadModels("3bana.bias"); + Float3 startPos = Float3(0,0,20.0f); + InitCamera(startPos); return gameStateState_playing; } -bool GameState::LoadModels(std::wstring mapFile) +bool GameState::LoadModels(std::string mapFile) { - // open file + GameLogic::LevelLoader levelLoader; + std::vector> objects; + objects = levelLoader.LoadLevel(mapFile); + + int objCount = objects.size(); + int modelId = 0; + ModelInitData modelData; + for (int i = 0; i < objCount; i++) + { + GameLogic::ObjectTypeHeader* obj = objects.at(i); + + switch (obj->typeID) + { + case GameLogic::ObjectType::ObjectType_LevelMetaData: + + break; + case GameLogic::ObjectType::ObjectType_Static: + { + GameLogic::ObjectHeader* staticObjData = ((GameLogic::ObjectHeader*)obj); + + modelData.modelPath.assign(staticObjData->ModelFile.begin(), staticObjData->ModelFile.end()); + modelData.visible = true; + //modelData.position = ; + //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1); + //modelData.scale = Oyster::Math::Float3(2,2,2); + modelData.id = modelId++; + + this->staticObjects.Push(new C_StaticObj()); + this->staticObjects[this->staticObjects.Size() -1 ]->Init(modelData); + } + break; + case GameLogic::ObjectType::ObjectType_Dynamic: + { + GameLogic::ObjectHeader* dynamicObjData = ((GameLogic::ObjectHeader*)obj); + //modelData.position = ; + //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1); + //modelData.scale = Oyster::Math::Float3(2,2,2); + modelData.modelPath.assign(dynamicObjData->ModelFile.begin(), dynamicObjData->ModelFile.end()); + modelData.visible = true; + modelData.id = modelId++; + + this->dynamicObjects.Push(new C_DynamicObj()); + this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData); + } + break; + case GameLogic::ObjectType::ObjectType_Light: + { + GameLogic::BasicLight* lightData = ((GameLogic::BasicLight*)obj); + + if(lightData->lightType == GameLogic::LightType_PointLight) + { + Oyster::Graphics::Definitions::Pointlight plight; + plight.Pos = ((GameLogic::PointLight*)lightData)->position; + plight.Color = lightData->diffuseColor; + plight.Radius = 100; + plight.Bright = 0.9f; + Oyster::Graphics::API::AddLight(plight); + } + } + break; + default: + break; + } + } + myId += modelId++; + // add player model + //modelData.position = ; + //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1); + //modelData.scale = Oyster::Math::Float3(2,2,2); + + + modelData.visible = true; + modelData.modelPath = L"char_still_sizeref.dan"; + modelData.id = myId; + // load models + this->dynamicObjects.Push(new C_DynamicObj()); + this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData); + + /*C_Player* obj = new C_Player(); + privData->object.push_back(obj); + privData->object[privData->object.size() -1 ]->Init(modelData); + */ + return true; + /*// open file // read file // init models int nrOfBoxex = 20; @@ -199,27 +279,18 @@ bool GameState::LoadModels(std::wstring mapFile) // load models obj = new C_Player(); privData->object.push_back(obj); - privData->object[privData->object.size() -1 ]->Init(modelData); - - return true; + privData->object[privData->object.size() -1 ]->Init(modelData); */ } -bool GameState::InitCamera(Oyster::Math::Float3 startPos) +bool GameState::InitCamera(Float3 startPos) { - Oyster::Math::Float3 dir = Oyster::Math::Float3(0,0,1); - Oyster::Math::Float3 up =Oyster::Math::Float3(0,1,0); - Oyster::Math::Float3 pos = Oyster::Math::Float3(0, 0, 20); - + Float3 dir = Float3(0,0,1); + Float3 up = Float3(0,1,0); + Float3 pos = Float3(0, 0, 20); camera->LookAt(pos, dir, up); - camera->SetLens(3.14f/2, 1024/768, 1, 1000); - - privData->proj = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1024.0f/768.0f,.1f,1000); - //privData->proj = Oyster::Math3D::ProjectionMatrix_Orthographic(1024, 768, 1, 1000); - Oyster::Graphics::API::SetProjection(privData->proj); + camera->SetLens(pi/4, 1024/768, 1, 1000); camera->UpdateViewMatrix(); - privData->view = camera->View(); - privData->view = Oyster::Math3D::ViewMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos); - privData->view = Oyster::Math3D::OrientationMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos); - privData->view = Oyster::Math3D::InverseOrientationMatrix(privData->view); + Oyster::Graphics::API::SetProjection(camera->Proj()); + return true; } void GameState::setClientId(int id) @@ -263,25 +334,28 @@ GameClientState::ClientState GameState::Update(float deltaTime, InputClass* KeyI bool GameState::Render() { Oyster::Graphics::API::SetView(camera->View()); - //Oyster::Graphics::API::SetProjection(camera->Proj()); - //Oyster::Graphics::API::SetView(privData->view); - Oyster::Graphics::API::SetProjection(privData->proj); + Oyster::Graphics::API::NewFrame(); - for (unsigned int i = 0; i < privData->object.size(); i++) + for (unsigned int i = 0; i < staticObjects.Size(); i++) { - privData->object[i]->Render(); + staticObjects[i]->Render(); } + for (unsigned int i = 0; i < dynamicObjects.Size(); i++) + { + dynamicObjects[i]->Render(); + } + Oyster::Graphics::API::EndFrame(); return true; } bool GameState::Release() { - for (unsigned int i = 0; i < privData->object.size(); i++) + /*for (unsigned int i = 0; i < privData->object.size(); i++) { - privData->object[i]->Release(); - delete privData->object[i]; - privData->object[i] = NULL; - } + privData->object[i]->Release(); + delete privData->object[i]; + privData->object[i] = NULL; + }*/ delete privData; privData = NULL; @@ -440,13 +514,17 @@ void GameState::Protocol(ProtocolStruct* pos) void GameState::Protocol( PlayerPos* pos ) { - Oyster::Math::Float4x4 world, translate; + //Oyster::Math::Float4x4 world, translate; - world = Oyster::Math::Float4x4::identity; - translate = Oyster::Math::Float4x4::identity; - translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(pos->playerPos[0],pos->playerPos[1],pos->playerPos[2])); - world = world * translate; - privData->object[0]->setPos( world ); + //world = Oyster::Math::Float4x4::identity; + //translate = Oyster::Math::Float4x4::identity; + //translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(pos->playerPos[0],pos->playerPos[1],pos->playerPos[2])); + //world = world * translate; + ////privData->object[0]->setPos( world ); + //for (unsigned int i = 0; i < dynamicObjects.Size(); i++) + //{ + // dynamicObjects[i]->Render(); + //} } void GameState::Protocol( ObjPos* pos ) @@ -457,21 +535,21 @@ void GameState::Protocol( ObjPos* pos ) world[i] = pos->worldPos[i]; } //printf("pos for obj %d, ",pos->object_ID ); - for (unsigned int i = 0; i < privData->object.size(); i++) + for (unsigned int i = 0; i < dynamicObjects.Size(); i++) { - if(privData->object[i]->GetId() == pos->object_ID) + if(dynamicObjects[i]->GetId() == pos->object_ID) { - privData->object[i]->setPos(world); + dynamicObjects[i]->setWorld(world); - if(i == myId) // playerobj + if(dynamicObjects[i]->GetId() == myId) // playerobj { - Oyster::Math::Float3 right = Oyster::Math::Float3(world[0], world[1], world[2]); - Oyster::Math::Float3 up = Oyster::Math::Float3(world[4], world[5], world[6]); - Oyster::Math::Float3 objForward = (Oyster::Math::Float3(world[8], world[9], world[10])); - Oyster::Math::Float3 pos = Oyster::Math::Float3(world[12], world[13], world[14]); + Float3 right = Float3(world[0], world[1], world[2]); + Float3 up = Float3(world[4], world[5], world[6]); + Float3 objForward = Float3(world[8], world[9], world[10]); + Float3 pos = Float3(world[12], world[13], world[14]); - Oyster::Math::Float3 cameraLook = camera->GetLook(); - Oyster::Math::Float3 cameraUp = camera->GetUp(); + Float3 cameraLook = camera->GetLook(); + Float3 cameraUp = camera->GetUp(); @@ -506,28 +584,29 @@ void GameState::Protocol( NewObj* newObj ) } ModelInitData modelData; - modelData.world = world; + //modelData.world = world; modelData.visible = true; modelData.id = newObj->object_ID; //not sure if this is good parsing rom char* to wstring const char* path = newObj->path; modelData.modelPath = std::wstring(path, path + strlen(path)); // load models - C_Object* player = new C_Player(); + C_DynamicObj* player = new C_DynamicObj(); player->Init(modelData); - privData->object.push_back(player); + dynamicObjects.Push(player); } void DanBias::Client::GameState::Protocol( RemoveObj* obj ) { - for (unsigned int i = 0; i < privData->object.size(); i++) + for (unsigned int i = 0; i < dynamicObjects.Size(); i++) { - if(privData->object[i]->GetId() == obj->object_ID) + if(dynamicObjects[i]->GetId() == obj->object_ID) { - privData->object.at(i)->Release(); - privData->object.erase(privData->object.begin() + i ); + //dynamicObjects[i]->Release(); + dynamicObjects[i].Release(); + //dynamicObjects.erase(privData->object.begin() + i ); } } //privData->object[obj->object_ID]->Release( ); diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.h b/Code/Game/DanBiasGame/GameClientState/GameState.h index d555134c..425fb2be 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.h +++ b/Code/Game/DanBiasGame/GameClientState/GameState.h @@ -4,6 +4,11 @@ #include "OysterMath.h" #include #include "Camera.h" +#include "LevelLoader/LevelLoader.h" +#include "C_obj/C_Player.h" +#include "C_obj/C_DynamicObj.h" +#include "C_obj/C_StaticObj.h" +#include "DynamicArray.h" namespace DanBias { namespace Client @@ -30,12 +35,15 @@ private: float pitch; struct myData; myData* privData; + Utility::DynamicMemory::DynamicArray> staticObjects; + Utility::DynamicMemory::DynamicArray> dynamicObjects; + Utility::DynamicMemory::DynamicArray> playObjects; public: GameState(void); ~GameState(void); bool Init(Oyster::Network::NetworkClient* nwClient); GameClientState::ClientState Update(float deltaTime, InputClass* KeyInput) override; - bool LoadModels(std::wstring mapFile) ; + bool LoadModels(std::string mapFile) ; bool InitCamera(Oyster::Math::Float3 startPos) ; gameStateState LoadGame(); void setClientId(int id); diff --git a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp index 8df39bfa..092307af 100644 --- a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp @@ -64,15 +64,16 @@ bool LanMenuState::LoadModels(std::wstring file) ModelInitData modelData; - modelData.world = Oyster::Math3D::Float4x4::identity; + modelData.position = Oyster::Math::Float3(0,0,0); + modelData.rotation = Oyster::Math::Quaternion::identity; + modelData.scale = Oyster::Math::Float3(1,1,1); modelData.visible = true; modelData.modelPath = L"..\\Content\\Models\\box_2.dan"; // load models privData->object[0] = new C_StaticObj(); privData->object[0]->Init(modelData); - Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(-2,-2,-2)); - modelData.world = modelData.world * translate; + modelData.position = Oyster::Math::Float3(-2, -2, -2); privData->object[1] = new C_DynamicObj(); privData->object[1]->Init(modelData); diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp new file mode 100644 index 00000000..55a39725 --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp @@ -0,0 +1,35 @@ +////////////////////////////////// +// Created by Sam Svensson 2013 // +////////////////////////////////// + +#include "LevelLoader.h" +#include "LevelParser.h" + +using namespace GameLogic; +using namespace GameLogic::LevelFileLoader; + +struct LevelLoader::PrivData +{ + LevelParser parser; + std::string folderPath; +}; + +LevelLoader::LevelLoader() + : pData(new PrivData) +{ + pData->folderPath = "Standard path"; +} + +LevelLoader::~LevelLoader() +{ +} + +std::vector> LevelLoader::LoadLevel(std::string fileName) +{ + return pData->parser.Parse(fileName); +} + +LevelMetaData LevelLoader::LoadLevelHeader(std::string fileName) +{ + return pData->parser.ParseHeader(fileName); +} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h new file mode 100644 index 00000000..bcd6e587 --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h @@ -0,0 +1,42 @@ +////////////////////////////////// +// Created by Sam Svensson 2013 // +////////////////////////////////// + +#ifndef LEVELLOADER_H +#define LEVELLOADER_H + +#include +#include +#include "../Misc/Utilities.h" +#include "ObjectDefines.h" + +namespace GameLogic +{ + class LevelLoader + { + + public: + LevelLoader(); + ~LevelLoader(); + + /******************************************************** + * Loads the level and objects from file. + * @param fileName: Path to the level-file that you want to load. + * @return: Returns all structs with objects and information about the level. + ********************************************************/ + std::vector> LoadLevel(std::string fileName); + + /******************************************************** + * Just for fast access for the meta information about the level. + * @param fileName: Path to the level-file that you want to load. + * @return: Returns the meta information about the level. + ********************************************************/ + LevelMetaData LoadLevelHeader(std::string fileName); //. + + private: + struct PrivData; + Utility::DynamicMemory::SmartPointer pData; + }; +} + +#endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp new file mode 100644 index 00000000..088c3916 --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp @@ -0,0 +1,190 @@ +#include "LevelParser.h" + +#include "Loader.h" +#include "ParseFunctions.h" + +using namespace GameLogic; +using namespace ::LevelFileLoader; +using namespace Utility::DynamicMemory; + +LevelParser::LevelParser() +{ + formatVersion.formatVersionMajor = 1; + formatVersion.formatVersionMinor = 0; +} + +LevelParser::~LevelParser() +{ +} + +std::vector> LevelParser::Parse(std::string filename) +{ + int bufferSize = 0; + int counter = 0; + + std::vector> objects; + + //Read entire level file. + Loader loader; + char* buffer = (char*)loader.LoadFile(filename.c_str(), bufferSize); + + //Read format version + FormatVersion levelFormatVersion; + ParseObject(&buffer[counter], &levelFormatVersion, sizeof(levelFormatVersion)); + counter += sizeof(levelFormatVersion); + if(this->formatVersion != levelFormatVersion) + { + //Do something if it's not the same version + } + + while(counter < bufferSize) + { + //Get typeID + ObjectTypeHeader typeID; + ParseObject(&buffer[counter], &typeID, sizeof(typeID)); + switch((int)typeID.typeID) + { + case ObjectType_LevelMetaData: + { + LevelMetaData* header = new LevelMetaData; + ParseLevelMetaData(&buffer[counter], *header, counter); + objects.push_back(header); + break; + } + + //This is by design, static and dynamic is using the same converter. Do not add anything inbetween them. + case ObjectType_Static: case ObjectType_Dynamic: + { + ObjectHeader* header = new ObjectHeader; + ParseObject(&buffer[counter], *header, counter); + objects.push_back(header); + break; + } + + case ObjectType_Light: + { + LightType lightType; + + //Get Light type + ParseObject(&buffer[counter+4], &lightType, sizeof(lightType)); + + switch(lightType) + { + case LightType_PointLight: + { + PointLight* header = new PointLight; + ParseObject(&buffer[counter], header, sizeof(*header)); + counter += sizeof(*header); + objects.push_back(header); + break; + } + case LightType_DirectionalLight: + { + DirectionalLight* header = new DirectionalLight; + ParseObject(&buffer[counter], header, sizeof(*header)); + counter += sizeof(*header); + objects.push_back(header); + break; + } + case LightType_SpotLight: + { + SpotLight* header = new SpotLight; + ParseObject(&buffer[counter], header, sizeof(*header)); + counter += sizeof(*header); + objects.push_back(header); + break; + } + default: + //Undefined LightType. + break; + } + break; + } + default: + //Couldn't find typeID. FAIL!!!!!! + break; + } + } + + return objects; +} + +//för meta information om leveln. +LevelMetaData LevelParser::ParseHeader(std::string filename) +{ + int bufferSize = 0; + int counter = 0; + + LevelMetaData levelHeader; + levelHeader.typeID = ObjectType::ObjectType_Unknown; + + //Read entire level file. + Loader loader; + char* buffer = (char*)loader.LoadFile(filename.c_str(), bufferSize); + + //Read format version + FormatVersion levelFormatVersion; + ParseObject(&buffer[counter], &levelFormatVersion, sizeof(formatVersion)); + counter += sizeof(levelFormatVersion); + if(this->formatVersion != levelFormatVersion) + { + //Do something if it's not the same version + } + + //Find the header in the returned string. + while(counter < bufferSize) + { + ObjectTypeHeader typeID; + ParseObject(&buffer[counter], &typeID, sizeof(typeID)); + + switch(typeID.typeID) + { + case ObjectType_LevelMetaData: + ParseLevelMetaData(&buffer[counter], levelHeader, counter); + return levelHeader; + break; + + //This is by design, static and dynamic is using the same converter. Do not add anything inbetween them. + case ObjectType_Static: case ObjectType_Dynamic: + { + ObjectHeader header; + ParseObject(&buffer[counter], header, counter); + break; + } + + case ObjectType_Light: + { + LightType lightType; + ParseObject(&buffer[counter+4], &lightType, sizeof(lightType)); + + switch(lightType) + { + case LightType_PointLight: + { + counter += sizeof(PointLight); + break; + } + case LightType_DirectionalLight: + { + counter += sizeof(DirectionalLight); + break; + } + case LightType_SpotLight: + { + counter += sizeof(SpotLight); + break; + } + default: + //Undefined LightType. + break; + } + } + + default: + //Couldn't find typeID. FAIL!!!!!! + break; + } + } + + return levelHeader; +} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h new file mode 100644 index 00000000..9ad30642 --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h @@ -0,0 +1,31 @@ +#ifndef LEVEL_PARSER_H +#define LEVEL_PARSER_H + +#include +#include +#include "ObjectDefines.h" +#include "../Misc/Utilities.h" + +namespace GameLogic +{ + namespace LevelFileLoader + { + class LevelParser + { + public: + LevelParser(); + ~LevelParser(); + + // + std::vector> Parse(std::string filename); + + // + LevelMetaData ParseHeader(std::string filename); + + private: + FormatVersion formatVersion; + + }; + } +} +#endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp new file mode 100644 index 00000000..3e15315c --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp @@ -0,0 +1,22 @@ +////////////////////////////////// +// Created by Sam Svensson 2013 // +////////////////////////////////// + +#include "Loader.h" +#include + +using namespace GameLogic::LevelFileLoader; +using namespace Oyster::Resource; +using namespace std; + +char* Loader::LoadFile(std::string fileName, int &size) +{ + //convert from string to wstring + std::wstring temp(fileName.begin(), fileName.end()); + + //convert from wstring to wchar then loads the file + char* buffer = (char*)OysterResource::LoadResource(temp.c_str(), Oyster::Resource::ResourceType::ResourceType_Byte_Raw, -1 , false); + + size = OysterResource::GetResourceSize(buffer); + return buffer; +} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h new file mode 100644 index 00000000..198c2a87 --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h @@ -0,0 +1,28 @@ +////////////////////////////////// +// Created by Sam Svensson 2013 // +////////////////////////////////// + +#ifndef LOADER_H +#define LOADER_H + +#include "..\Misc\Resource\OysterResource.h" +#include + +namespace GameLogic +{ + namespace LevelFileLoader + { + class Loader + { + public: + Loader (){}; + ~Loader(){}; + char* LoadFile(std::string fileName, int &size); + + //TODO: + //Add functionality to load physicsObjects (hitboxes) + }; + } +} + +#endif; \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h new file mode 100644 index 00000000..8287dafb --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h @@ -0,0 +1,172 @@ +#ifndef OBJECT_DEFINES_H +#define OBJECT_DEFINES_H + +#include +#include + +namespace GameLogic +{ + /************************************ + Enums + *************************************/ + + enum ObjectType + { + ObjectType_LevelMetaData, + ObjectType_Static, + ObjectType_Dynamic, + ObjectType_Light, + //Etc + + ObjectType_NUM_OF_TYPES, + + ObjectType_Unknown = -1 + }; + + enum UsePhysics + { + UsePhysics_UseFullPhysics, + UsePhysics_IgnoreGravity, + UsePhysics_IgnorePhysics, + UsePhysics_IgnoreCollision, + + UsePhysics_Count, + UsePhysics_Unknown = -1 + }; + + enum CollisionGeometryType + { + CollisionGeometryType_Box, + CollisionGeometryType_Sphere, + + CollisionGeometryType_Count, + CollisionGeometryType_Unknown = -1 + }; + + enum LightType + { + LightType_PointLight, + LightType_DirectionalLight, + LightType_SpotLight, + + LightType_Count, + LightType_Unknown = -1 + }; + + //Should this be moved somewhere else? + enum GameMode + { + GameMode_FreeForAll, + GameMode_TeamDeathMatch, + //Etc + + GameMode_Count, + GameMode_Unknown = -1 + }; + + enum WorldSize + { + WorldSize_Tiny, + WorldSize_Small, + WorldSize_Medium, + WorldSize_Big, + WorldSize_Humongous, + + WorldSize_Count, + WorldSize_Unknown = -1 + }; + + + /************************************ + Structs + *************************************/ + + struct FormatVersion + { + unsigned int formatVersionMajor; + unsigned int formatVersionMinor; + + bool operator ==(const FormatVersion& obj) + { + return (this->formatVersionMajor != obj.formatVersionMajor && this->formatVersionMinor != obj.formatVersionMinor); + } + + bool operator !=(const FormatVersion& obj) + { + return !(*this == obj); + } + }; + + struct ObjectTypeHeader + { + ObjectType typeID; + }; + + struct PhysicsObject + { + UsePhysics usePhysics; + float mass; + float inertiaMagnitude[3]; + float inertiaRotation[3]; + float frictionCoeffStatic; + float frictionCoeffDynamic; + CollisionGeometryType geometryType; + }; + + struct LevelMetaData : public ObjectTypeHeader + { + std::string levelName; + unsigned int levelVersion; + std::string levelDescription; + std::string levelAuthor; + unsigned int maxNumberOfPlayer; + WorldSize worldSize; + std::string overviewPicturePath; + std::vector gameModesSupported; + }; + + struct ObjectHeader : public ObjectTypeHeader, public PhysicsObject + { + //Model, + std::string ModelFile; + //Position + float position[3]; + //Rotation + float rotation[3]; + float angle; + //Scale + float scale[3]; + }; + + + /************************************ + Lights + *************************************/ + + struct BasicLight : public ObjectTypeHeader + { + LightType lightType; + float ambientColor[3]; + float diffuseColor[3]; + float specularColor[3]; + }; + + struct PointLight : public BasicLight + { + float position[3]; + }; + + struct DirectionalLight : public BasicLight + { + float direction[3]; + }; + + struct SpotLight : public BasicLight + { + float direction[3]; + float range; + float attenuation[3]; + }; +} + +#endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp new file mode 100644 index 00000000..08823d3d --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp @@ -0,0 +1,111 @@ +////////////////////////////////// +// Created by Sam Svensson 2013 // +////////////////////////////////// + +#include "ParseFunctions.h" +#include "../../../../Misc/Packing/Packing.h" +#include + +using namespace Oyster::Packing; +using namespace GameLogic::LevelFileLoader; +using namespace GameLogic; +using namespace std; + +namespace GameLogic +{ + namespace LevelFileLoader + { + void ParseObject(char* buffer, void *header, int size) + { + memcpy(header, buffer, size); + } + + void ParseObject(char* buffer, ObjectHeader& header, int& size) + { + char tempName[128]; + unsigned int tempSize = 0; + int start = 0; + + memcpy(&header.typeID, &buffer[start], 4); + start += 4; + + memcpy(&tempSize, &buffer[start], 4); + start += 4; + + memcpy(&tempName, &buffer[start], tempSize); + header.ModelFile.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + + //3 float[3], 1 float + memcpy(&header.position, &buffer[start], 40); + start += 40; + + //2 float[3], 3 float, 2 uint + memcpy(&header.usePhysics, &buffer[start], 44); + start += 44; + + size += start; + } + + void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size) + { + int start = 0; + unsigned int tempSize; + char tempName[128]; + + memcpy(&header.typeID, &buffer[start], 4); + start += 4; + + memcpy(&tempSize , &buffer[start], 4); + start += 4; + + memcpy(&tempName, &buffer[start], tempSize); + header.levelName.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + + memcpy(&header.levelVersion, &buffer[start], 4); + start += 4; + + memcpy(&tempSize, &buffer[start], 4); + start +=4; + + memcpy(&tempName, &buffer[start], tempSize); + header.levelDescription.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + + memcpy(&tempSize, &buffer[start], 4); + start += 4; + + memcpy(&tempName, &buffer[start], tempSize); + header.levelAuthor.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + + memcpy(&header.maxNumberOfPlayer, &buffer[start], 4); + start += 4; + + memcpy(&header.worldSize, &buffer[start], 4); + start += 4; + + memcpy(&tempSize, &buffer[start], 4); + start += 4; + + memcpy(&tempName, &buffer[start], tempSize); + header.overviewPicturePath.assign(&tempName[0], &tempName[tempSize]); + start += tempSize; + + memcpy(&tempSize, &buffer[start], 4); + start += 4; + + int temp; + + for(int i = 0; i < tempSize; i++) + { + memcpy(&temp, &buffer[start], 4); + start += 4; + header.gameModesSupported.push_back((GameMode)temp); + } + + size += start; + } + } +} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h new file mode 100644 index 00000000..f68a9289 --- /dev/null +++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h @@ -0,0 +1,28 @@ +////////////////////////////////// +// Created by Sam Svensson 2013 // +////////////////////////////////// + +#ifndef PARSERFUNCTIONS_H +#define PARSERFUNCTIONS_H +#include "ObjectDefines.h" + +namespace GameLogic +{ + namespace LevelFileLoader + { + /* + These functions will copy data from where the buffer pointer points. + header is the destination where the data will be copied. + size is either the size of the data to be copied (if it is NOT sent by reference). + Or the current index that is being used to parse the entire file (if it is sent by reference) this means you have to increase size with the appropiate size after you have copied. + + */ + + void ParseObject(char* buffer, void *header, int size); + void ParseObject(char* buffer, ObjectHeader& header, int& size); + void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size); + } +} + + +#endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp index 538408c5..07bf8d42 100644 --- a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp @@ -53,17 +53,18 @@ bool LobbyState::LoadModels(std::wstring file) ModelInitData modelData; - modelData.world = Oyster::Math3D::Float4x4::identity; + modelData.position = Oyster::Math::Float3(0,0,0); + modelData.rotation = Oyster::Math::Quaternion::identity; + modelData.scale = Oyster::Math::Float3(1,1,1); modelData.visible = true; modelData.modelPath = L"..\\Content\\Models\\box_2.dan"; // load models privData->object[0] = new C_StaticObj(); privData->object[0]->Init(modelData); - Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(2,2,2)); - modelData.world = modelData.world * translate; + modelData.position = Oyster::Math::Float3(2,2,2); - privData->object[1] = new C_DynamicObj(); + privData->object[1] = new C_StaticObj(); privData->object[1]->Init(modelData); return true; } diff --git a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp index 4a244a8b..1bc3af72 100644 --- a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp @@ -53,26 +53,18 @@ bool LoginState::LoadModels(std::wstring file) ModelInitData modelData; - modelData.world = Oyster::Math3D::Float4x4::identity; + modelData.rotation = Oyster::Math::Quaternion::identity; + modelData.scale = Oyster::Math::Float3(1,1,1); modelData.visible = true; modelData.modelPath = L"identityPlane.dan"; - // load models - Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(2,2,-2)); - Oyster::Math3D::Float4x4 rot = Oyster::Math3D::RotationMatrix(Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0)); - Oyster::Math3D::Float4x4 scale = Oyster::Math3D::Float4x4::identity; - int scaling = 2; - scale.v[0].x = scaling; - scale.v[1].y = scaling; - scale.v[2].z = scaling; + - modelData.world = translate; //scale * translate * rot; - privData->object[0] = new C_DynamicObj(); + modelData.position = Oyster::Math::Float3(2,2,2); + privData->object[0] = new C_StaticObj(); privData->object[0]->Init(modelData); - translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(0,0,-2)); - modelData.world = translate ;//* rot; - - privData->object[1] = new C_DynamicObj(); + modelData.position = Oyster::Math::Float3(0,0,-2); + privData->object[1] = new C_StaticObj(); privData->object[1]->Init(modelData); return true; } diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index 6aecc900..8077c6bf 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -81,7 +81,8 @@ Game::LevelData* Game::CreateLevel() if(this->level) return this->level; this->level = new LevelData(); - this->level->level->InitiateLevel(1000); + //this->level->level->InitiateLevel(1000); + this->level->level->InitiateLevel("3bana.bias"); return this->level; } diff --git a/Code/Game/GameLogic/GameLogic.vcxproj b/Code/Game/GameLogic/GameLogic.vcxproj index 674773bf..7ae78fac 100644 --- a/Code/Game/GameLogic/GameLogic.vcxproj +++ b/Code/Game/GameLogic/GameLogic.vcxproj @@ -181,7 +181,7 @@ - + @@ -203,7 +203,7 @@ - + diff --git a/Code/Game/GameLogic/GameMode.cpp b/Code/Game/GameLogic/GameMode.cpp deleted file mode 100644 index ba240fca..00000000 --- a/Code/Game/GameLogic/GameMode.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "GameMode.h" - -using namespace GameLogic; - - -GameMode::GameMode() -{ - -} - - -GameMode::~GameMode(void) -{ - -} diff --git a/Code/Game/GameLogic/GameModeType.cpp b/Code/Game/GameLogic/GameModeType.cpp new file mode 100644 index 00000000..b48fd475 --- /dev/null +++ b/Code/Game/GameLogic/GameModeType.cpp @@ -0,0 +1,15 @@ +#include "GameModeType.h" + +using namespace GameLogic; + + +GameModeType::GameModeType() +{ + +} + + +GameModeType::~GameModeType(void) +{ + +} diff --git a/Code/Game/GameLogic/GameMode.h b/Code/Game/GameLogic/GameModeType.h similarity index 63% rename from Code/Game/GameLogic/GameMode.h rename to Code/Game/GameLogic/GameModeType.h index d910c78c..8cc9fa37 100644 --- a/Code/Game/GameLogic/GameMode.h +++ b/Code/Game/GameLogic/GameModeType.h @@ -3,16 +3,16 @@ ////////////////////////////////////////////////// -#ifndef GAMEMODE_H -#define GAMEMODE_H +#ifndef GAMEMODETYPE_H +#define GAMEMODETYPE_H namespace GameLogic { - class GameMode + class GameModeType { public: - GameMode(void); - ~GameMode(void); + GameModeType(void); + ~GameModeType(void); private: diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index ee535868..d4657998 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -19,7 +19,7 @@ Game::PlayerData::PlayerData() Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release(); //create player with this rigid body - this->player = new Player(rigidBody,Player::DefaultCollisionAfter, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); + this->player = new Player(rigidBody,Level::LevelCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); /*Oyster::Physics::ICustomBody::State state; this->player->GetRigidBody()->GetState(state); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 81c71de6..a954e11b 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -13,10 +13,183 @@ Level::Level(void) Level::~Level(void) { } +void Level::parseObjectType(ObjectTypeHeader* obj) +{ + /*switch (obj->objectTypeID) + { + case skySphere: + // save the skysphere to be able to rotate it + break; + case jumppad: + // save direction + break; + case portal: + // save portal destination + break; + case world: + // add gravitation well here + // add outer limit of the world + case spawn: + // save spawnpoint pos + break; + default: + break; + }*/ +} +void Level::parsePhysicsObj(PhysicsObject* obj) +{ + // offset physObj med modelObj +} void Level::InitiateLevel(std::string levelPath) { + LevelLoader ll; + std::vector> objects; + objects = ll.LoadLevel(levelPath); + int objCount = objects.size(); + int modelCount = 0; + for (int i = 0; i < objCount; i++) + { + ObjectTypeHeader* obj = objects.at(i); + int id = obj->typeID; + switch (obj->typeID) + { + case ObjectType::ObjectType_LevelMetaData: + { + LevelMetaData* LevelObjData = ((LevelMetaData*)obj); + std::string levelName = LevelObjData->levelName; + // LevelObjData->worldSize; + } + break; + case ObjectType::ObjectType_Static: + { + + ObjectHeader* staticObjData = ((ObjectHeader*)obj); + PhysicsObject* staticObjPhysicData = ((ObjectHeader*)obj); + staticObjData->ModelFile; + ICustomBody* rigidBody_Static; + if( staticObjPhysicData->geometryType = CollisionGeometryType_Box) + { + API::SimpleBodyDescription sbDesc_Static; + + sbDesc_Static.centerPosition = staticObjData->position; + sbDesc_Static.ignoreGravity = false; // because it is static + sbDesc_Static.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); + + + //sbDesc_Static.inertiaTensor.Cuboid(staticObjPhysicData->mass); + sbDesc_Static.mass = staticObjPhysicData->mass; + sbDesc_Static.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; + sbDesc_Static.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; + //sbDesc_Static.restitutionCoeff = + sbDesc_Static.size = Oyster::Math::Float3(40,40,40); + rigidBody_Static = API::Instance().CreateRigidBody(sbDesc_Static).Release(); + if(rigidBody_Static) + { + this->staticObjects.Push(new StaticObject(rigidBody_Static,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); + int id = this->staticObjects.Size()-1; + rigidBody_Static->SetCustomTag(this->staticObjects[this->staticObjects.Size()-1]); + } + } + if( staticObjPhysicData->geometryType = CollisionGeometryType_Sphere) + { + API::SphericalBodyDescription sbDesc_Static; + + sbDesc_Static.centerPosition = staticObjData->position; + sbDesc_Static.ignoreGravity = true; // because it is static + sbDesc_Static.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); + + //sbDesc_Static.inertiaTensor.Sphere(staticObjPhysicData->mass); + + sbDesc_Static.mass = staticObjPhysicData->mass; + sbDesc_Static.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; + sbDesc_Static.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; + //sbDesc_Static.restitutionCoeff = + //sbDesc_Static.radius = + rigidBody_Static = API::Instance().CreateRigidBody(sbDesc_Static).Release(); + if(rigidBody_Static) + { + this->staticObjects.Push(new StaticObject(rigidBody_Static,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); + int id = this->staticObjects.Size()-1; + rigidBody_Static->SetCustomTag(this->staticObjects[this->staticObjects.Size()-1]); + } + + if (OBJECT_TYPE::OBJECT_TYPE_WORLD) + { + API::Gravity gravityWell; + gravityWell.gravityType = API::Gravity::GravityType_Well; + gravityWell.well.mass = 1e17f; + gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); + API::Instance().AddGravity(gravityWell); + } + } + } + break; + case ObjectType::ObjectType_Dynamic: + { + ObjectHeader* staticObjData = ((ObjectHeader*)obj); + PhysicsObject* staticObjPhysicData = ((ObjectHeader*)obj); + staticObjData->ModelFile; + + ICustomBody* rigidBody_Dynamic; + if( staticObjPhysicData->geometryType = CollisionGeometryType_Box) + { + API::SimpleBodyDescription sbDesc_Dynamic; + + sbDesc_Dynamic.centerPosition = staticObjData->position; + sbDesc_Dynamic.ignoreGravity = false; // because it is static + sbDesc_Dynamic.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); + + + //sbDesc_Static.inertiaTensor.Cuboid(staticObjPhysicData->mass); + sbDesc_Dynamic.mass = staticObjPhysicData->mass; + sbDesc_Dynamic.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; + sbDesc_Dynamic.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; + //sbDesc_Static.restitutionCoeff = + sbDesc_Dynamic.size = Oyster::Math::Float3(40,40,40); + rigidBody_Dynamic = API::Instance().CreateRigidBody(sbDesc_Dynamic).Release(); + if(rigidBody_Dynamic) + { + rigidBody_Dynamic->SetSubscription(Level::PhysicsOnMoveLevel); + this->dynamicObjects.Push(new DynamicObject(rigidBody_Dynamic,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); + int id = this->dynamicObjects.Size()-1; + rigidBody_Dynamic->SetCustomTag(this->dynamicObjects[this->dynamicObjects.Size()-1]); + } + } + if( staticObjPhysicData->geometryType = CollisionGeometryType_Sphere) + { + API::SphericalBodyDescription sbDesc_Dynamic; + + sbDesc_Dynamic.centerPosition = staticObjData->position; + sbDesc_Dynamic.ignoreGravity = false; // use gravity on dynamic obj + sbDesc_Dynamic.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); + + //sbDesc_Static.inertiaTensor.Sphere(staticObjPhysicData->mass); + + sbDesc_Dynamic.mass = staticObjPhysicData->mass; + sbDesc_Dynamic.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; + sbDesc_Dynamic.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; + //sbDesc_Static.restitutionCoeff = + //sbDesc_Static.radius = + rigidBody_Dynamic = API::Instance().CreateRigidBody(sbDesc_Dynamic).Release(); + if(rigidBody_Dynamic) + { + rigidBody_Dynamic->SetSubscription(Level::PhysicsOnMoveLevel); + this->dynamicObjects.Push(new DynamicObject(rigidBody_Dynamic,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); + int id = this->dynamicObjects.Size()-1; + rigidBody_Dynamic->SetCustomTag(this->dynamicObjects[this->dynamicObjects.Size()-1]); + } + } + } + break; + case ObjectType::ObjectType_Light: + // read on client + break; + default: + break; + } + } } void Level::InitiateLevel(float radius) { diff --git a/Code/Game/GameLogic/Level.h b/Code/Game/GameLogic/Level.h index cc34408b..64b09f5c 100644 --- a/Code/Game/GameLogic/Level.h +++ b/Code/Game/GameLogic/Level.h @@ -8,11 +8,12 @@ #include "Player.h" #include "StaticObject.h" #include "DynamicObject.h" -#include "GameMode.h" +#include "GameModeType.h" #include "Player.h" #include "PhysicsAPI.h" #include "TeamManager.h" #include "DynamicArray.h" +#include "LevelLoader/LevelLoader.h" namespace GameLogic { @@ -29,8 +30,10 @@ namespace GameLogic * @param levelPath: Path to a file that contains all information on the level ********************************************************/ void InitiateLevel(std::string levelPath); - void Level::InitiateLevel(float radius); + void InitiateLevel(float radius); + void parseObjectType(ObjectTypeHeader* obj); + void parsePhysicsObj(PhysicsObject* obj); /******************************************************** * Creates a team in the level * @param teamSize: The size of the team you want to create @@ -69,7 +72,7 @@ namespace GameLogic TeamManager teamManager; Utility::DynamicMemory::DynamicArray> staticObjects; Utility::DynamicMemory::DynamicArray> dynamicObjects; - GameMode gameMode; + GameModeType gameMode; Utility::DynamicMemory::SmartPointer rigidBodyLevel; StaticObject *levelObj; diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index ebd5c275..1a1f7338 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -178,13 +178,13 @@ void Object::EndFrame() //300, 0,0, //1,0,0 - /*if( pos.GetLength() < 303.5f) + if( pos.GetLength() < 303.5f) { Oyster::Math::Float moveUp = 303.5 - pos.GetLength(); up *= moveUp; currPhysicsState.SetCenterPosition(pos + up); - }*/ + } if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum()) diff --git a/Code/Game/GameLogic/Object.h b/Code/Game/GameLogic/Object.h index c484701c..91559734 100644 --- a/Code/Game/GameLogic/Object.h +++ b/Code/Game/GameLogic/Object.h @@ -27,6 +27,7 @@ namespace GameLogic // API overrides OBJECT_TYPE GetObjectType() const; + void setID(int id); int GetID() const; Oyster::Math::Float3 GetPosition(); Oyster::Math::Float4x4 GetOrientation(); diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp index d9f2f69d..f7a5646e 100644 --- a/Code/OysterPhysics3D/RigidBody.cpp +++ b/Code/OysterPhysics3D/RigidBody.cpp @@ -51,8 +51,8 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength ) // updating the linear //Decrease momentum with 1% as "fall-off" //! HACK: @todo Add real solution with fluid drag - //this->momentum_Linear = this->momentum_Linear*0.99f; - //this->momentum_Angular = this->momentum_Angular*0.99f; + this->momentum_Linear = this->momentum_Linear*0.99f; + this->momentum_Angular = this->momentum_Angular*0.99f; // ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G Float3 delta = AverageWithDelta( this->momentum_Linear, this->impulse_Linear ); From c18eb668aadf5a015a6baa919582e691a731a59c Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 14:18:45 +0100 Subject: [PATCH 25/35] Added more data for bodies and added cylinder --- .../Implementation/PhysicsAPI_Impl.cpp | 32 +++++++++++++++++-- .../Implementation/PhysicsAPI_Impl.h | 5 +-- .../Implementation/SimpleRigidBody.cpp | 21 ++++++++++++ .../Implementation/SimpleRigidBody.h | 4 +++ Code/GamePhysics/PhysicsAPI.h | 9 ++++-- Code/GamePhysics/PhysicsStructs.h | 7 +++- 6 files changed, 70 insertions(+), 8 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 4c3a25a0..7d70e146 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -47,7 +47,7 @@ API_Impl::~API_Impl() } // Bullet physics -ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) +ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) { SimpleRigidBody* body = new SimpleRigidBody; @@ -73,7 +73,8 @@ ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 r return body; } -ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) + +ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) { SimpleRigidBody* body = new SimpleRigidBody; @@ -100,6 +101,33 @@ ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 r return body; } +ICustomBody* API_Impl::AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) +{ + SimpleRigidBody* body = new SimpleRigidBody; + + // Add collision shape + btCollisionShape* collisionShape = new btCylinderShape(btVector3(halfSize.x, halfSize.y, halfSize.z)); + body->SetCollisionShape(collisionShape); + + // Add motion state + btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w),btVector3(position.x, position.y, position.z))); + body->SetMotionState(motionState); + + // Add rigid body + btVector3 fallInertia(0, 0, 0); + collisionShape->calculateLocalInertia(mass, fallInertia); + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); + btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); + rigidBody->setUserPointer(body); + body->SetRigidBody(rigidBody); + + // Add rigid body to world + this->dynamicsWorld->addRigidBody(rigidBody); + this->customBodies.push_back(body); + + return body; +} + void API_Impl::UpdateWorld() { this->dynamicsWorld->stepSimulation(1.0f/60.0f, 1.0f, 1.0f/60.0f); diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h index 03d1d3c6..28111d26 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h @@ -22,8 +22,9 @@ namespace Oyster void ReleaseFromLimbo( const ICustomBody* objRef ); // Bullet physics - ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass); - ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass); + ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); + ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); + ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); void UpdateWorld(); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index e5fea58b..9639a424 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -64,6 +64,27 @@ void SimpleRigidBody::SetSubscription(EventAction_Move function) this->onMovement = function; } +void SimpleRigidBody::SetLinearVelocity(Float3 velocity) +{ + this->rigidBody->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z)); +} + +void SimpleRigidBody::SetRotation(Float4 quaternion) +{ + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setRotation(btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w)); + this->motionState->setWorldTransform(trans); +} + +void SimpleRigidBody::SetRotation(Float3 eulerAngles) +{ + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setRotation(btQuaternion(eulerAngles.x, eulerAngles.y, eulerAngles.z)); + this->motionState->setWorldTransform(trans); +} + void SimpleRigidBody::CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) { if(this->onMovement) diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index d3655048..25fecfad 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -21,6 +21,10 @@ namespace Oyster void SetSubscription(EventAction_AfterCollisionResponse function); void SetSubscription(EventAction_Move function); + void SetLinearVelocity(Math::Float3 velocity); + void SetRotation(Math::Float4 quaternion); + void SetRotation(Math::Float3 eulerAngles); + void CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Math::Float kineticEnergyLoss); void CallSubscription_Move(); diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index c8bfde34..84f77b7d 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -80,9 +80,9 @@ namespace Oyster // Bullet physics - virtual ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) = 0; - - virtual ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass) = 0; + virtual ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0; + virtual ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0; + virtual ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0; virtual void UpdateWorld() = 0; @@ -144,6 +144,9 @@ namespace Oyster virtual void SetSubscription(EventAction_AfterCollisionResponse function) = 0; virtual void SetSubscription(EventAction_Move function) = 0; + virtual void SetLinearVelocity(::Oyster::Math::Float3 velocity) = 0; + virtual void SetRotation(::Oyster::Math::Float4 quaternion) = 0; + virtual void SetRotation(::Oyster::Math::Float3 eulerAngles) = 0; /******************************************************** * @return the void pointer set by SetCustomTag. diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index 5dc7d6f1..f68491d5 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -30,8 +30,13 @@ namespace Oyster ::Oyster::Math::Float4x4 GetOrientation() const; ::Oyster::Math::Float4x4 GetView() const; ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const; - void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j); + ::Oyster::Math::Float GetMass() const; + ::Oyster::Math::Float GetStaticFriction() const; + ::Oyster::Math::Float GetDynamicFriction() const; + ::Oyster::Math::Float GetRestitution() const; + + // Variables for state ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, dynamicFrictionCoeff; ::Oyster::Math::Float3 reach, centerPos; From 8547d17d0f567bc689aa976384359f27d90a7f10 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 14:22:10 +0100 Subject: [PATCH 26/35] Friction and restitution is now set --- Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 7d70e146..3c43fb29 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -64,6 +64,8 @@ ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 r collisionShape->calculateLocalInertia(mass, fallInertia); btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); + rigidBody->setFriction(staticFriction); + rigidBody->setRestitution(restitution); rigidBody->setUserPointer(body); body->SetRigidBody(rigidBody); @@ -91,6 +93,8 @@ ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 r collisionShape->calculateLocalInertia(mass, fallInertia); btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); + rigidBody->setFriction(staticFriction); + rigidBody->setRestitution(restitution); rigidBody->setUserPointer(body); body->SetRigidBody(rigidBody); @@ -118,6 +122,8 @@ ICustomBody* API_Impl::AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::O collisionShape->calculateLocalInertia(mass, fallInertia); btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia); btRigidBody* rigidBody = new btRigidBody(rigidBodyCI); + rigidBody->setFriction(staticFriction); + rigidBody->setRestitution(restitution); rigidBody->setUserPointer(body); body->SetRigidBody(rigidBody); From bd8722f107eca4026f47988515ca84ddf4503f78 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 14:39:45 +0100 Subject: [PATCH 27/35] Options for rigid bodies are now set directly --- .../Implementation/PhysicsAPI_Impl.cpp | 8 +-- .../Implementation/SimpleRigidBody.cpp | 56 +++++++++++++------ .../Implementation/SimpleRigidBody.h | 11 ++-- Code/GamePhysics/PhysicsAPI.h | 24 +++----- Code/GamePhysics/PhysicsStructs.h | 6 -- 5 files changed, 56 insertions(+), 49 deletions(-) diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 3c43fb29..7f3a53a7 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -142,19 +142,15 @@ void API_Impl::UpdateWorld() for(unsigned int i = 0; i < this->customBodies.size(); i++ ) { - this->customBodies[i]->GetState(state); - btTransform trans; dynamic_cast(this->customBodies[i])->GetMotionState()->getWorldTransform(trans); - state.centerPos = Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z()); - state.quaternion = Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w()); + this->customBodies[i]->SetPosition(Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z())); + this->customBodies[i]->SetRotation(Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w())); if(dynamic_cast(this->customBodies[i])->GetRigidBody()->getActivationState() == ACTIVE_TAG) { dynamic_cast(this->customBodies[i])->CallSubscription_Move(); } - - this->customBodies[i]->SetState(state); } int numManifolds = this->dynamicsWorld->getDispatcher()->getNumManifolds(); diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 9639a424..0621c2c6 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -69,12 +69,31 @@ void SimpleRigidBody::SetLinearVelocity(Float3 velocity) this->rigidBody->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z)); } +void SimpleRigidBody::SetPosition(::Oyster::Math::Float3 position) +{ + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setOrigin(btVector3(position.x, position.y, position.z)); + this->motionState->setWorldTransform(trans); + this->state.centerPos = position; +} + void SimpleRigidBody::SetRotation(Float4 quaternion) { btTransform trans; this->motionState->getWorldTransform(trans); trans.setRotation(btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w)); this->motionState->setWorldTransform(trans); + this->state.quaternion = Quaternion(quaternion.xyz, quaternion.w); +} + +void SimpleRigidBody::SetRotation(::Oyster::Math::Quaternion quaternion) +{ + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setRotation(btQuaternion(quaternion.imaginary.x, quaternion.imaginary.y, quaternion.imaginary.z, quaternion.real)); + this->motionState->setWorldTransform(trans); + this->state.quaternion = quaternion; } void SimpleRigidBody::SetRotation(Float3 eulerAngles) @@ -83,6 +102,27 @@ void SimpleRigidBody::SetRotation(Float3 eulerAngles) this->motionState->getWorldTransform(trans); trans.setRotation(btQuaternion(eulerAngles.x, eulerAngles.y, eulerAngles.z)); this->motionState->setWorldTransform(trans); + this->state.quaternion = Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w()); +} + +Float4x4 SimpleRigidBody::GetRotation() const +{ + return this->state.GetRotation(); +} + +Float4x4 SimpleRigidBody::GetOrientation() const +{ + return this->state.GetOrientation(); +} + +Float4x4 SimpleRigidBody::GetView() const +{ + return this->state.GetView(); +} + +Float4x4 SimpleRigidBody::GetView( const ::Oyster::Math::Float3 &offset ) const +{ + return this->state.GetView(offset); } void SimpleRigidBody::CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) @@ -112,22 +152,6 @@ btRigidBody* SimpleRigidBody::GetRigidBody() const return this->rigidBody; } -SimpleRigidBody::State SimpleRigidBody::GetState() const -{ - return this->state; -} - -SimpleRigidBody::State & SimpleRigidBody::GetState( SimpleRigidBody::State &targetMem ) const -{ - targetMem = this->state; - return targetMem; -} - -void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) -{ - this->state = state; -} - void * SimpleRigidBody::GetCustomTag() const { return this->customTag; diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index 25fecfad..caca6313 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -22,16 +22,19 @@ namespace Oyster void SetSubscription(EventAction_Move function); void SetLinearVelocity(Math::Float3 velocity); + void SetPosition(::Oyster::Math::Float3 position); void SetRotation(Math::Float4 quaternion); + void SetRotation(::Oyster::Math::Quaternion quaternion); void SetRotation(Math::Float3 eulerAngles); + Math::Float4x4 GetRotation() const; + Math::Float4x4 GetOrientation() const; + Math::Float4x4 GetView() const; + Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const; + void CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Math::Float kineticEnergyLoss); void CallSubscription_Move(); - State GetState() const; - State & GetState( State &targetMem ) const; - void SetState( const State &state ); - btCollisionShape* GetCollisionShape() const; btDefaultMotionState* GetMotionState() const; btRigidBody* GetRigidBody() const; diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 84f77b7d..608bf722 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -123,31 +123,21 @@ namespace Oyster virtual ~ICustomBody() {}; - /******************************************************** - * Gets the current state of the rigid body - * @return the current state of the rigid body - ********************************************************/ - virtual State GetState() const = 0; - - /******************************************************** - * Gets the current state of the rigid body - * @param targetMem: The state is copied into targetMem - * @return the current state of the rigid body - ********************************************************/ - virtual State & GetState( State &targetMem ) const = 0; - - /******************************************************** - * Sets the current state of the rigid body - ********************************************************/ - virtual void SetState( const State &state ) = 0; virtual void SetSubscription(EventAction_AfterCollisionResponse function) = 0; virtual void SetSubscription(EventAction_Move function) = 0; virtual void SetLinearVelocity(::Oyster::Math::Float3 velocity) = 0; + virtual void SetPosition(::Oyster::Math::Float3 position) = 0; virtual void SetRotation(::Oyster::Math::Float4 quaternion) = 0; + virtual void SetRotation(::Oyster::Math::Quaternion quaternion) = 0; virtual void SetRotation(::Oyster::Math::Float3 eulerAngles) = 0; + ::Oyster::Math::Float4x4 GetRotation() const; + ::Oyster::Math::Float4x4 GetOrientation() const; + ::Oyster::Math::Float4x4 GetView() const; + ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const; + /******************************************************** * @return the void pointer set by SetCustomTag. * nullptr if none is set. diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index f68491d5..4c4ae797 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -30,12 +30,6 @@ namespace Oyster ::Oyster::Math::Float4x4 GetOrientation() const; ::Oyster::Math::Float4x4 GetView() const; ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const; - - ::Oyster::Math::Float GetMass() const; - ::Oyster::Math::Float GetStaticFriction() const; - ::Oyster::Math::Float GetDynamicFriction() const; - ::Oyster::Math::Float GetRestitution() const; - // Variables for state ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, dynamicFrictionCoeff; From 55a2c6593ca57336f78a40348ed7c6751bb3b62a Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 14:50:40 +0100 Subject: [PATCH 28/35] Added states --- .../Implementation/SimpleRigidBody.cpp | 27 +++++++++++++++++++ .../Implementation/SimpleRigidBody.h | 4 +++ Code/GamePhysics/PhysicsAPI.h | 3 +++ 3 files changed, 34 insertions(+) diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index 0621c2c6..ab8925a8 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -38,6 +38,33 @@ SimpleRigidBody::~SimpleRigidBody() this->rigidBody = NULL; } +SimpleRigidBody::State SimpleRigidBody::GetState() const +{ + return this->state; +} + +SimpleRigidBody::State& SimpleRigidBody::GetState( SimpleRigidBody::State &targetMem ) const +{ + targetMem = this->state; + return targetMem; +} + +void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) +{ + btTransform trans; + this->motionState->getWorldTransform(trans); + trans.setRotation(btQuaternion(state.quaternion.imaginary.x, state.quaternion.imaginary.y, state.quaternion.imaginary.z, state.quaternion.real)); + trans.setOrigin(btVector3(state.centerPos.x, state.centerPos.y, state.centerPos.z)); + this->motionState->setWorldTransform(trans); + this->rigidBody->setFriction(state.staticFrictionCoeff); + this->rigidBody->setRestitution(state.restitutionCoeff); + btVector3 fallInertia(0, 0, 0); + collisionShape->calculateLocalInertia(state.mass, fallInertia); + this->rigidBody->setMassProps(state.mass, fallInertia); + + this->state = state; +} + void SimpleRigidBody::SetCollisionShape(btCollisionShape* shape) { this->collisionShape = shape; diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h index caca6313..55ae4fe3 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.h +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h @@ -14,6 +14,10 @@ namespace Oyster SimpleRigidBody(); virtual ~SimpleRigidBody(); + State GetState() const; + State& GetState( State &targetMem ) const; + void SetState( const State &state ); + void SetCollisionShape(btCollisionShape* shape); void SetMotionState(btDefaultMotionState* motionState); void SetRigidBody(btRigidBody* rigidBody); diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h index 608bf722..f57fe130 100644 --- a/Code/GamePhysics/PhysicsAPI.h +++ b/Code/GamePhysics/PhysicsAPI.h @@ -123,6 +123,9 @@ namespace Oyster virtual ~ICustomBody() {}; + virtual State GetState() const = 0; + virtual State & GetState( State &targetMem ) const = 0; + virtual void SetState( const State &state ) = 0; virtual void SetSubscription(EventAction_AfterCollisionResponse function) = 0; virtual void SetSubscription(EventAction_Move function) = 0; From c75493b6ce00d13f9102ef951476f21d27c4470b Mon Sep 17 00:00:00 2001 From: Sam Mario Svensson Date: Mon, 10 Feb 2014 14:58:39 +0100 Subject: [PATCH 29/35] GL - Levelformat updated 3.0 with new format! --- .../GameLogic/LevelLoader/LevelParser.cpp | 1 + .../GameLogic/LevelLoader/ObjectDefines.h | 30 ++++++---------- .../GameLogic/LevelLoader/ParseFunctions.cpp | 35 +++++++++---------- 3 files changed, 28 insertions(+), 38 deletions(-) diff --git a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp index 33567cc9..a6f806e8 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp +++ b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp @@ -123,6 +123,7 @@ std::vector> LevelParser::Parse(std::string filen break; } + default: //Couldn't find specialType break; diff --git a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h index d87e42b2..46cb2465 100644 --- a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h +++ b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h @@ -138,14 +138,18 @@ namespace GameLogic struct BoundingVolumeBase { + CollisionGeometryType geoType; float position[3]; + float rotation[4]; + float frictionCoeffStatic; + float frictionCoeffDynamic; + float restitutionCoeff; + float mass; }; struct BoundingVolumeBox : public BoundingVolumeBase { float size[3]; - float angularAxis[3]; - float angle; }; struct BoundingVolumeSphere : public BoundingVolumeBase @@ -156,8 +160,6 @@ namespace GameLogic struct BoundingVolumeCylinder : public BoundingVolumeBase { float length; - float angularAxis[3]; - float angle; float radius; }; @@ -172,17 +174,6 @@ namespace GameLogic }; }; - struct PhysicsObject - { - UsePhysics usePhysics; - float mass; - float inertiaMagnitude[3]; - float inertiaRotation[3]; - float frictionCoeffStatic; - float frictionCoeffDynamic; - float restitutionCoeff; - BoundingVolume boundingVolume; - }; } struct LevelMetaData : public ObjectTypeHeader @@ -200,7 +191,7 @@ namespace GameLogic }; - struct ObjectHeader : public ObjectTypeHeader, public LevelLoaderInternal::PhysicsObject + struct ObjectHeader : public ObjectTypeHeader { //Special type id for special objects: portal, jumppad, exploding objects, etc. ObjectSpecialType specialTypeID; @@ -208,12 +199,13 @@ namespace GameLogic std::string ModelFile; //Position float position[3]; - //Rotation - float rotation[3]; - float angle; + //Rotation Quaternion + float rotation[4]; //Scale float scale[3]; + ::GameLogic::LevelLoaderInternal::BoundingVolume boundingVolume; + virtual ~ObjectHeader(){} }; diff --git a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp index e8c055b3..722bd609 100644 --- a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp +++ b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp @@ -44,11 +44,6 @@ namespace GameLogic //3 float[3], 1 float memcpy(&header.position, &buffer[start], 40); start += 40; - - //Physics struct - //2 float[3], 4 float, 1 uint - memcpy(&header.usePhysics, &buffer[start], 44); - start += 44; //Read path for bounding volume ParseBoundingVolume(&buffer[start], header.boundingVolume, start); @@ -122,7 +117,7 @@ namespace GameLogic int start = 0; int tempSize = 0; char tempName[128]; - + memcpy(&tempSize, &buffer[start], 4); start += 4; @@ -132,39 +127,41 @@ namespace GameLogic fileName.assign(&tempName[0], &tempName[tempSize]); start += tempSize; + size += start; + //Läs in filen. int fileLength = 0; Loader loader; char* buf = loader.LoadFile("E:\\Dropbox\\Programming\\Github\\Danbias\\Bin\\Content\\Worlds\\cgf\\"+ fileName, fileLength); - - LevelLoaderInternal::FormatVersion version; - memcpy(&version, &buffer[0], sizeof(version)); - memcpy(&volume.geoType, &buf[8], sizeof(volume.geoType)); - //start += sizeof(volume.geoType); + start = 0; + LevelLoaderInternal::FormatVersion version; + memcpy(&version, &buf[0], sizeof(version)); + start += 4; + + memcpy(&volume.geoType, &buf[start], sizeof(volume.geoType)); + start += sizeof(volume.geoType); switch(volume.geoType) { case CollisionGeometryType_Box: - memcpy(&volume.box, &buf[12], sizeof(volume.box)); - //start += sizeof(volume.box); + memcpy(&volume.box, &buf[start], sizeof(volume.box)); + start += sizeof(volume.box); break; case CollisionGeometryType_Sphere: - memcpy(&volume.sphere, &buf[12], sizeof(volume.sphere)); - //start += sizeof(volume.sphere); + memcpy(&volume.sphere, &buf[start], sizeof(volume.sphere)); + start += sizeof(volume.sphere); break; case CollisionGeometryType_Cylinder: - memcpy(&volume.cylinder, &buf[12], sizeof(volume.cylinder)); - //start += sizeof(volume.cylinder); + memcpy(&volume.cylinder, &buf[start], sizeof(volume.cylinder)); + start += sizeof(volume.cylinder); break; default: break; } - - size += start; } } } \ No newline at end of file From 26e151f9b4fe01fd3d6f11d75f876fc194af2421 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Mon, 10 Feb 2014 15:46:55 +0100 Subject: [PATCH 30/35] Fixed state problem --- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Level.cpp | 4 +-- Code/Game/GameLogic/Object.cpp | 7 ++--- .../Implementation/PhysicsAPI_Impl.cpp | 30 +++++++++++++++++++ .../Implementation/SimpleRigidBody.cpp | 8 +++-- Code/GamePhysics/PhysicsStructs.h | 2 +- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 0cb4e4bd..5b99b1ee 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -15,7 +15,7 @@ Game::PlayerData::PlayerData() //sbDesc.quaternion = Oyster::Math::Float3(0, Oyster::Math::pi, 0); //create rigid body - Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass); + Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass, 1, 1, 1); //create player with this rigid body this->player = new Player(rigidBody,Player::DefaultCollisionAfter, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index 364972df..d39800ac 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -55,7 +55,7 @@ void Level::InitiateLevel(float radius) int idCount = 100; // add level sphere - ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 1, 1, 1); ICustomBody::State state; rigidBody->GetState(state); @@ -72,7 +72,7 @@ void Level::InitiateLevel(float radius) int offset = 0; for(int i =0; i< nrOfBoxex; i ++) { - rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5, 1, 1, 1); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); this->dynamicObjects[i]->objectID = idCount++; diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index f099be18..ded2148f 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -16,7 +16,7 @@ const Game *Object::gameInstance = (Game*)(&Game::Instance()); Object::Object() { - this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 1, 1, 1); this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN; this->objectID = GID(); @@ -26,7 +26,7 @@ Object::Object() Object::Object(OBJECT_TYPE type) { - this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 1, 1, 1); this->type = type; this->objectID = GID(); this->currPhysicsState = this->rigidBody->GetState(); @@ -44,7 +44,7 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) { - this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 1, 1, 1); this->type = type; this->objectID = GID(); @@ -101,7 +101,6 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { - this->rigidBody->SetState(this->newPhysicsState); } // update physic diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp index 7f3a53a7..9026a60f 100644 --- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp +++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp @@ -50,6 +50,7 @@ API_Impl::~API_Impl() ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) { SimpleRigidBody* body = new SimpleRigidBody; + SimpleRigidBody::State state; // Add collision shape btCollisionShape* collisionShape = new btSphereShape(radius); @@ -73,12 +74,22 @@ ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 r this->dynamicsWorld->addRigidBody(rigidBody); this->customBodies.push_back(body); + state.centerPos = position; + state.reach = Float3(radius, radius, radius); + state.dynamicFrictionCoeff = 0.5f; + state.staticFrictionCoeff = 0.5f; + state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w); + state.mass = mass; + + body->SetState(state); + return body; } ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) { SimpleRigidBody* body = new SimpleRigidBody; + SimpleRigidBody::State state; // Add collision shape btCollisionShape* collisionShape = new btBoxShape(btVector3(halfSize.x, halfSize.y, halfSize.z)); @@ -102,12 +113,22 @@ ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 r this->dynamicsWorld->addRigidBody(rigidBody); this->customBodies.push_back(body); + state.centerPos = position; + state.reach = halfSize; + state.dynamicFrictionCoeff = 0.5f; + state.staticFrictionCoeff = 0.5f; + state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w); + state.mass = mass; + + body->SetState(state); + return body; } ICustomBody* API_Impl::AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) { SimpleRigidBody* body = new SimpleRigidBody; + SimpleRigidBody::State state; // Add collision shape btCollisionShape* collisionShape = new btCylinderShape(btVector3(halfSize.x, halfSize.y, halfSize.z)); @@ -131,6 +152,15 @@ ICustomBody* API_Impl::AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::O this->dynamicsWorld->addRigidBody(rigidBody); this->customBodies.push_back(body); + state.centerPos = position; + state.reach = halfSize; + state.dynamicFrictionCoeff = 0.5f; + state.staticFrictionCoeff = 0.5f; + state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w); + state.mass = mass; + + body->SetState(state); + return body; } diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp index ab8925a8..879ff8bc 100644 --- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp +++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp @@ -52,9 +52,11 @@ SimpleRigidBody::State& SimpleRigidBody::GetState( SimpleRigidBody::State &targe void SimpleRigidBody::SetState( const SimpleRigidBody::State &state ) { btTransform trans; + btVector3 position(state.centerPos.x, state.centerPos.y, state.centerPos.z); + btQuaternion quaternion(state.quaternion.imaginary.x, state.quaternion.imaginary.y, state.quaternion.imaginary.z, state.quaternion.real); this->motionState->getWorldTransform(trans); - trans.setRotation(btQuaternion(state.quaternion.imaginary.x, state.quaternion.imaginary.y, state.quaternion.imaginary.z, state.quaternion.real)); - trans.setOrigin(btVector3(state.centerPos.x, state.centerPos.y, state.centerPos.z)); + trans.setRotation(quaternion); + trans.setOrigin(position); this->motionState->setWorldTransform(trans); this->rigidBody->setFriction(state.staticFrictionCoeff); this->rigidBody->setRestitution(state.restitutionCoeff); @@ -154,7 +156,7 @@ Float4x4 SimpleRigidBody::GetView( const ::Oyster::Math::Float3 &offset ) const void SimpleRigidBody::CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss) { - if(this->onMovement) + if(this->afterCollision) this->afterCollision(bodyA, bodyB, kineticEnergyLoss); } diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h index 4c4ae797..fa6c023c 100644 --- a/Code/GamePhysics/PhysicsStructs.h +++ b/Code/GamePhysics/PhysicsStructs.h @@ -16,7 +16,7 @@ namespace Oyster public: // Default constructor CustomBodyState( ::Oyster::Math::Float mass = 1.0f, - ::Oyster::Math::Float restitutionCoeff = 1.0f, + ::Oyster::Math::Float restitutionCoeff = 0.5f, ::Oyster::Math::Float staticFrictionCoeff = 1.0f, ::Oyster::Math::Float dynamicFrictionCoeff = 1.0f, const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null, From b731c206f4d4590c8d148588e661d9bed47446e3 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Mon, 10 Feb 2014 15:54:38 +0100 Subject: [PATCH 31/35] GL - physics merge 2 --- .../Game/DanBiasGame/GameClientState/GameState.cpp | 14 +++++++------- Code/Game/GameLogic/Game.cpp | 4 ++-- Code/Game/GameLogic/Game_PlayerData.cpp | 10 +++++----- Code/Game/GameLogic/Level.cpp | 9 ++------- Code/Game/GameLogic/Object.cpp | 6 +++--- Code/Game/GameLogic/Player.cpp | 7 ++++--- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index abc0e96e..9a14fa25 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -311,9 +311,9 @@ void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Flo C_Object* obj; modelData.visible = true; //modelData.world = world; - //modelData.position = ; - //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1); - //modelData.scale = Oyster::Math::Float3(2,2,2); + modelData.position = Oyster::Math::Float3(world[12], world[13], world[14]); + modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1); + modelData.scale = Oyster::Math::Float3(2,2,2); modelData.modelPath = modelName; modelData.id = myId; @@ -612,15 +612,15 @@ void GameState::Protocol( ObjPos* pos ) Oyster::Math::Float3 newLook = up.Cross(right); newLook.Normalize();*/ - camera->setRight(right); - camera->setUp(up); + //camera->setRight(right); + //camera->setUp(up); //camera->setLook(objForward); up *= 1; objForward *= -2; Oyster::Math::Float3 cameraPos = pos + up + objForward; - camera->SetPosition(cameraPos); - camera->UpdateViewMatrix(); + //camera->SetPosition(cameraPos); + //camera->UpdateViewMatrix(); } } diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp index ab10fcd2..c78abb09 100644 --- a/Code/Game/GameLogic/Game.cpp +++ b/Code/Game/GameLogic/Game.cpp @@ -81,8 +81,8 @@ Game::LevelData* Game::CreateLevel() if(this->level) return this->level; this->level = new LevelData(); - //this->level->level->InitiateLevel(1000); - this->level->level->InitiateLevel("3bana.bias"); + this->level->level->InitiateLevel(1000); + //this->level->level->InitiateLevel("3bana.bias"); return this->level; } diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index d598c27e..25fd51c1 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -15,16 +15,16 @@ Game::PlayerData::PlayerData() //sbDesc.quaternion = Oyster::Math::Float3(0, Oyster::Math::pi, 0); //create rigid body - Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass); + Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass, 0.5f, 0.8f, 0.6f ); //create player with this rigid body this->player = new Player(rigidBody,Level::LevelCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER); this->player->GetRigidBody()->SetCustomTag(this); - Oyster::Physics::ICustomBody::State state; - this->player->GetRigidBody()->GetState(state); - //state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0)); - this->player->GetRigidBody()->SetState(state); + //Oyster::Physics::ICustomBody::State state; + //this->player->GetRigidBody()->GetState(state); + ////state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0)); + //this->player->GetRigidBody()->SetState(state); player->EndFrame(); } Game::PlayerData::PlayerData(int playerID,int teamID) diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index bff1d5c3..0e96be28 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -230,12 +230,7 @@ void Level::InitiateLevel(float radius) int idCount = 100; // add level sphere - ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); - - ICustomBody::State state; - rigidBody->GetState(state); - state.restitutionCoeff = 0.2f; - rigidBody->SetState(state); + ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD); this->levelObj->objectID = idCount++; rigidBody->SetCustomTag(levelObj); @@ -247,7 +242,7 @@ void Level::InitiateLevel(float radius) int offset = 0; for(int i =0; i< nrOfBoxex; i ++) { - rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5); + rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5, 0.5f, 0.8f, 0.6f); this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); this->dynamicObjects[i]->objectID = idCount++; diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index f099be18..77c256eb 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -16,7 +16,7 @@ const Game *Object::gameInstance = (Game*)(&Game::Instance()); Object::Object() { - this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN; this->objectID = GID(); @@ -26,7 +26,7 @@ Object::Object() Object::Object(OBJECT_TYPE type) { - this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); this->type = type; this->objectID = GID(); this->currPhysicsState = this->rigidBody->GetState(); @@ -44,7 +44,7 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) { - this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0); + this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); this->type = type; this->objectID = GID(); diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index f407d8f0..de45f8cb 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -109,6 +109,7 @@ void Player::MoveForward() Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; //newPhysicsState.ApplyLinearImpulse(forward * (MOVE_FORCE * this->gameInstance->GetFrameTime())); + //rigidBody->SetLinearVelocity( 10 * this->gameInstance->GetFrameTime() ); } void Player::MoveBackwards() { @@ -120,10 +121,10 @@ void Player::MoveRight() { //Do cross product with forward vector and negative gravity vector Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + //Oyster::Math::Float3 forward = lookDir; - //Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); - //newPhysicsState.ApplyLinearImpulse(-r * MOVE_FORCE * this->gameInstance->GetFrameTime()); - + Oyster::Math::Float3 r = (-currPhysicsState.centerPos.Normalize()).Cross(forward); + //rigidBody->SetLinearVelocity(-r * 10 * this->gameInstance->GetFrameTime() ); } void Player::MoveLeft() { From 26755f8b0b81465d3e81fc3cd4764d3b53c56cac Mon Sep 17 00:00:00 2001 From: Sam Mario Svensson Date: Mon, 10 Feb 2014 16:24:05 +0100 Subject: [PATCH 32/35] GL- level format more updates.... --- .../GameLogic/LevelLoader/LevelLoader.cpp | 23 ++++++++++++++++--- Code/Game/GameLogic/LevelLoader/LevelLoader.h | 18 +++++++++++++-- .../GameLogic/LevelLoader/LevelParser.cpp | 23 +++++++++++-------- .../GameLogic/LevelLoader/ObjectDefines.h | 16 +++++++++---- .../GameLogic/LevelLoader/ParseFunctions.cpp | 1 + 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp b/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp index 55a39725..8fe880f3 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp +++ b/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp @@ -17,7 +17,14 @@ struct LevelLoader::PrivData LevelLoader::LevelLoader() : pData(new PrivData) { - pData->folderPath = "Standard path"; + //standard path + pData->folderPath = ""; +} + +LevelLoader::LevelLoader(std::string folderPath) + : pData(new PrivData) +{ + pData->folderPath = folderPath; } LevelLoader::~LevelLoader() @@ -26,10 +33,20 @@ LevelLoader::~LevelLoader() std::vector> LevelLoader::LoadLevel(std::string fileName) { - return pData->parser.Parse(fileName); + return pData->parser.Parse(pData->folderPath + fileName); } LevelMetaData LevelLoader::LoadLevelHeader(std::string fileName) { - return pData->parser.ParseHeader(fileName); + return pData->parser.ParseHeader(pData->folderPath + fileName); +} + +std::string LevelLoader::GetFolderPath() +{ + return this->pData->folderPath; +} + +void LevelLoader::SetFolderPath(std::string folderPath) +{ + } \ No newline at end of file diff --git a/Code/Game/GameLogic/LevelLoader/LevelLoader.h b/Code/Game/GameLogic/LevelLoader/LevelLoader.h index bcd6e587..184a7005 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelLoader.h +++ b/Code/Game/GameLogic/LevelLoader/LevelLoader.h @@ -17,11 +17,15 @@ namespace GameLogic public: LevelLoader(); + /*********************************************************** + * Lets you set the standard folderpath for the levels + ********************************************************/ + LevelLoader(std::string folderPath); ~LevelLoader(); /******************************************************** * Loads the level and objects from file. - * @param fileName: Path to the level-file that you want to load. + * @param fileName: Path/name to the level-file that you want to load. * @return: Returns all structs with objects and information about the level. ********************************************************/ std::vector> LoadLevel(std::string fileName); @@ -33,10 +37,20 @@ namespace GameLogic ********************************************************/ LevelMetaData LoadLevelHeader(std::string fileName); //. + /*********************************************************** + * @return: Returns the current standard folder path + ********************************************************/ + std::string GetFolderPath(); + + /*********************************************************** + * Sets the standard folder path + ********************************************************/ + void SetFolderPath(std::string folderPath); + private: struct PrivData; Utility::DynamicMemory::SmartPointer pData; - }; + }; } #endif \ No newline at end of file diff --git a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp index a6f806e8..f66fbe08 100644 --- a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp +++ b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp @@ -13,7 +13,7 @@ using namespace Utility::DynamicMemory; LevelParser::LevelParser() { - formatVersion.formatVersionMajor = 2; + formatVersion.formatVersionMajor = 3; formatVersion.formatVersionMinor = 0; } @@ -71,7 +71,6 @@ std::vector> LevelParser::Parse(std::string filen { //These three does not have any specail variables at this time. //There for they are using the same 'parser'. - case ObjectSpecialType_World: case ObjectSpecialType_Building: case ObjectSpecialType_Damaging: case ObjectSpecialType_Explosive: @@ -113,17 +112,26 @@ std::vector> LevelParser::Parse(std::string filen break; } - case ObjectSpecialType_SpawnPoint: + + case ObjectSpecialType_World: { - SpawnPointAttributes* header = new SpawnPointAttributes; + WorldAttributes* header = new WorldAttributes; ParseObject(&buffer[counter], *header, counter); - ParseObject(&buffer[counter], header->spawnPosition, 12); + ParseObject(&buffer[counter], &header->worldSize, 8); objects.push_back(header); - break; } + case ObjectSpecialType_Sky: + { + SkyAttributes* header = new SkyAttributes; + ParseObject(&buffer[counter], *header, counter); + + ParseObject(&buffer[counter], &header->skySize, 4); + objects.push_back(header); + break; + } default: //Couldn't find specialType break; @@ -240,9 +248,6 @@ LevelMetaData LevelParser::ParseHeader(std::string filename) case ObjectSpecialType_Portal: counter += sizeof(12); break; - case ObjectSpecialType_SpawnPoint: - counter += sizeof(12); - break; default: break; } diff --git a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h index 46cb2465..05d09714 100644 --- a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h +++ b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h @@ -32,7 +32,7 @@ namespace GameLogic ObjectSpecialType_JumpPad, ObjectSpecialType_BoostPad, ObjectSpecialType_Portal, - ObjectSpecialType_SpawnPoint, + ObjectSpecialType_Sky, ObjectSpecialType_Count, ObjectSpecialType_Unknown = -1 @@ -134,7 +134,7 @@ namespace GameLogic namespace LevelLoaderInternal { - const FormatVersion boundingVolumeVersion(1, 0); + const FormatVersion boundingVolumeVersion(2, 0); struct BoundingVolumeBase { @@ -224,11 +224,19 @@ namespace GameLogic float destination[3]; }; - struct SpawnPointAttributes : public ObjectHeader + struct WorldAttributes : public ObjectHeader { - float spawnPosition[3]; + float worldSize; + float atmoSphereSize; }; + struct SkyAttributes : public ObjectHeader + { + float skySize; + }; + + + /************************************ Lights *************************************/ diff --git a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp index 722bd609..d917a146 100644 --- a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp +++ b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp @@ -16,6 +16,7 @@ namespace GameLogic { namespace LevelFileLoader { + //can parse any struct without strings or char[] void ParseObject(char* buffer, void *header, int size) { memcpy(header, buffer, size); From 9a82b7002055cc769e30e934daa363eadcf050d9 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Tue, 11 Feb 2014 09:16:01 +0100 Subject: [PATCH 33/35] Misc - Button system working. (Logic) --- Code/Misc/EventHandler/EventButton.h | 273 +++++++++++++----- Code/Misc/EventHandler/EventButtonCircle.h | 64 ++++ .../EventHandler/EventButtonCollection.cpp | 16 +- .../Misc/EventHandler/EventButtonCollection.h | 25 +- Code/Misc/EventHandler/EventButtonRectangle.h | 60 ++++ Code/Misc/EventHandler/EventHandler.cpp | 17 +- Code/Misc/EventHandler/EventHandler.h | 10 +- Code/Misc/EventHandler/IEventButton.h | 32 +- Code/Misc/Misc.vcxproj | 2 + Code/Misc/Misc.vcxproj.filters | 6 + 10 files changed, 399 insertions(+), 106 deletions(-) create mode 100644 Code/Misc/EventHandler/EventButtonCircle.h create mode 100644 Code/Misc/EventHandler/EventButtonRectangle.h diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h index e8fbc690..64215da2 100644 --- a/Code/Misc/EventHandler/EventButton.h +++ b/Code/Misc/EventHandler/EventButton.h @@ -4,125 +4,256 @@ #ifndef MISC_EVENT_BUTTON_H #define MISC_EVENT_BUTTON_H -#include "../../Input/L_inputClass.h" + +#include "IEventButton.h" namespace Oyster { namespace Event { - template - class EventButton + template + struct ButtonEvent { - public: - struct ButtonEvent - { - IEventButton::ButtonState state; - EventButton &sender; - owner owner; - }; + ButtonState state; + IEventButton* sender; + Owner owner; + void* userData; + }; + + template + class EventButton : public IEventButton + { + protected: + //typedef for callback function pointer + typedef void (*EventFunc)(Oyster::Event::ButtonEvent& e); struct PrivData { + PrivData() : ID(currID++){} + static unsigned int currID; - unsigned int ID; + const unsigned int ID; - owner owner; - void (*EventFunc)( ButtonEvent e ); + ButtonState previousState; + Owner owner; + EventFunc eventCallback; + void* userData; + bool enabled; }; - + + PrivData privData; + private: + //Implement this in the inherited classes for collision against that shape. + virtual bool Collision(InputClass *input) = 0; + public: EventButton(); - EventButton(owner owner); - EventButton(void (*EventFunc)( ButtonEvent e)); - EventButton(void (*EventFunc)( ButtonEvent e), owner owner); - + EventButton(Owner owner); + EventButton(EventFunc func); + EventButton(EventFunc func, Owner owner); + EventButton(EventFunc func, Owner owner, void* userData); ~EventButton(); - - void CheckCollision(InputClass *input); - void SendEvent(IEventButton::ButtonState state); + void Update(InputClass *input); - void SetEventFunc(void (*EventFunc)( ButtonEvent e )); //? + //Send event to callback function + void SendEvent(ButtonState state); + //Set + void SetUserData(void* data); + void SetEventFunc(EventFunc func); + void SetOwner(Owner owner); + + //Get + bool Enabled(); unsigned int GetID(); - + //EventFunc GetFunctionPointer(); + Owner GetOwner(); + + bool operator ==(const EventButton& obj); + }; - template - unsigned int EventButton::PrivData::currID = 0; + template + unsigned int EventButton::PrivData::currID = 0; - template - EventButton::EventButton() + template + EventButton::EventButton() { - this->privData.ID = privData.currID; - this->privData.currID += 1; - //this->privData.owner = NULL; - this->privData.EventFunc = NULL; + this->privData.eventCallback = NULL; + this->privData.userData = NULL; + this->privData.previousState = ButtonState_None; + this->privData.enabled = true; } - template - EventButton::EventButton(owner owner) + template + EventButton::EventButton(Owner owner) { - this->privData.ID = privData.currID; - this->privData.currID += 1; this->privData.owner = owner; - this->privData.EventFunc = NULL; + this->privData.eventCallback = NULL; + this->privData.userData = NULL; + this->privData.previousState = ButtonState_None; + this->privData.enabled = true; } - template - EventButton::EventButton(void (*EventFunc)( ButtonEvent e)) + template + EventButton::EventButton(EventFunc func) { - this->privData.ID = privData.currID; - this->privData.currID += 1; - //this->privData.owner = NULL; - this->privData.EventFunc = EventFunc; + this->privData.eventCallback = func; + this->privData.userData = NULL; + this->privData.previousState = ButtonState_None; + this->privData.enabled = true; } - template - EventButton::EventButton(void (*EventFunc)( ButtonEvent e), owner owner) + template + EventButton::EventButton(EventFunc func, Owner owner) { - this->privData.ID = privData.currID; - this->privData.currID += 1; this->privData.owner = owner; + this->privData.eventCallback = func; + this->privData.userData = NULL; + this->privData.previousState = ButtonState_None; + this->privData.enabled = true; + } + + template + EventButton::EventButton(EventFunc func, Owner owner, void* userData) + { + this->privData.owner = owner; + this->privData.eventCallback = func; + this->privData.userData = userData; + this->privData.previousState = ButtonState_None; + this->privData.enabled = true; + } + + template + EventButton::~EventButton() + {} + + //Checks for collision and + template + void EventButton::Update(InputClass *input) + { + if(this->privData.enabled) + { + ButtonState currentState = ButtonState_None; + + if(Collision(input)) + { + if(input->IsMousePressed()) + { + //Change state when the mouse button is pressed + switch(this->privData.previousState) + { + case ButtonState_None: + currentState = ButtonState_Hover; + break; + + case ButtonState_Hover: + case ButtonState_Released: + currentState = ButtonState_Pressed; + break; + + case ButtonState_Pressed: + case ButtonState_Down: + currentState = ButtonState_Down; + break; + default: + break; + } + } + else + { + //Change state when the mouse button is NOT pressed + switch(this->privData.previousState) + { + case ButtonState_None: + case ButtonState_Hover: + case ButtonState_Released: + currentState = ButtonState_Hover; + break; + + case ButtonState_Pressed: + case ButtonState_Down: + currentState = ButtonState_Released; + break; + default: + break; + } + } + } + + //Only call the callback function when the state has changed. + if(this->privData.previousState != currentState) + SendEvent(currentState); + + this->privData.previousState = currentState; + } + } + + template + void EventButton::SendEvent(ButtonState state) + { + if(privData.eventCallback != NULL) + { + Oyster::Event::ButtonEvent event; + event.state = state; + event.sender = this; + event.owner = privData.owner; + event.userData = privData.userData; + privData.eventCallback(event); + } + } + + template + void EventButton::SetUserData(void* data) + { + this->privData.userData = data; + } + + template + void EventButton::SetEventFunc(EventFunc func) + { this->privData.EventFunc = EventFunc; } - template - EventButton::~EventButton() + template + void EventButton::SetOwner(Owner owner) { - + this->privData.owner = owner; } - template - void EventButton::CheckCollision(InputClass *input) + template + bool EventButton::Enabled() { - //??????????????? TODO: everything - SendEvent(Button_Smashed); - } - - template - void EventButton::SendEvent(IEventButton::ButtonState state) - { - ButtonEvent event; - event.state = state; - event.sender = this; - event.owner = privData.owner; - privData.EventFunc(event); + return this->privData.enabled; } - template - void EventButton::SetEventFunc(void (*EventFunc)( ButtonEvent e )) - { - this->privData.EventFunc = EventFunc; - } - - template - unsigned int EventButton::GetID() + template + unsigned int EventButton::GetID() { return this->privData.ID; } + + /* Something is wrong, can't return EventFunc + template + EventFunc EventButton::GetFunctionPointer() + { + return this->privData.eventCallback; + }*/ + + template + Owner EventButton::GetOwner() + { + return this->privData.owner; + } + + template + bool EventButton::operator ==(const EventButton& obj) + { + return (this->privData.ID == obj.privData.ID); + } } } diff --git a/Code/Misc/EventHandler/EventButtonCircle.h b/Code/Misc/EventHandler/EventButtonCircle.h new file mode 100644 index 00000000..3a298acb --- /dev/null +++ b/Code/Misc/EventHandler/EventButtonCircle.h @@ -0,0 +1,64 @@ +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + +#ifndef MISC_EVENT_BUTTON_CIRCLE_H +#define MISC_EVENT_BUTTON_CIRCLE_H + +#include "EventButton.h" +#include "../../Input/L_inputClass.h" + +namespace Oyster +{ + namespace Event + { + template + class EventButtonCircle : public EventButton + { + public: + EventButtonCircle() + : EventButton(), xPos(0), yPos(0), radius(0) + {} + EventButtonCircle(Owner owner, float xPos, float yPos, float radius) + : EventButton(owner), xPos(xPos), yPos(yPos), radius(radius) + {} + EventButtonCircle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), float xPos, float yPos, float radius) + : EventButton(EventFunc), xPos(xPos), yPos(yPos), radius(radius) + {} + EventButtonCircle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, float xPos, float yPos, float radius) + : EventButton(EventFunc, owner), xPos(xPos), yPos(yPos), radius(radius) + {} + EventButtonCircle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, void* userData, float xPos, float yPos, float radius) + : EventButton(EventFunc, owner, userData), xPos(xPos), yPos(yPos), radius(radius) + {} + ~EventButtonCircle() + {} + + //Circle vs point collision + bool Collision(InputClass* inputObject) + { + //Should come from the InputClass + float xMouse = 2, yMouse = 2; + + float xDiff = xMouse - xPos; + float yDiff = yMouse - yPos; + + float length = (xDiff * xDiff) + (yDiff * yDiff); + + if(length <= radius*radius) + { + return true; + } + + return false; + } + + private: + float xPos, yPos; + float radius; + + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp index 7908816e..6a77c520 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.cpp +++ b/Code/Misc/EventHandler/EventButtonCollection.cpp @@ -1,5 +1,11 @@ +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + #include "EventButtonCollection.h" +#include "../../Input/L_inputClass.h" + using namespace Oyster::Event; EventButtonCollection::EventButtonCollection() @@ -9,15 +15,21 @@ EventButtonCollection::EventButtonCollection() EventButtonCollection::~EventButtonCollection() { + int size = buttons.size(); + for(int i = 0; i < size; i++) + { + delete buttons[i]; + buttons[i] = NULL; + } } void EventButtonCollection::Update(InputClass* inputObject) { if(this->collectionState == EventCollectionState_Enabled) { - for(int i = 0; i < buttons.size(); i++) + for(int i = 0; i < (int)buttons.size(); i++) { - buttons.at(i)->CheckCollision(inputObject); + buttons[i]->Update(inputObject); } } } diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h index 130d59fa..0cc77b42 100644 --- a/Code/Misc/EventHandler/EventButtonCollection.h +++ b/Code/Misc/EventHandler/EventButtonCollection.h @@ -1,8 +1,14 @@ -#ifndef EVENT_BUTTON_COLLECTION_H -#define EVENT_BUTTON_COLLECTION_H +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + +#ifndef MISC_EVENT_BUTTON_COLLECTION_H +#define MISC_EVENT_BUTTON_COLLECTION_H #include "../../Input/L_inputClass.h" +#include "../DynamicArray.h" + #include "IEventButton.h" #include "EventButton.h" @@ -30,20 +36,9 @@ namespace Oyster void Update(InputClass* inputObject); template - void AddButton(EventButton& button) + void AddButton(EventButton* button) { - EventButton* b = new EventButton(); - buttons.size(); - buttons.push_back((IEventButton*)b); - //buttons.push_back((IEventButton*)&button); - } - - template - EventButton& CreateButton() - { - EventButton temp; - buttons.push_back(&temp); - return temp; + buttons.push_back(button); } EventCollectionState GetState() const; diff --git a/Code/Misc/EventHandler/EventButtonRectangle.h b/Code/Misc/EventHandler/EventButtonRectangle.h new file mode 100644 index 00000000..fc917437 --- /dev/null +++ b/Code/Misc/EventHandler/EventButtonRectangle.h @@ -0,0 +1,60 @@ +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + +#ifndef MISC_EVENT_BUTTON_RECTANGLE_H +#define MISC_EVENT_BUTTON_RECTANGLE_H + +#include "EventButton.h" +#include "../../Input/L_inputClass.h" + +namespace Oyster +{ + namespace Event + { + template + class EventButtonRectangle : public EventButton + { + public: + EventButtonRectangle() + : EventButton(), xPos(0), yPos(0), halfWidth(0), halfHeight(0) + {} + EventButtonRectangle(Owner owner, float xPos, float yPos, float halfWidth, float halfHeight) + : EventButton(owner), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight) + {} + EventButtonRectangle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), float xPos, float yPos, float halfWidth, float halfHeight) + : EventButton(EventFunc), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight) + {} + EventButtonRectangle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, float xPos, float yPos, float halfWidth, float halfHeight) + : EventButton(EventFunc, owner), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight) + {} + EventButtonRectangle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, void* userData, float xPos, float yPos, float halfWidth, float halfHeight) + : EventButton(EventFunc, owner, userData), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight) + {} + ~EventButtonRectangle() + {} + + //Circle vs point collision + bool Collision(InputClass* inputObject) + { + //Should come from the InputClass + float xMouse = 1, yMouse = 0; + + if(xMouse >= xPos - halfWidth && xMouse <= xPos + halfWidth + && yMouse >= yPos - halfHeight && yMouse <= yPos + halfHeight) + { + return true; + } + + return false; + } + + private: + float xPos, yPos; + float halfWidth, halfHeight; + + }; + } +} + +#endif \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp index 0d270997..a7347075 100644 --- a/Code/Misc/EventHandler/EventHandler.cpp +++ b/Code/Misc/EventHandler/EventHandler.cpp @@ -1,3 +1,7 @@ +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + #include "EventHandler.h" using namespace Oyster::Event; @@ -15,11 +19,16 @@ EventHandler::EventHandler() EventHandler::~EventHandler() { + int size = collections.size(); + for(int i = 0; i < size; i++) + { + delete collections[i]; + } } void EventHandler::Update(InputClass* inputObject) { - for(int i = 0; i < collections.size(); i++) + for(int i = 0; i < (int)collections.size(); i++) { collections.at(i)->Update(inputObject); } @@ -32,7 +41,7 @@ void EventHandler::AddCollection(EventButtonCollection& collection) EventButtonCollection& EventHandler::CreateCollection() { - EventButtonCollection temp; - collections.push_back(&temp); - return temp; + EventButtonCollection* temp = new EventButtonCollection; + collections.push_back(temp); + return *temp; } \ No newline at end of file diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h index 7fb86b13..4ca1a9ab 100644 --- a/Code/Misc/EventHandler/EventHandler.h +++ b/Code/Misc/EventHandler/EventHandler.h @@ -1,10 +1,16 @@ -#ifndef EVENT_HANDLER_H -#define EVENT_HANDLER_H +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + +#ifndef MISC_EVENT_HANDLER_H +#define MISC_EVENT_HANDLER_H #include "../../Input/L_inputClass.h" #include "EventButtonCollection.h" #include "EventButton.h" +#include "EventButtonCircle.h" +#include "EventButtonRectangle.h" #include diff --git a/Code/Misc/EventHandler/IEventButton.h b/Code/Misc/EventHandler/IEventButton.h index 92c58c10..901a8265 100644 --- a/Code/Misc/EventHandler/IEventButton.h +++ b/Code/Misc/EventHandler/IEventButton.h @@ -1,30 +1,38 @@ +////////////////////////////////////// +// Created by Pontus Fransson 2014 // +////////////////////////////////////// + #ifndef MISC_IEVENT_BUTTON #define MISC_IEVENT_BUTTON -#include "../../Input/L_inputClass.h" + +class InputClass; namespace Oyster { namespace Event { + enum ButtonState + { + ButtonState_None, + ButtonState_Hover, + ButtonState_Pressed, + ButtonState_Down, + ButtonState_Released, + }; + class IEventButton { public: - enum ButtonState - { - Button_Clicked, - Button_Hover, - Button_Hold, - Button_Smashed, - }; + virtual ~IEventButton(){} - virtual void CheckCollision(InputClass *input) = 0; + virtual void Update(InputClass *input){} - virtual void SendEvent(IEventButton::ButtonState state) = 0; + virtual void SendEvent(ButtonState state){} struct ButtonEvent; - virtual void SetEventFunc(void (*EventFunc)( ButtonEvent e )) = 0; + virtual void SetEventFunc(void (*EventFunc)( ButtonEvent e )){} - virtual unsigned int GetID() = 0; + virtual unsigned int GetID(){ return -1; } }; } diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj index f3e58e56..e329e9cd 100644 --- a/Code/Misc/Misc.vcxproj +++ b/Code/Misc/Misc.vcxproj @@ -165,7 +165,9 @@ + + diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters index edcf0e99..c50f2804 100644 --- a/Code/Misc/Misc.vcxproj.filters +++ b/Code/Misc/Misc.vcxproj.filters @@ -134,5 +134,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file From 489115840d3169745052102e5bbd62e9ed023e67 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Tue, 11 Feb 2014 09:17:16 +0100 Subject: [PATCH 34/35] GL - base for lvl loading --- .../DanBiasGame/GameClientState/GameState.cpp | 8 +- Code/Game/GameLogic/Level.cpp | 120 +++--------------- 2 files changed, 22 insertions(+), 106 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 9e52e218..8fecd86f 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -285,8 +285,8 @@ void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Flo modelData.visible = true; //modelData.world = world; modelData.position = Oyster::Math::Float3(world[12], world[13], world[14]); - modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1); - modelData.scale = Oyster::Math::Float3(2,2,2); + modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(0,0,0), 1); + modelData.scale = Oyster::Math::Float3(1,1,1); modelData.modelPath = modelName; modelData.id = myId; @@ -565,7 +565,9 @@ void GameState::Protocol( ObjPos* pos ) { if(dynamicObjects[i]->GetId() == pos->object_ID) { - dynamicObjects[i]->setWorld(world); + + dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14])); + if(dynamicObjects[i]->GetId() == myId) // playerobj { diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp index ec571b9f..06d461fa 100644 --- a/Code/Game/GameLogic/Level.cpp +++ b/Code/Game/GameLogic/Level.cpp @@ -51,6 +51,8 @@ void Level::InitiateLevel(std::string levelPath) objects = ll.LoadLevel(levelPath); int objCount = objects.size(); int modelCount = 0; + int staticObjCount = 0; + int dynamicObjCount = 0; for (int i = 0; i < objCount; i++) { ObjectTypeHeader* obj = objects.at(i); @@ -71,121 +73,33 @@ void Level::InitiateLevel(std::string levelPath) //LevelLoaderInternal::BoundingVolumeBase* staticObjPhysicData = ((ObjectHeader*)obj); staticObjData->ModelFile; - ICustomBody* rigidBody_Static; - //if( staticObjPhysicData->geometryType = CollisionGeometryType_Box) - //{ - // //API::SimpleBodyDescription sbDesc_Static; - - // //sbDesc_Static.centerPosition = staticObjData->position; - // //sbDesc_Static.ignoreGravity = false; // because it is static - // //sbDesc_Static.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); + ICustomBody* rigidBody_Static; + // collision shape + // radius, rotation in world, position in world, mass, restitution, static and dynamic friction + ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); + + // add rigidbody to the logical obj + // Object::DefaultCollisionBefore, Object::DefaultCollisionAfter for now, gamelogic will take care of this + // set object_type to objID + this->staticObjects.Push(new StaticObject(rigidBody,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); - // ////sbDesc_Static.inertiaTensor.Cuboid(staticObjPhysicData->mass); - // //sbDesc_Static.mass = staticObjPhysicData->mass; - // //sbDesc_Static.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; - // //sbDesc_Static.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; - // ////sbDesc_Static.restitutionCoeff = - // //sbDesc_Static.size = Oyster::Math::Float3(40,40,40); - // //rigidBody_Static = API::Instance().CreateRigidBody(sbDesc_Static).Release(); - // //if(rigidBody_Static) - // //{ - // // this->staticObjects.Push(new StaticObject(rigidBody_Static,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); - // // int id = this->staticObjects.Size()-1; - // // rigidBody_Static->SetCustomTag(this->staticObjects[this->staticObjects.Size()-1]); - // //} - //} - //if( staticObjPhysicData->geometryType = CollisionGeometryType_Sphere) - //{ - // //API::SphericalBodyDescription sbDesc_Static; - - // //sbDesc_Static.centerPosition = staticObjData->position; - // //sbDesc_Static.ignoreGravity = true; // because it is static - // //sbDesc_Static.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); - - // ////sbDesc_Static.inertiaTensor.Sphere(staticObjPhysicData->mass); - - // //sbDesc_Static.mass = staticObjPhysicData->mass; - // //sbDesc_Static.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; - // //sbDesc_Static.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; - // ////sbDesc_Static.restitutionCoeff = - // ////sbDesc_Static.radius = - // //rigidBody_Static = API::Instance().CreateRigidBody(sbDesc_Static).Release(); - // if(rigidBody_Static) - // { - // this->staticObjects.Push(new StaticObject(rigidBody_Static,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); - // int id = this->staticObjects.Size()-1; - // rigidBody_Static->SetCustomTag(this->staticObjects[this->staticObjects.Size()-1]); - // } - - // if (OBJECT_TYPE::OBJECT_TYPE_WORLD) - // { - // /*API::Gravity gravityWell; - // gravityWell.gravityType = API::Gravity::GravityType_Well; - // gravityWell.well.mass = 1e17f; - // gravityWell.well.position = Oyster::Math::Float4(0,0,0,1); - // API::Instance().AddGravity(gravityWell);*/ - // } - //} + this->staticObjects[staticObjCount]->objectID = modelCount++; + rigidBody->SetCustomTag(this->staticObjects[staticObjCount]); } break; case ObjectType::ObjectType_Dynamic: { ObjectHeader* staticObjData = ((ObjectHeader*)obj); - //LevelLoaderInternal::BoundingVolumeBase* staticObjPhysicData = ((ObjectHeader*)obj); staticObjData->ModelFile; ICustomBody* rigidBody_Dynamic; - //if( staticObjPhysicData->geometryType = CollisionGeometryType_Box) - //{ - // //API::Instance().AddCollisionBox() - // //API::SimpleBodyDescription sbDesc_Dynamic; - // //sbDesc_Dynamic.centerPosition = staticObjData->position; - // //sbDesc_Dynamic.ignoreGravity = false; // because it is static - // //sbDesc_Dynamic.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); + rigidBody_Dynamic = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5, 0.5f, 0.8f, 0.6f); - - // ////sbDesc_Static.inertiaTensor.Cuboid(staticObjPhysicData->mass); - // //sbDesc_Dynamic.mass = staticObjPhysicData->mass; - // //sbDesc_Dynamic.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; - // //sbDesc_Dynamic.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; - // ////sbDesc_Static.restitutionCoeff = - // //sbDesc_Dynamic.size = Oyster::Math::Float3(40,40,40); - // //rigidBody_Dynamic = API::Instance().CreateRigidBody(sbDesc_Dynamic).Release(); - // //if(rigidBody_Dynamic) - // //{ - // // rigidBody_Dynamic->SetSubscription(Level::PhysicsOnMoveLevel); - // // this->dynamicObjects.Push(new DynamicObject(rigidBody_Dynamic,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); - // // int id = this->dynamicObjects.Size()-1; - // // rigidBody_Dynamic->SetCustomTag(this->dynamicObjects[this->dynamicObjects.Size()-1]); - // //} - //} - //if( staticObjPhysicData->geometryType = CollisionGeometryType_Sphere) - //{ - // //API::Instance().AddCollisionBox() - // //API::SphericalBodyDescription sbDesc_Dynamic; - - // //sbDesc_Dynamic.centerPosition = staticObjData->position; - // //sbDesc_Dynamic.ignoreGravity = false; // use gravity on dynamic obj - // //sbDesc_Dynamic.rotation = Oyster::Math::Float3(staticObjData->rotation[0], staticObjData->rotation[1],staticObjData->rotation[2]);//Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0); - - // ////sbDesc_Static.inertiaTensor.Sphere(staticObjPhysicData->mass); - - // //sbDesc_Dynamic.mass = staticObjPhysicData->mass; - // //sbDesc_Dynamic.frictionCoeff_Static = staticObjPhysicData->frictionCoeffStatic; - // //sbDesc_Dynamic.frictionCoeff_Dynamic = staticObjPhysicData->frictionCoeffDynamic; - // ////sbDesc_Static.restitutionCoeff = - // ////sbDesc_Static.radius = - // //rigidBody_Dynamic = API::Instance().CreateRigidBody(sbDesc_Dynamic).Release(); - // //if(rigidBody_Dynamic) - // //{ - // // rigidBody_Dynamic->SetSubscription(Level::PhysicsOnMoveLevel); - // // this->dynamicObjects.Push(new DynamicObject(rigidBody_Dynamic,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC)); - // // int id = this->dynamicObjects.Size()-1; - // // rigidBody_Dynamic->SetCustomTag(this->dynamicObjects[this->dynamicObjects.Size()-1]); - // //} - //} + this->dynamicObjects.Push(new DynamicObject(rigidBody_Dynamic,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX)); + this->dynamicObjects[dynamicObjCount]->objectID = modelCount++; + rigidBody_Dynamic->SetCustomTag(this->dynamicObjects[dynamicObjCount]); } break; case ObjectType::ObjectType_Light: From d16d223c2ba3988f6f9147dfd5deada56443d746 Mon Sep 17 00:00:00 2001 From: lindaandersson Date: Tue, 11 Feb 2014 10:11:38 +0100 Subject: [PATCH 35/35] GL - player moving --- .../DanBiasGame/GameClientState/C_Object.cpp | 23 +++++++++--- .../DanBiasGame/GameClientState/C_Object.h | 8 +++-- .../GameClientState/C_obj/C_DynamicObj.cpp | 30 +--------------- .../GameClientState/C_obj/C_DynamicObj.h | 5 --- .../GameClientState/C_obj/C_Player.cpp | 34 +----------------- .../GameClientState/C_obj/C_Player.h | 7 ---- .../GameClientState/C_obj/C_StaticObj.cpp | 32 +---------------- .../GameClientState/C_obj/C_StaticObj.h | 5 --- .../GameClientState/C_obj/C_UIobject.cpp | 32 ----------------- .../GameClientState/C_obj/C_UIobject.h | 7 +--- .../DanBiasGame/GameClientState/GameState.cpp | 11 +++--- Code/Game/GameLogic/Game_PlayerData.cpp | 2 +- Code/Game/GameLogic/Object.cpp | 16 +-------- Code/Game/GameLogic/Object.h | 2 -- Code/Game/GameLogic/Player.cpp | 36 +++++++++---------- 15 files changed, 52 insertions(+), 198 deletions(-) diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp index 20b882d2..c5078224 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp @@ -5,6 +5,9 @@ void C_Object::Init(ModelInitData modelInit) position = modelInit.position; rotation = modelInit.rotation; scale = modelInit.scale; + id = modelInit.id; + model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); + model->Visible = modelInit.visible; updateWorld(); } void C_Object::updateWorld() @@ -17,10 +20,12 @@ void C_Object::updateWorld() scale.v[1].y = this->scale[1]; scale.v[2].z = this->scale[2]; world = translation * rot * scale; + + model->WorldMatrix = world; } void C_Object::setWorld(Oyster::Math::Float4x4 world) { - + model->WorldMatrix = world; } Oyster::Math::Float4x4 C_Object::getWorld() const { @@ -68,7 +73,15 @@ Oyster::Math::Float3 C_Object::getScale() const { return this->scale; } -//int C_Object::GetId() const -//{ -// return -//} +int C_Object::GetId() const +{ + return id; +} +void C_Object::Render() +{ + Oyster::Graphics::API::RenderModel(*(model)); +} +void C_Object::Release() +{ + Oyster::Graphics::API::DeleteModel(model); +} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.h b/Code/Game/DanBiasGame/GameClientState/C_Object.h index 13932930..9c06d2da 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_Object.h +++ b/Code/Game/DanBiasGame/GameClientState/C_Object.h @@ -23,6 +23,8 @@ private: Oyster::Math::Float3 position; Oyster::Math::Quaternion rotation; Oyster::Math::Float3 scale; + Oyster::Graphics::Model::Model *model; + int id; void updateWorld(); public: @@ -40,8 +42,8 @@ public: void addScale(Oyster::Math::Float3 deltaScale); Oyster::Math::Float3 getScale() const; - virtual void Render() = 0; - virtual void Release() = 0; - virtual int GetId() = 0; + virtual void Render(); + virtual void Release(); + virtual int GetId() const; };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp index 71c46f4a..e654348f 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp @@ -1,15 +1,7 @@ #include "C_DynamicObj.h" #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_DynamicObj::myData -{ - myData(){} - Oyster::Graphics::Model::Model *model; - int ID; - // light - // sound - // effect -}privData; + C_DynamicObj::C_DynamicObj(void) { } @@ -22,24 +14,4 @@ C_DynamicObj::~C_DynamicObj(void) void C_DynamicObj::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; } - -void C_DynamicObj::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_DynamicObj::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_DynamicObj::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h index d8e7023a..f73514da 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h @@ -8,15 +8,10 @@ namespace DanBias class C_DynamicObj : public C_Object { private: - struct myData; - myData* privData; public: C_DynamicObj(void); virtual ~C_DynamicObj(void); void Init(ModelInitData modelInit); - void Render(); - void Release(); - int GetId(); };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp index 5e5525e9..02cc58fc 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp @@ -2,21 +2,11 @@ #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_Player::myData -{ - myData(){} - Oyster::Math3D::Float4x4 view; - Oyster::Math3D::Float4x4 proj; - Oyster::Graphics::Model::Model *model; - Oyster::Math3D::Float4 lookDir; - int ID; -}privData; - C_Player::C_Player(void) :C_DynamicObj() { -} +} C_Player::~C_Player(void) { @@ -26,26 +16,4 @@ C_Player::~C_Player(void) void C_Player::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; - privData->lookDir = Oyster::Math3D::Float4 (0,0,1,0); } - - -void C_Player::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_Player::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_Player::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h index 556fd6dc..65a7e498 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h @@ -8,18 +8,11 @@ namespace DanBias class C_Player : public C_DynamicObj { private: - struct myData; - myData* privData; - public: C_Player(void); virtual ~C_Player(void); void Init(ModelInitData modelInit); - void Render(); - void Release(); - int GetId(); - };};}; #endif diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp index 6e7a20e9..9b13c460 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp @@ -3,18 +3,10 @@ #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_StaticObj::myData -{ - myData(){} - Oyster::Graphics::Model::Model *model; - int ID; - -}privData; C_StaticObj::C_StaticObj(void) { + } - - C_StaticObj::~C_StaticObj(void) { @@ -22,26 +14,4 @@ C_StaticObj::~C_StaticObj(void) void C_StaticObj::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; - } - - -void C_StaticObj::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_StaticObj::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_StaticObj::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h index 3bae1961..d2bcb2a9 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h @@ -8,15 +8,10 @@ namespace DanBias class C_StaticObj : public C_Object { private: - struct myData; - myData* privData; public: C_StaticObj(void); virtual ~C_StaticObj(void); void Init(ModelInitData modelInit); - void Render(); - void Release(); - int GetId(); };};}; #endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp index fc9c7d53..570fa22f 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp @@ -2,13 +2,6 @@ #include "DllInterfaces/GFXAPI.h" using namespace DanBias::Client; -struct C_UIobject::myData -{ - myData(){} - Oyster::Graphics::Model::Model *model; - int ID; -}privData; - C_UIobject::C_UIobject(void) { } @@ -20,29 +13,4 @@ C_UIobject::~C_UIobject(void) void C_UIobject::Init(ModelInitData modelInit) { C_Object::Init(modelInit); - // load models - privData = new myData(); - privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath); - privData->model->Visible = modelInit.visible; - privData->model->WorldMatrix = getWorld(); - privData->ID = modelInit.id; - } -void C_UIobject::setPos(Oyster::Math::Float4x4 world) -{ - privData->model->WorldMatrix = world; -} - -void C_UIobject::Render() -{ - Oyster::Graphics::API::RenderModel(*(privData->model)); -} -void C_UIobject::Release() -{ - Oyster::Graphics::API::DeleteModel(privData->model); - delete privData; -} -int C_UIobject::GetId() -{ - return privData->ID; -} \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h index b41fb047..f002fcb2 100644 --- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h +++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h @@ -8,16 +8,11 @@ namespace DanBias class C_UIobject : public C_Object { private: - struct myData; - myData* privData; + public: C_UIobject(void); virtual ~C_UIobject(void); void Init(ModelInitData modelInit); void setPos(Oyster::Math::Float4x4 world); - - void Render(); - void Release(); - int GetId(); };};}; #endif \ No newline at end of file diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp index 8fecd86f..5214875a 100644 --- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp +++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp @@ -122,7 +122,7 @@ bool GameState::LoadModels() this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData); } - + /* // add crystal model modelData.position = Oyster::Math::Float3(10, 301, 0); modelData.modelPath = L"crystalformation_b.dan"; @@ -174,7 +174,7 @@ bool GameState::LoadModels() modelData.id = id++; // load models this->dynamicObjects.Push(new C_DynamicObj()); - this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData); + this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);*/ return true; } bool GameState::LoadModels(std::string mapFile) @@ -316,7 +316,7 @@ void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Flo camera->setLook(objForward); up *= 2; - objForward *= -3; + objForward *= 3; Oyster::Math::Float3 cameraPos = up + pos + objForward; camera->SetPosition(cameraPos); @@ -566,8 +566,9 @@ void GameState::Protocol( ObjPos* pos ) if(dynamicObjects[i]->GetId() == pos->object_ID) { - dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14])); - + + //dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14])); + dynamicObjects[i]->setWorld(world); if(dynamicObjects[i]->GetId() == myId) // playerobj { diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp index 25fd51c1..15de4399 100644 --- a/Code/Game/GameLogic/Game_PlayerData.cpp +++ b/Code/Game/GameLogic/Game_PlayerData.cpp @@ -8,7 +8,7 @@ Game::PlayerData::PlayerData() //set some stats that are appropriate to a player Oyster::Math::Float3 centerPosition = Oyster::Math::Float3(0,608,-5); Oyster::Math::Float3 size = Oyster::Math::Float3(0.25f,1.0f,0.5f); - Oyster::Math::Float mass = 15; + Oyster::Math::Float mass = 60; Oyster::Math::Float restitutionCoeff = 0.5; Oyster::Math::Float frictionCoeff_Static = 0.4; Oyster::Math::Float frictionCoeff_Dynamic = 0.3; diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp index 77c256eb..b2b74838 100644 --- a/Code/Game/GameLogic/Object.cpp +++ b/Code/Game/GameLogic/Object.cpp @@ -20,8 +20,6 @@ Object::Object() this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(OBJECT_TYPE type) @@ -29,8 +27,6 @@ Object::Object(OBJECT_TYPE type) this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f); this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) @@ -38,8 +34,6 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type) this->rigidBody = rigidBody; this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) @@ -48,8 +42,6 @@ Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type) @@ -58,19 +50,14 @@ Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefor this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } Object::Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter), Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), OBJECT_TYPE type) { this->rigidBody = rigidBody; - this->type = type; this->objectID = GID(); - this->currPhysicsState = this->rigidBody->GetState(); - this->newPhysicsState = this->currPhysicsState; } void Object::ApplyLinearImpulse(Oyster::Math::Float3 force) @@ -102,12 +89,11 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody() void Object::BeginFrame() { - this->rigidBody->SetState(this->newPhysicsState); } // update physic void Object::EndFrame() { - this->newPhysicsState = this->currPhysicsState; + } void Object::setBeforeCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter)) diff --git a/Code/Game/GameLogic/Object.h b/Code/Game/GameLogic/Object.h index 5450e9fe..1098cb56 100644 --- a/Code/Game/GameLogic/Object.h +++ b/Code/Game/GameLogic/Object.h @@ -51,8 +51,6 @@ namespace GameLogic protected: Oyster::Physics::ICustomBody *rigidBody; - Oyster::Physics::ICustomBody::State newPhysicsState; - Oyster::Physics::ICustomBody::State currPhysicsState; static const Game* gameInstance; Oyster::Math::Float3 currLook; diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index de45f8cb..acbb33a9 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -70,12 +70,11 @@ void Player::EndFrame() Object::EndFrame(); // rotate - Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; - Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; + //Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; + //Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ; //currPhysicsState.AddRotation(deltaAxis); - dx = 0; - this->newPhysicsState = this->currPhysicsState; + } void Player::Move(const PLAYER_MOVEMENT &movement) @@ -106,33 +105,32 @@ void Player::Move(const PLAYER_MOVEMENT &movement) void Player::MoveForward() { - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - //newPhysicsState.ApplyLinearImpulse(forward * (MOVE_FORCE * this->gameInstance->GetFrameTime())); - //rigidBody->SetLinearVelocity( 10 * this->gameInstance->GetFrameTime() ); + rigidBody->SetLinearVelocity( 10 * forward.GetNormalized() ); } void Player::MoveBackwards() { - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - //newPhysicsState.ApplyLinearImpulse(-forward * MOVE_FORCE * this->gameInstance->GetFrameTime()); + rigidBody->SetLinearVelocity( 10 * -forward.GetNormalized() ); } void Player::MoveRight() { //Do cross product with forward vector and negative gravity vector - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - Oyster::Math::Float3 r = (-currPhysicsState.centerPos.Normalize()).Cross(forward); - //rigidBody->SetLinearVelocity(-r * 10 * this->gameInstance->GetFrameTime() ); + Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward); + rigidBody->SetLinearVelocity(r * 10); } void Player::MoveLeft() { //Do cross product with forward vector and negative gravity vector - Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2]; + Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2]; //Oyster::Math::Float3 forward = lookDir; - //Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); //Still get zero - //newPhysicsState.ApplyLinearImpulse(r * MOVE_FORCE * this->gameInstance->GetFrameTime()); + Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward); + rigidBody->SetLinearVelocity(-r * 10); } void Player::UseWeapon(const WEAPON_FIRE &usage) @@ -145,7 +143,7 @@ void Player::Respawn(Oyster::Math::Float3 spawnPoint) this->life = 100; this->playerState = PLAYER_STATE::PLAYER_STATE_IDLE; this->lookDir = Oyster::Math::Float4(1,0,0); - this->newPhysicsState.centerPos = spawnPoint; + //this->newPhysicsState.centerPos = spawnPoint; } void Player::Rotate(const Oyster::Math3D::Float4 lookDir) @@ -162,7 +160,7 @@ void Player::Rotate(const Oyster::Math3D::Float4 lookDir) void Player::Jump() { - Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1]; + Oyster::Math::Float3 up = this->rigidBody->GetState().GetOrientation().v[1]; //newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime()); } @@ -181,11 +179,11 @@ bool Player::IsIdle() Oyster::Math::Float3 Player::GetPosition() const { - return (Oyster::Math::Float3)currPhysicsState.centerPos; + return (Oyster::Math::Float3) this->rigidBody->GetState().centerPos; } Oyster::Math::Float4x4 Player::GetOrientation() const { - return this->currPhysicsState.GetOrientation(); + return this->rigidBody->GetState().GetOrientation(); } Oyster::Math::Float3 Player::GetLookDir() const {

    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

    Y)w=PDbYs|7}Hzh=Dg4-`0ZG|&HBBQWOl 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 literal 0 HcmV?d00001 diff --git a/Code/Physics/lib/Debug/BulletDynamics_Debug.lib b/Code/Physics/lib/Debug/BulletDynamics_Debug.lib new file mode 100644 index 0000000000000000000000000000000000000000..43b0628ed8d3d4cb4bdeb42cd08273c25241c4a2 GIT binary patch literal 3733436 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 z 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